/**
* API version
*/
-#define DBDRV_API_VERSION 19
+#define DBDRV_API_VERSION 20
//
void LIBNXDB_EXPORTABLE DBFreeResult(DB_UNBUFFERED_RESULT hResult);
TCHAR LIBNXDB_EXPORTABLE *DBGetField(DB_UNBUFFERED_RESULT hResult, int iColumn, TCHAR *pBuffer, int iBufSize);
-char LIBNXDB_EXPORTABLE *DBGetFieldUTF8(DB_UNBUFFERED_RESULT hResult, int iColumn, char *pBuffer, int iBufSize);
+char LIBNXDB_EXPORTABLE *DBGetFieldUTF8(DB_UNBUFFERED_RESULT hResult, int iColumn, char *buffer, int iBufSize);
INT32 LIBNXDB_EXPORTABLE DBGetFieldLong(DB_UNBUFFERED_RESULT hResult, int iColumn);
UINT32 LIBNXDB_EXPORTABLE DBGetFieldULong(DB_UNBUFFERED_RESULT hResult, int iColumn);
INT64 LIBNXDB_EXPORTABLE DBGetFieldInt64(DB_UNBUFFERED_RESULT hResult, int iColumn);
}
/**
- * Get field from current row in async query result
+ * Get field from current row in async query result - common implementation for wide char and UTF-8
*/
-extern "C" WCHAR EXPORT *DrvGetFieldUnbuffered(MYSQL_UNBUFFERED_RESULT *hResult, int iColumn, WCHAR *pBuffer, int iBufSize)
+static void *GetFieldUnbufferedInternal(MYSQL_UNBUFFERED_RESULT *hResult, int iColumn, void *pBuffer, int iBufSize, bool utf8)
{
- // Check if we have valid result handle
- if (hResult == NULL)
- return NULL;
-
- // Check if there are valid fetched row
- if ((hResult->noMoreRows) || ((hResult->pCurrRow == NULL) && !hResult->isPreparedStatement))
- return NULL;
-
- // Check if column number is valid
- if ((iColumn < 0) || (iColumn >= hResult->numColumns))
- return NULL;
-
- // Now get column data
- WCHAR *value = NULL;
- if (hResult->isPreparedStatement)
- {
+ // Check if we have valid result handle
+ if (hResult == NULL)
+ return NULL;
+
+ // Check if there are valid fetched row
+ if ((hResult->noMoreRows) || ((hResult->pCurrRow == NULL) && !hResult->isPreparedStatement))
+ return NULL;
+
+ // Check if column number is valid
+ if ((iColumn < 0) || (iColumn >= hResult->numColumns))
+ return NULL;
+
+ // Now get column data
+ void *value = NULL;
+ if (hResult->isPreparedStatement)
+ {
MYSQL_BIND b;
unsigned long l = 0;
my_bool isNull;
if (!isNull)
{
((char *)b.buffer)[l] = 0;
- MultiByteToWideChar(CP_UTF8, 0, (char *)b.buffer, -1, (WCHAR *)pBuffer, iBufSize);
- ((WCHAR *)pBuffer)[iBufSize - 1] = 0;
+ if (utf8)
+ {
+ strncpy((char *)pBuffer, (char *)b.buffer, iBufSize);
+ ((char *)pBuffer)[iBufSize - 1] = 0;
+ }
+ else
+ {
+ MultiByteToWideChar(CP_UTF8, 0, (char *)b.buffer, -1, (WCHAR *)pBuffer, iBufSize);
+ ((WCHAR *)pBuffer)[iBufSize - 1] = 0;
+ }
}
else
{
- *((WCHAR *)pBuffer) = 0;
+ if (utf8)
+ *((char *)pBuffer) = 0;
+ else
+ *((WCHAR *)pBuffer) = 0;
}
value = pBuffer;
}
#if !HAVE_ALLOCA
free(b.buffer);
#endif
- }
- else
- {
+ }
+ else
+ {
int iLen = min((int)hResult->lengthFields[iColumn], iBufSize - 1);
if (iLen > 0)
{
- MultiByteToWideChar(CP_UTF8, 0, hResult->pCurrRow[iColumn], iLen, pBuffer, iBufSize);
+ if (utf8)
+ {
+ memcpy(pBuffer, hResult->pCurrRow[iColumn], iLen);
+ ((char *)pBuffer)[iLen] = 0;
+ }
+ else
+ {
+ MultiByteToWideChar(CP_UTF8, 0, hResult->pCurrRow[iColumn], iLen, (WCHAR *)pBuffer, iBufSize);
+ ((WCHAR *)pBuffer)[iLen] = 0;
+ }
+ }
+ else
+ {
+ if (utf8)
+ *((char *)pBuffer) = 0;
+ else
+ *((WCHAR *)pBuffer) = 0;
}
- pBuffer[iLen] = 0;
value = pBuffer;
- }
- return value;
+ }
+ return value;
+}
+
+/**
+ * Get field from current row in async query result
+ */
+extern "C" WCHAR EXPORT *DrvGetFieldUnbuffered(MYSQL_UNBUFFERED_RESULT *hResult, int iColumn, WCHAR *pBuffer, int iBufSize)
+{
+ return (WCHAR *)GetFieldUnbufferedInternal(hResult, iColumn, pBuffer, iBufSize, false);
+}
+
+/**
+ * Get field from current row in async query result
+ */
+extern "C" char EXPORT *DrvGetFieldUnbufferedUTF8(MYSQL_UNBUFFERED_RESULT *hResult, int iColumn, char *pBuffer, int iBufSize)
+{
+ return (char *)GetFieldUnbufferedInternal(hResult, iColumn, pBuffer, iBufSize, true);
}
/**
return pBuffer;
}
+/**
+ * Get field from current row in async query result as UTF-8 string
+ */
+extern "C" char EXPORT *DrvGetFieldUnbufferedUTF8(PG_UNBUFFERED_RESULT *result, int nColumn, char *pBuffer, int nBufSize)
+{
+ if ((result == NULL) || (result->fetchBuffer == NULL))
+ return NULL;
+
+ // validate column index
+ if (nColumn >= PQnfields(result->fetchBuffer))
+ return NULL;
+
+ if (PQfformat(result->fetchBuffer, nColumn) != 0)
+ return NULL;
+
+ char *value = PQgetvalue(result->fetchBuffer, result->currRow, nColumn);
+ if (value == NULL)
+ return NULL;
+
+ strncpy(pBuffer, value, nBufSize);
+ pBuffer[nBufSize - 1] = 0;
+
+ return pBuffer;
+}
+
/**
* Get column count in async query result
*/
return pwszRet;
}
+/**
+ * Get field from current row in unbuffered query result as UTF-8 string
+ */
+extern "C" char EXPORT *DrvGetFieldUnbufferedUTF8(SQLITE_UNBUFFERED_RESULT *result, int iColumn, char *pBuffer, int iBufSize)
+{
+ char *pszData;
+ char *value = NULL;
+
+ if ((iColumn >= 0) && (iColumn < result->numColumns))
+ {
+ pszData = (char *)sqlite3_column_text(result->stmt, iColumn);
+ if (pszData != NULL)
+ {
+ strncpy(pBuffer, pszData, iBufSize);
+ pBuffer[iBufSize - 1] = 0;
+ value = pBuffer;
+ }
+ }
+ return value;
+}
+
/**
* Get column count in async query result
*/
driver->m_fpDrvGetField = (WCHAR* (*)(DBDRV_RESULT, int, int, WCHAR *, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetField");
driver->m_fpDrvGetFieldUTF8 = (char* (*)(DBDRV_RESULT, int, int, char *, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetFieldUTF8", false); // optional entry point
driver->m_fpDrvGetFieldUnbuffered = (WCHAR* (*)(DBDRV_UNBUFFERED_RESULT, int, WCHAR *, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetFieldUnbuffered");
+ driver->m_fpDrvGetFieldUnbufferedUTF8 = (char* (*)(DBDRV_UNBUFFERED_RESULT, int, char *, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetFieldUnbufferedUTF8");
driver->m_fpDrvGetNumRows = (int (*)(DBDRV_RESULT))DLGetSymbolAddrEx(driver->m_handle, "DrvGetNumRows");
driver->m_fpDrvGetColumnCount = (int (*)(DBDRV_RESULT))DLGetSymbolAddrEx(driver->m_handle, "DrvGetColumnCount");
driver->m_fpDrvGetColumnName = (const char* (*)(DBDRV_RESULT, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetColumnName");
WCHAR* (* m_fpDrvGetField)(DBDRV_RESULT, int, int, WCHAR *, int);
char* (* m_fpDrvGetFieldUTF8)(DBDRV_RESULT, int, int, char *, int);
WCHAR* (* m_fpDrvGetFieldUnbuffered)(DBDRV_UNBUFFERED_RESULT, int, WCHAR *, int);
+ char* (* m_fpDrvGetFieldUnbufferedUTF8)(DBDRV_UNBUFFERED_RESULT, int, char *, int);
int (* m_fpDrvGetNumRows)(DBDRV_RESULT);
void (* m_fpDrvFreeResult)(DBDRV_RESULT);
void (* m_fpDrvFreeUnbufferedResult)(DBDRV_UNBUFFERED_RESULT);
/**
* Get field's value from unbuffered SELECT result as UTF-8 string
*/
-char LIBNXDB_EXPORTABLE *DBGetFieldUTF8(DB_UNBUFFERED_RESULT hResult, int iColumn, char *pBuffer, int iBufSize)
+char LIBNXDB_EXPORTABLE *DBGetFieldUTF8(DB_UNBUFFERED_RESULT hResult, int iColumn, char *buffer, int iBufSize)
{
- /* FIXME: add appropriate call to DB drivers */
- TCHAR *tmp = DBGetField(hResult, iColumn, NULL, 0);
- if (tmp == NULL)
- return NULL;
-
- char *s;
-#ifdef UNICODE
- if (pBuffer != NULL)
- {
- s = pBuffer;
- WideCharToMultiByte(CP_UTF8, 0, tmp, -1, s, iBufSize, NULL, NULL);
- s[iBufSize - 1] = 0;
- }
- else
- {
- s = UTF8StringFromWideString(tmp);
- }
-#else
- if (pBuffer != NULL)
+ if (hResult->m_driver->m_fpDrvGetFieldUTF8 != NULL)
{
- s = pBuffer;
- mb_to_utf8(tmp, -1, s, iBufSize);
- s[iBufSize - 1] = 0;
+ if (buffer != NULL)
+ {
+ *buffer = 0;
+ return hResult->m_driver->m_fpDrvGetFieldUnbufferedUTF8(hResult->m_data, iColumn, buffer, iBufSize);
+ }
+ else
+ {
+ char *pszTemp;
+ LONG nLen = hResult->m_driver->m_fpDrvGetFieldLengthUnbuffered(hResult->m_data, iColumn);
+ if (nLen == -1)
+ {
+ pszTemp = NULL;
+ }
+ else
+ {
+ nLen = nLen * 2 + 1; // increase buffer size because driver may return field length in characters
+ pszTemp = (char *)malloc(nLen);
+ hResult->m_driver->m_fpDrvGetFieldUnbufferedUTF8(hResult->m_data, iColumn, pszTemp, nLen);
+ }
+ return pszTemp;
+ }
}
else
{
- s = UTF8StringFromMBString(tmp);
+ LONG nLen = hResult->m_driver->m_fpDrvGetFieldLengthUnbuffered(hResult->m_data, iColumn);
+ if (nLen == -1)
+ return NULL;
+ nLen = nLen * 2 + 1; // increase buffer size because driver may return field length in characters
+
+ WCHAR *wtemp = (WCHAR *)malloc(nLen * sizeof(WCHAR));
+ hResult->m_driver->m_fpDrvGetFieldUnbuffered(hResult->m_data, iColumn, wtemp, nLen);
+ char *value = (buffer != NULL) ? buffer : (char *)malloc(nLen);
+ WideCharToMultiByte(CP_UTF8, 0, wtemp, -1, value, (buffer != NULL) ? iBufSize : nLen, NULL, NULL);
+ free(wtemp);
+ return value;
}
-#endif
- free(tmp);
- return s;
}
/**