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:
parent
9be85a356c
commit
04f1904a7d
|
@ -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)
|
||||
|
173
Connection.c
173
Connection.c
|
@ -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.
|
||||
|
|
57
Cursor.c
57
Cursor.c
|
@ -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
|
||||
|
|
130
Environment.c
130
Environment.c
|
@ -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
16
Error.c
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
36
LobVar.c
36
LobVar.c
|
@ -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;
|
||||
|
|
43
LongVar.c
43
LongVar.c
|
@ -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
|
||||
}
|
||||
|
||||
|
|
44
NumberVar.c
44
NumberVar.c
|
@ -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)
|
||||
|
|
16
ObjectType.c
16
ObjectType.c
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
170
StringUtils.c
170
StringUtils.c
|
@ -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
|
||||
|
159
StringVar.c
159
StringVar.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
58
Variable.c
58
Variable.c
|
@ -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;
|
||||
|
||||
|
|
82
cx_Oracle.c
82
cx_Oracle.c
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
61
release.py
61
release.py
|
@ -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)
|
||||
|
||||
|
|
21
setup.py
21
setup.py
|
@ -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"])
|
||||
|
||||
|
|
31
test/test.py
31
test/test.py
|
@ -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):
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue