unicode strings. These are not explicitly supported in Oracle but can be used to bind to NCLOB, for example, without getting the "unimplemented or unreasonable conversion requested" error.
238 lines
9.3 KiB
C
238 lines
9.3 KiB
C
//-----------------------------------------------------------------------------
|
|
// 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);
|
|
static ub4 LongVar_GetBufferSize(udt_LongVar*);
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Python type declarations
|
|
//-----------------------------------------------------------------------------
|
|
static PyTypeObject g_LongStringVarType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
"cx_Oracle.LONG_STRING", // tp_name
|
|
sizeof(udt_LongVar), // tp_basicsize
|
|
0, // tp_itemsize
|
|
0, // 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
|
|
};
|
|
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
static PyTypeObject g_LongUnicodeVarType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
"cx_Oracle.LONG_UNICODE", // tp_name
|
|
sizeof(udt_LongVar), // tp_basicsize
|
|
0, // tp_itemsize
|
|
0, // 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
|
|
};
|
|
#endif
|
|
|
|
|
|
static PyTypeObject g_LongBinaryVarType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
"cx_Oracle.LONG_BINARY", // tp_name
|
|
sizeof(udt_LongVar), // tp_basicsize
|
|
0, // tp_itemsize
|
|
0, // 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
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// variable type declarations
|
|
//-----------------------------------------------------------------------------
|
|
static udt_VariableType vt_LongString = {
|
|
(InitializeProc) NULL,
|
|
(FinalizeProc) NULL,
|
|
(PreDefineProc) NULL,
|
|
(PostDefineProc) NULL,
|
|
(PreFetchProc) NULL,
|
|
(IsNullProc) NULL,
|
|
(SetValueProc) LongVar_SetValue,
|
|
(GetValueProc) LongVar_GetValue,
|
|
(GetBufferSizeProc) LongVar_GetBufferSize,
|
|
&g_LongStringVarType, // Python type
|
|
SQLT_LVC, // Oracle type
|
|
SQLCS_IMPLICIT, // charset form
|
|
128 * 1024, // element length (default)
|
|
1, // is character data
|
|
1, // is variable length
|
|
1, // can be copied
|
|
0 // can be in array
|
|
};
|
|
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
static udt_VariableType vt_LongNationalCharString = {
|
|
(InitializeProc) NULL,
|
|
(FinalizeProc) NULL,
|
|
(PreDefineProc) NULL,
|
|
(PostDefineProc) NULL,
|
|
(PreFetchProc) NULL,
|
|
(IsNullProc) NULL,
|
|
(SetValueProc) LongVar_SetValue,
|
|
(GetValueProc) LongVar_GetValue,
|
|
(GetBufferSizeProc) LongVar_GetBufferSize,
|
|
&g_LongUnicodeVarType, // Python type
|
|
SQLT_LVC, // Oracle type
|
|
SQLCS_NCHAR, // charset form
|
|
128 * 1024, // element length (default)
|
|
1, // is character data
|
|
1, // is variable length
|
|
1, // can be copied
|
|
0 // can be in array
|
|
};
|
|
#endif
|
|
|
|
|
|
static udt_VariableType vt_LongBinary = {
|
|
(InitializeProc) NULL,
|
|
(FinalizeProc) NULL,
|
|
(PreDefineProc) NULL,
|
|
(PostDefineProc) NULL,
|
|
(PreFetchProc) NULL,
|
|
(IsNullProc) NULL,
|
|
(SetValueProc) LongVar_SetValue,
|
|
(GetValueProc) LongVar_GetValue,
|
|
(GetBufferSizeProc) LongVar_GetBufferSize,
|
|
&g_LongBinaryVarType, // Python type
|
|
SQLT_LVB, // Oracle type
|
|
SQLCS_IMPLICIT, // charset form
|
|
128 * 1024, // element length (default)
|
|
0, // is character data
|
|
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
|
|
{
|
|
udt_Buffer buffer;
|
|
char *ptr;
|
|
|
|
// get the buffer data and size for binding
|
|
if (cxBuffer_FromObject(&buffer, value, var->environment->encoding) < 0)
|
|
return -1;
|
|
|
|
// verify there is enough space to store the value
|
|
if (buffer.numCharacters > var->size) {
|
|
if (Variable_Resize((udt_Variable*) var, buffer.numCharacters) < 0) {
|
|
cxBuffer_Clear(&buffer);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// copy the string to the Oracle buffer
|
|
ptr = var->data + var->bufferSize * pos;
|
|
*((ub4 *) ptr) = (ub4) buffer.size;
|
|
if (buffer.size)
|
|
memcpy(ptr + sizeof(ub4), buffer.ptr, buffer.size);
|
|
cxBuffer_Clear(&buffer);
|
|
|
|
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->bufferSize * pos;
|
|
size = *((ub4 *) ptr);
|
|
ptr += sizeof(ub4);
|
|
if (var->type == &vt_LongBinary)
|
|
return PyBytes_FromStringAndSize(ptr, size);
|
|
return cxString_FromEncodedString(ptr, size, var->environment->encoding);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// LongVar_GetBufferSize()
|
|
// Returns the size of the buffer to use for data of the given size.
|
|
//-----------------------------------------------------------------------------
|
|
static ub4 LongVar_GetBufferSize(
|
|
udt_LongVar *self) // variable to get buffer size
|
|
{
|
|
if (!self->type->isCharacterData)
|
|
return self->size + sizeof(ub4);
|
|
return sizeof(ub4) + self->size * self->environment->maxBytesPerCharacter;
|
|
}
|
|
|