new DB API call: DBSelectPreparedUnbuffered; DB API refactoring; unbuffered select...
authorVictor Kirhenshtein <victor@netxms.org>
Sat, 5 Dec 2015 16:34:19 +0000 (18:34 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Sat, 5 Dec 2015 16:34:19 +0000 (18:34 +0200)
23 files changed:
include/dbdrv.h
include/nxdbapi.h
src/db/dbdrv/mysql/mysql.cpp
src/db/dbdrv/mysql/mysqldrv.h
src/db/dbdrv/odbc/odbc.cpp
src/db/dbdrv/odbc/odbcdrv.h
src/db/dbdrv/oracle/oracle.cpp
src/db/dbdrv/oracle/oracledrv.h
src/db/dbdrv/pgsql/pgsql.cpp
src/db/dbdrv/pgsql/pgsqldrv.h
src/db/dbdrv/sqlite/.cproject [new file with mode: 0644]
src/db/dbdrv/sqlite/.project [new file with mode: 0644]
src/db/dbdrv/sqlite/.settings/language.settings.xml [new file with mode: 0644]
src/db/dbdrv/sqlite/sqlite.cpp
src/db/libnxdb/drivers.cpp
src/db/libnxdb/libnxdb.h
src/db/libnxdb/session.cpp
src/server/core/dcitem.cpp
src/server/core/session.cpp
src/server/tools/nxdbmgr/export.cpp
src/server/tools/nxdbmgr/migrate.cpp
src/server/tools/nxdbmgr/nxdbmgr.cpp
src/server/tools/nxdbmgr/nxdbmgr.h

index 54548ee..495ddfd 100644 (file)
@@ -28,7 +28,7 @@
 /**
  * API version
  */
-#define DBDRV_API_VERSION           15
+#define DBDRV_API_VERSION           16
 
 
 //
@@ -64,7 +64,7 @@ const char EXPORT *drvName = name;
 typedef void * DBDRV_CONNECTION;
 typedef void * DBDRV_STATEMENT;
 typedef void * DBDRV_RESULT;
-typedef void * DBDRV_ASYNC_RESULT;
+typedef void * DBDRV_UNBUFFERED_RESULT;
 
 
 //
index ab90bc6..1e8e2f4 100644 (file)
@@ -81,8 +81,8 @@ typedef db_statement_t * DB_STATEMENT;
 struct db_result_t;
 typedef db_result_t * DB_RESULT;
 
-struct db_async_result_t;
-typedef db_async_result_t * DB_ASYNC_RESULT;
+struct db_unbuffered_result_t;
+typedef db_unbuffered_result_t * DB_UNBUFFERED_RESULT;
 
 /**
  * Pool connection information
@@ -147,6 +147,8 @@ bool LIBNXDB_EXPORTABLE DBExecute(DB_STATEMENT hStmt);
 bool LIBNXDB_EXPORTABLE DBExecuteEx(DB_STATEMENT hStmt, TCHAR *errorText);
 DB_RESULT LIBNXDB_EXPORTABLE DBSelectPrepared(DB_STATEMENT hStmt);
 DB_RESULT LIBNXDB_EXPORTABLE DBSelectPreparedEx(DB_STATEMENT hStmt, TCHAR *errorText);
+DB_UNBUFFERED_RESULT LIBNXDB_EXPORTABLE DBSelectPreparedUnbuffered(DB_STATEMENT hStmt);
+DB_UNBUFFERED_RESULT LIBNXDB_EXPORTABLE DBSelectPreparedUnbufferedEx(DB_STATEMENT hStmt, TCHAR *errorText);
 
 bool LIBNXDB_EXPORTABLE DBQuery(DB_HANDLE hConn, const TCHAR *szQuery);
 bool LIBNXDB_EXPORTABLE DBQueryEx(DB_HANDLE hConn, const TCHAR *szQuery, TCHAR *errorText);
@@ -175,21 +177,22 @@ bool LIBNXDB_EXPORTABLE DBGetFieldByteArray2(DB_RESULT hResult, int iRow, int iC
                                              BYTE *data, int nSize, int nDefault);
 uuid LIBNXDB_EXPORTABLE DBGetFieldGUID(DB_RESULT hResult, int iRow, int iColumn);
 
-DB_ASYNC_RESULT LIBNXDB_EXPORTABLE DBAsyncSelect(DB_HANDLE hConn, const TCHAR *szQuery);
-DB_ASYNC_RESULT LIBNXDB_EXPORTABLE DBAsyncSelectEx(DB_HANDLE hConn, const TCHAR *szQuery, TCHAR *errorText);
-bool LIBNXDB_EXPORTABLE DBFetch(DB_ASYNC_RESULT hResult);
-int LIBNXDB_EXPORTABLE DBGetColumnCountAsync(DB_ASYNC_RESULT hResult);
-bool LIBNXDB_EXPORTABLE DBGetColumnNameAsync(DB_ASYNC_RESULT hResult, int column, TCHAR *buffer, int bufSize);
-void LIBNXDB_EXPORTABLE DBFreeAsyncResult(DB_ASYNC_RESULT hResult);
-
-TCHAR LIBNXDB_EXPORTABLE *DBGetFieldAsync(DB_ASYNC_RESULT hResult, int iColumn, TCHAR *pBuffer, int iBufSize);
-INT32 LIBNXDB_EXPORTABLE DBGetFieldAsyncLong(DB_ASYNC_RESULT hResult, int iColumn);
-UINT32 LIBNXDB_EXPORTABLE DBGetFieldAsyncULong(DB_ASYNC_RESULT hResult, int iColumn);
-INT64 LIBNXDB_EXPORTABLE DBGetFieldAsyncInt64(DB_ASYNC_RESULT hResult, int iColumn);
-UINT64 LIBNXDB_EXPORTABLE DBGetFieldAsyncUInt64(DB_ASYNC_RESULT hResult, int iColumn);
-double LIBNXDB_EXPORTABLE DBGetFieldAsyncDouble(DB_ASYNC_RESULT hResult, int iColumn);
-UINT32 LIBNXDB_EXPORTABLE DBGetFieldAsyncIPAddr(DB_ASYNC_RESULT hResult, int iColumn);
-InetAddress LIBNXDB_EXPORTABLE DBGetFieldAsyncInetAddr(DB_ASYNC_RESULT hResult, int iColumn);
+DB_UNBUFFERED_RESULT LIBNXDB_EXPORTABLE DBSelectUnbuffered(DB_HANDLE hConn, const TCHAR *szQuery);
+DB_UNBUFFERED_RESULT LIBNXDB_EXPORTABLE DBSelectUnbufferedEx(DB_HANDLE hConn, const TCHAR *szQuery, TCHAR *errorText);
+bool LIBNXDB_EXPORTABLE DBFetch(DB_UNBUFFERED_RESULT hResult);
+int LIBNXDB_EXPORTABLE DBGetColumnCount(DB_UNBUFFERED_RESULT hResult);
+bool LIBNXDB_EXPORTABLE DBGetColumnName(DB_UNBUFFERED_RESULT hResult, int column, TCHAR *buffer, int bufSize);
+void LIBNXDB_EXPORTABLE DBFreeResult(DB_UNBUFFERED_RESULT hResult);
+
+TCHAR LIBNXDB_EXPORTABLE *DBGetField(DB_UNBUFFERED_RESULT hResult, int iColumn, TCHAR *pBuffer, 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);
+UINT64 LIBNXDB_EXPORTABLE DBGetFieldUInt64(DB_UNBUFFERED_RESULT hResult, int iColumn);
+double LIBNXDB_EXPORTABLE DBGetFieldDouble(DB_UNBUFFERED_RESULT hResult, int iColumn);
+UINT32 LIBNXDB_EXPORTABLE DBGetFieldIPAddr(DB_UNBUFFERED_RESULT hResult, int iColumn);
+InetAddress LIBNXDB_EXPORTABLE DBGetFieldInetAddr(DB_UNBUFFERED_RESULT hResult, int iColumn);
+uuid LIBNXDB_EXPORTABLE DBGetFieldGUID(DB_UNBUFFERED_RESULT hResult, int iColumn);
 
 bool LIBNXDB_EXPORTABLE DBBegin(DB_HANDLE hConn);
 bool LIBNXDB_EXPORTABLE DBCommit(DB_HANDLE hConn);
index f0f7d61..7131fe2 100644 (file)
@@ -363,11 +363,13 @@ extern "C" void EXPORT DrvBind(MYSQL_STATEMENT *hStmt, int pos, int sqlType, int
                {
                        case DB_CTYPE_UINT32:
                                b->is_unsigned = true;
+                               /* no break */
                        case DB_CTYPE_INT32:
                                b->buffer_type = MYSQL_TYPE_LONG;
                                break;
                        case DB_CTYPE_UINT64:
                                b->is_unsigned = true;
+            /* no break */
                        case DB_CTYPE_INT64:
                                b->buffer_type = MYSQL_TYPE_LONGLONG;
                                break;
@@ -800,11 +802,11 @@ extern "C" void EXPORT DrvFreeResult(MYSQL_RESULT *hResult)
 }
 
 /**
- * Perform asynchronous SELECT query
+ * Perform unbuffered SELECT query
  */
-extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(MYSQL_CONN *pConn, WCHAR *pwszQuery, DWORD *pdwError, WCHAR *errorText)
+extern "C" DBDRV_UNBUFFERED_RESULT EXPORT DrvSelectUnbuffered(MYSQL_CONN *pConn, WCHAR *pwszQuery, DWORD *pdwError, WCHAR *errorText)
 {
-       MYSQL_ASYNC_RESULT *pResult = NULL;
+       MYSQL_UNBUFFERED_RESULT *pResult = NULL;
        char *pszQueryUTF8;
        
        if (pConn == NULL)
@@ -817,7 +819,7 @@ extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(MYSQL_CONN *pConn, WCHAR *pw
        MutexLock(pConn->mutexQueryLock);
        if (mysql_query(pConn->pMySQL, pszQueryUTF8) == 0)
        {
-               pResult = (MYSQL_ASYNC_RESULT *)malloc(sizeof(MYSQL_ASYNC_RESULT));
+               pResult = (MYSQL_UNBUFFERED_RESULT *)malloc(sizeof(MYSQL_UNBUFFERED_RESULT));
                pResult->connection = pConn;
                pResult->pHandle = mysql_use_result(pConn->pMySQL);
                if (pResult->pHandle != NULL)
@@ -869,7 +871,7 @@ extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(MYSQL_CONN *pConn, WCHAR *pw
 /**
  * Fetch next result line from asynchronous SELECT results
  */
-extern "C" bool EXPORT DrvFetch(MYSQL_ASYNC_RESULT *hResult)
+extern "C" bool EXPORT DrvFetch(MYSQL_UNBUFFERED_RESULT *hResult)
 {
        bool bResult = true;
        
@@ -909,7 +911,7 @@ extern "C" bool EXPORT DrvFetch(MYSQL_ASYNC_RESULT *hResult)
 /**
  * Get field length from async query result result
  */
-extern "C" LONG EXPORT DrvGetFieldLengthAsync(MYSQL_ASYNC_RESULT *hResult, int iColumn)
+extern "C" LONG EXPORT DrvGetFieldLengthUnbuffered(MYSQL_UNBUFFERED_RESULT *hResult, int iColumn)
 {
        // Check if we have valid result handle
        if (hResult == NULL)
@@ -929,7 +931,7 @@ extern "C" LONG EXPORT DrvGetFieldLengthAsync(MYSQL_ASYNC_RESULT *hResult, int i
 /**
  * Get field from current row in async query result
  */
-extern "C" WCHAR EXPORT *DrvGetFieldAsync(DBDRV_ASYNC_RESULT hResult, int iColumn, WCHAR *pBuffer, int iBufSize)
+extern "C" WCHAR EXPORT *DrvGetFieldUnbuffered(MYSQL_UNBUFFERED_RESULT *hResult, int iColumn, WCHAR *pBuffer, int iBufSize)
 {
        int iLen;
        
@@ -938,20 +940,18 @@ extern "C" WCHAR EXPORT *DrvGetFieldAsync(DBDRV_ASYNC_RESULT hResult, int iColum
                return NULL;
        
        // Check if there are valid fetched row
-       if ((((MYSQL_ASYNC_RESULT *)hResult)->noMoreRows) ||
-               (((MYSQL_ASYNC_RESULT *)hResult)->pCurrRow == NULL))
+       if ((hResult->noMoreRows) || (hResult->pCurrRow == NULL))
                return NULL;
        
        // Check if column number is valid
-       if ((iColumn < 0) || (iColumn >= ((MYSQL_ASYNC_RESULT *)hResult)->iNumCols))
+       if ((iColumn < 0) || (iColumn >= hResult->iNumCols))
                return NULL;
        
        // Now get column data
-       iLen = min((int)((MYSQL_ASYNC_RESULT *)hResult)->pulColLengths[iColumn], iBufSize - 1);
+       iLen = min((int)hResult->pulColLengths[iColumn], iBufSize - 1);
        if (iLen > 0)
        {
-               MultiByteToWideChar(CP_UTF8, 0, ((MYSQL_ASYNC_RESULT *)hResult)->pCurrRow[iColumn],
-                                   iLen, pBuffer, iBufSize);
+               MultiByteToWideChar(CP_UTF8, 0, hResult->pCurrRow[iColumn], iLen, pBuffer, iBufSize);
        }
        pBuffer[iLen] = 0;
        
@@ -961,45 +961,45 @@ extern "C" WCHAR EXPORT *DrvGetFieldAsync(DBDRV_ASYNC_RESULT hResult, int iColum
 /**
  * Get column count in async query result
  */
-extern "C" int EXPORT DrvGetColumnCountAsync(DBDRV_ASYNC_RESULT hResult)
+extern "C" int EXPORT DrvGetColumnCountUnbuffered(MYSQL_UNBUFFERED_RESULT *hResult)
 {
-       return ((hResult != NULL) && (((MYSQL_ASYNC_RESULT *)hResult)->pHandle != NULL))? (int)mysql_num_fields(((MYSQL_ASYNC_RESULT *)hResult)->pHandle) : 0;
+       return ((hResult != NULL) && (hResult->pHandle != NULL))? (int)mysql_num_fields(hResult->pHandle) : 0;
 }
 
 /**
  * Get column name in async query result
  */
-extern "C" const char EXPORT *DrvGetColumnNameAsync(DBDRV_ASYNC_RESULT hResult, int column)
+extern "C" const char EXPORT *DrvGetColumnNameUnbuffered(MYSQL_UNBUFFERED_RESULT *hResult, int column)
 {
        MYSQL_FIELD *field;
 
-       if ((hResult == NULL) || (((MYSQL_ASYNC_RESULT *)hResult)->pHandle == NULL))
+       if ((hResult == NULL) || (hResult->pHandle == NULL))
                return NULL;
 
-       field = mysql_fetch_field_direct(((MYSQL_ASYNC_RESULT *)hResult)->pHandle, column);
+       field = mysql_fetch_field_direct(hResult->pHandle, column);
        return (field != NULL) ? field->name : NULL;
 }
 
 /**
  * Destroy result of async query
  */
-extern "C" void EXPORT DrvFreeAsyncResult(DBDRV_ASYNC_RESULT hResult)
+extern "C" void EXPORT DrvFreeUnbufferedResult(MYSQL_UNBUFFERED_RESULT *hResult)
 {
        if (hResult != NULL)
        {
                // Check if all result rows fetched
-               if (!((MYSQL_ASYNC_RESULT *)hResult)->noMoreRows)
+               if (!hResult->noMoreRows)
                {
                        // Fetch remaining rows
-                       while(mysql_fetch_row(((MYSQL_ASYNC_RESULT *)hResult)->pHandle) != NULL);
+                       while(mysql_fetch_row(hResult->pHandle) != NULL);
                        
                        // Now we are ready for next query, so unlock query mutex
-                       MutexUnlock(((MYSQL_ASYNC_RESULT *)hResult)->connection->mutexQueryLock);
+                       MutexUnlock(hResult->connection->mutexQueryLock);
                }
                
                // Free allocated memory
-               mysql_free_result(((MYSQL_ASYNC_RESULT *)hResult)->pHandle);
-               safe_free(((MYSQL_ASYNC_RESULT *)hResult)->pulColLengths);
+               mysql_free_result(hResult->pHandle);
+               safe_free(hResult->pulColLengths);
                free(hResult);
        }
 }
index 76ed9f6..9426630 100644 (file)
@@ -95,6 +95,6 @@ typedef struct
    bool noMoreRows;
    int iNumCols;
    unsigned long *pulColLengths;
-} MYSQL_ASYNC_RESULT;
+} MYSQL_UNBUFFERED_RESULT;
 
 #endif   /* _mysqldrv_h_ */
index 608d761..8379019 100644 (file)
@@ -1,6 +1,6 @@
 /* 
 ** ODBC Database Driver
-** Copyright (C) 2004-2014 Victor Kirhenshtein
+** Copyright (C) 2004-2015 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -779,11 +779,11 @@ extern "C" void EXPORT DrvFreeResult(ODBCDRV_QUERY_RESULT *pResult)
 }
 
 /**
- * Perform asynchronous SELECT query
+ * Perform unbuffered SELECT query
  */
-extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(ODBCDRV_CONN *pConn, NETXMS_WCHAR *pwszQuery, DWORD *pdwError, NETXMS_WCHAR *errorText)
+extern "C" DBDRV_UNBUFFERED_RESULT EXPORT DrvSelectUnbuffered(ODBCDRV_CONN *pConn, NETXMS_WCHAR *pwszQuery, DWORD *pdwError, NETXMS_WCHAR *errorText)
 {
-   ODBCDRV_ASYNC_QUERY_RESULT *pResult = NULL;
+   ODBCDRV_UNBUFFERED_QUERY_RESULT *pResult = NULL;
    long iResult;
    short wNumCols;
        int i;
@@ -814,7 +814,7 @@ extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(ODBCDRV_CONN *pConn, NETXMS_
           if ((iResult == SQL_SUCCESS) || (iResult == SQL_SUCCESS_WITH_INFO))
       {
          // Allocate result buffer and determine column info
-         pResult = (ODBCDRV_ASYNC_QUERY_RESULT *)malloc(sizeof(ODBCDRV_ASYNC_QUERY_RESULT));
+         pResult = (ODBCDRV_UNBUFFERED_QUERY_RESULT *)malloc(sizeof(ODBCDRV_UNBUFFERED_QUERY_RESULT));
          SQLNumResultCols(pConn->sqlStatement, &wNumCols);
          pResult->iNumCols = wNumCols;
          pResult->pConn = pConn;
@@ -867,7 +867,7 @@ extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(ODBCDRV_CONN *pConn, NETXMS_
 /**
  * Fetch next result line from asynchronous SELECT results
  */
-extern "C" bool EXPORT DrvFetch(ODBCDRV_ASYNC_QUERY_RESULT *pResult)
+extern "C" bool EXPORT DrvFetch(ODBCDRV_UNBUFFERED_QUERY_RESULT *pResult)
 {
    bool success = false;
 
@@ -963,7 +963,7 @@ extern "C" bool EXPORT DrvFetch(ODBCDRV_ASYNC_QUERY_RESULT *pResult)
 /**
  * Get field length from async query result
  */
-extern "C" LONG EXPORT DrvGetFieldLengthAsync(ODBCDRV_ASYNC_QUERY_RESULT *result, int col)
+extern "C" LONG EXPORT DrvGetFieldLengthUnbuffered(ODBCDRV_UNBUFFERED_QUERY_RESULT *result, int col)
 {
    if (result == NULL)
       return -1;
@@ -977,7 +977,7 @@ extern "C" LONG EXPORT DrvGetFieldLengthAsync(ODBCDRV_ASYNC_QUERY_RESULT *result
 /**
  * Get field from current row in async query result
  */
-extern "C" NETXMS_WCHAR EXPORT *DrvGetFieldAsync(ODBCDRV_ASYNC_QUERY_RESULT *result, int col, NETXMS_WCHAR *buffer, int bufferSize)
+extern "C" NETXMS_WCHAR EXPORT *DrvGetFieldUnbuffered(ODBCDRV_UNBUFFERED_QUERY_RESULT *result, int col, NETXMS_WCHAR *buffer, int bufferSize)
 {
    // Check if we have valid result handle
    if (result == NULL)
@@ -1002,7 +1002,7 @@ extern "C" NETXMS_WCHAR EXPORT *DrvGetFieldAsync(ODBCDRV_ASYNC_QUERY_RESULT *res
 /**
  * Get column count in async query result
  */
-extern "C" int EXPORT DrvGetColumnCountAsync(ODBCDRV_ASYNC_QUERY_RESULT *pResult)
+extern "C" int EXPORT DrvGetColumnCountUnbuffered(ODBCDRV_UNBUFFERED_QUERY_RESULT *pResult)
 {
        return (pResult != NULL) ? pResult->iNumCols : 0;
 }
@@ -1010,7 +1010,7 @@ extern "C" int EXPORT DrvGetColumnCountAsync(ODBCDRV_ASYNC_QUERY_RESULT *pResult
 /**
  * Get column name in async query result
  */
-extern "C" const char EXPORT *DrvGetColumnNameAsync(ODBCDRV_ASYNC_QUERY_RESULT *pResult, int column)
+extern "C" const char EXPORT *DrvGetColumnNameUnbuffered(ODBCDRV_UNBUFFERED_QUERY_RESULT *pResult, int column)
 {
        return ((pResult != NULL) && (column >= 0) && (column < pResult->iNumCols)) ? pResult->columnNames[column] : NULL;
 }
@@ -1018,7 +1018,7 @@ extern "C" const char EXPORT *DrvGetColumnNameAsync(ODBCDRV_ASYNC_QUERY_RESULT *
 /**
  * Destroy result of async query
  */
-extern "C" void EXPORT DrvFreeAsyncResult(ODBCDRV_ASYNC_QUERY_RESULT *pResult)
+extern "C" void EXPORT DrvFreeUnbufferedResult(ODBCDRV_UNBUFFERED_QUERY_RESULT *pResult)
 {
    if (pResult != NULL)
    {
index 8d621e9..37b6272 100644 (file)
@@ -1,6 +1,6 @@
 /* 
 ** ODBC Database Driver
-** Copyright (C) 2004-2011 Victor Kirhenshtein
+** Copyright (C) 2004-2015 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -115,7 +115,7 @@ typedef struct
 } ODBCDRV_QUERY_RESULT;
 
 /**
- * Async result buffer structure
+ * Unbuffered result buffer structure
  */
 typedef struct
 {
@@ -124,7 +124,7 @@ typedef struct
    bool noMoreRows;
        char **columnNames;
    NETXMS_WCHAR **values;
-} ODBCDRV_ASYNC_QUERY_RESULT;
+} ODBCDRV_UNBUFFERED_QUERY_RESULT;
 
 
 #endif   /* _odbcdrv_h_ */
index d63cfe0..fd94b71 100644 (file)
@@ -1193,17 +1193,105 @@ extern "C" void EXPORT DrvFreeResult(ORACLE_RESULT *pResult)
 }
 
 /**
- * Perform asynchronous SELECT query
+ * Process results of unbuffered query execution (prepare for fetching results)
  */
-extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(ORACLE_CONN *pConn, WCHAR *pwszQuery,
-                                                 DWORD *pdwError, WCHAR *errorText)
+static ORACLE_UNBUFFERED_RESULT *ProcessUnbufferedQueryResults(ORACLE_CONN *pConn, OCIStmt *handleStmt, DWORD *pdwError)
 {
-       OCIParam *handleParam;
-       OCIDefine *handleDefine;
-       ub4 nCount;
-       ub2 nWidth;
-       text *colName;
-       int i;
+   ORACLE_UNBUFFERED_RESULT *result = (ORACLE_UNBUFFERED_RESULT *)malloc(sizeof(ORACLE_UNBUFFERED_RESULT));
+   result->handleStmt = handleStmt;
+   result->connection = pConn;
+
+   ub4 nCount;
+   OCIAttrGet(result->handleStmt, OCI_HTYPE_STMT, &nCount, NULL, OCI_ATTR_PARAM_COUNT, pConn->handleError);
+   result->nCols = nCount;
+   if (result->nCols > 0)
+   {
+      // Prepare receive buffers and fetch column names
+      result->columnNames = (char **)malloc(sizeof(char *) * result->nCols);
+      result->pBuffers = (ORACLE_FETCH_BUFFER *)malloc(sizeof(ORACLE_FETCH_BUFFER) * result->nCols);
+      memset(result->pBuffers, 0, sizeof(ORACLE_FETCH_BUFFER) * result->nCols);
+      for(int i = 0; i < result->nCols; i++)
+      {
+         OCIParam *handleParam;
+
+         result->pBuffers[i].isNull = 1;   // Mark all columns as NULL initially
+         if (OCIParamGet(result->handleStmt, OCI_HTYPE_STMT, pConn->handleError,
+                         (void **)&handleParam, (ub4)(i + 1)) == OCI_SUCCESS)
+         {
+            // Column name
+            text *colName;
+            if (OCIAttrGet(handleParam, OCI_DTYPE_PARAM, &colName, &nCount, OCI_ATTR_NAME, pConn->handleError) == OCI_SUCCESS)
+            {
+               // We are in UTF-16 mode, so OCIAttrGet will return UTF-16 strings
+               result->columnNames[i] = MBStringFromUCS2String((UCS2CHAR *)colName);
+            }
+            else
+            {
+               result->columnNames[i] = strdup("");
+            }
+
+            // Data size
+            sword nStatus;
+            ub2 type = 0;
+            OCIAttrGet(handleParam, OCI_DTYPE_PARAM, &type, NULL, OCI_ATTR_DATA_TYPE, pConn->handleError);
+            OCIDefine *handleDefine;
+            if (type == OCI_TYPECODE_CLOB)
+            {
+               result->pBuffers[i].pData = NULL;
+               OCIDescriptorAlloc(pConn->handleEnv, (void **)&result->pBuffers[i].lobLocator, OCI_DTYPE_LOB, 0, NULL);
+               handleDefine = NULL;
+               nStatus = OCIDefineByPos(result->handleStmt, &handleDefine, pConn->handleError, i + 1,
+                                        &result->pBuffers[i].lobLocator, 0, SQLT_CLOB, &result->pBuffers[i].isNull,
+                                        NULL, NULL, OCI_DEFAULT);
+            }
+            else
+            {
+               ub2 nWidth;
+               result->pBuffers[i].lobLocator = NULL;
+               OCIAttrGet(handleParam, OCI_DTYPE_PARAM, &nWidth, NULL, OCI_ATTR_DATA_SIZE, pConn->handleError);
+               result->pBuffers[i].pData = (UCS2CHAR *)malloc((nWidth + 31) * sizeof(UCS2CHAR));
+               handleDefine = NULL;
+               nStatus = OCIDefineByPos(result->handleStmt, &handleDefine, pConn->handleError, i + 1,
+                                        result->pBuffers[i].pData, (nWidth + 31) * sizeof(UCS2CHAR),
+                                        SQLT_CHR, &result->pBuffers[i].isNull, &result->pBuffers[i].nLength,
+                                        &result->pBuffers[i].nCode, OCI_DEFAULT);
+            }
+            if (nStatus == OCI_SUCCESS)
+            {
+               *pdwError = DBERR_SUCCESS;
+            }
+            else
+            {
+               SetLastError(pConn);
+               *pdwError = IsConnectionError(pConn);
+            }
+            OCIDescriptorFree(handleParam, OCI_DTYPE_PARAM);
+         }
+         else
+         {
+            SetLastError(pConn);
+            *pdwError = IsConnectionError(pConn);
+            free(result);
+            result = NULL;
+            break;
+         }
+      }
+   }
+   else
+   {
+      free(result);
+      result = NULL;
+   }
+
+   return result;
+}
+
+/**
+ * Perform unbuffered SELECT query
+ */
+extern "C" DBDRV_UNBUFFERED_RESULT EXPORT DrvSelectUnbuffered(ORACLE_CONN *pConn, WCHAR *pwszQuery, DWORD *pdwError, WCHAR *errorText)
+{
+   ORACLE_UNBUFFERED_RESULT *result = NULL;
 
 #if UNICODE_UCS4
        UCS2CHAR *ucs2Query = UCS2StringFromUCS4String(pwszQuery);
@@ -1213,83 +1301,15 @@ extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(ORACLE_CONN *pConn, WCHAR *p
 
        MutexLock(pConn->mutexQueryLock);
 
-       pConn->pBuffers = NULL;
-       pConn->nCols = 0;
-
-       if (OCIStmtPrepare2(pConn->handleService, &pConn->handleStmt, pConn->handleError, (text *)ucs2Query,
+       OCIStmt *handleStmt;
+       if (OCIStmtPrepare2(pConn->handleService, &handleStmt, pConn->handleError, (text *)ucs2Query,
                            (ub4)ucs2_strlen(ucs2Query) * sizeof(UCS2CHAR), NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT) == OCI_SUCCESS)
        {
-      OCIAttrSet(pConn->handleStmt, OCI_HTYPE_STMT, &pConn->prefetchLimit, 0, OCI_ATTR_PREFETCH_ROWS, pConn->handleError);
-               if (OCIStmtExecute(pConn->handleService, pConn->handleStmt, pConn->handleError,
+      OCIAttrSet(handleStmt, OCI_HTYPE_STMT, &pConn->prefetchLimit, 0, OCI_ATTR_PREFETCH_ROWS, pConn->handleError);
+               if (OCIStmtExecute(pConn->handleService, handleStmt, pConn->handleError,
                                   0, 0, NULL, NULL, (pConn->nTransLevel == 0) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT) == OCI_SUCCESS)
                {
-                       OCIAttrGet(pConn->handleStmt, OCI_HTYPE_STMT, &nCount, NULL, OCI_ATTR_PARAM_COUNT, pConn->handleError);
-                       pConn->nCols = nCount;
-                       if (pConn->nCols > 0)
-                       {
-                               // Prepare receive buffers and fetch column names
-                               pConn->columnNames = (char **)malloc(sizeof(char *) * pConn->nCols);
-                               pConn->pBuffers = (ORACLE_FETCH_BUFFER *)malloc(sizeof(ORACLE_FETCH_BUFFER) * pConn->nCols);
-                               memset(pConn->pBuffers, 0, sizeof(ORACLE_FETCH_BUFFER) * pConn->nCols);
-                               for(i = 0; i < pConn->nCols; i++)
-                               {
-                                       pConn->pBuffers[i].isNull = 1;  // Mark all columns as NULL initially
-                                       if (OCIParamGet(pConn->handleStmt, OCI_HTYPE_STMT, pConn->handleError,
-                                                       (void **)&handleParam, (ub4)(i + 1)) == OCI_SUCCESS)
-                                       {
-                                               // Column name
-                                               if (OCIAttrGet(handleParam, OCI_DTYPE_PARAM, &colName, &nCount, OCI_ATTR_NAME, pConn->handleError) == OCI_SUCCESS)
-                                               {
-                                                       // We are in UTF-16 mode, so OCIAttrGet will return UTF-16 strings
-                                                       pConn->columnNames[i] = MBStringFromUCS2String((UCS2CHAR *)colName);
-                                               }
-                                               else
-                                               {
-                                                       pConn->columnNames[i] = strdup("");
-                                               }
-
-                                     // Data size
-                  sword nStatus;
-                  ub2 type = 0;
-                                     OCIAttrGet(handleParam, OCI_DTYPE_PARAM, &type, NULL, OCI_ATTR_DATA_TYPE, pConn->handleError);
-                  if (type == OCI_TYPECODE_CLOB)
-                  {
-                     pConn->pBuffers[i].pData = NULL;
-                     OCIDescriptorAlloc(pConn->handleEnv, (void **)&pConn->pBuffers[i].lobLocator, OCI_DTYPE_LOB, 0, NULL);
-                                        handleDefine = NULL;
-                                        nStatus = OCIDefineByPos(pConn->handleStmt, &handleDefine, pConn->handleError, i + 1,
-                                              &pConn->pBuffers[i].lobLocator, 0, SQLT_CLOB, &pConn->pBuffers[i].isNull, 
-                                              NULL, NULL, OCI_DEFAULT);
-                  }
-                  else
-                  {
-                     pConn->pBuffers[i].lobLocator = NULL;
-                                        OCIAttrGet(handleParam, OCI_DTYPE_PARAM, &nWidth, NULL, OCI_ATTR_DATA_SIZE, pConn->handleError);
-                                        pConn->pBuffers[i].pData = (UCS2CHAR *)malloc((nWidth + 31) * sizeof(UCS2CHAR));
-                                        handleDefine = NULL;
-                                        nStatus = OCIDefineByPos(pConn->handleStmt, &handleDefine, pConn->handleError, i + 1,
-                                              pConn->pBuffers[i].pData, (nWidth + 31) * sizeof(UCS2CHAR),
-                                                                 SQLT_CHR, &pConn->pBuffers[i].isNull, &pConn->pBuffers[i].nLength,
-                                                                 &pConn->pBuffers[i].nCode, OCI_DEFAULT);
-                  }
-                  if (nStatus == OCI_SUCCESS)
-                  {
-                                                       *pdwError = DBERR_SUCCESS;
-                  }
-                  else
-                                {
-                                        SetLastError(pConn);
-                                        *pdwError = IsConnectionError(pConn);
-                                }
-                                     OCIDescriptorFree(handleParam, OCI_DTYPE_PARAM);
-                                       }
-                                       else
-                                       {
-                                               SetLastError(pConn);
-                                               *pdwError = IsConnectionError(pConn);
-                                       }
-                               }
-                       }
+                  result = ProcessUnbufferedQueryResults(pConn, handleStmt, pdwError);
                }
                else
                {
@@ -1307,14 +1327,11 @@ extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(ORACLE_CONN *pConn, WCHAR *p
        free(ucs2Query);
 #endif
 
-       if (*pdwError == DBERR_SUCCESS)
-               return pConn;
+       if ((*pdwError == DBERR_SUCCESS) && (result != NULL))
+               return result;
 
        // On failure, unlock query mutex and do cleanup
-       OCIStmtRelease(pConn->handleStmt, pConn->handleError, NULL, 0, OCI_DEFAULT);
-       for(i = 0; i < pConn->nCols; i++)
-               safe_free(pConn->pBuffers[i].pData);
-       safe_free(pConn->pBuffers);
+       OCIStmtRelease(handleStmt, pConn->handleError, NULL, 0, OCI_DEFAULT);
        if (errorText != NULL)
        {
                wcsncpy(errorText, pConn->lastErrorText, DBDRV_MAX_ERROR_TEXT);
@@ -1325,95 +1342,129 @@ extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(ORACLE_CONN *pConn, WCHAR *p
 }
 
 /**
- * Fetch next result line from asynchronous SELECT results
+ * Perform SELECT query using prepared statement
  */
-extern "C" bool EXPORT DrvFetch(ORACLE_CONN *pConn)
+extern "C" DBDRV_UNBUFFERED_RESULT EXPORT DrvSelectPreparedUnbuffered(ORACLE_CONN *pConn, ORACLE_STATEMENT *stmt, DWORD *pdwError, WCHAR *errorText)
+{
+   ORACLE_UNBUFFERED_RESULT *result = NULL;
+
+   MutexLock(pConn->mutexQueryLock);
+
+   OCIAttrSet(stmt->handleStmt, OCI_HTYPE_STMT, &pConn->prefetchLimit, 0, OCI_ATTR_PREFETCH_ROWS, pConn->handleError);
+   if (OCIStmtExecute(pConn->handleService, stmt->handleStmt, pConn->handleError,
+                      0, 0, NULL, NULL, (pConn->nTransLevel == 0) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT) == OCI_SUCCESS)
+   {
+      result = ProcessUnbufferedQueryResults(pConn, stmt->handleStmt, pdwError);
+   }
+   else
+   {
+      SetLastError(pConn);
+      *pdwError = IsConnectionError(pConn);
+   }
+
+   if ((*pdwError == DBERR_SUCCESS) && (result != NULL))
+      return result;
+
+   // On failure, unlock query mutex and do cleanup
+   if (errorText != NULL)
+   {
+      wcsncpy(errorText, pConn->lastErrorText, DBDRV_MAX_ERROR_TEXT);
+      errorText[DBDRV_MAX_ERROR_TEXT - 1] = 0;
+   }
+   MutexUnlock(pConn->mutexQueryLock);
+   return NULL;
+}
+
+/**
+ * Fetch next result line from unbuffered SELECT results
+ */
+extern "C" bool EXPORT DrvFetch(ORACLE_UNBUFFERED_RESULT *result)
 {
        bool success;
 
-       if (pConn == NULL)
+       if (result == NULL)
                return false;
 
-       sword rc = OCIStmtFetch2(pConn->handleStmt, pConn->handleError, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+       sword rc = OCIStmtFetch2(result->handleStmt, result->connection->handleError, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
        if ((rc == OCI_SUCCESS) || (rc == OCI_SUCCESS_WITH_INFO))
        {
                success = true;
        }
        else
        {
-               SetLastError(pConn);
+               SetLastError(result->connection);
                success = false;
        }
        return success;
 }
 
 /**
- * Get field length from current row in async query result
+ * Get field length from current row in unbuffered query result
  */
-extern "C" LONG EXPORT DrvGetFieldLengthAsync(ORACLE_CONN *pConn, int nColumn)
+extern "C" LONG EXPORT DrvGetFieldLengthUnbuffered(ORACLE_UNBUFFERED_RESULT *result, int nColumn)
 {
-       if (pConn == NULL)
+       if (result == NULL)
                return 0;
 
-       if ((nColumn < 0) || (nColumn >= pConn->nCols))
+       if ((nColumn < 0) || (nColumn >= result->nCols))
                return 0;
 
-       if (pConn->pBuffers[nColumn].isNull)
+       if (result->pBuffers[nColumn].isNull)
                return 0;
 
-   if (pConn->pBuffers[nColumn].lobLocator != NULL)
+   if (result->pBuffers[nColumn].lobLocator != NULL)
    {
       ub4 length = 0;
-      OCILobGetLength(pConn->handleService, pConn->handleError, pConn->pBuffers[nColumn].lobLocator, &length);
+      OCILobGetLength(result->connection->handleService, result->connection->handleError, result->pBuffers[nColumn].lobLocator, &length);
       return (LONG)length;
    }
 
-       return (LONG)(pConn->pBuffers[nColumn].nLength / sizeof(UCS2CHAR));
+       return (LONG)(result->pBuffers[nColumn].nLength / sizeof(UCS2CHAR));
 }
 
 /**
- * Get field from current row in async query result
+ * Get field from current row in unbuffered query result
  */
-extern "C" WCHAR EXPORT *DrvGetFieldAsync(ORACLE_CONN *pConn, int nColumn, WCHAR *pBuffer, int nBufSize)
+extern "C" WCHAR EXPORT *DrvGetFieldUnbuffered(ORACLE_UNBUFFERED_RESULT *result, int nColumn, WCHAR *pBuffer, int nBufSize)
 {
        int nLen;
 
-       if (pConn == NULL)
+       if (result == NULL)
                return NULL;
 
-       if ((nColumn < 0) || (nColumn >= pConn->nCols))
+       if ((nColumn < 0) || (nColumn >= result->nCols))
                return NULL;
 
-       if (pConn->pBuffers[nColumn].isNull)
+       if (result->pBuffers[nColumn].isNull)
        {
                *pBuffer = 0;
        }
-   else if (pConn->pBuffers[nColumn].lobLocator != NULL)
+   else if (result->pBuffers[nColumn].lobLocator != NULL)
    {
       ub4 length = 0;
-      OCILobGetLength(pConn->handleService, pConn->handleError, pConn->pBuffers[nColumn].lobLocator, &length);
+      OCILobGetLength(result->connection->handleService, result->connection->handleError, result->pBuffers[nColumn].lobLocator, &length);
 
                nLen = min(nBufSize - 1, (int)length);
       ub4 amount = nLen;
 #if UNICODE_UCS4
       UCS2CHAR *ucs2buffer = (UCS2CHAR *)malloc(nLen * sizeof(UCS2CHAR));
-      OCILobRead(pConn->handleService, pConn->handleError, pConn->pBuffers[nColumn].lobLocator, &amount, 1, 
+      OCILobRead(result->connection->handleService, result->connection->handleError, result->pBuffers[nColumn].lobLocator, &amount, 1,
                  ucs2buffer, nLen * sizeof(UCS2CHAR), NULL, NULL, OCI_UCS2ID, SQLCS_IMPLICIT);
                ucs2_to_ucs4(ucs2buffer, nLen, pBuffer, nLen);
       free(ucs2buffer);
 #else
-      OCILobRead(pConn->handleService, pConn->handleError, pConn->pBuffers[nColumn].lobLocator, &amount, 1, 
+      OCILobRead(result->connection->handleService, result->connection->handleError, result->pBuffers[nColumn].lobLocator, &amount, 1,
                  pBuffer, nBufSize * sizeof(WCHAR), NULL, NULL, OCI_UCS2ID, SQLCS_IMPLICIT);
 #endif
                pBuffer[nLen] = 0;
    }
        else
        {
-               nLen = min(nBufSize - 1, ((int)(pConn->pBuffers[nColumn].nLength / sizeof(UCS2CHAR))));
+               nLen = min(nBufSize - 1, ((int)(result->pBuffers[nColumn].nLength / sizeof(UCS2CHAR))));
 #if UNICODE_UCS4
-               ucs2_to_ucs4(pConn->pBuffers[nColumn].pData, nLen, pBuffer, nLen + 1);
+               ucs2_to_ucs4(result->pBuffers[nColumn].pData, nLen, pBuffer, nLen + 1);
 #else
-               memcpy(pBuffer, pConn->pBuffers[nColumn].pData, nLen * sizeof(WCHAR));
+               memcpy(pBuffer, result->pBuffers[nColumn].pData, nLen * sizeof(WCHAR));
 #endif
                pBuffer[nLen] = 0;
        }
@@ -1422,49 +1473,48 @@ extern "C" WCHAR EXPORT *DrvGetFieldAsync(ORACLE_CONN *pConn, int nColumn, WCHAR
 }
 
 /**
- * Get column count in async query result
+ * Get column count in unbuffered query result
  */
-extern "C" int EXPORT DrvGetColumnCountAsync(ORACLE_CONN *pConn)
+extern "C" int EXPORT DrvGetColumnCountUnbuffered(ORACLE_UNBUFFERED_RESULT *result)
 {
-       return (pConn != NULL) ? pConn->nCols : 0;
+       return (result != NULL) ? result->nCols : 0;
 }
 
 /**
- * Get column name in async query result
+ * Get column name in unbuffered query result
  */
-extern "C" const char EXPORT *DrvGetColumnNameAsync(ORACLE_CONN *pConn, int column)
+extern "C" const char EXPORT *DrvGetColumnNameUnbuffered(ORACLE_UNBUFFERED_RESULT *result, int column)
 {
-       return ((pConn != NULL) && (column >= 0) && (column < pConn->nCols)) ? pConn->columnNames[column] : NULL;
+       return ((result != NULL) && (column >= 0) && (column < result->nCols)) ? result->columnNames[column] : NULL;
 }
 
 /**
- * Destroy result of async query
+ * Destroy result of unbuffered query
  */
-extern "C" void EXPORT DrvFreeAsyncResult(ORACLE_CONN *pConn)
+extern "C" void EXPORT DrvFreeUnbufferedResult(ORACLE_UNBUFFERED_RESULT *result)
 {
        int i;
 
-       if (pConn == NULL)
+       if (result == NULL)
                return;
 
-       OCIStmtRelease(pConn->handleStmt, pConn->handleError, NULL, 0, OCI_DEFAULT);
+       OCIStmtRelease(result->handleStmt, result->connection->handleError, NULL, 0, OCI_DEFAULT);
 
-       for(i = 0; i < pConn->nCols; i++)
+       for(i = 0; i < result->nCols; i++)
    {
-               safe_free(pConn->pBuffers[i].pData);
-      if (pConn->pBuffers[i].lobLocator != NULL)
+               safe_free(result->pBuffers[i].pData);
+      if (result->pBuffers[i].lobLocator != NULL)
       {
-         OCIDescriptorFree(pConn->pBuffers[i].lobLocator, OCI_DTYPE_LOB);
+         OCIDescriptorFree(result->pBuffers[i].lobLocator, OCI_DTYPE_LOB);
       }
    }
-       safe_free_and_null(pConn->pBuffers);
+       free(result->pBuffers);
 
-       for(i = 0; i < pConn->nCols; i++)
-               safe_free(pConn->columnNames[i]);
-       safe_free_and_null(pConn->columnNames);
+       for(i = 0; i < result->nCols; i++)
+               free(result->columnNames[i]);
+       free(result->columnNames);
 
-       pConn->nCols = 0;
-       MutexUnlock(pConn->mutexQueryLock);
+       MutexUnlock(result->connection->mutexQueryLock);
 }
 
 /**
index 233e89f..7c033bf 100644 (file)
@@ -1,6 +1,6 @@
 /* $Id$ */
 /** Oracle Database Driver
-** Copyright (C) 2007, 2008, 2009 Victor Kirhenshtein
+** Copyright (C) 2007-2015 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -62,15 +62,11 @@ struct ORACLE_CONN
        OCIServer *handleServer;
        OCISvcCtx *handleService;
        OCISession *handleSession;
-       OCIStmt *handleStmt;
        OCIError *handleError;
        MUTEX mutexQueryLock;
        int nTransLevel;
        sb4 lastErrorCode;
        WCHAR lastErrorText[DBDRV_MAX_ERROR_TEXT];
-       ORACLE_FETCH_BUFFER *pBuffers;
-       int nCols;
-       char **columnNames;
    ub4 prefetchLimit;
 };
 
@@ -127,4 +123,13 @@ struct ORACLE_RESULT
        char **columnNames;
 };
 
+struct ORACLE_UNBUFFERED_RESULT
+{
+   ORACLE_CONN *connection;
+   OCIStmt *handleStmt;
+   ORACLE_FETCH_BUFFER *pBuffers;
+   int nCols;
+   char **columnNames;
+};
+
 #endif   /* _oracledrv_h_ */
index 78ded59..b487b86 100644 (file)
@@ -200,14 +200,14 @@ extern "C" DBDRV_CONNECTION EXPORT DrvConnect(const char *szHost, const char *sz
        if (pConn != NULL)
        {
                // should be replaced with PQconnectdb();
-               pConn->pHandle = PQsetdbLogin(szHost, port, NULL, NULL, szDatabase, szLogin, szPassword);
+               pConn->handle = PQsetdbLogin(szHost, port, NULL, NULL, szDatabase, szLogin, szPassword);
 
-               if (PQstatus(pConn->pHandle) == CONNECTION_BAD)
+               if (PQstatus(pConn->handle) == CONNECTION_BAD)
                {
-                       MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->pHandle), -1, errorText, DBDRV_MAX_ERROR_TEXT);
+                       MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->handle), -1, errorText, DBDRV_MAX_ERROR_TEXT);
                        errorText[DBDRV_MAX_ERROR_TEXT - 1] = 0;
                        RemoveTrailingCRLFW(errorText);
-                       PQfinish(pConn->pHandle);
+                       PQfinish(pConn->handle);
                        free(pConn);
                        pConn = NULL;
                }
@@ -215,16 +215,16 @@ extern "C" DBDRV_CONNECTION EXPORT DrvConnect(const char *szHost, const char *sz
                {
                        PGresult        *pResult;
 
-                       pResult = PQexec(pConn->pHandle, "SET standard_conforming_strings TO off");
+                       pResult = PQexec(pConn->handle, "SET standard_conforming_strings TO off");
                        PQclear(pResult);
                        
-                       pResult = PQexec(pConn->pHandle, "SET escape_string_warning TO off");
+                       pResult = PQexec(pConn->handle, "SET escape_string_warning TO off");
                        PQclear(pResult);
 
-                       PQsetClientEncoding(pConn->pHandle, "UTF8");
+                       PQsetClientEncoding(pConn->handle, "UTF8");
 
                pConn->mutexQueryLock = MutexCreate();
-         pConn->pFetchBuffer = NULL;
+         pConn->fetchBuffer = NULL;
 
                        if ((schema != NULL) && (schema[0] != 0))
                        {
@@ -253,7 +253,7 @@ extern "C" void EXPORT DrvDisconnect(DBDRV_CONNECTION pConn)
 {
        if (pConn != NULL)
        {
-       PQfinish(((PG_CONN *)pConn)->pHandle);
+       PQfinish(((PG_CONN *)pConn)->handle);
        MutexDestroy(((PG_CONN *)pConn)->mutexQueryLock);
       free(pConn);
        }
@@ -332,17 +332,17 @@ extern "C" DBDRV_STATEMENT EXPORT DrvPrepare(PG_CONN *pConn, WCHAR *pwszQuery, D
    snprintf(hStmt->name, 64, "netxms_stmt_%p_%d", hStmt, (int)InterlockedIncrement(&s_statementId));
 
        MutexLock(pConn->mutexQueryLock);
-       PGresult        *pResult = PQprepare(pConn->pHandle, hStmt->name, pszQueryUTF8, 0, NULL);
+       PGresult        *pResult = PQprepare(pConn->handle, hStmt->name, pszQueryUTF8, 0, NULL);
        if ((pResult == NULL) || (PQresultStatus(pResult) != PGRES_COMMAND_OK))
        {
                free(hStmt);
                hStmt = NULL;
 
-               *pdwError = (PQstatus(pConn->pHandle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+               *pdwError = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
 
                if (errorText != NULL)
                {
-                       MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->pHandle), -1, errorText, DBDRV_MAX_ERROR_TEXT);
+                       MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->handle), -1, errorText, DBDRV_MAX_ERROR_TEXT);
                        errorText[DBDRV_MAX_ERROR_TEXT - 1] = 0;
                        RemoveTrailingCRLFW(errorText);
                }
@@ -429,7 +429,7 @@ extern "C" DWORD EXPORT DrvExecute(PG_CONN *pConn, PG_STATEMENT *hStmt, WCHAR *e
    do
    {
       retry = false;
-          PGresult     *pResult = PQexecPrepared(pConn->pHandle, hStmt->name, hStmt->pcount, hStmt->buffers, NULL, NULL, 0);
+          PGresult     *pResult = PQexecPrepared(pConn->handle, hStmt->name, hStmt->pcount, hStmt->buffers, NULL, NULL, 0);
           if (pResult != NULL)
           {
                   if (PQresultStatus(pResult) == PGRES_COMMAND_OK)
@@ -441,7 +441,7 @@ extern "C" DWORD EXPORT DrvExecute(PG_CONN *pConn, PG_STATEMENT *hStmt, WCHAR *e
          else
                   {
             const char *sqlState = PQresultErrorField(pResult, PG_DIAG_SQLSTATE);
-            if ((PQstatus(pConn->pHandle) != CONNECTION_BAD) && 
+            if ((PQstatus(pConn->handle) != CONNECTION_BAD) &&
                 (sqlState != NULL) && (!strcmp(sqlState, "53000") || !strcmp(sqlState, "53200")) && (retryCount > 0))
             {
                ThreadSleep(500);
@@ -459,11 +459,11 @@ extern "C" DWORD EXPORT DrvExecute(PG_CONN *pConn, PG_STATEMENT *hStmt, WCHAR *e
                      errorText[len] = L' ';
                      len++;
                   }
-                                     MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->pHandle), -1, &errorText[len], DBDRV_MAX_ERROR_TEXT - len);
+                                     MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->handle), -1, &errorText[len], DBDRV_MAX_ERROR_TEXT - len);
                                      errorText[DBDRV_MAX_ERROR_TEXT - 1] = 0;
                                      RemoveTrailingCRLFW(errorText);
                              }
-                             rc = (PQstatus(pConn->pHandle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+                             rc = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
             }
                   }
 
@@ -511,7 +511,7 @@ static bool UnsafeDrvQuery(PG_CONN *pConn, const char *szQuery, WCHAR *errorText
    int retryCount = 60;
 
 retry:
-   PGresult    *pResult = PQexec(pConn->pHandle, szQuery);
+   PGresult    *pResult = PQexec(pConn->handle, szQuery);
 
        if (pResult == NULL)
        {
@@ -523,7 +523,7 @@ retry:
        if (PQresultStatus(pResult) != PGRES_COMMAND_OK)
        {
       const char *sqlState = PQresultErrorField(pResult, PG_DIAG_SQLSTATE);
-      if ((PQstatus(pConn->pHandle) != CONNECTION_BAD) && 
+      if ((PQstatus(pConn->handle) != CONNECTION_BAD) &&
           (sqlState != NULL) && (!strcmp(sqlState, "53000") || !strcmp(sqlState, "53200")) && (retryCount > 0))
       {
          ThreadSleep(500);
@@ -542,7 +542,7 @@ retry:
                errorText[len] = L' ';
                len++;
             }
-                     MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->pHandle), -1, &errorText[len], DBDRV_MAX_ERROR_TEXT - len);
+                     MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->handle), -1, &errorText[len], DBDRV_MAX_ERROR_TEXT - len);
                      errorText[DBDRV_MAX_ERROR_TEXT - 1] = 0;
                      RemoveTrailingCRLFW(errorText);
              }
@@ -572,7 +572,7 @@ extern "C" DWORD EXPORT DrvQuery(PG_CONN *pConn, WCHAR *pwszQuery, WCHAR *errorT
    }
    else
    {
-      dwRet = (PQstatus(pConn->pHandle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+      dwRet = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
    }
        MutexUnlock(pConn->mutexQueryLock);
    free(pszQueryUTF8);
@@ -588,7 +588,7 @@ static DBDRV_RESULT UnsafeDrvSelect(PG_CONN *pConn, const char *szQuery, WCHAR *
    int retryCount = 60;
 
 retry:
-       PGresult        *pResult = PQexec(((PG_CONN *)pConn)->pHandle, szQuery);
+       PGresult        *pResult = PQexec(((PG_CONN *)pConn)->handle, szQuery);
 
        if (pResult == NULL)
        {
@@ -601,7 +601,7 @@ retry:
            (PQresultStatus(pResult) != PGRES_TUPLES_OK))
        {       
       const char *sqlState = PQresultErrorField(pResult, PG_DIAG_SQLSTATE);
-      if ((PQstatus(pConn->pHandle) != CONNECTION_BAD) && 
+      if ((PQstatus(pConn->handle) != CONNECTION_BAD) &&
           (sqlState != NULL) && (!strcmp(sqlState, "53000") || !strcmp(sqlState, "53200")) && (retryCount > 0))
       {
          ThreadSleep(500);
@@ -620,7 +620,7 @@ retry:
                errorText[len] = L' ';
                len++;
             }
-                     MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->pHandle), -1, &errorText[len], DBDRV_MAX_ERROR_TEXT - len);
+                     MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->handle), -1, &errorText[len], DBDRV_MAX_ERROR_TEXT - len);
                      errorText[DBDRV_MAX_ERROR_TEXT - 1] = 0;
                      RemoveTrailingCRLFW(errorText);
              }
@@ -651,7 +651,7 @@ extern "C" DBDRV_RESULT EXPORT DrvSelect(PG_CONN *pConn, WCHAR *pwszQuery, DWORD
    }
    else
    {
-      *pdwError = (PQstatus(pConn->pHandle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+      *pdwError = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
    }
        MutexUnlock(pConn->mutexQueryLock);
    free(pszQueryUTF8);
@@ -672,7 +672,7 @@ extern "C" DBDRV_RESULT EXPORT DrvSelectPrepared(PG_CONN *pConn, PG_STATEMENT *h
    do
    {
       retry = false;
-          pResult = PQexecPrepared(pConn->pHandle, hStmt->name, hStmt->pcount, hStmt->buffers, NULL, NULL, 0);
+          pResult = PQexecPrepared(pConn->handle, hStmt->name, hStmt->pcount, hStmt->buffers, NULL, NULL, 0);
           if (pResult != NULL)
           {
                   if ((PQresultStatus(pResult) == PGRES_COMMAND_OK) ||
@@ -685,7 +685,7 @@ extern "C" DBDRV_RESULT EXPORT DrvSelectPrepared(PG_CONN *pConn, PG_STATEMENT *h
                   else
                   {
             const char *sqlState = PQresultErrorField(pResult, PG_DIAG_SQLSTATE);
-            if ((PQstatus(pConn->pHandle) != CONNECTION_BAD) && 
+            if ((PQstatus(pConn->handle) != CONNECTION_BAD) &&
                 (sqlState != NULL) && (!strcmp(sqlState, "53000") || !strcmp(sqlState, "53200")) && (retryCount > 0))
             {
                ThreadSleep(500);
@@ -703,21 +703,21 @@ extern "C" DBDRV_RESULT EXPORT DrvSelectPrepared(PG_CONN *pConn, PG_STATEMENT *h
                      errorText[len] = L' ';
                      len++;
                   }
-                                     MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->pHandle), -1, &errorText[len], DBDRV_MAX_ERROR_TEXT - len);
+                                     MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->handle), -1, &errorText[len], DBDRV_MAX_ERROR_TEXT - len);
                                      errorText[DBDRV_MAX_ERROR_TEXT - 1] = 0;
                                      RemoveTrailingCRLFW(errorText);
                              }
             }
                           PQclear(pResult);
                           pResult = NULL;
-                *pdwError = (PQstatus(pConn->pHandle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+                *pdwError = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
                   }
           }
           else
           {
                   if (errorText != NULL)
                           wcsncpy(errorText, L"Internal error (pResult is NULL in UnsafeDrvSelect)", DBDRV_MAX_ERROR_TEXT);
-         *pdwError = (PQstatus(pConn->pHandle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+         *pdwError = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
           }
    }
    while(retry);
@@ -796,11 +796,9 @@ extern "C" const char EXPORT *DrvGetColumnName(DBDRV_RESULT hResult, int column)
        return (hResult != NULL) ? PQfname((PGresult *)hResult, column) : NULL;
 }
 
-
-//
-// Free SELECT results
-//
-
+/**
+ * Free SELECT results
+ */
 extern "C" void EXPORT DrvFreeResult(DBDRV_RESULT pResult)
 {
        if (pResult != NULL)
@@ -810,105 +808,212 @@ extern "C" void EXPORT DrvFreeResult(DBDRV_RESULT pResult)
 }
 
 /**
- * Perform asynchronous SELECT query
+ * Perform unbuffered SELECT query
  */
-extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(PG_CONN *pConn, WCHAR *pwszQuery, DWORD *pdwError, WCHAR *errorText)
+extern "C" DBDRV_UNBUFFERED_RESULT EXPORT DrvSelectUnbuffered(PG_CONN *pConn, WCHAR *pwszQuery, DWORD *pdwError, WCHAR *errorText)
 {
-       bool bSuccess = false;
-   char *pszReq, *pszQueryUTF8;
-   static char szDeclareCursor[] = "DECLARE cur1 CURSOR FOR ";
-
        if (pConn == NULL)
                return NULL;
 
        MutexLock(pConn->mutexQueryLock);
+       pConn->fetchBuffer = NULL;
+   pConn->keepFetchBuffer = true;
 
-       if (UnsafeDrvQuery(pConn, "BEGIN", errorText))
+       bool success = false;
+       bool retry;
+       int retryCount = 60;
+   char *queryUTF8 = UTF8StringFromWideString(pwszQuery);
+   do
    {
-      pszQueryUTF8 = UTF8StringFromWideString(pwszQuery);
-       pszReq = (char *)malloc(strlen(pszQueryUTF8) + sizeof(szDeclareCursor));
-          if (pszReq != NULL)
-          {
-                  strcpy(pszReq, szDeclareCursor);
-                  strcat(pszReq, pszQueryUTF8);
-                  if (UnsafeDrvQuery(pConn, pszReq, errorText))
-                  {
-            ((PG_CONN *)pConn)->pFetchBuffer = PQdescribePortal(pConn->pHandle, "cur1");
-                          bSuccess = true;
-                  }
-                  free(pszReq);
-          }
-      free(pszQueryUTF8);
-
-      if (!bSuccess)
-         UnsafeDrvQuery(pConn, "ROLLBACK", NULL);
+      retry = false;
+      if (PQsendQuery(pConn->handle, queryUTF8))
+      {
+         if (PQsetSingleRowMode(pConn->handle))
+         {
+            // Fetch first row (to check for errors in Select instead of Fetch call)
+            pConn->fetchBuffer = PQgetResult(pConn->handle);
+            if ((PQresultStatus(pConn->fetchBuffer) == PGRES_COMMAND_OK) ||
+                (PQresultStatus(pConn->fetchBuffer) == PGRES_TUPLES_OK) ||
+                (PQresultStatus(pConn->fetchBuffer) == PGRES_SINGLE_TUPLE))
+            {
+               if (errorText != NULL)
+                  *errorText = 0;
+               *pdwError = DBERR_SUCCESS;
+               success = true;
+            }
+            else
+            {
+               const char *sqlState = PQresultErrorField(pConn->fetchBuffer, PG_DIAG_SQLSTATE);
+               if ((PQstatus(pConn->handle) != CONNECTION_BAD) &&
+                   (sqlState != NULL) && (!strcmp(sqlState, "53000") || !strcmp(sqlState, "53200")) && (retryCount > 0))
+               {
+                  ThreadSleep(500);
+                  retry = true;
+                  retryCount--;
+               }
+               else
+               {
+                  if (errorText != NULL)
+                  {
+                     MultiByteToWideChar(CP_UTF8, 0, CHECK_NULL_EX_A(sqlState), -1, errorText, DBDRV_MAX_ERROR_TEXT);
+                     int len = (int)wcslen(errorText);
+                     if (len > 0)
+                     {
+                        errorText[len] = L' ';
+                        len++;
+                     }
+                     MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->handle), -1, &errorText[len], DBDRV_MAX_ERROR_TEXT - len);
+                     errorText[DBDRV_MAX_ERROR_TEXT - 1] = 0;
+                     RemoveTrailingCRLFW(errorText);
+                  }
+               }
+               PQclear(pConn->fetchBuffer);
+               pConn->fetchBuffer = NULL;
+               *pdwError = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+            }
+         }
+         else
+         {
+            if (errorText != NULL)
+               wcsncpy(errorText, L"Internal error (pResult is NULL in UnsafeDrvSelect)", DBDRV_MAX_ERROR_TEXT);
+            *pdwError = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+         }
+      }
    }
+   while(retry);
+   return (DBDRV_UNBUFFERED_RESULT)pConn;
+}
+
+/**
+ * Perform unbuffered SELECT query using prepared statement
+ */
+extern "C" DBDRV_UNBUFFERED_RESULT EXPORT DrvSelectPreparedUnbuffered(PG_CONN *pConn, PG_STATEMENT *hStmt, DWORD *pdwError, WCHAR *errorText)
+{
+   if (pConn == NULL)
+      return NULL;
+
+   MutexLock(pConn->mutexQueryLock);
+   pConn->fetchBuffer = NULL;
+   pConn->keepFetchBuffer = true;
 
-       if (bSuccess)
+   bool success = false;
+   bool retry;
+   int retryCount = 60;
+   do
    {
-      *pdwError = DBERR_SUCCESS;
+      retry = false;
+      if (PQsendQueryPrepared(pConn->handle, hStmt->name, hStmt->pcount, hStmt->buffers, NULL, NULL, 0))
+      {
+         if (PQsetSingleRowMode(pConn->handle))
+         {
+            // Fetch first row (to check for errors in Select instead of Fetch call)
+            pConn->fetchBuffer = PQgetResult(pConn->handle);
+            if ((PQresultStatus(pConn->fetchBuffer) == PGRES_COMMAND_OK) ||
+                (PQresultStatus(pConn->fetchBuffer) == PGRES_TUPLES_OK) ||
+                (PQresultStatus(pConn->fetchBuffer) == PGRES_SINGLE_TUPLE))
+            {
+               if (errorText != NULL)
+                  *errorText = 0;
+               *pdwError = DBERR_SUCCESS;
+               success = true;
+            }
+            else
+            {
+               const char *sqlState = PQresultErrorField(pConn->fetchBuffer, PG_DIAG_SQLSTATE);
+               if ((PQstatus(pConn->handle) != CONNECTION_BAD) &&
+                   (sqlState != NULL) && (!strcmp(sqlState, "53000") || !strcmp(sqlState, "53200")) && (retryCount > 0))
+               {
+                  ThreadSleep(500);
+                  retry = true;
+                  retryCount--;
+               }
+               else
+               {
+                  if (errorText != NULL)
+                  {
+                     MultiByteToWideChar(CP_UTF8, 0, CHECK_NULL_EX_A(sqlState), -1, errorText, DBDRV_MAX_ERROR_TEXT);
+                     int len = (int)wcslen(errorText);
+                     if (len > 0)
+                     {
+                        errorText[len] = L' ';
+                        len++;
+                     }
+                     MultiByteToWideChar(CP_UTF8, 0, PQerrorMessage(pConn->handle), -1, &errorText[len], DBDRV_MAX_ERROR_TEXT - len);
+                     errorText[DBDRV_MAX_ERROR_TEXT - 1] = 0;
+                     RemoveTrailingCRLFW(errorText);
+                  }
+               }
+               PQclear(pConn->fetchBuffer);
+               pConn->fetchBuffer = NULL;
+               *pdwError = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+            }
+         }
+         else
+         {
+            if (errorText != NULL)
+               wcsncpy(errorText, L"Internal error (pResult is NULL in UnsafeDrvSelect)", DBDRV_MAX_ERROR_TEXT);
+            *pdwError = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+         }
+      }
    }
-   else
-       {
-      *pdwError = (PQstatus(pConn->pHandle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
-               MutexUnlock(pConn->mutexQueryLock);
-               return NULL;
-       }
-
-       return (DBDRV_ASYNC_RESULT)pConn;
+   while(retry);
+   return (DBDRV_UNBUFFERED_RESULT)pConn;
 }
 
 /**
  * Fetch next result line from asynchronous SELECT results
  */
-extern "C" bool EXPORT DrvFetch(DBDRV_ASYNC_RESULT pConn)
+extern "C" bool EXPORT DrvFetch(PG_CONN *pConn)
 {
-   bool bResult = true;
-   
    if (pConn == NULL)
+      return false;
+
+   if (!pConn->keepFetchBuffer)
    {
-      bResult = false;
+      if (pConn->fetchBuffer != NULL)
+         PQclear(pConn->fetchBuffer);
+      pConn->fetchBuffer = PQgetResult(pConn->handle);
    }
    else
    {
-      if (((PG_CONN *)pConn)->pFetchBuffer != NULL)
-         PQclear(((PG_CONN *)pConn)->pFetchBuffer);
-               ((PG_CONN *)pConn)->pFetchBuffer =
-                       (PGresult *)UnsafeDrvSelect((PG_CONN *)pConn, "FETCH cur1", NULL);
-               if (((PG_CONN *)pConn)->pFetchBuffer != NULL)
-      {
-         if (DrvGetNumRows(((PG_CONN *)pConn)->pFetchBuffer) <= 0)
-                  {
-            PQclear(((PG_CONN *)pConn)->pFetchBuffer);
-            ((PG_CONN *)pConn)->pFetchBuffer = NULL;
-                          bResult = false;
-                  }
-      }
-      else
-      {
-         bResult = false;
-      }
+      pConn->keepFetchBuffer = false;
+   }
+
+   if (pConn->fetchBuffer == NULL)
+      return false;
+
+   bool success;
+   if ((PQresultStatus(pConn->fetchBuffer) == PGRES_SINGLE_TUPLE) || (PQresultStatus(pConn->fetchBuffer) == PGRES_TUPLES_OK))
+   {
+      success = (PQntuples(pConn->fetchBuffer) > 0);
+   }
+   else
+   {
+      PQclear(pConn->fetchBuffer);
+      pConn->fetchBuffer = NULL;
+      success = false;
    }
-   return bResult;
+
+   return success;
 }
 
 /**
  * Get field length from async quety result
  */
-extern "C" LONG EXPORT DrvGetFieldLengthAsync(PG_CONN *pConn, int nColumn)
+extern "C" LONG EXPORT DrvGetFieldLengthUnbuffered(PG_CONN *pConn, int nColumn)
 {
-       if ((pConn == NULL) || (pConn->pFetchBuffer == NULL))
+       if ((pConn == NULL) || (pConn->fetchBuffer == NULL))
        {
                return 0;
        }
 
        // validate column index
-       if (nColumn >= PQnfields(pConn->pFetchBuffer))
+       if (nColumn >= PQnfields(pConn->fetchBuffer))
        {
                return 0;
        }
 
-       char *value = PQgetvalue(pConn->pFetchBuffer, 0, nColumn);
+       char *value = PQgetvalue(pConn->fetchBuffer, 0, nColumn);
        if (value == NULL)
        {
                return 0;
@@ -920,17 +1025,17 @@ extern "C" LONG EXPORT DrvGetFieldLengthAsync(PG_CONN *pConn, int nColumn)
 /**
  * Get field from current row in async query result
  */
-extern "C" WCHAR EXPORT *DrvGetFieldAsync(PG_CONN *pConn, int nColumn, WCHAR *pBuffer, int nBufSize)
+extern "C" WCHAR EXPORT *DrvGetFieldUnbuffered(PG_CONN *pConn, int nColumn, WCHAR *pBuffer, int nBufSize)
 {
        char *pszResult;
 
-       if ((pConn == NULL) || (pConn->pFetchBuffer == NULL))
+       if ((pConn == NULL) || (pConn->fetchBuffer == NULL))
        {
                return NULL;
        }
 
        // validate column index
-       if (nColumn >= PQnfields(pConn->pFetchBuffer))
+       if (nColumn >= PQnfields(pConn->fetchBuffer))
        {
                return NULL;
        }
@@ -938,24 +1043,20 @@ extern "C" WCHAR EXPORT *DrvGetFieldAsync(PG_CONN *pConn, int nColumn, WCHAR *pB
        // FIXME: correct processing of binary fields
        // PQfformat not supported in 7.3
 #ifdef HAVE_PQFFORMAT
-       if (PQfformat(pConn->pFetchBuffer, nColumn) != 0)
+       if (PQfformat(pConn->fetchBuffer, nColumn) != 0)
 #else
-       if (PQbinaryTuples(pConn->pFetchBuffer) != 0)
+       if (PQbinaryTuples(pConn->fetchBuffer) != 0)
 #endif
        {
-               //fprintf(stderr, "db:postgres:binary fields not supported\n");
-               //fflush(stderr);
-               // abort();
                return NULL;
        }
 
-       pszResult = PQgetvalue(pConn->pFetchBuffer, 0, nColumn);
+       pszResult = PQgetvalue(pConn->fetchBuffer, 0, nColumn);
        if (pszResult == NULL)
        {
                return NULL;
        }
 
-       // Now get column data
    MultiByteToWideChar(CP_UTF8, 0, pszResult, -1, pBuffer, nBufSize);
    pBuffer[nBufSize - 1] = 0;
 
@@ -965,34 +1066,36 @@ extern "C" WCHAR EXPORT *DrvGetFieldAsync(PG_CONN *pConn, int nColumn, WCHAR *pB
 /**
  * Get column count in async query result
  */
-extern "C" int EXPORT DrvGetColumnCountAsync(DBDRV_ASYNC_RESULT hResult)
+extern "C" int EXPORT DrvGetColumnCountUnbuffered(PG_CONN *hResult)
 {
-       return ((hResult != NULL) && (((PG_CONN *)hResult)->pFetchBuffer != NULL)) ? PQnfields(((PG_CONN *)hResult)->pFetchBuffer) : 0;
+       return ((hResult != NULL) && (hResult->fetchBuffer != NULL)) ? PQnfields(hResult->fetchBuffer) : 0;
 }
 
 /**
  * Get column name in async query result
  */
-extern "C" const char EXPORT *DrvGetColumnNameAsync(DBDRV_ASYNC_RESULT hResult, int column)
+extern "C" const char EXPORT *DrvGetColumnNameUnbuffered(PG_CONN *hResult, int column)
 {
-       return ((hResult != NULL) && (((PG_CONN *)hResult)->pFetchBuffer != NULL))? PQfname(((PG_CONN *)hResult)->pFetchBuffer, column) : NULL;
+       return ((hResult != NULL) && (hResult->fetchBuffer != NULL))? PQfname(hResult->fetchBuffer, column) : NULL;
 }
 
 /**
  * Destroy result of async query
  */
-extern "C" void EXPORT DrvFreeAsyncResult(PG_CONN *pConn)
+extern "C" void EXPORT DrvFreeUnbufferedResult(PG_CONN *pConn)
 {
    if (pConn == NULL)
       return;
 
-   if (pConn->pFetchBuffer != NULL)
+   if (pConn->fetchBuffer != NULL)
    {
-      PQclear(pConn->pFetchBuffer);
-      pConn->pFetchBuffer = NULL;
+      PQclear(pConn->fetchBuffer);
+      pConn->fetchBuffer = NULL;
    }
-   UnsafeDrvQuery(pConn, "CLOSE cur1", NULL);
-   UnsafeDrvQuery(pConn, "COMMIT", NULL);
+
+   // read all outstanding results
+   while(PQgetResult(pConn->handle) != NULL);
+
    MutexUnlock(pConn->mutexQueryLock);
 }
 
@@ -1013,17 +1116,15 @@ extern "C" DWORD EXPORT DrvBegin(PG_CONN *pConn)
    }
    else
    {
-      dwResult = (PQstatus(pConn->pHandle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
+      dwResult = (PQstatus(pConn->handle) == CONNECTION_BAD) ? DBERR_CONNECTION_LOST : DBERR_OTHER_ERROR;
    }
        MutexUnlock(pConn->mutexQueryLock);
    return dwResult;
 }
 
-
-//
-// Commit transaction
-//
-
+/**
+ * Commit transaction
+ */
 extern "C" DWORD EXPORT DrvCommit(PG_CONN *pConn)
 {
    bool bRet;
index dbbcfee..026e70c 100644 (file)
@@ -45,8 +45,9 @@
 
 typedef struct
 {
-       PGconn *pHandle;
-       PGresult *pFetchBuffer;
+       PGconn *handle;
+       PGresult *fetchBuffer;
+       bool keepFetchBuffer;
        MUTEX mutexQueryLock;
 } PG_CONN;
 
diff --git a/src/db/dbdrv/sqlite/.cproject b/src/db/dbdrv/sqlite/.cproject
new file mode 100644 (file)
index 0000000..62156be
--- /dev/null
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+       <storageModule moduleId="org.eclipse.cdt.core.settings">
+               <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1509404546">
+                       <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1509404546" moduleId="org.eclipse.cdt.core.settings" name="Default">
+                               <externalSettings/>
+                               <extensions>
+                                       <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+                               </extensions>
+                       </storageModule>
+                       <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+                               <configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.1509404546" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+                                       <folderInfo id="cdt.managedbuild.toolchain.gnu.base.1509404546.1448224696" name="/" resourcePath="">
+                                               <toolChain id="cdt.managedbuild.toolchain.gnu.base.2051980121" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+                                                       <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.305376511" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+                                                       <builder id="cdt.managedbuild.target.gnu.builder.base.533846172" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
+                                                       <tool id="cdt.managedbuild.tool.gnu.archiver.base.458109626" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+                                                       <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1331044278" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+                                                               <option id="gnu.cpp.compiler.option.include.paths.235707540" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}/include&quot;"/>
+                                                               </option>
+                                                               <option id="gnu.cpp.compiler.option.preprocessor.def.1645313309" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+                                                                       <listOptionValue builtIn="false" value="_THREAD_SAFE"/>
+                                                                       <listOptionValue builtIn="false" value="TRE_WCHAR=1"/>
+                                                                       <listOptionValue builtIn="false" value="UNICODE"/>
+                                                                       <listOptionValue builtIn="false" value="_GNU_SOURCE"/>
+                                                               </option>
+                                                               <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.2034524751" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+                                                       </tool>
+                                                       <tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1303745534" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+                                                               <option id="gnu.c.compiler.option.include.paths.396207137" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}/include&quot;"/>
+                                                               </option>
+                                                               <option id="gnu.c.compiler.option.preprocessor.def.symbols.1843385456" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+                                                                       <listOptionValue builtIn="false" value="_THREAD_SAFE"/>
+                                                                       <listOptionValue builtIn="false" value="TRE_WCHAR=1"/>
+                                                                       <listOptionValue builtIn="false" value="UNICODE"/>
+                                                                       <listOptionValue builtIn="false" value="_GNU_SOURCE"/>
+                                                               </option>
+                                                               <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1810665783" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+                                                       </tool>
+                                                       <tool id="cdt.managedbuild.tool.gnu.c.linker.base.2085452289" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+                                                       <tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.777264770" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+                                                               <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1125618544" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+                                                                       <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+                                                                       <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+                                                               </inputType>
+                                                       </tool>
+                                                       <tool id="cdt.managedbuild.tool.gnu.assembler.base.176099933" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+                                                               <option id="gnu.both.asm.option.include.paths.1663072604" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}/include&quot;"/>
+                                                               </option>
+                                                               <inputType id="cdt.managedbuild.tool.gnu.assembler.input.836147139" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+                                                       </tool>
+                                               </toolChain>
+                                       </folderInfo>
+                               </configuration>
+                       </storageModule>
+                       <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+               </cconfiguration>
+       </storageModule>
+       <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+               <project id="sqlite.ddr.null.405899403" name="sqlite.ddr"/>
+       </storageModule>
+       <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+       <storageModule moduleId="scannerConfiguration">
+               <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+               <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1509404546;cdt.managedbuild.toolchain.gnu.base.1509404546.1448224696;cdt.managedbuild.tool.gnu.c.compiler.base.1303745534;cdt.managedbuild.tool.gnu.c.compiler.input.1810665783">
+                       <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+               </scannerConfigBuildInfo>
+               <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1509404546;cdt.managedbuild.toolchain.gnu.base.1509404546.1448224696;cdt.managedbuild.tool.gnu.cpp.compiler.base.1331044278;cdt.managedbuild.tool.gnu.cpp.compiler.input.2034524751">
+                       <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+               </scannerConfigBuildInfo>
+       </storageModule>
+</cproject>
diff --git a/src/db/dbdrv/sqlite/.project b/src/db/dbdrv/sqlite/.project
new file mode 100644 (file)
index 0000000..c4f963f
--- /dev/null
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>sqlite.ddr</name>
+       <comment></comment>
+       <projects>
+               <project>libnetxms</project>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+                       <triggers>clean,full,incremental,</triggers>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+                       <triggers>full,incremental,</triggers>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.cdt.core.cnature</nature>
+               <nature>org.eclipse.cdt.core.ccnature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+       </natures>
+       <filteredResources>
+               <filter>
+                       <id>1449312651349</id>
+                       <name></name>
+                       <type>6</type>
+                       <matcher>
+                               <id>org.eclipse.ui.ide.multiFilter</id>
+                               <arguments>1.0-name-matches-false-false-*.o</arguments>
+                       </matcher>
+               </filter>
+               <filter>
+                       <id>1449312651353</id>
+                       <name></name>
+                       <type>6</type>
+                       <matcher>
+                               <id>org.eclipse.ui.ide.multiFilter</id>
+                               <arguments>1.0-name-matches-false-false-*.lo</arguments>
+                       </matcher>
+               </filter>
+               <filter>
+                       <id>1449312651356</id>
+                       <name></name>
+                       <type>6</type>
+                       <matcher>
+                               <id>org.eclipse.ui.ide.multiFilter</id>
+                               <arguments>1.0-name-matches-false-false-*.la</arguments>
+                       </matcher>
+               </filter>
+       </filteredResources>
+</projectDescription>
diff --git a/src/db/dbdrv/sqlite/.settings/language.settings.xml b/src/db/dbdrv/sqlite/.settings/language.settings.xml
new file mode 100644 (file)
index 0000000..ec85e5e
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project>
+       <configuration id="cdt.managedbuild.toolchain.gnu.base.1509404546" name="Default">
+               <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
+                       <provider class="org.eclipse.cdt.core.language.settings.providers.LanguageSettingsGenericProvider" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider" name="CDT User Setting Entries" prefer-non-shared="true"/>
+                       <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
+                       <provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
+                       <provider-reference id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" ref="shared-provider"/>
+                       <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
+               </extension>
+       </configuration>
+</project>
index fb80159..63eaf0e 100644 (file)
@@ -586,11 +586,11 @@ extern "C" const char EXPORT *DrvGetColumnName(SQLITE_RESULT *hResult, int colum
 }
 
 /**
- * Perform asynchronous SELECT query
+ * Perform unbuffered SELECT query
  */
-extern "C" DBDRV_ASYNC_RESULT EXPORT DrvAsyncSelect(SQLITE_CONN *hConn, WCHAR *pwszQuery, DWORD *pdwError, WCHAR *errorText)
+extern "C" DBDRV_UNBUFFERED_RESULT EXPORT DrvSelectUnbuffered(SQLITE_CONN *hConn, WCHAR *pwszQuery, DWORD *pdwError, WCHAR *errorText)
 {
-   DBDRV_ASYNC_RESULT hResult;
+   DBDRV_UNBUFFERED_RESULT hResult;
    char *pszQueryUTF8;
 
    pszQueryUTF8 = UTF8StringFromWideString(pwszQuery);
@@ -622,7 +622,7 @@ retry:
 /**
  * Fetch next result line from asynchronous SELECT results
  */
-extern "C" bool EXPORT DrvFetch(DBDRV_ASYNC_RESULT hResult)
+extern "C" bool EXPORT DrvFetch(DBDRV_UNBUFFERED_RESULT hResult)
 {
        if (hResult == NULL)
                return false;
@@ -645,9 +645,9 @@ retry:
 }
 
 /**
- * Get field length from async query result
+ * Get field length from unbuffered query result
  */
-extern "C" LONG EXPORT DrvGetFieldLengthAsync(DBDRV_RESULT hResult, int iColumn)
+extern "C" LONG EXPORT DrvGetFieldLengthUnbuffered(DBDRV_UNBUFFERED_RESULT hResult, int iColumn)
 {
    if ((iColumn >= 0) && (iColumn < ((SQLITE_CONN *)hResult)->nNumCols))
       return (LONG)strlen((char *)sqlite3_column_text(((SQLITE_CONN *)hResult)->pvm, iColumn));
@@ -655,9 +655,9 @@ extern "C" LONG EXPORT DrvGetFieldLengthAsync(DBDRV_RESULT hResult, int iColumn)
 }
 
 /**
- * Get field from current row in async query result
+ * Get field from current row in unbuffered query result
  */
-extern "C" WCHAR EXPORT *DrvGetFieldAsync(DBDRV_ASYNC_RESULT hResult, int iColumn, WCHAR *pBuffer, int iBufSize)
+extern "C" WCHAR EXPORT *DrvGetFieldUnbuffered(DBDRV_UNBUFFERED_RESULT hResult, int iColumn, WCHAR *pBuffer, int iBufSize)
 {
    char *pszData;
    WCHAR *pwszRet = NULL;
@@ -678,7 +678,7 @@ extern "C" WCHAR EXPORT *DrvGetFieldAsync(DBDRV_ASYNC_RESULT hResult, int iColum
 /**
  * Get column count in async query result
  */
-extern "C" int EXPORT DrvGetColumnCountAsync(DBDRV_ASYNC_RESULT hResult)
+extern "C" int EXPORT DrvGetColumnCountUnbuffered(DBDRV_UNBUFFERED_RESULT hResult)
 {
        return (hResult != NULL) ? ((SQLITE_CONN *)hResult)->nNumCols : 0;
 }
@@ -686,7 +686,7 @@ extern "C" int EXPORT DrvGetColumnCountAsync(DBDRV_ASYNC_RESULT hResult)
 /**
  * Get column name in async query result
  */
-extern "C" const char EXPORT *DrvGetColumnNameAsync(DBDRV_ASYNC_RESULT hResult, int column)
+extern "C" const char EXPORT *DrvGetColumnNameUnbuffered(DBDRV_UNBUFFERED_RESULT hResult, int column)
 {
    const char *pszRet = NULL;
 
@@ -700,7 +700,7 @@ extern "C" const char EXPORT *DrvGetColumnNameAsync(DBDRV_ASYNC_RESULT hResult,
 /**
  * Destroy result of async query
  */
-extern "C" void EXPORT DrvFreeAsyncResult(DBDRV_ASYNC_RESULT hResult)
+extern "C" void EXPORT DrvFreeUnbufferedResult(DBDRV_UNBUFFERED_RESULT hResult)
 {
    if (hResult != NULL)
    {
index 16960d4..eb7a2c3 100644 (file)
@@ -196,21 +196,22 @@ DB_DRIVER LIBNXDB_EXPORTABLE DBLoadDriver(const TCHAR *module, const TCHAR *init
        driver->m_fpDrvExecute = (DWORD (*)(DBDRV_CONNECTION, DBDRV_STATEMENT, WCHAR *))DLGetSymbolAddrEx(driver->m_handle, "DrvExecute");
    driver->m_fpDrvQuery = (DWORD (*)(DBDRV_CONNECTION, const WCHAR *, WCHAR *))DLGetSymbolAddrEx(driver->m_handle, "DrvQuery");
    driver->m_fpDrvSelect = (DBDRV_RESULT (*)(DBDRV_CONNECTION, const WCHAR *, DWORD *, WCHAR *))DLGetSymbolAddrEx(driver->m_handle, "DrvSelect");
-   driver->m_fpDrvAsyncSelect = (DBDRV_ASYNC_RESULT (*)(DBDRV_CONNECTION, const WCHAR *, DWORD *, WCHAR *))DLGetSymbolAddrEx(driver->m_handle, "DrvAsyncSelect");
+   driver->m_fpDrvSelectUnbuffered = (DBDRV_UNBUFFERED_RESULT (*)(DBDRV_CONNECTION, const WCHAR *, DWORD *, WCHAR *))DLGetSymbolAddrEx(driver->m_handle, "DrvSelectUnbuffered");
        driver->m_fpDrvSelectPrepared = (DBDRV_RESULT (*)(DBDRV_CONNECTION, DBDRV_STATEMENT, DWORD *, WCHAR *))DLGetSymbolAddrEx(driver->m_handle, "DrvSelectPrepared");
-   driver->m_fpDrvFetch = (bool (*)(DBDRV_ASYNC_RESULT))DLGetSymbolAddrEx(driver->m_handle, "DrvFetch");
+   driver->m_fpDrvSelectPreparedUnbuffered = (DBDRV_UNBUFFERED_RESULT (*)(DBDRV_CONNECTION, DBDRV_STATEMENT, DWORD *, WCHAR *))DLGetSymbolAddrEx(driver->m_handle, "DrvSelectPreparedUnbuffered");
+   driver->m_fpDrvFetch = (bool (*)(DBDRV_UNBUFFERED_RESULT))DLGetSymbolAddrEx(driver->m_handle, "DrvFetch");
    driver->m_fpDrvGetFieldLength = (LONG (*)(DBDRV_RESULT, int, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetFieldLength");
-   driver->m_fpDrvGetFieldLengthAsync = (LONG (*)(DBDRV_RESULT, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetFieldLengthAsync");
+   driver->m_fpDrvGetFieldLengthUnbuffered = (LONG (*)(DBDRV_UNBUFFERED_RESULT, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetFieldLengthUnbuffered");
    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_fpDrvGetFieldAsync = (WCHAR* (*)(DBDRV_ASYNC_RESULT, int, WCHAR *, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetFieldAsync");
+   driver->m_fpDrvGetFieldUnbuffered = (WCHAR* (*)(DBDRV_UNBUFFERED_RESULT, int, WCHAR *, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetFieldUnbuffered");
    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");
-   driver->m_fpDrvGetColumnCountAsync = (int (*)(DBDRV_ASYNC_RESULT))DLGetSymbolAddrEx(driver->m_handle, "DrvGetColumnCountAsync");
-   driver->m_fpDrvGetColumnNameAsync = (const char* (*)(DBDRV_ASYNC_RESULT, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetColumnNameAsync");
+   driver->m_fpDrvGetColumnCountUnbuffered = (int (*)(DBDRV_UNBUFFERED_RESULT))DLGetSymbolAddrEx(driver->m_handle, "DrvGetColumnCountUnbuffered");
+   driver->m_fpDrvGetColumnNameUnbuffered = (const char* (*)(DBDRV_UNBUFFERED_RESULT, int))DLGetSymbolAddrEx(driver->m_handle, "DrvGetColumnNameUnbuffered");
    driver->m_fpDrvFreeResult = (void (*)(DBDRV_RESULT))DLGetSymbolAddrEx(driver->m_handle, "DrvFreeResult");
-   driver->m_fpDrvFreeAsyncResult = (void (*)(DBDRV_ASYNC_RESULT))DLGetSymbolAddrEx(driver->m_handle, "DrvFreeAsyncResult");
+   driver->m_fpDrvFreeUnbufferedResult = (void (*)(DBDRV_UNBUFFERED_RESULT))DLGetSymbolAddrEx(driver->m_handle, "DrvFreeUnbufferedResult");
    driver->m_fpDrvBegin = (DWORD (*)(DBDRV_CONNECTION))DLGetSymbolAddrEx(driver->m_handle, "DrvBegin");
    driver->m_fpDrvCommit = (DWORD (*)(DBDRV_CONNECTION))DLGetSymbolAddrEx(driver->m_handle, "DrvCommit");
    driver->m_fpDrvRollback = (DWORD (*)(DBDRV_CONNECTION))DLGetSymbolAddrEx(driver->m_handle, "DrvRollback");
@@ -222,12 +223,13 @@ DB_DRIVER LIBNXDB_EXPORTABLE DBLoadDriver(const TCHAR *module, const TCHAR *init
            (driver->m_fpDrvPrepare == NULL) || (driver->m_fpDrvBind == NULL) || (driver->m_fpDrvFreeStatement == NULL) ||
        (driver->m_fpDrvQuery == NULL) || (driver->m_fpDrvSelect == NULL) || (driver->m_fpDrvGetField == NULL) ||
        (driver->m_fpDrvGetNumRows == NULL) || (driver->m_fpDrvFreeResult == NULL) || (driver->m_fpDrvSelectPrepared == NULL) ||
-       (driver->m_fpDrvUnload == NULL) || (driver->m_fpDrvAsyncSelect == NULL) || (driver->m_fpDrvFetch == NULL) ||
-       (driver->m_fpDrvFreeAsyncResult == NULL) || (driver->m_fpDrvGetFieldAsync == NULL) ||
+       (driver->m_fpDrvSelectPreparedUnbuffered == NULL) || (driver->m_fpDrvUnload == NULL) ||
+       (driver->m_fpDrvSelectUnbuffered == NULL) || (driver->m_fpDrvFetch == NULL) ||
+       (driver->m_fpDrvFreeUnbufferedResult == NULL) || (driver->m_fpDrvGetFieldUnbuffered == NULL) ||
        (driver->m_fpDrvBegin == NULL) || (driver->m_fpDrvCommit == NULL) || (driver->m_fpDrvRollback == NULL) ||
                 (driver->m_fpDrvGetColumnCount == NULL) || (driver->m_fpDrvGetColumnName == NULL) ||
-                (driver->m_fpDrvGetColumnCountAsync == NULL) || (driver->m_fpDrvGetColumnNameAsync == NULL) ||
-       (driver->m_fpDrvGetFieldLength == NULL) || (driver->m_fpDrvGetFieldLengthAsync == NULL) ||
+                (driver->m_fpDrvGetColumnCountUnbuffered == NULL) || (driver->m_fpDrvGetColumnNameUnbuffered == NULL) ||
+       (driver->m_fpDrvGetFieldLength == NULL) || (driver->m_fpDrvGetFieldLengthUnbuffered == NULL) ||
                 (driver->m_fpDrvPrepareStringA == NULL) || (driver->m_fpDrvPrepareStringW == NULL) || (driver->m_fpDrvIsTableExist == NULL))
    {
       if (s_writeLog)
index 1fe2f3b..3845f50 100644 (file)
@@ -58,17 +58,18 @@ struct db_driver_t
        DWORD (* m_fpDrvExecute)(DBDRV_CONNECTION, DBDRV_STATEMENT, WCHAR *);
        DWORD (* m_fpDrvQuery)(DBDRV_CONNECTION, const WCHAR *, WCHAR *);
        DBDRV_RESULT (* m_fpDrvSelect)(DBDRV_CONNECTION, const WCHAR *, DWORD *, WCHAR *);
-       DBDRV_ASYNC_RESULT (* m_fpDrvAsyncSelect)(DBDRV_CONNECTION, const WCHAR *, DWORD *, WCHAR *);
+       DBDRV_UNBUFFERED_RESULT (* m_fpDrvSelectUnbuffered)(DBDRV_CONNECTION, const WCHAR *, DWORD *, WCHAR *);
        DBDRV_RESULT (* m_fpDrvSelectPrepared)(DBDRV_CONNECTION, DBDRV_STATEMENT, DWORD *, WCHAR *);
-       bool (* m_fpDrvFetch)(DBDRV_ASYNC_RESULT);
+   DBDRV_UNBUFFERED_RESULT (* m_fpDrvSelectPreparedUnbuffered)(DBDRV_CONNECTION, DBDRV_STATEMENT, DWORD *, WCHAR *);
+       bool (* m_fpDrvFetch)(DBDRV_UNBUFFERED_RESULT);
        LONG (* m_fpDrvGetFieldLength)(DBDRV_RESULT, int, int);
-       LONG (* m_fpDrvGetFieldLengthAsync)(DBDRV_RESULT, int);
+       LONG (* m_fpDrvGetFieldLengthUnbuffered)(DBDRV_UNBUFFERED_RESULT, int);
        WCHAR* (* m_fpDrvGetField)(DBDRV_RESULT, int, int, WCHAR *, int);
        char* (* m_fpDrvGetFieldUTF8)(DBDRV_RESULT, int, int, char *, int);
-       WCHAR* (* m_fpDrvGetFieldAsync)(DBDRV_ASYNC_RESULT, int, WCHAR *, int);
+       WCHAR* (* m_fpDrvGetFieldUnbuffered)(DBDRV_UNBUFFERED_RESULT, int, WCHAR *, int);
        int (* m_fpDrvGetNumRows)(DBDRV_RESULT);
        void (* m_fpDrvFreeResult)(DBDRV_RESULT);
-       void (* m_fpDrvFreeAsyncResult)(DBDRV_ASYNC_RESULT);
+       void (* m_fpDrvFreeUnbufferedResult)(DBDRV_UNBUFFERED_RESULT);
        DWORD (* m_fpDrvBegin)(DBDRV_CONNECTION);
        DWORD (* m_fpDrvCommit)(DBDRV_CONNECTION);
        DWORD (* m_fpDrvRollback)(DBDRV_CONNECTION);
@@ -76,8 +77,8 @@ struct db_driver_t
        void (* m_fpEventHandler)(DWORD, const WCHAR *, const WCHAR *, bool, void *);
        int (* m_fpDrvGetColumnCount)(DBDRV_RESULT);
        const char* (* m_fpDrvGetColumnName)(DBDRV_RESULT, int);
-       int (* m_fpDrvGetColumnCountAsync)(DBDRV_ASYNC_RESULT);
-       const char* (* m_fpDrvGetColumnNameAsync)(DBDRV_ASYNC_RESULT, int);
+       int (* m_fpDrvGetColumnCountUnbuffered)(DBDRV_UNBUFFERED_RESULT);
+       const char* (* m_fpDrvGetColumnNameUnbuffered)(DBDRV_UNBUFFERED_RESULT, int);
        WCHAR* (* m_fpDrvPrepareStringW)(const WCHAR *);
        char* (* m_fpDrvPrepareStringA)(const char *);
        int (* m_fpDrvIsTableExist)(DBDRV_CONNECTION, const WCHAR *);
@@ -124,31 +125,26 @@ struct db_result_t
 };
 
 /**
- * Async SELECT query result
+ * Unbuffered SELECT query result
  */
-struct db_async_result_t
+struct db_unbuffered_result_t
 {
        DB_DRIVER m_driver;
        DB_HANDLE m_connection;
-       DBDRV_ASYNC_RESULT m_data;
+       DBDRV_UNBUFFERED_RESULT m_data;
 };
 
-
-//
-// Internal functions
-//
-
+/**
+ * Internal functions
+ */
 void __DBWriteLog(WORD level, const TCHAR *format, ...);
 void __DBDbgPrintf(int level, const TCHAR *format, ...);
 
-
-//
-// Global variables
-//
-
+/**
+ * Global variables
+ */
 extern UINT32 g_logMsgCode;
 extern UINT32 g_sqlErrorMsgCode;
 extern UINT32 g_sqlQueryExecTimeThreshold;
 
-
 #endif   /* _libnxsrv_h_ */
index 2c95d3a..2b6141a 100644 (file)
@@ -412,21 +412,21 @@ bool LIBNXDB_EXPORTABLE DBGetColumnName(DB_RESULT hResult, int column, TCHAR *bu
 }
 
 /**
- * Get column count for async request
+ * Get column count for unbuffered result set
  */
-int LIBNXDB_EXPORTABLE DBGetColumnCountAsync(DB_ASYNC_RESULT hResult)
+int LIBNXDB_EXPORTABLE DBGetColumnCount(DB_UNBUFFERED_RESULT hResult)
 {
-       return hResult->m_driver->m_fpDrvGetColumnCountAsync(hResult->m_data);
+       return hResult->m_driver->m_fpDrvGetColumnCountUnbuffered(hResult->m_data);
 }
 
 /**
- * Get column name for async request
+ * Get column name for unbuffered result set
  */
-bool LIBNXDB_EXPORTABLE DBGetColumnNameAsync(DB_ASYNC_RESULT hResult, int column, TCHAR *buffer, int bufSize)
+bool LIBNXDB_EXPORTABLE DBGetColumnName(DB_UNBUFFERED_RESULT hResult, int column, TCHAR *buffer, int bufSize)
 {
        const char *name;
 
-       name = hResult->m_driver->m_fpDrvGetColumnNameAsync(hResult->m_data, column);
+       name = hResult->m_driver->m_fpDrvGetColumnNameUnbuffered(hResult->m_data, column);
        if (name != NULL)
        {
 #ifdef UNICODE
@@ -775,12 +775,12 @@ void LIBNXDB_EXPORTABLE DBFreeResult(DB_RESULT hResult)
 }
 
 /**
- * Asyncronous SELECT query
+ * Unbuffered SELECT query
  */
-DB_ASYNC_RESULT LIBNXDB_EXPORTABLE DBAsyncSelectEx(DB_HANDLE hConn, const TCHAR *szQuery, TCHAR *errorText)
+DB_UNBUFFERED_RESULT LIBNXDB_EXPORTABLE DBSelectUnbufferedEx(DB_HANDLE hConn, const TCHAR *szQuery, TCHAR *errorText)
 {
-   DBDRV_ASYNC_RESULT hResult;
-       DB_ASYNC_RESULT result = NULL;
+   DBDRV_UNBUFFERED_RESULT hResult;
+       DB_UNBUFFERED_RESULT result = NULL;
    DWORD dwError = DBERR_OTHER_ERROR;
 #ifdef UNICODE
 #define pwszQuery szQuery
@@ -796,17 +796,17 @@ DB_ASYNC_RESULT LIBNXDB_EXPORTABLE DBAsyncSelectEx(DB_HANDLE hConn, const TCHAR
    s_perfSelectQueries++;
    s_perfTotalQueries++;
 
-   hResult = hConn->m_driver->m_fpDrvAsyncSelect(hConn->m_connection, pwszQuery, &dwError, wcErrorText);
+   hResult = hConn->m_driver->m_fpDrvSelectUnbuffered(hConn->m_connection, pwszQuery, &dwError, wcErrorText);
    if ((hResult == NULL) && (dwError == DBERR_CONNECTION_LOST) && hConn->m_reconnectEnabled)
    {
       DBReconnect(hConn);
-      hResult = hConn->m_driver->m_fpDrvAsyncSelect(hConn->m_connection, pwszQuery, &dwError, wcErrorText);
+      hResult = hConn->m_driver->m_fpDrvSelectUnbuffered(hConn->m_connection, pwszQuery, &dwError, wcErrorText);
    }
 
    ms = GetCurrentTimeMs() - ms;
    if (hConn->m_driver->m_dumpSql)
    {
-      __DBDbgPrintf(9, _T("%s async query: \"%s\" [%d ms]"), (hResult != NULL) ? _T("Successful") : _T("Failed"), szQuery, (int)ms);
+      __DBDbgPrintf(9, _T("%s unbuffered query: \"%s\" [%d ms]"), (hResult != NULL) ? _T("Successful") : _T("Failed"), szQuery, (int)ms);
    }
    if ((hResult != NULL) && ((UINT32)ms > g_sqlQueryExecTimeThreshold))
    {
@@ -835,7 +835,7 @@ DB_ASYNC_RESULT LIBNXDB_EXPORTABLE DBAsyncSelectEx(DB_HANDLE hConn, const TCHAR
    
        if (hResult != NULL)
        {
-               result = (DB_ASYNC_RESULT)malloc(sizeof(db_async_result_t));
+               result = (DB_UNBUFFERED_RESULT)malloc(sizeof(db_unbuffered_result_t));
                result->m_driver = hConn->m_driver;
                result->m_connection = hConn;
                result->m_data = hResult;
@@ -846,37 +846,37 @@ DB_ASYNC_RESULT LIBNXDB_EXPORTABLE DBAsyncSelectEx(DB_HANDLE hConn, const TCHAR
 #undef wcErrorText
 }
 
-DB_ASYNC_RESULT LIBNXDB_EXPORTABLE DBAsyncSelect(DB_HANDLE hConn, const TCHAR *query)
+DB_UNBUFFERED_RESULT LIBNXDB_EXPORTABLE DBSelectUnbuffered(DB_HANDLE hConn, const TCHAR *query)
 {
    TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
 
-       return DBAsyncSelectEx(hConn, query, errorText);
+       return DBSelectUnbufferedEx(hConn, query, errorText);
 }
 
 /**
- * Fetch next row from asynchronous SELECT result
+ * Fetch next row from unbuffered SELECT result
  */
-bool LIBNXDB_EXPORTABLE DBFetch(DB_ASYNC_RESULT hResult)
+bool LIBNXDB_EXPORTABLE DBFetch(DB_UNBUFFERED_RESULT hResult)
 {
        return hResult->m_driver->m_fpDrvFetch(hResult->m_data);
 }
 
 /**
- * Get field's value from asynchronous SELECT result
+ * Get field's value from unbuffered SELECT result
  */
-TCHAR LIBNXDB_EXPORTABLE *DBGetFieldAsync(DB_ASYNC_RESULT hResult, int iColumn, TCHAR *pBuffer, int iBufSize)
+TCHAR LIBNXDB_EXPORTABLE *DBGetField(DB_UNBUFFERED_RESULT hResult, int iColumn, TCHAR *pBuffer, int iBufSize)
 {
 #ifdef UNICODE
    if (pBuffer != NULL)
    {
-          return hResult->m_driver->m_fpDrvGetFieldAsync(hResult->m_data, iColumn, pBuffer, iBufSize);
+          return hResult->m_driver->m_fpDrvGetFieldUnbuffered(hResult->m_data, iColumn, pBuffer, iBufSize);
    }
    else
    {
       INT32 nLen;
       WCHAR *pszTemp;
 
-      nLen = hResult->m_driver->m_fpDrvGetFieldLengthAsync(hResult->m_data, iColumn);
+      nLen = hResult->m_driver->m_fpDrvGetFieldLengthUnbuffered(hResult->m_data, iColumn);
       if (nLen == -1)
       {
          pszTemp = NULL;
@@ -885,7 +885,7 @@ TCHAR LIBNXDB_EXPORTABLE *DBGetFieldAsync(DB_ASYNC_RESULT hResult, int iColumn,
       {
          nLen++;
          pszTemp = (WCHAR *)malloc(nLen * sizeof(WCHAR));
-         hResult->m_driver->m_fpDrvGetFieldAsync(hResult->m_data, iColumn, pszTemp, nLen);
+         hResult->m_driver->m_fpDrvGetFieldUnbuffered(hResult->m_data, iColumn, pszTemp, nLen);
       }
       return pszTemp;
    }
@@ -897,7 +897,7 @@ TCHAR LIBNXDB_EXPORTABLE *DBGetFieldAsync(DB_ASYNC_RESULT hResult, int iColumn,
    if (pBuffer != NULL)
    {
                pwszBuffer = (WCHAR *)malloc(iBufSize * sizeof(WCHAR));
-               if (hResult->m_driver->m_fpDrvGetFieldAsync(hResult->m_data, iColumn, pwszBuffer, iBufSize) != NULL)
+               if (hResult->m_driver->m_fpDrvGetFieldUnbuffered(hResult->m_data, iColumn, pwszBuffer, iBufSize) != NULL)
                {
                        WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
                                                                          pwszBuffer, -1, pBuffer, iBufSize, NULL, NULL);
@@ -911,7 +911,7 @@ TCHAR LIBNXDB_EXPORTABLE *DBGetFieldAsync(DB_ASYNC_RESULT hResult, int iColumn,
    }
    else
    {
-               nLen = hResult->m_driver->m_fpDrvGetFieldLengthAsync(hResult->m_data, iColumn);
+               nLen = hResult->m_driver->m_fpDrvGetFieldLengthUnbuffered(hResult->m_data, iColumn);
       if (nLen == -1)
       {
          pszRet = NULL;
@@ -920,7 +920,7 @@ TCHAR LIBNXDB_EXPORTABLE *DBGetFieldAsync(DB_ASYNC_RESULT hResult, int iColumn,
       {
          nLen++;
          pwszBuffer = (WCHAR *)malloc(nLen * sizeof(WCHAR));
-                       pwszData = hResult->m_driver->m_fpDrvGetFieldAsync(hResult->m_data, iColumn, pwszBuffer, nLen);
+                       pwszData = hResult->m_driver->m_fpDrvGetFieldUnbuffered(hResult->m_data, iColumn, pwszBuffer, nLen);
          if (pwszData != NULL)
          {
             nLen = (int)wcslen(pwszData) + 1;
@@ -940,15 +940,15 @@ TCHAR LIBNXDB_EXPORTABLE *DBGetFieldAsync(DB_ASYNC_RESULT hResult, int iColumn,
 }
 
 /**
- * Get field's value as unsigned long from asynchronous SELECT result
+ * Get field's value as unsigned long from unbuffered SELECT result
  */
-UINT32 LIBNXDB_EXPORTABLE DBGetFieldAsyncULong(DB_ASYNC_RESULT hResult, int iColumn)
+UINT32 LIBNXDB_EXPORTABLE DBGetFieldULong(DB_UNBUFFERED_RESULT hResult, int iColumn)
 {
    INT32 iVal;
    UINT32 dwVal;
    TCHAR szBuffer[64];
 
-   if (DBGetFieldAsync(hResult, iColumn, szBuffer, 64) == NULL)
+   if (DBGetField(hResult, iColumn, szBuffer, 64) == NULL)
       return 0;
        StrStrip(szBuffer);
        if (szBuffer[0] == _T('-'))
@@ -964,15 +964,15 @@ UINT32 LIBNXDB_EXPORTABLE DBGetFieldAsyncULong(DB_ASYNC_RESULT hResult, int iCol
 }
 
 /**
- * Get field's value as unsigned 64-bit int from asynchronous SELECT result
+ * Get field's value as unsigned 64-bit int from unbuffered SELECT result
  */
-UINT64 LIBNXDB_EXPORTABLE DBGetFieldAsyncUInt64(DB_ASYNC_RESULT hResult, int iColumn)
+UINT64 LIBNXDB_EXPORTABLE DBGetFieldUInt64(DB_UNBUFFERED_RESULT hResult, int iColumn)
 {
    INT64 iVal;
    UINT64 qwVal;
    TCHAR szBuffer[64];
 
-   if (DBGetFieldAsync(hResult, iColumn, szBuffer, 64) == NULL)
+   if (DBGetField(hResult, iColumn, szBuffer, 64) == NULL)
       return 0;
        StrStrip(szBuffer);
        if (szBuffer[0] == _T('-'))
@@ -988,61 +988,65 @@ UINT64 LIBNXDB_EXPORTABLE DBGetFieldAsyncUInt64(DB_ASYNC_RESULT hResult, int iCo
 }
 
 /**
- * Get field's value as signed long from asynchronous SELECT result
+ * Get field's value as signed long from unbuffered SELECT result
  */
-INT32 LIBNXDB_EXPORTABLE DBGetFieldAsyncLong(DB_ASYNC_RESULT hResult, int iColumn)
+INT32 LIBNXDB_EXPORTABLE DBGetFieldLong(DB_UNBUFFERED_RESULT hResult, int iColumn)
 {
    TCHAR szBuffer[64];
-   
-   return DBGetFieldAsync(hResult, iColumn, szBuffer, 64) == NULL ? 0 : _tcstol(szBuffer, NULL, 10);
+   return DBGetField(hResult, iColumn, szBuffer, 64) == NULL ? 0 : _tcstol(szBuffer, NULL, 10);
 }
 
 /**
- * Get field's value as signed 64-bit int from asynchronous SELECT result
+ * Get field's value as signed 64-bit int from unbuffered SELECT result
  */
-INT64 LIBNXDB_EXPORTABLE DBGetFieldAsyncInt64(DB_ASYNC_RESULT hResult, int iColumn)
+INT64 LIBNXDB_EXPORTABLE DBGetFieldInt64(DB_UNBUFFERED_RESULT hResult, int iColumn)
 {
    TCHAR szBuffer[64];
-   
-   return DBGetFieldAsync(hResult, iColumn, szBuffer, 64) == NULL ? 0 : _tcstoll(szBuffer, NULL, 10);
+   return DBGetField(hResult, iColumn, szBuffer, 64) == NULL ? 0 : _tcstoll(szBuffer, NULL, 10);
 }
 
 /**
- * Get field's value as signed long from asynchronous SELECT result
+ * Get field's value as signed long from unbuffered SELECT result
  */
-double LIBNXDB_EXPORTABLE DBGetFieldAsyncDouble(DB_ASYNC_RESULT hResult, int iColumn)
+double LIBNXDB_EXPORTABLE DBGetFieldDouble(DB_UNBUFFERED_RESULT hResult, int iColumn)
 {
    TCHAR szBuffer[64];
-   
-   return DBGetFieldAsync(hResult, iColumn, szBuffer, 64) == NULL ? 0 : _tcstod(szBuffer, NULL);
+   return DBGetField(hResult, iColumn, szBuffer, 64) == NULL ? 0 : _tcstod(szBuffer, NULL);
 }
 
 /**
- * Get field's value as IPv4 address from asynchronous SELECT result
+ * Get field's value as IPv4 address from unbuffered SELECT result
  */
-UINT32 LIBNXDB_EXPORTABLE DBGetFieldAsyncIPAddr(DB_ASYNC_RESULT hResult, int iColumn)
+UINT32 LIBNXDB_EXPORTABLE DBGetFieldIPAddr(DB_UNBUFFERED_RESULT hResult, int iColumn)
 {
-   TCHAR szBuffer[64];
-   
-   return (DBGetFieldAsync(hResult, iColumn, szBuffer, 64) == NULL) ? INADDR_NONE : ntohl(_t_inet_addr(szBuffer));
+   TCHAR buffer[64];
+   return (DBGetField(hResult, iColumn, buffer, 64) == NULL) ? INADDR_NONE : ntohl(_t_inet_addr(buffer));
 }
 
 /**
- * Get field's value as IP address from asynchronous SELECT result
+ * Get field's value as IP address from unbuffered SELECT result
  */
-InetAddress LIBNXDB_EXPORTABLE DBGetFieldAsyncInetAddr(DB_ASYNC_RESULT hResult, int iColumn)
+InetAddress LIBNXDB_EXPORTABLE DBGetFieldInetAddr(DB_UNBUFFERED_RESULT hResult, int iColumn)
 {
-   TCHAR szBuffer[64];
-   
-   return (DBGetFieldAsync(hResult, iColumn, szBuffer, 64) == NULL) ? InetAddress() : InetAddress::parse(szBuffer);
+   TCHAR buffer[64];
+   return (DBGetField(hResult, iColumn, buffer, 64) == NULL) ? InetAddress() : InetAddress::parse(buffer);
 }
 
 /**
- * Free asynchronous SELECT result
+ * Get field's value as GUID from unbuffered SELECT result
  */
-void LIBNXDB_EXPORTABLE DBFreeAsyncResult(DB_ASYNC_RESULT hResult)
+uuid LIBNXDB_EXPORTABLE DBGetFieldGUID(DB_UNBUFFERED_RESULT hResult, int iColumn)
 {
-       hResult->m_driver->m_fpDrvFreeAsyncResult(hResult->m_data);
+   TCHAR buffer[64];
+   return (DBGetField(hResult, iColumn, buffer, 64) == NULL) ? uuid::NULL_UUID : uuid::parse(buffer);
+}
+
+/**
+ * Free unbuffered SELECT result
+ */
+void LIBNXDB_EXPORTABLE DBFreeResult(DB_UNBUFFERED_RESULT hResult)
+{
+       hResult->m_driver->m_fpDrvFreeUnbufferedResult(hResult->m_data);
        MutexUnlock(hResult->m_connection->m_mutexTransLock);
        free(hResult);
 }
@@ -1503,6 +1507,98 @@ DB_RESULT LIBNXDB_EXPORTABLE DBSelectPrepared(DB_STATEMENT hStmt)
        return DBSelectPreparedEx(hStmt, errorText);
 }
 
+/**
+ * Execute prepared SELECT statement without caching results
+ */
+DB_UNBUFFERED_RESULT LIBNXDB_EXPORTABLE DBSelectPreparedUnbufferedEx(DB_STATEMENT hStmt, TCHAR *errorText)
+{
+   if (!IS_VALID_STATEMENT_HANDLE(hStmt))
+   {
+      _tcscpy(errorText, _T("Invalid statement handle"));
+      return NULL;
+   }
+
+   DB_UNBUFFERED_RESULT result = NULL;
+#ifdef UNICODE
+#define wcErrorText errorText
+#else
+   WCHAR wcErrorText[DBDRV_MAX_ERROR_TEXT] = L"";
+#endif
+
+   DB_HANDLE hConn = hStmt->m_connection;
+   MutexLock(hConn->m_mutexTransLock);
+
+   s_perfSelectQueries++;
+   s_perfTotalQueries++;
+
+   INT64 ms = GetCurrentTimeMs();
+   DWORD dwError = DBERR_OTHER_ERROR;
+   DBDRV_UNBUFFERED_RESULT hResult = hConn->m_driver->m_fpDrvSelectPreparedUnbuffered(hConn->m_connection, hStmt->m_statement, &dwError, wcErrorText);
+
+   ms = GetCurrentTimeMs() - ms;
+   if (hConn->m_driver->m_dumpSql)
+   {
+      __DBDbgPrintf(9, _T("%s prepared sync query: \"%s\" [%d ms]"),
+                    (hResult != NULL) ? _T("Successful") : _T("Failed"), hStmt->m_query, (int)ms);
+   }
+   if ((hResult != NULL) && ((UINT32)ms > g_sqlQueryExecTimeThreshold))
+   {
+      __DBDbgPrintf(3, _T("Long running query: \"%s\" [%d ms]"), hStmt->m_query, (int)ms);
+      s_perfLongRunningQueries++;
+   }
+
+   // Do reconnect if needed, but don't retry statement execution
+   // because it will fail anyway
+   if ((hResult == NULL) && (dwError == DBERR_CONNECTION_LOST) && hConn->m_reconnectEnabled)
+   {
+      DBReconnect(hConn);
+   }
+
+#ifndef UNICODE
+   WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, wcErrorText, -1, errorText, DBDRV_MAX_ERROR_TEXT, NULL, NULL);
+   errorText[DBDRV_MAX_ERROR_TEXT - 1] = 0;
+#endif
+
+   if (hResult == NULL)
+   {
+      MutexUnlock(hConn->m_mutexTransLock);
+
+      if (hConn->m_driver->m_logSqlErrors)
+         nxlog_write(g_sqlErrorMsgCode, EVENTLOG_ERROR_TYPE, "ss", hStmt->m_query, errorText);
+      if (hConn->m_driver->m_fpEventHandler != NULL)
+      {
+#ifdef UNICODE
+         hConn->m_driver->m_fpEventHandler(DBEVENT_QUERY_FAILED, hStmt->m_query, wcErrorText, dwError == DBERR_CONNECTION_LOST, hConn->m_driver->m_userArg);
+#else
+         WCHAR *query = WideStringFromMBString(hStmt->m_query);
+         hConn->m_driver->m_fpEventHandler(DBEVENT_QUERY_FAILED, query, wcErrorText, dwError == DBERR_CONNECTION_LOST, hConn->m_driver->m_userArg);
+         free(query);
+#endif
+      }
+      s_perfFailedQueries++;
+   }
+
+   if (hResult != NULL)
+   {
+      result = (DB_UNBUFFERED_RESULT)malloc(sizeof(db_unbuffered_result_t));
+      result->m_driver = hConn->m_driver;
+      result->m_connection = hConn;
+      result->m_data = hResult;
+   }
+
+   return result;
+#undef wcErrorText
+}
+
+/**
+ * Execute prepared SELECT statement
+ */
+DB_UNBUFFERED_RESULT LIBNXDB_EXPORTABLE DBSelectPreparedUnbuffered(DB_STATEMENT hStmt)
+{
+   TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
+   return DBSelectPreparedUnbufferedEx(hStmt, errorText);
+}
+
 /**
  * Begin transaction
  */
index b31e2db..abd79db 100644 (file)
@@ -1113,7 +1113,7 @@ void DCItem::reloadCache()
    }
 
    DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-   DB_ASYNC_RESULT hResult = DBAsyncSelect(hdb, szBuffer);
+   DB_UNBUFFERED_RESULT hResult = DBSelectUnbuffered(hdb, szBuffer);
 
    lock();
 
@@ -1135,8 +1135,8 @@ void DCItem::reloadCache()
          moreData = DBFetch(hResult);
          if (moreData)
          {
-            DBGetFieldAsync(hResult, 0, szBuffer, MAX_DB_STRING);
-            m_ppValueCache[i] = new ItemValue(szBuffer, DBGetFieldAsyncULong(hResult, 1));
+            DBGetField(hResult, 0, szBuffer, MAX_DB_STRING);
+            m_ppValueCache[i] = new ItemValue(szBuffer, DBGetFieldULong(hResult, 1));
          }
          else
          {
@@ -1148,7 +1148,7 @@ void DCItem::reloadCache()
       for(; i < m_requiredCacheSize; i++)
          m_ppValueCache[i] = new ItemValue(_T(""), 1);
 
-      DBFreeAsyncResult(hResult);
+      DBFreeResult(hResult);
    }
    else
    {
index ffd41cc..9fe84d4 100644 (file)
@@ -1924,7 +1924,6 @@ void ClientSession::login(NXCPMessage *pRequest)
  */
 void ClientSession::sendEventDB(UINT32 dwRqId)
 {
-   DB_ASYNC_RESULT hResult;
    NXCPMessage msg;
    TCHAR szBuffer[4096];
 
@@ -1945,26 +1944,26 @@ void ClientSession::sendEventDB(UINT32 dwRqId)
          msg.setId(dwRqId);
 
          DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-         hResult = DBAsyncSelect(hdb, _T("SELECT event_code,event_name,severity,flags,message,description FROM event_cfg"));
+         DB_UNBUFFERED_RESULT hResult = DBSelectUnbuffered(hdb, _T("SELECT event_code,event_name,severity,flags,message,description FROM event_cfg"));
          if (hResult != NULL)
          {
             while(DBFetch(hResult))
             {
-               msg.setField(VID_EVENT_CODE, DBGetFieldAsyncULong(hResult, 0));
-               msg.setField(VID_NAME, DBGetFieldAsync(hResult, 1, szBuffer, 1024));
-               msg.setField(VID_SEVERITY, DBGetFieldAsyncULong(hResult, 2));
-               msg.setField(VID_FLAGS, DBGetFieldAsyncULong(hResult, 3));
+               msg.setField(VID_EVENT_CODE, DBGetFieldULong(hResult, 0));
+               msg.setField(VID_NAME, DBGetField(hResult, 1, szBuffer, 1024));
+               msg.setField(VID_SEVERITY, DBGetFieldULong(hResult, 2));
+               msg.setField(VID_FLAGS, DBGetFieldULong(hResult, 3));
 
-               DBGetFieldAsync(hResult, 4, szBuffer, 4096);
+               DBGetField(hResult, 4, szBuffer, 4096);
                msg.setField(VID_MESSAGE, szBuffer);
 
-               DBGetFieldAsync(hResult, 5, szBuffer, 4096);
+               DBGetField(hResult, 5, szBuffer, 4096);
                msg.setField(VID_DESCRIPTION, szBuffer);
 
                sendMessage(&msg);
                msg.deleteAllFields();
             }
-            DBFreeAsyncResult(hResult);
+            DBFreeResult(hResult);
          }
          DBConnectionPoolReleaseConnection(hdb);
 
@@ -2290,7 +2289,6 @@ void ClientSession::sendSelectedObjects(NXCPMessage *pRequest)
 void ClientSession::sendEventLog(NXCPMessage *pRequest)
 {
    NXCPMessage msg;
-   DB_ASYNC_RESULT hResult = NULL;
    DB_RESULT hTempResult;
    UINT32 dwRqId, dwMaxRecords, dwNumRows, dwId;
    TCHAR szQuery[1024], szBuffer[1024];
@@ -2351,7 +2349,7 @@ void ClientSession::sendEventLog(NXCPMessage *pRequest)
          szQuery[0] = 0;
          break;
    }
-   hResult = DBAsyncSelect(hdb, szQuery);
+   DB_UNBUFFERED_RESULT hResult = DBSelectUnbuffered(hdb, szQuery);
    if (hResult != NULL)
    {
       msg.setField(VID_RCC, RCC_SUCCESS);
@@ -2370,18 +2368,18 @@ void ClientSession::sendEventLog(NXCPMessage *pRequest)
             dwNumRows = 0;
             dwId = VID_EVENTLOG_MSG_BASE;
          }
-         msg.setField(dwId++, DBGetFieldAsyncUInt64(hResult, 0));
-         msg.setField(dwId++, DBGetFieldAsyncULong(hResult, 1));
-         msg.setField(dwId++, DBGetFieldAsyncULong(hResult, 2));
-         msg.setField(dwId++, DBGetFieldAsyncULong(hResult, 3));
-         msg.setField(dwId++, (WORD)DBGetFieldAsyncLong(hResult, 4));
-         DBGetFieldAsync(hResult, 5, szBuffer, 1024);
+         msg.setField(dwId++, DBGetFieldUInt64(hResult, 0));
+         msg.setField(dwId++, DBGetFieldULong(hResult, 1));
+         msg.setField(dwId++, DBGetFieldULong(hResult, 2));
+         msg.setField(dwId++, DBGetFieldULong(hResult, 3));
+         msg.setField(dwId++, (WORD)DBGetFieldLong(hResult, 4));
+         DBGetField(hResult, 5, szBuffer, 1024);
          msg.setField(dwId++, szBuffer);
-         DBGetFieldAsync(hResult, 6, szBuffer, 1024);
+         DBGetField(hResult, 6, szBuffer, 1024);
          msg.setField(dwId++, szBuffer);
          msg.setField(dwId++, (UINT32)0);      // Do not send parameters
       }
-      DBFreeAsyncResult(hResult);
+      DBFreeResult(hResult);
 
       // Send remaining records with End-Of-Sequence notification
       msg.setField(VID_NUM_RECORDS, dwNumRows);
@@ -4259,7 +4257,7 @@ read_from_db:
                if (timeTo != 0)
                        DBBind(hStmt, pos++, DB_SQLTYPE_INTEGER, timeTo);
 
-               DB_RESULT hResult = DBSelectPrepared(hStmt);
+               DB_UNBUFFERED_RESULT hResult = DBSelectPreparedUnbuffered(hStmt);
                if (hResult != NULL)
                {
 #if !defined(UNICODE) || defined(UNICODE_UCS4)
@@ -4272,8 +4270,6 @@ read_from_db:
                                ((DCItem *)dci)->fillMessageWithThresholds(response);
                        sendMessage(response);
 
-                       UINT32 numRows = (UINT32)DBGetNumRows(hResult);
-
                        int dataType;
                        switch(dciType)
                        {
@@ -4289,38 +4285,48 @@ read_from_db:
                        }
 
                        // Allocate memory for data and prepare data header
-                       pData = (DCI_DATA_HEADER *)malloc(numRows * s_rowSize[dataType] + sizeof(DCI_DATA_HEADER));
+                       int allocated = 8192;
+                       int rows = 0;
+                       pData = (DCI_DATA_HEADER *)malloc(allocated * s_rowSize[dataType] + sizeof(DCI_DATA_HEADER));
                        pData->dataType = htonl((UINT32)dataType);
                        pData->dciId = htonl(dci->getId());
 
                        // Fill memory block with records
                        pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER));
-                       for(UINT32 i = 0; i < numRows; i++)
+                       while(DBFetch(hResult))
                        {
-                               pCurr->timeStamp = htonl(DBGetFieldULong(hResult, i, 0));
+                          if (rows == allocated)
+                          {
+                             allocated += 8192;
+                        pData = (DCI_DATA_HEADER *)realloc(pData, allocated * s_rowSize[dataType] + sizeof(DCI_DATA_HEADER));
+                        pCurr = (DCI_DATA_ROW *)(((char *)pData + s_rowSize[dataType] * rows) + sizeof(DCI_DATA_HEADER));
+                          }
+            rows++;
+
+                               pCurr->timeStamp = htonl(DBGetFieldULong(hResult, 0));
                                switch(dataType)
                                {
                                        case DCI_DT_INT:
                                        case DCI_DT_UINT:
-                                               pCurr->value.int32 = htonl(DBGetFieldULong(hResult, i, 1));
+                                               pCurr->value.int32 = htonl(DBGetFieldULong(hResult, 1));
                                                break;
                                        case DCI_DT_INT64:
                                        case DCI_DT_UINT64:
-                                               pCurr->value.ext.v64.int64 = htonq(DBGetFieldUInt64(hResult, i, 1));
+                                               pCurr->value.ext.v64.int64 = htonq(DBGetFieldUInt64(hResult, 1));
                                                break;
                                        case DCI_DT_FLOAT:
-                                               pCurr->value.ext.v64.real = htond(DBGetFieldDouble(hResult, i, 1));
+                                               pCurr->value.ext.v64.real = htond(DBGetFieldDouble(hResult, 1));
                                                break;
                                        case DCI_DT_STRING:
 #ifdef UNICODE
 #ifdef UNICODE_UCS4
-                                               DBGetField(hResult, i, 1, szBuffer, MAX_DCI_STRING_VALUE);
+                                               DBGetField(hResult, 1, szBuffer, MAX_DCI_STRING_VALUE);
                                                ucs4_to_ucs2(szBuffer, -1, pCurr->value.string, MAX_DCI_STRING_VALUE);
 #else
-                                               DBGetField(hResult, i, 1, pCurr->value.string, MAX_DCI_STRING_VALUE);
+                                               DBGetField(hResult, 1, pCurr->value.string, MAX_DCI_STRING_VALUE);
 #endif
 #else
-                                               DBGetField(hResult, i, 1, szBuffer, MAX_DCI_STRING_VALUE);
+                                               DBGetField(hResult, 1, szBuffer, MAX_DCI_STRING_VALUE);
                                                mb_to_ucs2(szBuffer, -1, pCurr->value.string, MAX_DCI_STRING_VALUE);
 #endif
                                                SwapWideString(pCurr->value.string);
@@ -4329,12 +4335,12 @@ read_from_db:
                                pCurr = (DCI_DATA_ROW *)(((char *)pCurr) + s_rowSize[dataType]);
                        }
                        DBFreeResult(hResult);
-                       pData->numRows = htonl(numRows);
+                       pData->numRows = htonl(rows);
 
                        // Prepare and send raw message with fetched data
                        NXCP_MESSAGE *msg =
                                CreateRawNXCPMessage(CMD_DCI_DATA, request->getId(), 0,
-                                                                                       numRows * s_rowSize[dataType] + sizeof(DCI_DATA_HEADER),
+                                                                                       rows * s_rowSize[dataType] + sizeof(DCI_DATA_HEADER),
                                                                                        pData, NULL);
                        free(pData);
                        sendRawMessage(msg);
@@ -6658,7 +6664,6 @@ void ClientSession::LockPackageDB(UINT32 dwRqId, BOOL bLock)
 void ClientSession::SendAllPackages(UINT32 dwRqId)
 {
    NXCPMessage msg;
-   DB_ASYNC_RESULT hResult;
    BOOL bSuccess = FALSE;
    TCHAR szBuffer[MAX_DB_STRING];
 
@@ -6671,7 +6676,7 @@ void ClientSession::SendAllPackages(UINT32 dwRqId)
       if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
       {
          DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-         hResult = DBAsyncSelect(hdb, _T("SELECT pkg_id,version,platform,pkg_file,pkg_name,description FROM agent_pkg"));
+         DB_UNBUFFERED_RESULT hResult = DBSelectUnbuffered(hdb, _T("SELECT pkg_id,version,platform,pkg_file,pkg_name,description FROM agent_pkg"));
          if (hResult != NULL)
          {
             msg.setField(VID_RCC, RCC_SUCCESS);
@@ -6683,12 +6688,12 @@ void ClientSession::SendAllPackages(UINT32 dwRqId)
 
             while(DBFetch(hResult))
             {
-               msg.setField(VID_PACKAGE_ID, DBGetFieldAsyncULong(hResult, 0));
-               msg.setField(VID_PACKAGE_VERSION, DBGetFieldAsync(hResult, 1, szBuffer, MAX_DB_STRING));
-               msg.setField(VID_PLATFORM_NAME, DBGetFieldAsync(hResult, 2, szBuffer, MAX_DB_STRING));
-               msg.setField(VID_FILE_NAME, DBGetFieldAsync(hResult, 3, szBuffer, MAX_DB_STRING));
-               msg.setField(VID_PACKAGE_NAME, DBGetFieldAsync(hResult, 4, szBuffer, MAX_DB_STRING));
-               DBGetFieldAsync(hResult, 5, szBuffer, MAX_DB_STRING);
+               msg.setField(VID_PACKAGE_ID, DBGetFieldULong(hResult, 0));
+               msg.setField(VID_PACKAGE_VERSION, DBGetField(hResult, 1, szBuffer, MAX_DB_STRING));
+               msg.setField(VID_PLATFORM_NAME, DBGetField(hResult, 2, szBuffer, MAX_DB_STRING));
+               msg.setField(VID_FILE_NAME, DBGetField(hResult, 3, szBuffer, MAX_DB_STRING));
+               msg.setField(VID_PACKAGE_NAME, DBGetField(hResult, 4, szBuffer, MAX_DB_STRING));
+               DBGetField(hResult, 5, szBuffer, MAX_DB_STRING);
                DecodeSQLString(szBuffer);
                msg.setField(VID_DESCRIPTION, szBuffer);
                sendMessage(&msg);
@@ -6698,7 +6703,7 @@ void ClientSession::SendAllPackages(UINT32 dwRqId)
             msg.setField(VID_PACKAGE_ID, (UINT32)0);
             sendMessage(&msg);
 
-            DBFreeAsyncResult(hResult);
+            DBFreeResult(hResult);
          }
          else
          {
@@ -8466,7 +8471,6 @@ void ClientSession::sendSyslog(NXCPMessage *pRequest)
    NXCPMessage msg;
    UINT32 dwMaxRecords, dwNumRows, dwId;
    DB_RESULT hTempResult;
-   DB_ASYNC_RESULT hResult;
    TCHAR szQuery[1024], szBuffer[1024];
    WORD wRecOrder;
 
@@ -8525,7 +8529,7 @@ void ClientSession::sendSyslog(NXCPMessage *pRequest)
          szQuery[0] = 0;
          break;
    }
-   hResult = DBAsyncSelect(hdb, szQuery);
+   DB_UNBUFFERED_RESULT hResult = DBSelectUnbuffered(hdb, szQuery);
    if (hResult != NULL)
    {
                msg.setField(VID_RCC, RCC_SUCCESS);
@@ -8545,16 +8549,16 @@ void ClientSession::sendSyslog(NXCPMessage *pRequest)
             dwNumRows = 0;
             dwId = VID_SYSLOG_MSG_BASE;
          }
-         msg.setField(dwId++, DBGetFieldAsyncUInt64(hResult, 0));
-         msg.setField(dwId++, DBGetFieldAsyncULong(hResult, 1));
-         msg.setField(dwId++, (WORD)DBGetFieldAsyncLong(hResult, 2));
-         msg.setField(dwId++, (WORD)DBGetFieldAsyncLong(hResult, 3));
-         msg.setField(dwId++, DBGetFieldAsyncULong(hResult, 4));
-         msg.setField(dwId++, DBGetFieldAsync(hResult, 5, szBuffer, 1024));
-         msg.setField(dwId++, DBGetFieldAsync(hResult, 6, szBuffer, 1024));
-         msg.setField(dwId++, DBGetFieldAsync(hResult, 7, szBuffer, 1024));
+         msg.setField(dwId++, DBGetFieldUInt64(hResult, 0));
+         msg.setField(dwId++, DBGetFieldULong(hResult, 1));
+         msg.setField(dwId++, (WORD)DBGetFieldLong(hResult, 2));
+         msg.setField(dwId++, (WORD)DBGetFieldLong(hResult, 3));
+         msg.setField(dwId++, DBGetFieldULong(hResult, 4));
+         msg.setField(dwId++, DBGetField(hResult, 5, szBuffer, 1024));
+         msg.setField(dwId++, DBGetField(hResult, 6, szBuffer, 1024));
+         msg.setField(dwId++, DBGetField(hResult, 7, szBuffer, 1024));
       }
-      DBFreeAsyncResult(hResult);
+      DBFreeResult(hResult);
 
       // Send remaining records with End-Of-Sequence notification
       msg.setField(VID_NUM_RECORDS, dwNumRows);
@@ -8601,7 +8605,6 @@ void ClientSession::SendTrapLog(NXCPMessage *pRequest)
    TCHAR szBuffer[4096], szQuery[1024];
    UINT32 dwId, dwNumRows, dwMaxRecords;
    DB_RESULT hTempResult;
-   DB_ASYNC_RESULT hResult;
    WORD wRecOrder;
 
    wRecOrder = ((g_dbSyntax == DB_SYNTAX_MSSQL) || (g_dbSyntax == DB_SYNTAX_ORACLE)) ? RECORD_ORDER_REVERSED : RECORD_ORDER_NORMAL;
@@ -8666,7 +8669,7 @@ void ClientSession::SendTrapLog(NXCPMessage *pRequest)
             break;
       }
 
-      hResult = DBAsyncSelect(hdb, szQuery);
+      DB_UNBUFFERED_RESULT hResult = DBSelectUnbuffered(hdb, szQuery);
       if (hResult != NULL)
       {
          // Send events, one per message
@@ -8681,14 +8684,14 @@ void ClientSession::SendTrapLog(NXCPMessage *pRequest)
                dwNumRows = 0;
                dwId = VID_TRAP_LOG_MSG_BASE;
             }
-            msg.setField(dwId++, DBGetFieldAsyncUInt64(hResult, 0));
-            msg.setField(dwId++, DBGetFieldAsyncULong(hResult, 1));
-            msg.setField(dwId++, DBGetFieldAsyncIPAddr(hResult, 2));
-            msg.setField(dwId++, DBGetFieldAsyncULong(hResult, 3));
-            msg.setField(dwId++, DBGetFieldAsync(hResult, 4, szBuffer, 256));
-            msg.setField(dwId++, DBGetFieldAsync(hResult, 5, szBuffer, 4096));
-         }
-         DBFreeAsyncResult(hResult);
+            msg.setField(dwId++, DBGetFieldUInt64(hResult, 0));
+            msg.setField(dwId++, DBGetFieldULong(hResult, 1));
+            msg.setField(dwId++, DBGetFieldIPAddr(hResult, 2));
+            msg.setField(dwId++, DBGetFieldULong(hResult, 3));
+            msg.setField(dwId++, DBGetField(hResult, 4, szBuffer, 256));
+            msg.setField(dwId++, DBGetField(hResult, 5, szBuffer, 4096));
+         }
+         DBFreeResult(hResult);
 
          // Send remaining records with End-Of-Sequence notification
          msg.setField(VID_NUM_RECORDS, dwNumRows);
index 68845cc..d9b969a 100644 (file)
@@ -1,6 +1,6 @@
 /* 
 ** nxdbmgr - NetXMS database manager
-** Copyright (C) 2004-2013 Victor Kirhenshtein
+** Copyright (C) 2004-2015 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -72,7 +72,6 @@ static BOOL ExportTable(sqlite3 *db, const TCHAR *name)
        String query;
        TCHAR buffer[256];
        char *errmsg;
-       DB_ASYNC_RESULT hResult;
        int i, columnCount = 0;
        BOOL success = TRUE;
 
@@ -82,7 +81,7 @@ static BOOL ExportTable(sqlite3 *db, const TCHAR *name)
        {
                _sntprintf(buffer, 256, _T("SELECT * FROM %s"), name);
 
-               hResult = SQLAsyncSelect(buffer);
+               DB_UNBUFFERED_RESULT hResult = SQLSelectUnbuffered(buffer);
                if (hResult != NULL)
                {
                        while(DBFetch(hResult))
@@ -90,11 +89,11 @@ static BOOL ExportTable(sqlite3 *db, const TCHAR *name)
                                query = _T("");
 
                                // Column names
-                               columnCount = DBGetColumnCountAsync(hResult);
+                               columnCount = DBGetColumnCount(hResult);
                                query.appendFormattedString(_T("INSERT INTO %s ("), name);
                                for(i = 0; i < columnCount; i++)
                                {
-                                       DBGetColumnNameAsync(hResult, i, buffer, 256);
+                                       DBGetColumnName(hResult, i, buffer, 256);
                                        query += buffer;
                                        query += _T(",");
                                }
@@ -105,7 +104,7 @@ static BOOL ExportTable(sqlite3 *db, const TCHAR *name)
                                TCHAR data[8192];
                                for(i = 0; i < columnCount; i++)
                                {
-                                       TCHAR *escapedString = EscapeString(DBGetFieldAsync(hResult, i, data, 8192));
+                                       TCHAR *escapedString = EscapeString(DBGetField(hResult, i, data, 8192));
                                        query.appendPreallocated(escapedString);
                                        query += _T(",");
                                }
@@ -123,7 +122,7 @@ static BOOL ExportTable(sqlite3 *db, const TCHAR *name)
                                }
                                free(utf8query);
                        }
-                       DBFreeAsyncResult(hResult);
+                       DBFreeResult(hResult);
 
                        if (success)
                        {
index d7d2f80..1c7293d 100644 (file)
@@ -122,7 +122,7 @@ static bool MigrateTable(const TCHAR *table)
    bool success = false;
    TCHAR buffer[256], errorText[DBDRV_MAX_ERROR_TEXT];
    _sntprintf(buffer, 256, _T("SELECT * FROM %s"), table);
-   DB_ASYNC_RESULT hResult = DBAsyncSelectEx(s_hdbSource, buffer, errorText);
+   DB_UNBUFFERED_RESULT hResult = DBSelectUnbufferedEx(s_hdbSource, buffer, errorText);
    if (hResult == NULL)
    {
                _tprintf(_T("ERROR: unable to read data from source table (%s)\n"), errorText);
@@ -134,10 +134,10 @@ static bool MigrateTable(const TCHAR *table)
    String query = _T("INSERT INTO ");
    query += table;
    query += _T(" (");
-       int columnCount = DBGetColumnCountAsync(hResult);
+       int columnCount = DBGetColumnCount(hResult);
        for(int i = 0; i < columnCount; i++)
        {
-               DBGetColumnNameAsync(hResult, i, buffer, 256);
+               DBGetColumnName(hResult, i, buffer, 256);
                query += buffer;
                query += _T(",");
        }
@@ -156,15 +156,15 @@ static bool MigrateTable(const TCHAR *table)
       {
                        for(int i = 0; i < columnCount; i++)
          {
-            DBBind(hStmt, i + 1, DB_SQLTYPE_VARCHAR, DBGetFieldAsync(hResult, i, NULL, 0), DB_BIND_DYNAMIC);
+            DBBind(hStmt, i + 1, DB_SQLTYPE_VARCHAR, DBGetField(hResult, i, NULL, 0), DB_BIND_DYNAMIC);
          }
          if (!SQLExecute(hStmt))
          {
             _tprintf(_T("Failed input record:\n"));
             for(int i = 0; i < columnCount; i++)
             {
-               DBGetColumnNameAsync(hResult, i, buffer, 256);
-               TCHAR *value = DBGetFieldAsync(hResult, i, NULL, 0);
+               DBGetColumnName(hResult, i, buffer, 256);
+               TCHAR *value = DBGetField(hResult, i, NULL, 0);
                _tprintf(_T("   %s = \"%s\"\n"), buffer, CHECK_NULL(value));
                safe_free(value);
             }
@@ -199,7 +199,7 @@ static bool MigrateTable(const TCHAR *table)
                _tprintf(_T("ERROR: cannot prepare INSERT statement (%s)\n"), errorText);
       DBRollback(g_hCoreDB);
    }
-   DBFreeAsyncResult(hResult);
+   DBFreeResult(hResult);
        return success;
 }
 
index 441ebec..90a1337 100644 (file)
@@ -170,17 +170,15 @@ DB_RESULT SQLSelect(const TCHAR *pszQuery)
 }
 
 /**
- * Execute SQL SELECT query via DBAsyncSelect and print error message on screen if query failed
+ * Execute SQL SELECT query via DBSelectUnbuffered and print error message on screen if query failed
  */
-DB_ASYNC_RESULT SQLAsyncSelect(const TCHAR *pszQuery)
+DB_UNBUFFERED_RESULT SQLSelectUnbuffered(const TCHAR *pszQuery)
 {
-   DB_ASYNC_RESULT hResult;
-       TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
-
    if (g_bTrace)
       ShowQuery(pszQuery);
 
-   hResult = DBAsyncSelectEx(g_hCoreDB, pszQuery, errorText);
+   TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
+   DB_UNBUFFERED_RESULT hResult = DBSelectUnbufferedEx(g_hCoreDB, pszQuery, errorText);
    if (hResult == NULL)
       WriteToTerminalEx(_T("SQL query failed (%s):\n\x1b[33;1m%s\x1b[0m\n"), errorText, pszQuery);
    return hResult;
index a731b89..988bc4f 100644 (file)
@@ -59,7 +59,7 @@ void UpgradeDatabase();
 void UnlockDatabase();
 void ReindexIData();
 DB_RESULT SQLSelect(const TCHAR *pszQuery);
-DB_ASYNC_RESULT SQLAsyncSelect(const TCHAR *pszQuery);
+DB_UNBUFFERED_RESULT SQLSelectUnbuffered(const TCHAR *pszQuery);
 bool SQLExecute(DB_STATEMENT hStmt);
 bool SQLQuery(const TCHAR *pszQuery);
 bool SQLBatch(const TCHAR *pszBatch);