//-----------------------------------------------------------------------------
// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// cxoVarType.c
// Defines variable types for various transformations.
//-----------------------------------------------------------------------------
#include "cxoModule.h"
// define variable types for each of the supported transforms
static cxoVarType cxoAllVarTypes[] = {
{
CXO_TRANSFORM_NONE,
&cxoPyTypeStringVar,
1
},
{
CXO_TRANSFORM_BINARY,
&cxoPyTypeBinaryVar,
4000
},
{
CXO_TRANSFORM_BFILE,
&cxoPyTypeBfileVar,
0
},
{
CXO_TRANSFORM_BLOB,
&cxoPyTypeBlobVar,
0
},
{
CXO_TRANSFORM_BOOLEAN,
&cxoPyTypeBooleanVar,
0
},
{
CXO_TRANSFORM_CLOB,
&cxoPyTypeClobVar,
0
},
{
CXO_TRANSFORM_CURSOR,
&cxoPyTypeCursorVar,
0
},
{
CXO_TRANSFORM_DATE,
&cxoPyTypeDateTimeVar,
0
},
{
CXO_TRANSFORM_DATETIME,
&cxoPyTypeDateTimeVar,
0
},
{
CXO_TRANSFORM_DECIMAL,
&cxoPyTypeNumberVar,
1000
},
{
CXO_TRANSFORM_FIXED_CHAR,
&cxoPyTypeFixedCharVar,
2000
},
{
CXO_TRANSFORM_FIXED_NCHAR,
&cxoPyTypeFixedNcharVar,
2000
},
{
CXO_TRANSFORM_FLOAT,
&cxoPyTypeNumberVar,
1000
},
{
CXO_TRANSFORM_INT,
&cxoPyTypeNumberVar,
1000
},
{
CXO_TRANSFORM_LONG_BINARY,
&cxoPyTypeLongBinaryVar,
128 * 1024
},
{
CXO_TRANSFORM_LONG_STRING,
&cxoPyTypeLongStringVar,
128 * 1024
},
{
CXO_TRANSFORM_NATIVE_DOUBLE,
&cxoPyTypeNativeFloatVar,
0
},
{
CXO_TRANSFORM_NATIVE_FLOAT,
&cxoPyTypeNativeFloatVar,
0
},
{
CXO_TRANSFORM_NATIVE_INT,
&cxoPyTypeNativeIntVar,
0
},
{
CXO_TRANSFORM_NCLOB,
&cxoPyTypeNclobVar,
0
},
{
CXO_TRANSFORM_NSTRING,
&cxoPyTypeNcharVar,
4000
},
{
CXO_TRANSFORM_OBJECT,
&cxoPyTypeObjectVar,
0
},
{
CXO_TRANSFORM_ROWID,
&cxoPyTypeRowidVar,
0
},
{
CXO_TRANSFORM_STRING,
&cxoPyTypeStringVar,
4000
},
{
CXO_TRANSFORM_TIMEDELTA,
&cxoPyTypeIntervalVar,
0
},
{
CXO_TRANSFORM_TIMESTAMP,
&cxoPyTypeTimestampVar,
0
},
{
CXO_TRANSFORM_TIMESTAMP_LTZ,
&cxoPyTypeTimestampVar,
0
}
};
//-----------------------------------------------------------------------------
// cxoVarType_fromDataTypeInfo()
// Return a variable type given query metadata, or NULL indicating that the
// data indicated by the query metadata is not supported.
//-----------------------------------------------------------------------------
cxoVarType *cxoVarType_fromDataTypeInfo(dpiDataTypeInfo *info)
{
cxoTransformNum transformNum;
char message[120];
transformNum = cxoTransform_getNumFromDataTypeInfo(info);
if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
snprintf(message, sizeof(message), "Oracle type %d not supported.",
info->oracleTypeNum);
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
return NULL;
}
return &cxoAllVarTypes[transformNum];
}
//-----------------------------------------------------------------------------
// cxoVarType_fromPythonType()
// Return a variable type given a Python type object or NULL if the Python
// type does not have a corresponding variable type. If the type provided is an
// object type, return that as well.
//-----------------------------------------------------------------------------
cxoVarType *cxoVarType_fromPythonType(PyObject *type, cxoObjectType **objType)
{
cxoTransformNum transformNum;
PyTypeObject *pyType;
char message[250];
if (Py_TYPE(type) == &cxoPyTypeObjectType) {
transformNum = CXO_TRANSFORM_OBJECT;
*objType = (cxoObjectType*) type;
} else if (Py_TYPE(type) != &PyType_Type) {
PyErr_SetString(PyExc_TypeError, "expecting type");
return NULL;
} else {
*objType = NULL;
pyType = (PyTypeObject*) type;
transformNum = cxoTransform_getNumFromType(pyType);
if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
snprintf(message, sizeof(message), "Python type %s not supported.",
pyType->tp_name);
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
return NULL;
}
}
return &cxoAllVarTypes[transformNum];
}
//-----------------------------------------------------------------------------
// cxoVarType_calculateSize()
// Calculate the size to use with the specified transform and Python value.
// This function is only called by cxoVarType_fromPythonValue() and no attempt
// is made to verify the value further.
//-----------------------------------------------------------------------------
static Py_ssize_t cxoVarType_calculateSize(PyObject *value,
cxoTransformNum transformNum)
{
Py_ssize_t size = 0;
#if PY_MAJOR_VERSION < 3
const void *ptr;
#endif
switch (transformNum) {
case CXO_TRANSFORM_NONE:
return 1;
case CXO_TRANSFORM_BINARY:
#if PY_MAJOR_VERSION >= 3
return PyBytes_GET_SIZE(value);
#else
PyObject_AsReadBuffer(value, &ptr, &size);
return size;
#endif
case CXO_TRANSFORM_NSTRING:
size = PyUnicode_GET_SIZE(value);
return (size == 0) ? 1 : size;
case CXO_TRANSFORM_STRING:
#if PY_MAJOR_VERSION >= 3
size = PyUnicode_GET_SIZE(value);
#else
size = PyString_GET_SIZE(value);
#endif
return (size == 0) ? 1 : size;
default:
break;
}
return 0;
}
//-----------------------------------------------------------------------------
// cxoVarType_fromPythonValue()
// Return a variable type given a Python object or NULL if the Python object
// does not have a corresponding variable type.
//-----------------------------------------------------------------------------
cxoVarType *cxoVarType_fromPythonValue(PyObject *value, int *isArray,
Py_ssize_t *size, Py_ssize_t *numElements, int plsql)
{
cxoTransformNum transformNum, tempTransformNum;
PyObject *elementValue;
Py_ssize_t i, tempSize;
char message[250];
// initialization (except numElements which always has a valid value and is
// only overridden when a an array is encountered)
*size = 0;
*isArray = 0;
// handle arrays
if (PyList_Check(value)) {
transformNum = CXO_TRANSFORM_NONE;
for (i = 0; i < PyList_GET_SIZE(value); i++) {
elementValue = PyList_GET_ITEM(value, i);
tempTransformNum = cxoTransform_getNumFromValue(elementValue, 1);
if (tempTransformNum == CXO_TRANSFORM_UNSUPPORTED) {
snprintf(message, sizeof(message),
"element %u value is unsupported", (unsigned) i);
cxoError_raiseFromString(cxoNotSupportedErrorException,
message);
return NULL;
} else if (transformNum == CXO_TRANSFORM_NONE) {
transformNum = tempTransformNum;
} else if (transformNum != tempTransformNum) {
snprintf(message, sizeof(message),
"element %u value is not the same type as previous "
"elements", (unsigned) i);
cxoError_raiseFromString(cxoNotSupportedErrorException,
message);
return NULL;
}
tempSize = cxoVarType_calculateSize(elementValue,
tempTransformNum);
if (tempSize > *size)
*size = tempSize;
}
*isArray = 1;
*numElements = PyList_GET_SIZE(value);
return &cxoAllVarTypes[transformNum];
}
// handle scalar values
transformNum = cxoTransform_getNumFromValue(value, plsql);
if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
snprintf(message, sizeof(message),
"Python value of type %s not supported.",
Py_TYPE(value)->tp_name);
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
return NULL;
}
*size = cxoVarType_calculateSize(value, transformNum);
return &cxoAllVarTypes[transformNum];
}