Remove "unicode" mode and simply permit unicode to be used everywhere within

cx_Oracle; stop using "unicode" mode in the OCI as well since that appears to
have bugs in some places and doesn't really solve any problems anyway.
This commit is contained in:
Anthony Tuininga 2011-02-19 03:50:16 +00:00
parent 9be85a356c
commit 04f1904a7d
24 changed files with 577 additions and 725 deletions

89
Buffer.c Normal file
View File

@ -0,0 +1,89 @@
//-----------------------------------------------------------------------------
// Buffer.c
// Defines buffer structure and routines for populating it. These are used
// to translate Python objects into the buffers needed for Oracle, including
// Unicode or buffer objects.
//-----------------------------------------------------------------------------
// define structure for abstracting string buffers
typedef struct {
const void *ptr;
Py_ssize_t numCharacters;
Py_ssize_t size;
PyObject *obj;
} udt_Buffer;
//-----------------------------------------------------------------------------
// cxBuffer_Init()
// Initialize the buffer with an empty string. Returns 0 as a convenience to
// the caller.
//-----------------------------------------------------------------------------
static int cxBuffer_Init(
udt_Buffer *buf) // buffer to initialize
{
buf->ptr = NULL;
buf->size = 0;
buf->numCharacters = 0;
buf->obj = NULL;
return 0;
}
//-----------------------------------------------------------------------------
// cxBuffer_Copy()
// Copy the contents of the buffer.
//-----------------------------------------------------------------------------
static int cxBuffer_Copy(
udt_Buffer *buf, // buffer to copy into
udt_Buffer *copyFromBuf) // buffer to copy from
{
buf->ptr = copyFromBuf->ptr;
buf->size = copyFromBuf->size;
buf->numCharacters = copyFromBuf->numCharacters;
Py_XINCREF(copyFromBuf->obj);
buf->obj = copyFromBuf->obj;
return 0;
}
//-----------------------------------------------------------------------------
// cxBuffer_FromObject()
// Populate the string buffer from a unicode object.
//-----------------------------------------------------------------------------
static int cxBuffer_FromObject(
udt_Buffer *buf, // buffer to fill
PyObject *obj, // object (string or Unicode object)
const char *encoding) // encoding to use, if applicable
{
if (!obj)
return cxBuffer_Init(buf);
if (encoding && PyUnicode_Check(obj)) {
buf->obj = PyUnicode_AsEncodedString(obj, encoding, NULL);
if (!buf->obj)
return -1;
buf->ptr = PyBytes_AS_STRING(buf->obj);
buf->size = PyBytes_GET_SIZE(buf->obj);
buf->numCharacters = PyUnicode_GET_SIZE(obj);
} else if (PyBytes_Check(obj)) {
Py_INCREF(obj);
buf->obj = obj;
buf->ptr = PyBytes_AS_STRING(buf->obj);
buf->size = buf->numCharacters = PyBytes_GET_SIZE(buf->obj);
#if PY_MAJOR_VERSION < 3
} else if (PyBuffer_Check(obj)) {
if (PyObject_AsReadBuffer(obj, &buf->ptr, &buf->size) < 0)
return -1;
Py_INCREF(obj);
buf->obj = obj;
buf->numCharacters = buf->size;
#endif
} else {
PyErr_SetString(PyExc_TypeError, CXORA_TYPE_ERROR);
return -1;
}
return 0;
}
#define cxBuffer_Clear(buf) Py_XDECREF((buf)->obj)

View File

@ -62,10 +62,6 @@ static PyObject *Connection_GetMaxBytesPerCharacter(udt_Connection*, void*);
static PyObject *Connection_ContextManagerEnter(udt_Connection*, PyObject*);
static PyObject *Connection_ContextManagerExit(udt_Connection*, PyObject*);
static PyObject *Connection_ChangePasswordExternal(udt_Connection*, PyObject*);
#ifndef WITH_UNICODE
static PyObject *Connection_GetEncoding(udt_Connection*, void*);
static PyObject *Connection_GetNationalEncoding(udt_Connection*, void*);
#endif
static PyObject *Connection_GetStmtCacheSize(udt_Connection*, void*);
static int Connection_SetStmtCacheSize(udt_Connection*, PyObject*, void*);
#ifdef ORACLE_10G
@ -135,10 +131,6 @@ static PyMemberDef g_ConnectionMembers[] = {
// declaration of calculated members for Python type "Connection"
//-----------------------------------------------------------------------------
static PyGetSetDef g_ConnectionCalcMembers[] = {
#ifndef WITH_UNICODE
{ "encoding", (getter) Connection_GetEncoding, 0, 0, 0 },
{ "nencoding", (getter) Connection_GetNationalEncoding, 0, 0, 0 },
#endif
{ "version", (getter) Connection_GetVersion, 0, 0, 0 },
{ "maxBytesPerCharacter", (getter) Connection_GetMaxBytesPerCharacter,
0, 0, 0 },
@ -238,7 +230,7 @@ static int Connection_GetConnection(
{
int externalCredentials, proxyCredentials;
udt_Environment *environment;
udt_StringBuffer buffer;
udt_Buffer buffer;
OCIAuthInfo *authInfo;
PyObject *dbNameObj;
boolean found;
@ -277,7 +269,8 @@ static int Connection_GetConnection(
// set the user name, if applicable
externalCredentials = 1;
if (StringBuffer_Fill(&buffer, self->username) < 0)
if (cxBuffer_FromObject(&buffer, self->username,
self->environment->encoding) < 0)
return -1;
if (buffer.size > 0) {
externalCredentials = 0;
@ -286,14 +279,15 @@ static int Connection_GetConnection(
environment->errorHandle);
if (Environment_CheckForError(environment, status,
"Connection_GetConnection(): set user name") < 0) {
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
return -1;
}
}
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
// set the password, if applicable
if (StringBuffer_Fill(&buffer, self->password) < 0)
if (cxBuffer_FromObject(&buffer, self->password,
self->environment->encoding) < 0)
return -1;
if (buffer.size > 0) {
externalCredentials = 0;
@ -302,11 +296,11 @@ static int Connection_GetConnection(
environment->errorHandle);
if (Environment_CheckForError(environment, status,
"Connection_GetConnection(): set password") < 0) {
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
return -1;
}
}
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
// if no user name or password are set, using external credentials
if (!pool && externalCredentials)
@ -314,7 +308,8 @@ static int Connection_GetConnection(
#ifdef ORACLE_11G
// set the connection class, if applicable
if (StringBuffer_Fill(&buffer, cclassObj) < 0)
if (cxBuffer_FromObject(&buffer, cclassObj,
self->environment->encoding) < 0)
return -1;
if (buffer.size > 0) {
status = OCIAttrSet(authInfo, OCI_HTYPE_AUTHINFO,
@ -322,11 +317,11 @@ static int Connection_GetConnection(
environment->errorHandle);
if (Environment_CheckForError(environment, status,
"Connection_GetConnection(): set connection class") < 0) {
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
return -1;
}
}
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
// set the purity, if applicable
if (purity != OCI_ATTR_PURITY_DEFAULT) {
@ -341,14 +336,15 @@ static int Connection_GetConnection(
}
// acquire the new session
if (StringBuffer_Fill(&buffer, dbNameObj) < 0)
if (cxBuffer_FromObject(&buffer, dbNameObj,
self->environment->encoding) < 0)
return -1;
Py_BEGIN_ALLOW_THREADS
status = OCISessionGet(environment->handle, environment->errorHandle,
&self->handle, authInfo, (text*) buffer.ptr, buffer.size, NULL, 0,
NULL, NULL, &found, mode);
Py_END_ALLOW_THREADS
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
if (Environment_CheckForError(environment, status,
"Connection_GetConnection(): get connection") < 0)
return -1;
@ -386,7 +382,7 @@ static PyObject *Connection_GetOCIAttr(
ub4 *attribute) // OCI attribute type
{
OCISession *sessionHandle;
udt_StringBuffer buffer;
udt_Buffer buffer;
sword status;
// make sure connection is connected
@ -409,7 +405,8 @@ static PyObject *Connection_GetOCIAttr(
"Connection_GetOCIAttr()") < 0)
return NULL;
return cxString_FromEncodedString(buffer.ptr, buffer.size);
return cxString_FromEncodedString(buffer.ptr, buffer.size,
self->environment->encoding);
}
#endif
@ -424,7 +421,7 @@ static int Connection_SetOCIAttr(
ub4 *attribute) // OCI attribute type
{
OCISession *sessionHandle;
udt_StringBuffer buffer;
udt_Buffer buffer;
sword status;
// verify arguments
@ -446,11 +443,11 @@ static int Connection_SetOCIAttr(
return -1;
// set the value in the OCI
if (StringBuffer_Fill(&buffer, value))
if (cxBuffer_FromObject(&buffer, value, self->environment->encoding))
return -1;
status = OCIAttrSet(sessionHandle, OCI_HTYPE_SESSION, (text*) buffer.ptr,
buffer.size, *attribute, self->environment->errorHandle);
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
if (Environment_CheckForError(self->environment, status,
"Connection_SetOCIAttr(): set value") < 0)
return -1;
@ -519,18 +516,21 @@ static int Connection_ChangePassword(
PyObject *oldPasswordObj, // old password
PyObject *newPasswordObj) // new password
{
udt_StringBuffer usernameBuffer, oldPasswordBuffer, newPasswordBuffer;
udt_Buffer usernameBuffer, oldPasswordBuffer, newPasswordBuffer;
sword status;
if (StringBuffer_Fill(&usernameBuffer, self->username) < 0)
if (cxBuffer_FromObject(&usernameBuffer, self->username,
self->environment->encoding) < 0)
return -1;
if (StringBuffer_Fill(&oldPasswordBuffer, oldPasswordObj) < 0) {
StringBuffer_Clear(&usernameBuffer);
if (cxBuffer_FromObject(&oldPasswordBuffer, oldPasswordObj,
self->environment->encoding) < 0) {
cxBuffer_Clear(&usernameBuffer);
return -1;
}
if (StringBuffer_Fill(&newPasswordBuffer, newPasswordObj) < 0) {
StringBuffer_Clear(&usernameBuffer);
StringBuffer_Clear(&oldPasswordBuffer);
if (cxBuffer_FromObject(&newPasswordBuffer, newPasswordObj,
self->environment->encoding) < 0) {
cxBuffer_Clear(&usernameBuffer);
cxBuffer_Clear(&oldPasswordBuffer);
return -1;
}
@ -542,9 +542,9 @@ static int Connection_ChangePassword(
(text*) newPasswordBuffer.ptr, newPasswordBuffer.size,
OCI_AUTH);
Py_END_ALLOW_THREADS
StringBuffer_Clear(&usernameBuffer);
StringBuffer_Clear(&oldPasswordBuffer);
StringBuffer_Clear(&newPasswordBuffer);
cxBuffer_Clear(&usernameBuffer);
cxBuffer_Clear(&oldPasswordBuffer);
cxBuffer_Clear(&newPasswordBuffer);
if (Environment_CheckForError(self->environment, status,
"Connection_ChangePassword(): change password") < 0)
return -1;
@ -590,7 +590,7 @@ static int Connection_Connect(
PyObject *newPasswordObj) // new password (if desired)
{
ub4 credentialType = OCI_CRED_EXT;
udt_StringBuffer buffer;
udt_Buffer buffer;
sword status;
// allocate the server handle
@ -601,14 +601,15 @@ static int Connection_Connect(
return -1;
// attach to the server
if (StringBuffer_Fill(&buffer, self->dsn) < 0)
if (cxBuffer_FromObject(&buffer, self->dsn,
self->environment->encoding) < 0)
return -1;
Py_BEGIN_ALLOW_THREADS
status = OCIServerAttach(self->serverHandle,
self->environment->errorHandle, (text*) buffer.ptr, buffer.size,
OCI_DEFAULT);
Py_END_ALLOW_THREADS
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
if (Environment_CheckForError(self->environment, status,
"Connection_Connect(): server attach") < 0)
return -1;
@ -652,7 +653,8 @@ static int Connection_Connect(
return -1;
// set user name in session handle
if (StringBuffer_Fill(&buffer, self->username) < 0)
if (cxBuffer_FromObject(&buffer, self->username,
self->environment->encoding) < 0)
return -1;
if (buffer.size > 0) {
credentialType = OCI_CRED_RDBMS;
@ -661,14 +663,15 @@ static int Connection_Connect(
self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"Connection_Connect(): set user name") < 0) {
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
return -1;
}
}
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
// set password in session handle
if (StringBuffer_Fill(&buffer, self->password) < 0)
if (cxBuffer_FromObject(&buffer, self->password,
self->environment->encoding) < 0)
return -1;
if (buffer.size > 0) {
credentialType = OCI_CRED_RDBMS;
@ -677,11 +680,11 @@ static int Connection_Connect(
self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"Connection_Connect(): set password") < 0) {
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
return -1;
}
}
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
#ifdef OCI_ATTR_DRIVER_NAME
status = OCIAttrSet(self->sessionHandle, OCI_HTYPE_SESSION,
@ -801,6 +804,7 @@ static int Connection_Init(
PyObject *threadedObj, *twophaseObj, *eventsObj, *newPasswordObj;
PyObject *usernameObj, *passwordObj, *dsnObj, *cclassObj;
int threaded, twophase, events;
char *encoding, *nencoding;
ub4 connectMode, purity;
udt_SessionPool *pool;
OCISvcCtx *handle;
@ -808,7 +812,7 @@ static int Connection_Init(
// define keyword arguments
static char *keywordList[] = { "user", "password", "dsn", "mode",
"handle", "pool", "threaded", "twophase", "events", "cclass",
"purity", "newpassword", NULL };
"purity", "newpassword", "encoding", "nencoding", NULL };
// parse arguments
pool = NULL;
@ -817,15 +821,15 @@ static int Connection_Init(
usernameObj = passwordObj = dsnObj = cclassObj = NULL;
threadedObj = twophaseObj = eventsObj = newPasswordObj = NULL;
threaded = twophase = events = purity = 0;
encoding = nencoding = NULL;
#ifdef ORACLE_11G
purity = OCI_ATTR_PURITY_DEFAULT;
#endif
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|O!O!O!iiO!OOOO!iO!",
keywordList, cxString_Type, &usernameObj, cxString_Type,
&passwordObj, cxString_Type, &dsnObj, &connectMode, &handle,
&g_SessionPoolType, &pool, &threadedObj, &twophaseObj, &eventsObj,
cxString_Type, &cclassObj, &purity, cxString_Type,
&newPasswordObj))
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs,
"|OOOiiO!OOOOiOss", keywordList, &usernameObj, &passwordObj,
&dsnObj, &connectMode, &handle, &g_SessionPoolType, &pool,
&threadedObj, &twophaseObj, &eventsObj, &cclassObj, &purity,
&newPasswordObj, &encoding, &nencoding))
return -1;
if (threadedObj) {
threaded = PyObject_IsTrue(threadedObj);
@ -846,7 +850,8 @@ static int Connection_Init(
// set up the environment
if (pool)
self->environment = Environment_Clone(pool->environment);
else self->environment = Environment_NewFromScratch(threaded, events);
else self->environment = Environment_NewFromScratch(threaded, events,
encoding, nencoding);
if (!self->environment)
return -1;
@ -953,70 +958,6 @@ static PyObject *Connection_Repr(
}
#ifndef WITH_UNICODE
//-----------------------------------------------------------------------------
// Connection_GetCharacterSetName()
// Retrieve the IANA character set name for the attribute.
//-----------------------------------------------------------------------------
static PyObject *Connection_GetCharacterSetName(
udt_Connection *self, // connection object
ub2 attribute) // attribute to fetch
{
char charsetName[OCI_NLS_MAXBUFSZ], ianaCharsetName[OCI_NLS_MAXBUFSZ];
ub2 charsetId;
sword status;
// get character set id
status = OCIAttrGet(self->environment->handle, OCI_HTYPE_ENV, &charsetId,
NULL, attribute, self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"Connection_GetCharacterSetName(): get charset id") < 0)
return NULL;
// get character set name
status = OCINlsCharSetIdToName(self->environment->handle,
(text*) charsetName, OCI_NLS_MAXBUFSZ, charsetId);
if (Environment_CheckForError(self->environment, status,
"Connection_GetCharacterSetName(): get Oracle charset name") < 0)
return NULL;
// get IANA character set name
status = OCINlsNameMap(self->environment->handle,
(oratext*) ianaCharsetName, OCI_NLS_MAXBUFSZ,
(oratext*) charsetName, OCI_NLS_CS_ORA_TO_IANA);
if (Environment_CheckForError(self->environment, status,
"Connection_GetCharacterSetName(): translate NLS charset") < 0)
return NULL;
return PyBytes_FromString(ianaCharsetName);
}
//-----------------------------------------------------------------------------
// Connection_GetEncoding()
// Retrieve the IANA encoding used by the client.
//-----------------------------------------------------------------------------
static PyObject *Connection_GetEncoding(
udt_Connection *self, // connection object
void *arg) // optional argument (ignored)
{
return Connection_GetCharacterSetName(self, OCI_ATTR_ENV_CHARSET_ID);
}
//-----------------------------------------------------------------------------
// Connection_GetNationalEncoding()
// Retrieve the IANA national encoding used by the client.
//-----------------------------------------------------------------------------
static PyObject *Connection_GetNationalEncoding(
udt_Connection *self, // connection object
void *arg) // optional argument (ignored)
{
return Connection_GetCharacterSetName(self, OCI_ATTR_ENV_NCHARSET_ID);
}
#endif
//-----------------------------------------------------------------------------
// Connection_GetStmtCacheSize()
// Return the Oracle statement cache size.

View File

@ -206,7 +206,7 @@ static int Cursor_FreeHandle(
udt_Cursor *self, // cursor object
int raiseException) // raise an exception, if necesary?
{
udt_StringBuffer buffer;
udt_Buffer buffer;
sword status;
if (self->handle) {
@ -216,12 +216,13 @@ static int Cursor_FreeHandle(
self->environment, status, "Cursor_FreeHandle()") < 0)
return -1;
} else if (self->connection->handle != 0) {
if (!StringBuffer_Fill(&buffer, self->statementTag) < 0)
if (!cxBuffer_FromObject(&buffer, self->statementTag,
self->environment->encoding) < 0)
return (raiseException) ? -1 : 0;
status = OCIStmtRelease(self->handle,
self->environment->errorHandle, (text*) buffer.ptr,
buffer.size, OCI_DEFAULT);
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
if (raiseException && Environment_CheckForError(
self->environment, status, "Cursor_FreeHandle()") < 0)
return -1;
@ -428,7 +429,8 @@ static int Cursor_GetBindNames(
for (i = 0; i < foundElements; i++) {
if (!duplicate[i]) {
temp = cxString_FromEncodedString(bindNames[i],
bindNameLengths[i]);
bindNameLengths[i],
self->connection->environment->encoding);
if (!temp) {
Py_DECREF(*names);
PyMem_Free(buffer);
@ -689,7 +691,7 @@ static PyObject *Cursor_ItemDescriptionHelper(
type = (PyObject*) varType->pythonType;
if (type == (PyObject*) &g_StringVarType)
displaySize = charSize;
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
else if (type == (PyObject*) &g_UnicodeVarType)
displaySize = charSize;
#endif
@ -697,7 +699,7 @@ static PyObject *Cursor_ItemDescriptionHelper(
displaySize = internalSize;
else if (type == (PyObject*) &g_FixedCharVarType)
displaySize = charSize;
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
else if (type == (PyObject*) &g_FixedUnicodeVarType)
displaySize = charSize;
#endif
@ -720,7 +722,8 @@ static PyObject *Cursor_ItemDescriptionHelper(
return NULL;
// set each of the items in the tuple
PyTuple_SET_ITEM(tuple, 0, cxString_FromEncodedString(name, nameLength));
PyTuple_SET_ITEM(tuple, 0, cxString_FromEncodedString(name, nameLength,
self->connection->environment->encoding));
Py_INCREF(type);
PyTuple_SET_ITEM(tuple, 1, type);
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(displaySize));
@ -1126,7 +1129,7 @@ static int Cursor_InternalPrepare(
PyObject *statement, // statement to prepare
PyObject *statementTag) // tag of statement to prepare
{
udt_StringBuffer statementBuffer, tagBuffer;
udt_Buffer statementBuffer, tagBuffer;
sword status;
// make sure we don't get a situation where nothing is to be executed
@ -1160,10 +1163,12 @@ static int Cursor_InternalPrepare(
// prepare statement
self->isOwned = 0;
if (StringBuffer_Fill(&statementBuffer, statement) < 0)
if (cxBuffer_FromObject(&statementBuffer, statement,
self->environment->encoding) < 0)
return -1;
if (StringBuffer_Fill(&tagBuffer, statementTag) < 0) {
StringBuffer_Clear(&statementBuffer);
if (cxBuffer_FromObject(&tagBuffer, statementTag,
self->environment->encoding) < 0) {
cxBuffer_Clear(&statementBuffer);
return -1;
}
Py_BEGIN_ALLOW_THREADS
@ -1172,8 +1177,8 @@ static int Cursor_InternalPrepare(
statementBuffer.size, (text*) tagBuffer.ptr, tagBuffer.size,
OCI_NTV_SYNTAX, OCI_DEFAULT);
Py_END_ALLOW_THREADS
StringBuffer_Clear(&statementBuffer);
StringBuffer_Clear(&tagBuffer);
cxBuffer_Clear(&statementBuffer);
cxBuffer_Clear(&tagBuffer);
if (Environment_CheckForError(self->environment, status,
"Cursor_InternalPrepare(): prepare") < 0) {
// this is needed to avoid "invalid handle" errors since Oracle doesn't
@ -1255,8 +1260,7 @@ static PyObject *Cursor_Prepare(
// statement text and optional tag is expected
statementTag = NULL;
if (!PyArg_ParseTuple(args, "O!|O!", cxString_Type, &statement,
cxString_Type, &statementTag))
if (!PyArg_ParseTuple(args, "O|O", &statement, &statementTag))
return NULL;
// make sure the cursor is open
@ -1516,9 +1520,8 @@ static PyObject *Cursor_CallFunc(
// parse arguments
listOfArguments = keywordArguments = NULL;
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O!O|OO", keywordList,
cxString_Type, &name, &returnType, &listOfArguments,
&keywordArguments))
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "OO|OO", keywordList,
&name, &returnType, &listOfArguments, &keywordArguments))
return NULL;
// create the return variable
@ -1553,8 +1556,8 @@ static PyObject *Cursor_CallProc(
// parse arguments
listOfArguments = keywordArguments = NULL;
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O!|OO", keywordList,
cxString_Type, &name, &listOfArguments, &keywordArguments))
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O|OO", keywordList,
&name, &listOfArguments, &keywordArguments))
return NULL;
// call the stored procedure
@ -1595,10 +1598,6 @@ static PyObject *Cursor_Execute(
executeArgs = NULL;
if (!PyArg_ParseTuple(args, "O|O", &statement, &executeArgs))
return NULL;
if (statement != Py_None && !cxString_Check(statement)) {
PyErr_SetString(PyExc_TypeError, "expecting None or a string");
return NULL;
}
if (executeArgs && keywordArgs) {
if (PyDict_Size(keywordArgs) == 0)
keywordArgs = NULL;
@ -1674,10 +1673,6 @@ static PyObject *Cursor_ExecuteMany(
if (!PyArg_ParseTuple(args, "OO!", &statement, &PyList_Type,
&listOfArguments))
return NULL;
if (statement != Py_None && !cxString_Check(statement)) {
PyErr_SetString(PyExc_TypeError, "expecting None or string");
return NULL;
}
// make sure the cursor is open
if (Cursor_IsOpen(self) < 0)
@ -2115,9 +2110,9 @@ static PyObject *Cursor_Var(
size = 0;
arraySize = self->bindArraySize;
inConverter = outConverter = typeNameObj = NULL;
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O|iiOOO!",
keywordList, &type, &size, &arraySize, &inConverter,
&outConverter, cxString_Type, &typeNameObj))
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O|iiOOO", keywordList,
&type, &size, &arraySize, &inConverter, &outConverter,
&typeNameObj))
return NULL;
// determine the type of variable

View File

@ -12,8 +12,13 @@ typedef struct {
OCIError *errorHandle;
int maxBytesPerCharacter;
int fixedWidth;
char *encoding;
char *nencoding;
ub4 maxStringBytes;
PyObject *cloneEnv;
udt_Buffer numberToStringFormatBuffer;
udt_Buffer numberFromStringFormatBuffer;
udt_Buffer nlsNumericCharactersBuffer;
} udt_Environment;
//-----------------------------------------------------------------------------
@ -76,9 +81,12 @@ static udt_Environment *Environment_New(
env->handle = NULL;
env->errorHandle = NULL;
env->fixedWidth = 1;
env->maxBytesPerCharacter = CXORA_BYTES_PER_CHAR;
env->maxStringBytes = MAX_STRING_CHARS * CXORA_BYTES_PER_CHAR;
env->maxBytesPerCharacter = 1;
env->maxStringBytes = MAX_STRING_CHARS;
env->cloneEnv = NULL;
cxBuffer_Init(&env->numberToStringFormatBuffer);
cxBuffer_Init(&env->numberFromStringFormatBuffer);
cxBuffer_Init(&env->nlsNumericCharactersBuffer);
// create the error handle
status = OCIHandleAlloc(handle, (dvoid**) &env->errorHandle,
@ -94,13 +102,86 @@ static udt_Environment *Environment_New(
}
//-----------------------------------------------------------------------------
// Environment_GetCharacterSetName()
// Retrieve and store the IANA character set name for the attribute.
//-----------------------------------------------------------------------------
static int Environment_GetCharacterSetName(
udt_Environment *self, // environment object
ub2 attribute, // attribute to fetch
const char *overrideValue, // override value, if specified
char **result) // place to store result
{
char charsetName[OCI_NLS_MAXBUFSZ], ianaCharsetName[OCI_NLS_MAXBUFSZ];
ub2 charsetId;
sword status;
// if override value specified, use it
if (overrideValue) {
*result = PyMem_Malloc(strlen(overrideValue) + 1);
if (!*result)
return -1;
strcpy(*result, overrideValue);
return 0;
}
// get character set id
status = OCIAttrGet(self->handle, OCI_HTYPE_ENV, &charsetId, NULL,
attribute, self->errorHandle);
if (Environment_CheckForError(self, status,
"Environment_GetCharacterSetName(): get charset id") < 0)
return -1;
// get character set name
status = OCINlsCharSetIdToName(self->handle, (text*) charsetName,
OCI_NLS_MAXBUFSZ, charsetId);
if (Environment_CheckForError(self, status,
"Environment_GetCharacterSetName(): get Oracle charset name") < 0)
return -1;
// get IANA character set name
status = OCINlsNameMap(self->handle, (oratext*) ianaCharsetName,
OCI_NLS_MAXBUFSZ, (oratext*) charsetName, OCI_NLS_CS_ORA_TO_IANA);
if (Environment_CheckForError(self, status,
"Environment_GetCharacterSetName(): translate NLS charset") < 0)
return -1;
// store results
*result = PyMem_Malloc(strlen(ianaCharsetName) + 1);
if (!*result)
return -1;
strcpy(*result, ianaCharsetName);
return 0;
}
//-----------------------------------------------------------------------------
// Environment_SetBuffer()
// Set the buffer in the environment from the specified string.
//-----------------------------------------------------------------------------
static int Environment_SetBuffer(
udt_Buffer *buf, // buffer to set
const char *value, // ASCII value to use
const char *encoding) // encoding to use
{
PyObject *obj;
obj = cxString_FromAscii(value);
if (!obj)
return -1;
return cxBuffer_FromObject(buf, obj, encoding);
}
//-----------------------------------------------------------------------------
// Environment_NewFromScratch()
// Create a new environment object from scratch.
//-----------------------------------------------------------------------------
static udt_Environment *Environment_NewFromScratch(
int threaded, // use threaded mode?
int events) // use events mode?
int events, // use events mode?
char *encoding, // override value for encoding
char *nencoding) // override value for nencoding
{
udt_Environment *env;
OCIEnv *handle;
@ -117,8 +198,8 @@ static udt_Environment *Environment_NewFromScratch(
#endif
// create the new environment handle
status = OCIEnvNlsCreate(&handle, mode, NULL, NULL, NULL,
NULL, 0, NULL, CXORA_CHARSETID, CXORA_CHARSETID);
status = OCIEnvNlsCreate(&handle, mode, NULL, NULL, NULL, NULL, 0, NULL, 0,
0);
if (!handle ||
(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO)) {
PyErr_SetString(g_InterfaceErrorException,
@ -133,7 +214,6 @@ static udt_Environment *Environment_NewFromScratch(
return NULL;
}
#ifndef WITH_UNICODE
// acquire max bytes per character
status = OCINlsNumericInfoGet(env->handle, env->errorHandle,
&env->maxBytesPerCharacter, OCI_NLS_CHARSET_MAXBYTESZ);
@ -152,7 +232,26 @@ static udt_Environment *Environment_NewFromScratch(
Py_DECREF(env);
return NULL;
}
#endif
// determine encodings to use for Unicode values
if (Environment_GetCharacterSetName(env, OCI_ATTR_ENV_CHARSET_ID,
encoding, &env->encoding) < 0)
return NULL;
if (Environment_GetCharacterSetName(env, OCI_ATTR_ENV_NCHARSET_ID,
nencoding, &env->nencoding) < 0)
return NULL;
// fill buffers for number formats
if (Environment_SetBuffer(&env->numberToStringFormatBuffer, "TM9",
env->encoding) < 0)
return NULL;
if (Environment_SetBuffer(&env->numberFromStringFormatBuffer,
"999999999999999999999999999999999999999999999999999999999999999",
env->encoding) < 0)
return NULL;
if (Environment_SetBuffer(&env->nlsNumericCharactersBuffer,
"NLS_NUMERIC_CHARACTERS='.,'", env->encoding) < 0)
return NULL;
return env;
}
@ -176,6 +275,14 @@ static udt_Environment *Environment_Clone(
env->fixedWidth = cloneEnv->fixedWidth;
Py_INCREF(cloneEnv);
env->cloneEnv = (PyObject*) cloneEnv;
env->encoding = cloneEnv->encoding;
env->nencoding = cloneEnv->nencoding;
cxBuffer_Copy(&env->numberToStringFormatBuffer,
&cloneEnv->numberToStringFormatBuffer);
cxBuffer_Copy(&env->numberFromStringFormatBuffer,
&cloneEnv->numberFromStringFormatBuffer);
cxBuffer_Copy(&env->nlsNumericCharactersBuffer,
&cloneEnv->nlsNumericCharactersBuffer);
return env;
}
@ -192,6 +299,15 @@ static void Environment_Free(
OCIHandleFree(self->errorHandle, OCI_HTYPE_ERROR);
if (self->handle && !self->cloneEnv)
OCIHandleFree(self->handle, OCI_HTYPE_ENV);
if (!self->cloneEnv) {
if (self->encoding)
PyMem_Free(self->encoding);
if (self->nencoding)
PyMem_Free(self->nencoding);
}
cxBuffer_Clear(&self->numberToStringFormatBuffer);
cxBuffer_Clear(&self->numberFromStringFormatBuffer);
cxBuffer_Clear(&self->nlsNumericCharactersBuffer);
Py_CLEAR(self->cloneEnv);
Py_TYPE(self)->tp_free((PyObject*) self);
}

16
Error.c
View File

@ -80,12 +80,12 @@ static udt_Error *Error_New(
const char *context, // context in which error occurred
int retrieveError) // retrieve error from OCI?
{
char errorText[1024 * CXORA_BYTES_PER_CHAR];
char errorText[4096];
udt_Error *self;
ub4 handleType;
dvoid *handle;
sword status;
#ifdef WITH_UNICODE
#if PY_MAJOR_VERSION >= 3
Py_ssize_t len;
#endif
@ -108,14 +108,12 @@ static udt_Error *Error_New(
PyErr_SetString(g_InternalErrorException, "No Oracle error?");
return NULL;
}
#ifdef WITH_UNICODE
for (len = 0; len < sizeof(errorText); len += 2) {
if (errorText[len] == 0 && errorText[len + 1] == 0)
break;
}
self->message = cxString_FromEncodedString(errorText, len);
#else
#if PY_MAJOR_VERSION < 3
self->message = PyBytes_FromString(errorText);
#else
len = strlen(errorText);
self->message = PyUnicode_Decode(errorText, len, environment->encoding,
NULL);
#endif
if (!self->message) {
Py_DECREF(self);

View File

@ -169,7 +169,6 @@ static int ExternalLobVar_InternalRead(
ub4 *length, // length of data (IN/OUT)
int offset) // offset
{
ub2 charsetId;
sword status;
if (var->lobVar->isFile) {
@ -183,15 +182,11 @@ static int ExternalLobVar_InternalRead(
return -1;
}
if (var->lobVar->type == &vt_NCLOB)
charsetId = OCI_UTF16ID;
else charsetId = CXORA_CHARSETID;
Py_BEGIN_ALLOW_THREADS
status = OCILobRead(var->lobVar->connection->handle,
var->lobVar->environment->errorHandle,
var->lobVar->data[var->pos], length, offset, buffer,
bufferSize, NULL, NULL, charsetId, var->lobVar->type->charsetForm);
bufferSize, NULL, NULL, 0, var->lobVar->type->charsetForm);
Py_END_ALLOW_THREADS
if (Environment_CheckForError(var->lobVar->environment, status,
"ExternalLobVar_LobRead()") < 0) {
@ -284,13 +279,11 @@ static PyObject *ExternalLobVar_Value(
if (var->lobVar->type == &vt_CLOB) {
if (var->lobVar->environment->fixedWidth)
length = length * var->lobVar->environment->maxBytesPerCharacter;
result = cxString_FromEncodedString(buffer, length);
result = cxString_FromEncodedString(buffer, length,
var->lobVar->environment->encoding);
} else if (var->lobVar->type == &vt_NCLOB) {
#ifdef Py_UNICODE_WIDE
result = PyUnicode_DecodeUTF16(buffer, length * 2, NULL, NULL);
#else
result = PyUnicode_FromUnicode((Py_UNICODE*) buffer, length);
#endif
result = PyUnicode_Decode(buffer, length,
var->lobVar->environment->encoding, NULL);
} else {
result = PyBytes_FromStringAndSize(buffer, length);
}
@ -550,7 +543,7 @@ static PyObject *ExternalLobVar_GetFileName(
udt_ExternalLobVar *var, // variable to get file name for
PyObject *args) // arguments
{
char dirAlias[30 * CXORA_BYTES_PER_CHAR], name[255 * CXORA_BYTES_PER_CHAR];
char dirAlias[120], name[1020];
ub2 dirAliasLength, nameLength;
PyObject *result, *temp;
sword status;
@ -558,8 +551,8 @@ static PyObject *ExternalLobVar_GetFileName(
// determine the directory alias and name
if (ExternalLobVar_Verify(var) < 0)
return NULL;
dirAliasLength = sizeof(dirAlias);
nameLength = sizeof(name);
dirAliasLength = sizeof(dirAlias);
status = OCILobFileGetName(var->lobVar->environment->handle,
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
(text*) dirAlias, &dirAliasLength, (text*) name, &nameLength);
@ -571,13 +564,15 @@ static PyObject *ExternalLobVar_GetFileName(
result = PyTuple_New(2);
if (!result)
return NULL;
temp = cxString_FromEncodedString(dirAlias, dirAliasLength);
temp = cxString_FromEncodedString(dirAlias, dirAliasLength,
var->lobVar->environment->encoding);
if (!temp) {
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, temp);
temp = cxString_FromEncodedString(name, nameLength);
temp = cxString_FromEncodedString(name, nameLength,
var->lobVar->environment->encoding);
if (!temp) {
Py_DECREF(result);
return NULL;

View File

@ -225,7 +225,7 @@ static PyObject *ExternalObjectVar_ConvertToPython(
stringSize = OCIStringSize(environment->handle,
* (OCIString**) value);
return cxString_FromEncodedString( (char*) stringValue,
stringSize);
stringSize, environment->encoding);
case OCI_TYPECODE_NUMBER:
return OracleNumberToPythonFloat(environment, (OCINumber*) value);
case OCI_TYPECODE_DATE:
@ -257,19 +257,20 @@ static PyObject *ExternalObjectVar_GetAttributeValue(
{
dvoid *valueIndicator, *value;
OCIInd scalarValueIndicator;
udt_StringBuffer buffer;
udt_Buffer buffer;
sword status;
OCIType *tdo;
// get the value for the attribute
if (StringBuffer_Fill(&buffer, attribute->name) < 0)
if (cxBuffer_FromObject(&buffer, attribute->name,
self->objectType->environment->encoding) < 0)
return NULL;
status = OCIObjectGetAttr(self->objectType->environment->handle,
self->objectType->environment->errorHandle, self->instance,
self->indicator, self->objectType->tdo,
(const OraText**) &buffer.ptr, (ub4*) &buffer.size, 1, 0, 0,
&scalarValueIndicator, &valueIndicator, &value, &tdo);
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
if (Environment_CheckForError(self->objectType->environment, status,
"ExternalObjectVar_GetAttributeValue(): getting value") < 0)
return NULL;

View File

@ -308,8 +308,7 @@ static int LobVar_Write(
ub4 offset, // offset into variable
ub4 *amount) // amount to write
{
ub2 charsetId = CXORA_CHARSETID;
udt_StringBuffer buffer;
udt_Buffer buffer;
sword status;
// verify the data type
@ -317,29 +316,20 @@ static int LobVar_Write(
PyErr_SetString(PyExc_TypeError, "BFILEs are read only");
return -1;
} else if (var->type == &vt_BLOB) {
if (!PyBytes_Check(dataObj)) {
PyErr_SetString(PyExc_TypeError, "BLOBs expect byte data");
if (cxBuffer_FromObject(&buffer, dataObj,
var->environment->encoding) < 0)
return -1;
}
StringBuffer_FromBytes(&buffer, dataObj);
*amount = buffer.size;
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
} else if (var->type == &vt_NCLOB) {
if (!PyUnicode_Check(dataObj)) {
PyErr_SetString(PyExc_TypeError, "NCLOBs expect unicode data");
if (cxBuffer_FromObject(&buffer, dataObj,
var->environment->nencoding) < 0)
return -1;
}
if (StringBuffer_FromUnicode(&buffer, dataObj) < 0)
return -1;
*amount = buffer.size / 2;
charsetId = OCI_UTF16ID;
*amount = buffer.size;
#endif
} else {
if (!cxString_Check(dataObj)) {
PyErr_SetString(PyExc_TypeError, "CLOBs expect string data");
return -1;
}
if (StringBuffer_Fill(&buffer, dataObj) < 0)
if (cxBuffer_FromObject(&buffer, dataObj,
var->environment->encoding) < 0)
return -1;
if (var->environment->fixedWidth
&& var->environment->maxBytesPerCharacter > 1)
@ -349,17 +339,17 @@ static int LobVar_Write(
// nothing to do if no data to write
if (*amount == 0) {
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
return 0;
}
Py_BEGIN_ALLOW_THREADS
status = OCILobWrite(var->connection->handle,
var->environment->errorHandle, var->data[position], amount, offset,
(void*) buffer.ptr, buffer.size, OCI_ONE_PIECE, NULL, NULL,
charsetId, var->type->charsetForm);
(void*) buffer.ptr, buffer.size, OCI_ONE_PIECE, NULL, NULL, 0,
var->type->charsetForm);
Py_END_ALLOW_THREADS
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
if (Environment_CheckForError(var->environment, status,
"LobVar_Write()") < 0)
return -1;

View File

@ -127,40 +127,17 @@ static int LongVar_SetValue(
unsigned pos, // array position to set
PyObject *value) // value to set
{
udt_StringBuffer buffer;
udt_Buffer buffer;
char *ptr;
ub4 size;
// get the buffer data and size for binding
if (var->type == &vt_LongBinary) {
if (PyBytes_Check(value)) {
if (StringBuffer_FromBytes(&buffer, value) < 0)
return -1;
#if PY_MAJOR_VERSION < 3
} else if (cxBinary_Check(value)) {
if (StringBuffer_FromBinary(&buffer, value) < 0)
return -1;
#endif
} else {
PyErr_SetString(PyExc_TypeError,
"expecting string or buffer data");
return -1;
}
size = buffer.size;
} else {
if (!cxString_Check(value)) {
PyErr_SetString(PyExc_TypeError, "expecting string data");
return -1;
}
if (StringBuffer_Fill(&buffer, value) < 0)
return -1;
size = cxString_GetSize(value);
}
if (cxBuffer_FromObject(&buffer, value, var->environment->encoding) < 0)
return -1;
// verify there is enough space to store the value
if (size > var->size) {
if (Variable_Resize((udt_Variable*) var, size) < 0) {
StringBuffer_Clear(&buffer);
if (buffer.numCharacters > var->size) {
if (Variable_Resize((udt_Variable*) var, buffer.numCharacters) < 0) {
cxBuffer_Clear(&buffer);
return -1;
}
}
@ -170,7 +147,7 @@ static int LongVar_SetValue(
*((ub4 *) ptr) = (ub4) buffer.size;
if (buffer.size)
memcpy(ptr + sizeof(ub4), buffer.ptr, buffer.size);
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
return 0;
}
@ -192,7 +169,7 @@ static PyObject *LongVar_GetValue(
ptr += sizeof(ub4);
if (var->type == &vt_LongBinary)
return PyBytes_FromStringAndSize(ptr, size);
return cxString_FromEncodedString(ptr, size);
return cxString_FromEncodedString(ptr, size, var->environment->encoding);
}
@ -205,10 +182,6 @@ static ub4 LongVar_GetBufferSize(
{
if (!self->type->isCharacterData)
return self->size + sizeof(ub4);
#ifdef WITH_UNICODE
return sizeof(ub4) + self->size * CXORA_BYTES_PER_CHAR;
#else
return sizeof(ub4) + self->size * self->environment->maxBytesPerCharacter;
#endif
}

View File

@ -332,20 +332,22 @@ static int NumberVar_SetValueFromLong(
unsigned pos, // array position to set
PyObject *value) // value to set
{
udt_StringBuffer textBuffer;
udt_Buffer textBuffer;
PyObject *textValue;
sword status;
textValue = cxString_FromObject(value);
textValue = PyObject_Str(value);
if (!textValue)
return -1;
if (StringBuffer_Fill(&textBuffer, textValue) < 0)
if (cxBuffer_FromObject(&textBuffer, textValue,
var->environment->encoding) < 0)
return -1;
status = OCINumberFromText(var->environment->errorHandle,
(text*) textBuffer.ptr, textBuffer.size,
(text*) g_NumberToStringFormatBuffer.ptr,
g_NumberToStringFormatBuffer.size, NULL, 0, &var->data[pos]);
StringBuffer_Clear(&textBuffer);
(text*) var->environment->numberFromStringFormatBuffer.ptr,
var->environment->numberFromStringFormatBuffer.size, NULL, 0,
&var->data[pos]);
cxBuffer_Clear(&textBuffer);
Py_DECREF(textValue);
return Environment_CheckForError(var->environment, status,
"NumberVar_SetValueFromLong()");
@ -450,7 +452,7 @@ static int NumberVar_SetValueFromDecimal(
PyObject *value) // value to set
{
PyObject *textValue, *format, *tupleValue;
udt_StringBuffer textBuffer, formatBuffer;
udt_Buffer textBuffer, formatBuffer;
sword status;
tupleValue = PyObject_CallMethod(value, "as_tuple", NULL);
@ -462,18 +464,22 @@ static int NumberVar_SetValueFromDecimal(
return -1;
}
Py_DECREF(tupleValue);
if (StringBuffer_Fill(&textBuffer, textValue) < 0)
if (cxBuffer_FromObject(&textBuffer, textValue,
var->environment->encoding) < 0)
return -1;
if (StringBuffer_Fill(&formatBuffer, format) < 0) {
StringBuffer_Clear(&textBuffer);
if (cxBuffer_FromObject(&formatBuffer, format,
var->environment->encoding) < 0) {
cxBuffer_Clear(&textBuffer);
return -1;
}
status = OCINumberFromText(var->environment->errorHandle,
(text*) textBuffer.ptr, textBuffer.size, (text*) formatBuffer.ptr,
formatBuffer.size, g_NlsNumericCharactersBuffer.ptr,
g_NlsNumericCharactersBuffer.size, &var->data[pos]);
StringBuffer_Clear(&textBuffer);
StringBuffer_Clear(&formatBuffer);
formatBuffer.size,
var->environment->nlsNumericCharactersBuffer.ptr,
var->environment->nlsNumericCharactersBuffer.size,
&var->data[pos]);
cxBuffer_Clear(&textBuffer);
cxBuffer_Clear(&formatBuffer);
Py_DECREF(textValue);
Py_DECREF(format);
return Environment_CheckForError(var->environment, status,
@ -541,13 +547,15 @@ static PyObject *NumberVar_GetValue(
if (var->type == &vt_NumberAsString || var->type == &vt_LongInteger) {
stringLength = sizeof(stringValue);
status = OCINumberToText(var->environment->errorHandle,
&var->data[pos], (text*) g_ShortNumberToStringFormatBuffer.ptr,
g_ShortNumberToStringFormatBuffer.size, NULL, 0, &stringLength,
(unsigned char*) stringValue);
&var->data[pos],
(text*) var->environment->numberToStringFormatBuffer.ptr,
var->environment->numberToStringFormatBuffer.size, NULL, 0,
&stringLength, (unsigned char*) stringValue);
if (Environment_CheckForError(var->environment, status,
"NumberVar_GetValue(): as string") < 0)
return NULL;
stringObj = cxString_FromEncodedString(stringValue, stringLength);
stringObj = cxString_FromEncodedString(stringValue, stringLength,
var->environment->encoding);
if (!stringObj)
return NULL;
if (var->type == &vt_NumberAsString)

View File

@ -297,7 +297,8 @@ static int ObjectType_Initialize(
if (Environment_CheckForError(self->environment, status,
"ObjectType_Initialize(): get schema name") < 0)
return -1;
self->schema = cxString_FromEncodedString(name, size);
self->schema = cxString_FromEncodedString(name, size,
self->environment->encoding);
if (!self->schema)
return -1;
@ -307,7 +308,8 @@ static int ObjectType_Initialize(
if (Environment_CheckForError(self->environment, status,
"ObjectType_Initialize(): get name") < 0)
return -1;
self->name = cxString_FromEncodedString(name, size);
self->name = cxString_FromEncodedString(name, size,
self->environment->encoding);
if (!self->name)
return -1;
@ -386,8 +388,8 @@ static udt_ObjectType *ObjectType_NewByName(
PyObject *name) // name of object type to describe
{
OCIDescribe *describeHandle;
udt_StringBuffer buffer;
udt_ObjectType *result;
udt_Buffer buffer;
OCIParam *param;
sword status;
@ -399,14 +401,15 @@ static udt_ObjectType *ObjectType_NewByName(
return NULL;
// describe the object
if (StringBuffer_Fill(&buffer, name) < 0) {
if (cxBuffer_FromObject(&buffer, name,
connection->environment->encoding) < 0) {
OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
return NULL;
}
status = OCIDescribeAny(connection->handle,
connection->environment->errorHandle, (dvoid*) buffer.ptr,
buffer.size, OCI_OTYPE_NAME, 0, OCI_PTYPE_TYPE, describeHandle);
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
if (Environment_CheckForError(connection->environment, status,
"ObjectType_NewByName(): describe type") < 0) {
OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
@ -509,7 +512,8 @@ static int ObjectAttribute_Initialize(
if (Environment_CheckForError(connection->environment, status,
"ObjectAttribute_Initialize(): get name") < 0)
return -1;
self->name = cxString_FromEncodedString(name, size);
self->name = cxString_FromEncodedString(name, size,
connection->environment->encoding);
if (!self->name)
return -1;

View File

@ -171,7 +171,7 @@ static int SessionPool_Init(
{
unsigned minSessions, maxSessions, sessionIncrement;
PyObject *threadedObj, *eventsObj, *homogeneousObj;
udt_StringBuffer username, password, dsn;
udt_Buffer username, password, dsn;
int threaded, events, homogeneous;
PyTypeObject *connectionType;
unsigned poolNameLength;
@ -235,7 +235,8 @@ static int SessionPool_Init(
self->homogeneous = homogeneous;
// set up the environment
self->environment = Environment_NewFromScratch(threaded, events);
self->environment = Environment_NewFromScratch(threaded, events, NULL,
NULL);
if (!self->environment)
return -1;
@ -252,15 +253,18 @@ static int SessionPool_Init(
poolMode |= OCI_SPC_HOMOGENEOUS;
// create the session pool
if (StringBuffer_Fill(&username, self->username) < 0)
if (cxBuffer_FromObject(&username, self->username,
self->environment->encoding) < 0)
return -1;
if (StringBuffer_Fill(&password, self->password) < 0) {
StringBuffer_Clear(&username);
if (cxBuffer_FromObject(&password, self->password,
self->environment->encoding) < 0) {
cxBuffer_Clear(&username);
return -1;
}
if (StringBuffer_Fill(&dsn, self->dsn) < 0) {
StringBuffer_Clear(&username);
StringBuffer_Clear(&password);
if (cxBuffer_FromObject(&dsn, self->dsn,
self->environment->encoding) < 0) {
cxBuffer_Clear(&username);
cxBuffer_Clear(&password);
return -1;
}
Py_BEGIN_ALLOW_THREADS
@ -271,15 +275,16 @@ static int SessionPool_Init(
(OraText*) username.ptr, username.size, (OraText*) password.ptr,
password.size, poolMode);
Py_END_ALLOW_THREADS
StringBuffer_Clear(&username);
StringBuffer_Clear(&password);
StringBuffer_Clear(&dsn);
cxBuffer_Clear(&username);
cxBuffer_Clear(&password);
cxBuffer_Clear(&dsn);
if (Environment_CheckForError(self->environment, status,
"SessionPool_New(): create pool") < 0)
return -1;
// create the string for the pool name
self->name = cxString_FromEncodedString(poolName, poolNameLength);
self->name = cxString_FromEncodedString(poolName, poolNameLength,
self->environment->encoding);
if (!self->name)
return -1;

View File

@ -1,170 +0,0 @@
//-----------------------------------------------------------------------------
// StringUtils.c
// Defines constants and routines specific to handling strings.
//-----------------------------------------------------------------------------
// define structure for abstracting string buffers
typedef struct {
const void *ptr;
Py_ssize_t size;
#ifdef Py_UNICODE_WIDE
PyObject *encodedString;
#endif
} udt_StringBuffer;
// use the bytes methods in cx_Oracle and define them as the equivalent string
// type methods as is done in Python 2.6
#ifndef PyBytes_Check
#define PyBytes_Type PyString_Type
#define PyBytes_AS_STRING PyString_AS_STRING
#define PyBytes_GET_SIZE PyString_GET_SIZE
#define PyBytes_Check PyString_Check
#define PyBytes_Format PyString_Format
#define PyBytes_FromString PyString_FromString
#define PyBytes_FromStringAndSize PyString_FromStringAndSize
#endif
// define binary type and methods
#if PY_MAJOR_VERSION >= 3
#define cxBinary_Type PyBytes_Type
#define cxBinary_Check PyBytes_Check
#else
#define cxBinary_Type PyBuffer_Type
#define cxBinary_Check PyBuffer_Check
#endif
//-----------------------------------------------------------------------------
// StringBuffer_Init()
// Initialize the string buffer with an empty string. Returns 0 as a
// convenience to the caller.
//-----------------------------------------------------------------------------
static int StringBuffer_Init(
udt_StringBuffer *buf) // buffer to fill
{
buf->ptr = NULL;
buf->size = 0;
#ifdef Py_UNICODE_WIDE
buf->encodedString = NULL;
#endif
return 0;
}
//-----------------------------------------------------------------------------
// StringBuffer_FromUnicode()
// Populate the string buffer from a unicode object.
//-----------------------------------------------------------------------------
static int StringBuffer_FromUnicode(
udt_StringBuffer *buf, // buffer to fill
PyObject *obj) // unicode object expected
{
if (!obj)
return StringBuffer_Init(buf);
#ifdef Py_UNICODE_WIDE
int one = 1;
int byteOrder = (IS_LITTLE_ENDIAN) ? -1 : 1;
buf->encodedString = PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(obj),
PyUnicode_GET_SIZE(obj), NULL, byteOrder);
if (!buf->encodedString)
return -1;
buf->ptr = PyBytes_AS_STRING(buf->encodedString);
buf->size = PyBytes_GET_SIZE(buf->encodedString);
#else
buf->ptr = (char*) PyUnicode_AS_UNICODE(obj);
buf->size = PyUnicode_GET_DATA_SIZE(obj);
#endif
return 0;
}
//-----------------------------------------------------------------------------
// StringBuffer_FromBytes()
// Populate the string buffer from a bytes object.
//-----------------------------------------------------------------------------
static int StringBuffer_FromBytes(
udt_StringBuffer *buf, // buffer to fill
PyObject *obj) // bytes object expected
{
if (!obj)
return StringBuffer_Init(buf);
buf->ptr = PyBytes_AS_STRING(obj);
buf->size = PyBytes_GET_SIZE(obj);
#ifdef Py_UNICODE_WIDE
buf->encodedString = NULL;
#endif
return 0;
}
#if PY_MAJOR_VERSION < 3
//-----------------------------------------------------------------------------
// StringBuffer_FromBuffer()
// Populate the string buffer from a buffer object.
//-----------------------------------------------------------------------------
static int StringBuffer_FromBuffer(
udt_StringBuffer *buf, // buffer to fill
PyObject *obj) // bytes object expected
{
if (!obj)
return StringBuffer_Init(buf);
if (PyObject_AsReadBuffer(obj, &buf->ptr, &buf->size) < 0)
return -1;
#ifdef Py_UNICODE_WIDE
buf->encodedString = NULL;
#endif
return 0;
}
#endif
#if PY_MAJOR_VERSION >= 3
#define StringBuffer_FromBinary StringBuffer_FromBytes
#else
#define StringBuffer_FromBinary StringBuffer_FromBuffer
#endif
#ifdef WITH_UNICODE
#define CXORA_CHARSETID OCI_UTF16ID
#define CXORA_BYTES_PER_CHAR 2
#define cxString_Type &PyUnicode_Type
#define cxString_Format PyUnicode_Format
#define cxString_Check PyUnicode_Check
#define cxString_GetSize PyUnicode_GET_SIZE
#if PY_MAJOR_VERSION >= 3
#define cxString_FromObject PyObject_Str
#else
#define cxString_FromObject PyObject_Unicode
#endif
#define cxString_FromAscii(str) \
PyUnicode_DecodeASCII(str, strlen(str), NULL)
#ifdef Py_UNICODE_WIDE
#define StringBuffer_Clear(buffer) \
Py_XDECREF((buffer)->encodedString)
#define cxString_FromEncodedString(buffer, numBytes) \
PyUnicode_DecodeUTF16(buffer, numBytes, NULL, NULL)
#else
#define StringBuffer_Clear(buffer)
#define cxString_FromEncodedString(buffer, numBytes) \
PyUnicode_FromUnicode((Py_UNICODE*) (buffer), (numBytes) / 2)
#endif
#define StringBuffer_Fill StringBuffer_FromUnicode
#else
#define CXORA_CHARSETID 0
#define CXORA_BYTES_PER_CHAR 1
#define cxString_Type &PyBytes_Type
#define cxString_Format PyBytes_Format
#define cxString_Check PyBytes_Check
#define cxString_GetSize PyBytes_GET_SIZE
#define cxString_FromObject PyObject_Str
#define StringBuffer_Clear(buffer)
#define cxString_FromAscii(str) \
PyBytes_FromString(str)
#define cxString_FromEncodedString(buffer, numBytes) \
PyBytes_FromStringAndSize(buffer, numBytes)
#define StringBuffer_Fill StringBuffer_FromBytes
#endif

View File

@ -16,11 +16,11 @@ typedef struct {
// Declaration of string variable functions.
//-----------------------------------------------------------------------------
static int StringVar_Initialize(udt_StringVar*, udt_Cursor*);
#ifndef WITH_UNICODE
static int StringVar_PostDefine(udt_StringVar*);
#endif
static int StringVar_SetValue(udt_StringVar*, unsigned, PyObject*);
static PyObject *StringVar_GetValue(udt_StringVar*, unsigned);
#if PY_MAJOR_VERSION < 3
static int StringVar_PostDefine(udt_StringVar*);
#endif
static ub4 StringVar_GetBufferSize(udt_StringVar*);
//-----------------------------------------------------------------------------
@ -51,7 +51,7 @@ static PyTypeObject g_StringVarType = {
};
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
static PyTypeObject g_UnicodeVarType = {
PyVarObject_HEAD_INIT(NULL, 0)
"cx_Oracle.UNICODE", // tp_name
@ -103,7 +103,7 @@ static PyTypeObject g_FixedCharVarType = {
};
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
static PyTypeObject g_FixedUnicodeVarType = {
PyVarObject_HEAD_INIT(NULL, 0)
"cx_Oracle.FIXED_UNICODE", // tp_name
@ -204,7 +204,7 @@ static udt_VariableType vt_String = {
};
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
static udt_VariableType vt_NationalCharString = {
(InitializeProc) StringVar_Initialize,
(FinalizeProc) NULL,
@ -248,7 +248,7 @@ static udt_VariableType vt_FixedChar = {
};
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
static udt_VariableType vt_FixedNationalChar = {
(InitializeProc) StringVar_Initialize,
(FinalizeProc) NULL,
@ -331,37 +331,6 @@ static int StringVar_Initialize(
}
#ifndef WITH_UNICODE
//-----------------------------------------------------------------------------
// StringVar_PostDefine()
// Set the character set information when values are fetched from this
// variable.
//-----------------------------------------------------------------------------
static int StringVar_PostDefine(
udt_StringVar *var) // variable to initialize
{
ub2 charsetId;
sword status;
status = OCIAttrSet(var->defineHandle, OCI_HTYPE_DEFINE,
&var->type->charsetForm, 0, OCI_ATTR_CHARSET_FORM,
var->environment->errorHandle);
if (Environment_CheckForError(var->environment, status,
"StringVar_PostDefine(): setting charset form") < 0)
return -1;
charsetId = OCI_UTF16ID;
status = OCIAttrSet(var->defineHandle, OCI_HTYPE_DEFINE, &charsetId, 0,
OCI_ATTR_CHARSET_ID, var->environment->errorHandle);
if (Environment_CheckForError(var->environment, status,
"StringVar_PostDefine(): setting charset id") < 0)
return -1;
return 0;
}
#endif
//-----------------------------------------------------------------------------
// StringVar_SetValue()
// Set the value of the variable.
@ -371,58 +340,27 @@ static int StringVar_SetValue(
unsigned pos, // array position to set
PyObject *value) // value to set
{
udt_StringBuffer buffer;
ub4 size;
udt_Buffer buffer;
// get the buffer data and size for binding
#ifdef WITH_UNICODE
if (!var->type->isCharacterData) {
#else
if (var->type->charsetForm == SQLCS_IMPLICIT) {
#endif
if (PyBytes_Check(value)) {
StringBuffer_FromBytes(&buffer, value);
size = buffer.size;
#if PY_MAJOR_VERSION < 3
} else if (cxBinary_Check(value)) {
if (StringBuffer_FromBinary(&buffer, value) < 0)
return -1;
size = buffer.size;
#endif
} else {
PyErr_SetString(PyExc_TypeError,
"expecting string or buffer data");
return -1;
}
if (var->type->isCharacterData
&& buffer.size > var->environment->maxStringBytes) {
StringBuffer_Clear(&buffer);
PyErr_SetString(PyExc_ValueError, "string data too large");
return -1;
} else if (!var->type->isCharacterData
&& buffer.size > MAX_BINARY_BYTES) {
StringBuffer_Clear(&buffer);
PyErr_SetString(PyExc_ValueError, "binary data too large");
return -1;
}
} else {
if (!PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError, "expecting unicode data");
return -1;
}
size = PyUnicode_GET_SIZE(value);
if (size > MAX_STRING_CHARS) {
PyErr_SetString(PyExc_ValueError, "unicode data too large");
return -1;
}
if (StringBuffer_FromUnicode(&buffer, value) < 0)
return -1;
// populate the buffer and confirm the maximum size is not exceeded
if (cxBuffer_FromObject(&buffer, value, var->environment->encoding) < 0)
return -1;
if (var->type->isCharacterData
&& buffer.numCharacters > MAX_STRING_CHARS) {
cxBuffer_Clear(&buffer);
PyErr_SetString(PyExc_ValueError, "string data too large");
return -1;
} else if (!var->type->isCharacterData
&& buffer.size > MAX_BINARY_BYTES) {
cxBuffer_Clear(&buffer);
PyErr_SetString(PyExc_ValueError, "binary data too large");
return -1;
}
// ensure that the buffer is large enough
if (buffer.size > var->bufferSize) {
if (Variable_Resize( (udt_Variable*) var, size) < 0) {
StringBuffer_Clear(&buffer);
if (Variable_Resize( (udt_Variable*) var, buffer.numCharacters) < 0) {
cxBuffer_Clear(&buffer);
return -1;
}
}
@ -431,7 +369,7 @@ static int StringVar_SetValue(
var->actualLength[pos] = (ub2) buffer.size;
if (buffer.size)
memcpy(var->data + var->bufferSize * pos, buffer.ptr, buffer.size);
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
return 0;
}
@ -448,23 +386,42 @@ static PyObject *StringVar_GetValue(
char *data;
data = var->data + pos * var->bufferSize;
#ifdef WITH_UNICODE
if (var->type == &vt_Binary)
return PyBytes_FromStringAndSize(data, var->actualLength[pos]);
return cxString_FromEncodedString(data, var->actualLength[pos]);
#else
if (var->type->charsetForm == SQLCS_IMPLICIT)
return PyBytes_FromStringAndSize(data, var->actualLength[pos]);
#ifdef Py_UNICODE_WIDE
return PyUnicode_DecodeUTF16(data, var->actualLength[pos], NULL, NULL);
#else
return PyUnicode_FromUnicode((Py_UNICODE*) data,
var->actualLength[pos] / 2);
#endif
#if PY_MAJOR_VERSION < 3
if (var->type == &vt_FixedNationalChar
|| var->type == &vt_NationalCharString)
return PyUnicode_Decode(data, var->actualLength[pos],
var->environment->nencoding, NULL);
#endif
return cxString_FromEncodedString(data, var->actualLength[pos],
var->environment->encoding);
}
#if PY_MAJOR_VERSION < 3
//-----------------------------------------------------------------------------
// StringVar_PostDefine()
// Set the character set information when values are fetched from this
// variable.
//-----------------------------------------------------------------------------
static int StringVar_PostDefine(
udt_StringVar *var) // variable to initialize
{
sword status;
status = OCIAttrSet(var->defineHandle, OCI_HTYPE_DEFINE,
&var->type->charsetForm, 0, OCI_ATTR_CHARSET_FORM,
var->environment->errorHandle);
if (Environment_CheckForError(var->environment, status,
"StringVar_PostDefine(): setting charset form") < 0)
return -1;
return 0;
}
#endif
//-----------------------------------------------------------------------------
// StringVar_GetBufferSize()
// Returns the buffer size to use for the variable.
@ -472,12 +429,8 @@ static PyObject *StringVar_GetValue(
static ub4 StringVar_GetBufferSize(
udt_StringVar* self) // variable to get buffer size for
{
#ifdef WITH_UNICODE
return self->size * CXORA_BYTES_PER_CHAR;
#else
if (self->type->charsetForm == SQLCS_IMPLICIT)
if (self->type->isCharacterData)
return self->size * self->environment->maxBytesPerCharacter;
return self->size * 2;
#endif
return self->size;
}

View File

@ -304,7 +304,8 @@ static int MessageRow_Initialize(
if (Environment_CheckForError(env, status,
"MessageRow_Initialize(): get rowid") < 0)
return -1;
self->rowid = cxString_FromEncodedString(rowid, rowidLength);
self->rowid = cxString_FromEncodedString(rowid, rowidLength,
env->encoding);
if (!self->rowid)
return -1;
@ -343,7 +344,7 @@ static int MessageTable_Initialize(
if (Environment_CheckForError(env, status,
"MessageTable_Initialize(): get table name") < 0)
return -1;
self->name = cxString_FromEncodedString(name, nameLength);
self->name = cxString_FromEncodedString(name, nameLength, env->encoding);
if (!self->name)
return -1;
@ -418,7 +419,8 @@ static int Message_Initialize(
if (Environment_CheckForError(env, status,
"Message_Initialize(): get database name") < 0)
return -1;
self->dbname = cxString_FromEncodedString(dbname, dbnameLength);
self->dbname = cxString_FromEncodedString(dbname, dbnameLength,
env->encoding);
if (!self->dbname)
return -1;
@ -537,7 +539,7 @@ static void Subscription_Callback(
#endif
// perform the call
env = Environment_NewFromScratch(0, 0);
env = Environment_NewFromScratch(0, 0, NULL, NULL);
if (!env)
PyErr_Print();
else {
@ -758,7 +760,7 @@ static PyObject *Subscription_RegisterQuery(
PyObject *args) // arguments
{
PyObject *statement, *executeArgs;
udt_StringBuffer statementBuffer;
udt_Buffer statementBuffer;
udt_Environment *env;
udt_Cursor *cursor;
sword status;
@ -789,14 +791,15 @@ static PyObject *Subscription_RegisterQuery(
}
// prepare the statement for execution
if (StringBuffer_Fill(&statementBuffer, statement) < 0) {
if (cxBuffer_FromObject(&statementBuffer, statement,
env->encoding) < 0) {
Py_DECREF(cursor);
return NULL;
}
status = OCIStmtPrepare(cursor->handle, env->errorHandle,
(text*) statementBuffer.ptr, statementBuffer.size, OCI_NTV_SYNTAX,
OCI_DEFAULT);
StringBuffer_Clear(&statementBuffer);
cxBuffer_Clear(&statementBuffer);
if (Environment_CheckForError(env, status,
"Subscription_RegisterQuery(): prepare statement") < 0) {
Py_DECREF(cursor);

View File

@ -363,7 +363,7 @@ static int Variable_Check(
Py_TYPE(object) == &g_StringVarType ||
Py_TYPE(object) == &g_FixedCharVarType ||
Py_TYPE(object) == &g_NCLOBVarType ||
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
Py_TYPE(object) == &g_UnicodeVarType ||
Py_TYPE(object) == &g_FixedUnicodeVarType ||
#endif
@ -393,7 +393,7 @@ static udt_VariableType *Variable_TypeByPythonType(
return &vt_String;
if (type == (PyObject*) &g_FixedCharVarType)
return &vt_FixedChar;
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
if (type == (PyObject*) &g_UnicodeVarType)
return &vt_NationalCharString;
if (type == (PyObject*) &PyUnicode_Type)
@ -487,33 +487,33 @@ static udt_VariableType *Variable_TypeByValue(
return &vt_LongString;
return &vt_String;
}
#ifdef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
if (PyUnicode_Check(value)) {
*size = PyUnicode_GET_SIZE(value);
if (*size > MAX_STRING_CHARS)
return &vt_LongString;
return &vt_NationalCharString;
}
if (PyInt_Check(value))
return &vt_Integer;
#else
if (PyBytes_Check(value)) {
*size = PyBytes_GET_SIZE(value);
if (*size > MAX_BINARY_BYTES)
return &vt_LongBinary;
return &vt_Binary;
}
#else
if (PyUnicode_Check(value)) {
*size = PyUnicode_GET_SIZE(value);
return &vt_NationalCharString;
}
#endif
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(value))
return &vt_Integer;
#endif
if (PyLong_Check(value))
return &vt_LongInteger;
if (PyFloat_Check(value))
return &vt_Float;
if (cxBinary_Check(value)) {
udt_StringBuffer temp;
if (StringBuffer_FromBinary(&temp, value) < 0)
udt_Buffer temp;
if (cxBuffer_FromObject(&temp, value, NULL) < 0)
return NULL;
*size = temp.size;
StringBuffer_Clear(&temp);
cxBuffer_Clear(&temp);
if (*size > MAX_BINARY_BYTES)
return &vt_LongBinary;
return &vt_Binary;
@ -574,13 +574,13 @@ static udt_VariableType *Variable_TypeByOracleDataType (
case SQLT_LNG:
return &vt_LongString;
case SQLT_AFC:
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
if (charsetForm == SQLCS_NCHAR)
return &vt_FixedNationalChar;
#endif
return &vt_FixedChar;
case SQLT_CHR:
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
if (charsetForm == SQLCS_NCHAR)
return &vt_NationalCharString;
#endif
@ -1056,8 +1056,9 @@ static int Variable_InternalBind(
// perform the bind
if (var->boundName) {
udt_StringBuffer buffer;
if (StringBuffer_Fill(&buffer, var->boundName) < 0)
udt_Buffer buffer;
if (cxBuffer_FromObject(&buffer, var->boundName,
var->environment->encoding) < 0)
return -1;
if (var->isArray) {
status = OCIBindByName(var->boundCursorHandle, &var->bindHandle,
@ -1073,7 +1074,7 @@ static int Variable_InternalBind(
var->type->oracleType, var->indicator, var->actualLength,
var->returnCode, 0, 0, OCI_DEFAULT);
}
StringBuffer_Clear(&buffer);
cxBuffer_Clear(&buffer);
} else {
if (var->isArray) {
status = OCIBindByPos(var->boundCursorHandle, &var->bindHandle,
@ -1092,22 +1093,15 @@ static int Variable_InternalBind(
"Variable_InternalBind()") < 0)
return -1;
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
// set the charset form and id if applicable
if (var->type->charsetForm != SQLCS_IMPLICIT) {
ub2 charsetId = OCI_UTF16ID;
status = OCIAttrSet(var->bindHandle, OCI_HTYPE_BIND,
(dvoid*) &var->type->charsetForm, 0, OCI_ATTR_CHARSET_FORM,
var->environment->errorHandle);
if (Environment_CheckForError(var->environment, status,
"Variable_InternalBind(): set charset form") < 0)
return -1;
status = OCIAttrSet(var->bindHandle, OCI_HTYPE_BIND,
(dvoid*) &charsetId, 0, OCI_ATTR_CHARSET_ID,
var->environment->errorHandle);
if (Environment_CheckForError(var->environment, status,
"Variable_InternalBind(): setting charset Id") < 0)
return -1;
status = OCIAttrSet(var->bindHandle, OCI_HTYPE_BIND,
(dvoid*) &var->bufferSize, 0, OCI_ATTR_MAXDATA_SIZE,
var->environment->errorHandle);
@ -1150,14 +1144,6 @@ static int Variable_Bind(
var->boundPos = pos;
var->boundCursorHandle = cursor->handle;
Py_XDECREF(var->boundName);
#if defined(WITH_UNICODE) && PY_MAJOR_VERSION < 3
if (name && PyBytes_Check(name)) {
var->boundName = PyObject_Unicode(name);
if (!var->boundName)
return -1;
return Variable_InternalBind(var);
}
#endif
Py_XINCREF(name);
var->boundName = name;

View File

@ -58,17 +58,57 @@ typedef int Py_ssize_t;
#define PyInt_Type PyLong_Type
#endif
// use the bytes methods in cx_Oracle and define them as the equivalent string
// type methods as is done in Python 2.6
#ifndef PyBytes_Check
#define PyBytes_Type PyString_Type
#define PyBytes_AS_STRING PyString_AS_STRING
#define PyBytes_GET_SIZE PyString_GET_SIZE
#define PyBytes_Check PyString_Check
#define PyBytes_Format PyString_Format
#define PyBytes_FromString PyString_FromString
#define PyBytes_FromStringAndSize PyString_FromStringAndSize
#endif
// define types and methods for strings and binary data
#if PY_MAJOR_VERSION >= 3
#define cxBinary_Type PyBytes_Type
#define cxBinary_Check PyBytes_Check
#define cxString_Type &PyUnicode_Type
#define cxString_Format PyUnicode_Format
#define cxString_Check PyUnicode_Check
#define cxString_GetSize PyUnicode_GET_SIZE
#else
#define cxBinary_Type PyBuffer_Type
#define cxBinary_Check PyBuffer_Check
#define cxString_Type &PyBytes_Type
#define cxString_Format PyBytes_Format
#define cxString_Check PyBytes_Check
#define cxString_GetSize PyBytes_GET_SIZE
#endif
// define string type and methods
#if PY_MAJOR_VERSION >= 3
#define cxString_FromAscii(str) \
PyUnicode_DecodeASCII(str, strlen(str), NULL)
#define cxString_FromEncodedString(buffer, numBytes, encoding) \
PyUnicode_Decode(buffer, numBytes, encoding, NULL)
#else
#define cxString_FromAscii(str) \
PyBytes_FromString(str)
#define cxString_FromEncodedString(buffer, numBytes, encoding) \
PyBytes_FromStringAndSize(buffer, numBytes)
#endif
// define base exception
#if PY_MAJOR_VERSION >= 3
#define CXORA_BASE_EXCEPTION NULL
#define CXORA_TYPE_ERROR "expecting string or bytes object"
#else
#define CXORA_BASE_EXCEPTION PyExc_StandardError
#define CXORA_TYPE_ERROR "expecting string, unicode or buffer object"
#endif
// define simple construct for determining endianness of the platform
// Oracle uses native encoding with OCI_UTF16 but bails when a BOM is written
#define IS_LITTLE_ENDIAN (int)*(unsigned char*) &one
// define macro for adding OCI constants
#define ADD_OCI_CONSTANT(x) \
if (PyModule_AddIntConstant(module, #x, OCI_ ##x) < 0) \
@ -94,7 +134,7 @@ typedef int Py_ssize_t;
#define BUILD_VERSION_STRING xstr(BUILD_VERSION)
#define DRIVER_NAME "cx_Oracle-"BUILD_VERSION_STRING
#include "StringUtils.c"
#include "Buffer.c"
//-----------------------------------------------------------------------------
// Globals
@ -114,12 +154,6 @@ static PyObject *g_ProgrammingErrorException = NULL;
static PyObject *g_NotSupportedErrorException = NULL;
static PyTypeObject *g_DateTimeType = NULL;
static PyTypeObject *g_DecimalType = NULL;
static PyObject *g_ShortNumberToStringFormatObj = NULL;
static udt_StringBuffer g_ShortNumberToStringFormatBuffer;
static PyObject *g_NumberToStringFormatObj = NULL;
static udt_StringBuffer g_NumberToStringFormatBuffer;
static PyObject *g_NlsNumericCharactersObj = NULL;
static udt_StringBuffer g_NlsNumericCharactersBuffer;
//-----------------------------------------------------------------------------
@ -324,28 +358,6 @@ static PyObject *Module_Initialize(void)
if (!g_DecimalType)
return NULL;
// set up the string and buffer for converting numbers to strings
g_ShortNumberToStringFormatObj = cxString_FromAscii("TM9");
if (!g_ShortNumberToStringFormatObj)
return NULL;
if (StringBuffer_Fill(&g_ShortNumberToStringFormatBuffer,
g_ShortNumberToStringFormatObj) < 0)
return NULL;
g_NumberToStringFormatObj = cxString_FromAscii(
"999999999999999999999999999999999999999999999999999999999999999");
if (!g_NumberToStringFormatObj)
return NULL;
if (StringBuffer_Fill(&g_NumberToStringFormatBuffer,
g_NumberToStringFormatObj) < 0)
return NULL;
g_NlsNumericCharactersObj = cxString_FromAscii(
"NLS_NUMERIC_CHARACTERS='.,'");
if (!g_NlsNumericCharactersObj)
return NULL;
if (StringBuffer_Fill(&g_NlsNumericCharactersBuffer,
g_NlsNumericCharactersObj) < 0)
return NULL;
// prepare the types for use by the module
MAKE_TYPE_READY(&g_ConnectionType);
MAKE_TYPE_READY(&g_CursorType);
@ -376,7 +388,7 @@ static PyObject *Module_Initialize(void)
MAKE_VARIABLE_TYPE_READY(&g_BFILEVarType);
MAKE_VARIABLE_TYPE_READY(&g_CursorVarType);
MAKE_VARIABLE_TYPE_READY(&g_ObjectVarType);
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
MAKE_VARIABLE_TYPE_READY(&g_UnicodeVarType);
MAKE_VARIABLE_TYPE_READY(&g_FixedUnicodeVarType);
#endif
@ -448,7 +460,7 @@ static PyObject *Module_Initialize(void)
ADD_TYPE_OBJECT("OBJECT", &g_ObjectVarType)
ADD_TYPE_OBJECT("DATETIME", &g_DateTimeVarType)
ADD_TYPE_OBJECT("FIXED_CHAR", &g_FixedCharVarType)
#ifndef WITH_UNICODE
#if PY_MAJOR_VERSION < 3
ADD_TYPE_OBJECT("FIXED_UNICODE", &g_FixedUnicodeVarType)
ADD_TYPE_OBJECT("UNICODE", &g_UnicodeVarType)
#endif

View File

@ -39,9 +39,9 @@ copyright = '2010, Anthony Tuininga'
# other places throughout the built documents.
#
# The short X.Y version.
version = '5.0'
version = '5.1'
# The full version, including alpha/beta/rc tags.
release = '5.0.4'
release = '5.1'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:

View File

@ -12,38 +12,33 @@ pythonVersions = os.environ["CX_ORACLE_PYTHON_VERSIONS"].split(",")
pythonFormat = os.environ["CX_ORACLE_PYTHON_FORMAT"]
origPath = os.environ["PATH"]
for withUnicode in (False, True):
if withUnicode:
os.environ["WITH_UNICODE"] = "1"
for version in pythonVersions:
majorVersion, minorVersion = [int(s) for s in version.split(".")]
if withUnicode and majorVersion >= 3:
continue
for oracleHome in oracleHomes:
if sys.platform == "win32":
os.environ["PATH"] = oracleHome + os.pathsep + origPath
for version in pythonVersions:
majorVersion, minorVersion = [int(s) for s in version.split(".")]
for oracleHome in oracleHomes:
if sys.platform == "win32":
os.environ["PATH"] = oracleHome + os.pathsep + origPath
else:
os.environ["ORACLE_HOME"] = oracleHome
python = pythonFormat % (majorVersion, minorVersion)
if testMode:
subCommand = "test"
subCommandArgs = ""
elif sys.platform == "win32":
subCommandArgs = ""
if majorVersion == 2 and minorVersion == 4:
subCommand = "bdist_wininst"
else:
os.environ["ORACLE_HOME"] = oracleHome
python = pythonFormat % (majorVersion, minorVersion)
if testMode:
subCommand = "test"
subCommandArgs = ""
elif sys.platform == "win32":
subCommandArgs = ""
if majorVersion == 2 and minorVersion == 4:
subCommand = "bdist_wininst"
else:
subCommand = "bdist_msi"
else:
subCommand = "bdist_rpm"
subCommandArgs = "--no-autoreq --python %s" % python
command = "%s setup.py %s %s" % \
(python, subCommand, subCommandArgs)
messageFragment = "%s for Python %s.%s in home %s" % \
(subCommand, majorVersion, minorVersion, oracleHome)
sys.stdout.write("Executing %s.\n" % messageFragment)
sys.stdout.write("Running command %s\n" % command)
if os.system(command) != 0:
msg = "Stopping. execution of %s failed.\n" % messageFragment
sys.exit(msg)
subCommand = "bdist_msi"
else:
subCommand = "bdist_rpm"
subCommandArgs = "--no-autoreq --python %s" % python
command = "%s setup.py %s %s" % \
(python, subCommand, subCommandArgs)
messageFragment = "%s for Python %s.%s in home %s" % \
(subCommand, majorVersion, minorVersion, oracleHome)
sys.stdout.write("Executing %s.\n" % messageFragment)
sys.stdout.write("Running command %s\n" % command)
if os.system(command) != 0:
msg = "Stopping. execution of %s failed.\n" % messageFragment
sys.exit(msg)

View File

@ -37,7 +37,7 @@ except:
from distutils.extension import Extension
# define build constants
BUILD_VERSION = "5.0.4"
BUILD_VERSION = "5.1"
# define the list of files to be included as documentation for Windows
dataFiles = None
@ -203,9 +203,6 @@ elif sys.platform == "cygwin":
extraLinkArgs.append("-Wl,--enable-runtime-pseudo-reloc")
elif sys.platform == "darwin":
extraLinkArgs.append("-shared-libgcc")
withUnicode = sys.version_info[0] < 3 and "WITH_UNICODE" in os.environ
if withUnicode or sys.version_info[0] >= 3:
extraCompileArgs.append("-DWITH_UNICODE")
# force the inclusion of an RPATH linker directive if desired; this will
# eliminate the need for setting LD_LIBRARY_PATH but it also means that this
@ -218,10 +215,7 @@ class Distribution(distutils.dist.Distribution):
def get_fullname_with_oracle_version(self):
name = self.metadata.get_fullname()
fullName = "%s-%s" % (name, oracleVersion)
if withUnicode:
fullName += "-unicode"
return fullName
return "%s-%s" % (name, oracleVersion)
# tweak the RPM build command to include the Python and Oracle version
@ -237,8 +231,6 @@ class bdist_rpm(distutils.command.bdist_rpm.bdist_rpm):
parts = origFileName.split("-")
parts.insert(2, oracleVersion)
parts.insert(3, "py%s%s" % sys.version_info[:2])
if withUnicode:
parts.insert(3, "unicode")
newFileName = "-".join(parts)
self.move_file(os.path.join("dist", origFileName),
os.path.join("dist", newFileName))
@ -248,15 +240,12 @@ class bdist_rpm(distutils.command.bdist_rpm.bdist_rpm):
class build(distutils.command.build.build):
def finalize_options(self):
global withUnicode
import distutils.util
import os
import sys
platSpecifier = ".%s-%s-%s" % \
(distutils.util.get_platform(), sys.version[0:3],
oracleVersion)
if withUnicode:
platSpecifier += "-unicode"
if self.build_platlib is None:
self.build_platlib = os.path.join(self.build_base,
"lib%s" % platSpecifier)
@ -338,11 +327,11 @@ extension = Extension(
extra_compile_args = extraCompileArgs,
extra_link_args = extraLinkArgs,
sources = ["cx_Oracle.c"],
depends = ["Callback.c", "Connection.c", "Cursor.c", "CursorVar.c",
"DateTimeVar.c", "Environment.c", "Error.c",
depends = ["Buffer.c", "Callback.c", "Connection.c", "Cursor.c",
"CursorVar.c", "DateTimeVar.c", "Environment.c", "Error.c",
"ExternalLobVar.c", "ExternalObjectVar.c", "IntervalVar.c",
"LobVar.c", "LongVar.c", "NumberVar.c", "ObjectType.c",
"ObjectVar.c", "SessionPool.c", "StringUtils.c", "StringVar.c",
"ObjectVar.c", "SessionPool.c", "StringVar.c",
"Subscription.c", "TimestampVar.c", "Transforms.c",
"Variable.c"])

View File

@ -14,36 +14,33 @@ inSetup = (os.path.basename(sys.argv[0]).lower() == "setup.py")
if len(sys.argv) > 1 and not inSetup:
moduleNames = [os.path.splitext(v)[0] for v in sys.argv[1:]]
elif hasattr(cx_Oracle, "UNICODE"):
moduleNames = [
"Connection",
"Cursor",
"CursorVar",
"DateTimeVar",
"IntervalVar",
"LobVar",
"LongVar",
"NumberVar",
"ObjectVar",
"SessionPool",
"StringVar",
"TimestampVar",
"UnicodeVar"
]
else:
moduleNames = [
"Connection",
"uConnection",
"Cursor",
"uCursor",
"CursorVar",
"uCursorVar",
"DateTimeVar",
"uDateTimeVar",
"IntervalVar",
"uIntervalVar",
"LobVar",
"uLobVar",
"LongVar",
"uLongVar",
"NumberVar",
"uNumberVar",
"ObjectVar",
"uObjectVar",
"SessionPool",
"uSessionPool",
"StringVar",
"uStringVar",
"uTimestampVar"
"TimestampVar",
"uTimestampVar",
"UnicodeVar"
]
class BaseTestCase(unittest.TestCase):

View File

@ -71,7 +71,7 @@ class TestConnection(TestCase):
"connection version is a string"
connection = cx_Oracle.connect(self.username, self.password,
self.tnsentry)
self.failUnless(isinstance(connection.version, unicode))
self.failUnless(isinstance(connection.version, str))
def testRollbackOnClose(self):
"connection rolls back before close"

View File

@ -80,14 +80,6 @@ class TestLongVar(BaseTestCase):
self.failUnlessEqual(longVar.size, 131072)
self.failUnlessEqual(longVar.bufferSize, 131076)
def testSetOutputSizesRightColumn(self):
"test setoutputsizes is valid (right column)"
self.cursor.setoutputsize(35000, 2)
self.cursor.execute(u"select * from TestLongs")
longVar = self.cursor.fetchvars[1]
self.failUnlessEqual(longVar.size, 35000)
self.failUnlessEqual(longVar.bufferSize, 70004)
def testArraySizeTooLarge(self):
"test array size too large generates an exception"
self.cursor.arraysize = 65536

View File

@ -46,26 +46,6 @@ class TestStringVar(BaseTestCase):
p_Value = u"String 6")
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[6]])
def testBindStringArrayDirect(self):
"test binding in a string array"
returnValue = self.cursor.var(cx_Oracle.NUMBER)
array = [r[1] for r in self.rawData]
statement = u"""
begin
:p_ReturnValue := pkg_TestStringArrays.TestInArrays(
:p_IntegerValue, :p_Array);
end;"""
self.cursor.execute(statement,
p_ReturnValue = returnValue,
p_IntegerValue = 5,
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 86)
array = [ u"String - %d" % i for i in range(15) ]
self.cursor.execute(statement,
p_IntegerValue = 8,
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 163)
def testBindStringArrayBySizes(self):
"test binding in a string array (with setinputsizes)"
returnValue = self.cursor.var(cx_Oracle.NUMBER)