in language-extensions/python/src/PythonDataSet.cpp [1244:1323]
void PythonOutputDataSet::RetrieveRawColumnFromDataFrame(
string columnName,
SQLULEN &columnSize,
SQLSMALLINT &decimalDigits,
SQLSMALLINT &nullable)
{
LOG("PythonOutputDataSet::RetrieveRawColumnFromDataFrame");
vector<char> columnData;
SQLINTEGER *strLenOrNullMap = nullptr;
if (m_rowsNumber > 0)
{
strLenOrNullMap = new SQLINTEGER[m_rowsNumber];
}
decimalDigits = 0;
nullable = SQL_NO_NULLS;
np::ndarray column = ExtractArrayFromDataFrame(columnName);
// Store the data in a vector (columnData) while we calculate the total size we need
// for the contiguous char data.
//
SQLINTEGER maxLen = sizeof(char);
int fullSize = 0;
for (SQLULEN row = 0; row < m_rowsNumber; ++row)
{
bp::object pyObj = column[row];
if (!pyObj.is_none())
{
// Extract the size and bytes of the pyObj
//
PyObject *baseObj = pyObj.ptr();
int size = PyBytes_Size(baseObj);
char *bytes = static_cast<char *>(
static_cast<void *>(PyBytes_AsString(baseObj)));
fullSize += size;
strLenOrNullMap[row] = size;
columnData.insert(columnData.end(), bytes, bytes+size);
}
else
{
strLenOrNullMap[row] = SQL_NULL_DATA;
nullable = SQL_NULLABLE;
}
// Store the maximum length to find the widest the column needs to be
//
if (maxLen < strLenOrNullMap[row])
{
maxLen = strLenOrNullMap[row];
}
}
// Create a single block of memory that will hold all the data contiguously.
//
unique_ptr<char[]> dataPtr(new char[fullSize]);
// Copy our data from the vector of strings to the single chunk of memory.
//
memcpy(dataPtr.get(), columnData.data(), fullSize);
columnSize = maxLen;
if (m_rowsNumber > 0)
{
// Add the memory block to the m_data and give the memory handling job to m_data.
//
m_data.push_back(static_cast<SQLPOINTER>(dataPtr.release()));
}
else
{
m_data.push_back(nullptr);
}
m_columnNullMap.push_back(strLenOrNullMap);
}