Last public release from Computronix.

This commit is contained in:
Anthony Tuininga 2007-06-13 21:15:16 +00:00
commit 104e11b67a
67 changed files with 15931 additions and 0 deletions

328
Callback.c Normal file
View File

@ -0,0 +1,328 @@
//-----------------------------------------------------------------------------
// Callback.c
// Definition of OCI callback functions.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Callback_NewVariable()
// Return a new variable from a callback.
//-----------------------------------------------------------------------------
static udt_Variable *Callback_NewVariable(
udt_Connection *connection, // connection to use
ub2 oracleType, // Oracle type of data
ub4 maxLength, // maximum length of elements
void *data, // data pointer
void *indicator, // indicator pointer
ub2 *returnCode, // return code pointer
ub2 *actualLength) // actual length pointer
{
udt_VariableType *type;
udt_Variable *var;
// determine the type to use
type = Variable_TypeByOracleDataType(oracleType, SQLCS_IMPLICIT);
if (!type)
return NULL;
// attempt to allocate the object
var = PyObject_NEW(udt_Variable, type->pythonType);
if (!var)
return NULL;
// perform basic initialization
// note that the number of allocated elements is set arbitrarily high
// because the OCI doesn't give information about how many elements are
// actually allocated; that has to be implied by the number of rows
// passed to OCIStmtFetch and OCIStmtExecute
Py_INCREF(connection->environment);
var->environment = connection->environment;
var->boundCursorHandle = NULL;
var->bindHandle = NULL;
var->defineHandle = NULL;
var->boundName = NULL;
var->allocatedElements = 2147483647;
var->actualElements = 0;
var->isArray = 0;
var->isAllocatedInternally = 0;
var->type = type;
var->indicator = indicator;
var->data = data;
var->actualLength = actualLength;
var->returnCode = returnCode;
var->maxLength = type->elementLength;
if (type->isVariableLength)
var->maxLength = maxLength;
return var;
}
//-----------------------------------------------------------------------------
// Callback_BindByNameArgs()
// Return the arguments to be passed when OCIBindByName is called.
//-----------------------------------------------------------------------------
static PyObject *Callback_BindByNameArgs(
udt_Connection *connection, // connection to use
va_list args) // arguments to OCI function
{
ub4 nameLength, allocatedElements, *actualElements;
ub2 dataType, *actualLength, *returnCode;
dvoid *indicator, *value;
OCIBind **bindHandlePtr;
OCIError *errorHandle;
udt_Variable *var;
PyObject *result;
sb4 valueLength;
OCIStmt *handle;
text *name;
handle = va_arg(args, OCIStmt*);
bindHandlePtr = va_arg(args, OCIBind**);
errorHandle = va_arg(args, OCIError*);
name = va_arg(args, text*);
nameLength = va_arg(args, ub4);
value = va_arg(args, dvoid*);
valueLength = va_arg(args, sb4);
dataType = va_arg(args, int);
indicator = va_arg(args, dvoid*);
actualLength = va_arg(args, ub2*);
returnCode = va_arg(args, ub2*);
allocatedElements = va_arg(args, ub4);
actualElements = va_arg(args, ub4*);
var = Callback_NewVariable(connection, dataType, valueLength, value,
indicator, returnCode, actualLength);
if (!var)
return NULL;
if (allocatedElements > 0) {
var->isArray = 1;
var->actualElements = *actualElements;
}
result = Py_BuildValue("ls#O", handle, name, nameLength, var);
Py_DECREF(var);
return result;
}
//-----------------------------------------------------------------------------
// Callback_DefineByPosArgs()
// Return the arguments to be passed when OCIDefineByPos is called.
//-----------------------------------------------------------------------------
static PyObject *Callback_DefineByPosArgs(
udt_Connection *connection, // connection to use
va_list args) // arguments to OCI function
{
ub2 dataType, *actualLength, *returnCode;
OCIDefine **defineHandle;
dvoid *indicator, *value;
OCIError *errorHandle;
udt_Variable *var;
PyObject *result;
OCIStmt *handle;
sb4 valueLength;
ub4 position;
handle = va_arg(args, OCIStmt*);
defineHandle = va_arg(args, OCIDefine**);
errorHandle = va_arg(args, OCIError*);
position = va_arg(args, ub4);
value = va_arg(args, dvoid*);
valueLength = va_arg(args, sb4);
dataType = va_arg(args, int);
indicator = va_arg(args, dvoid*);
actualLength = va_arg(args, ub2*);
returnCode = va_arg(args, ub2*);
// create a variable
var = Callback_NewVariable(connection, dataType, valueLength, value,
indicator, returnCode, actualLength);
if (!var)
return NULL;
result = Py_BuildValue("liO", handle, position, var);
Py_DECREF(var);
return result;
}
//-----------------------------------------------------------------------------
// Callback_ExecuteArgs()
// Return the arguments to be passed when OCIStmtExecute is called.
//-----------------------------------------------------------------------------
static PyObject *Callback_ExecuteArgs(
va_list args) // arguments to OCI function
{
OCISvcCtx* serviceContextHandle;
OCIError *errorHandle;
ub4 iters, rowoff;
OCIStmt *handle;
serviceContextHandle = va_arg(args, OCISvcCtx*);
handle = va_arg(args, OCIStmt*);
errorHandle = va_arg(args, OCIError*);
iters = va_arg(args, ub4);
rowoff = va_arg(args, ub4);
return Py_BuildValue("lii", handle, iters, rowoff);
}
//-----------------------------------------------------------------------------
// Callback_FetchArgs()
// Return the arguments to be passed when OCIStmtFetch is called.
//-----------------------------------------------------------------------------
static PyObject *Callback_FetchArgs(
udt_Connection *connection, // connection to use
va_list args) // arguments to OCI function
{
ub4 numRows, rowCount;
OCIError *errorHandle;
OCIStmt *handle;
sword status;
handle = va_arg(args, OCIStmt*);
errorHandle = va_arg(args, OCIError*);
numRows = va_arg(args, ub4);
status = OCIAttrGet(handle, OCI_HTYPE_STMT, &rowCount, 0,
OCI_ATTR_ROW_COUNT, connection->environment->errorHandle);
if (Environment_CheckForError(connection->environment, status,
"Callback_FetchArgs()") < 0)
return NULL;
return Py_BuildValue("lii", handle, numRows, rowCount);
}
//-----------------------------------------------------------------------------
// Callback_PrepareArgs()
// Return the arguments to be passed when OCIStmtPrepare is called.
//-----------------------------------------------------------------------------
static PyObject *Callback_PrepareArgs(
va_list args) // arguments to OCI function
{
OCIError *errorHandle;
ub4 statementLength;
OCIStmt *handle;
text *statement;
handle = va_arg(args, OCIStmt*);
errorHandle = va_arg(args, OCIError*);
statement = va_arg(args, text *);
statementLength = va_arg(args, ub4);
return Py_BuildValue("ls#", handle, statement, statementLength);
}
//-----------------------------------------------------------------------------
// Callback_GetArgs()
// Return the arguments to be passed to the Python callback method.
//-----------------------------------------------------------------------------
static PyObject *Callback_GetArgs(
udt_Connection *connection, // connection to use
ub4 functionCode, // function code
va_list args) // OCI function arguments
{
switch (functionCode) {
case OCI_FNCODE_BINDBYNAME:
return Callback_BindByNameArgs(connection, args);
case OCI_FNCODE_DEFINEBYPOS:
return Callback_DefineByPosArgs(connection, args);
case OCI_FNCODE_STMTEXECUTE:
return Callback_ExecuteArgs(args);
case OCI_FNCODE_STMTFETCH:
return Callback_FetchArgs(connection, args);
case OCI_FNCODE_STMTPREPARE:
return Callback_PrepareArgs(args);
}
return PyTuple_New(0);
}
//-----------------------------------------------------------------------------
// Callback_Call()
// Actually make the call to the Python function.
//-----------------------------------------------------------------------------
static sword Callback_Call(
PyObject *tuple, // tuple containing connection/callback
ub4 functionCode, // function code
va_list args) // arguments
{
PyObject *callback, *callbackArgs, *result;
udt_Connection *connection;
// determine the connection and callback
connection = (udt_Connection*) PyTuple_GET_ITEM(tuple, 0);
callback = PyTuple_GET_ITEM(tuple, 1);
// determine the arguments to pass to the function
callbackArgs = Callback_GetArgs(connection, functionCode, args);
if (!callbackArgs)
return OCI_ERROR;
// actually make the call to the method
result = PyEval_CallObject(callback, callbackArgs);
Py_DECREF(callbackArgs);
if (!result)
return OCI_ERROR;
Py_DECREF(result);
return OCI_SUCCESS;
}
//-----------------------------------------------------------------------------
// Callback_Handler()
// Callback handler for calling Python code within an OCI callback.
//-----------------------------------------------------------------------------
static sword Callback_Handler(
PyObject *tuple, // tuple containing connection/callback
dvoid *handle, // pointer to handle
ub4 handleType, // handle type
ub4 functionCode, // function code
ub1 when, // when being called
sword returnCode, // return code
ub4 *errorCode, // error code (IN/OUT)
va_list args) // arguments
{
#ifdef WITH_THREAD
PyThreadState *threadState;
#endif
sword result;
// create new thread state, if necessary
#ifdef WITH_THREAD
threadState = PyThreadState_Swap(NULL);
if (threadState) {
PyThreadState_Swap(threadState);
threadState = NULL;
} else {
threadState = PyThreadState_New(g_InterpreterState);
if (!threadState) {
PyErr_Print();
return OCI_ERROR;
}
PyEval_AcquireThread(threadState);
}
#endif
// perform the call
result = Callback_Call(tuple, functionCode, args);
if (result != OCI_CONTINUE)
PyErr_Print();
// restore thread state, if necessary
#ifdef WITH_THREAD
if (threadState) {
PyThreadState_Clear(threadState);
PyEval_ReleaseThread(threadState);
PyThreadState_Delete(threadState);
}
#endif
return result;
}

1113
Connection.c Normal file

File diff suppressed because it is too large Load Diff

2001
Cursor.c Normal file

File diff suppressed because it is too large Load Diff

172
CursorVar.c Normal file
View File

@ -0,0 +1,172 @@
//-----------------------------------------------------------------------------
// CursorVar.c
// Defines the routines specific to the cursor type.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Cursor variable type
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
OCIStmt **data;
udt_Connection *connection;
PyObject *cursors;
} udt_CursorVar;
//-----------------------------------------------------------------------------
// Declaration of cursor variable functions.
//-----------------------------------------------------------------------------
static int CursorVar_Initialize(udt_CursorVar*, udt_Cursor*);
static void CursorVar_Finalize(udt_CursorVar*);
static int CursorVar_SetValue(udt_CursorVar*, unsigned, PyObject*);
static PyObject *CursorVar_GetValue(udt_CursorVar*, unsigned);
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
static PyTypeObject g_CursorVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.CURSOR", // tp_name
sizeof(udt_CursorVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
static udt_VariableType vt_Cursor = {
(InitializeProc) CursorVar_Initialize,
(FinalizeProc) CursorVar_Finalize,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) CursorVar_SetValue,
(GetValueProc) CursorVar_GetValue,
&g_CursorVarType, // Python type
SQLT_RSET, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCIStmt*), // element length
0, // is variable length
0, // can be copied
0 // can be in array
};
//-----------------------------------------------------------------------------
// CursorVar_Initialize()
// Initialize the variable.
//-----------------------------------------------------------------------------
static int CursorVar_Initialize(
udt_CursorVar *var, // variable to initialize
udt_Cursor *cursor) // cursor created by
{
udt_Cursor *tempCursor;
ub4 i;
Py_INCREF(cursor->connection);
var->connection = cursor->connection;
var->cursors = PyList_New(var->allocatedElements);
if (!var->cursors)
return -1;
for (i = 0; i < var->allocatedElements; i++) {
tempCursor = (udt_Cursor*) Connection_NewCursor(var->connection, NULL);
if (!tempCursor) {
Py_DECREF(var);
return -1;
}
PyList_SET_ITEM(var->cursors, i, (PyObject*) tempCursor);
if (Cursor_AllocateHandle(tempCursor) < 0) {
Py_DECREF(var);
return -1;
}
var->data[i] = tempCursor->handle;
}
return 0;
}
//-----------------------------------------------------------------------------
// CursorVar_Finalize()
// Prepare for variable destruction.
//-----------------------------------------------------------------------------
static void CursorVar_Finalize(
udt_CursorVar *var) // variable to free
{
Py_DECREF(var->connection);
Py_XDECREF(var->cursors);
}
//-----------------------------------------------------------------------------
// CursorVar_SetValue()
// Set the value of the variable.
//-----------------------------------------------------------------------------
static int CursorVar_SetValue(
udt_CursorVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
udt_Cursor *cursor;
if (!PyObject_IsInstance(value, (PyObject*) &g_CursorType)) {
PyErr_SetString(PyExc_TypeError, "expecting cursor");
return -1;
}
Py_XDECREF(PyList_GET_ITEM(var->cursors, pos));
Py_INCREF(value);
PyList_SET_ITEM(var->cursors, pos, value);
cursor = (udt_Cursor *) value;
#ifdef ORACLE_9I
if (!cursor->isOwned) {
if (Cursor_FreeHandle(cursor, 1) < 0)
return -1;
cursor->isOwned = 1;
if (Cursor_AllocateHandle(cursor) < 0)
return -1;
}
#endif
var->data[pos] = cursor->handle;
cursor->statementType = -1;
return 0;
}
//-----------------------------------------------------------------------------
// CursorVar_GetValue()
// Set the value of the variable.
//-----------------------------------------------------------------------------
static PyObject *CursorVar_GetValue(
udt_CursorVar *var, // variable to set value for
unsigned pos) // array position to set
{
PyObject *cursor;
cursor = PyList_GET_ITEM(var->cursors, pos);
((udt_Cursor*) cursor)->statementType = -1;
Py_INCREF(cursor);
return cursor;
}

222
DateTimeVar.c Normal file
View File

@ -0,0 +1,222 @@
//-----------------------------------------------------------------------------
// DateTimeVar.c
// Defines the routines for handling date (time) variables.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// DateTime type
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
OCIDate *data;
} udt_DateTimeVar;
//-----------------------------------------------------------------------------
// Declaration of date/time variable functions.
//-----------------------------------------------------------------------------
static int DateTimeVar_SetValue(udt_DateTimeVar*, unsigned, PyObject*);
static PyObject *DateTimeVar_GetValue(udt_DateTimeVar*, unsigned);
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
static PyTypeObject g_DateTimeVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.DATETIME", // tp_name
sizeof(udt_DateTimeVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
static udt_VariableType vt_DateTime = {
(InitializeProc) NULL,
(FinalizeProc) NULL,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) DateTimeVar_SetValue,
(GetValueProc) DateTimeVar_GetValue,
&g_DateTimeVarType, // Python type
SQLT_ODT, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCIDate), // element length (default)
0, // is variable length
1, // can be copied
1 // can be in array
};
#ifdef NATIVE_DATETIME
static udt_VariableType vt_Date = {
(InitializeProc) NULL,
(FinalizeProc) NULL,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) DateTimeVar_SetValue,
(GetValueProc) DateTimeVar_GetValue,
&g_DateTimeVarType, // Python type
SQLT_ODT, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCIDate), // element length (default)
0, // is variable length
1, // can be copied
1 // can be in array
};
//-----------------------------------------------------------------------------
// DateTimeVar_SetValue()
// Set the value of the variable.
//-----------------------------------------------------------------------------
static int DateTimeVar_SetValue(
udt_DateTimeVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
ub1 month, day, hour, minute, second;
short year;
if (PyDateTime_Check(value)) {
year = (short) PyDateTime_GET_YEAR(value);
month = PyDateTime_GET_MONTH(value);
day = PyDateTime_GET_DAY(value);
hour = PyDateTime_DATE_GET_HOUR(value);
minute = PyDateTime_DATE_GET_MINUTE(value);
second = PyDateTime_DATE_GET_SECOND(value);
} else if (PyDate_Check(value)) {
year = (short) PyDateTime_GET_YEAR(value);
month = PyDateTime_GET_MONTH(value);
day = PyDateTime_GET_DAY(value);
hour = minute = second = 0;
} else {
PyErr_SetString(PyExc_TypeError, "expecting date data");
return -1;
}
// store a copy of the value
OCIDateSetDate(&var->data[pos], year, month, day);
OCIDateSetTime(&var->data[pos], hour, minute, second);
return 0;
}
#else
//-----------------------------------------------------------------------------
// DateTimeVar_GetAttribute()
// Get the attribute from the object and convert it to an integer.
//-----------------------------------------------------------------------------
static int DateTimeVar_GetAttribute(
PyObject *value, // value to get attribute for
char *name, // name to acquire
unsigned *outputValue) // output value
{
PyObject *attrValue;
attrValue = PyObject_GetAttrString(value, name);
if (!attrValue)
return -1;
*outputValue = PyInt_AsLong(attrValue);
if (PyErr_Occurred())
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// DateTimeVar_SetValue()
// Set the value of the variable.
//-----------------------------------------------------------------------------
static int DateTimeVar_SetValue(
udt_DateTimeVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
unsigned year, month, day, hour, minute, second;
udt_ExternalDateTimeVar *dateValue;
sword status;
uword valid;
// handle internal cx_Oracle date type
if (value->ob_type == &g_ExternalDateTimeVarType) {
dateValue = (udt_ExternalDateTimeVar*) value;
year = dateValue->year;
month = dateValue->month;
day = dateValue->day;
hour = dateValue->hour;
minute = dateValue->minute;
second = dateValue->second;
// handle Python 2.3 datetime type
} else if (value->ob_type == g_DateTimeType) {
if (DateTimeVar_GetAttribute(value, "year", &year) < 0)
return -1;
if (DateTimeVar_GetAttribute(value, "month", &month) < 0)
return -1;
if (DateTimeVar_GetAttribute(value, "day", &day) < 0)
return -1;
if (DateTimeVar_GetAttribute(value, "hour", &hour) < 0)
return -1;
if (DateTimeVar_GetAttribute(value, "minute", &minute) < 0)
return -1;
if (DateTimeVar_GetAttribute(value, "second", &second) < 0)
return -1;
} else {
PyErr_SetString(PyExc_TypeError, "expecting date data");
return -1;
}
// store a copy of the value
OCIDateSetDate(&var->data[pos], (sb2) year, (ub1) month, (ub1) day);
OCIDateSetTime(&var->data[pos], (ub1) hour, (ub1) minute, (ub1) second);
status = OCIDateCheck(var->environment->errorHandle, &var->data[pos],
&valid);
if (Environment_CheckForError(var->environment, status,
"DateTimeVar_SetValue()") < 0)
return -1;
if (valid != 0) {
PyErr_Format(g_DataErrorException, "invalid date: %d/%d/%d %d:%d:%d",
year, month, day, hour, minute, second);
return -1;
}
return 0;
}
#endif
//-----------------------------------------------------------------------------
// DateTimeVar_GetValue()
// Returns the value stored at the given array position.
//-----------------------------------------------------------------------------
static PyObject *DateTimeVar_GetValue(
udt_DateTimeVar *var, // variable to determine value for
unsigned pos) // array position
{
return OracleDateToPythonDate(var->type, &var->data[pos]);
}

197
Environment.c Normal file
View File

@ -0,0 +1,197 @@
//-----------------------------------------------------------------------------
// Environment.c
// Environment handling.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// structure for the Python type
//-----------------------------------------------------------------------------
typedef struct {
PyObject_HEAD
OCIEnv *handle;
OCIError *errorHandle;
int maxBytesPerCharacter;
int fixedWidth;
ub4 maxStringBytes;
} udt_Environment;
//-----------------------------------------------------------------------------
// maximum number of characters applicable to strings
//-----------------------------------------------------------------------------
#define MAX_STRING_CHARS 4000
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
static void Environment_Free(udt_Environment*);
static int Environment_CheckForError(udt_Environment*, sword, const char*);
//-----------------------------------------------------------------------------
// declaration of Python type
//-----------------------------------------------------------------------------
static PyTypeObject g_EnvironmentType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"OracleEnvironment", // tp_name
sizeof(udt_Environment), // tp_basicsize
0, // tp_itemsize
(destructor) Environment_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
#include "Error.c"
//-----------------------------------------------------------------------------
// Environment_New()
// Create a new environment object.
//-----------------------------------------------------------------------------
static udt_Environment *Environment_New(
int threaded) // use threaded mode?
{
udt_Environment *environment;
sword status;
ub4 mode;
// create a new object for the Oracle environment
environment = PyObject_NEW(udt_Environment, &g_EnvironmentType);
if (!environment)
return NULL;
environment->handle = NULL;
environment->errorHandle = NULL;
environment->maxBytesPerCharacter = 1;
environment->fixedWidth = 1;
environment->maxStringBytes = MAX_STRING_CHARS;
// turn threading mode on, if desired
mode = OCI_OBJECT;
if (threaded)
mode |= OCI_THREADED;
// create the environment handle
status = OCIEnvCreate(&environment->handle, mode, NULL, NULL,
NULL, NULL, 0, NULL);
if (!environment->handle) {
Py_DECREF(environment);
PyErr_SetString(PyExc_RuntimeError,
"Unable to acquire Oracle environment handle");
return NULL;
}
if (Environment_CheckForError(environment, status,
"Environment_New(): create env handle") < 0) {
environment->handle = NULL;
Py_DECREF(environment);
return NULL;
}
// create the error handle
status = OCIHandleAlloc(environment->handle,
(dvoid**) &environment->errorHandle, OCI_HTYPE_ERROR, 0, 0);
if (Environment_CheckForError(environment, status,
"Environment_New(): create error handle") < 0) {
Py_DECREF(environment);
return NULL;
}
// acquire max bytes per character
#ifdef OCI_NLS_CHARSET_MAXBYTESZ
status = OCINlsNumericInfoGet(environment->handle,
environment->errorHandle, &environment->maxBytesPerCharacter,
OCI_NLS_CHARSET_MAXBYTESZ);
if (Environment_CheckForError(environment, status,
"Environment_New(): get max bytes per character") < 0) {
Py_DECREF(environment);
return NULL;
}
environment->maxStringBytes =
MAX_STRING_CHARS * environment->maxBytesPerCharacter;
// acquire whether character set is fixed width
status = OCINlsNumericInfoGet(environment->handle,
environment->errorHandle, &environment->fixedWidth,
OCI_NLS_CHARSET_FIXEDWIDTH);
if (Environment_CheckForError(environment, status,
"Environment_New(): determine if charset is fixed width") < 0) {
Py_DECREF(environment);
return NULL;
}
#endif
return environment;
}
//-----------------------------------------------------------------------------
// Environment_Free()
// Deallocate the environment. Note that destroying the environment handle
// will automatically destroy any child handles that were created.
//-----------------------------------------------------------------------------
static void Environment_Free(
udt_Environment *environment) // environment object
{
if (environment->handle)
OCIHandleFree(environment->handle, OCI_HTYPE_ENV);
PyObject_DEL(environment);
}
//-----------------------------------------------------------------------------
// Environment_RaiseError()
// Reads the error that was caused by the last Oracle statement and raise an
// exception for Python. At this point it is assumed that the Oracle
// environment is fully initialized.
//-----------------------------------------------------------------------------
static void Environment_RaiseError(
udt_Environment *environment, // environment to raise error for
const char *context) // context in which error occurred
{
PyObject *exceptionType;
udt_Error *error;
error = Error_New(environment, context);
if (error) {
if (error->errorNumber == 1 ||
(error->errorNumber >= 2290 && error->errorNumber <= 2292))
exceptionType = g_IntegrityErrorException;
else exceptionType = g_DatabaseErrorException;
PyErr_SetObject(exceptionType, (PyObject*) error);
Py_DECREF(error);
}
}
//-----------------------------------------------------------------------------
// Environment_CheckForError()
// Check for an error in the last call and if an error has occurred, raise a
// Python exception.
//-----------------------------------------------------------------------------
static int Environment_CheckForError(
udt_Environment *environment, // environment to raise error in
sword status, // status of last call
const char *context) // context
{
if (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO) {
if (status == OCI_INVALID_HANDLE)
PyErr_SetString(g_DatabaseErrorException, "Invalid handle!");
else Environment_RaiseError(environment, context);
return -1;
}
return 0;
}

129
Error.c Normal file
View File

@ -0,0 +1,129 @@
//-----------------------------------------------------------------------------
// Error.c
// Error handling.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// structure for the Python type
//-----------------------------------------------------------------------------
typedef struct {
PyObject_HEAD
sb4 errorNumber;
char errorText[1024];
const char *context;
} udt_Error;
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
static void Error_Free(udt_Error*);
static PyObject *Error_Str(udt_Error*);
//-----------------------------------------------------------------------------
// declaration of members
//-----------------------------------------------------------------------------
static PyMemberDef g_ErrorMembers[] = {
{ "code", T_INT, offsetof(udt_Error, errorNumber), READONLY },
{ "message", T_STRING_INPLACE, offsetof(udt_Error, errorText), READONLY },
{ "context", T_STRING, offsetof(udt_Error, context), READONLY },
{ NULL }
};
//-----------------------------------------------------------------------------
// declaration of Python type
//-----------------------------------------------------------------------------
static PyTypeObject g_ErrorType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle._Error", // tp_name
sizeof(udt_Error), // tp_basicsize
0, // tp_itemsize
(destructor) Error_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
(reprfunc) Error_Str, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0, // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
0, // tp_methods
g_ErrorMembers, // tp_members
0 // tp_getset
};
//-----------------------------------------------------------------------------
// Error_New()
// Create a new error object.
//-----------------------------------------------------------------------------
static udt_Error *Error_New(
udt_Environment *environment, // environment object
const char *context) // context in which error occurred
{
udt_Error *error;
ub4 handleType;
dvoid *handle;
sword status;
error = PyObject_NEW(udt_Error, &g_ErrorType);
if (!error)
return NULL;
error->context = context;
if (environment->errorHandle) {
handle = environment->errorHandle;
handleType = OCI_HTYPE_ERROR;
} else {
handle = environment->handle;
handleType = OCI_HTYPE_ENV;
}
status = OCIErrorGet(handle, 1, 0, &error->errorNumber,
(unsigned char*) error->errorText, sizeof(error->errorText),
handleType);
if (status != OCI_SUCCESS) {
Py_DECREF(error);
PyErr_SetString(g_InternalErrorException, "No Oracle error?");
return NULL;
}
return error;
}
//-----------------------------------------------------------------------------
// Error_Free()
// Deallocate the environment, disconnecting from the database if necessary.
//-----------------------------------------------------------------------------
static void Error_Free(
udt_Error *self) // error object
{
self->ob_type->tp_free((PyObject*) self);
}
//-----------------------------------------------------------------------------
// Error_Str()
// Return a string representation of the error variable.
//-----------------------------------------------------------------------------
static PyObject *Error_Str(
udt_Error *self) // variable to return the string for
{
return PyString_FromString(self->errorText);
}

239
ExternalDateTimeVar.c Normal file
View File

@ -0,0 +1,239 @@
//-----------------------------------------------------------------------------
// ExternalDateTimeVar.c
// Defines the routines for handling date variables external to this module.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// external date/time type
//-----------------------------------------------------------------------------
typedef struct {
PyObject_HEAD
unsigned year;
unsigned month;
unsigned day;
unsigned hour;
unsigned minute;
unsigned second;
unsigned fsecond;
} udt_ExternalDateTimeVar;
//-----------------------------------------------------------------------------
// Declaration of external date variable functions.
//-----------------------------------------------------------------------------
static void ExternalDateTimeVar_Free(udt_ExternalDateTimeVar*);
static PyObject *ExternalDateTimeVar_Str(udt_ExternalDateTimeVar*);
static int ExternalDateTimeVar_Cmp(udt_ExternalDateTimeVar*,
udt_ExternalDateTimeVar*);
static PyObject *ExternalDateTimeVar_New(PyTypeObject*, PyObject*, PyObject*);
static PyObject *ExternalDateTimeVar_Reduce(udt_ExternalDateTimeVar*);
//-----------------------------------------------------------------------------
// declaration of members for Python type
//-----------------------------------------------------------------------------
static PyMemberDef g_ExternalDateTimeVarMembers[] = {
{ "year", T_INT, offsetof(udt_ExternalDateTimeVar, year), READONLY },
{ "month", T_INT, offsetof(udt_ExternalDateTimeVar, month), READONLY },
{ "day", T_INT, offsetof(udt_ExternalDateTimeVar, day), READONLY },
{ "hour", T_INT, offsetof(udt_ExternalDateTimeVar, hour), READONLY },
{ "minute", T_INT, offsetof(udt_ExternalDateTimeVar, minute), READONLY },
{ "second", T_INT, offsetof(udt_ExternalDateTimeVar, second), READONLY },
{ "fsecond", T_INT, offsetof(udt_ExternalDateTimeVar, fsecond), READONLY },
{ NULL }
};
//-----------------------------------------------------------------------------
// declaration of methods for Python type
//-----------------------------------------------------------------------------
static PyMethodDef g_ExternalDateTimeVarMethods[] = {
{"__reduce__", (PyCFunction) ExternalDateTimeVar_Reduce, METH_NOARGS },
{ NULL, NULL }
};
//-----------------------------------------------------------------------------
// Python type declaration
//-----------------------------------------------------------------------------
static PyTypeObject g_ExternalDateTimeVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.Timestamp", // tp_name
sizeof(udt_ExternalDateTimeVar), // tp_basicsize
0, // tp_itemsize
(destructor) ExternalDateTimeVar_Free,
// tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
(cmpfunc) ExternalDateTimeVar_Cmp, // tp_compare
(reprfunc) ExternalDateTimeVar_Str, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
(reprfunc) ExternalDateTimeVar_Str, // tp_str
// tp_getattro
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
// tp_flags
0, // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
g_ExternalDateTimeVarMethods, // tp_methods
g_ExternalDateTimeVarMembers, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
0, // tp_alloc
ExternalDateTimeVar_New, // tp_new
0, // tp_free
0, // tp_is_gc
0 // tp_bases
};
//-----------------------------------------------------------------------------
// ExternalDateTimeVar_NewFromC()
// Create a new external date variable from C code.
//-----------------------------------------------------------------------------
PyObject *ExternalDateTimeVar_NewFromC(
PyTypeObject *type, // type of object
unsigned year, // year
unsigned month, // month
unsigned day, // day
unsigned hour, // hour
unsigned minute, // minute
unsigned second, // second
unsigned fsecond) // fractional seconds
{
udt_ExternalDateTimeVar *var;
var = (udt_ExternalDateTimeVar*) type->tp_alloc(type, 0);
if (var) {
var->year = year;
var->month = month;
var->day = day;
var->hour = hour;
var->minute = minute;
var->second = second;
var->fsecond = fsecond;
}
return (PyObject*) var;
}
//-----------------------------------------------------------------------------
// ExternalDateTimeVar_New()
// Create a new cursor object.
//-----------------------------------------------------------------------------
static PyObject *ExternalDateTimeVar_New(
PyTypeObject *type, // type object
PyObject *args, // arguments
PyObject *keywordArgs) // keyword arguments
{
unsigned year, month, day, hour, minute, second, fsecond;
hour = minute = second = fsecond = 0;
if (!PyArg_ParseTuple(args, "iii|iiii", &year, &month, &day, &hour,
&minute, &second, &fsecond))
return NULL;
return ExternalDateTimeVar_NewFromC(type, year, month, day, hour, minute,
second, fsecond);
}
//-----------------------------------------------------------------------------
// ExternalDateTimeVar_Reduce()
// Provide information for pickling and unpickling.
//-----------------------------------------------------------------------------
static PyObject* ExternalDateTimeVar_Reduce(
udt_ExternalDateTimeVar* self) // object to pickle
{
return Py_BuildValue("(O, (iiiiiii))", &g_ExternalDateTimeVarType,
self->year, self->month, self->day, self->hour, self->minute,
self->second, self->fsecond);
}
//-----------------------------------------------------------------------------
// ExternalDateTimeVar_Free()
// Free an external date variable.
//-----------------------------------------------------------------------------
static void ExternalDateTimeVar_Free(
udt_ExternalDateTimeVar *var) // variable to free
{
PyObject_DEL(var);
}
//-----------------------------------------------------------------------------
// ExternalDateTimeVar_Str()
// Return the string representation of the external date variable object.
//-----------------------------------------------------------------------------
static PyObject *ExternalDateTimeVar_Str(
udt_ExternalDateTimeVar *var) // external date variable object
{
char value[100];
sprintf(value, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d", var->year,
var->month, var->day, var->hour, var->minute, var->second);
if (var->fsecond > 0)
sprintf(value + strlen(value), ".%.6d", var->fsecond);
return PyString_FromString(value);
}
//-----------------------------------------------------------------------------
// ExternalDateTimeVar_Cmp()
// Return -1 if the second date is less than the first; 0 if the dates are
// the same and +1 if the second date is greater than the first.
//-----------------------------------------------------------------------------
static int ExternalDateTimeVar_Cmp(
udt_ExternalDateTimeVar *var1, // first date
udt_ExternalDateTimeVar *var2) // second date
{
if (var1->year < var2->year)
return -1;
if (var1->year > var2->year)
return 1;
if (var1->month < var2->month)
return -1;
if (var1->month > var2->month)
return 1;
if (var1->day < var2->day)
return -1;
if (var1->day > var2->day)
return 1;
if (var1->hour < var2->hour)
return -1;
if (var1->hour > var2->hour)
return 1;
if (var1->minute < var2->minute)
return -1;
if (var1->minute > var2->minute)
return 1;
if (var1->second < var2->second)
return -1;
if (var1->second > var2->second)
return 1;
if (var1->fsecond < var2->fsecond)
return -1;
if (var1->fsecond > var2->fsecond)
return 1;
return 0;
}

518
ExternalLobVar.c Normal file
View File

@ -0,0 +1,518 @@
//-----------------------------------------------------------------------------
// ExternalLobVar.c
// Defines the routines for handling LOB variables external to this module.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// external LOB type
//-----------------------------------------------------------------------------
typedef struct {
PyObject_HEAD
udt_LobVar *lobVar;
unsigned pos;
unsigned internalFetchNum;
} udt_ExternalLobVar;
//-----------------------------------------------------------------------------
// Declaration of external LOB variable functions.
//-----------------------------------------------------------------------------
static void ExternalLobVar_Free(udt_ExternalLobVar*);
static PyObject *ExternalLobVar_Str(udt_ExternalLobVar*);
static PyObject *ExternalLobVar_GetAttr(udt_ExternalLobVar*, PyObject*);
static PyObject *ExternalLobVar_Size(udt_ExternalLobVar*, PyObject*);
static PyObject *ExternalLobVar_Read(udt_ExternalLobVar*, PyObject*,
PyObject*);
static PyObject *ExternalLobVar_Write(udt_ExternalLobVar*, PyObject*,
PyObject*);
static PyObject *ExternalLobVar_Trim(udt_ExternalLobVar*, PyObject*,
PyObject*);
static PyObject *ExternalLobVar_GetFileName(udt_ExternalLobVar*, PyObject*);
static PyObject *ExternalLobVar_SetFileName(udt_ExternalLobVar*, PyObject*);
static PyObject *ExternalLobVar_FileExists(udt_ExternalLobVar*, PyObject*);
static PyObject *ExternalLobVar_Reduce(udt_ExternalLobVar*);
//-----------------------------------------------------------------------------
// Python type declaration
//-----------------------------------------------------------------------------
static PyTypeObject g_ExternalLobVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.LOB", // tp_name
sizeof(udt_ExternalLobVar), // tp_basicsize
0, // tp_itemsize
(destructor) ExternalLobVar_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
(reprfunc) ExternalLobVar_Str, // tp_str
(getattrofunc) ExternalLobVar_GetAttr,
// tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// declaration of methods for Python type "ExternalLOBVar"
//-----------------------------------------------------------------------------
static PyMethodDef g_ExternalLobVarMethods[] = {
{ "size", (PyCFunction) ExternalLobVar_Size, METH_NOARGS },
{ "read", (PyCFunction) ExternalLobVar_Read,
METH_VARARGS | METH_KEYWORDS },
{ "write", (PyCFunction) ExternalLobVar_Write,
METH_VARARGS | METH_KEYWORDS },
{ "trim", (PyCFunction) ExternalLobVar_Trim,
METH_VARARGS | METH_KEYWORDS },
{ "getfilename", (PyCFunction) ExternalLobVar_GetFileName, METH_NOARGS },
{ "setfilename", (PyCFunction) ExternalLobVar_SetFileName, METH_VARARGS },
{ "fileexists", (PyCFunction) ExternalLobVar_FileExists, METH_NOARGS },
{ "__reduce__", (PyCFunction) ExternalLobVar_Reduce, METH_NOARGS },
{ NULL, NULL }
};
//-----------------------------------------------------------------------------
// ExternalLobVar_New()
// Create a new external LOB variable.
//-----------------------------------------------------------------------------
PyObject *ExternalLobVar_New(
udt_LobVar *var, // variable to encapsulate
unsigned pos) // position in array to encapsulate
{
udt_ExternalLobVar *newVar;
newVar = PyObject_NEW(udt_ExternalLobVar, &g_ExternalLobVarType);
if (!newVar)
return NULL;
newVar->pos = pos;
newVar->internalFetchNum = var->internalFetchNum;
Py_INCREF(var);
newVar->lobVar = var;
return (PyObject*) newVar;
}
//-----------------------------------------------------------------------------
// ExternalLobVar_Free()
// Free an external LOB variable.
//-----------------------------------------------------------------------------
static void ExternalLobVar_Free(
udt_ExternalLobVar *var) // variable to free
{
Py_DECREF(var->lobVar);
PyObject_DEL(var);
}
//-----------------------------------------------------------------------------
// ExternalLobVar_Verify()
// Verify that the external LOB var is still valid.
//-----------------------------------------------------------------------------
static int ExternalLobVar_Verify(
udt_ExternalLobVar *var) // variable to verify
{
if (var->internalFetchNum != var->lobVar->internalFetchNum) {
PyErr_SetString(g_ProgrammingErrorException,
"LOB variable no longer valid after subsequent fetch");
return -1;
}
return 0;
}
//-----------------------------------------------------------------------------
// ExternalLobVar_GetAttr()
// Retrieve an attribute on the external LOB variable object.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_GetAttr(
udt_ExternalLobVar *var, // cursor object
PyObject *name) // name of attribute
{
return Py_FindMethod(g_ExternalLobVarMethods, (PyObject*) var,
PyString_AS_STRING(name));
}
//-----------------------------------------------------------------------------
// ExternalLobVar_InternalRead()
// Return the size of the LOB variable for internal comsumption.
//-----------------------------------------------------------------------------
static int ExternalLobVar_InternalRead(
udt_ExternalLobVar *var, // variable to return the size of
char *buffer, // buffer in which to put data
ub4 bufferSize, // size of buffer
ub4 *length, // length of data (IN/OUT)
int offset) // offset
{
sword status;
if (var->lobVar->isFile) {
status = OCILobFileOpen(var->lobVar->connection->handle,
var->lobVar->environment->errorHandle,
var->lobVar->data[var->pos], OCI_FILE_READONLY);
if (Environment_CheckForError(var->lobVar->environment, status,
"ExternalLobVar_FileOpen()") < 0)
return -1;
}
status = OCILobRead(var->lobVar->connection->handle,
var->lobVar->environment->errorHandle,
var->lobVar->data[var->pos], length, offset, buffer,
bufferSize, NULL, NULL, 0, var->lobVar->type->charsetForm);
if (Environment_CheckForError(var->lobVar->environment, status,
"ExternalLobVar_LobRead()") < 0) {
OCILobFileClose(var->lobVar->connection->handle,
var->lobVar->environment->errorHandle,
var->lobVar->data[var->pos]);
return -1;
}
if (var->lobVar->isFile) {
status = OCILobFileClose(var->lobVar->connection->handle,
var->lobVar->environment->errorHandle,
var->lobVar->data[var->pos]);
if (Environment_CheckForError(var->lobVar->environment, status,
"ExternalLobVar_FileClose()") < 0)
return -1;
}
return 0;
}
//-----------------------------------------------------------------------------
// ExternalLobVar_InternalSize()
// Return the size of the LOB variable for internal comsumption.
//-----------------------------------------------------------------------------
static int ExternalLobVar_InternalSize(
udt_ExternalLobVar *var) // variable to return the size of
{
sword status;
ub4 length;
status = OCILobGetLength(var->lobVar->connection->handle,
var->lobVar->environment->errorHandle,
var->lobVar->data[var->pos], &length);
if (Environment_CheckForError(var->lobVar->environment, status,
"ExternalLobVar_InternalSize()") < 0)
return -1;
return length;
}
//-----------------------------------------------------------------------------
// ExternalLobVar_Value()
// Return a portion (or all) of the data in the external LOB variable.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_Value(
udt_ExternalLobVar *var, // variable to return the size of
int offset, // offset into LOB
int amount) // amount to read from LOB
{
ub4 length, bufferSize;
PyObject *result;
char *buffer;
// modify the arguments
if (offset < 0)
offset = 1;
if (amount < 0) {
amount = ExternalLobVar_InternalSize(var);
if (amount < 0)
return NULL;
amount = amount - offset + 1;
if (amount <= 0)
amount = 1;
}
length = amount;
bufferSize = amount * var->lobVar->environment->maxBytesPerCharacter;
// create a string for retrieving the value
buffer = (char*) PyMem_Malloc(bufferSize);
if (!buffer)
return PyErr_NoMemory();
if (ExternalLobVar_InternalRead(var, buffer, bufferSize, &length,
offset) < 0) {
PyMem_Free(buffer);
return NULL;
}
// return the result
if (var->lobVar->environment->fixedWidth)
length = length * var->lobVar->environment->maxBytesPerCharacter;
result = PyString_FromStringAndSize(buffer, length);
PyMem_Free(buffer);
return result;
}
//-----------------------------------------------------------------------------
// ExternalLobVar_Size()
// Return the size of the data in the LOB variable.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_Size(
udt_ExternalLobVar *var, // variable to return the size of
PyObject *args) // arguments
{
int length;
if (ExternalLobVar_Verify(var) < 0)
return NULL;
length = ExternalLobVar_InternalSize(var);
if (length < 0)
return NULL;
return PyInt_FromLong(length);
}
//-----------------------------------------------------------------------------
// ExternalLobVar_Read()
// Return a portion (or all) of the data in the external LOB variable.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_Read(
udt_ExternalLobVar *var, // variable to return the size of
PyObject *args, // arguments
PyObject *keywordArgs) // keyword arguments
{
static char *keywordList[] = { "offset", "amount", NULL };
int offset, amount;
// offset and amount are expected, both optional
offset = amount = -1;
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|ii", keywordList,
&offset, &amount))
return NULL;
if (ExternalLobVar_Verify(var) < 0)
return NULL;
return ExternalLobVar_Value(var, offset, amount);
}
//-----------------------------------------------------------------------------
// ExternalLobVar_Str()
// Return all of the data in the external LOB variable.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_Str(
udt_ExternalLobVar *var) // variable to return the string for
{
if (ExternalLobVar_Verify(var) < 0)
return NULL;
return ExternalLobVar_Value(var, 1, -1);
}
//-----------------------------------------------------------------------------
// ExternalLobVar_Write()
// Write a value to the LOB variable; return the number of bytes written.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_Write(
udt_ExternalLobVar *var, // variable to perform write against
PyObject *args, // arguments
PyObject *keywordArgs) // keyword arguments
{
static char *keywordList[] = { "data", "offset", NULL };
int offset, bufferLength, length;
char *buffer;
sword status;
// buffer and offset are expected, offset is optional
offset = -1;
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "s#|i", keywordList,
&buffer, &bufferLength, &offset))
return NULL;
if (offset < 0)
offset = 1;
// create a string for retrieving the value
if (ExternalLobVar_Verify(var) < 0)
return NULL;
length = bufferLength;
status = OCILobWrite(var->lobVar->connection->handle,
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
(unsigned int*) &length, offset, buffer, bufferLength,
OCI_ONE_PIECE, NULL, NULL, 0, var->lobVar->type->charsetForm);
if (Environment_CheckForError(var->lobVar->environment, status,
"ExternalLobVar_Write()") < 0)
return NULL;
// return the result
return PyInt_FromLong(length);
}
//-----------------------------------------------------------------------------
// ExternalLobVar_Trim()
// Trim the LOB variable to the specified length.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_Trim(
udt_ExternalLobVar *var, // variable to perform write against
PyObject *args, // arguments
PyObject *keywordArgs) // keyword arguments
{
static char *keywordList[] = { "newSize", NULL };
sword status;
ub4 newSize;
// buffer and offset are expected, offset is optional
newSize = 0;
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|i", keywordList,
&newSize))
return NULL;
// create a string for retrieving the value
if (ExternalLobVar_Verify(var) < 0)
return NULL;
status = OCILobTrim(var->lobVar->connection->handle,
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
newSize);
if (Environment_CheckForError(var->lobVar->environment, status,
"ExternalLobVar_Trim()") < 0)
return NULL;
// return the result
Py_INCREF(Py_None);
return Py_None;
}
//-----------------------------------------------------------------------------
// ExternalLobVar_Reduce()
// Method provided for pickling/unpickling of LOB variables.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_Reduce(
udt_ExternalLobVar *self) // variable to dump
{
PyObject *result, *value;
value = ExternalLobVar_Str(self);
if (!value)
return NULL;
result = Py_BuildValue("(O(O))", &PyString_Type, value);
Py_DECREF(value);
return result;
}
//-----------------------------------------------------------------------------
// ExternalLobVar_GetFileName()
// Return the directory alias and file name for the BFILE lob.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_GetFileName(
udt_ExternalLobVar *var, // variable to perform write against
PyObject *args) // arguments
{
char dirAlias[30], name[255];
ub2 dirAliasLength, nameLength;
PyObject *result, *temp;
sword status;
// determine the directory alias and name
if (ExternalLobVar_Verify(var) < 0)
return NULL;
dirAliasLength = sizeof(dirAlias);
nameLength = sizeof(name);
status = OCILobFileGetName(var->lobVar->environment->handle,
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
(text*) dirAlias, &dirAliasLength, (text*) name, &nameLength);
if (Environment_CheckForError(var->lobVar->environment, status,
"ExternalLobVar_GetFileName()") < 0)
return NULL;
// create the two-tuple for returning
result = PyTuple_New(2);
if (!result)
return NULL;
temp = PyString_FromStringAndSize(dirAlias, dirAliasLength);
if (!temp) {
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, temp);
temp = PyString_FromStringAndSize(name, nameLength);
if (!temp) {
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 1, temp);
return result;
}
//-----------------------------------------------------------------------------
// ExternalLobVar_SetFileName()
// Set the directory alias and file name for the BFILE lob.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_SetFileName(
udt_ExternalLobVar *var, // variable to perform write against
PyObject *args) // arguments
{
int dirAliasLength, nameLength;
char *dirAlias, *name;
sword status;
// get the directory alias and name as strings
if (!PyArg_ParseTuple(args, "s#s#", &dirAlias, &dirAliasLength, &name,
&nameLength))
return NULL;
// create a string for retrieving the value
if (ExternalLobVar_Verify(var) < 0)
return NULL;
status = OCILobFileSetName(var->lobVar->environment->handle,
var->lobVar->environment->errorHandle,
&var->lobVar->data[var->pos], (text*) dirAlias,
(ub2) dirAliasLength, (text*) name, (ub2) nameLength);
if (Environment_CheckForError(var->lobVar->environment, status,
"ExternalLobVar_SetFileName()") < 0)
return NULL;
// return the result
Py_INCREF(Py_None);
return Py_None;
}
//-----------------------------------------------------------------------------
// ExternalLobVar_FileExists()
// Return a boolean indicating if the BFIILE lob exists.
//-----------------------------------------------------------------------------
static PyObject *ExternalLobVar_FileExists(
udt_ExternalLobVar *var, // variable to perform write against
PyObject *args) // arguments
{
PyObject *result;
sword status;
boolean flag;
if (ExternalLobVar_Verify(var) < 0)
return NULL;
status = OCILobFileExists(var->lobVar->connection->handle,
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
&flag);
if (Environment_CheckForError(var->lobVar->environment, status,
"ExternalLobVar_FileExists()") < 0)
return NULL;
// return the result
if (flag)
result = Py_True;
else result = Py_False;
Py_INCREF(result);
return result;
}

286
ExternalObjectVar.c Normal file
View File

@ -0,0 +1,286 @@
//-----------------------------------------------------------------------------
// ExternalObjectVar.c
// Defines the routines for handling object variables external to this
// module.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// external Object type
//-----------------------------------------------------------------------------
typedef struct {
PyObject_HEAD
PyObject *referencedObject;
udt_ObjectType *objectType;
dvoid *instance;
dvoid *indicator;
int isIndependent;
} udt_ExternalObjectVar;
//-----------------------------------------------------------------------------
// Declaration of external object variable functions.
//-----------------------------------------------------------------------------
static void ExternalObjectVar_Free(udt_ExternalObjectVar*);
static PyObject *ExternalObjectVar_GetAttr(udt_ExternalObjectVar*, PyObject*);
static PyObject *ExternalObjectVar_ConvertToPython(udt_Environment*,
OCITypeCode, dvoid*, dvoid*, PyObject*, udt_ObjectType*);
//-----------------------------------------------------------------------------
// Python type declaration
//-----------------------------------------------------------------------------
static PyTypeObject g_ExternalObjectVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.OBJECT", // tp_name
sizeof(udt_ExternalObjectVar), // tp_basicsize
0, // tp_itemsize
(destructor) ExternalObjectVar_Free,
// tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) ExternalObjectVar_GetAttr,
// tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// ExternalObjectVar_New()
// Create a new external LOB variable.
//-----------------------------------------------------------------------------
PyObject *ExternalObjectVar_New(
PyObject *referencedObject, // referenced object
udt_ObjectType *objectType, // type of object
dvoid *instance, // object instance data
dvoid *indicator, // indicator structure
int isIndependent) // is object independent?
{
udt_ExternalObjectVar *newVar;
newVar = PyObject_NEW(udt_ExternalObjectVar, &g_ExternalObjectVarType);
if (!newVar)
return NULL;
Py_INCREF(referencedObject);
newVar->referencedObject = referencedObject;
Py_INCREF(objectType);
newVar->objectType = objectType;
newVar->instance = instance;
newVar->indicator = indicator;
newVar->isIndependent = isIndependent;
return (PyObject*) newVar;
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_Free()
// Free an external LOB variable.
//-----------------------------------------------------------------------------
static void ExternalObjectVar_Free(
udt_ExternalObjectVar *self) // variable to free
{
if (self->isIndependent)
OCIObjectFree(self->objectType->environment->handle,
self->objectType->environment->errorHandle,
self->instance, OCI_OBJECTFREE_FORCE);
Py_DECREF(self->objectType);
Py_DECREF(self->referencedObject);
PyObject_DEL(self);
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_ConvertCollectionElements()
// Convert the collection elements to Python values.
//-----------------------------------------------------------------------------
static int ExternalObjectVar_ConvertCollectionElements(
udt_Environment *environment, // environment to use
OCIIter *iter, // iterator
PyObject *list, // list result
PyObject *referencedObject, // referenced object
udt_ObjectType *objectType) // collection type information
{
dvoid *elementValue, *elementIndicator;
PyObject *elementObject;
boolean endOfCollection;
sword status;
while (list) {
status = OCIIterNext(environment->handle, environment->errorHandle,
iter, &elementValue, &elementIndicator, &endOfCollection);
if (Environment_CheckForError(environment, status,
"ExternalObjectVar_ConvertCollection(): get next") < 0)
return -1;
if (endOfCollection)
break;
elementObject = ExternalObjectVar_ConvertToPython(environment,
objectType->elementTypeCode, elementValue, elementIndicator,
referencedObject, (udt_ObjectType*) objectType->elementType);
if (!elementObject)
return -1;
if (PyList_Append(list, elementObject) < 0) {
Py_DECREF(elementObject);
return -1;
}
Py_DECREF(elementObject);
}
return 0;
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_ConvertCollection()
// Convert a collection to a Python list.
//-----------------------------------------------------------------------------
static PyObject *ExternalObjectVar_ConvertCollection(
udt_Environment *environment, // environment to use
OCIColl *collectionValue, // collection value
PyObject *referencedObject, // referenced object
udt_ObjectType *objectType) // collection type information
{
PyObject *list;
OCIIter *iter;
sword status;
int result;
// create the iterator
status = OCIIterCreate(environment->handle, environment->errorHandle,
collectionValue, &iter);
if (Environment_CheckForError(environment, status,
"ExternalObjectVar_ConvertCollection(): creating iterator") < 0)
return NULL;
// create the result list
list = PyList_New(0);
if (list) {
result = ExternalObjectVar_ConvertCollectionElements(environment, iter,
list, referencedObject, objectType);
if (result < 0) {
Py_DECREF(list);
list = NULL;
}
}
OCIIterDelete(environment->handle, environment->errorHandle, &iter);
return list;
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_ConvertToPython()
// Convert an Oracle value to a Python value.
//-----------------------------------------------------------------------------
static PyObject *ExternalObjectVar_ConvertToPython(
udt_Environment *environment, // environment to use
OCITypeCode typeCode, // type of Oracle data
dvoid *value, // Oracle value
dvoid *indicator, // null indicator
PyObject *referencedObject, // referenced object (for sub objects)
udt_ObjectType *subType) // sub type (for sub objects)
{
OraText *stringValue;
// null values returned as None
if (* (OCIInd*) indicator == OCI_IND_NULL) {
Py_INCREF(Py_None);
return Py_None;
}
switch (typeCode) {
case OCI_TYPECODE_VARCHAR2:
stringValue = OCIStringPtr(environment->handle,
* (OCIString**) value);
return PyString_FromString((char*) stringValue);
case OCI_TYPECODE_NUMBER:
return OracleNumberToPythonFloat(environment, (OCINumber*) value);
case OCI_TYPECODE_DATE:
return OracleDateToPythonDate(&vt_DateTime, (OCIDate*) value);
case OCI_TYPECODE_OBJECT:
return ExternalObjectVar_New(referencedObject, subType, value,
indicator, 0);
case OCI_TYPECODE_NAMEDCOLLECTION:
return ExternalObjectVar_ConvertCollection(environment,
* (OCIColl**) value, referencedObject, subType);
};
return PyErr_Format(g_NotSupportedErrorException,
"ExternalObjectVar_GetAttributeValue(): unhandled data type %d",
typeCode);
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_GetAttributeValue()
// Retrieve an attribute on the external LOB variable object.
//-----------------------------------------------------------------------------
static PyObject *ExternalObjectVar_GetAttributeValue(
udt_ExternalObjectVar *self, // object
udt_ObjectAttribute *attribute) // attribute to get
{
dvoid *valueIndicator, *value;
OCIInd scalarValueIndicator;
ub4 nameLength;
sword status;
OCIType *tdo;
char *name;
// get the value for the attribute
name = PyString_AS_STRING(attribute->name);
nameLength = PyString_GET_SIZE(attribute->name);
status = OCIObjectGetAttr(self->objectType->environment->handle,
self->objectType->environment->errorHandle, self->instance,
self->indicator, self->objectType->tdo, (const OraText**) &name,
&nameLength, 1, 0, 0, &scalarValueIndicator, &valueIndicator,
&value, &tdo);
if (Environment_CheckForError(self->objectType->environment, status,
"ExternalObjectVar_GetAttributeValue(): getting value") < 0)
return NULL;
// determine the proper null indicator
if (!valueIndicator)
valueIndicator = &scalarValueIndicator;
return ExternalObjectVar_ConvertToPython(self->objectType->environment,
attribute->typeCode, value, valueIndicator, (PyObject*) self,
attribute->subType);
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_GetAttr()
// Retrieve an attribute on the external LOB variable object.
//-----------------------------------------------------------------------------
static PyObject *ExternalObjectVar_GetAttr(
udt_ExternalObjectVar *self, // object
PyObject *nameObject) // name of attribute
{
udt_ObjectAttribute *attribute;
char *name;
attribute = (udt_ObjectAttribute*)
PyDict_GetItem(self->objectType->attributesByName, nameObject);
if (attribute)
return ExternalObjectVar_GetAttributeValue(self, attribute);
name = PyString_AS_STRING(nameObject);
if (name[0] == 't' && strcmp(name, "type") == 0) {
Py_INCREF(self->objectType);
return (PyObject*) self->objectType;
}
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
}

447
HISTORY.txt Normal file
View File

@ -0,0 +1,447 @@
Changes from 4.3 to 4.3.1
1) Ensure that if the client buffer size exceeds 4000 bytes that the server
buffer size does not as strings may only contain 4000 bytes; this allows
handling of multibyte character sets on the server as well as the client.
2) Added support for using buffer objects to populate binary data and made the
Binary() constructor the buffer type as requested by Ken Mason.
3) Fix potential crash when using full optimization with some compilers.
Thanks to Aris Motas for noticing this and providing the initial patch and
to Amaury Forgeot d'Arc for providing an even simpler solution.
4) Pass the correct charset form in to the write call in order to support
writing to national character set LOB values properly. Thanks to Ian Kelly
for noticing this discrepancy.
Changes from 4.2.1 to 4.3
1) Added preliminary support for fetching Oracle objects (SQL types) as
requested by Kristof Beyls (who kindly provided an initial patch).
Additional work needs to be done to support binding and updating objects
but the basic structure is now in place.
2) Added connection.maxBytesPerCharacter which indicates the maximum number of
bytes each character can use; use this value to also determine the size of
local buffers in order to handle discrepancies between the client character
set and the server character set. Thanks to Andreas Mock for providing the
initial patch and working with me to resolve this issue.
3) Added support for querying native floats in Oracle 10g as requested by
Danny Boxhoorn.
4) Add support for temporary LOB variables created via PL/SQL instead of only
directly by cx_Oracle; thanks to Henning von Bargen for discovering this
problem.
5) Added support for specifying variable types using the builtin types int,
float, str and datetime.date which allows for finer control of what type of
Python object is returned from cursor.callfunc() for example.
6) Added support for passing booleans to callproc() and callfunc() as
requested by Anana Aiyer.
7) Fixed support for 64-bit environments in Python 2.5.
8) Thanks to Filip Ballegeer and a number of his co-workers, an intermittent
crash was tracked down; specifically, if a connection is closed, then the
call to OCIStmtRelease() will free memory twice. Preventing the call when
the connection is closed solves the problem.
Changes from 4.2 to 4.2.1
1) Added additional type (NCLOB) to handle CLOBs that use the national
character set as requested by Chris Dunscombe.
2) Added support for returning cursors from functions as requested by Daniel
Steinmann.
3) Added support for getting/setting the "get" mode on session pools as
requested by Anand Aiyer.
4) Added support for binding subclassed cursors.
5) Fixed binding of decimal objects with absolute values less than 0.1.
Changes from 4.1.2 to 4.2
1) Added support for parsing an Oracle statement as requested by Patrick
Blackwill.
2) Added support for BFILEs at the request of Matthew Cahn.
3) Added support for binding decimal.Decimal objects to cursors.
4) Added support for reading from NCLOBs as requested by Chris Dunscombe.
5) Added connection attributes encoding and nencoding which return the IANA
character set name for the character set and national character set in use
by the client.
6) Rework module initialization to use the techniques recommended by the
Python documentation as one user was experiencing random segfaults due
to the use of the module dictionary after the initialization was complete.
7) Removed support for the OPT_Threading attribute. Use the threaded keyword
when creating connections and session pools instead.
8) Removed support for the OPT_NumbersAsStrings attribute. Use the
numbersAsStrings attribute on cursors instead.
9) Use type long rather than type int in order to support long integers on
64-bit machines as reported by Uwe Hoffmann.
10) Add cursor attribute "bindarraysize" which is defaulted to 1 and is used
to determine the size of the arrays created for bind variables.
11) Added repr() methods to provide something a little more useful than the
standard type name and memory address.
12) Added keyword argument support to the functions that imply such in the
documentation as requested by Harald Armin Massa.
13) Treat an empty dictionary passed through to cursor.execute() as keyword
arguments the same as if no keyword arguments were specified at all, as
requested by Fabien Grumelard.
14) Fixed memory leak when a LOB read would fail.
15) Set the LDFLAGS value in the environment rather than directly in the
setup.py file in order to satisfy those who wish to enable the use of
debugging symbols.
16) Use __DATE__ and __TIME__ to determine the date and time of the build
rather than passing it through directly.
17) Use Oracle types and add casts to reduce warnings as requested by Amaury
Forgeot d'Arc.
18) Fixed typo in error message.
Changes from 4.1.1 to 4.1.2
1) Restore support of Oracle 9i features when using the Oracle 10g client.
Changes from 4.1 to 4.1.1
1) Add support for dropping a connection from a session pool.
2) Add support for write only attributes "module", "action" and "clientinfo"
which work only in Oracle 10g as requested by Egor Starostin.
3) Add support for pickling database errors.
4) Use the previously created bind variable as a template if available when
creating a new variable of a larger size. Thanks to Ted Skolnick for the
initial patch.
5) Fixed tests to work properly in the Python 2.4 environment where dates and
timestamps are different Python types. Thanks to Henning von Bargen for
pointing this out.
6) Added additional directories to search for include files and libraries in
order to better support the Oracle 10g instant client.
7) Set the internal fetch number to 0 in order to satisfy very picky source
analysis tools as requested by Amaury Fogeot d'Arc.
8) Improve the documentation for building and installing the module from
source as some people are unaware of the standard methods for building
Python modules using distutils.
9) Added note in the documentation indicating that the arraysize attribute
can drastically affect performance of queries since this seems to be a
common misunderstanding of first time users of cx_Oracle.
10) Add a comment indicating that on HP-UX Itanium with Oracle 10g the library
ttsh10 must alos be linked against. Thanks to Bernard Delmee for the
information.
Changes from 4.1 beta 1 to 4.1
1) Fixed bug where subclasses of Cursor do not pass the connection in the
constructor causing a segfault.
2) DDL statements must be reparsed before execution as noted by Mihai
Ibanescu.
3) Add support for setting input sizes by position.
4) Fixed problem with catching an exception during execute and then still
attempting to perform a fetch afterwards as noted by Leith Parkin.
5) Rename the types so that they can be pickled and unpickled. Thanks to Harri
Pasanen for pointing out the problem.
6) Handle invalid NLS_LANG setting properly (Oracle seems to like to provide a
handle back even though it is invalid) and determine the number of bytes
per character in order to allow for proper support in the future of
multibyte and variable width character sets.
7) Remove date checking from the native case since Python already checks that
dates are valid; enhance error message when invalid dates are encountered
so that additional processing can be done.
8) Fix bug executing SQL using numeric parameter names with predefined
variables (such as what takes place when calling stored procedures with out
parameters).
9) Add support for reading CLOB values using multibyte or variable length
character sets.
Changes from 4.0.1 to 4.1 beta 1
1) Added support for Python 2.4. In Python 2.4, the datetime module is used
for both binding and fetching of date and timestamp data. In Python 2.3,
objects from the datetime module can be bound but the internal datetime
objects will be returned from queries.
2) Added pickling support for LOB and datetime data.
3) Fully qualified the table name that was missing in an alter table
statement in the setup test script as noted by Marc Gehling.
4) Added a section allowing for the setting of the RPATH linker directive in
setup.py as requested by Iustin Pop.
5) Added code to raise a programming error exception when an attempt is made
to access a LOB locator variable in a subsequent fetch.
6) The username, password and dsn (tnsentry) are stored on the connection
object when specified, regardless of whether or not a standard connection
takes place.
7) Added additional module level constant called "LOB" as requested by Joseph
Canedo.
8) Changed exception type to IntegrityError for constraint violations as
requested by Joseph Canedo.
9) If scale and precision are not specified, an attempt is made to return a
long integer as requested by Joseph Canedo.
10) Added workaround for Oracle bug which returns an invalid handle when the
prepare call fails. Thanks to alantam@hsbc.com for providing the code that
demonstrated the problem.
11) The cusor method arravar() will now accept the actual list so that it is
not necessary to call cursor.arrayvar() followed immediately by
var.setvalue().
12) Fixed bug where attempts to execute the statement "None" with bind
variables would cause a segmentation fault.
13) Added support for binding by position (paramstyle = "numeric").
14) Removed memory leak created by calls to OCIParamGet() which were not
mirrored by calls to OCIDescriptorFree(). Thanks to Mihai Ibanescu for
pointing this out and providing a patch.
15) Added support for calling cursor.executemany() with statement None
implying that the previously prepared statement ought to be executed.
Thanks to Mihai Ibanescu for providing a patch.
16) Added support for rebinding variables when a subsequent call to
cursor.executemany() uses a different number of rows. Thanks to Mihai
Ibanescu for supplying a patch.
17) The microseconds are now displayed in datetime variables when nonzero
similar to method used in the datetime module.
18) Added support for binary_float and binary_double columns in Oracle 10g.
Changes from 4.0 to 4.0.1
1) Fixed bugs on 64-bit platforms that caused segmentation faults and bus
errors in session pooling and determining the bind variables associated
with a statement.
2) Modified test suite so that 64-bit platforms are tested properly.
3) Added missing commit statements in the test setup scripts. Thanks to Keith
Lyon for pointing this out.
4) Fix setup.py for Cygwin environments. Thanks to Doug Henderson for
providing the necessary fix.
5) Added support for compiling cx_Oracle without thread support. Thanks to
Andre Reitz for pointing this out.
6) Added support for a new keyword parameter called threaded on connections
and session pools. This parameter defaults to False and indicates whether
threaded mode ought to be used. It replaces the module level attribute
OPT_Threading although examining the attribute will be retained until the
next release at least.
7) Added support for a new keyword parameter called twophase on connections.
This parameter defaults to False and indicates whether support for two
phase (distributed or global) transactions ought to be present. Note that
support for distributed transactions is buggy when crossing major version
boundaries (Oracle 8i to Oracle 9i for example).
8) Ensure that the rowcount attribute is set properly when an exception is
raised during execution. Thanks to Gary Aviv for pointing out this problem
and its solution.
Changes from 3.1 to 4.0
1) Added support for subclassing connections, cursors and session pools. The
changes involved made it necessary to drop support for Python 2.1 and
earlier although a branch exists in CVS to allow for support of Python 2.1
and earlier if needed.
2) Connections and session pools can now be created with keyword parameters,
not just sequential parameters.
3) Queries now return integers whenever possible and long integers if the
number will overflow a simple integer. Floats are only returned when it is
known that the number is a floating point number or the integer conversion
fails.
4) Added initial support for user callbacks on OCI functions. See the
documentation for more details.
5) Add support for retrieving the bind variable names associated with a
cursor with a new method bindnames().
6) Add support for temporary LOB variables. This means that setinputsizes()
can be used with the values CLOB and BLOB to create these temporary LOB
variables and allow for the equivalent of empty_clob() and empty_blob()
since otherwise Oracle will treat empty strings as NULL values.
7) Automatically switch to long strings when the data size exceeds the
maximum string size that Oracle allows (4000 characters) and raise an
error if an attempt is made to set a string variable to a size that it
does not support. This avoids truncation errors as reported by Jon Franz.
8) Add support for global (distributed) transactions and two phase commit.
9) Force the NLS settings for the session so that test tables are populated
correctly in all circumstances; problems were noted by Ralf Braun and
Allan Poulsen.
10) Display error messages using the environment handle when the error handle
has not yet been created; this provides better error messages during this
rather rare situation.
11) Removed memory leak in callproc() that was reported by Todd Whiteman.
12) Make consistent the calls to manipulate memory; otherwise segfaults can
occur when the pymalloc option is used, as reported by Matt Hoskins.
13) Force a rollback when a session is released back to the session pool.
Apparently the connections are not as stateless as Oracle's documentation
suggests and this makes the logic consistent with normal connections.
14) Removed module method attach(). This can be replaced with a call to
Connection(handle=) if needed.
Changes from 3.0a to 3.1
1) Added support for connecting with SYSDBA and SYSOPER access which is
needed for connecting as sys in Oracle 9i.
2) Only check the dictionary size if the variable is not NULL; otherwise, an
error takes place which is not caught or cleared; this eliminates a
spurious "Objects/dictobject.c:1258: bad argument to internal function" in
Python 2.3.
3) Add support for session pooling. This is only support for Oracle 9i but
is amazingly fast -- about 100 times faster than connecting.
4) Add support for statement caching when pooling sessions, this reduces the
parse time considerably. Unfortunately, the Oracle OCI does not allow this
to be easily turned on for normal sessions.
5) Add method trim() on CLOB and BLOB variables for trimming the size.
6) Add support for externally identified users; to use this feature leave the
username and password fields empty when connecting.
7) Add method cancel() on connection objects to cancel long running queries.
Note that this only works on non-Windows platforms.
8) Add method callfunc() on cursor objects to allow calling a function
without using an anonymous PL/SQL block.
9) Added documentation on objects that were not documented. At this point all
objects, methods and constants in cx_Oracle have been documented.
10) Added support for timestamp columns in Oracle 9i.
11) Added module level method makedsn() which creates a data source name given
the host, port and SID.
12) Added constant "buildtime" which is the time when the module was built as
an additional means of identifying the build that is in use.
13) Binding a value that is incompatible to the previous value that was bound
(data types do not match or array size is larger) will now result in a
new bind taking place. This is more consistent with the DB API although
it does imply a performance penalty when used.
Changes from 3.0 to 3.0a
1) Fixed bug where zero length PL/SQL arrays were being mishandled
2) Fixed support for the data type "float" in Oracle; added one to the
display size to allow for the sign of the number, if necessary; changed
the display size of unconstrained numbers to 127, which is the largest
number that Oracle can handle
3) Added support for retrieving the description of a bound cursor before
fetching it
4) Fixed a couple of build issues on Mac OS X, AIX and Solaris (64-bit)
5) Modified documentation slightly based on comments from several people
6) Included files in MANIFEST that are needed to generate the binaries
7) Modified test suite to work within the test environment at Computronix
as well as within the packages that are distributed
Changes from 2.5a to 3.0
1) Removed support for connection to Oracle7 databases; it is entirely
possible that it will still work but I no longer have any way of testing
and Oracle has dropped any meaningful support for Oracle7 anyway
2) Fetching of strings is now done with predefined memory areas rather than
dynamic memory areas; dynamic fetching of strings was causing problems
with Oracle 9i in some instances and databases using a different character
set other than US ASCII
3) Fixed bug where segfault would occur if the '/' character preceded the '@'
character in a connect string
4) Added two new cursor methods var() and arrayvar() in order to eliminate
the need for setinputsizes() when defining PL/SQL arrays and as a generic
method of acquiring bind variables directly when needed
5) Fixed support for binding cursors and added support for fetching cursors
(these are known as ref cursors in PL/SQL).
6) Eliminated discrepancy between the array size used internally and the
array size specified by the interface user; this was done earlier to avoid
bus errors on 64-bit platforms but another way has been found to get
around that issue and a number of people were getting confused because of
the discrepancy
7) Added support for the attribute "connection" on cursors, an optional
DB API extension
8) Added support for passing a dictionary as the second parameter for the
cursor.execute() method in order to comply with the DB API more closely;
the method of passing parameters with keyword arguments is still supported
and is in fact preferred
9) Added support for the attribute "statement" on cursors which is a
reference to the last SQL statement prepared or executed
10) Added support for passing any sequence to callproc() rather than just
lists as before
11) Fixed bug where segfault would occur if the array size was changed after
the cursor was executed but before it was fetched
12) Ignore array size when performing executemany() and use the length of the
list of arguments instead
13) Rollback when connection is closed or destroyed to follow DB API rather
than use the Oracle default (which is commit)
14) Added check for array size too large causing an integer overflow
15) Added support for iterators for Python 2.2 and above
16) Added test suite based on PyUnitTest
17) Added documentation in HTML format similar to the documentation for the
core Python library
Changes from 2.5 to 2.5a
1) Fix problem with Oracle 9i and retrieving strings; it seems that Oracle 9i
uses the correct method for dynamic callback but Oracle 8i will not work
with that method so an #ifdef was added to check for the existence of an
Oracle 9i feature; thanks to Paul Denize for discovering this problem
Changes from 2.4 to 2.5
1) Added flag OPT_NoOracle7 which, if set, assumes that connections are being
made to Oracle8 or higher databases; this allows for eliminating the
overhead in performing this check at connect time
2) Added flag OPT_NumbersAsStrings which, if set, returns all numbers as
strings rather than integers or floats; this flag is used when defined
variables are created (during select statements only)
3) Added flag OPT_Threading which, if set, uses OCI threading mode; there is a
significant performance degradation in this mode (about 15-20%) but it does
allow threads to share connections (threadsafety level 2 according to the
Python Database API 2.0); note that in order to support this, Oracle 8i or
higher is now required
4) Added Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS pairs where
applicable to support threading during blocking OCI calls
5) Added global method attach() to cx_Oracle to support attaching to an
existing database handle (as provided by PowerBuilder, for example)
6) Eliminated the cursor method fetchbinds() which was used for returning the
list of bind variables after execution to get the values of out variables;
the cursor method setinputsizes() was modified to return the list of bind
variables and the cursor method execute() was modified to return the list
of defined variables in the case of a select statement being executed;
these variables have three methods available to them: getvalue([<pos>]) to
get the value of a variable, setvalue(<pos>, <value>) to set its value and
copy(<var>, <src_pos>, <targ_pos>) to copy the value from a variable in a
more efficient manner than setvalue(getvalue())
7) Implemented cursor method executemany() which expects a list of
dictionaries for the arguments
8) Implemented cursor method callproc()
9) Added cursr method prepare() which parses (prepares) the statement for
execution; subsequent execute() or executemany() calls can pass None as the
statement which will imply use of the previously prepared statement; used
for high performance only
10) Added cursor method fetchraw() which will perform a raw fetch of the cursor
returning the number of rows thus fetched; this is used to avoid the
overhead of generating result sets; used for high performance only
11) Added cursor method executemanyprepared() which is identical to the method
executemany() except that it takes a single argument which is the number of
times to execute a previously prepared statement and it assumes that the
bind variables already have their values set; used for high performance
only
12) Added support for rowid being returned in a select statement
13) Added support for comparing dates returned by cx_Oracle
14) Integrated patch from Andre Reitz to set the null ok flag in the
description attribute of the cursor
15) Integrated patch from Andre Reitz to setup.py to support compilation with
Python 1.5
16) Integrated patch from Benjamin Kearns to setup.py to support compilation
on Cygwin
Changes from 2.3 to 2.4
1) String variables can now be made any length (previously restricted to the
64K limit imposed by Oracle for default binding); use the type
cx_Oracle.LONG_STRING as the argument to setinputsizes() for binding in
string values larger than 4000 bytes.
2) Raw and long raw columns are now supported; use the types cx_Oracle.BINARY
and cx_Oracle.LONG_BINARY as the argument to setinputsizes() for binding in
values of these types.
3) Functions DateFromTicks(), TimeFromTicks() and TimestampFromTicks()
are now implemented.
4) Function cursor.setoutputsize() implemented
5) Added the ability to bind arrays as out parameters to procedures; use the
format [cx_Oracle.<DataType>, <NumElems>] as the input to the function
setinputsizes() for binding arrays
6) Discovered from the Oracle 8.1.6 version of the documentation of the OCI
libraries, that the size of the memory location required for the precision
variable is larger than the printed documentation says; this was causing a
problem with the code on the Sun platform.
7) Now support building RPMs for Linux.
Changes from 2.2 to 2.3
1) Incremental performance enhancements (dealing with reusing cursors and
bind handles)
2) Ensured that arrays of integers with a single float in them are all
treated as floats, as suggested by Martin Koch.
3) Fixed code dealing with scale and precision for both defining a numeric
variable and for providing the cursor description; this eliminates the
problem of an underflow error (OCI-22054) when retrieving data with
non-zero scale.
Changes from 2.1 to 2.2
1) Upgraded thread safety to level 1 (according to the Python DB API 2.0) as
an internal project required the ability to share the module between
threads.
2) Added ability to bind ref cursors to PL/SQL blocks as requested by
Brad Powell.
3) Added function write(Value, [Offset]) to LOB variables as requested by
Matthias Kirst.
4) Procedure execute() on Cursor objects now permits a value None for the
statement which means that the previously prepared statement will be
executed and any input sizes set earlier will be retained. This was done to
improve the performance of scripts that execute one statement many times.
5) Modified module global constants BINARY and DATETIME to point to the
external representations of those types so that the expression
type(var) == cx_Oracle.DATETIME will work as expected.
6) Added global constant version to provide means of determining the current
version of the module.
7) Modified error checking routine to distinguish between an Oracle error and
invalid handles.
8) Added error checking to avoid setting the value of a bind variable to a
value that it cannot support and raised an exception to indicate this fact.
9) Added extra compile arguments for the AIX platform as suggested by Jehwan
Ryu.
10) Added section to the README to indicate the method for a binary
installation as suggested by Steve Holden.
11) Added simple usage example as requested by many people.
12) Added HISTORY file to the distribution.

35
LICENSE.txt Normal file
View File

@ -0,0 +1,35 @@
Copyright © 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta, Canada.
All rights reserved.
License for cx_Oracle
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the disclaimer that follows.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Computronix nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
DISCLAIMER:
THIS SOFTWARE IS PROVIDED BY COMPUTRONIX AND CONTRIBUTORS *AS IS*
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COMPUTRONIX
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Computronix® is a registered trademark of Computronix (Canada) Ltd.

333
LobVar.c Normal file
View File

@ -0,0 +1,333 @@
//-----------------------------------------------------------------------------
// LobVar.c
// Defines the routines for handling LOB variables.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LOB type
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
OCILobLocator **data;
udt_Connection *connection;
int isFile;
} udt_LobVar;
#include "ExternalLobVar.c"
//-----------------------------------------------------------------------------
// Declaration of LOB variable functions.
//-----------------------------------------------------------------------------
static int LobVar_Initialize(udt_LobVar*, udt_Cursor*);
static void LobVar_Finalize(udt_LobVar*);
static PyObject *LobVar_GetValue(udt_LobVar*, unsigned);
static int LobVar_SetValue(udt_LobVar*, unsigned, PyObject*);
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
static PyTypeObject g_CLOBVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.CLOB", // tp_name
sizeof(udt_LobVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
static PyTypeObject g_NCLOBVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.NCLOB", // tp_name
sizeof(udt_LobVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
static PyTypeObject g_BLOBVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.BLOB", // tp_name
sizeof(udt_LobVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
static PyTypeObject g_BFILEVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.BFILE", // tp_name
sizeof(udt_LobVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
static udt_VariableType vt_CLOB = {
(InitializeProc) LobVar_Initialize,
(FinalizeProc) LobVar_Finalize,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) LobVar_SetValue,
(GetValueProc) LobVar_GetValue,
&g_CLOBVarType, // Python type
SQLT_CLOB, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCILobLocator*), // element length
0, // is variable length
0, // can be copied
0 // can be in array
};
static udt_VariableType vt_NCLOB = {
(InitializeProc) LobVar_Initialize,
(FinalizeProc) LobVar_Finalize,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) LobVar_SetValue,
(GetValueProc) LobVar_GetValue,
&g_NCLOBVarType, // Python type
SQLT_CLOB, // Oracle type
SQLCS_NCHAR, // charset form
sizeof(OCILobLocator*), // element length
0, // is variable length
0, // can be copied
0 // can be in array
};
static udt_VariableType vt_BLOB = {
(InitializeProc) LobVar_Initialize,
(FinalizeProc) LobVar_Finalize,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) LobVar_SetValue,
(GetValueProc) LobVar_GetValue,
&g_BLOBVarType, // Python type
SQLT_BLOB, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCILobLocator*), // element length
0, // is variable length
0, // can be copied
0 // can be in array
};
static udt_VariableType vt_BFILE = {
(InitializeProc) LobVar_Initialize,
(FinalizeProc) LobVar_Finalize,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) LobVar_SetValue,
(GetValueProc) LobVar_GetValue,
&g_BFILEVarType, // Python type
SQLT_BFILE, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCILobLocator*), // element length
0, // is variable length
0, // can be copied
0 // can be in array
};
//-----------------------------------------------------------------------------
// LobVar_Initialize()
// Initialize the variable.
//-----------------------------------------------------------------------------
static int LobVar_Initialize(
udt_LobVar *var, // variable to initialize
udt_Cursor *cursor) // cursor created by
{
sword status;
ub4 i;
// initialize members
Py_INCREF(cursor->connection);
var->connection = cursor->connection;
var->isFile = (var->type == &vt_BFILE);
// initialize the LOB locators
for (i = 0; i < var->allocatedElements; i++) {
status = OCIDescriptorAlloc(var->environment->handle,
(dvoid**) &var->data[i], OCI_DTYPE_LOB, 0, 0);
if (Environment_CheckForError(var->environment, status,
"LobVar_Initialize()") < 0)
return -1;
}
return 0;
}
//-----------------------------------------------------------------------------
// LobVar_Finalize()
// Prepare for variable destruction.
//-----------------------------------------------------------------------------
static void LobVar_Finalize(
udt_LobVar *var) // variable to free
{
boolean isTemporary;
ub4 i;
for (i = 0; i < var->allocatedElements; i++) {
if (var->data[i]) {
OCILobIsTemporary(var->environment->handle,
var->environment->errorHandle, var->data[i], &isTemporary);
if (isTemporary)
OCILobFreeTemporary(var->connection->handle,
var->environment->errorHandle, var->data[i]);
OCIDescriptorFree(var->data[i], OCI_DTYPE_LOB);
}
}
Py_DECREF(var->connection);
}
//-----------------------------------------------------------------------------
// LobVar_GetValue()
// Returns the value stored at the given array position.
//-----------------------------------------------------------------------------
static PyObject *LobVar_GetValue(
udt_LobVar *var, // variable to determine value for
unsigned pos) // array position
{
return ExternalLobVar_New(var, pos);
}
//-----------------------------------------------------------------------------
// LobVar_SetValue()
// Sets the value stored at the given array position.
//-----------------------------------------------------------------------------
static int LobVar_SetValue(
udt_LobVar *var, // variable to determine value for
unsigned pos, // array position
PyObject *value) // value to set
{
boolean isTemporary;
sword status;
ub1 lobType;
ub4 length;
// only support strings
if (!PyString_Check(value)) {
PyErr_SetString(PyExc_TypeError, "expecting string data");
return -1;
}
// make sure have temporary LOBs set up
status = OCILobIsTemporary(var->environment->handle,
var->environment->errorHandle, var->data[pos], &isTemporary);
if (Environment_CheckForError(var->environment, status,
"LobVar_SetValue(): is temporary?") < 0)
return -1;
if (!isTemporary) {
if (var->type->oracleType == SQLT_BLOB)
lobType = OCI_TEMP_BLOB;
else lobType = OCI_TEMP_CLOB;
status = OCILobCreateTemporary(var->connection->handle,
var->environment->errorHandle, var->data[pos], OCI_DEFAULT,
OCI_DEFAULT, lobType, FALSE, OCI_DURATION_SESSION);
if (Environment_CheckForError(var->environment, status,
"LobVar_SetValue(): create temporary") < 0)
return -1;
}
// trim the current value
status = OCILobTrim(var->connection->handle,
var->environment->errorHandle, var->data[pos], 0);
if (Environment_CheckForError(var->environment, status,
"LobVar_SetValue(): trim") < 0)
return -1;
// set the current value
length = PyString_GET_SIZE(value);
if (length) {
status = OCILobWrite(var->connection->handle,
var->environment->errorHandle, var->data[pos],
&length, 1, PyString_AS_STRING(value),
PyString_GET_SIZE(value), OCI_ONE_PIECE, NULL, NULL, 0, 0);
if (Environment_CheckForError(var->environment, status,
"LobVar_SetValue(): write") < 0)
return -1;
}
return 0;
}

171
LongVar.c Normal file
View File

@ -0,0 +1,171 @@
//-----------------------------------------------------------------------------
// LongVar.c
// Defines the routines specific to the long type.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// long type
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
char *data;
} udt_LongVar;
//-----------------------------------------------------------------------------
// declaration of long variable functions.
//-----------------------------------------------------------------------------
static int LongVar_SetValue(udt_LongVar*, unsigned, PyObject*);
static PyObject *LongVar_GetValue(udt_LongVar*, unsigned);
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
static PyTypeObject g_LongStringVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.LONG_STRING", // tp_name
sizeof(udt_LongVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
static PyTypeObject g_LongBinaryVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.LONG_BINARY", // tp_name
sizeof(udt_LongVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
static udt_VariableType vt_LongString = {
(InitializeProc) NULL,
(FinalizeProc) NULL,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) LongVar_SetValue,
(GetValueProc) LongVar_GetValue,
&g_LongStringVarType, // Python type
SQLT_LVC, // Oracle type
SQLCS_IMPLICIT, // charset form
128 * 1024, // element length (default)
1, // is variable length
1, // can be copied
0 // can be in array
};
static udt_VariableType vt_LongBinary = {
(InitializeProc) NULL,
(FinalizeProc) NULL,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) LongVar_SetValue,
(GetValueProc) LongVar_GetValue,
&g_LongBinaryVarType, // Python type
SQLT_LVB, // Oracle type
SQLCS_IMPLICIT, // charset form
128 * 1024, // element length (default)
1, // is variable length
1, // can be copied
0 // can be in array
};
//-----------------------------------------------------------------------------
// LongVar_SetValue()
// Set the value of the variable.
//-----------------------------------------------------------------------------
static int LongVar_SetValue(
udt_LongVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
Py_ssize_t bufferSize;
const void *buffer;
char *ptr;
// get the buffer data and size for binding
if (PyString_Check(value)) {
buffer = PyString_AS_STRING(value);
bufferSize = PyString_GET_SIZE(value);
} else if (PyBuffer_Check(value)) {
if (PyObject_AsReadBuffer(value, &buffer, &bufferSize) < 0)
return -1;
} else {
PyErr_SetString(PyExc_TypeError, "expecting string or buffer data");
return -1;
}
// copy the string to the Oracle buffer
if (bufferSize + sizeof(ub4) > var->maxLength) {
if (Variable_Resize( (udt_Variable*) var,
bufferSize + sizeof(ub4)) < 0)
return -1;
}
ptr = var->data + var->maxLength * pos;
*((ub4 *) ptr) = (ub4) bufferSize;
if (bufferSize)
memcpy(ptr + sizeof(ub4), buffer, bufferSize);
return 0;
}
//-----------------------------------------------------------------------------
// LongVar_GetValue()
// Returns the value stored at the given array position.
//-----------------------------------------------------------------------------
static PyObject *LongVar_GetValue(
udt_LongVar *var, // variable to determine value for
unsigned pos) // array position
{
char *ptr;
ub4 size;
ptr = var->data + var->maxLength * pos;
size = *((ub4 *) ptr);
return PyString_FromStringAndSize(ptr + sizeof(ub4), size);
}

66
MANIFEST Normal file
View File

@ -0,0 +1,66 @@
setup.py
setup.cfg
README.txt
LICENSE.txt
HISTORY.txt
MANIFEST
Callback.c
Connection.c
Cursor.c
CursorVar.c
cx_Oracle.c
DateTimeVar.c
Environment.c
Error.c
ExternalDateTimeVar.c
ExternalLobVar.c
ExternalObjectVar.c
LobVar.c
LongVar.c
NumberVar.c
ObjectType.c
ObjectVar.c
SessionPool.c
StringVar.c
TimestampVar.c
Transforms.c
Variable.c
html/about.html
html/blank.png
html/connobj.html
html/contents.html
html/contents.png
html/cursorobj.html
html/cx_Oracle.css
html/cx_Oracle.html
html/dateobj.html
html/front.html
html/index.html
html/index.png
html/lobobj.html
html/module.html
html/modules.png
html/next.png
html/node12.html
html/node4.html
html/node5.html
html/previous.png
html/sesspool.html
html/up.png
html/varobj.html
test/Connection.py
test/Cursor.py
test/CursorVar.py
test/DateTimeVar.py
test/LobVar.py
test/LongVar.py
test/NumberVar.py
test/ObjectVar.py
test/SessionPool.py
test/SetupTest_9i.sql
test/SetupTest.sql
test/StringVar.py
test/test_dbapi20.py
test/TestEnv.py
test/test.py
test/TimestampVar.py

508
NumberVar.c Normal file
View File

@ -0,0 +1,508 @@
//-----------------------------------------------------------------------------
// NumberVar.c
// Defines the routines for handling numeric variables.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// define number format used for acquiring long integers
//-----------------------------------------------------------------------------
static const char gc_NumberFormat[63] =
"999999999999999999999999999999999999999999999999999999999999999";
//-----------------------------------------------------------------------------
// Number type
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
OCINumber *data;
} udt_NumberVar;
//-----------------------------------------------------------------------------
// Declaration of number variable functions.
//-----------------------------------------------------------------------------
static int NumberVar_PreDefine(udt_NumberVar*, OCIParam*);
static int NumberVar_SetValue(udt_NumberVar*, unsigned, PyObject*);
static PyObject *NumberVar_GetValue(udt_NumberVar*, unsigned);
#ifdef SQLT_BFLOAT
static int NumberVar_SetValueAsDouble(udt_NumberVar*, unsigned, PyObject*);
static PyObject *NumberVar_GetValueAsDouble(udt_NumberVar*, unsigned);
#endif
//-----------------------------------------------------------------------------
// Python type declaration
//-----------------------------------------------------------------------------
static PyTypeObject g_NumberVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.NUMBER", // tp_name
sizeof(udt_NumberVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
static udt_VariableType vt_Float = {
(InitializeProc) NULL,
(FinalizeProc) NULL,
(PreDefineProc) NumberVar_PreDefine,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) NumberVar_SetValue,
(GetValueProc) NumberVar_GetValue,
&g_NumberVarType, // Python type
SQLT_VNU, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCINumber), // element length
0, // is variable length
1, // can be copied
1 // can be in array
};
#ifdef SQLT_BFLOAT
static udt_VariableType vt_NativeFloat = {
(InitializeProc) NULL,
(FinalizeProc) NULL,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) NumberVar_SetValueAsDouble,
(GetValueProc) NumberVar_GetValueAsDouble,
&g_NumberVarType, // Python type
SQLT_BDOUBLE, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(double), // element length
0, // is variable length
1, // can be copied
1 // can be in array
};
#endif
static udt_VariableType vt_Integer = {
(InitializeProc) NULL,
(FinalizeProc) NULL,
(PreDefineProc) NumberVar_PreDefine,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) NumberVar_SetValue,
(GetValueProc) NumberVar_GetValue,
&g_NumberVarType, // Python type
SQLT_VNU, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCINumber), // element length
0, // is variable length
1, // can be copied
1 // can be in array
};
static udt_VariableType vt_LongInteger = {
(InitializeProc) NULL,
(FinalizeProc) NULL,
(PreDefineProc) NumberVar_PreDefine,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) NumberVar_SetValue,
(GetValueProc) NumberVar_GetValue,
&g_NumberVarType, // Python type
SQLT_VNU, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCINumber), // element length
0, // is variable length
1, // can be copied
1 // can be in array
};
static udt_VariableType vt_NumberAsString = {
(InitializeProc) NULL,
(FinalizeProc) NULL,
(PreDefineProc) NumberVar_PreDefine,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) NumberVar_SetValue,
(GetValueProc) NumberVar_GetValue,
&g_NumberVarType, // Python type
SQLT_VNU, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCINumber), // element length
0, // is variable length
1, // can be copied
1 // can be in array
};
static udt_VariableType vt_Boolean = {
(InitializeProc) NULL,
(FinalizeProc) NULL,
(PreDefineProc) NumberVar_PreDefine,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) NumberVar_SetValue,
(GetValueProc) NumberVar_GetValue,
&g_NumberVarType, // Python type
SQLT_VNU, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCINumber), // element length
0, // is variable length
1, // can be copied
1 // can be in array
};
//-----------------------------------------------------------------------------
// NumberVar_PreDefine()
// Set the type of value (integer, float or string) that will be returned
// when values are fetched from this variable.
//-----------------------------------------------------------------------------
static int NumberVar_PreDefine(
udt_NumberVar *var, // variable to initialize
OCIParam *param) // parameter handle
{
sb2 precision;
sword status;
sb1 scale;
// if the return type has not already been specified, check to see if the
// number can fit inside an integer by looking at the precision and scale
if (var->type == &vt_Float) {
scale = 0;
precision = 0;
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &scale, 0,
OCI_ATTR_SCALE, var->environment->errorHandle);
if (Environment_CheckForError(var->environment, status,
"NumberVar_PreDefine(): scale") < 0)
return -1;
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &precision, 0,
OCI_ATTR_PRECISION, var->environment->errorHandle);
if (Environment_CheckForError(var->environment, status,
"NumberVar_PreDefine(): precision") < 0)
return -1;
if (scale == 0 && precision > 0 && precision < 10)
var->type = &vt_Integer;
else if (scale == 0 || (scale == -127 && precision == 0))
var->type = &vt_LongInteger;
}
return 0;
}
#if (PY_VERSION_HEX >= 0x02030000)
//-----------------------------------------------------------------------------
// NumberVar_SetValueFromBoolean()
// Set the value of the variable from a Python boolean.
//-----------------------------------------------------------------------------
static int NumberVar_SetValueFromBoolean(
udt_NumberVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
long integerValue;
sword status;
integerValue = (value == Py_True);
status = OCINumberFromInt(var->environment->errorHandle, &integerValue,
sizeof(long), OCI_NUMBER_SIGNED, &var->data[pos]);
return Environment_CheckForError(var->environment, status,
"NumberVar_SetValueFromBoolean()");
}
#endif
//-----------------------------------------------------------------------------
// NumberVar_SetValueFromInteger()
// Set the value of the variable from a Python integer.
//-----------------------------------------------------------------------------
static int NumberVar_SetValueFromInteger(
udt_NumberVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
long integerValue;
sword status;
integerValue = PyInt_AS_LONG(value);
status = OCINumberFromInt(var->environment->errorHandle, &integerValue,
sizeof(long), OCI_NUMBER_SIGNED, &var->data[pos]);
return Environment_CheckForError(var->environment, status,
"NumberVar_SetValueFromInteger()");
}
//-----------------------------------------------------------------------------
// NumberVar_SetValueFromFloat()
// Set the value of the variable from a Python float.
//-----------------------------------------------------------------------------
static int NumberVar_SetValueFromFloat(
udt_NumberVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
double doubleValue;
sword status;
doubleValue = PyFloat_AS_DOUBLE(value);
status = OCINumberFromReal(var->environment->errorHandle, &doubleValue,
sizeof(double), &var->data[pos]);
return Environment_CheckForError(var->environment, status,
"NumberVar_SetValueFromFloat()");
}
//-----------------------------------------------------------------------------
// NumberVar_SetValueFromLong()
// Set the value of the variable from a Python long.
//-----------------------------------------------------------------------------
static int NumberVar_SetValueFromLong(
udt_NumberVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
PyObject *textValue;
sword status;
textValue = PyObject_Str(value);
if (!textValue)
return -1;
status = OCINumberFromText(var->environment->errorHandle,
(OraText*) PyString_AS_STRING(textValue),
PyString_GET_SIZE(textValue), (OraText*) gc_NumberFormat,
sizeof(gc_NumberFormat), NULL, 0, &var->data[pos]);
Py_DECREF(textValue);
return Environment_CheckForError(var->environment, status,
"NumberVar_SetValueFromLong()");
}
//-----------------------------------------------------------------------------
// NumberVar_GetFormatAndTextFromDecimal()
// Return the number format and text to use for the Decimal object.
//-----------------------------------------------------------------------------
static int NumberVar_GetFormatAndTextFromDecimal(
PyObject *tupleValue, // decimal as_tuple() value
char **textValue, // text string for conversion
char **format) // format for conversion
{
long numDigits, scale, i, sign, length, digit;
char *valuePtr, *formatPtr;
PyObject *digits;
// acquire basic information from the value tuple
sign = PyInt_AS_LONG(PyTuple_GET_ITEM(tupleValue, 0));
digits = PyTuple_GET_ITEM(tupleValue, 1);
scale = PyInt_AS_LONG(PyTuple_GET_ITEM(tupleValue, 2));
numDigits = PyTuple_GET_SIZE(digits);
// allocate memory for the string and format to use in conversion
length = numDigits + abs(scale) + 3;
*textValue = valuePtr = PyMem_Malloc(length);
if (!*textValue) {
PyErr_NoMemory();
return -1;
}
*format = formatPtr = PyMem_Malloc(length);
if (!*format) {
PyMem_Free(*textValue);
PyErr_NoMemory();
return -1;
}
// populate the string and format
if (sign)
*valuePtr++ = '-';
for (i = 0; i < numDigits + scale; i++) {
*formatPtr++ = '9';
if (i < numDigits)
digit = PyInt_AS_LONG(PyTuple_GetItem(digits, i));
else digit = 0;
*valuePtr++ = '0' + (char) digit;
}
if (scale < 0) {
*formatPtr++ = 'D';
*valuePtr++ = '.';
for (i = scale; i < 0; i++) {
*formatPtr++ = '9';
if (numDigits + i < 0)
digit = 0;
else digit = PyInt_AS_LONG(PyTuple_GetItem(digits, numDigits + i));
*valuePtr++ = '0' + (char) digit;
}
}
*formatPtr = '\0';
*valuePtr = '\0';
return 0;
}
//-----------------------------------------------------------------------------
// NumberVar_SetValueFromDecimal()
// Set the value of the variable from a Python decimal.Decimal object.
//-----------------------------------------------------------------------------
static int NumberVar_SetValueFromDecimal(
udt_NumberVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
char *textValue, *format;
PyObject *tupleValue;
sword status;
tupleValue = PyObject_CallMethod(value, "as_tuple", NULL);
if (!tupleValue)
return -1;
if (NumberVar_GetFormatAndTextFromDecimal(tupleValue, &textValue,
&format) < 0) {
Py_DECREF(tupleValue);
return -1;
}
status = OCINumberFromText(var->environment->errorHandle,
(OraText*) textValue, strlen(textValue), (OraText*) format,
strlen(format), NULL, 0, &var->data[pos]);
Py_DECREF(tupleValue);
PyMem_Free(textValue);
PyMem_Free(format);
return Environment_CheckForError(var->environment, status,
"NumberVar_SetValueFromDecimal()");
}
//-----------------------------------------------------------------------------
// NumberVar_SetValue()
// Set the value of the variable.
//-----------------------------------------------------------------------------
static int NumberVar_SetValue(
udt_NumberVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
if (PyInt_Check(value))
return NumberVar_SetValueFromInteger(var, pos, value);
#if (PY_VERSION_HEX >= 0x02030000)
else if (PyBool_Check(value))
return NumberVar_SetValueFromBoolean(var, pos, value);
#endif
else if (PyFloat_Check(value))
return NumberVar_SetValueFromFloat(var, pos, value);
else if (PyLong_Check(value))
return NumberVar_SetValueFromLong(var, pos, value);
else if (value->ob_type == g_DecimalType)
return NumberVar_SetValueFromDecimal(var, pos, value);
PyErr_SetString(PyExc_TypeError, "expecting numeric data");
return -1;
}
#ifdef SQLT_BFLOAT
//-----------------------------------------------------------------------------
// NumberVar_SetValueAsDouble()
// Set the value of the variable which should be a native double.
//-----------------------------------------------------------------------------
static int NumberVar_SetValueAsDouble(
udt_NumberVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
double *doublePtr;
if (!PyFloat_Check(value)) {
PyErr_SetString(PyExc_TypeError, "expecting float");
return -1;
}
doublePtr = (double*) &var->data[pos];
*doublePtr = PyFloat_AS_DOUBLE(value);
return 0;
}
#endif
//-----------------------------------------------------------------------------
// NumberVar_GetValue()
// Returns the value stored at the given array position.
//-----------------------------------------------------------------------------
static PyObject *NumberVar_GetValue(
udt_NumberVar *var, // variable to determine value for
unsigned pos) // array position
{
char stringValue[200];
long integerValue;
ub4 stringLength;
PyObject *result;
sword status;
if (var->type == &vt_Integer || var->type == &vt_Boolean) {
status = OCINumberToInt(var->environment->errorHandle, &var->data[pos],
sizeof(long), OCI_NUMBER_SIGNED, (dvoid*) &integerValue);
if (Environment_CheckForError(var->environment, status,
"NumberVar_GetValue(): as integer") < 0)
return NULL;
if (var->type == &vt_Integer)
return PyInt_FromLong(integerValue);
#if (PY_VERSION_HEX >= 0x02030000)
return PyBool_FromLong(integerValue);
#endif
}
if (var->type == &vt_NumberAsString || var->type == &vt_LongInteger) {
stringLength = sizeof(stringValue);
status = OCINumberToText(var->environment->errorHandle,
&var->data[pos], (unsigned char*) "TM9", 3, NULL, 0,
&stringLength, (unsigned char*) stringValue);
if (Environment_CheckForError(var->environment, status,
"NumberVar_GetValue(): as string") < 0)
return NULL;
if (var->type == &vt_NumberAsString)
return PyString_FromStringAndSize(stringValue, stringLength);
result = PyInt_FromString(stringValue, NULL, 10);
if (result || !PyErr_ExceptionMatches(PyExc_ValueError))
return result;
PyErr_Clear();
result = PyLong_FromString(stringValue, NULL, 10);
if (result || !PyErr_ExceptionMatches(PyExc_ValueError))
return result;
PyErr_Clear();
}
return OracleNumberToPythonFloat(var->environment, &var->data[pos]);
}
#ifdef SQLT_BFLOAT
//-----------------------------------------------------------------------------
// NumberVar_GetValueAsDouble()
// Returns the value stored at the given array position as a float.
//-----------------------------------------------------------------------------
static PyObject *NumberVar_GetValueAsDouble(
udt_NumberVar *var, // variable to determine value for
unsigned pos) // array position
{
double *doublePtr;
doublePtr = (double*) &var->data[pos];
return PyFloat_FromDouble(*doublePtr);
}
#endif

518
ObjectType.c Normal file
View File

@ -0,0 +1,518 @@
//-----------------------------------------------------------------------------
// ObjectType.c
// Defines the routines for handling Oracle type information.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// structures used for handling object types
//-----------------------------------------------------------------------------
typedef struct {
PyObject_HEAD
udt_Environment *environment;
OCIType *tdo;
PyObject *schema;
PyObject *name;
PyObject *attributes;
PyObject *attributesByName;
OCITypeCode collectionTypeCode;
OCITypeCode elementTypeCode;
PyObject *elementType;
int isCollection;
} udt_ObjectType;
typedef struct {
PyObject_HEAD
PyObject *name;
OCITypeCode typeCode;
udt_ObjectType *subType;
} udt_ObjectAttribute;
//-----------------------------------------------------------------------------
// Declaration of type variable functions.
//-----------------------------------------------------------------------------
static udt_ObjectType *ObjectType_New(udt_Connection*, OCIParam*);
static void ObjectType_Free(udt_ObjectType*);
static PyObject *ObjectType_Repr(udt_ObjectType*);
static udt_ObjectAttribute *ObjectAttribute_New(udt_Connection*, OCIParam*);
static void ObjectAttribute_Free(udt_ObjectAttribute*);
static PyObject *ObjectAttribute_Repr(udt_ObjectAttribute*);
//-----------------------------------------------------------------------------
// declaration of members for Python type "ObjectType"
//-----------------------------------------------------------------------------
static PyMemberDef g_ObjectTypeMembers[] = {
{ "schema", T_OBJECT, offsetof(udt_ObjectType, schema), READONLY },
{ "name", T_OBJECT, offsetof(udt_ObjectType, name), READONLY },
{ "attributes", T_OBJECT, offsetof(udt_ObjectType, attributes), READONLY },
{ NULL }
};
//-----------------------------------------------------------------------------
// declaration of members for Python type "ObjectAttribute"
//-----------------------------------------------------------------------------
static PyMemberDef g_ObjectAttributeMembers[] = {
{ "name", T_OBJECT, offsetof(udt_ObjectAttribute, name), READONLY },
{ NULL }
};
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
static PyTypeObject g_ObjectTypeType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.ObjectType", // tp_name
sizeof(udt_ObjectType), // tp_basicsize
0, // tp_itemsize
(destructor) ObjectType_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) ObjectType_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0, // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
0, // tp_methods
g_ObjectTypeMembers, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
0, // tp_alloc
0, // tp_new
0, // tp_free
0, // tp_is_gc
0 // tp_bases
};
static PyTypeObject g_ObjectAttributeType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.ObjectAttribute", // tp_name
sizeof(udt_ObjectAttribute), // tp_basicsize
0, // tp_itemsize
(destructor) ObjectAttribute_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) ObjectAttribute_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0, // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
0, // tp_methods
g_ObjectAttributeMembers, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
0, // tp_alloc
0, // tp_new
0, // tp_free
0, // tp_is_gc
0 // tp_bases
};
//-----------------------------------------------------------------------------
// ObjectType_Describe()
// Describe the type and store information about it as needed.
//-----------------------------------------------------------------------------
static int ObjectType_Describe(
udt_ObjectType *self, // type to populate
udt_Connection *connection, // connection for type information
OCIDescribe *describeHandle) // describe handle
{
OCIParam *topLevelParam, *attributeListParam, *attributeParam;
udt_ObjectAttribute *attribute;
OCIParam *collectionParam;
OCITypeCode typeCode;
ub2 numAttributes;
sword status;
int i;
// describe the type
status = OCIDescribeAny(connection->handle, self->environment->errorHandle,
(dvoid*) self->tdo, 0, OCI_OTYPE_PTR, OCI_DEFAULT, OCI_PTYPE_TYPE,
describeHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Describe(): describe type") < 0)
return -1;
// get top level parameter descriptor
status = OCIAttrGet(describeHandle, OCI_HTYPE_DESCRIBE, &topLevelParam, 0,
OCI_ATTR_PARAM, self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Describe(): get top level parameter descriptor") < 0)
return -1;
// determine type of type
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM, &typeCode, 0,
OCI_ATTR_TYPECODE, self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Describe(): get type code") < 0)
return -1;
// if a collection, need to determine the sub type
if (typeCode == OCI_TYPECODE_NAMEDCOLLECTION) {
self->isCollection = 1;
// determine type of collection
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM,
&self->collectionTypeCode, 0, OCI_ATTR_COLLECTION_TYPECODE,
self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Describe(): get collection type code") < 0)
return -1;
// acquire collection parameter descriptor
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM, &collectionParam,
0, OCI_ATTR_COLLECTION_ELEMENT,
self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Describe(): get collection descriptor") < 0)
return -1;
// determine type of element
status = OCIAttrGet(collectionParam, OCI_DTYPE_PARAM,
&self->elementTypeCode, 0, OCI_ATTR_TYPECODE,
self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Describe(): get element type code") < 0)
return -1;
// if element type is an object type get its type
if (self->elementTypeCode == OCI_TYPECODE_OBJECT) {
self->elementType = (PyObject*)
ObjectType_New(connection, collectionParam);
if (!self->elementType)
return -1;
}
}
// determine the number of attributes
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM,
(dvoid*) &numAttributes, 0, OCI_ATTR_NUM_TYPE_ATTRS,
self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Describe(): get number of attributes") < 0)
return -1;
// allocate the attribute list and dictionary
self->attributes = PyList_New(numAttributes);
if (!self->attributes)
return -1;
self->attributesByName = PyDict_New();
if (!self->attributesByName)
return -1;
// acquire the list parameter descriptor
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM,
(dvoid*) &attributeListParam, 0, OCI_ATTR_LIST_TYPE_ATTRS,
self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Describe(): get list parameter descriptor") < 0)
return -1;
// create attribute information for each attribute
for (i = 0; i < numAttributes; i++) {
status = OCIParamGet(attributeListParam, OCI_DTYPE_PARAM,
self->environment->errorHandle, (dvoid**) &attributeParam,
(ub4) i + 1);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Describe(): get attribute param descriptor") < 0)
return -1;
attribute = ObjectAttribute_New(connection, attributeParam);
if (!attribute)
return -1;
PyList_SET_ITEM(self->attributes, i, (PyObject*) attribute);
if (PyDict_SetItem(self->attributesByName, attribute->name,
(PyObject*) attribute) < 0)
return -1;
}
return 0;
}
//-----------------------------------------------------------------------------
// ObjectType_Initialize()
// Initialize the object type with the information that is required.
//-----------------------------------------------------------------------------
static int ObjectType_Initialize(
udt_ObjectType *self, // type to initialize
udt_Connection *connection, // connection for type information
OCIParam *param) // parameter descriptor
{
OCIDescribe *describeHandle;
OCIRef *tdoReference;
sword status;
char *name;
ub4 size;
// determine the schema of the type
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &name, &size,
OCI_ATTR_SCHEMA_NAME, self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Initialize(): get schema name") < 0)
return -1;
self->schema = PyString_FromStringAndSize(name, size);
if (!self->schema)
return -1;
// determine the name of the type
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &name, &size,
OCI_ATTR_TYPE_NAME, self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Initialize(): get name") < 0)
return -1;
self->name = PyString_FromStringAndSize(name, size);
if (!self->name)
return -1;
// retrieve TDO of the parameter
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &tdoReference, 0,
OCI_ATTR_REF_TDO, self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Initialize(): get TDO reference") < 0)
return -1;
status = OCIObjectPin(self->environment->handle,
self->environment->errorHandle, tdoReference, NULL, OCI_PIN_ANY,
OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid**) &self->tdo);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Initialize(): pin TDO reference") < 0)
return -1;
// acquire a describe handle
status = OCIHandleAlloc(self->environment->handle,
(dvoid**) &describeHandle, OCI_HTYPE_DESCRIBE, 0, 0);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Initialize(): allocate describe handle") < 0)
return -1;
// describe the type
if (ObjectType_Describe(self, connection, describeHandle) < 0)
return -1;
// free the describe handle
status = OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
if (Environment_CheckForError(self->environment, status,
"ObjectType_Initialize(): free describe handle") < 0)
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// ObjectType_New()
// Allocate a new object type.
//-----------------------------------------------------------------------------
static udt_ObjectType *ObjectType_New(
udt_Connection *connection, // connection for type information
OCIParam *param) // parameter descriptor
{
udt_ObjectType *self;
self = PyObject_NEW(udt_ObjectType, &g_ObjectTypeType);
if (!self)
return NULL;
Py_INCREF(connection->environment);
self->environment = connection->environment;
self->tdo = NULL;
self->schema = NULL;
self->name = NULL;
self->attributes = NULL;
self->attributesByName = NULL;
self->elementType = NULL;
self->isCollection = 0;
if (ObjectType_Initialize(self, connection, param) < 0) {
Py_DECREF(self);
return NULL;
}
return self;
}
//-----------------------------------------------------------------------------
// ObjectType_Free()
// Free the memory associated with an object type.
//-----------------------------------------------------------------------------
static void ObjectType_Free(
udt_ObjectType *self) // object type to free
{
Py_DECREF(self->environment);
Py_XDECREF(self->schema);
Py_XDECREF(self->name);
Py_XDECREF(self->attributes);
Py_XDECREF(self->attributesByName);
Py_XDECREF(self->elementType);
if (self->tdo)
OCIObjectUnpin(self->environment->handle,
self->environment->errorHandle, self->tdo);
PyObject_DEL(self);
}
//-----------------------------------------------------------------------------
// ObjectType_Repr()
// Return a string representation of the object type.
//-----------------------------------------------------------------------------
static PyObject *ObjectType_Repr(
udt_ObjectType *self) // object type to return the string for
{
PyObject *module, *name, *result;
if (GetModuleAndName(self->ob_type, &module, &name) < 0)
return NULL;
result = PyString_FromFormat("<%s.%s %s.%s>",
PyString_AS_STRING(module), PyString_AS_STRING(name),
PyString_AS_STRING(self->schema), PyString_AS_STRING(self->name));
Py_DECREF(module);
Py_DECREF(name);
return result;
}
//-----------------------------------------------------------------------------
// ObjectAttribute_Initialize()
// Initialize the new object attribute.
//-----------------------------------------------------------------------------
static int ObjectAttribute_Initialize(
udt_ObjectAttribute *self, // object attribute to initialize
udt_Connection *connection, // connection in use
OCIParam *param) // parameter descriptor
{
sword status;
char *name;
ub4 size;
// determine the name of the attribute
status = OCIAttrGet(param, OCI_DTYPE_PARAM, (dvoid*) &name, &size,
OCI_ATTR_NAME, connection->environment->errorHandle);
if (Environment_CheckForError(connection->environment, status,
"ObjectAttribute_Initialize(): get name") < 0)
return -1;
self->name = PyString_FromStringAndSize(name, size);
if (!self->name)
return -1;
// determine the type of the attribute
status = OCIAttrGet(param, OCI_DTYPE_PARAM, (dvoid*) &self->typeCode, 0,
OCI_ATTR_TYPECODE, connection->environment->errorHandle);
if (Environment_CheckForError(connection->environment, status,
"ObjectAttribute_Initialize(): get type code") < 0)
return -1;
// if the type of the attribute is object, recurse
switch (self->typeCode) {
case OCI_TYPECODE_NAMEDCOLLECTION:
case OCI_TYPECODE_OBJECT:
self->subType = ObjectType_New(connection, param);
if (!self->subType)
return -1;
break;
};
return 0;
}
//-----------------------------------------------------------------------------
// ObjectAttribute_New()
// Allocate a new object attribute.
//-----------------------------------------------------------------------------
static udt_ObjectAttribute *ObjectAttribute_New(
udt_Connection *connection, // connection information
OCIParam *param) // parameter descriptor
{
udt_ObjectAttribute *self;
self = PyObject_NEW(udt_ObjectAttribute, &g_ObjectAttributeType);
if (!self)
return NULL;
self->name = NULL;
self->subType = NULL;
if (ObjectAttribute_Initialize(self, connection, param) < 0) {
Py_DECREF(self);
return NULL;
}
return self;
}
//-----------------------------------------------------------------------------
// ObjectAttribute_Free()
// Free the memory associated with an object attribute.
//-----------------------------------------------------------------------------
static void ObjectAttribute_Free(
udt_ObjectAttribute *self) // object attribute to free
{
Py_XDECREF(self->name);
Py_XDECREF(self->subType);
PyObject_DEL(self);
}
//-----------------------------------------------------------------------------
// ObjectAttribute_Repr()
// Return a string representation of the object attribute.
//-----------------------------------------------------------------------------
static PyObject *ObjectAttribute_Repr(
udt_ObjectAttribute *self) // attribute to return the string for
{
PyObject *module, *name, *result;
if (GetModuleAndName(self->ob_type, &module, &name) < 0)
return NULL;
result = PyString_FromFormat("<%s.%s %s>",
PyString_AS_STRING(module), PyString_AS_STRING(name),
PyString_AS_STRING(self->name));
Py_DECREF(module);
Py_DECREF(name);
return result;
}

227
ObjectVar.c Normal file
View File

@ -0,0 +1,227 @@
//-----------------------------------------------------------------------------
// ObjectVar.c
// Defines the routines for handling Oracle object variables.
//-----------------------------------------------------------------------------
#include "ObjectType.c"
#include "ExternalObjectVar.c"
//-----------------------------------------------------------------------------
// Object type
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
dvoid **data;
dvoid **objectIndicator;
udt_Connection *connection;
udt_ObjectType *objectType;
} udt_ObjectVar;
//-----------------------------------------------------------------------------
// Declaration of object variable functions.
//-----------------------------------------------------------------------------
static int ObjectVar_Initialize(udt_ObjectVar*, udt_Cursor*);
static void ObjectVar_Finalize(udt_ObjectVar*);
static PyObject *ObjectVar_GetAttr(udt_ObjectVar*, PyObject*);
static PyObject *ObjectVar_GetValue(udt_ObjectVar*, unsigned);
static int ObjectVar_PreDefine(udt_ObjectVar*, OCIParam*);
static int ObjectVar_PostDefine(udt_ObjectVar*);
static int ObjectVar_IsNull(udt_ObjectVar*, unsigned);
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
static PyTypeObject g_ObjectVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.OBJECTVAR", // tp_name
sizeof(udt_ObjectVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) ObjectVar_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
static udt_VariableType vt_Object = {
(InitializeProc) ObjectVar_Initialize,
(FinalizeProc) ObjectVar_Finalize,
(PreDefineProc) ObjectVar_PreDefine,
(PostDefineProc) ObjectVar_PostDefine,
(IsNullProc) ObjectVar_IsNull,
(SetValueProc) NULL,
(GetValueProc) ObjectVar_GetValue,
&g_ObjectVarType, // Python type
SQLT_NTY, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(dvoid*), // element length
0, // is variable length
0, // can be copied
0 // can be in array
};
//-----------------------------------------------------------------------------
// ObjectVar_Initialize()
// Initialize the variable.
//-----------------------------------------------------------------------------
static int ObjectVar_Initialize(
udt_ObjectVar *self, // variable to initialize
udt_Cursor *cursor) // cursor to use
{
int i;
Py_INCREF(cursor->connection);
self->connection = cursor->connection;
self->objectType = NULL;
self->objectIndicator =
PyMem_Malloc(self->allocatedElements * sizeof(dvoid*));
if (!self->objectIndicator) {
PyErr_NoMemory();
return -1;
}
for (i = 0; i < self->allocatedElements; i++) {
self->data[i] = NULL;
self->objectIndicator[i] = NULL;
}
return 0;
}
//-----------------------------------------------------------------------------
// ObjectVar_Finalize()
// Prepare for variable destruction.
//-----------------------------------------------------------------------------
static void ObjectVar_Finalize(
udt_ObjectVar *self) // variable to free
{
int i;
for (i = 0; i < self->allocatedElements; i++) {
if (self->data[i])
OCIObjectFree(self->environment->handle,
self->environment->errorHandle, self->data[i],
OCI_OBJECTFREE_FORCE);
}
Py_DECREF(self->connection);
Py_XDECREF(self->objectType);
if (self->objectIndicator)
PyMem_Free(self->objectIndicator);
}
//-----------------------------------------------------------------------------
// ObjectVar_GetAttr()
// Retrieve an attribute on the variable object.
//-----------------------------------------------------------------------------
static PyObject *ObjectVar_GetAttr(
udt_ObjectVar *self, // variable object
PyObject *nameObject) // name of attribute
{
char *name;
name = PyString_AS_STRING(nameObject);
if (name[0] == 't' && strcmp(name, "type") == 0) {
Py_INCREF(self->objectType);
return (PyObject*) self->objectType;
}
return Variable_GetAttr((udt_Variable*) self, nameObject);
}
//-----------------------------------------------------------------------------
// ObjectVar_PreDefine()
// Performs additional steps required for defining objects.
//-----------------------------------------------------------------------------
static int ObjectVar_PreDefine(
udt_ObjectVar *self, // variable to set up
OCIParam *param) // parameter being defined
{
self->objectType = ObjectType_New(self->connection, param);
if (!self->objectType)
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// ObjectVar_PostDefine()
// Performs additional steps required for defining objects.
//-----------------------------------------------------------------------------
static int ObjectVar_PostDefine(
udt_ObjectVar *self) // variable to set up
{
sword status;
status = OCIDefineObject(self->defineHandle,
self->environment->errorHandle, self->objectType->tdo, self->data,
0, self->objectIndicator, 0);
return Environment_CheckForError(self->environment, status,
"ObjectVar_PostDefine(): define object");
}
//-----------------------------------------------------------------------------
// ObjectVar_IsNull()
// Returns a boolean indicating if the variable is null or not.
//-----------------------------------------------------------------------------
static int ObjectVar_IsNull(
udt_ObjectVar *self, // variable to set up
unsigned pos) // position to check
{
if (!self->objectIndicator[pos])
return 1;
return (*((OCIInd*) self->objectIndicator[pos]) == OCI_IND_NULL);
}
//-----------------------------------------------------------------------------
// ObjectVar_GetValue()
// Returns the value stored at the given array position.
//-----------------------------------------------------------------------------
static PyObject *ObjectVar_GetValue(
udt_ObjectVar *self, // variable to determine value for
unsigned pos) // array position
{
PyObject *var;
// only allowed to get the value once (for now)
if (!self->data[pos]) {
PyErr_SetString(g_ProgrammingErrorException,
"variable value can only be acquired once");
return NULL;
}
// for collections, return the list rather than the object
if (self->objectType->isCollection)
return ExternalObjectVar_ConvertCollection(self->environment,
self->data[pos], (PyObject*) self, self->objectType);
// for objects, return a representation of the object
var = ExternalObjectVar_New((PyObject*) self, self->objectType,
self->data[pos], self->objectIndicator[pos], 1);
if (!var)
return NULL;
self->data[pos] = NULL;
self->objectIndicator[pos] = NULL;
return var;
}

11
PKG-INFO Normal file
View File

@ -0,0 +1,11 @@
Metadata-Version: 1.0
Name: cx_Oracle
Version: 4.3.1
Summary: Python interface to Oracle
Home-page: http://starship.python.net/crew/atuining
Author: Anthony Tuininga
Author-email: anthony.tuininga@gmail.com
License: See LICENSE.txt
Description: Python interface to Oracle conforming to the Python DB API 2.0 specification.
See http://www.python.org/topics/database/DatabaseAPI-2.0.html.
Platform: UNKNOWN

57
README.txt Normal file
View File

@ -0,0 +1,57 @@
Open Source Python/Oracle Utility - cx_Oracle
cx_Oracle is a Python extension module that allows access to Oracle and
conforms to the Python database API 2.0 specifications with a few exceptions.
See http://www.python.org/topics/database/DatabaseAPI-2.0.html for more
information on the Python database API specification.
For comments, contact Anthony Tuininga at anthony.tuininga@gmail.com or use the
mailing list at http://lists.sourceforge.net/lists/listinfo/cx-oracle-users
BINARY INSTALL:
Place the file cx_Oracle.pyd or cx_Oracle.so anywhere on your Python path.
SOURCE INSTALL:
This module has been built with Oracle 8.1.7, 9.2.0 and 10.1.0 on Linux,
Solaris, HP/UX, Tru64 Unix and Windows. It will likely build on other
platforms and other Oracle versions but I haven't tried them. Use the provided
setup.py to build and install the module which makes use of the distutils
module. Note that on Windows, I have used mingw32 (http://www.mingw.org) and
the module will not build with MSVC without modification. The commands
required to build and install the module are as follows:
python setup.py build
python setup.py install
USAGE EXAMPLE:
import cx_Oracle
# connect via SQL*Net string or by each segment in a separate argument
#connection = cx_Oracle.connect("user/password@TNS")
connection = cx_Oracle.connect("user", "password", "TNS")
cursor = connection.cursor()
cursor.arraysize = 50
cursor.execute("""
select Col1, Col2, Col3
from SomeTable
where Col4 = :arg_1
and Col5 between :arg_2 and :arg_3""",
arg_1 = "VALUE",
arg_2 = 5,
arg_3 = 15)
for column_1, column_2, column_3 in cursor.fetchall():
print "Values:", column_1, column_2, column_3
EXCEPTIONS:
The only exception to the DB API specification is the lack of a nextset()
method which is not supported by Oracle.
Please see the included documentation for additional information.

483
SessionPool.c Normal file
View File

@ -0,0 +1,483 @@
//-----------------------------------------------------------------------------
// SessionPool.c
// Handles session pooling (only available in Oracle 9i and up).
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// structure for the Python type "SessionPool"
//-----------------------------------------------------------------------------
typedef struct {
PyObject_HEAD
OCISPool *handle;
ub4 minSessions;
ub4 maxSessions;
ub4 sessionIncrement;
ub4 cacheSize;
PyObject *name;
PyObject *username;
PyObject *password;
PyObject *dsn;
udt_Environment *environment;
PyTypeObject *connectionType;
} udt_SessionPool;
//-----------------------------------------------------------------------------
// constants for the OCI attributes
//-----------------------------------------------------------------------------
static ub4 gc_OpenAttribute = OCI_ATTR_SPOOL_OPEN_COUNT;
static ub4 gc_BusyAttribute = OCI_ATTR_SPOOL_BUSY_COUNT;
static ub4 gc_TimeoutAttribute = OCI_ATTR_SPOOL_TIMEOUT;
static ub4 gc_GetModeAttribute = OCI_ATTR_SPOOL_GETMODE;
//-----------------------------------------------------------------------------
// functions for the Python type "SessionPool"
//-----------------------------------------------------------------------------
static PyObject *SessionPool_New(PyTypeObject*, PyObject*, PyObject*);
static int SessionPool_Init(udt_SessionPool*, PyObject*, PyObject*);
static void SessionPool_Free(udt_SessionPool*);
static PyObject *SessionPool_Acquire(udt_SessionPool*, PyObject*);
static PyObject *SessionPool_Drop(udt_SessionPool*, PyObject*);
static PyObject *SessionPool_Release(udt_SessionPool*, PyObject*);
static PyObject *SessionPool_GetOCIAttr(udt_SessionPool*, ub4*);
static int SessionPool_SetOCIAttr(udt_SessionPool*, PyObject*, ub4*);
//-----------------------------------------------------------------------------
// declaration of methods for Python type "SessionPool"
//-----------------------------------------------------------------------------
static PyMethodDef g_SessionPoolMethods[] = {
{ "acquire", (PyCFunction) SessionPool_Acquire, METH_NOARGS },
{ "drop", (PyCFunction) SessionPool_Drop, METH_VARARGS },
{ "release", (PyCFunction) SessionPool_Release, METH_VARARGS },
{ NULL }
};
//-----------------------------------------------------------------------------
// declaration of members for Python type "SessionPool"
//-----------------------------------------------------------------------------
static PyMemberDef g_SessionPoolMembers[] = {
{ "username", T_OBJECT, offsetof(udt_SessionPool, username), READONLY },
{ "password", T_OBJECT, offsetof(udt_SessionPool, password), READONLY },
{ "dsn", T_OBJECT, offsetof(udt_SessionPool, dsn), READONLY },
{ "tnsentry", T_OBJECT, offsetof(udt_SessionPool, dsn), READONLY },
{ "name", T_OBJECT, offsetof(udt_SessionPool, name), READONLY },
{ "max", T_INT, offsetof(udt_SessionPool, maxSessions), READONLY },
{ "min", T_INT, offsetof(udt_SessionPool, minSessions), READONLY },
{ "increment", T_INT, offsetof(udt_SessionPool, sessionIncrement),
READONLY },
{ NULL }
};
//-----------------------------------------------------------------------------
// declaration of calculated members for Python type "SessionPool"
//-----------------------------------------------------------------------------
static PyGetSetDef g_SessionPoolCalcMembers[] = {
{ "opened", (getter) SessionPool_GetOCIAttr, 0, 0, &gc_OpenAttribute },
{ "busy", (getter) SessionPool_GetOCIAttr, 0, 0, &gc_BusyAttribute },
{ "timeout", (getter) SessionPool_GetOCIAttr,
(setter) SessionPool_SetOCIAttr, 0, &gc_TimeoutAttribute },
{ "getmode", (getter) SessionPool_GetOCIAttr,
(setter) SessionPool_SetOCIAttr, 0, &gc_GetModeAttribute },
{ NULL }
};
//-----------------------------------------------------------------------------
// declaration of Python type "SessionPool"
//-----------------------------------------------------------------------------
static PyTypeObject g_SessionPoolType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"OracleSessionPool", // tp_name
sizeof(udt_SessionPool), // tp_basicsize
0, // tp_itemsize
(destructor) SessionPool_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
// tp_flags
0, // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
g_SessionPoolMethods, // tp_methods
g_SessionPoolMembers, // tp_members
g_SessionPoolCalcMembers, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
(initproc) SessionPool_Init, // tp_init
0, // tp_alloc
(newfunc) SessionPool_New, // tp_new
0, // tp_free
0, // tp_is_gc
0 // tp_bases
};
#include "Connection.c"
//-----------------------------------------------------------------------------
// SessionPool_New()
// Create a new session pool object.
//-----------------------------------------------------------------------------
static PyObject *SessionPool_New(
PyTypeObject *type, // type object
PyObject *args, // arguments
PyObject *keywordArgs) // keyword arguments
{
udt_SessionPool *newObject;
// create the object
newObject = (udt_SessionPool*) type->tp_alloc(type, 0);
if (!newObject)
return NULL;
newObject->environment = NULL;
return (PyObject*) newObject;
}
//-----------------------------------------------------------------------------
// SessionPool_Init()
// Initialize the session pool object.
//-----------------------------------------------------------------------------
static int SessionPool_Init(
udt_SessionPool *self, // session pool object
PyObject *args, // arguments
PyObject *keywordArgs) // keyword arguments
{
unsigned usernameLength, passwordLength, dsnLength, poolNameLength;
const char *username, *password, *dsn, *poolName;
unsigned minSessions, maxSessions, sessionIncrement;
PyTypeObject *connectionType;
PyObject *threadedObj;
int threaded;
sword status;
ub1 getMode;
// define keyword arguments
static char *keywordList[] = { "user", "password", "dsn", "min", "max",
"increment", "connectiontype", "threaded", "getmode", NULL };
// parse arguments and keywords
threaded = 0;
threadedObj = NULL;
connectionType = &g_ConnectionType;
getMode = OCI_SPOOL_ATTRVAL_NOWAIT;
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "s#s#s#iii|OOb",
keywordList, &username, &usernameLength, &password,
&passwordLength, &dsn, &dsnLength, &minSessions,
&maxSessions, &sessionIncrement, &connectionType, &threadedObj,
&getMode))
return -1;
if (!PyType_Check(connectionType)) {
PyErr_SetString(g_ProgrammingErrorException,
"connectiontype must be a type");
return -1;
}
if (!PyType_IsSubtype(connectionType, &g_ConnectionType)) {
PyErr_SetString(g_ProgrammingErrorException,
"connectiontype must be a subclass of Connection");
return -1;
}
if (threadedObj) {
threaded = PyObject_IsTrue(threadedObj);
if (threaded < 0)
return -1;
}
// initialize the object's members
Py_INCREF(connectionType);
self->connectionType = connectionType;
self->minSessions = minSessions;
self->maxSessions = maxSessions;
self->sessionIncrement = sessionIncrement;
// set up the environment
self->environment = Environment_New(threaded);
if (!self->environment)
return -1;
// create the string for the username
self->username = PyString_FromStringAndSize(username, usernameLength);
if (!self->username)
return -1;
// create the string for the password
self->password = PyString_FromStringAndSize(password, passwordLength);
if (!self->password)
return -1;
// create the string for the TNS entry
self->dsn = PyString_FromStringAndSize(dsn, dsnLength);
if (!self->dsn)
return -1;
// create the session pool handle
status = OCIHandleAlloc(self->environment->handle, (dvoid**) &self->handle,
OCI_HTYPE_SPOOL, 0, 0);
if (Environment_CheckForError(self->environment, status,
"SessionPool_New(): allocate handle") < 0)
return -1;
// create the session pool
Py_BEGIN_ALLOW_THREADS
status = OCISessionPoolCreate(self->environment->handle,
self->environment->errorHandle, self->handle,
(OraText**) &poolName, &poolNameLength, (OraText*) dsn, dsnLength,
minSessions, maxSessions, sessionIncrement, (OraText*) username,
usernameLength, (OraText*) password, passwordLength,
OCI_SPC_HOMOGENEOUS | OCI_SPC_STMTCACHE);
Py_END_ALLOW_THREADS
if (Environment_CheckForError(self->environment, status,
"SessionPool_New(): create pool") < 0)
return -1;
// create the string for the pool name
self->name = PyString_FromStringAndSize(poolName, poolNameLength);
if (!self->name)
return -1;
// set the mode on the pool
status = OCIAttrSet(self->handle, OCI_HTYPE_SPOOL, (dvoid*) &getMode, 0,
OCI_ATTR_SPOOL_GETMODE, self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"SessionPool_New(): set wait mode") < 0)
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// SessionPool_Free()
// Deallocate the session pool.
//-----------------------------------------------------------------------------
static void SessionPool_Free(
udt_SessionPool *self) // session pool
{
if (self->handle) {
OCISessionPoolDestroy(self->handle, self->environment->errorHandle,
OCI_SPD_FORCE);
OCIHandleFree(self->handle, OCI_HTYPE_SPOOL);
}
Py_XDECREF(self->name);
Py_XDECREF(self->environment);
Py_XDECREF(self->username);
Py_XDECREF(self->password);
Py_XDECREF(self->dsn);
self->ob_type->tp_free((PyObject*) self);
}
//-----------------------------------------------------------------------------
// SessionPool_IsConnected()
// Determines if the session pool object is connected to the database. If
// not, a Python exception is raised.
//-----------------------------------------------------------------------------
static int SessionPool_IsConnected(
udt_SessionPool *self) // session pool
{
if (!self->handle) {
PyErr_SetString(g_InterfaceErrorException, "not connected");
return -1;
}
return 0;
}
//-----------------------------------------------------------------------------
// SessionPool_Acquire()
// Create a new connection within the session pool.
//-----------------------------------------------------------------------------
static PyObject *SessionPool_Acquire(
udt_SessionPool *self, // session pool
PyObject *args) // arguments
{
PyObject *createArgs, *createKeywordArgs, *result;
// make sure session pool is connected
if (SessionPool_IsConnected(self) < 0)
return NULL;
// create arguments
createArgs = PyTuple_New(0);
if (!createArgs)
return NULL;
createKeywordArgs = PyDict_New();
if (!createKeywordArgs) {
Py_DECREF(createArgs);
return NULL;
}
if (PyDict_SetItemString(createKeywordArgs, "pool",
(PyObject*) self) < 0) {
Py_DECREF(createArgs);
Py_DECREF(createKeywordArgs);
return NULL;
}
// create the connection object
result = PyObject_Call( (PyObject*) self->connectionType, createArgs,
createKeywordArgs);
Py_DECREF(createArgs);
Py_DECREF(createKeywordArgs);
return result;
}
//-----------------------------------------------------------------------------
// SessionPool_InternalRelease()
// Internal method used to release a connection back to the pool in order to
// allow for the possibility of dropping the connection.
//-----------------------------------------------------------------------------
static PyObject *SessionPool_InternalRelease(
udt_SessionPool *self, // session pool
PyObject *args, // arguments
ub4 mode) // OCI mode to use
{
udt_Connection *connection;
sword status;
// connection is expected
if (!PyArg_ParseTuple(args, "O!", &g_ConnectionType, &connection))
return NULL;
// make sure session pool is connected
if (SessionPool_IsConnected(self) < 0)
return NULL;
if (connection->sessionPool != self) {
PyErr_SetString(g_ProgrammingErrorException,
"connection not acquired with this session pool");
return NULL;
}
// release the connection
Py_BEGIN_ALLOW_THREADS
status = OCITransRollback(connection->handle,
connection->environment->errorHandle, OCI_DEFAULT);
Py_END_ALLOW_THREADS
if (Environment_CheckForError(connection->environment, status,
"SessionPool_Release(): rollback") < 0)
return NULL;
Py_BEGIN_ALLOW_THREADS
status = OCISessionRelease(connection->handle,
connection->environment->errorHandle, NULL, 0, mode);
Py_END_ALLOW_THREADS
if (Environment_CheckForError(connection->environment, status,
"SessionPool_Release(): release session") < 0)
return NULL;
// ensure that the connection behaves as closed
Py_DECREF(connection->sessionPool);
connection->sessionPool = NULL;
connection->handle = NULL;
Py_INCREF(Py_None);
return Py_None;
}
//-----------------------------------------------------------------------------
// SessionPool_Drop()
// Release a connection back to the session pool, dropping it so that a new
// connection will be created if needed.
//-----------------------------------------------------------------------------
static PyObject *SessionPool_Drop(
udt_SessionPool *self, // session pool
PyObject *args) // arguments
{
return SessionPool_InternalRelease(self, args, OCI_SESSRLS_DROPSESS);
}
//-----------------------------------------------------------------------------
// SessionPool_Release()
// Release a connection back to the session pool.
//-----------------------------------------------------------------------------
static PyObject *SessionPool_Release(
udt_SessionPool *self, // session pool
PyObject *args) // arguments
{
return SessionPool_InternalRelease(self, args, OCI_DEFAULT);
}
//-----------------------------------------------------------------------------
// SessionPool_GetOCIAttr()
// Return the value for the OCI attribute.
//-----------------------------------------------------------------------------
static PyObject *SessionPool_GetOCIAttr(
udt_SessionPool *self, // session pool
ub4 *attribute) // OCI attribute type
{
sword status;
ub4 value;
// make sure session pool is connected
if (SessionPool_IsConnected(self) < 0)
return NULL;
// get the value from the OCI
status = OCIAttrGet(self->handle, OCI_HTYPE_SPOOL, &value, 0, *attribute,
self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"SessionPool_GetOCIAttr()") < 0)
return NULL;
if (*attribute == OCI_ATTR_SPOOL_GETMODE)
return PyInt_FromLong((ub1) value);
return PyInt_FromLong(value);
}
//-----------------------------------------------------------------------------
// SessionPool_SetOCIAttr()
// Set the value of the OCI attribute.
//-----------------------------------------------------------------------------
static int SessionPool_SetOCIAttr(
udt_SessionPool *self, // session pool
PyObject *value, // value to set
ub4 *attribute) // OCI attribute type
{
ub4 ociValue;
sword status;
// make sure session pool is connected
if (SessionPool_IsConnected(self) < 0)
return -1;
// set the value in the OCI
if (!PyInt_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an integer");
return -1;
}
ociValue = PyInt_AS_LONG(value);
status = OCIAttrSet(self->handle, OCI_HTYPE_SPOOL, &ociValue, 0,
*attribute, self->environment->errorHandle);
if (Environment_CheckForError(self->environment, status,
"SessionPool_SetOCIAttr()") < 0)
return -1;
return 0;
}

323
StringVar.c Normal file
View File

@ -0,0 +1,323 @@
//-----------------------------------------------------------------------------
// StringVar.c
// Defines the routines specific to the string type.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// String type
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
char *data;
ub1 charsetForm;
ub2 charsetId;
} udt_StringVar;
//-----------------------------------------------------------------------------
// Declaration of string variable functions.
//-----------------------------------------------------------------------------
static int StringVar_Initialize(udt_StringVar*, udt_Cursor*);
static int StringVar_PreDefine(udt_StringVar*, OCIParam*);
static int StringVar_SetValue(udt_StringVar*, unsigned, PyObject*);
static PyObject *StringVar_GetValue(udt_StringVar*, unsigned);
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
static PyTypeObject g_StringVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.STRING", // tp_name
sizeof(udt_StringVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
static PyTypeObject g_FixedCharVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.FIXED_CHAR", // tp_name
sizeof(udt_StringVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
static PyTypeObject g_RowidVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.ROWID", // tp_name
sizeof(udt_StringVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
static PyTypeObject g_BinaryVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.BINARY", // tp_name
sizeof(udt_StringVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
static udt_VariableType vt_String = {
(InitializeProc) StringVar_Initialize,
(FinalizeProc) NULL,
(PreDefineProc) StringVar_PreDefine,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) StringVar_SetValue,
(GetValueProc) StringVar_GetValue,
&g_StringVarType, // Python type
SQLT_CHR, // Oracle type
SQLCS_IMPLICIT, // charset form
MAX_STRING_CHARS, // element length (default)
1, // is variable length
1, // can be copied
1 // can be in array
};
static udt_VariableType vt_NationalCharString = {
(InitializeProc) StringVar_Initialize,
(FinalizeProc) NULL,
(PreDefineProc) StringVar_PreDefine,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) StringVar_SetValue,
(GetValueProc) StringVar_GetValue,
&g_StringVarType, // Python type
SQLT_CHR, // Oracle type
SQLCS_NCHAR, // charset form
MAX_STRING_CHARS, // element length (default)
1, // is variable length
1, // can be copied
1 // can be in array
};
static udt_VariableType vt_FixedChar = {
(InitializeProc) StringVar_Initialize,
(FinalizeProc) NULL,
(PreDefineProc) StringVar_PreDefine,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) StringVar_SetValue,
(GetValueProc) StringVar_GetValue,
&g_FixedCharVarType, // Python type
SQLT_AFC, // Oracle type
SQLCS_IMPLICIT, // charset form
2000, // element length (default)
1, // is variable length
1, // can be copied
1 // can be in array
};
static udt_VariableType vt_Rowid = {
(InitializeProc) StringVar_Initialize,
(FinalizeProc) NULL,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) StringVar_SetValue,
(GetValueProc) StringVar_GetValue,
&g_RowidVarType, // Python type
SQLT_CHR, // Oracle type
SQLCS_IMPLICIT, // charset form
18, // element length (default)
0, // is variable length
1, // can be copied
1 // can be in array
};
static udt_VariableType vt_Binary = {
(InitializeProc) StringVar_Initialize,
(FinalizeProc) NULL,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) StringVar_SetValue,
(GetValueProc) StringVar_GetValue,
&g_BinaryVarType, // Python type
SQLT_BIN, // Oracle type
SQLCS_IMPLICIT, // charset form
MAX_STRING_CHARS, // element length (default)
1, // is variable length
1, // can be copied
1 // can be in array
};
//-----------------------------------------------------------------------------
// StringVar_Initialize()
// Initialize the variable.
//-----------------------------------------------------------------------------
static int StringVar_Initialize(
udt_StringVar *var, // variable to initialize
udt_Cursor *cursor) // cursor to use
{
var->actualLength = (ub2*) PyMem_Malloc(var->allocatedElements *
sizeof(ub2));
if (!var->actualLength) {
PyErr_NoMemory();
return -1;
}
return 0;
}
//-----------------------------------------------------------------------------
// StringVar_PreDefine()
// Set the character set information when values are fetched from this
// variable.
//-----------------------------------------------------------------------------
static int StringVar_PreDefine(
udt_StringVar *var, // variable to initialize
OCIParam *param) // parameter handle
{
sword status;
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &var->charsetForm,
0, OCI_ATTR_CHARSET_FORM, var->environment->errorHandle);
if (Environment_CheckForError(var->environment, status,
"StringVar_PreDefine(): getting charset form") < 0)
return -1;
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &var->charsetId, 0,
OCI_ATTR_CHARSET_ID, var->environment->errorHandle);
if (Environment_CheckForError(var->environment, status,
"StringVar_PreDefine(): getting charset id") < 0)
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// StringVar_SetValue()
// Set the value of the variable.
//-----------------------------------------------------------------------------
static int StringVar_SetValue(
udt_StringVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
Py_ssize_t bufferSize;
const void *buffer;
// get the buffer data and size for binding
if (PyString_Check(value)) {
buffer = PyString_AS_STRING(value);
bufferSize = PyString_GET_SIZE(value);
} else if (PyBuffer_Check(value)) {
if (PyObject_AsReadBuffer(value, &buffer, &bufferSize) < 0)
return -1;
} else {
PyErr_SetString(PyExc_TypeError, "expecting string or buffer data");
return -1;
}
// ensure that the buffer is not too large
if (bufferSize > var->maxLength) {
if (bufferSize > var->environment->maxStringBytes) {
PyErr_SetString(PyExc_ValueError, "string data too large");
return -1;
}
if (Variable_Resize( (udt_Variable*) var, bufferSize) < 0)
return -1;
}
// keep a copy of the string
var->actualLength[pos] = (ub2) bufferSize;
if (bufferSize)
memcpy(var->data + var->maxLength * pos, buffer, bufferSize);
return 0;
}
//-----------------------------------------------------------------------------
// StringVar_GetValue()
// Returns the value stored at the given array position.
//-----------------------------------------------------------------------------
static PyObject *StringVar_GetValue(
udt_StringVar *var, // variable to determine value for
unsigned pos) // array position
{
return PyString_FromStringAndSize(var->data + pos * var->maxLength,
var->actualLength[pos]);
}

238
TimestampVar.c Normal file
View File

@ -0,0 +1,238 @@
//-----------------------------------------------------------------------------
// TimestampVar.c
// Defines the routines for handling timestamp variables.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Timestamp type
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
OCIDateTime **data;
} udt_TimestampVar;
//-----------------------------------------------------------------------------
// Declaration of date/time variable functions.
//-----------------------------------------------------------------------------
static int TimestampVar_Initialize(udt_TimestampVar*, udt_Cursor*);
static void TimestampVar_Finalize(udt_TimestampVar*);
static int TimestampVar_SetValue(udt_TimestampVar*, unsigned, PyObject*);
static PyObject *TimestampVar_GetValue(udt_TimestampVar*, unsigned);
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
static PyTypeObject g_TimestampVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.TIMESTAMP", // tp_name
sizeof(udt_TimestampVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
static udt_VariableType vt_Timestamp = {
(InitializeProc) TimestampVar_Initialize,
(FinalizeProc) TimestampVar_Finalize,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) TimestampVar_SetValue,
(GetValueProc) TimestampVar_GetValue,
&g_TimestampVarType, // Python type
SQLT_TIMESTAMP, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCIDateTime*), // element length (default)
0, // is variable length
1, // can be copied
1 // can be in array
};
//-----------------------------------------------------------------------------
// TimestampVar_Initialize()
// Initialize the variable.
//-----------------------------------------------------------------------------
static int TimestampVar_Initialize(
udt_TimestampVar *var, // variable to initialize
udt_Cursor *cursor) // cursor variable associated with
{
sword status;
ub4 i;
// initialize the LOB locators
for (i = 0; i < var->allocatedElements; i++) {
status = OCIDescriptorAlloc(var->environment->handle,
(dvoid**) &var->data[i], OCI_DTYPE_TIMESTAMP, 0, 0);
if (Environment_CheckForError(var->environment, status,
"TimestampVar_Initialize()") < 0)
return -1;
}
return 0;
}
//-----------------------------------------------------------------------------
// TimestampVar_Finalize()
// Prepare for variable destruction.
//-----------------------------------------------------------------------------
static void TimestampVar_Finalize(
udt_TimestampVar *var) // variable to free
{
ub4 i;
for (i = 0; i < var->allocatedElements; i++) {
if (var->data[i])
OCIDescriptorFree(var->data[i], OCI_DTYPE_TIMESTAMP);
}
}
#ifdef NATIVE_DATETIME
//-----------------------------------------------------------------------------
// TimestampVar_SetValue()
// Set the value of the variable.
//-----------------------------------------------------------------------------
static int TimestampVar_SetValue(
udt_TimestampVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
sword status;
uword valid;
// make sure a timestamp is being bound
if (!PyDateTime_Check(value)) {
PyErr_SetString(PyExc_TypeError, "expecting timestamp data");
return -1;
}
// store a copy of the value
status = OCIDateTimeConstruct(var->environment->handle,
var->environment->errorHandle, var->data[pos],
(sb2) PyDateTime_GET_YEAR(value),
PyDateTime_GET_MONTH(value),
PyDateTime_GET_DAY(value),
PyDateTime_DATE_GET_HOUR(value),
PyDateTime_DATE_GET_MINUTE(value),
PyDateTime_DATE_GET_SECOND(value),
PyDateTime_DATE_GET_MICROSECOND(value) * 1000, NULL, 0);
if (Environment_CheckForError(var->environment, status,
"TimestampVar_SetValue(): create structure") < 0)
return -1;
status = OCIDateTimeCheck(var->environment->handle,
var->environment->errorHandle, var->data[pos], &valid);
if (Environment_CheckForError(var->environment, status,
"TimestampVar_SetValue()") < 0)
return -1;
if (valid != 0) {
PyErr_SetString(g_DataErrorException, "invalid date");
return -1;
}
return 0;
}
#else
//-----------------------------------------------------------------------------
// TimestampVar_SetValue()
// Set the value of the variable.
//-----------------------------------------------------------------------------
static int TimestampVar_SetValue(
udt_TimestampVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
udt_ExternalDateTimeVar *dateValue;
sword status;
uword valid;
// make sure a date is being bound
if (value->ob_type != &g_ExternalDateTimeVarType) {
PyErr_SetString(PyExc_TypeError, "expecting date data");
return -1;
}
// store a copy of the value
dateValue = (udt_ExternalDateTimeVar*) value;
status = OCIDateTimeConstruct(var->environment->handle,
var->environment->errorHandle, var->data[pos],
dateValue->year, dateValue->month, dateValue->day, dateValue->hour,
dateValue->minute, dateValue->second, dateValue->fsecond * 1000,
NULL, 0);
if (Environment_CheckForError(var->environment, status,
"TimestampVar_SetValue(): create structure") < 0)
return -1;
status = OCIDateTimeCheck(var->environment->handle,
var->environment->errorHandle, var->data[pos], &valid);
if (Environment_CheckForError(var->environment, status,
"TimestampVar_SetValue()") < 0)
return -1;
if (valid != 0) {
PyErr_SetString(g_DataErrorException, "invalid date");
return -1;
}
return 0;
}
#endif
//-----------------------------------------------------------------------------
// TimestampVar_GetValue()
// Returns the value stored at the given array position.
//-----------------------------------------------------------------------------
static PyObject *TimestampVar_GetValue(
udt_TimestampVar *var, // variable to determine value for
unsigned pos) // array position
{
ub1 hour, minute, second, month, day;
sword status;
ub4 fsecond;
sb2 year;
status = OCIDateTimeGetDate(var->environment->handle,
var->environment->errorHandle, var->data[pos], &year, &month,
&day);
if (Environment_CheckForError(var->environment, status,
"TimestampVar_GetValue(): date portion") < 0)
return NULL;
status = OCIDateTimeGetTime(var->environment->handle,
var->environment->errorHandle, var->data[pos], &hour, &minute,
&second, &fsecond);
if (Environment_CheckForError(var->environment, status,
"TimestampVar_GetValue(): time portion") < 0)
return NULL;
#ifdef NATIVE_DATETIME
return PyDateTime_FromDateAndTime(year, month, day, hour, minute, second,
fsecond / 1000);
#else
return ExternalDateTimeVar_NewFromC(&g_ExternalDateTimeVarType, year,
month, day, hour, minute, second, fsecond / 1000);
#endif
}

55
Transforms.c Normal file
View File

@ -0,0 +1,55 @@
//-----------------------------------------------------------------------------
// Transforms.c
// Provides methods for transforming Oracle data to Python objects or for
// setting Oracle data from Python objects.
//-----------------------------------------------------------------------------
#ifdef NATIVE_DATETIME
static udt_VariableType vt_Date;
#endif
//-----------------------------------------------------------------------------
// OracleDateToPythonDate()
// Return a Python date object given an Oracle date.
//-----------------------------------------------------------------------------
static PyObject *OracleDateToPythonDate(
udt_VariableType *varType, // variable type
OCIDate* value) // value to convert
{
ub1 hour, minute, second, month, day;
sb2 year;
OCIDateGetDate(value, &year, &month, &day);
OCIDateGetTime(value, &hour, &minute, &second);
#ifdef NATIVE_DATETIME
if (varType == &vt_Date)
return PyDate_FromDate(year, month, day);
return PyDateTime_FromDateAndTime(year, month, day, hour, minute, second,
0);
#else
return ExternalDateTimeVar_NewFromC(&g_ExternalDateTimeVarType, year,
month, day, hour, minute, second, 0);
#endif
}
//-----------------------------------------------------------------------------
// OracleNumberToPythonFloat()
// Return a Python date object given an Oracle date.
//-----------------------------------------------------------------------------
static PyObject *OracleNumberToPythonFloat(
udt_Environment *environment, // environment
OCINumber* value) // value to convert
{
double doubleValue;
sword status;
status = OCINumberToReal(environment->errorHandle,
value, sizeof(double), (dvoid*) &doubleValue);
if (Environment_CheckForError(environment, status,
"OracleNumberToPythonFloat()") < 0)
return NULL;
return PyFloat_FromDouble(doubleValue);
}

1204
Variable.c Normal file

File diff suppressed because it is too large Load Diff

472
cx_Oracle.c Normal file
View File

@ -0,0 +1,472 @@
//-----------------------------------------------------------------------------
// cx_Oracle.c
// Shared library for use by Python.
//-----------------------------------------------------------------------------
#include <Python.h>
#include <structmember.h>
#include <time.h>
#include <oci.h>
#include <orid.h>
#include <xa.h>
// define whether or not we are building Oracle 9i
#ifdef OCI_ATTR_MODULE
#define ORACLE_10G
#endif
#if OCI_FNCODE_STMTRELEASE
#define ORACLE_9I
#endif
// define whether or not we are building with the native datetime module
#if (PY_VERSION_HEX >= 0x02040000)
#include <datetime.h>
#define NATIVE_DATETIME
#endif
// PY_LONG_LONG was called LONG_LONG before Python 2.3
#ifndef PY_LONG_LONG
#define PY_LONG_LONG LONG_LONG
#endif
// define Py_ssize_t for versions before Python 2.5
#if PY_VERSION_HEX < 0x02050000
typedef int Py_ssize_t;
#define PY_SSIZE_T_MAX INT_MAX
#define PY_SSIZE_T_MIN INT_MIN
#endif
// define macro for adding OCI constants
#define ADD_OCI_CONSTANT(x) \
if (PyModule_AddIntConstant(module, #x, OCI_ ##x) < 0) \
return;
// define macro for adding type objects
#define ADD_TYPE_OBJECT(name, type) \
Py_INCREF(type); \
if (PyModule_AddObject(module, name, (PyObject*) type) < 0) \
return;
// define macro to get the build version as a string
#define xstr(s) str(s)
#define str(s) #s
#define BUILD_VERSION_STRING xstr(BUILD_VERSION)
//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
#ifdef WITH_THREAD
static PyInterpreterState *g_InterpreterState;
#endif
static PyObject *g_WarningException = NULL;
static PyObject *g_ErrorException = NULL;
static PyObject *g_InterfaceErrorException = NULL;
static PyObject *g_DatabaseErrorException = NULL;
static PyObject *g_DataErrorException = NULL;
static PyObject *g_OperationalErrorException = NULL;
static PyObject *g_IntegrityErrorException = NULL;
static PyObject *g_InternalErrorException = NULL;
static PyObject *g_ProgrammingErrorException = NULL;
static PyObject *g_NotSupportedErrorException = NULL;
static PyTypeObject *g_DateTimeType = NULL;
static PyTypeObject *g_DecimalType = NULL;
//-----------------------------------------------------------------------------
// SetException()
// Create an exception and set it in the provided dictionary.
//-----------------------------------------------------------------------------
static int SetException(
PyObject *module, // module object
PyObject **exception, // exception to create
char *name, // name of the exception
PyObject *baseException) // exception to base exception on
{
char buffer[100];
sprintf(buffer, "cx_Oracle.%s", name);
*exception = PyErr_NewException(buffer, baseException, NULL);
if (!*exception)
return -1;
return PyModule_AddObject(module, name, *exception);
}
//-----------------------------------------------------------------------------
// GetModuleAndName()
// Return the module and name for the type.
//-----------------------------------------------------------------------------
static int GetModuleAndName(
PyTypeObject *type, // type to get module/name for
PyObject **module, // name of module
PyObject **name) // name of type
{
*module = PyObject_GetAttrString( (PyObject*) type, "__module__");
if (!*module)
return -1;
*name = PyObject_GetAttrString( (PyObject*) type, "__name__");
if (!*name) {
Py_DECREF(*module);
return -1;
}
return 0;
}
#include "Environment.c"
#ifdef ORACLE_9I
#include "SessionPool.c"
#else
#include "Connection.c"
#endif
//-----------------------------------------------------------------------------
// MakeDSN()
// Make a data source name given the host port and SID.
//-----------------------------------------------------------------------------
static PyObject* MakeDSN(
PyObject* self, // passthrough argument
PyObject* args) // arguments to function
{
char *host, *sid;
int port;
// parse arguments
if (!PyArg_ParseTuple(args, "sis", &host, &port, &sid))
return NULL;
// return the formatted string
return PyString_FromFormat("(DESCRIPTION=(ADDRESS_LIST=(ADDRESS="
"(PROTOCOL=TCP)(HOST=%s)(PORT=%d)))(CONNECT_DATA=(SID=%s)))",
host, port, sid);
}
//-----------------------------------------------------------------------------
// Time()
// Returns a time value suitable for binding.
//-----------------------------------------------------------------------------
static PyObject* Time(
PyObject* self, // passthrough argument
PyObject* args) // arguments to function
{
PyErr_SetString(g_NotSupportedErrorException,
"Oracle does not support time only variables");
return NULL;
}
//-----------------------------------------------------------------------------
// TimeFromTicks()
// Returns a time value suitable for binding.
//-----------------------------------------------------------------------------
static PyObject* TimeFromTicks(
PyObject* self, // passthrough argument
PyObject* args) // arguments to function
{
PyErr_SetString(g_NotSupportedErrorException,
"Oracle does not support time only variables");
return NULL;
}
#ifndef NATIVE_DATETIME
//-----------------------------------------------------------------------------
// Date()
// Returns a date value suitable for binding.
//-----------------------------------------------------------------------------
static PyObject* Date(
PyObject* self, // passthrough argument
PyObject* args) // arguments to function
{
return ExternalDateTimeVar_New(&g_ExternalDateTimeVarType, args, NULL);
}
#endif
//-----------------------------------------------------------------------------
// DateFromTicks()
// Returns a date value suitable for binding.
//-----------------------------------------------------------------------------
static PyObject* DateFromTicks(
PyObject* self, // passthrough argument
PyObject* args) // arguments to function
{
#ifdef NATIVE_DATETIME
return PyDate_FromTimestamp(args);
#else
struct tm *time;
time_t ticks;
int ticksArg;
if (!PyArg_ParseTuple(args, "i", &ticksArg))
return NULL;
ticks = ticksArg;
time = localtime(&ticks);
if (time == NULL)
return PyErr_SetFromErrno(g_DataErrorException);
return ExternalDateTimeVar_NewFromC(&g_ExternalDateTimeVarType,
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, 0, 0, 0, 0);
#endif
}
//-----------------------------------------------------------------------------
// TimestampFromTicks()
// Returns a date value suitable for binding.
//-----------------------------------------------------------------------------
static PyObject* TimestampFromTicks(
PyObject* self, // passthrough argument
PyObject* args) // arguments to function
{
#ifdef NATIVE_DATETIME
return PyDateTime_FromTimestamp(args);
#else
struct tm *time;
time_t ticks;
int ticksArg;
if (!PyArg_ParseTuple(args, "i", &ticksArg))
return NULL;
ticks = ticksArg;
time = localtime(&ticks);
if (time == NULL)
return PyErr_SetFromErrno(g_DataErrorException);
return ExternalDateTimeVar_NewFromC(&g_ExternalDateTimeVarType,
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
time->tm_hour, time->tm_min, time->tm_sec, 0);
#endif
}
//-----------------------------------------------------------------------------
// Declaration of methods supported by this module
//-----------------------------------------------------------------------------
static PyMethodDef g_ModuleMethods[] = {
{ "makedsn", MakeDSN, METH_VARARGS },
#ifndef NATIVE_DATETIME
{ "Date", Date, METH_VARARGS },
#endif
{ "Time", Time, METH_VARARGS },
{ "DateFromTicks", DateFromTicks, METH_VARARGS },
{ "TimeFromTicks", TimeFromTicks, METH_VARARGS },
{ "TimestampFromTicks", TimestampFromTicks, METH_VARARGS },
{ NULL }
};
//-----------------------------------------------------------------------------
// initcx_Oracle()
// Initialization routine for the shared libary.
//-----------------------------------------------------------------------------
void initcx_Oracle(void)
{
PyThreadState *threadState;
PyObject *module;
// initialize the interpreter state for callbacks
#ifdef WITH_THREAD
PyEval_InitThreads();
threadState = PyThreadState_Swap(NULL);
if (!threadState)
return;
g_InterpreterState = threadState->interp;
PyThreadState_Swap(threadState);
#endif
// manage the use of the datetime module; in Python 2.4 and up, the native
// datetime type is used since a C API is exposed; in all other cases, the
// internal datetime type is used and if the datetime module exists,
// binding to that type is permitted
#ifdef NATIVE_DATETIME
PyDateTime_IMPORT;
if (PyErr_Occurred())
return;
#else
module = PyImport_ImportModule("datetime");
if (module)
g_DateTimeType = (PyTypeObject*) PyObject_GetAttrString(module,
"datetime");
PyErr_Clear();
#endif
// attempt to import the decimal module
module = PyImport_ImportModule("decimal");
if (module)
g_DecimalType = (PyTypeObject*) PyObject_GetAttrString(module,
"Decimal");
PyErr_Clear();
// prepare the types for use by the module
if (PyType_Ready(&g_ConnectionType) < 0)
return;
if (PyType_Ready(&g_CursorType) < 0)
return;
if (PyType_Ready(&g_ErrorType) < 0)
return;
#ifndef NATIVE_DATETIME
if (PyType_Ready(&g_ExternalDateTimeVarType) < 0)
return;
#endif
#ifdef ORACLE_9I
if (PyType_Ready(&g_SessionPoolType) < 0)
return;
if (PyType_Ready(&g_TimestampVarType) < 0)
return;
#endif
if (PyType_Ready(&g_EnvironmentType) < 0)
return;
if (PyType_Ready(&g_ObjectTypeType) < 0)
return;
if (PyType_Ready(&g_ObjectAttributeType) < 0)
return;
if (PyType_Ready(&g_StringVarType) < 0)
return;
if (PyType_Ready(&g_FixedCharVarType) < 0)
return;
if (PyType_Ready(&g_RowidVarType) < 0)
return;
if (PyType_Ready(&g_BinaryVarType) < 0)
return;
if (PyType_Ready(&g_LongStringVarType) < 0)
return;
if (PyType_Ready(&g_LongBinaryVarType) < 0)
return;
if (PyType_Ready(&g_NumberVarType) < 0)
return;
if (PyType_Ready(&g_ExternalLobVarType) < 0)
return;
if (PyType_Ready(&g_DateTimeVarType) < 0)
return;
if (PyType_Ready(&g_CLOBVarType) < 0)
return;
if (PyType_Ready(&g_NCLOBVarType) < 0)
return;
if (PyType_Ready(&g_BLOBVarType) < 0)
return;
if (PyType_Ready(&g_BFILEVarType) < 0)
return;
if (PyType_Ready(&g_CursorVarType) < 0)
return;
if (PyType_Ready(&g_ObjectVarType) < 0)
return;
if (PyType_Ready(&g_ExternalObjectVarType) < 0)
return;
// initialize module and retrieve the dictionary
module = Py_InitModule("cx_Oracle", g_ModuleMethods);
if (!module)
return;
// create exception object and add it to the dictionary
if (SetException(module, &g_WarningException,
"Warning", PyExc_StandardError) < 0)
return;
if (SetException(module, &g_ErrorException,
"Error", PyExc_StandardError) < 0)
return;
if (SetException(module, &g_InterfaceErrorException,
"InterfaceError", g_ErrorException) < 0)
return;
if (SetException(module, &g_DatabaseErrorException,
"DatabaseError", g_ErrorException) < 0)
return;
if (SetException(module, &g_DataErrorException,
"DataError", g_DatabaseErrorException) < 0)
return;
if (SetException(module, &g_OperationalErrorException,
"OperationalError", g_DatabaseErrorException) < 0)
return;
if (SetException(module, &g_IntegrityErrorException,
"IntegrityError", g_DatabaseErrorException) < 0)
return;
if (SetException(module, &g_InternalErrorException,
"InternalError", g_DatabaseErrorException) < 0)
return;
if (SetException(module, &g_ProgrammingErrorException,
"ProgrammingError", g_DatabaseErrorException) < 0)
return;
if (SetException(module, &g_NotSupportedErrorException,
"NotSupportedError", g_DatabaseErrorException) < 0)
return;
// set up the types that are available
ADD_TYPE_OBJECT("Binary", &PyBuffer_Type)
ADD_TYPE_OBJECT("Connection", &g_ConnectionType)
ADD_TYPE_OBJECT("Cursor", &g_CursorType)
#ifdef NATIVE_DATETIME
ADD_TYPE_OBJECT("Timestamp", PyDateTimeAPI->DateTimeType)
ADD_TYPE_OBJECT("Date", PyDateTimeAPI->DateType)
#else
ADD_TYPE_OBJECT("Timestamp", &g_ExternalDateTimeVarType)
#endif
#ifdef ORACLE_9I
ADD_TYPE_OBJECT("SessionPool", &g_SessionPoolType)
#endif
ADD_TYPE_OBJECT("_Error", &g_ErrorType)
// the name "connect" is required by the DB API
ADD_TYPE_OBJECT("connect", &g_ConnectionType)
// create the basic data types for setting input sizes
ADD_TYPE_OBJECT("BINARY", &g_BinaryVarType)
ADD_TYPE_OBJECT("BFILE", &g_BFILEVarType)
ADD_TYPE_OBJECT("BLOB", &g_BLOBVarType)
ADD_TYPE_OBJECT("CLOB", &g_CLOBVarType)
ADD_TYPE_OBJECT("CURSOR", &g_CursorVarType)
ADD_TYPE_OBJECT("OBJECT", &g_ObjectVarType)
#ifdef NATIVE_DATETIME
ADD_TYPE_OBJECT("DATETIME", PyDateTimeAPI->DateTimeType)
#else
ADD_TYPE_OBJECT("DATETIME", &g_ExternalDateTimeVarType)
#endif
ADD_TYPE_OBJECT("FIXED_CHAR", &g_FixedCharVarType)
ADD_TYPE_OBJECT("LOB", &g_ExternalLobVarType)
ADD_TYPE_OBJECT("LONG_BINARY", &g_LongBinaryVarType)
ADD_TYPE_OBJECT("LONG_STRING", &g_LongStringVarType)
ADD_TYPE_OBJECT("NCLOB", &g_NCLOBVarType)
ADD_TYPE_OBJECT("NUMBER", &g_NumberVarType)
ADD_TYPE_OBJECT("ROWID", &g_RowidVarType)
ADD_TYPE_OBJECT("STRING", &g_StringVarType)
#ifdef ORACLE_9I
ADD_TYPE_OBJECT("TIMESTAMP", &g_TimestampVarType)
#endif
// create constants required by Python DB API 2.0
if (PyModule_AddStringConstant(module, "apilevel", "2.0") < 0)
return;
if (PyModule_AddIntConstant(module, "threadsafety", 2) < 0)
return;
if (PyModule_AddStringConstant(module, "paramstyle", "named") < 0)
return;
// add version and build time for easier support
if (PyModule_AddStringConstant(module, "version",
BUILD_VERSION_STRING) < 0)
return;
if (PyModule_AddStringConstant(module, "buildtime",
__DATE__ " " __TIME__) < 0)
return;
// add constants for registering callbacks
ADD_OCI_CONSTANT(SYSDBA)
ADD_OCI_CONSTANT(SYSOPER)
ADD_OCI_CONSTANT(FNCODE_BINDBYNAME)
ADD_OCI_CONSTANT(FNCODE_BINDBYPOS)
ADD_OCI_CONSTANT(FNCODE_DEFINEBYPOS)
ADD_OCI_CONSTANT(FNCODE_STMTEXECUTE)
ADD_OCI_CONSTANT(FNCODE_STMTFETCH)
ADD_OCI_CONSTANT(FNCODE_STMTPREPARE)
ADD_OCI_CONSTANT(UCBTYPE_ENTRY)
ADD_OCI_CONSTANT(UCBTYPE_EXIT)
ADD_OCI_CONSTANT(UCBTYPE_REPLACE)
#ifdef ORACLE_9I
ADD_OCI_CONSTANT(SPOOL_ATTRVAL_WAIT)
ADD_OCI_CONSTANT(SPOOL_ATTRVAL_NOWAIT)
ADD_OCI_CONSTANT(SPOOL_ATTRVAL_FORCEGET)
#endif
}

112
html/about.html Normal file
View File

@ -0,0 +1,112 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="prev" href="node12.html" />
<link rel="parent" href="cx_Oracle.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>About this document ...</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="8. License"
href="node12.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node12.html">8. License</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION0011000000000000000000">
About this document ...</a>
</h1>
<strong>cx_Oracle</strong>,
April 18, 2007, Release 4.3.1
<p> This document was generated using the <a
href="http://saftsack.fs.uni-bayreuth.de/~latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> translator.
</p>
<p> <a
href="http://saftsack.fs.uni-bayreuth.de/~latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> is Copyright &copy;
1993, 1994, 1995, 1996, 1997, <a
href="http://cbl.leeds.ac.uk/nikos/personal.html">Nikos
Drakos</a>, Computer Based Learning Unit, University of
Leeds, and Copyright &copy; 1997, 1998, <a
href="http://www.maths.mq.edu.au/~ross/">Ross
Moore</a>, Mathematics Department, Macquarie University,
Sydney.
</p>
<p> The application of <a
href="http://saftsack.fs.uni-bayreuth.de/~latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> to the Python
documentation has been heavily tailored by Fred L. Drake,
Jr. Original navigation icons were contributed by Christopher
Petrilli.
</p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="8. License"
href="node12.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node12.html">8. License</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

BIN
html/blank.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

323
html/connobj.html Normal file
View File

@ -0,0 +1,323 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="cursorobj.html" />
<link rel="prev" href="module.html" />
<link rel="parent" href="cx_Oracle.html" />
<link rel="next" href="cursorobj.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>2. Connection Objects</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.2 Exceptions"
href="node5.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="3. cursor Objects"
href="cursorobj.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node5.html">1.2 Exceptions</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="cursorobj.html">3. Cursor Objects</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION004000000000000000000"></a><a name="connobj"></a>
<br>
2. Connection Objects
</h1>
<p>
<strong>NOTE</strong>: Any outstanding changes will be rolled back when the connection
object is destroyed or closed.
<p>
<dl><dt><b><tt id='l2h-58' xml:id='l2h-58'>action</tt></b></dt>
<dd>
This write-only attribute sets the action column in the v$session table and
is only available in Oracle 10g.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-59' xml:id='l2h-59' class="function">begin</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
<dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt class="function">begin</tt></b>(</nobr></td>
<td><var></var><big>[</big><var><var>formatId</var>, <var>transactionId</var>,
<var>branchId</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd> Explicitly begin a new transaction. Without parameters, this explicitly
begins a local transaction; otherwise, this explicitly begins a distributed
(global) transaction with the given parameters. See the Oracle documentation
for more details.
<p>
Note that in order to make use of global (distributed) transactions, the
twophase argument to the Connection constructor must be a true value. See the
comments on the Connection constructor for more information (<a href="module.html#module">1</a>).
<p>
<strong>NOTE:</strong> This method is an extension to the DB API definition.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-61' xml:id='l2h-61' class="function">cancel</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Cancel a long-running transaction. This is only effective on non-Windows
platforms.
</dl>
<p>
<dl><dt><b><tt id='l2h-62' xml:id='l2h-62'>clientinfo</tt></b></dt>
<dd>
This write-only attribute sets the client_info column in the v$session table
and is only available in Oracle 10g.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-63' xml:id='l2h-63' class="function">close</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Close the connection now, rather than whenever __del__ is called. The
connection will be unusable from this point forward; an Error exception will
be raised if any operation is attempted with the connection. The same applies
to any cursor objects trying to use the connection.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-64' xml:id='l2h-64' class="function">commit</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Commit any pending transactions to the database.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-65' xml:id='l2h-65' class="function">cursor</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Return a new Cursor object (<a href="cursorobj.html#cursorobj">3</a>) using the connection.
</dl>
<p>
<dl><dt><b><tt id='l2h-66' xml:id='l2h-66'>dsn</tt></b></dt>
<dd>
This read-only attribute returns the TNS entry of the database to which a
connection has been established.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-67' xml:id='l2h-67'>encoding</tt></b></dt>
<dd>
This read-only attribute returns the IANA character set name of the character
set in use by the Oracle client.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-68' xml:id='l2h-68'>maxBytesPerCharacter</tt></b></dt>
<dd>
This read-only attribute returns the maximum number of bytes each character
can use for the client character set.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-69' xml:id='l2h-69'>module</tt></b></dt>
<dd>
This write-only attribute sets the module column in the v$session table and
is only available in Oracle 10g.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-70' xml:id='l2h-70'>nencoding</tt></b></dt>
<dd>
This read-only attribute returns the IANA character set name of the national
character set in use by the Oracle client.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-71' xml:id='l2h-71'>password</tt></b></dt>
<dd>
This read-only attribute returns the password of the user which established
the connection to the database.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-72' xml:id='l2h-72' class="function">prepare</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Prepare the distributed (global) transaction for commit.
<p>
<strong>NOTE:</strong> This method is an extension to the DB API definition.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-73' xml:id='l2h-73' class="function">register</tt></b>(</nobr></td>
<td><var><var>code</var>, <var>when</var>, <var>function</var></var>)</td></tr></table></dt>
<dd>
Register the function as an OCI callback. The code is one of the function
codes defined in the Oracle documentation of which the most common ones are
defined as constants in this module. The when parameter is one of
UCBTYPE_ENTRY, UCBTYPE_EXIT or UCBTYPE_REPLACE. The function is a Python
function which will accept the parameters that the OCI function accepts,
modified as needed to return Python objects that are of some use. Note that
this is a highly experimental method and can cause cx_Oracle to crash if not
used properly. In particular, the OCI does not provide sizing information to
the callback so attempts to access a variable beyond the allocated size will
crash cx_Oracle. Use with caution.
<p>
<strong>NOTE:</strong> This method is an extension to the DB API definition.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-74' xml:id='l2h-74' class="function">rollback</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Rollback any pending transactions.
</dl>
<p>
<dl><dt><b><tt id='l2h-75' xml:id='l2h-75'>tnsentry</tt></b></dt>
<dd>
This read-only attribute returns the TNS entry of the database to which a
connection has been established.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-76' xml:id='l2h-76' class="function">unregister</tt></b>(</nobr></td>
<td><var><var>code</var>, <var>when</var></var>)</td></tr></table></dt>
<dd>
Unregister the function as an OCI callback. The code is one of the function
codes defined in the Oracle documentation of which the most common ones are
defined as constants in this module. The when parameter is one of
UCBTYPE_ENTRY, UCBTYPE_EXIT or UCBTYPE_REPLACE.
<p>
<strong>NOTE:</strong> This method is an extension to the DB API definition.
</dl>
<p>
<dl><dt><b><tt id='l2h-77' xml:id='l2h-77'>username</tt></b></dt>
<dd>
This read-only attribute returns the name of the user which established the
connection to the database.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-78' xml:id='l2h-78'>version</tt></b></dt>
<dd>
This read-only attribute returns the version of the database to which a
connection has been established.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.2 Exceptions"
href="node5.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="3. cursor Objects"
href="cursorobj.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node5.html">1.2 Exceptions</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="cursorobj.html">3. Cursor Objects</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

109
html/contents.html Normal file
View File

@ -0,0 +1,109 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="module.html" />
<link rel="prev" href="front.html" />
<link rel="parent" href="cx_Oracle.html" />
<link rel="next" href="module.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>Contents</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="Front Matter"
href="front.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1. module Interface"
href="module.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="front.html">Front Matter</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="module.html">1. Module Interface</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<br><h2><a name="SECTION002000000000000000000">
Contents</a>
</h2>
<!--Table of Contents-->
<ul class="TofC">
<li><a href="module.html">1. Module Interface</a>
<ul>
<li><a href="node4.html">1.1 Constants</a>
<li><a href="node5.html">1.2 Exceptions</a>
</ul>
<li><a href="connobj.html">2. Connection Objects</a>
<li><a href="cursorobj.html">3. Cursor Objects</a>
<li><a href="varobj.html">4. Variable Objects</a>
<li><a href="sesspool.html">5. SessionPool Objects</a>
<li><a href="lobobj.html">6. LOB Objects</a>
<li><a href="dateobj.html">7. Date Objects</a>
<li><a href="node12.html">8. License</a>
</ul>
<!--End of Table of Contents-->
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="Front Matter"
href="front.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1. module Interface"
href="module.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="front.html">Front Matter</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="module.html">1. Module Interface</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

BIN
html/contents.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

459
html/cursorobj.html Normal file
View File

@ -0,0 +1,459 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="varobj.html" />
<link rel="prev" href="connobj.html" />
<link rel="parent" href="cx_Oracle.html" />
<link rel="next" href="varobj.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>3. Cursor Objects</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="2. connection Objects"
href="connobj.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="4. variable Objects"
href="varobj.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="connobj.html">2. Connection Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="varobj.html">4. Variable Objects</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION005000000000000000000"></a><a name="cursorobj"></a>
<br>
3. Cursor Objects
</h1>
<p>
<dl><dt><b><tt id='l2h-79' xml:id='l2h-79'>arraysize</tt></b></dt>
<dd>
This read-write attribute specifies the number of rows to fetch at a time
internally and is the default number of rows to fetch with the fetchmany()
call. It defaults to 1 meaning to fetch a single row at a time. Note that
this attribute can drastically affect the performance of a query since it
directly affects the number of network round trips that need to be performed.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-80' xml:id='l2h-80'>bindarraysize</tt></b></dt>
<dd>
This read-write attribute specifies the number of rows to bind at a time and
is used when creating variables via setinputsizes() or var(). It defaults to
1 meaning to bind a single row at a time.
<p>
<strong>NOTE:</strong> The DB API definition does not define this attribute.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-81' xml:id='l2h-81' class="function">arrayvar</tt></b>(</nobr></td>
<td><var><var>dataType</var>, <var>value</var>, </var><big>[</big><var><var>size</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Create an array variable associated with the cursor of the given type and
size and return a variable object (<a href="varobj.html#varobj">4</a>). The value is either an
integer specifying the number of elements to allocate or it is a list and
the number of elements allocated is drawn from the size of the list. If the
value is a list, the variable is also set with the contents of the list. If
the size is not specified and the type is a string or binary, 4000 bytes
(maximum allowable by Oracle) is allocated. This is needed for passing arrays
to PL/SQL (in cases where the list might be empty and the type cannot be
determined automatically) or returning arrays from PL/SQL.
<p>
<strong>NOTE:</strong> The DB API definition does not define this method.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-82' xml:id='l2h-82' class="function">bindnames</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Return the list of bind variable names bound to the statement. Note that the
statement must have been prepared first.
<p>
<strong>NOTE:</strong> The DB API definition does not define this method.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-83' xml:id='l2h-83' class="function">callfunc</tt></b>(</nobr></td>
<td><var><var>name</var>, <var>returnType</var>,
</var><big>[</big><var><var>parameters=[]</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Call a function with the given name. The return type is specified in the
same notation as is required by setinputsizes(). The sequence of parameters
must contain one entry for each argument that the function expects.
The result of the call is the return value of the function.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-84' xml:id='l2h-84' class="function">callproc</tt></b>(</nobr></td>
<td><var><var>name</var>, </var><big>[</big><var><var>parameters=[]</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Call a procedure with the given name. The sequence of parameters must contain
one entry for each argument that the procedure expects. The result of the
call is a modified copy of the input sequence. Input parameters are left
untouched; output and input/output parameters are replaced with possibly new
values.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-85' xml:id='l2h-85' class="function">close</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Close the cursor now, rather than whenever __del__ is called. The cursor will
be unusable from this point forward; an Error exception will be raised if any
operation is attempted with the cursor.
</dl>
<p>
<dl><dt><b><tt id='l2h-86' xml:id='l2h-86'>connection</tt></b></dt>
<dd>
This read-only attribute returns a reference to the connection object on
which the cursor was created.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition but it
is mentioned in PEP 249 as an optional extension.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-87' xml:id='l2h-87'>description</tt></b></dt>
<dd>
This read-only attribute is a sequence of 7-item sequences. Each of these
sequences contains information describing one result column: (name, type,
display_size, internal_size, precision, scale, null_ok). This attribute will
be None for operations that do not return rows or if the cursor has not had
an operation invoked via the execute() method yet.
<p>
The type will be one of the type objects defined at the module level.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-88' xml:id='l2h-88' class="function">execute</tt></b>(</nobr></td>
<td><var><var>statement</var>, </var><big>[</big><var><var>parameters</var></var><big>]</big><var>,
<var>**keywordParameters</var></var>)</td></tr></table></dt>
<dd>
Execute a statement against the database. Parameters may be passed as a
dictionary or sequence or as keyword arguments. If the arguments are a
dictionary, the values will be bound by name and if the arguments are a
sequence the values will be bound by position.
<p>
A reference to the statement will be retained by the cursor. If None or the
same string object is passed in again, the cursor will execute that
statement again without performing a prepare or rebinding and redefining.
This is most effective for algorithms where the same statement is used, but
different parameters are bound to it (many times).
<p>
For maximum efficiency when reusing an statement, it is best to use the
setinputsizes() method to specify the parameter types and sizes ahead of
time; in particular, None is assumed to be a string of length 1 so any
values that are later bound as numbers or dates will raise a TypeError
exception.
<p>
If the statement is a query, a list of variable objects (<a href="varobj.html#varobj">4</a>) will
be returned corresponding to the list of variables into which data will be
fetched with the fetchone(), fetchmany() and fetchall() methods; otherwise,
None will be returned.
<p>
<strong>NOTE:</strong> The DB API definition does not define the return value of this
method.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-89' xml:id='l2h-89' class="function">executemany</tt></b>(</nobr></td>
<td><var><var>statement</var>, <var>parameters</var></var>)</td></tr></table></dt>
<dd>
Prepare a statement for execution against a database and then execute it
against all parameter mappings or sequences found in the sequence parameters.
The statement is managed in the same way as the execute() method manages it.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-90' xml:id='l2h-90' class="function">executemanyprepared</tt></b>(</nobr></td>
<td><var><var>numIters</var></var>)</td></tr></table></dt>
<dd>
Execute the previously prepared and bound statement the given number of
times. The variables that are bound must have already been set to their
desired value before this call is made. This method was designed for the
case where optimal performance is required as it comes at the expense of
compatibility with the DB API.
<p>
<strong>NOTE:</strong> The DB API definition does not define this method.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-91' xml:id='l2h-91' class="function">fetchall</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Fetch all (remaining) rows of a query result, returning them as a list of
tuples. An empty list is returned if no more rows are available. Note that
the cursor's arraysize attribute can affect the performance of this
operation, as internally reads from the database are done in batches
corresponding to the arraysize.
<p>
An exception is raised if the previous call to execute() did not produce any
result set or no call was issued yet.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-92' xml:id='l2h-92' class="function">fetchmany</tt></b>(</nobr></td>
<td><var></var><big>[</big><var><var>numRows=cursor.arraysize</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Fetch the next set of rows of a query result, returning a list of tuples. An
empty list is returned if no more rows are available. Note that the cursor's
arraysize attribute can affect the performance of this operation.
<p>
The number of rows to fetch is specified by the parameter. If it is not
given, the cursor's arrysize attribute determines the number of rows to be
fetched. If the number of rows available to be fetched is fewer than the
amount requested, fewer rows will be returned.
<p>
An exception is raised if the previous call to execute() did not produce any
result set or no call was issued yet.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-93' xml:id='l2h-93' class="function">fetchone</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Fetch the next row of a query result set, returning a single tuple or None
when no more data is available.
<p>
An exception is raised if the previous call to execute() did not produce any
result set or no call was issued yet.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-94' xml:id='l2h-94' class="function">fetchraw</tt></b>(</nobr></td>
<td><var></var><big>[</big><var><var>numRows=cursor.arraysize</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Fetch the next set of rows of a query result into the internal buffers of the
defined variables for the cursor. The number of rows actually fetched is
returned. This method was designed for the case where optimal performance is
required as it comes at the expense of compatibility with the DB API.
<p>
An exception is raised if the previous call to execute() did not produce any
result set or no call was issued yet.
<p>
<strong>NOTE:</strong> The DB API definition does not define this method.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-95' xml:id='l2h-95' class="function">__iter__</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Returns the cursor itself to be used as an iterator.
<p>
<strong>NOTE:</strong> This method is an extension to the DB API definition but it
is mentioned in PEP 249 as an optional extension.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-96' xml:id='l2h-96' class="function">next</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Fetch the next row of a query result set, using the same semantics as
the method fetchone().
<p>
<strong>NOTE:</strong> This method is an extension to the DB API definition but it
is mentioned in PEP 249 as an optional extension.
</dl>
<p>
<dl><dt><b><tt id='l2h-97' xml:id='l2h-97'>numbersAsStrings</tt></b></dt>
<dd>
This integer attribute defines whether or not numbers should be returned as
strings rather than integers or floating point numbers. This is useful to get
around the fact that Oracle floating point numbers have considerably greater
precision than C floating point numbers and not require a change to the SQL
being executed.
<p>
<strong>NOTE:</strong> The DB API definition does not define this attribute.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-98' xml:id='l2h-98' class="function">parse</tt></b>(</nobr></td>
<td><var><var>statement</var></var>)</td></tr></table></dt>
<dd>
This can be used to parse a statement without actually executing it (this
step is done automatically by Oracle when a statement is executed).
<p>
<strong>NOTE:</strong> The DB API definition does not define this method.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-99' xml:id='l2h-99' class="function">prepare</tt></b>(</nobr></td>
<td><var><var>statement</var></var>)</td></tr></table></dt>
<dd>
This can be used before a call to execute() to define the statement that will
be executed. When this is done, the prepare phase will not be performed when
the call to execute() is made with None or the same string object as the
statement.
<p>
<strong>NOTE:</strong> The DB API definition does not define this method.
</dl>
<p>
<dl><dt><b><tt id='l2h-100' xml:id='l2h-100'>rowcount</tt></b></dt>
<dd>
This read-only attribute specifies the number of rows that have currently
been fetched from the cursor (for select statements) or that have been
affected by the operation (for insert, update and delete statements).
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-101' xml:id='l2h-101' class="function">setinputsizes</tt></b>(</nobr></td>
<td><var><var>*args</var>, <var>**keywordArgs</var></var>)</td></tr></table></dt>
<dd>
This can be used before a call to execute() to predefine memory areas for the
operation's parameters. Each parameter should be a type object corresponding
to the input that will be used or it should be an integer specifying the
maximum length of a string parameter. Use keyword arguments when binding by
name and positional arguments when binding by position. The singleton None
can be used as a parameter when using positional arguments to indicate that
no space should be reserved for that position.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-102' xml:id='l2h-102' class="function">setoutputsize</tt></b>(</nobr></td>
<td><var><var>size</var>, </var><big>[</big><var><var>column</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
This can be used before a call to execute() to predefine memory areas for the
long columns that will be fetched. The column is specified as an index into
the result sequence. Not specifying the column will set the default size for
all large columns in the cursor.
</dl>
<p>
<dl><dt><b><tt id='l2h-103' xml:id='l2h-103'>statement</tt></b></dt>
<dd>
This read-only attribute provides the string object that was previously
prepared with prepare() or executed with execute().
<p>
<strong>NOTE:</strong> The DB API definition does not define this attribute.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-104' xml:id='l2h-104' class="function">var</tt></b>(</nobr></td>
<td><var><var>dataType</var>, </var><big>[</big><var><var>size</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Create a variable associated with the cursor of the given type and size and
return a variable object (<a href="varobj.html#varobj">4</a>). If the size is not specified and the
type is a string or binary, 4000 bytes (maximum allowable by Oracle) is
allocated; if the size is not specified and the type is a long string or long
binary, 128KB is allocated. This method was designed for use with PL/SQL
in/out variables where the length or type cannot be determined automatically
from the Python object passed in.
<p>
<strong>NOTE:</strong> The DB API definition does not define this method.
</dl>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="2. connection Objects"
href="connobj.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="4. variable Objects"
href="varobj.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="connobj.html">2. Connection Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="varobj.html">4. Variable Objects</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

243
html/cx_Oracle.css Normal file
View File

@ -0,0 +1,243 @@
/*
* The first part of this is the standard CSS generated by LaTeX2HTML,
* with the "empty" declarations removed.
*/
/* Century Schoolbook font is very similar to Computer Modern Math: cmmi */
.math { font-family: "Century Schoolbook", serif; }
.math i { font-family: "Century Schoolbook", serif;
font-weight: bold }
.boldmath { font-family: "Century Schoolbook", serif;
font-weight: bold }
/*
* Implement both fixed-size and relative sizes.
*
* I think these can be safely removed, as it doesn't appear that
* LaTeX2HTML ever generates these, even though these are carried
* over from the LaTeX2HTML stylesheet.
*/
small.xtiny { font-size : xx-small; }
small.tiny { font-size : x-small; }
small.scriptsize { font-size : smaller; }
small.footnotesize { font-size : small; }
big.xlarge { font-size : large; }
big.xxlarge { font-size : x-large; }
big.huge { font-size : larger; }
big.xhuge { font-size : xx-large; }
/*
* Document-specific styles come next;
* these are added for the Python documentation.
*
* Note that the size specifications for the H* elements are because
* Netscape on Solaris otherwise doesn't get it right; they all end up
* the normal text size.
*/
body { color: #000000;
background-color: #ffffff; }
a:link:active { color: #ff0000; }
a:link:hover { background-color: #bbeeff; }
a:visited:hover { background-color: #bbeeff; }
a:visited { color: #551a8b; }
a:link { color: #0000bb; }
h1, h2, h3, h4, h5, h6 { font-family: avantgarde, sans-serif;
font-weight: bold; }
h1 { font-size: 180%; }
h2 { font-size: 150%; }
h3, h4 { font-size: 120%; }
/* These are section titles used in navigation links, so make sure we
* match the section header font here, even it not the weight.
*/
.sectref { font-family: avantgarde, sans-serif; }
/* And the label before the titles in navigation: */
.navlabel { font-size: 85%; }
/* LaTeX2HTML insists on inserting <br> elements into headers which
* are marked with \label. This little bit of CSS magic ensures that
* these elements don't cause spurious whitespace to be added.
*/
h1>br, h2>br, h3>br,
h4>br, h5>br, h6>br { display: none; }
code, tt { font-family: "lucida typewriter", lucidatypewriter,
monospace; }
var { font-family: times, serif;
font-style: italic;
font-weight: normal; }
.Unix { font-variant: small-caps; }
.typelabel { font-family: lucida, sans-serif; }
.navigation td { background-color: #99ccff;
font-weight: bold;
font-family: avantgarde, sans-serif;
font-size: 110%; }
div.warning { background-color: #fffaf0;
border: thin solid black;
padding: 1em;
margin-left: 2em;
margin-right: 2em; }
div.warning .label { font-family: sans-serif;
font-size: 110%;
margin-right: 0.5em; }
div.note { background-color: #fffaf0;
border: thin solid black;
padding: 1em;
margin-left: 2em;
margin-right: 2em; }
div.note .label { margin-right: 0.5em;
font-family: sans-serif; }
address { font-size: 80%; }
.release-info { font-style: italic;
font-size: 80%; }
.titlegraphic { vertical-align: top; }
.verbatim pre { color: #00008b;
font-family: "lucida typewriter", lucidatypewriter,
monospace;
font-size: 90%; }
.verbatim { margin-left: 2em; }
.verbatim .footer { padding: 0.05in;
font-size: 85%;
background-color: #99ccff;
margin-right: 0.5in; }
.grammar { background-color: #99ccff;
margin-right: 0.5in;
padding: 0.05in; }
.grammar-footer { padding: 0.05in;
font-size: 85%; }
.grammartoken { font-family: "lucida typewriter", lucidatypewriter,
monospace; }
.productions { background-color: #bbeeff; }
.productions a:active { color: #ff0000; }
.productions a:link:hover { background-color: #99ccff; }
.productions a:visited:hover { background-color: #99ccff; }
.productions a:visited { color: #551a8b; }
.productions a:link { color: #0000bb; }
.productions table { vertical-align: baseline;
empty-cells: show; }
.productions > table td,
.productions > table th { padding: 2px; }
.productions > table td:first-child,
.productions > table td:last-child {
font-family: "lucida typewriter",
lucidatypewriter,
monospace;
}
/* same as the second selector above, but expressed differently for Opera */
.productions > table td:first-child + td + td {
font-family: "lucida typewriter",
lucidatypewriter,
monospace;
vertical-align: baseline;
}
.productions > table td:first-child + td {
padding-left: 1em;
padding-right: 1em;
}
.productions > table tr { vertical-align: baseline; }
.email { font-family: avantgarde, sans-serif; }
.mailheader { font-family: avantgarde, sans-serif; }
.mimetype { font-family: avantgarde, sans-serif; }
.newsgroup { font-family: avantgarde, sans-serif; }
.url { font-family: avantgarde, sans-serif; }
.file { font-family: avantgarde, sans-serif; }
.guilabel { font-family: avantgarde, sans-serif; }
.realtable { border-collapse: collapse;
border-color: black;
border-style: solid;
border-width: 0px 0px 2px 0px;
empty-cells: show;
margin-left: auto;
margin-right: auto;
padding-left: 0.4em;
padding-right: 0.4em;
}
.realtable tbody { vertical-align: baseline; }
.realtable tfoot { display: table-footer-group; }
.realtable thead { background-color: #99ccff;
border-width: 0px 0px 2px 1px;
display: table-header-group;
font-family: avantgarde, sans-serif;
font-weight: bold;
vertical-align: baseline;
}
.realtable thead :first-child {
border-width: 0px 0px 2px 0px;
}
.realtable thead th { border-width: 0px 0px 2px 1px }
.realtable td,
.realtable th { border-color: black;
border-style: solid;
border-width: 0px 0px 1px 1px;
padding-left: 0.4em;
padding-right: 0.4em;
}
.realtable td:first-child,
.realtable th:first-child {
border-left-width: 0px;
vertical-align: baseline;
}
.center { text-align: center; }
.left { text-align: left; }
.right { text-align: right; }
.refcount-info { font-style: italic; }
.refcount-info .value { font-weight: bold;
color: #006600; }
/*
* Some decoration for the "See also:" blocks, in part inspired by some of
* the styling on Lars Marius Garshol's XSA pages.
* (The blue in the navigation bars is #99CCFF.)
*/
.seealso { background-color: #fffaf0;
border: thin solid black;
padding: 0pt 1em 4pt 1em; }
.seealso > .heading { font-size: 110%;
font-weight: bold; }
/*
* Class 'availability' is used for module availability statements at
* the top of modules.
*/
.availability .platform { font-weight: bold; }
/*
* Additional styles for the distutils package.
*/
.du-command { font-family: monospace; }
.du-option { font-family: avantgarde, sans-serif; }
.du-filevar { font-family: avantgarde, sans-serif;
font-style: italic; }
.du-xxx:before { content: "** ";
font-weight: bold; }
.du-xxx:after { content: " **";
font-weight: bold; }
/*
* Some specialization for printed output.
*/
@media print {
.online-navigation { display: none; }
}

119
html/cx_Oracle.html Normal file
View File

@ -0,0 +1,119 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="front.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>cx_Oracle</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></td>
<td class='online-navigation'><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></td>
<td class='online-navigation'><a rel="next" title="Front Matter"
href="front.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="front.html">Front Matter</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<p>
<div class="titlepage">
<div class='center'>
<h1>cx_Oracle</h1>
<p><b><font size="+2">Anthony Tuininga</font></b></p>
<p>
<strong>Computronix</strong>
<br>
Email: <span class="email">anthony.tuininga@gmail.com</span>
</p>
<p><strong>Release 4.3.1</strong><br />
<strong>April 18, 2007</strong></p>
<p></p>
</div>
</div>
<p>
<p><br /></p><hr class='online-navigation' />
<div class='online-navigation'>
<!--Table of Child-Links-->
<a name="CHILD_LINKS"></a>
<ul class="ChildLinks">
<li><a href="front.html">Front Matter</a>
<li><a href="contents.html">Contents</a>
<li><a href="module.html">1. Module Interface</a>
<ul>
<li><a href="node4.html">1.1 Constants</a>
<li><a href="node5.html">1.2 Exceptions</a>
</ul>
<li><a href="connobj.html">2. Connection Objects</a>
<li><a href="cursorobj.html">3. Cursor Objects</a>
<li><a href="varobj.html">4. Variable Objects</a>
<li><a href="sesspool.html">5. SessionPool Objects</a>
<li><a href="lobobj.html">6. LOB Objects</a>
<li><a href="dateobj.html">7. Date Objects</a>
<li><a href="node12.html">8. License</a>
<li><a href="about.html">About this document ...</a>
</ul>
<!--End of Table of Child-Links-->
</div>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></td>
<td class='online-navigation'><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></td>
<td class='online-navigation'><a rel="next" title="Front Matter"
href="front.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="front.html">Front Matter</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

148
html/dateobj.html Normal file
View File

@ -0,0 +1,148 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="node12.html" />
<link rel="prev" href="lobobj.html" />
<link rel="parent" href="cx_Oracle.html" />
<link rel="next" href="node12.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>7. Date Objects</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="6. lob Objects"
href="lobobj.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="8. License"
href="node12.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="lobobj.html">6. LOB Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node12.html">8. License</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION009000000000000000000"></a><a name="dateobj"></a>
<br>
7. Date Objects
</h1>
<p>
<strong>NOTE</strong>: This object is an extension the DB API. It is returned whenever
Oracle date and timestamp (in Oracle 9i) columns are fetched and whenever the
constructor methods (Date(), Time(), Timestamp()) are called.
<p>
<strong>NOTE</strong>: As of Python 2.4 cx_Oracle returns the datetime objects from the
standard library datetime module instead of these objects.
<p>
<dl><dt><b><tt id='l2h-130' xml:id='l2h-130'>year</tt></b></dt>
<dd>
This read-only attribute returns the year.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-131' xml:id='l2h-131'>month</tt></b></dt>
<dd>
This read-only attribute returns the month.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-132' xml:id='l2h-132'>day</tt></b></dt>
<dd>
This read-only attribute returns the day.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-133' xml:id='l2h-133'>hour</tt></b></dt>
<dd>
This read-only attribute returns the hour.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-134' xml:id='l2h-134'>minute</tt></b></dt>
<dd>
This read-only attribute returns the minute.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-135' xml:id='l2h-135'>second</tt></b></dt>
<dd>
This read-only attribute returns the second.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-136' xml:id='l2h-136'>fsecond</tt></b></dt>
<dd>
This read-only attribute returns the fractional second.
</dd></dl>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="6. lob Objects"
href="lobobj.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="8. License"
href="node12.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="lobobj.html">6. LOB Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node12.html">8. License</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

120
html/front.html Normal file
View File

@ -0,0 +1,120 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="contents.html" />
<link rel="prev" href="cx_Oracle.html" />
<link rel="parent" href="cx_Oracle.html" />
<link rel="next" href="contents.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>Front Matter</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="cx_Oracle"
href="cx_Oracle.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="Contents"
href="contents.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="contents.html">Contents</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION001000000000000000000"></a><a name="front"></a>
<br>
Front Matter
</h1>
<p>
Copyright © 2001-2007 Computronix.
All rights reserved.
<p>
See the end of this document for complete license and permissions
information.
<p>
<h3>Abstract:</h3>
<div class="ABSTRACT">
<p>
cx_Oracle is a Python extension module that allows access to Oracle and
conforms to the Python database API 2.0 specifications with a few exceptions.
See <a class="url" href="http://www.python.org/topics/database/DatabaseAPI-2.0.html">http://www.python.org/topics/database/DatabaseAPI-2.0.html</a> for more
information on the Python database API specification.
<p>
</div>
<p>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="cx_Oracle"
href="cx_Oracle.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="Contents"
href="contents.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="contents.html">Contents</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

119
html/index.html Normal file
View File

@ -0,0 +1,119 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="front.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>cx_Oracle</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></td>
<td class='online-navigation'><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></td>
<td class='online-navigation'><a rel="next" title="Front Matter"
href="front.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="front.html">Front Matter</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<p>
<div class="titlepage">
<div class='center'>
<h1>cx_Oracle</h1>
<p><b><font size="+2">Anthony Tuininga</font></b></p>
<p>
<strong>Computronix</strong>
<br>
Email: <span class="email">anthony.tuininga@gmail.com</span>
</p>
<p><strong>Release 4.3.1</strong><br />
<strong>April 18, 2007</strong></p>
<p></p>
</div>
</div>
<p>
<p><br /></p><hr class='online-navigation' />
<div class='online-navigation'>
<!--Table of Child-Links-->
<a name="CHILD_LINKS"></a>
<ul class="ChildLinks">
<li><a href="front.html">Front Matter</a>
<li><a href="contents.html">Contents</a>
<li><a href="module.html">1. Module Interface</a>
<ul>
<li><a href="node4.html">1.1 Constants</a>
<li><a href="node5.html">1.2 Exceptions</a>
</ul>
<li><a href="connobj.html">2. Connection Objects</a>
<li><a href="cursorobj.html">3. Cursor Objects</a>
<li><a href="varobj.html">4. Variable Objects</a>
<li><a href="sesspool.html">5. SessionPool Objects</a>
<li><a href="lobobj.html">6. LOB Objects</a>
<li><a href="dateobj.html">7. Date Objects</a>
<li><a href="node12.html">8. License</a>
<li><a href="about.html">About this document ...</a>
</ul>
<!--End of Table of Child-Links-->
</div>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></td>
<td class='online-navigation'><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></td>
<td class='online-navigation'><a rel="next" title="Front Matter"
href="front.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="front.html">Front Matter</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

BIN
html/index.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

169
html/lobobj.html Normal file
View File

@ -0,0 +1,169 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="dateobj.html" />
<link rel="prev" href="sesspool.html" />
<link rel="parent" href="cx_Oracle.html" />
<link rel="next" href="dateobj.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>6. LOB Objects</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="5. sessionpool Objects"
href="sesspool.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="7. date Objects"
href="dateobj.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="sesspool.html">5. SessionPool Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="dateobj.html">7. Date Objects</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION008000000000000000000"></a><a name="lobobj"></a>
<br>
6. LOB Objects
</h1>
<p>
<strong>NOTE</strong>: This object is an extension the DB API. It is returned whenever
Oracle CLOB, BLOB and BFILE columns are fetched.
<p>
<strong>NOTE</strong>: Internally, Oracle uses LOB locators which are allocated based
on the cursor array size. Thus, it is important that the data in the LOB object
be manipulated before another internal fetch takes place. The safest way to do
this is to use the cursor as an iterator. In particular, do not use the
fetchall() method. The exception "LOB variable no longer valid after
subsequent fetch" will be raised if an attempt to access a LOB variable after
a subsequent fetch is detected.
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-123' xml:id='l2h-123' class="function">fileexists</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Return a boolean indicating if the file referenced by the BFILE type LOB
exists.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-124' xml:id='l2h-124' class="function">getfilename</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Return a two-tuple consisting of the directory alias and file name for a
BFILE type LOB.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-125' xml:id='l2h-125' class="function">read</tt></b>(</nobr></td>
<td><var></var><big>[</big><var><var>offset = 1</var>, </var><big>[</big><var><var>amount</var></var><big>]</big><var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Return a portion (or all) of the data in the LOB object.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-126' xml:id='l2h-126' class="function">setfilename</tt></b>(</nobr></td>
<td><var><var>dirAlias</var>, <var>name</var></var>)</td></tr></table></dt>
<dd>
Set the directory alias and name of the BFILE type LOB.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-127' xml:id='l2h-127' class="function">size</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Returns the size of the data in the LOB object.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-128' xml:id='l2h-128' class="function">trim</tt></b>(</nobr></td>
<td><var></var><big>[</big><var><var>newSize = 0</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Trim the LOB to the new size.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-129' xml:id='l2h-129' class="function">write</tt></b>(</nobr></td>
<td><var><var>data</var>, </var><big>[</big><var><var>offset = 1</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Write the data to the LOB object at the given offset. Note that if you want
to make the LOB value smaller, you must use the trim() function.
</dl>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="5. sessionpool Objects"
href="sesspool.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="7. date Objects"
href="dateobj.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="sesspool.html">5. SessionPool Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="dateobj.html">7. Date Objects</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

256
html/module.html Normal file
View File

@ -0,0 +1,256 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="connobj.html" />
<link rel="prev" href="contents.html" />
<link rel="parent" href="cx_Oracle.html" />
<link rel="next" href="node4.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>1. Module Interface</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="Contents"
href="contents.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1 Constants"
href="node4.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="contents.html">Contents</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node4.html">1.1 Constants</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION003000000000000000000"></a><a name="module"></a>
<br>
1. Module Interface
</h1>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-1' xml:id='l2h-1' class="function">Binary</tt></b>(</nobr></td>
<td><var><var>string</var></var>)</td></tr></table></dt>
<dd>
Construct an object holding a binary (long) string value.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-2' xml:id='l2h-2' class="function">Connection</tt></b>(</nobr></td>
<td><var></var><big>[</big><var><var>user</var>, <var>password</var>,
<var>dsn</var>, <var>mode</var>, <var>handle</var>, <var>pool</var>, <var>threaded</var>,
<var>twophase</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
<dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt class="function">connect</tt></b>(</nobr></td>
<td><var></var><big>[</big><var><var>user</var>, <var>password</var>,
<var>dsn</var>, <var>mode</var>, <var>handle</var>, <var>pool</var>, <var>threaded</var>,
<var>twophase</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd> Constructor for creating a connection to the database. Return a Connection
object (<a href="connobj.html#connobj">2</a>). All arguments are optional and can be specified as
keyword parameters. The dsn (data source name) is the TNS entry (from the
Oracle names server or tnsnames.ora file) or is a string like the one
returned from makedsn(). If only one parameter is passed, a connect string is
assumed which is to be of the format "user/password@dsn", the same format
accepted by Oracle applications such as SQL*Plus. If the mode is specified,
it must be one of SYSDBA or SYSOPER which are defined at the module level;
otherwise it defaults to the normal mode of connecting. If the handle is
specified, it must be of type OCISvcCtx* and is only of use when embedding
Python in an application (like PowerBuilder) which has already made the
connection. The pool is only valid in Oracle 9i and is a session pool object
(<a href="sesspool.html#sesspool">5</a>) which is the equivalent of calling pool.acquire(). The
threaded attribute is expected to be a boolean expression which indicates
whether or not Oracle should use the mode OCI_THREADED to wrap accesses to
connections with a mutex. Doing so in single threaded applications imposes
a performance penalty of about 10-15% which is why the default is False.
The twophase attribute is expected to be a boolean expression which indicates
whether or not the attributes should be set on the connection object to allow
for two phase commit. The default for this value is also False because of
bugs in Oracle prior to Oracle 10g.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-4' xml:id='l2h-4' class="function">Cursor</tt></b>(</nobr></td>
<td><var><var>connection</var></var>)</td></tr></table></dt>
<dd>
Constructor for creating a cursor. Return a new Cursor object
(<a href="cursorobj.html#cursorobj">3</a>) using the connection.
<p>
<strong>NOTE:</strong> This method is an extension to the DB API definition.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-5' xml:id='l2h-5' class="function">Date</tt></b>(</nobr></td>
<td><var><var>year</var>, <var>month</var>, <var>day</var></var>)</td></tr></table></dt>
<dd>
Construct an object holding a date value.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-6' xml:id='l2h-6' class="function">DateFromTicks</tt></b>(</nobr></td>
<td><var><var>ticks</var></var>)</td></tr></table></dt>
<dd>
Construct an object holding a date value from the given ticks value (number
of seconds since the epoch; see the documentation of the standard Python
time module for details).
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-7' xml:id='l2h-7' class="function">makedsn</tt></b>(</nobr></td>
<td><var><var>host</var>, <var>port</var>, <var>sid</var></var>)</td></tr></table></dt>
<dd>
Return a string suitable for use as the dsn for the connect() method. This
string is identical to the strings that are defined by the Oracle names
server or defined in the tnsnames.ora file.
<p>
<strong>NOTE:</strong> This method is an extension to the DB API definition.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-8' xml:id='l2h-8' class="function">SessionPool</tt></b>(</nobr></td>
<td><var><var>user</var>, <var>password</var>, <var>database</var>,
<var>min</var>, <var>max</var>, <var>increment</var>, </var><big>[</big><var><var>connectiontype</var>,
<var>threaded</var>, <var>getmode=cx_Oracle.SPOOL_ATTRVAL_NOWAIT</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Create a session pool (see Oracle 9i documentation for more information)
and return a session pool object (<a href="sesspool.html#sesspool">5</a>). This allows for very
fast connections to the database and is of primary use in a server where
the same connection is being made multiple times in rapid succession (a
web server, for example). If the connection type is specified, all calls to
acquire() will create connection objects of that type, rather than the base
type defined at the module level. The threaded attribute is expected to be a
boolean expression which indicates whether or not Oracle should use the mode
OCI_THREADED to wrap accesses to connections with a mutex. Doing so in single
threaded applications imposes a performance penalty of about 10-15% which is
why the default is False.
<p>
<strong>NOTE:</strong> This method is an extension to the DB API definition and is
only available in Oracle 9i.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-9' xml:id='l2h-9' class="function">Time</tt></b>(</nobr></td>
<td><var><var>hour</var>, <var>minute</var>, <var>second</var></var>)</td></tr></table></dt>
<dd>
Construct an object holding a time value.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-10' xml:id='l2h-10' class="function">TimeFromTicks</tt></b>(</nobr></td>
<td><var><var>ticks</var></var>)</td></tr></table></dt>
<dd>
Construct an object holding a time value from the given ticks value (number
of seconds since the epoch; see the documentation of the standard Python
time module for details).
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-11' xml:id='l2h-11' class="function">Timestamp</tt></b>(</nobr></td>
<td><var><var>year</var>, <var>month</var>, <var>day</var>,
<var>hour</var>, <var>minute</var>, <var>second</var></var>)</td></tr></table></dt>
<dd>
Construct an object holding a time stamp value.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-12' xml:id='l2h-12' class="function">TimestampFromTicks</tt></b>(</nobr></td>
<td><var><var>ticks</var></var>)</td></tr></table></dt>
<dd>
Construct an object holding a time stamp value from the given ticks value
(number of seconds since the epoch; see the documentation of the standard
Python time module for details).
</dl>
<p>
<p><br /></p><hr class='online-navigation' />
<div class='online-navigation'>
<!--Table of Child-Links-->
<a name="CHILD_LINKS"><strong>Subsections</strong></a>
<ul class="ChildLinks">
<li><a href="node4.html">1.1 Constants</a>
<li><a href="node5.html">1.2 Exceptions</a>
</ul>
<!--End of Table of Child-Links-->
</div>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="Contents"
href="contents.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1 Constants"
href="node4.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="contents.html">Contents</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node4.html">1.1 Constants</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

BIN
html/modules.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

BIN
html/next.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

146
html/node12.html Normal file
View File

@ -0,0 +1,146 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="about.html" />
<link rel="prev" href="dateobj.html" />
<link rel="parent" href="cx_Oracle.html" />
<link rel="next" href="about.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>8. License</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="7. date Objects"
href="dateobj.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="About this document ..."
href="about.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="dateobj.html">7. Date Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="about.html">About this document ...</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION0010000000000000000000">
8. License</a>
</h1>
<p>
<div class="centerline" id="par1465" align="CENTER">
<strong>LICENSE AGREEMENT FOR CX_ORACLE 4.3.1</strong></div>
<p>
Copyright © 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta, Canada.
All rights reserved.
<p>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
<p>
<ol>
<li>Redistributions of source code must retain the above copyright notice,
this list of conditions, and the disclaimer that follows.
<p>
</li>
<li>Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
<p>
</li>
<li>Neither the name of Computronix nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
</li>
</ol>
<p>
DISCLAIMER:
THIS SOFTWARE IS PROVIDED BY COMPUTRONIX AND CONTRIBUTORS *AS IS*
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COMPUTRONIX
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
<p>
Computronix (R) is a registered trademark of Computronix (Canada) Ltd.
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="7. date Objects"
href="dateobj.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="About this document ..."
href="about.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="dateobj.html">7. Date Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="about.html">About this document ...</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

427
html/node4.html Normal file
View File

@ -0,0 +1,427 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="node5.html" />
<link rel="prev" href="module.html" />
<link rel="parent" href="module.html" />
<link rel="next" href="node5.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>1.1 Constants</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1. module Interface"
href="module.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1. module Interface"
href="module.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.2 Exceptions"
href="node5.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="module.html">1. Module Interface</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module.html">1. Module Interface</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node5.html">1.2 Exceptions</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION003100000000000000000">
1.1 Constants</a>
</h1>
<p>
<dl><dt><b><tt id='l2h-13' xml:id='l2h-13'>apilevel</tt></b></dt>
<dd>
String constant stating the supported DB API level. Currently '2.0'.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-14' xml:id='l2h-14'>buildtime</tt></b></dt>
<dd>
String constant stating the time when the binary was built.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-15' xml:id='l2h-15'>BINARY</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are binary
(in Oracle this is RAW columns).
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-16' xml:id='l2h-16'>BFILE</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are BFILEs.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-17' xml:id='l2h-17'>BLOB</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are BLOBs.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-18' xml:id='l2h-18'>CLOB</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are CLOBs.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-19' xml:id='l2h-19'>CURSOR</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are cursors
(in PL/SQL these are known as ref cursors).
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-20' xml:id='l2h-20'>DATETIME</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are dates.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-21' xml:id='l2h-21'>FIXED_CHAR</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are fixed
length strings (in Oracle this is CHAR columns); these behave differently
in Oracle than varchar2 so they are differentiated here even though the DB
API does not differentiate them.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-22' xml:id='l2h-22'>FNCODE_BINDBYNAME</tt></b></dt>
<dd>
This constant is used to register callbacks on the OCIBindByName() function
of the OCI.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-23' xml:id='l2h-23'>FNCODE_BINDBYPOS</tt></b></dt>
<dd>
This constant is used to register callbacks on the OCIBindByPos() function
of the OCI.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-24' xml:id='l2h-24'>FNCODE_DEFINEBYPOS</tt></b></dt>
<dd>
This constant is used to register callbacks on the OCIDefineByPos() function
of the OCI.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-25' xml:id='l2h-25'>FNCODE_STMTEXECUTE</tt></b></dt>
<dd>
This constant is used to register callbacks on the OCIStmtExecute() function
of the OCI.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-26' xml:id='l2h-26'>FNCODE_STMTFETCH</tt></b></dt>
<dd>
This constant is used to register callbacks on the OCIStmtFetch() function
of the OCI.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-27' xml:id='l2h-27'>FNCODE_STMTPREPARE</tt></b></dt>
<dd>
This constant is used to register callbacks on the OCIStmtPrepare() function
of the OCI.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-28' xml:id='l2h-28'>LOB</tt></b></dt>
<dd>
This type object is the Python type of BLOB and CLOB data that is returned
from cursors.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-29' xml:id='l2h-29'>LONG_BINARY</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are long
binary (in Oracle these are LONG RAW columns).
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-30' xml:id='l2h-30'>LONG_STRING</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are long
strings (in Oracle these are LONG columns).
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-31' xml:id='l2h-31'>NCLOB</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are NCLOBs.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-32' xml:id='l2h-32'>NUMBER</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are numbers.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-33' xml:id='l2h-33'>OBJECT</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are objects.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-34' xml:id='l2h-34'>paramstyle</tt></b></dt>
<dd>
String constant stating the type of parameter marker formatting expected by
the interface. Currently 'named' as in 'where name = :name'.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-35' xml:id='l2h-35'>ROWID</tt></b></dt>
<dd>
This type object is used to describe the pseudo column "rowid".
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-36' xml:id='l2h-36'>SPOOL_ATTRVAL_FORCEGET</tt></b></dt>
<dd>
This constant is used to define the "get" mode on session pools and indicates
that a new connection will be returned if there are no free sessions
available in the pool.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-37' xml:id='l2h-37'>SPOOL_ATTRVAL_NOWAIT</tt></b></dt>
<dd>
This constant is used to define the "get" mode on session pools and indicates
that an exception is raised if there are no free sessions available in the
pool.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-38' xml:id='l2h-38'>SPOOL_ATTRVAL_WAIT</tt></b></dt>
<dd>
This constant is used to define the "get" mode on session pools and indicates
that the acquisition of a connection waits until a session is freed if there
are no free sessions available in the pool.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-39' xml:id='l2h-39'>STRING</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are strings
(in Oracle this is VARCHAR2 columns).
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-40' xml:id='l2h-40'>SYSDBA</tt></b></dt>
<dd>
Value to be passed to the connect() method which indicates that SYSDBA
access is to be acquired. See the Oracle documentation for more details.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-41' xml:id='l2h-41'>SYSOPER</tt></b></dt>
<dd>
Value to be passed to the connect() method which indicates that SYSOPER
access is to be acquired. See the Oracle documentation for more details.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-42' xml:id='l2h-42'>threadsafety</tt></b></dt>
<dd>
Integer constant stating the level of thread safety that the interface
supports. Currently 2, which means that threads may share the module and
connections, but not cursors. Sharing means that a thread may use a resource
without wrapping it using a mutex semaphore to implement resource locking.
<p>
Note that in order to make use of multiple threads in a program which intends
to connect and disconnect in different threads, the threaded argument to the
Connection constructor must be a true value. See the comments on the
Connection constructor for more information (<a href="module.html#module">1</a>).
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-43' xml:id='l2h-43'>TIMESTAMP</tt></b></dt>
<dd>
This type object is used to describe columns in a database that are
timestamps.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition and
is only available in Oracle 9i.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-44' xml:id='l2h-44'>UCBTYPE_ENTRY</tt></b></dt>
<dd>
This constant is used to register callbacks on entry to the function
of the OCI. In other words, the callback will be called prior to the
execution of the OCI function.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-45' xml:id='l2h-45'>UCBTYPE_EXIT</tt></b></dt>
<dd>
This constant is used to register callbacks on exit from the function
of the OCI. In other words, the callback will be called after the execution
of the OCI function.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-46' xml:id='l2h-46'>UCBTYPE_REPLACE</tt></b></dt>
<dd>
This constant is used to register callbacks that completely replace the
call to the OCI function.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-47' xml:id='l2h-47'>version</tt></b></dt>
<dd>
String constant stating the version of the module. Currently '4.3.1'.
<p>
<strong>NOTE:</strong> This attribute is an extension to the DB API definition.
</dd></dl>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1. module Interface"
href="module.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1. module Interface"
href="module.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.2 Exceptions"
href="node5.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="module.html">1. Module Interface</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module.html">1. Module Interface</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node5.html">1.2 Exceptions</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

166
html/node5.html Normal file
View File

@ -0,0 +1,166 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="prev" href="node4.html" />
<link rel="parent" href="module.html" />
<link rel="next" href="connobj.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>1.2 Exceptions</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1 Constants"
href="node4.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1. module Interface"
href="module.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="2. connection Objects"
href="connobj.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node4.html">1.1 Constants</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module.html">1. Module Interface</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="connobj.html">2. Connection Objects</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION003200000000000000000">
1.2 Exceptions</a>
</h1>
<p>
<dl><dt><b><tt id='l2h-48' xml:id='l2h-48'>Warning</tt></b></dt>
<dd>
Exception raised for important warnings and defined by the DB API but not
actually used by cx_Oracle.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-49' xml:id='l2h-49'>Error</tt></b></dt>
<dd>
Exception that is the base class of all other exceptions defined by
cx_Oracle and is a subclass of the Python StandardError exception (defined in
the module exceptions).
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-50' xml:id='l2h-50'>InterfaceError</tt></b></dt>
<dd>
Exception raised for errors that are related to the database interface rather
than the database itself. It is a subclass of Error.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-51' xml:id='l2h-51'>DatabaseError</tt></b></dt>
<dd>
Exception raised for errors that are related to the database. It is a
subclass of Error.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-52' xml:id='l2h-52'>DataError</tt></b></dt>
<dd>
Exception raised for errors that are due to problems with the processed data.
It is a subclass of DatabaseError.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-53' xml:id='l2h-53'>OperationalError</tt></b></dt>
<dd>
Exception raised for errors that are related to the operation of the database
but are not necessarily under the control of the progammer. It is a
subclass of DatabaseError.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-54' xml:id='l2h-54'>IntegrityError</tt></b></dt>
<dd>
Exception raised when the relational integrity of the database is affected.
It is a subclass of DatabaseError.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-55' xml:id='l2h-55'>InternalError</tt></b></dt>
<dd>
Exception raised when the database encounters an internal error.
It is a subclass of DatabaseError.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-56' xml:id='l2h-56'>ProgrammingError</tt></b></dt>
<dd>
Exception raised for programming errors. It is a subclass of DatabaseError.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-57' xml:id='l2h-57'>NotSupportedError</tt></b></dt>
<dd>
Exception raised when a method or database API was used which is not
supported by the database. It is a subclass of DatabaseError.
</dd></dl>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1 Constants"
href="node4.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1. module Interface"
href="module.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="2. connection Objects"
href="connobj.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node4.html">1.1 Constants</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module.html">1. Module Interface</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="connobj.html">2. Connection Objects</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

BIN
html/previous.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

206
html/sesspool.html Normal file
View File

@ -0,0 +1,206 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="lobobj.html" />
<link rel="prev" href="varobj.html" />
<link rel="parent" href="cx_Oracle.html" />
<link rel="next" href="lobobj.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>5. SessionPool Objects</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="4. variable Objects"
href="varobj.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="6. lob Objects"
href="lobobj.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="varobj.html">4. Variable Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="lobobj.html">6. LOB Objects</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION007000000000000000000"></a><a name="sesspool"></a>
<br>
5. SessionPool Objects
</h1>
<p>
<strong>NOTE</strong>: This object is an extension the DB API and is only available in
Oracle 9i.
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-109' xml:id='l2h-109' class="function">acquire</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Acquire a connection from the session pool and return a connection
object (<a href="connobj.html#connobj">2</a>).
</dl>
<p>
<dl><dt><b><tt id='l2h-110' xml:id='l2h-110'>busy</tt></b></dt>
<dd>
This read-only attribute returns the number of sessions currently acquired.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-111' xml:id='l2h-111' class="function">drop</tt></b>(</nobr></td>
<td><var><var>connection</var></var>)</td></tr></table></dt>
<dd>
Drop the connection from the pool which is useful if the connection is no
longer usable (such as when the session is killed).
</dl>
<p>
<dl><dt><b><tt id='l2h-112' xml:id='l2h-112'>dsn</tt></b></dt>
<dd>
This read-only attribute returns the TNS entry of the database to which a
connection has been established.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-113' xml:id='l2h-113'>increment</tt></b></dt>
<dd>
This read-only attribute returns the number of sessions that will be
established when additional sessions need to be created.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-114' xml:id='l2h-114'>max</tt></b></dt>
<dd>
This read-only attribute returns the maximum number of sessions that the
session pool can control.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-115' xml:id='l2h-115'>min</tt></b></dt>
<dd>
This read-only attribute returns the number of sessions with which the
session pool was created and the minimum number of sessions that will be
controlled by the session pool.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-116' xml:id='l2h-116'>name</tt></b></dt>
<dd>
This read-only attribute returns the name assigned to the session pool by
Oracle.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-117' xml:id='l2h-117'>opened</tt></b></dt>
<dd>
This read-only attribute returns the number of sessions currently opened by
the session pool.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-118' xml:id='l2h-118'>password</tt></b></dt>
<dd>
This read-only attribute returns the password of the user which established
the connection to the database.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-119' xml:id='l2h-119' class="function">release</tt></b>(</nobr></td>
<td><var><var>connection</var></var>)</td></tr></table></dt>
<dd>
Release the connection back to the pool. This will be done automatically as
well if the connection object is garbage collected.
</dl>
<p>
<dl><dt><b><tt id='l2h-120' xml:id='l2h-120'>timeout</tt></b></dt>
<dd>
This read-write attribute indicates the time (in seconds) after which idle
sessions will be terminated in order to maintain an optimum number of open
sessions.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-121' xml:id='l2h-121'>tnsentry</tt></b></dt>
<dd>
This read-only attribute returns the TNS entry of the database to which a
connection has been established.
</dd></dl>
<p>
<dl><dt><b><tt id='l2h-122' xml:id='l2h-122'>username</tt></b></dt>
<dd>
This read-only attribute returns the name of the user which established the
connection to the database.
</dd></dl>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="4. variable Objects"
href="varobj.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="6. lob Objects"
href="lobobj.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="varobj.html">4. Variable Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="lobobj.html">6. LOB Objects</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

BIN
html/up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

129
html/varobj.html Normal file
View File

@ -0,0 +1,129 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="cx_Oracle.css" type='text/css' />
<link rel="first" href="cx_Oracle.html" title='cx_Oracle' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="sesspool.html" />
<link rel="prev" href="cursorobj.html" />
<link rel="parent" href="cx_Oracle.html" />
<link rel="next" href="sesspool.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>4. Variable Objects</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="3. cursor Objects"
href="cursorobj.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="5. sessionpool Objects"
href="sesspool.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="cursorobj.html">3. Cursor Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="sesspool.html">5. SessionPool Objects</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION006000000000000000000"></a><a name="varobj"></a>
<br>
4. Variable Objects
</h1>
<p>
<strong>NOTE:</strong> The DB API definition does not define this object.
<p>
<dl><dt><b><tt id='l2h-105' xml:id='l2h-105'>allocelems</tt></b></dt>
<dd>
This read-only attribute returns the number of elements allocated in an
array, or the number of scalar items that can be fetched into the variable.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-106' xml:id='l2h-106' class="function">getvalue</tt></b>(</nobr></td>
<td><var></var><big>[</big><var><var>pos=0</var></var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Return the value at the given position in the variable.
</dl>
<p>
<dl><dt><b><tt id='l2h-107' xml:id='l2h-107'>maxlength</tt></b></dt>
<dd>
This read-only attribute returns the maximum length of the variable.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-108' xml:id='l2h-108' class="function">setvalue</tt></b>(</nobr></td>
<td><var><var>pos</var>, <var>value</var></var>)</td></tr></table></dt>
<dd>
Set the value at the given position in the variable.
</dl>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="3. cursor Objects"
href="cursorobj.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="cx_Oracle"
href="cx_Oracle.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="5. sessionpool Objects"
href="sesspool.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">cx_Oracle</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="cursorobj.html">3. Cursor Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="cx_Oracle.html">cx_Oracle</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="sesspool.html">5. SessionPool Objects</a>
</div>
</div>
<hr />
<span class="release-info">Release 4.3.1, documentation updated on April 18, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

3
setup.cfg Normal file
View File

@ -0,0 +1,3 @@
[bdist_rpm]
doc_files = LICENSE.txt README.txt HISTORY.txt html test

114
setup.py Normal file
View File

@ -0,0 +1,114 @@
"""Distutils script for cx_Oracle.
Windows platforms:
python setup.py build --compiler=mingw32 install
Unix platforms
python setup.py build install
"""
import os
import sys
from distutils.core import setup
from distutils.extension import Extension
# define build constants
BUILD_VERSION = "4.3.1"
# define the list of files to be included as documentation for Windows
dataFiles = None
if sys.platform in ("win32", "cygwin"):
baseName = "cx_Oracle-doc"
dataFiles = [ (baseName, [ "LICENSE.TXT", "README.TXT", "HISTORY.txt"]) ]
allFiles = []
for fileName in open("MANIFEST").readlines():
allFiles.append(fileName.strip())
for dir in ("html", "test"):
files = []
for name in allFiles:
if name.startswith(dir):
files.append(name)
dataFiles.append( ("%s/%s" % (baseName, dir), files) )
# define some variables
oracleHome = os.environ["ORACLE_HOME"]
if sys.platform == "win32":
libDirs = None
includeDirs = [os.path.join(oracleHome, "oci", "include"), \
os.path.join(oracleHome, "rdbms", "demo")]
libs = []
elif sys.platform == "cygwin":
includeDirs = ["/usr/include", "rdbms/demo", "rdbms/public", \
"network/public", "oci/include"]
libDirs = ["bin", "lib"]
for i in range(len(includeDirs)):
includeDirs[i] = os.path.join(oracleHome, includeDirs[i])
for i in range(len(libDirs)):
libDirs[i] = os.path.join(oracleHome, libDirs[i])
libs = ["oci"]
else:
includeDirs = ["rdbms/demo", "rdbms/public", "network/public",
"sdk/include"]
if sys.platform == "darwin":
includeDirs.append("plsql/public")
for i in range(len(includeDirs)):
includeDirs[i] = os.path.join(oracleHome, includeDirs[i])
libPath = os.path.join(oracleHome, "lib")
if sys.platform == "sunos5" and sys.maxint > 2147483647:
libPath = os.path.join(oracleHome, "lib64")
libDirs = [libPath, oracleHome]
libs = ["clntsh"]
# NOTE: on HP-UX Itanium with Oracle 10g you need to add the library "ttsh10"
# to the list of libraries along with "clntsh"; since I am unable to test, I'll
# leave this as a comment until someone can verify when this is required
# without making other cases where sys.platform == "hp-ux11" stop working
# setup extra link and compile args
extraCompileArgs = ["-DBUILD_VERSION=%s" % BUILD_VERSION]
extraLinkArgs = []
if sys.platform == "aix4":
extraCompileArgs.append("-qcpluscmt")
elif sys.platform == "cygwin":
extraCompileArgs.append("-mno-cygwin")
elif sys.platform == "darwin":
extraLinkArgs = None
elif sys.platform == "win32":
import win32api
extraLinkArgs.append(win32api.GetModuleFileName(sys.dllhandle))
extraLinkArgs.append(os.path.join(oracleHome, "bin", "oci.dll"))
# 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
# location will be the only location searched for the Oracle client library
if "FORCE_RPATH" in os.environ:
extraLinkArgs.append("-Wl,-rpath,%s/lib" % oracleHome)
# setup the extension
extension = Extension(
name = "cx_Oracle",
include_dirs = includeDirs,
libraries = libs,
library_dirs = libDirs,
extra_compile_args = extraCompileArgs,
extra_link_args = extraLinkArgs,
sources = ["cx_Oracle.c"])
# perform the setup
setup(
name = "cx_Oracle",
version = BUILD_VERSION,
description = "Python interface to Oracle",
license = "See LICENSE.txt",
data_files = dataFiles,
long_description = \
"Python interface to Oracle conforming to the Python DB API 2.0 "
"specification.\n"
"See http://www.python.org/topics/database/DatabaseAPI-2.0.html.",
author = "Anthony Tuininga",
author_email = "anthony.tuininga@gmail.com",
url = "http://starship.python.net/crew/atuining",
ext_modules = [extension])

116
test/Connection.py Normal file
View File

@ -0,0 +1,116 @@
"""Module for testing connections."""
import threading
class TestConnection(TestCase):
def __ConnectAndDrop(self):
"""Connect to the database, perform a query and drop the connection."""
connection = cx_Oracle.connect(self.username, self.password,
self.tnsentry, threaded = True)
cursor = connection.cursor()
cursor.execute("select count(*) from TestNumbers")
count, = cursor.fetchone()
self.failUnlessEqual(count, 10)
def setUp(self):
self.username = USERNAME
self.password = PASSWORD
self.tnsentry = TNSENTRY
def verifyArgs(self, connection):
self.failUnlessEqual(connection.username, self.username,
"user name differs")
self.failUnlessEqual(connection.password, self.password,
"password differs")
self.failUnlessEqual(connection.tnsentry, self.tnsentry,
"tnsentry differs")
def testAllArgs(self):
"connection to database with user, password, TNS separate"
connection = cx_Oracle.connect(self.username, self.password,
self.tnsentry)
self.verifyArgs(connection)
def testBadConnectString(self):
"connection to database with bad connect string"
self.failUnlessRaises(cx_Oracle.DatabaseError, cx_Oracle.connect,
self.username)
self.failUnlessRaises(cx_Oracle.DatabaseError, cx_Oracle.connect,
self.username + "@" + self.tnsentry)
self.failUnlessRaises(cx_Oracle.DatabaseError, cx_Oracle.connect,
self.username + "@" + self.tnsentry + "/" + self.password)
def testBadPassword(self):
"connection to database with bad password"
self.failUnlessRaises(cx_Oracle.DatabaseError, cx_Oracle.connect,
self.username, self.password + "X", self.tnsentry)
def testExceptionOnClose(self):
"confirm an exception is raised after closing a connection"
connection = cx_Oracle.connect(self.username, self.password,
self.tnsentry)
connection.close()
self.failUnlessRaises(cx_Oracle.InterfaceError, connection.rollback)
def testMakeDSN(self):
"test making a data source name from host, port and sid"
formatString = "(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)" + \
"(HOST=%s)(PORT=%d)))(CONNECT_DATA=(SID=%s)))"
args = ("hostname", 1521, "TEST")
result = cx_Oracle.makedsn(*args)
self.failUnlessEqual(result, formatString % args)
def testSingleArg(self):
"connection to database with user, password, TNS together"
connection = cx_Oracle.connect("%s/%s@%s" % \
(self.username, self.password, self.tnsentry))
self.verifyArgs(connection)
def testVersion(self):
"connection version is a string"
connection = cx_Oracle.connect(self.username, self.password,
self.tnsentry)
self.failUnless(isinstance(connection.version, str))
def testRollbackOnClose(self):
"connection rolls back before close"
connection = cx_Oracle.connect(self.username, self.password,
self.tnsentry)
cursor = connection.cursor()
cursor.execute("truncate table TestExecuteMany")
otherConnection = cx_Oracle.connect(self.username, self.password,
self.tnsentry)
otherCursor = otherConnection.cursor()
otherCursor.execute("insert into TestExecuteMany values (1)")
otherConnection.close()
cursor.execute("select count(*) from TestExecuteMany")
count, = cursor.fetchone()
self.failUnlessEqual(count, 0)
def testRollbackOnDel(self):
"connection rolls back before destruction"
connection = cx_Oracle.connect(self.username, self.password,
self.tnsentry)
cursor = connection.cursor()
cursor.execute("truncate table TestExecuteMany")
otherConnection = cx_Oracle.connect(self.username, self.password,
self.tnsentry)
otherCursor = otherConnection.cursor()
otherCursor.execute("insert into TestExecuteMany values (1)")
del otherCursor
del otherConnection
cursor.execute("select count(*) from TestExecuteMany")
count, = cursor.fetchone()
self.failUnlessEqual(count, 0)
def testThreading(self):
"connection to database with multiple threads"
threads = []
for i in range(20):
thread = threading.Thread(None, self.__ConnectAndDrop)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()

225
test/Cursor.py Normal file
View File

@ -0,0 +1,225 @@
"""Module for testing cursor objects."""
import cx_Oracle
class TestCursor(BaseTestCase):
def testExecuteNoArgs(self):
"""test executing a statement without any arguments"""
result = self.cursor.execute("begin null; end;")
self.failUnlessEqual(result, None)
def testExecuteNoStatementWithArgs(self):
"""test executing a None statement with bind variables"""
self.failUnlessRaises(cx_Oracle.ProgrammingError, self.cursor.execute,
None, x = 5)
def testExecuteEmptyKeywordArgs(self):
"""test executing a statement with args and empty keyword args"""
simpleVar = self.cursor.var(cx_Oracle.NUMBER)
args = [simpleVar]
kwArgs = {}
result = self.cursor.execute("begin :1 := 25; end;", args, **kwArgs)
self.failUnlessEqual(result, None)
self.failUnlessEqual(simpleVar.getvalue(), 25)
def testExecuteKeywordArgs(self):
"""test executing a statement with keyword arguments"""
simpleVar = self.cursor.var(cx_Oracle.NUMBER)
result = self.cursor.execute("begin :p_Value := 5; end;",
p_Value = simpleVar)
self.failUnlessEqual(result, None)
self.failUnlessEqual(simpleVar.getvalue(), 5)
def testExecuteDictionaryArg(self):
"""test executing a statement with a dictionary argument"""
simpleVar = self.cursor.var(cx_Oracle.NUMBER)
dictArg = { "p_Value" : simpleVar }
result = self.cursor.execute("begin :p_Value := 10; end;", dictArg)
self.failUnlessEqual(result, None)
self.failUnlessEqual(simpleVar.getvalue(), 10)
def testExecuteMultipleMethod(self):
"""test executing a statement with both a dict arg and keyword args"""
simpleVar = self.cursor.var(cx_Oracle.NUMBER)
dictArg = { "p_Value" : simpleVar }
self.failUnlessRaises(cx_Oracle.InterfaceError, self.cursor.execute,
"begin :p_Value := 15; end;", dictArg, p_Value = simpleVar)
def testExecuteAndModifyArraySize(self):
"""test executing a statement and then changing the array size"""
self.cursor.execute("select IntCol from TestNumbers")
self.cursor.arraysize = 20
self.failUnlessEqual(len(self.cursor.fetchall()), 10)
def testCallProc(self):
"""test executing a stored procedure"""
var = self.cursor.var(cx_Oracle.NUMBER)
results = self.cursor.callproc("proc_Test", ("hi", 5, var))
self.failUnlessEqual(results, ["hi", 10, 2.0])
def testCallProcNoArgs(self):
"""test executing a stored procedure without any arguments"""
results = self.cursor.callproc("proc_TestNoArgs")
self.failUnlessEqual(results, [])
def testCallFunc(self):
"""test executing a stored function"""
results = self.cursor.callfunc("func_Test", cx_Oracle.NUMBER,
("hi", 5))
self.failUnlessEqual(results, 7)
def testCallFuncNoArgs(self):
"""test executing a stored function without any arguments"""
results = self.cursor.callfunc("func_TestNoArgs", cx_Oracle.NUMBER)
self.failUnlessEqual(results, 712)
def testExecuteManyByName(self):
"""test executing a statement multiple times (named args)"""
self.cursor.execute("truncate table TestExecuteMany")
rows = [ { "value" : n } for n in range(250) ]
self.cursor.arraysize = 100
statement = "insert into TestExecuteMany values (:value)"
self.cursor.executemany(statement, rows)
self.connection.commit()
self.cursor.execute("select count(*) from TestExecuteMany")
count, = self.cursor.fetchone()
self.failUnlessEqual(count, len(rows))
def testExecuteManyByPosition(self):
"""test executing a statement multiple times (positional args)"""
self.cursor.execute("truncate table TestExecuteMany")
rows = [ [n] for n in range(230) ]
self.cursor.arraysize = 100
statement = "insert into TestExecuteMany values (:1)"
self.cursor.executemany(statement, rows)
self.connection.commit()
self.cursor.execute("select count(*) from TestExecuteMany")
count, = self.cursor.fetchone()
self.failUnlessEqual(count, len(rows))
def testExecuteManyWithPrepare(self):
"""test executing a statement multiple times (with prepare)"""
self.cursor.execute("truncate table TestExecuteMany")
rows = [ [n] for n in range(225) ]
self.cursor.arraysize = 100
statement = "insert into TestExecuteMany values (:1)"
self.cursor.prepare(statement)
self.cursor.executemany(None, rows)
self.connection.commit()
self.cursor.execute("select count(*) from TestExecuteMany")
count, = self.cursor.fetchone()
self.failUnlessEqual(count, len(rows))
def testExecuteManyWithRebind(self):
"""test executing a statement multiple times (with rebind)"""
self.cursor.execute("truncate table TestExecuteMany")
rows = [ [n] for n in range(235) ]
self.cursor.arraysize = 100
statement = "insert into TestExecuteMany values (:1)"
self.cursor.executemany(statement, rows[:50])
self.cursor.executemany(statement, rows[50:])
self.connection.commit()
self.cursor.execute("select count(*) from TestExecuteMany")
count, = self.cursor.fetchone()
self.failUnlessEqual(count, len(rows))
def testExecuteManyWithExecption(self):
"""test executing a statement multiple times (with exception)"""
self.cursor.execute("truncate table TestExecuteMany")
rows = [ { "p_Value" : n } for n in (1, 2, 3, 2, 5) ]
statement = "insert into TestExecuteMany values (:p_Value)"
self.failUnlessRaises(cx_Oracle.DatabaseError, self.cursor.executemany,
statement, rows)
self.failUnlessEqual(self.cursor.rowcount, 3)
def testPrepare(self):
"""test preparing a statement and executing it multiple times"""
self.failUnlessEqual(self.cursor.statement, None)
statement = "begin :p_Value := :p_Value + 5; end;"
self.cursor.prepare(statement)
var = self.cursor.var(cx_Oracle.NUMBER)
self.failUnlessEqual(self.cursor.statement, statement)
var.setvalue(0, 2)
self.cursor.execute(None, p_Value = var)
self.failUnlessEqual(var.getvalue(), 7)
self.cursor.execute(None, p_Value = var)
self.failUnlessEqual(var.getvalue(), 12)
self.cursor.execute("begin :p_Value2 := 3; end;", p_Value2 = var)
self.failUnlessEqual(var.getvalue(), 3)
def testExceptionOnClose(self):
"confirm an exception is raised after closing a cursor"
self.cursor.close()
self.failUnlessRaises(cx_Oracle.InterfaceError, self.cursor.execute,
"select 1 from dual")
def testIterators(self):
"""test iterators"""
self.cursor.execute("""
select IntCol
from TestNumbers
where IntCol between 1 and 3
order by IntCol""")
rows = []
for row in self.cursor:
rows.append(row[0])
self.failUnlessEqual(rows, [1, 2, 3])
def testIteratorsInterrupted(self):
"""test iterators (with intermediate execute)"""
self.cursor.execute("truncate table TestExecuteMany")
self.cursor.execute("""
select IntCol
from TestNumbers
where IntCol between 1 and 3
order by IntCol""")
testIter = iter(self.cursor)
value, = testIter.next()
self.cursor.execute("insert into TestExecuteMany values (1)")
self.failUnlessRaises(cx_Oracle.InterfaceError, testIter.next)
def testBindNames(self):
"""test that bindnames() works correctly."""
self.failUnlessRaises(cx_Oracle.ProgrammingError,
self.cursor.bindnames)
self.cursor.prepare("begin null; end;")
self.failUnlessEqual(self.cursor.bindnames(), [])
self.cursor.prepare("begin :retval := :inval + 5; end;")
self.failUnlessEqual(self.cursor.bindnames(), ["RETVAL", "INVAL"])
self.cursor.prepare("begin :retval := :a * :a + :b * :b; end;")
self.failUnlessEqual(self.cursor.bindnames(), ["RETVAL", "A", "B"])
self.cursor.prepare("begin :a := :b + :c + :d + :e + :f + :g + " + \
":h + :i + :j + :k + :l; end;")
self.failUnlessEqual(self.cursor.bindnames(),
["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"])
def testBadPrepare(self):
"""test that subsequent executes succeed after bad prepare"""
self.failUnlessRaises(cx_Oracle.DatabaseError,
self.cursor.execute,
"begin raise_application_error(-20000, 'this); end;")
self.cursor.execute("begin null; end;")
def testBadExecute(self):
"""test that subsequent fetches fail after bad execute"""
self.failUnlessRaises(cx_Oracle.DatabaseError,
self.cursor.execute, "select y from dual")
self.failUnlessRaises(cx_Oracle.InterfaceError,
self.cursor.fetchall)
def testSetInputSizesMultipleMethod(self):
"""test setting input sizes with both positional and keyword args"""
self.failUnlessRaises(cx_Oracle.InterfaceError,
self.cursor.setinputsizes, 5, x = 5)
def testSetInputSizesByPosition(self):
"""test setting input sizes with positional args"""
var = self.cursor.var(cx_Oracle.STRING, 100)
self.cursor.setinputsizes(None, 5, None, 10, None, cx_Oracle.NUMBER)
self.cursor.execute("""
begin
:1 := :2 || to_char(:3) || :4 || to_char(:5) || to_char(:6);
end;""", [var, 'test_', 5, '_second_', 3, 7])
self.failUnlessEqual(var.getvalue(), "test_5_second_37")

50
test/CursorVar.py Normal file
View File

@ -0,0 +1,50 @@
"""Module for testing cursor variables."""
import sys
class TestCursorVar(BaseTestCase):
def testBindCursor(self):
"test binding in a cursor"
cursor = self.connection.cursor()
self.failUnlessEqual(cursor.description, None)
self.cursor.execute("""
begin
open :p_Cursor for select 1 NumberCol from dual;
end;""",
p_Cursor = cursor)
self.failUnlessEqual(cursor.description,
[ ('NUMBERCOL', cx_Oracle.NUMBER, 127, 2, 0, 0, 1) ])
self.failUnlessEqual(cursor.fetchall(), [(1.0,)])
def testBindCursorInPackage(self):
"test binding in a cursor from a package"
cursor = self.connection.cursor()
self.failUnlessEqual(cursor.description, None)
self.cursor.callproc("pkg_TestOutCursors.TestOutCursor", (2, cursor))
self.failUnlessEqual(cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('STRINGCOL', cx_Oracle.STRING, 20, 20, 0, 0, 0) ])
self.failUnlessEqual(cursor.fetchall(),
[ (1, 'String 1'), (2, 'String 2') ])
def testFetchCursor(self):
"test fetching a cursor"
self.cursor.execute("""
select
IntCol,
cursor(select IntCol + 1 from dual) CursorValue
from TestNumbers
order by IntCol""")
if len(str(sys.maxint)) == 10:
size = 4
else:
size = 8
self.failUnlessEqual(self.cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('CURSORVALUE', cx_Oracle.CURSOR, -1, size, 0, 0, 1) ])
for i in range(1, 11):
number, cursor = self.cursor.fetchone()
self.failUnlessEqual(number, i)
self.failUnlessEqual(cursor.fetchall(), [(i + 1,)])

230
test/DateTimeVar.py Normal file
View File

@ -0,0 +1,230 @@
"""Module for testing date/time variables."""
import sys
import time
class TestDateTimeVar(BaseTestCase):
def setUp(self):
BaseTestCase.setUp(self)
self.rawData = []
self.dataByKey = {}
for i in range(1, 11):
timeTuple = (2002, 12, 9, 0, 0, 0, 0, 0, -1)
timeInTicks = time.mktime(timeTuple) + i * 86400 + i * 8640
dateCol = cx_Oracle.TimestampFromTicks(int(timeInTicks))
if i % 2:
timeInTicks = time.mktime(timeTuple) + i * 86400 * 2 + \
i * 12960
nullableCol = cx_Oracle.TimestampFromTicks(int(timeInTicks))
else:
nullableCol = None
tuple = (i, dateCol, nullableCol)
self.rawData.append(tuple)
self.dataByKey[i] = tuple
def testBindDate(self):
"test binding in a date"
self.cursor.execute("""
select * from TestDates
where DateCol = :p_Value""",
p_Value = cx_Oracle.Timestamp(2002, 12, 13, 9, 36, 0))
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[4]])
if sys.version_info[:2] != (2, 2):
def testBindDateTime(self):
"test binding in a Python 2.3 and higher date time"
import datetime
self.cursor.execute("""
select * from TestDates
where DateCol = :value""",
value = datetime.datetime(2002, 12, 13, 9, 36, 0))
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[4]])
def testBindDateAfterString(self):
"test binding in a date after setting input sizes to a string"
self.cursor.setinputsizes(p_Value = 15)
self.cursor.execute("""
select * from TestDates
where DateCol = :p_Value""",
p_Value = cx_Oracle.Timestamp(2002, 12, 14, 12, 0, 0))
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[5]])
def testBindNull(self):
"test binding in a null"
self.cursor.setinputsizes(p_Value = cx_Oracle.DATETIME)
self.cursor.execute("""
select * from TestDates
where DateCol = :p_Value""",
p_Value = None)
self.failUnlessEqual(self.cursor.fetchall(), [])
def testBindDateArrayDirect(self):
"test binding in a date array"
returnValue = self.cursor.var(cx_Oracle.NUMBER)
array = [r[1] for r in self.rawData]
statement = """
begin
:p_ReturnValue := pkg_TestDateArrays.TestInArrays(
:p_StartValue, :p_BaseDate, :p_Array);
end;"""
self.cursor.execute(statement,
p_ReturnValue = returnValue,
p_StartValue = 5,
p_BaseDate = cx_Oracle.Date(2002, 12, 12),
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 35.5)
array = array + array[:5]
self.cursor.execute(statement,
p_StartValue = 7,
p_BaseDate = cx_Oracle.Date(2002, 12, 13),
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 24.0)
def testBindDateArrayBySizes(self):
"test binding in a date array (with setinputsizes)"
returnValue = self.cursor.var(cx_Oracle.NUMBER)
self.cursor.setinputsizes(p_Array = [cx_Oracle.DATETIME, 10])
array = [r[1] for r in self.rawData]
self.cursor.execute("""
begin
:p_ReturnValue := pkg_TestDateArrays.TestInArrays(
:p_StartValue, :p_BaseDate, :p_Array);
end;""",
p_ReturnValue = returnValue,
p_StartValue = 6,
p_BaseDate = cx_Oracle.Date(2002, 12, 13),
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 26.5)
def testBindDateArrayByVar(self):
"test binding in a date array (with arrayvar)"
returnValue = self.cursor.var(cx_Oracle.NUMBER)
array = self.cursor.arrayvar(cx_Oracle.DATETIME, 10, 20)
array.setvalue(0, [r[1] for r in self.rawData])
self.cursor.execute("""
begin
:p_ReturnValue := pkg_TestDateArrays.TestInArrays(
:p_StartValue, :p_BaseDate, :p_Array);
end;""",
p_ReturnValue = returnValue,
p_StartValue = 7,
p_BaseDate = cx_Oracle.Date(2002, 12, 14),
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 17.5)
def testBindInOutDateArrayByVar(self):
"test binding in/out a date array (with arrayvar)"
array = self.cursor.arrayvar(cx_Oracle.DATETIME, 10, 100)
originalData = [r[1] for r in self.rawData]
array.setvalue(0, originalData)
self.cursor.execute("""
begin
pkg_TestDateArrays.TestInOutArrays(:p_NumElems, :p_Array);
end;""",
p_NumElems = 5,
p_Array = array)
self.failUnlessEqual(array.getvalue(),
[ cx_Oracle.Timestamp(2002, 12, 17, 2, 24, 0),
cx_Oracle.Timestamp(2002, 12, 18, 4, 48, 0),
cx_Oracle.Timestamp(2002, 12, 19, 7, 12, 0),
cx_Oracle.Timestamp(2002, 12, 20, 9, 36, 0),
cx_Oracle.Timestamp(2002, 12, 21, 12, 0, 0) ] + \
originalData[5:])
def testBindOutDateArrayByVar(self):
"test binding out a date array (with arrayvar)"
array = self.cursor.arrayvar(cx_Oracle.DATETIME, 6, 100)
self.cursor.execute("""
begin
pkg_TestDateArrays.TestOutArrays(:p_NumElems, :p_Array);
end;""",
p_NumElems = 6,
p_Array = array)
self.failUnlessEqual(array.getvalue(),
[ cx_Oracle.Timestamp(2002, 12, 13, 4, 48, 0),
cx_Oracle.Timestamp(2002, 12, 14, 9, 36, 0),
cx_Oracle.Timestamp(2002, 12, 15, 14, 24, 0),
cx_Oracle.Timestamp(2002, 12, 16, 19, 12, 0),
cx_Oracle.Timestamp(2002, 12, 18, 0, 0, 0),
cx_Oracle.Timestamp(2002, 12, 19, 4, 48, 0) ])
def testBindOutSetInputSizes(self):
"test binding out with set input sizes defined"
vars = self.cursor.setinputsizes(p_Value = cx_Oracle.DATETIME)
self.cursor.execute("""
begin
:p_Value := to_date(20021209, 'YYYYMMDD');
end;""")
self.failUnlessEqual(vars["p_Value"].getvalue(),
cx_Oracle.Timestamp(2002, 12, 9))
def testBindInOutSetInputSizes(self):
"test binding in/out with set input sizes defined"
vars = self.cursor.setinputsizes(p_Value = cx_Oracle.DATETIME)
self.cursor.execute("""
begin
:p_Value := :p_Value + 5.25;
end;""",
p_Value = cx_Oracle.Timestamp(2002, 12, 12, 10, 0, 0))
self.failUnlessEqual(vars["p_Value"].getvalue(),
cx_Oracle.Timestamp(2002, 12, 17, 16, 0, 0))
def testBindOutVar(self):
"test binding out with cursor.var() method"
var = self.cursor.var(cx_Oracle.DATETIME)
self.cursor.execute("""
begin
:p_Value := to_date('20021231 12:31:00',
'YYYYMMDD HH24:MI:SS');
end;""",
p_Value = var)
self.failUnlessEqual(var.getvalue(),
cx_Oracle.Timestamp(2002, 12, 31, 12, 31, 0))
def testBindInOutVarDirectSet(self):
"test binding in/out with cursor.var() method"
var = self.cursor.var(cx_Oracle.DATETIME)
var.setvalue(0, cx_Oracle.Timestamp(2002, 12, 9, 6, 0, 0))
self.cursor.execute("""
begin
:p_Value := :p_Value + 5.25;
end;""",
p_Value = var)
self.failUnlessEqual(var.getvalue(),
cx_Oracle.Timestamp(2002, 12, 14, 12, 0, 0))
def testCursorDescription(self):
"test cursor description is accurate"
self.cursor.execute("select * from TestDates")
self.failUnlessEqual(self.cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('DATECOL', cx_Oracle.DATETIME, 23, 7, 0, 0, 0),
('NULLABLECOL', cx_Oracle.DATETIME, 23, 7, 0, 0, 1) ])
def testFetchAll(self):
"test that fetching all of the data returns the correct results"
self.cursor.execute("select * From TestDates order by IntCol")
self.failUnlessEqual(self.cursor.fetchall(), self.rawData)
self.failUnlessEqual(self.cursor.fetchall(), [])
def testFetchMany(self):
"test that fetching data in chunks returns the correct results"
self.cursor.execute("select * From TestDates order by IntCol")
self.failUnlessEqual(self.cursor.fetchmany(3), self.rawData[0:3])
self.failUnlessEqual(self.cursor.fetchmany(2), self.rawData[3:5])
self.failUnlessEqual(self.cursor.fetchmany(4), self.rawData[5:9])
self.failUnlessEqual(self.cursor.fetchmany(3), self.rawData[9:])
self.failUnlessEqual(self.cursor.fetchmany(3), [])
def testFetchOne(self):
"test that fetching a single row returns the correct results"
self.cursor.execute("""
select *
from TestDates
where IntCol in (3, 4)
order by IntCol""")
self.failUnlessEqual(self.cursor.fetchone(), self.dataByKey[3])
self.failUnlessEqual(self.cursor.fetchone(), self.dataByKey[4])
self.failUnlessEqual(self.cursor.fetchone(), None)

123
test/LobVar.py Normal file
View File

@ -0,0 +1,123 @@
"""Module for testing LOB (CLOB and BLOB) variables."""
class TestLobVar(BaseTestCase):
def __PerformTest(self, type, inputType):
longString = ""
directType = getattr(cx_Oracle, type)
self.cursor.execute("truncate table Test%ss" % type)
for i in range(0, 11):
if i > 0:
char = chr(ord('A') + i - 1)
longString += char * 25000
elif inputType != directType:
continue
self.cursor.setinputsizes(longString = inputType)
self.cursor.execute("""
insert into Test%ss (
IntCol,
%sCol
) values (
:integerValue,
:longString
)""" % (type, type),
integerValue = i,
longString = longString)
self.connection.commit()
self.cursor.execute("""
select *
from Test%ss
order by IntCol""" % type)
longString = ""
for row in self.cursor:
integerValue, lob = row
if integerValue == 0:
self.failUnlessEqual(lob.size(), 0)
self.failUnlessEqual(lob.read(), "")
else:
char = chr(ord('A') + integerValue - 1)
prevChar = chr(ord('A') + integerValue - 2)
longString += char * 25000
self.failUnlessEqual(lob.size(), len(longString))
self.failUnlessEqual(lob.read(), longString)
self.failUnlessEqual(str(lob), longString)
self.failUnlessEqual(lob.read(len(longString)), char)
if integerValue > 1:
offset = (integerValue - 1) * 25000 - 4
string = prevChar * 5 + char * 5
self.failUnlessEqual(lob.read(offset, 10), string)
def __TestTrim(self, type):
self.cursor.execute("truncate table Test%ss" % type)
self.cursor.setinputsizes(longString = getattr(cx_Oracle, type))
self.cursor.execute("""
insert into Test%ss (
IntCol,
%sCol
) values (
:integerValue,
:longString
)""" % (type, type),
integerValue = 1,
longString = "X" * 75000)
self.cursor.execute("""
select %sCol
from Test%ss
where IntCol = 1""" % (type, type))
lob, = self.cursor.fetchone()
self.failUnlessEqual(lob.size(), 75000)
lob.trim(25000)
self.failUnlessEqual(lob.size(), 25000)
lob.trim()
self.failUnlessEqual(lob.size(), 0)
def testBLOBsIndirect(self):
"test binding and fetching BLOB data (indirectly)"
self.__PerformTest("BLOB", cx_Oracle.LONG_BINARY)
def testCLOBsIndirect(self):
"test binding and fetching CLOB data (indirectly)"
self.__PerformTest("CLOB", cx_Oracle.LONG_STRING)
def testBLOBsDirect(self):
"test binding and fetching BLOB data (directly)"
self.__PerformTest("BLOB", cx_Oracle.BLOB)
def testCLOBsDirect(self):
"test binding and fetching CLOB data (directly)"
self.__PerformTest("CLOB", cx_Oracle.CLOB)
def testCLOBCursorDescription(self):
"test cursor description is accurate for CLOBs"
self.cursor.execute("select * from TestCLOBs")
self.failUnlessEqual(self.cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('CLOBCOL', cx_Oracle.CLOB, -1, 4000, 0, 0, 0) ])
def testBLOBCursorDescription(self):
"test cursor description is accurate for BLOBs"
self.cursor.execute("select * from TestBLOBs")
self.failUnlessEqual(self.cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('BLOBCOL', cx_Oracle.BLOB, -1, 4000, 0, 0, 0) ])
def testBLOBTrim(self):
"test trimming a BLOB"
self.__TestTrim("BLOB")
def testCLOBTrim(self):
"test trimming a CLOB"
self.__TestTrim("CLOB")
def testMultipleFetch(self):
"test retrieving data from a CLOB after multiple fetches"
self.cursor.arraysize = 1
self.cursor.execute("select CLOBCol from TestCLOBS")
rows = self.cursor.fetchall()
self.failUnlessRaises(cx_Oracle.ProgrammingError, rows[1][0].read)
if __name__ == "__main__":
print "Testing cx_Oracle version", cx_Oracle.version
unittest.main()

91
test/LongVar.py Normal file
View File

@ -0,0 +1,91 @@
"""Module for testing long and long raw variables."""
class TestLongVar(BaseTestCase):
def __PerformTest(self, a_Type, a_InputType):
self.cursor.execute("truncate table Test%ss" % a_Type)
longString = ""
for i in range(1, 11):
char = chr(ord('A') + i - 1)
longString += char * 25000
self.cursor.setinputsizes(p_LongString = a_InputType)
self.cursor.execute("""
insert into Test%ss (
IntCol,
%sCol
) values (
:p_IntegerValue,
:p_LongString
)""" % (a_Type, a_Type),
p_IntegerValue = i,
p_LongString = longString)
self.connection.commit()
self.cursor.setoutputsize(250000, 2)
self.cursor.execute("""
select *
from Test%ss
order by IntCol""" % a_Type)
longString = ""
while 1:
row = self.cursor.fetchone()
if row is None:
break
integerValue, fetchedValue = row
char = chr(ord('A') + integerValue - 1)
longString += char * 25000
self.failUnlessEqual(len(fetchedValue), integerValue * 25000)
self.failUnlessEqual(fetchedValue, longString)
def testLongs(self):
"test binding and fetching long data"
self.__PerformTest("Long", cx_Oracle.LONG_STRING)
def testLongRaws(self):
"test binding and fetching long raw data"
self.__PerformTest("LongRaw", cx_Oracle.LONG_BINARY)
def testLongCursorDescription(self):
"test cursor description is accurate for longs"
self.cursor.execute("select * from TestLongs")
self.failUnlessEqual(self.cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('LONGCOL', cx_Oracle.LONG_STRING, -1, 0, 0, 0, 0) ])
def testLongRawCursorDescription(self):
"test cursor description is accurate for long raws"
self.cursor.execute("select * from TestLongRaws")
self.failUnlessEqual(self.cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('LONGRAWCOL', cx_Oracle.LONG_BINARY, -1, 0, 0, 0, 0) ])
def testSetOutputSizesAll(self):
"test setoutputsizes is valid (all)"
self.cursor.setoutputsize(25000)
longVar = self.cursor.execute("select * from TestLongRaws")[1]
self.failUnlessEqual(longVar.maxlength,
25004 * self.connection.maxBytesPerCharacter)
def testSetOutputSizesWrongColumn(self):
"test setoutputsizes is valid (wrong column)"
self.cursor.setoutputsize(25000, 1)
longVar = self.cursor.execute("select * from TestLongRaws")[1]
self.failUnlessEqual(longVar.maxlength,
131072 * self.connection.maxBytesPerCharacter)
def testSetOutputSizesRightColumn(self):
"test setoutputsizes is valid (right column)"
self.cursor.setoutputsize(35000, 2)
longVar = self.cursor.execute("select * from TestLongRaws")[1]
self.failUnlessEqual(longVar.maxlength,
35004 * self.connection.maxBytesPerCharacter)
def testArraySizeTooLarge(self):
"test array size too large generates an exception"
self.cursor.arraysize = 65536
self.failUnlessRaises(ValueError, self.cursor.execute,
"select * from TestLongRaws")
if __name__ == "__main__":
print "Testing cx_Oracle version", cx_Oracle.version
unittest.main()

273
test/NumberVar.py Normal file
View File

@ -0,0 +1,273 @@
"""Module for testing number variables."""
import cx_Oracle
import sys
class TestNumberVar(BaseTestCase):
def setUp(self):
BaseTestCase.setUp(self)
self.rawData = []
self.dataByKey = {}
for i in range(1, 11):
numberCol = i + i * 0.25
floatCol = i + i * 0.75
unconstrainedCol = i ** 3 + i * 0.5
if i % 2:
nullableCol = 143L ** i
else:
nullableCol = None
dataTuple = (i, numberCol, floatCol, unconstrainedCol, nullableCol)
self.rawData.append(dataTuple)
self.dataByKey[i] = dataTuple
if sys.version_info[:2] > (2, 3):
def testBindDecimal(self):
"test binding in a decimal.Decimal"
import decimal
self.cursor.execute("""
select * from TestNumbers
where NumberCol - :value1 - :value2 = trunc(NumberCol)""",
value1 = decimal.Decimal("0.20"),
value2 = decimal.Decimal("0.05"))
self.failUnlessEqual(self.cursor.fetchall(),
[self.dataByKey[1], self.dataByKey[5], self.dataByKey[9]])
def testBindFloat(self):
"test binding in a float"
self.cursor.execute("""
select * from TestNumbers
where NumberCol - :value = trunc(NumberCol)""",
value = 0.25)
self.failUnlessEqual(self.cursor.fetchall(),
[self.dataByKey[1], self.dataByKey[5], self.dataByKey[9]])
def testBindInteger(self):
"test binding in an integer"
self.cursor.execute("""
select * from TestNumbers
where IntCol = :value""",
value = 2)
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[2]])
def testBindSmallLong(self):
"test binding in a small long integer"
self.cursor.execute("""
select * from TestNumbers
where IntCol = :value""",
value = 3L)
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[3]])
def testBindLargeLong(self):
"test binding in a large long integer"
valueVar = self.cursor.var(cx_Oracle.NUMBER)
valueVar.setvalue(0, 6088343244)
self.cursor.execute("""
begin
:value := :value + 5;
end;""",
value = valueVar)
value = valueVar.getvalue()
self.failUnlessEqual(value, 6088343249)
def testBindIntegerAfterString(self):
"test binding in an number after setting input sizes to a string"
self.cursor.setinputsizes(value = 15)
self.cursor.execute("""
select * from TestNumbers
where IntCol = :value""",
value = 3)
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[3]])
def testBindNull(self):
"test binding in a null"
self.cursor.execute("""
select * from TestNumbers
where IntCol = :value""",
value = None)
self.failUnlessEqual(self.cursor.fetchall(), [])
def testBindNumberArrayDirect(self):
"test binding in a number array"
returnValue = self.cursor.var(cx_Oracle.NUMBER)
array = [r[1] for r in self.rawData]
statement = """
begin
:p_ReturnValue := pkg_TestNumberArrays.TestInArrays(
:p_StartValue, :p_Array);
end;"""
self.cursor.execute(statement,
p_ReturnValue = returnValue,
p_StartValue = 5,
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 73.75)
array = range(15)
self.cursor.execute(statement,
p_StartValue = 10,
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 115.0)
def testBindNumberArrayBySizes(self):
"test binding in a number array (with setinputsizes)"
returnValue = self.cursor.var(cx_Oracle.NUMBER)
self.cursor.setinputsizes(p_Array = [cx_Oracle.NUMBER, 10])
array = [r[1] for r in self.rawData]
self.cursor.execute("""
begin
:p_ReturnValue := pkg_TestNumberArrays.TestInArrays(
:p_StartValue, :p_Array);
end;""",
p_ReturnValue = returnValue,
p_StartValue = 6,
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 74.75)
def testBindNumberArrayByVar(self):
"test binding in a number array (with arrayvar)"
returnValue = self.cursor.var(cx_Oracle.NUMBER)
array = self.cursor.arrayvar(cx_Oracle.NUMBER,
[r[1] for r in self.rawData])
array.setvalue(0, [r[1] for r in self.rawData])
self.cursor.execute("""
begin
:p_ReturnValue := pkg_TestNumberArrays.TestInArrays(
:p_IntegerValue, :p_Array);
end;""",
p_ReturnValue = returnValue,
p_IntegerValue = 7,
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 75.75)
def testBindZeroLengthNumberArrayByVar(self):
"test binding in a zero length number array (with arrayvar)"
returnValue = self.cursor.var(cx_Oracle.NUMBER)
array = self.cursor.arrayvar(cx_Oracle.NUMBER, 0)
self.cursor.execute("""
begin
:p_ReturnValue := pkg_TestNumberArrays.TestInArrays(
:p_IntegerValue, :p_Array);
end;""",
p_ReturnValue = returnValue,
p_IntegerValue = 8,
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 8.0)
self.failUnlessEqual(array.getvalue(), [])
def testBindInOutNumberArrayByVar(self):
"test binding in/out a number array (with arrayvar)"
array = self.cursor.arrayvar(cx_Oracle.NUMBER, 10)
originalData = [r[1] for r in self.rawData]
expectedData = [originalData[i - 1] * 10 for i in range(1, 6)] + \
originalData[5:]
array.setvalue(0, originalData)
self.cursor.execute("""
begin
pkg_TestNumberArrays.TestInOutArrays(:p_NumElems, :p_Array);
end;""",
p_NumElems = 5,
p_Array = array)
self.failUnlessEqual(array.getvalue(), expectedData)
def testBindOutNumberArrayByVar(self):
"test binding out a Number array (with arrayvar)"
array = self.cursor.arrayvar(cx_Oracle.NUMBER, 6)
expectedData = [i * 100 for i in range(1, 7)]
self.cursor.execute("""
begin
pkg_TestNumberArrays.TestOutArrays(:p_NumElems, :p_Array);
end;""",
p_NumElems = 6,
p_Array = array)
self.failUnlessEqual(array.getvalue(), expectedData)
def testBindOutSetInputSizes(self):
"test binding out with set input sizes defined"
vars = self.cursor.setinputsizes(value = cx_Oracle.NUMBER)
self.cursor.execute("""
begin
:value := 5;
end;""")
self.failUnlessEqual(vars["value"].getvalue(), 5)
def testBindInOutSetInputSizes(self):
"test binding in/out with set input sizes defined"
vars = self.cursor.setinputsizes(value = cx_Oracle.NUMBER)
self.cursor.execute("""
begin
:value := :value + 5;
end;""",
value = 1.25)
self.failUnlessEqual(vars["value"].getvalue(), 6.25)
def testBindOutVar(self):
"test binding out with cursor.var() method"
var = self.cursor.var(cx_Oracle.NUMBER)
self.cursor.execute("""
begin
:value := 5;
end;""",
value = var)
self.failUnlessEqual(var.getvalue(), 5)
def testBindInOutVarDirectSet(self):
"test binding in/out with cursor.var() method"
var = self.cursor.var(cx_Oracle.NUMBER)
var.setvalue(0, 2.25)
self.cursor.execute("""
begin
:value := :value + 5;
end;""",
value = var)
self.failUnlessEqual(var.getvalue(), 7.25)
def testCursorDescription(self):
"test cursor description is accurate"
self.cursor.execute("select * from TestNumbers")
self.failUnlessEqual(self.cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('NUMBERCOL', cx_Oracle.NUMBER, 13, 22, 9, 2, 0),
('FLOATCOL', cx_Oracle.NUMBER, 127, 22, 126, -127, 0),
('UNCONSTRAINEDCOL', cx_Oracle.NUMBER, 127, 22, 0, -127, 0),
('NULLABLECOL', cx_Oracle.NUMBER, 39, 22, 38, 0, 1) ])
def testFetchAll(self):
"test that fetching all of the data returns the correct results"
self.cursor.execute("select * From TestNumbers order by IntCol")
self.failUnlessEqual(self.cursor.fetchall(), self.rawData)
self.failUnlessEqual(self.cursor.fetchall(), [])
def testFetchMany(self):
"test that fetching data in chunks returns the correct results"
self.cursor.execute("select * From TestNumbers order by IntCol")
self.failUnlessEqual(self.cursor.fetchmany(3), self.rawData[0:3])
self.failUnlessEqual(self.cursor.fetchmany(2), self.rawData[3:5])
self.failUnlessEqual(self.cursor.fetchmany(4), self.rawData[5:9])
self.failUnlessEqual(self.cursor.fetchmany(3), self.rawData[9:])
self.failUnlessEqual(self.cursor.fetchmany(3), [])
def testFetchOne(self):
"test that fetching a single row returns the correct results"
self.cursor.execute("""
select *
from TestNumbers
where IntCol in (3, 4)
order by IntCol""")
self.failUnlessEqual(self.cursor.fetchone(), self.dataByKey[3])
self.failUnlessEqual(self.cursor.fetchone(), self.dataByKey[4])
self.failUnlessEqual(self.cursor.fetchone(), None)
def testReturnAsLong(self):
"test that fetching a long integer returns such in Python"
self.cursor.execute("""
select NullableCol
from TestNumbers
where IntCol = 9""")
col, = self.cursor.fetchone()
self.failUnless(isinstance(col, long), "long integer not returned")
def testReturnAsFloat(self):
"test that fetching a floating point number returns such in Python"
self.cursor.execute("select 1.25 from dual")
result, = self.cursor.fetchone()
self.failUnlessEqual(result, 1.25)

38
test/ObjectVar.py Normal file
View File

@ -0,0 +1,38 @@
"""Module for testing object variables."""
import sys
class TestObjectVar(BaseTestCase):
def __TestData(self, expectedIntValue, expectedObjectValue,
expectedArrayValue):
intValue, objectValue, arrayValue = self.cursor.fetchone()
if objectValue is not None:
attributeValues = []
for attribute in objectValue.type.attributes:
value = getattr(objectValue, attribute.name)
attributeValues.append(value)
objectValue = tuple(attributeValues)
self.failUnlessEqual(intValue, expectedIntValue)
self.failUnlessEqual(objectValue, expectedObjectValue)
self.failUnlessEqual(arrayValue, expectedArrayValue)
def testFetchData(self):
"test fetching objects"
self.cursor.execute("""
select
IntCol,
ObjectCol,
ArrayCol
from TestObjects
order by IntCol""")
self.failUnlessEqual(self.cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('OBJECTCOL', cx_Oracle.OBJECT, -1, 2000, 0, 0, 1),
('ARRAYCOL', cx_Oracle.OBJECT, -1, 2000, 0, 0, 1) ])
self.__TestData(1, (1, 'First row',
cx_Oracle.Timestamp(2007, 3, 6, 0, 0, 0)), [5, 10, None, 20])
self.__TestData(2, None, [3, None, 9, 12, 15])
self.__TestData(3, (3, 'Third row',
cx_Oracle.Timestamp(2007, 6, 21, 0, 0, 0)), None)

80
test/SessionPool.py Normal file
View File

@ -0,0 +1,80 @@
"""Module for testing session pools."""
import threading
class TestConnection(TestCase):
def __ConnectAndDrop(self):
"""Connect to the database, perform a query and drop the connection."""
connection = self.pool.acquire()
cursor = connection.cursor()
cursor.execute("select count(*) from TestNumbers")
count, = cursor.fetchone()
self.failUnlessEqual(count, 10)
def testPool(self):
"""test that the pool is created and has the right attributes"""
pool = cx_Oracle.SessionPool(USERNAME, PASSWORD, TNSENTRY, 2, 8, 3)
self.failUnlessEqual(pool.username, USERNAME, "user name differs")
self.failUnlessEqual(pool.password, PASSWORD, "password differs")
self.failUnlessEqual(pool.tnsentry, TNSENTRY, "tnsentry differs")
self.failUnlessEqual(pool.max, 8, "max differs")
self.failUnlessEqual(pool.min, 2, "min differs")
self.failUnlessEqual(pool.increment, 3, "increment differs")
self.failUnlessEqual(pool.opened, 2, "opened differs")
self.failUnlessEqual(pool.busy, 0, "busy not 0 at start")
connection_1 = pool.acquire()
self.failUnlessEqual(pool.busy, 1, "busy not 1 after acquire")
self.failUnlessEqual(pool.opened, 2, "opened not unchanged (1)")
connection_2 = pool.acquire()
self.failUnlessEqual(pool.busy, 2, "busy not 2 after acquire")
self.failUnlessEqual(pool.opened, 2, "opened not unchanged (2)")
connection_3 = pool.acquire()
self.failUnlessEqual(pool.busy, 3, "busy not 3 after acquire")
self.failUnlessEqual(pool.opened, 5, "opened not changed (3)")
pool.release(connection_3)
self.failUnlessEqual(pool.busy, 2, "busy not 2 after release")
del connection_2
self.failUnlessEqual(pool.busy, 1, "busy not 1 after del")
def testRollbackOnDel(self):
"connection rolls back before being destroyed"
pool = cx_Oracle.SessionPool(USERNAME, PASSWORD, TNSENTRY, 1, 8, 3)
connection = pool.acquire()
cursor = connection.cursor()
cursor.execute("truncate table TestExecuteMany")
cursor.execute("insert into TestExecuteMany values (1)")
pool = cx_Oracle.SessionPool(USERNAME, PASSWORD, TNSENTRY, 1, 8, 3)
connection = pool.acquire()
cursor = connection.cursor()
cursor.execute("select count(*) from TestExecuteMany")
count, = cursor.fetchone()
self.failUnlessEqual(count, 0)
def testRollbackOnRelease(self):
"connection rolls back before released back to the pool"
pool = cx_Oracle.SessionPool(USERNAME, PASSWORD, TNSENTRY, 1, 8, 3)
connection = pool.acquire()
cursor = connection.cursor()
cursor.execute("truncate table TestExecuteMany")
cursor.execute("insert into TestExecuteMany values (1)")
pool.release(connection)
pool = cx_Oracle.SessionPool(USERNAME, PASSWORD, TNSENTRY, 1, 8, 3)
connection = pool.acquire()
cursor = connection.cursor()
cursor.execute("select count(*) from TestExecuteMany")
count, = cursor.fetchone()
self.failUnlessEqual(count, 0)
def testThreading(self):
"""test session pool to database with multiple threads"""
self.pool = cx_Oracle.SessionPool(USERNAME, PASSWORD, TNSENTRY, 5, 20,
2, threaded = True)
threads = []
for i in range(20):
thread = threading.Thread(None, self.__ConnectAndDrop)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()

411
test/SetupTest.sql Normal file
View File

@ -0,0 +1,411 @@
/*-----------------------------------------------------------------------------
* SetupTest.sql
* Creates a user named "cx_Oracle" and populates its schema with the tables
* and packages necessary for performing the test suite.
*---------------------------------------------------------------------------*/
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_numeric_characters='.,';
create user cx_Oracle identified by dev
quota unlimited on users
default tablespace users;
grant
create session,
create table,
create procedure,
create type
to cx_Oracle;
-- create types
create type cx_Oracle.udt_Object as object (
NumberValue number,
StringValue varchar2(60),
DateValue date
);
/
create type cx_Oracle.udt_Array as varray(10) of number;
/
-- create tables
create table cx_Oracle.TestNumbers (
IntCol number(9) not null,
NumberCol number(9, 2) not null,
FloatCol float not null,
UnconstrainedCol number not null,
NullableCol number(38)
) tablespace users;
create table cx_Oracle.TestStrings (
IntCol number(9) not null,
StringCol varchar2(20) not null,
RawCol raw(30) not null,
FixedCharCol char(40) not null,
NullableCol varchar2(50)
) tablespace users;
create table cx_Oracle.TestDates (
IntCol number(9) not null,
DateCol date not null,
NullableCol date
) tablespace users;
create table cx_Oracle.TestCLOBs (
IntCol number(9) not null,
CLOBCol clob not null
) tablespace users;
create table cx_Oracle.TestBLOBs (
IntCol number(9) not null,
BLOBCol blob not null
) tablespace users;
create table cx_Oracle.TestLongs (
IntCol number(9) not null,
LongCol long not null
) tablespace users;
create table cx_Oracle.TestLongRaws (
IntCol number(9) not null,
LongRawCol long raw not null
) tablespace users;
create table cx_Oracle.TestExecuteMany (
IntCol number(9) not null
) tablespace users;
create table cx_Oracle.TestObjects (
IntCol number(9) not null,
ObjectCol cx_Oracle.udt_Object,
ArrayCol cx_Oracle.udt_Array
);
alter table cx_Oracle.testexecutemany
add constraint testexecutemany_pk
primary key (
intcol
) using index tablespace users;
-- populate tables
begin
for i in 1..10 loop
insert into cx_Oracle.TestNumbers
values (i, i + i * 0.25, i + i * .75, i * i * i + i *.5,
decode(mod(i, 2), 0, null, power(143, i)));
end loop;
end;
/
declare
t_RawValue raw(30);
function ConvertHexDigit(a_Value number) return varchar2 is
begin
if a_Value between 0 and 9 then
return to_char(a_Value);
end if;
return chr(ascii('A') + a_Value - 10);
end;
function ConvertToHex(a_Value varchar2) return varchar2 is
t_HexValue varchar2(60);
t_Digit number;
begin
for i in 1..length(a_Value) loop
t_Digit := ascii(substr(a_Value, i, 1));
t_HexValue := t_HexValue ||
ConvertHexDigit(trunc(t_Digit / 16)) ||
ConvertHexDigit(mod(t_Digit, 16));
end loop;
return t_HexValue;
end;
begin
for i in 1..10 loop
t_RawValue := hextoraw(ConvertToHex('Raw ' || to_char(i)));
insert into cx_Oracle.TestStrings
values (i, 'String ' || to_char(i), t_RawValue,
'Fixed Char ' || to_char(i),
decode(mod(i, 2), 0, null, 'Nullable ' || to_char(i)));
end loop;
end;
/
begin
for i in 1..10 loop
insert into cx_Oracle.TestDates
values (i, to_date(20021209, 'YYYYMMDD') + i + i * .1,
decode(mod(i, 2), 0, null,
to_date(20021209, 'YYYYMMDD') + i + i + i * .15));
end loop;
end;
/
insert into cx_Oracle.TestObjects values (1,
cx_Oracle.udt_Object(1, 'First row',
to_date(20070306, 'YYYYMMDD')),
cx_Oracle.udt_Array(5, 10, null, 20));
insert into cx_Oracle.TestObjects values (2, null,
cx_Oracle.udt_Array(3, null, 9, 12, 15));
insert into cx_Oracle.TestObjects values (3,
cx_Oracle.udt_Object(3, 'Third row',
to_date(20070621, 'YYYYMMDD')), null);
commit;
-- create procedures for testing callproc()
create procedure cx_Oracle.proc_Test (
a_InValue varchar2,
a_InOutValue in out number,
a_OutValue out number
) as
begin
a_InOutValue := a_InOutValue * length(a_InValue);
a_OutValue := length(a_InValue);
end;
/
create procedure cx_Oracle.proc_TestNoArgs as
begin
null;
end;
/
-- create functions for testing callfunc()
create function cx_Oracle.func_Test (
a_String varchar2,
a_ExtraAmount number
) return number as
begin
return length(a_String) + a_ExtraAmount;
end;
/
create function cx_Oracle.func_TestNoArgs
return number as
begin
return 712;
end;
/
-- create packages
create or replace package cx_Oracle.pkg_TestStringArrays as
type udt_StringList is table of varchar2(100) index by binary_integer;
function TestInArrays (
a_StartingLength number,
a_Array udt_StringList
) return number;
procedure TestInOutArrays (
a_NumElems number,
a_Array in out nocopy udt_StringList
);
procedure TestOutArrays (
a_NumElems number,
a_Array out nocopy udt_StringList
);
end;
/
create or replace package body cx_Oracle.pkg_TestStringArrays as
function TestInArrays (
a_StartingLength number,
a_Array udt_StringList
) return number is
t_Length number;
begin
t_Length := a_StartingLength;
for i in 1..a_Array.count loop
t_Length := t_Length + length(a_Array(i));
end loop;
return t_Length;
end;
procedure TestInOutArrays (
a_NumElems number,
a_Array in out udt_StringList
) is
begin
for i in 1..a_NumElems loop
a_Array(i) := 'Converted element # ' ||
to_char(i) || ' originally had length ' ||
to_char(length(a_Array(i)));
end loop;
end;
procedure TestOutArrays (
a_NumElems number,
a_Array out udt_StringList
) is
begin
for i in 1..a_NumElems loop
a_Array(i) := 'Test out element # ' || to_char(i);
end loop;
end;
end;
/
create or replace package cx_Oracle.pkg_TestNumberArrays as
type udt_NumberList is table of number index by binary_integer;
function TestInArrays (
a_StartingValue number,
a_Array udt_NumberList
) return number;
procedure TestInOutArrays (
a_NumElems number,
a_Array in out nocopy udt_NumberList
);
procedure TestOutArrays (
a_NumElems number,
a_Array out nocopy udt_NumberList
);
end;
/
create or replace package body cx_Oracle.pkg_TestNumberArrays as
function TestInArrays (
a_StartingValue number,
a_Array udt_NumberList
) return number is
t_Value number;
begin
t_Value := a_StartingValue;
for i in 1..a_Array.count loop
t_Value := t_Value + a_Array(i);
end loop;
return t_Value;
end;
procedure TestInOutArrays (
a_NumElems number,
a_Array in out udt_NumberList
) is
begin
for i in 1..a_NumElems loop
a_Array(i) := a_Array(i) * 10;
end loop;
end;
procedure TestOutArrays (
a_NumElems number,
a_Array out udt_NumberList
) is
begin
for i in 1..a_NumElems loop
a_Array(i) := i * 100;
end loop;
end;
end;
/
create or replace package cx_Oracle.pkg_TestDateArrays as
type udt_DateList is table of date index by binary_integer;
function TestInArrays (
a_StartingValue number,
a_BaseDate date,
a_Array udt_DateList
) return number;
procedure TestInOutArrays (
a_NumElems number,
a_Array in out nocopy udt_DateList
);
procedure TestOutArrays (
a_NumElems number,
a_Array out nocopy udt_DateList
);
end;
/
create or replace package body cx_Oracle.pkg_TestDateArrays as
function TestInArrays (
a_StartingValue number,
a_BaseDate date,
a_Array udt_DateList
) return number is
t_Value number;
begin
t_Value := a_StartingValue;
for i in 1..a_Array.count loop
t_Value := t_Value + a_Array(i) - a_BaseDate;
end loop;
return t_Value;
end;
procedure TestInOutArrays (
a_NumElems number,
a_Array in out udt_DateList
) is
begin
for i in 1..a_NumElems loop
a_Array(i) := a_Array(i) + 7;
end loop;
end;
procedure TestOutArrays (
a_NumElems number,
a_Array out udt_DateList
) is
begin
for i in 1..a_NumElems loop
a_Array(i) := to_date(20021212, 'YYYYMMDD') + i * 1.2;
end loop;
end;
end;
/
create or replace package cx_Oracle.pkg_TestOutCursors as
type udt_RefCursor is ref cursor;
procedure TestOutCursor (
a_MaxIntValue number,
a_Cursor out udt_RefCursor
);
end;
/
create or replace package body cx_Oracle.pkg_TestOutCursors as
procedure TestOutCursor (
a_MaxIntValue number,
a_Cursor out udt_RefCursor
) is
begin
open a_Cursor for
select
IntCol,
StringCol
from TestStrings
where IntCol <= a_MaxIntValue
order by IntCol;
end;
end;
/

30
test/SetupTest_9i.sql Normal file
View File

@ -0,0 +1,30 @@
/*-----------------------------------------------------------------------------
* SetupTest_9i.sql
* Additional setup for Oracle 9i databases only.
*---------------------------------------------------------------------------*/
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_numeric_characters='.,';
create table cx_Oracle.TestTimestamps (
IntCol number(9) not null,
TimestampCol timestamp not null,
NullableCol timestamp
) tablespace users;
begin
for i in 1..10 loop
insert into cx_Oracle.TestTimestamps
values (i, to_timestamp('20021209', 'YYYYMMDD') +
to_dsinterval(to_char(i) || ' 00:00:' || to_char(i * 2) || '.' ||
to_char(i * 50)),
decode(mod(i, 2), 0, to_timestamp(null, 'YYYYMMDD'),
to_timestamp('20021209', 'YYYYMMDD') +
to_dsinterval(to_char(i + 1) || ' 00:00:' ||
to_char(i * 3) || '.' || to_char(i * 125))));
end loop;
end;
/
commit;

290
test/StringVar.py Normal file
View File

@ -0,0 +1,290 @@
"""Module for testing string variables."""
class TestStringVar(BaseTestCase):
def setUp(self):
BaseTestCase.setUp(self)
self.rawData = []
self.dataByKey = {}
for i in range(1, 11):
stringCol = "String %d" % i
fixedCharCol = ("Fixed Char %d" % i).ljust(40)
rawCol = "Raw %d" % i
if i % 2:
nullableCol = "Nullable %d" % i
else:
nullableCol = None
dataTuple = (i, stringCol, rawCol, fixedCharCol, nullableCol)
self.rawData.append(dataTuple)
self.dataByKey[i] = dataTuple
def testBindString(self):
"test binding in a string"
self.cursor.execute("""
select * from TestStrings
where StringCol = :p_Value""",
p_Value = "String 5")
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[5]])
def testBindDifferentVar(self):
"test binding a different variable on second execution"
retval_1 = self.cursor.var(cx_Oracle.STRING, 30)
retval_2 = self.cursor.var(cx_Oracle.STRING, 30)
self.cursor.execute("begin :retval := 'Called'; end;",
retval = retval_1)
self.failUnlessEqual(retval_1.getvalue(), "Called")
self.cursor.execute("begin :retval := 'Called'; end;",
retval = retval_2)
self.failUnlessEqual(retval_2.getvalue(), "Called")
def testBindStringAfterNumber(self):
"test binding in a string after setting input sizes to a number"
self.cursor.setinputsizes(p_Value = cx_Oracle.NUMBER)
self.cursor.execute("""
select * from TestStrings
where StringCol = :p_Value""",
p_Value = "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 = """
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 = [ "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)
self.cursor.setinputsizes(p_Array = [cx_Oracle.STRING, 10])
array = [r[1] for r in self.rawData]
self.cursor.execute("""
begin
:p_ReturnValue := pkg_TestStringArrays.TestInArrays(
:p_IntegerValue, :p_Array);
end;""",
p_ReturnValue = returnValue,
p_IntegerValue = 6,
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 87)
def testBindStringArrayByVar(self):
"test binding in a string array (with arrayvar)"
returnValue = self.cursor.var(cx_Oracle.NUMBER)
array = self.cursor.arrayvar(cx_Oracle.STRING, 10, 20)
array.setvalue(0, [r[1] for r in self.rawData])
self.cursor.execute("""
begin
:p_ReturnValue := pkg_TestStringArrays.TestInArrays(
:p_IntegerValue, :p_Array);
end;""",
p_ReturnValue = returnValue,
p_IntegerValue = 7,
p_Array = array)
self.failUnlessEqual(returnValue.getvalue(), 88)
def testBindInOutStringArrayByVar(self):
"test binding in/out a string array (with arrayvar)"
array = self.cursor.arrayvar(cx_Oracle.STRING, 10, 100)
originalData = [r[1] for r in self.rawData]
expectedData = ["Converted element # %d originally had length %d" % \
(i, len(originalData[i - 1])) for i in range(1, 6)] + \
originalData[5:]
array.setvalue(0, originalData)
self.cursor.execute("""
begin
pkg_TestStringArrays.TestInOutArrays(:p_NumElems, :p_Array);
end;""",
p_NumElems = 5,
p_Array = array)
self.failUnlessEqual(array.getvalue(), expectedData)
def testBindOutStringArrayByVar(self):
"test binding out a string array (with arrayvar)"
array = self.cursor.arrayvar(cx_Oracle.STRING, 6, 100)
expectedData = ["Test out element # %d" % i for i in range(1, 7)]
self.cursor.execute("""
begin
pkg_TestStringArrays.TestOutArrays(:p_NumElems, :p_Array);
end;""",
p_NumElems = 6,
p_Array = array)
self.failUnlessEqual(array.getvalue(), expectedData)
def testBindRaw(self):
"test binding in a raw"
self.cursor.setinputsizes(p_Value = cx_Oracle.BINARY)
self.cursor.execute("""
select * from TestStrings
where RawCol = :p_Value""",
p_Value = "Raw 4")
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[4]])
def testBindAndFetchRowid(self):
"test binding (and fetching) a rowid"
self.cursor.execute("""
select rowid
from TestStrings
where IntCol = 3""")
rowid, = self.cursor.fetchone()
self.cursor.execute("""
select *
from TestStrings
where rowid = :p_Value""",
p_Value = rowid)
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[3]])
def testBindNull(self):
"test binding in a null"
self.cursor.execute("""
select * from TestStrings
where StringCol = :p_Value""",
p_Value = None)
self.failUnlessEqual(self.cursor.fetchall(), [])
def testBindOutSetInputSizesByType(self):
"test binding out with set input sizes defined (by type)"
vars = self.cursor.setinputsizes(p_Value = cx_Oracle.STRING)
self.cursor.execute("""
begin
:p_Value := 'TSI';
end;""")
self.failUnlessEqual(vars["p_Value"].getvalue(), "TSI")
def testBindOutSetInputSizesByInteger(self):
"test binding out with set input sizes defined (by integer)"
vars = self.cursor.setinputsizes(p_Value = 30)
self.cursor.execute("""
begin
:p_Value := 'TSI (I)';
end;""")
self.failUnlessEqual(vars["p_Value"].getvalue(), "TSI (I)")
def testBindInOutSetInputSizesByType(self):
"test binding in/out with set input sizes defined (by type)"
vars = self.cursor.setinputsizes(p_Value = cx_Oracle.STRING)
self.cursor.execute("""
begin
:p_Value := :p_Value || ' TSI';
end;""",
p_Value = "InVal")
self.failUnlessEqual(vars["p_Value"].getvalue(), "InVal TSI")
def testBindInOutSetInputSizesByInteger(self):
"test binding in/out with set input sizes defined (by integer)"
vars = self.cursor.setinputsizes(p_Value = 30)
self.cursor.execute("""
begin
:p_Value := :p_Value || ' TSI (I)';
end;""",
p_Value = "InVal")
self.failUnlessEqual(vars["p_Value"].getvalue(), "InVal TSI (I)")
def testBindOutVar(self):
"test binding out with cursor.var() method"
var = self.cursor.var(cx_Oracle.STRING)
self.cursor.execute("""
begin
:p_Value := 'TSI (VAR)';
end;""",
p_Value = var)
self.failUnlessEqual(var.getvalue(), "TSI (VAR)")
def testBindInOutVarDirectSet(self):
"test binding in/out with cursor.var() method"
var = self.cursor.var(cx_Oracle.STRING)
var.setvalue(0, "InVal")
self.cursor.execute("""
begin
:p_Value := :p_Value || ' TSI (VAR)';
end;""",
p_Value = var)
self.failUnlessEqual(var.getvalue(), "InVal TSI (VAR)")
def testBindLongString(self):
"test that binding a long string succeeds"
self.cursor.execute("""
declare
t_Temp varchar2(10000);
begin
t_Temp := :bigString;
end;""",
bigString = "X" * 10000)
def testBindLongStringAfterSettingSize(self):
"test that setinputsizes() returns a long variable"
var = self.cursor.setinputsizes(test = 90000)["test"]
self.failUnlessEqual(type(var), cx_Oracle.LONG_STRING)
inString = "1234567890" * 9000
var.setvalue(0, inString)
outString = var.getvalue()
self.failUnlessEqual(inString, outString,
"output does not match: in was %d, out was %d" % \
(len(inString), len(outString)))
def testStringMaximumReached(self):
"test that an error is raised when maximum string length exceeded"
var = self.cursor.setinputsizes(test = 100)["test"]
inString = "1234567890" * 400
var.setvalue(0, inString)
outString = var.getvalue()
self.failUnlessEqual(inString, outString,
"output does not match: in was %d, out was %d" % \
(len(inString), len(outString)))
badStringSize = 4000 * self.connection.maxBytesPerCharacter + 1
inString = "X" * badStringSize
self.failUnlessRaises(ValueError, var.setvalue, 0, inString)
def testCursorDescription(self):
"test cursor description is accurate"
self.cursor.execute("select * from TestStrings")
self.failUnlessEqual(self.cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('STRINGCOL', cx_Oracle.STRING, 20, 20, 0, 0, 0),
('RAWCOL', cx_Oracle.BINARY, 30, 30, 0, 0, 0),
('FIXEDCHARCOL', cx_Oracle.FIXED_CHAR, 40, 40, 0, 0, 0),
('NULLABLECOL', cx_Oracle.STRING, 50, 50, 0, 0, 1) ])
def testFetchAll(self):
"test that fetching all of the data returns the correct results"
self.cursor.execute("select * From TestStrings order by IntCol")
self.failUnlessEqual(self.cursor.fetchall(), self.rawData)
self.failUnlessEqual(self.cursor.fetchall(), [])
def testFetchMany(self):
"test that fetching data in chunks returns the correct results"
self.cursor.execute("select * From TestStrings order by IntCol")
self.failUnlessEqual(self.cursor.fetchmany(3), self.rawData[0:3])
self.failUnlessEqual(self.cursor.fetchmany(2), self.rawData[3:5])
self.failUnlessEqual(self.cursor.fetchmany(4), self.rawData[5:9])
self.failUnlessEqual(self.cursor.fetchmany(3), self.rawData[9:])
self.failUnlessEqual(self.cursor.fetchmany(3), [])
def testFetchOne(self):
"test that fetching a single row returns the correct results"
self.cursor.execute("""
select *
from TestStrings
where IntCol in (3, 4)
order by IntCol""")
self.failUnlessEqual(self.cursor.fetchone(), self.dataByKey[3])
self.failUnlessEqual(self.cursor.fetchone(), self.dataByKey[4])
self.failUnlessEqual(self.cursor.fetchone(), None)
if __name__ == "__main__":
print "Testing cx_Oracle version", cx_Oracle.version
unittest.main()

17
test/TestEnv.py Normal file
View File

@ -0,0 +1,17 @@
"""Define test environment."""
import cx_Oracle
import os
import unittest
def GetValue(name, label):
value = os.environ.get("CX_ORACLE_" + name)
if value is None:
value = raw_input(label + ": ")
return value
USERNAME = GetValue("USERNAME", "user name")
PASSWORD = GetValue("PASSWORD", "password")
TNSENTRY = GetValue("TNSENTRY", "TNS entry")
ARRAY_SIZE = int(GetValue("ARRAY_SIZE", "array size"))

130
test/TimestampVar.py Normal file
View File

@ -0,0 +1,130 @@
"""Module for testing timestamp variables."""
import time
class TestTimestampVar(BaseTestCase):
def setUp(self):
BaseTestCase.setUp(self)
self.rawData = []
self.dataByKey = {}
for i in range(1, 11):
timeTuple = (2002, 12, 9, 0, 0, 0, 0, 0, -1)
timeInTicks = time.mktime(timeTuple) + i * 86400
dateValue = cx_Oracle.TimestampFromTicks(int(timeInTicks))
strValue = str(i * 50)
fsecond = int(strValue + "0" * (6 - len(strValue)))
dateCol = cx_Oracle.Timestamp(dateValue.year, dateValue.month,
dateValue.day, dateValue.hour, dateValue.minute,
i * 2, fsecond)
if i % 2:
timeInTicks = time.mktime(timeTuple) + i * 86400 + 86400
dateValue = cx_Oracle.TimestampFromTicks(int(timeInTicks))
strValue = str(i * 125)
fsecond = int(strValue + "0" * (6 - len(strValue)))
nullableCol = cx_Oracle.Timestamp(dateValue.year,
dateValue.month, dateValue.day, dateValue.hour,
dateValue.minute, i * 3, fsecond)
else:
nullableCol = None
tuple = (i, dateCol, nullableCol)
self.rawData.append(tuple)
self.dataByKey[i] = tuple
def testBindTimestamp(self):
"test binding in a timestamp"
self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
self.cursor.execute("""
select * from TestTimestamps
where TimestampCol = :value""",
value = cx_Oracle.Timestamp(2002, 12, 14, 0, 0, 10, 250000))
self.failUnlessEqual(self.cursor.fetchall(), [self.dataByKey[5]])
def testBindNull(self):
"test binding in a null"
self.cursor.setinputsizes(p_Value = cx_Oracle.TIMESTAMP)
self.cursor.execute("""
select * from TestTimestamps
where TimestampCol = :p_Value""",
p_Value = None)
self.failUnlessEqual(self.cursor.fetchall(), [])
def testBindOutSetInputSizes(self):
"test binding out with set input sizes defined"
vars = self.cursor.setinputsizes(p_Value = cx_Oracle.TIMESTAMP)
self.cursor.execute("""
begin
:p_Value := to_timestamp('20021209', 'YYYYMMDD');
end;""")
self.failUnlessEqual(vars["p_Value"].getvalue(),
cx_Oracle.Timestamp(2002, 12, 9))
def testBindInOutSetInputSizes(self):
"test binding in/out with set input sizes defined"
vars = self.cursor.setinputsizes(p_Value = cx_Oracle.TIMESTAMP)
self.cursor.execute("""
begin
:p_Value := :p_Value + 5.25;
end;""",
p_Value = cx_Oracle.Timestamp(2002, 12, 12, 10, 0, 0))
self.failUnlessEqual(vars["p_Value"].getvalue(),
cx_Oracle.Timestamp(2002, 12, 17, 16, 0, 0))
def testBindOutVar(self):
"test binding out with cursor.var() method"
var = self.cursor.var(cx_Oracle.TIMESTAMP)
self.cursor.execute("""
begin
:p_Value := to_date('20021231 12:31:00',
'YYYYMMDD HH24:MI:SS');
end;""",
p_Value = var)
self.failUnlessEqual(var.getvalue(),
cx_Oracle.Timestamp(2002, 12, 31, 12, 31, 0))
def testBindInOutVarDirectSet(self):
"test binding in/out with cursor.var() method"
var = self.cursor.var(cx_Oracle.TIMESTAMP)
var.setvalue(0, cx_Oracle.Timestamp(2002, 12, 9, 6, 0, 0))
self.cursor.execute("""
begin
:p_Value := :p_Value + 5.25;
end;""",
p_Value = var)
self.failUnlessEqual(var.getvalue(),
cx_Oracle.Timestamp(2002, 12, 14, 12, 0, 0))
def testCursorDescription(self):
"test cursor description is accurate"
self.cursor.execute("select * from TestTimestamps")
self.failUnlessEqual(self.cursor.description,
[ ('INTCOL', cx_Oracle.NUMBER, 10, 22, 9, 0, 0),
('TIMESTAMPCOL', cx_Oracle.TIMESTAMP, -1, 11, 0, 0, 0),
('NULLABLECOL', cx_Oracle.TIMESTAMP, -1, 11, 0, 0, 1) ])
def testFetchAll(self):
"test that fetching all of the data returns the correct results"
self.cursor.execute("select * From TestTimestamps order by IntCol")
self.failUnlessEqual(self.cursor.fetchall(), self.rawData)
self.failUnlessEqual(self.cursor.fetchall(), [])
def testFetchMany(self):
"test that fetching data in chunks returns the correct results"
self.cursor.execute("select * From TestTimestamps order by IntCol")
self.failUnlessEqual(self.cursor.fetchmany(3), self.rawData[0:3])
self.failUnlessEqual(self.cursor.fetchmany(2), self.rawData[3:5])
self.failUnlessEqual(self.cursor.fetchmany(4), self.rawData[5:9])
self.failUnlessEqual(self.cursor.fetchmany(3), self.rawData[9:])
self.failUnlessEqual(self.cursor.fetchmany(3), [])
def testFetchOne(self):
"test that fetching a single row returns the correct results"
self.cursor.execute("""
select *
from TestTimestamps
where IntCol in (3, 4)
order by IntCol""")
self.failUnlessEqual(self.cursor.fetchone(), self.dataByKey[3])
self.failUnlessEqual(self.cursor.fetchone(), self.dataByKey[4])
self.failUnlessEqual(self.cursor.fetchone(), None)

67
test/test.py Normal file
View File

@ -0,0 +1,67 @@
"""Runs all defined unit tests."""
import cx_Oracle
import imp
import os
import sys
import unittest
print "Running tests for cx_Oracle version", cx_Oracle.version
import TestEnv
moduleNames = [
"Connection",
"Cursor",
"CursorVar",
"DateTimeVar",
"LobVar",
"LongVar",
"NumberVar",
"ObjectVar",
"StringVar"
]
if hasattr(cx_Oracle, "TIMESTAMP"):
moduleNames.append("TimestampVar")
if hasattr(cx_Oracle, "SessionPool"):
moduleNames.append("SessionPool")
class BaseTestCase(unittest.TestCase):
def setUp(self):
self.connection = cx_Oracle.connect(TestEnv.USERNAME,
TestEnv.PASSWORD, TestEnv.TNSENTRY)
self.cursor = self.connection.cursor()
self.cursor.arraysize = TestEnv.ARRAY_SIZE
def tearDown(self):
del self.cursor
del self.connection
loader = unittest.TestLoader()
runner = unittest.TextTestRunner(verbosity = 2)
failures = []
for name in moduleNames:
fileName = name + ".py"
print
print "Running tests in", fileName
module = imp.new_module(name)
setattr(module, "USERNAME", TestEnv.USERNAME)
setattr(module, "PASSWORD", TestEnv.PASSWORD)
setattr(module, "TNSENTRY", TestEnv.TNSENTRY)
setattr(module, "ARRAY_SIZE", TestEnv.ARRAY_SIZE)
setattr(module, "TestCase", unittest.TestCase)
setattr(module, "BaseTestCase", BaseTestCase)
setattr(module, "cx_Oracle", cx_Oracle)
execfile(fileName, module.__dict__)
tests = loader.loadTestsFromModule(module)
result = runner.run(tests)
if not result.wasSuccessful():
failures.append(name)
if failures:
print "***** Some tests in the following modules failed. *****"
for name in failures:
print " %s" % name

39
test/test_dbapi20.py Normal file
View File

@ -0,0 +1,39 @@
"""Driver specific portion of the DB API test suite provided by Stuart Bishop
available at http://stuartbishop.net/Software/DBAPI20TestSuite/"""
import cx_Oracle
import dbapi20
import unittest
import TestEnv
class TestSuite(dbapi20.DatabaseAPI20Test):
connect_args = (TestEnv.USERNAME, TestEnv.PASSWORD, TestEnv.TNSENTRY)
driver = cx_Oracle
# not implemented; use a string instead
def test_Binary(self):
pass
# not implemented; see cx_Oracle specific test suite instead
def test_callproc(self):
pass
# not implemented; Oracle does not support the concept
def test_nextset(self):
pass
# not implemented; see cx_Oracle specific test suite instead
def test_setinputsizes(self):
pass
# not implemented; see cx_Oracle specific test suite instead
def test_setoutputsize(self):
pass
if __name__ == "__main__":
print "Testing cx_Oracle version", cx_Oracle.version
unittest.main()