void PythonOutputDataSet::RetrieveRawColumnFromDataFrame()

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);
}