]> granicus.if.org Git - postgresql/commitdiff
1) Implement SQLParamOptions().
authorHiroshi Inoue <inoue@tpf.co.jp>
Fri, 8 Mar 2002 08:52:55 +0000 (08:52 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Fri, 8 Mar 2002 08:52:55 +0000 (08:52 +0000)
2) Handle Multiple results and implement SQLMoreResult().
3) Improve multibyte handling thanks to Eiji Tokuya.
4) Add new options.
   LF <-> CR/LF converion.
   TRUE is -1 (for VB).
5) Introduce unicode(UCS-2) support.
6) Reduce the length of connection strings.
7) Improve SQLError, SQLGetDiagRec(ODBC 3.0).
8) Implement SQLTablePrivileges().
9) Miscellaneous changes for ODBC 3.0 support.

43 files changed:
src/interfaces/odbc/bind.c
src/interfaces/odbc/connection.c
src/interfaces/odbc/connection.h
src/interfaces/odbc/convert.c
src/interfaces/odbc/convert.h
src/interfaces/odbc/dlg_specific.c
src/interfaces/odbc/dlg_specific.h
src/interfaces/odbc/drvconn.c
src/interfaces/odbc/environ.c
src/interfaces/odbc/environ.h
src/interfaces/odbc/execute.c
src/interfaces/odbc/info.c
src/interfaces/odbc/info30.c
src/interfaces/odbc/misc.c
src/interfaces/odbc/misc.h
src/interfaces/odbc/multibyte.c
src/interfaces/odbc/multibyte.h
src/interfaces/odbc/odbcapi.c
src/interfaces/odbc/odbcapi25w.c
src/interfaces/odbc/odbcapi30.c
src/interfaces/odbc/odbcapi30w.c
src/interfaces/odbc/odbcapiw.c
src/interfaces/odbc/options.c
src/interfaces/odbc/parse.c
src/interfaces/odbc/pgapi30.c
src/interfaces/odbc/pgapifunc.h
src/interfaces/odbc/pgtypes.c
src/interfaces/odbc/psqlodbc.h
src/interfaces/odbc/psqlodbc.rc
src/interfaces/odbc/psqlodbc_api30w.def [new file with mode: 0644]
src/interfaces/odbc/psqlodbc_apiw.def [new file with mode: 0644]
src/interfaces/odbc/qresult.c
src/interfaces/odbc/qresult.h
src/interfaces/odbc/resource.h
src/interfaces/odbc/results.c
src/interfaces/odbc/setup.c
src/interfaces/odbc/statement.c
src/interfaces/odbc/statement.h
src/interfaces/odbc/win32.mak
src/interfaces/odbc/win32_30.mak
src/interfaces/odbc/win32_30w.mak [new file with mode: 0644]
src/interfaces/odbc/win32w.mak [new file with mode: 0644]
src/interfaces/odbc/win_unicode.c

index f3fb35373578d2af34e4d6c5d43000cf56a00fd4..6ce32c7982b8848d0c783b7786383b9e95506a05 100644 (file)
@@ -7,7 +7,7 @@
  * Classes:                    BindInfoClass, ParameterInfoClass
  *
  * API functions:      SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams,
- *                                     SQLParamOptions(NI)
+ *                                     SQLParamOptions
  *
  * Comments:           See "notice.txt" for copyright and license information.
  *-------
@@ -331,17 +331,9 @@ PGAPI_ParamOptions(
 
        mylog("%s: entering... %d %x\n", func, crow, pirow);
 
-       if (crow == 1)                          /* temporary solution and must be
-                                                                * rewritten later */
-       {
-               if (pirow)
-                       *pirow = 1;
-               return SQL_SUCCESS;
-       }
-       stmt->errornumber = CONN_UNSUPPORTED_OPTION;
-       stmt->errormsg = "Function not implemented";
-       SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
-       return SQL_ERROR;
+       stmt->options.paramset_size = crow;
+       stmt->options.param_processed_ptr = pirow;
+       return SQL_SUCCESS;
 }
 
 
index 3d07474a560cc49243d270d74f8d2a7255aef1c0..44d7589496a478da99e2adc33eef5207437562de 100644 (file)
@@ -75,7 +75,8 @@ PGAPI_AllocConnect(
                return SQL_ERROR;
        }
 
-       *phdbc = (HDBC) conn;
+       if (phdbc)
+               *phdbc = (HDBC) conn;
 
        return SQL_SUCCESS;
 }
@@ -228,6 +229,16 @@ PGAPI_FreeConnect(
 }
 
 
+void
+CC_conninfo_init(ConnInfo *conninfo)
+{
+               memset(conninfo, 0, sizeof(ConnInfo));
+               conninfo->disallow_premature = -1;
+               conninfo->updatable_cursors = -1;
+               conninfo->lf_conversion = -1;
+               conninfo->true_is_minus1 = -1;
+               memcpy(&(conninfo->drivers), &globals, sizeof(globals));
+}
 /*
  *             IMPLEMENTATION CONNECTION CLASS
  */
@@ -249,11 +260,7 @@ CC_Constructor()
                rv->status = CONN_NOT_CONNECTED;
                rv->transact_status = CONN_IN_AUTOCOMMIT;               /* autocommit by default */
 
-               memset(&rv->connInfo, 0, sizeof(ConnInfo));
-#ifdef DRIVER_CURSOR_IMPLEMENT
-               rv->connInfo.updatable_cursors = 1;
-#endif   /* DRIVER_CURSOR_IMPLEMENT */
-               memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
+               CC_conninfo_init(&(rv->connInfo));
                rv->sock = SOCK_Constructor(rv);
                if (!rv->sock)
                        return NULL;
@@ -280,6 +287,7 @@ CC_Constructor()
                rv->pg_version_major = 0;
                rv->pg_version_minor = 0;
                rv->ms_jet = 0;
+               rv->unicode = 0;
 #ifdef MULTIBYTE
                rv->client_encoding = NULL;
                rv->server_encoding = NULL;
@@ -338,7 +346,7 @@ CC_cursor_count(ConnectionClass *self)
        for (i = 0; i < self->num_stmts; i++)
        {
                stmt = self->stmts[i];
-               if (stmt && stmt->result && stmt->result->cursor)
+               if (stmt && SC_get_Result(stmt) && SC_get_Result(stmt)->cursor)
                        count++;
        }
 
@@ -366,18 +374,18 @@ CC_begin(ConnectionClass *self)
        char    ret = TRUE;
        if (!CC_is_in_trans(self))
        {
-               QResultClass *res = CC_send_query(self, "BEGIN", NULL);
+               QResultClass *res = CC_send_query(self, "BEGIN", NULL, TRUE);
                mylog("CC_begin:  sending BEGIN!\n");
 
                if (res != NULL)
                {
-                       ret = (!QR_aborted(res) && QR_command_successful(res));
+                       ret = QR_command_successful(res);
                        QR_Destructor(res);
                        if (ret)
                                CC_set_in_trans(self);
                }
                else
-                       ret = FALSE;
+                       return FALSE;
        }
 
        return ret;
@@ -393,7 +401,7 @@ CC_commit(ConnectionClass *self)
        char    ret = FALSE;
        if (CC_is_in_trans(self))
        {
-               QResultClass *res = CC_send_query(self, "COMMIT", NULL);
+               QResultClass *res = CC_send_query(self, "COMMIT", NULL, TRUE);
                mylog("CC_commit:  sending COMMIT!\n");
 
                CC_set_no_trans(self);
@@ -404,7 +412,7 @@ CC_commit(ConnectionClass *self)
                        QR_Destructor(res);
                }
                else
-                       ret = FALSE;
+                       return FALSE;
        }
 
        return ret;
@@ -419,7 +427,7 @@ CC_abort(ConnectionClass *self)
 {
        if (CC_is_in_trans(self))
        {
-               QResultClass *res = CC_send_query(self, "ROLLBACK", NULL);
+               QResultClass *res = CC_send_query(self, "ROLLBACK", NULL, TRUE);
                mylog("CC_abort:  sending ABORT!\n");
 
                CC_set_no_trans(self);
@@ -488,11 +496,7 @@ CC_cleanup(ConnectionClass *self)
 
        self->status = CONN_NOT_CONNECTED;
        self->transact_status = CONN_IN_AUTOCOMMIT;
-       memset(&self->connInfo, 0, sizeof(ConnInfo));
-#ifdef DRIVER_CURSOR_IMPLEMENT
-       self->connInfo.updatable_cursors = 1;
-#endif   /* DRIVER_CURSOR_IMPLEMENT */
-       memcpy(&(self->connInfo.drivers), &globals, sizeof(globals));
+       CC_conninfo_init(&(self->connInfo));
 #ifdef MULTIBYTE
        if (self->client_encoding)
                free(self->client_encoding);
@@ -578,12 +582,12 @@ md5_auth_send(ConnectionClass *self, const char *salt)
        {
                free(pwd1);
                return 1;
-       }
+       } 
        if (!(pwd2 = malloc(MD5_PASSWD_LEN + 1)))
        {
                free(pwd1);
                return 1;
-       }
+       } 
        if (!EncryptMD5(pwd1 + strlen("md5"), salt, 4, pwd2))
        {
                free(pwd2);
@@ -595,7 +599,7 @@ md5_auth_send(ConnectionClass *self, const char *salt)
        SOCK_put_n_char(sock, pwd2, strlen(pwd2) + 1);
        SOCK_flush_output(sock);
        free(pwd2);
-       return 0;
+       return 0; 
 }
 
 char
@@ -608,7 +612,7 @@ CC_connect(ConnectionClass *self, char do_password)
        ConnInfo   *ci = &(self->connInfo);
        int                     areq = -1;
        int                     beresp;
-       char            msgbuffer[ERROR_MSG_LENGTH];
+       static char             msgbuffer[ERROR_MSG_LENGTH];
        char            salt[5];
        static char *func = "CC_connect";
 
@@ -651,15 +655,16 @@ CC_connect(ConnectionClass *self, char do_password)
                        if (encoding && strcmp(encoding, "OTHER"))
                                self->client_encoding = strdup(encoding);
                }
+               if (self->client_encoding)
+                       self->ccsc = pg_CS_code(self->client_encoding);
                qlog("                extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n",
                         ci->drivers.extra_systable_prefixes,
                         ci->drivers.conn_settings,
                         encoding ? encoding : "");
 #else
-               qlog("                extra_systable_prefixes='%s', conn_settings='%s', protocol='%s'\n",
+               qlog("                extra_systable_prefixes='%s', conn_settings='%s'\n",
                         ci->drivers.extra_systable_prefixes,
-                        ci->drivers.conn_settings,
-                        ci->protocol);
+                        ci->drivers.conn_settings);
 #endif
 
                if (self->status != CONN_NOT_CONNECTED)
@@ -914,7 +919,7 @@ another_version_retry:
         */
        mylog("sending an empty query...\n");
 
-       res = CC_send_query(self, " ", NULL);
+       res = CC_send_query(self, " ", NULL, TRUE);
        if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY)
        {
                mylog("got no result from the empty query.  (probably database does not exist)\n");
@@ -942,13 +947,55 @@ another_version_retry:
         * function instead.
         */
        CC_send_settings(self);
-       CC_lookup_lo(self);                     /* a hack to get the oid of our large
-                                                                * object oid type */
-#ifdef MULTIBYTE\r
-       CC_lookup_characterset(self);\r
-#endif\r
-       CC_lookup_pg_version(self); /* Get PostgreSQL version for SQLGetInfo
-                                                                * use */
+       CC_lookup_lo(self);                     /* a hack to get the oid of
+                                                  our large object oid type */
+       CC_lookup_pg_version(self);             /* Get PostgreSQL version for
+                                                  SQLGetInfo use */
+
+       /*
+        *      Multibyte handling is available ?
+        */
+#ifdef MULTIBYTE
+       if (PG_VERSION_GE(self, 7.0))
+       {
+               CC_lookup_characterset(self);
+               if (self->errornumber != 0)
+                       return 0;
+#ifdef UNICODE_SUPPORT
+               if (self->unicode)
+               {
+                       if (!self->client_encoding ||
+                           stricmp(self->client_encoding, "UNICODE"))
+                       {
+                               QResultClass    *res;
+                               if (PG_VERSION_LT(self, 7.1))
+                               {
+                                       self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
+                                       self->errormsg = "UTF-8 conversion isn't implemented before 7.1";
+                                       return 0;
+                               }
+                               if (self->client_encoding)
+                                       free(self->client_encoding);
+                               self->client_encoding = NULL;
+                               if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, TRUE), res)
+                               {
+                                       self->client_encoding = strdup("UNICODE");
+                                       QR_Destructor(res);
+                                       
+                               }
+                       }
+               }
+#endif /* UNICODE_SUPPORT */
+       }
+#ifdef UNICODE_SUPPORT
+       else if (self->unicode)
+       {
+               self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
+               self->errormsg = "Unicode isn't supported before 7.0";
+               return 0;
+       }
+#endif /* UNICODE_SUPPORT */
+#endif /* MULTIBYTE */
 
        CC_clear_error(self);           /* clear any initial command errors */
        self->status = CONN_CONNECTED;
@@ -1081,11 +1128,12 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
  *     'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
  */
 QResultClass *
-CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
+CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL clear_result_on_abort)
 {
        QResultClass *result_in = NULL,
-                          *res = NULL,
-                          *retres = NULL;
+                          *cmdres = NULL,
+                          *retres = NULL,
+                          *res = NULL;
        char            swallow,
                           *wq;
        int                     id;
@@ -1094,9 +1142,9 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                                empty_reqs;
        BOOL            msg_truncated,
                                ReadyToReturn,
-                               tuples_return = FALSE,
                                query_completed = FALSE,
                                before_64 = PG_VERSION_LT(self, 6.4),
+                               aborted = FALSE,
                                used_passed_result_object = FALSE;
 
        /* ERROR_MSG_LENGTH is suffcient */
@@ -1156,6 +1204,20 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                ;
        if (*wq == '\0')
                empty_reqs = 1;
+       cmdres = qi ? qi->result_in : NULL;
+       if (cmdres)
+               used_passed_result_object = TRUE;
+       else
+       {
+               cmdres = QR_Constructor();
+               if (!cmdres)
+               {
+                       self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
+                       self->errormsg = "Could not create result info in send_query.";
+                       return NULL;
+               }
+       }
+       res = cmdres;
        while (!ReadyToReturn)
        {
                /* what type of message is coming now ? */
@@ -1199,12 +1261,14 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                                {
                                        mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
 
-                                       if (res == NULL)        /* allow for "show" style info */
-                                               res = QR_Constructor();
+                                       if (query_completed)    /* allow for "show" style notices */
+                                       {
+                                               res->next = QR_Constructor();
+                                               res = res->next;
+                                       } 
 
                                        mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);
 
-                                       /* Only save the first command */
                                        if (QR_command_successful(res))
                                                QR_set_status(res, PGRES_COMMAND_OK);
                                        QR_set_command(res, cmdbuffer);
@@ -1233,44 +1297,19 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                                if (empty_reqs == 0)
                                {
                                        ReadyToReturn = TRUE;
-                                       if (res && QR_get_aborted(res))
-                                               retres = res;
-                                       else if (tuples_return)
-                                               retres = result_in;
-                                       else if (query_completed)
-                                               retres = res;
+                                       if (aborted || query_completed)
+                                               retres = cmdres;
                                        else
                                                ReadyToReturn = FALSE;
                                }
                                break;
-                       case 'N':                       /* INFO, NOTICE, WARNING */
+                       case 'N':                       /* NOTICE: */
                                msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
-                               if (!res)
-                                       res = QR_Constructor();
                                if (QR_command_successful(res))
                                        QR_set_status(res, PGRES_NONFATAL_ERROR);
                                QR_set_notice(res, cmdbuffer);  /* will dup this string */
-#ifdef MULTIBYTE\r
-                               if (strstr(cmdbuffer,"encoding is"))\r
-                               {\r
-                                       if (strstr(cmdbuffer,"Current client encoding is"))\r
-                                               strcpy(PG_CCSS, cmdbuffer + 36);\r
-                                       if (strstr(cmdbuffer,"Current server encoding is"))\r
-                                               strcpy(PG_SCSS, cmdbuffer + 36);\r
-                                       mylog("~~~ WARNING: '%s'\n", cmdbuffer);\r
-                                       qlog("WARNING from backend during send_query: '%s'\n ClientEncoding = %s\n ServerEncoding = %s\n", cmdbuffer, PG_CCSS, PG_SCSS);\r
-\r
-                               }\r
-                               else\r
-                               {\r
-\r
-                                       mylog("~~~ WARNING: '%s'\n", cmdbuffer);\r
-                                       qlog("WARNING from backend during send_query: '%s'\n", cmdbuffer);\r
-                               }\r
-#else\r
-                               mylog("~~~ WARNING: '%s'\n", cmdbuffer);\r
-                               qlog("WARNING from backend during send_query: '%s'\n", cmdbuffer);\r
-#endif
+                               mylog("~~~ NOTICE: '%s'\n", cmdbuffer);
+                               qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer);
                                while (msg_truncated)
                                        msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 
@@ -1280,15 +1319,13 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                        case 'I':                       /* The server sends an empty query */
                                /* There is a closing '\0' following the 'I', so we eat it */
                                swallow = SOCK_get_char(sock);
-                               if (!res)
-                                       res = QR_Constructor();
                                if ((swallow != '\0') || SOCK_get_errcode(sock) != 0)
                                {
                                        self->errornumber = CONNECTION_BACKEND_CRAZY;
                                        self->errormsg = "Unexpected protocol character from backend (send_query - I)";
                                        QR_set_status(res, PGRES_FATAL_ERROR);
                                        ReadyToReturn = TRUE;
-                                       retres = res;
+                                       retres = cmdres;
                                        break;
                                }
                                else
@@ -1315,8 +1352,6 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                                qlog("ERROR from backend during send_query: '%s'\n", self->errormsg);
 
                                /* We should report that an error occured. Zoltan */
-                               if (!res)
-                                       res = QR_Constructor();
 
                                if (!strncmp(self->errormsg, "FATAL", 5))
                                {
@@ -1327,6 +1362,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                                        self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
                                QR_set_status(res, PGRES_FATAL_ERROR);
                                QR_set_aborted(res, TRUE);
+                               aborted = TRUE;
                                while (msg_truncated)
                                        msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 
@@ -1337,13 +1373,11 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                                SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
                                break;
                        case 'T':                       /* Tuple results start here */
-                               result_in = qi ? qi->result_in : NULL;
-
-                               if (result_in == NULL)
+                               if (query_completed)
                                {
-                                       result_in = QR_Constructor();
-                                       mylog("send_query: 'T' no result_in: res = %u\n", result_in);
-                                       if (!result_in)
+                                       res->next = QR_Constructor();
+                                       mylog("send_query: 'T' no result_in: res = %u\n", res->next);
+                                       if (!res->next)
                                        {
                                                self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
                                                self->errormsg = "Could not create result info in send_query.";
@@ -1351,55 +1385,60 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                                                retres = NULL;
                                                break;
                                        }
+                                       res = res->next;
 
                                        if (qi)
-                                               QR_set_cache_size(result_in, qi->row_size);
-
-                                       if (!QR_fetch_tuples(result_in, self, qi ? qi->cursor : NULL))
+                                               QR_set_cache_size(res, qi->row_size);
+                               }
+                               if (!used_passed_result_object)
+                               {
+                                       if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
                                        {
                                                self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
-                                               self->errormsg = QR_get_message(result_in);
+                                               self->errormsg = QR_get_message(res);
                                                ReadyToReturn = TRUE;
                                                retres = NULL;
                                                break;
                                        }
+                                       query_completed = TRUE;
                                }
                                else
                                {                               /* next fetch, so reuse an existing result */
 
-                                       used_passed_result_object = TRUE;
                                        /*
                                         * called from QR_next_tuple and must return
                                         * immediately.
                                         */
                                        ReadyToReturn = TRUE;
-                                       if (!QR_fetch_tuples(result_in, NULL, NULL))
+                                       if (!QR_fetch_tuples(res, NULL, NULL))
                                        {
                                                self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
-                                               self->errormsg = QR_get_message(result_in);
+                                               self->errormsg = QR_get_message(res);
                                                retres = NULL;
                                                break;
                                        }
-                                       retres = result_in;
+                                       retres = cmdres;
                                }
-
-                               tuples_return = TRUE;
                                break;
                        case 'D':                       /* Copy in command began successfully */
-                               if (!res)
-                                       res = QR_Constructor();
-                               if (QR_command_successful(res))
-                                       QR_set_status(res, PGRES_COPY_IN);
+                               if (query_completed)
+                               {
+                                       res->next = QR_Constructor();
+                                       res = res->next;
+                               }
+                               QR_set_status(res, PGRES_COPY_IN);
                                ReadyToReturn = TRUE;
-                               retres = res;
+                               retres = cmdres;
                                break;
                        case 'B':                       /* Copy out command began successfully */
-                               if (!res)
-                                       res = QR_Constructor();
-                               if (QR_command_successful(res))
-                                       QR_set_status(res, PGRES_COPY_OUT);
+                               if (query_completed)
+                               {
+                                       res->next = QR_Constructor();
+                                       res = res->next;
+                               }
+                               QR_set_status(res, PGRES_COPY_OUT);
                                ReadyToReturn = TRUE;
-                               retres = res;
+                               retres = cmdres;
                                break;
                        default:
                                self->errornumber = CONNECTION_BACKEND_CRAZY;
@@ -1417,7 +1456,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                 */
                if (before_64)
                {
-                       if (empty_reqs == 0 && (query_completed || tuples_return))
+                       if (empty_reqs == 0 && query_completed)
                                break;
                }
        }
@@ -1426,34 +1465,44 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
         * Break before being ready to return.
         */
        if (!ReadyToReturn)
-       {
-               if (res && QR_get_aborted(res))
-                       retres = res;
-               else if (tuples_return)
-                       retres = result_in;
-               else
-                       retres = res;
-       }
+               retres = cmdres;
 
        /*
-        * set notice message to result_in.
+        * Cleanup garbage results before returning.
         */
-       if (result_in && res && retres == result_in)
-       {
-               if (QR_command_successful(result_in))
-                       QR_set_status(result_in, QR_get_status(res));
-               QR_set_notice(result_in, QR_get_notice(res));
-       }
-
+       if (cmdres && retres != cmdres && !used_passed_result_object)
+               QR_Destructor(cmdres);
        /*
-        * Cleanup garbage results before returning.
+        * Cleanup the aborted result if specified
         */
-       if (res && retres != res)
-               QR_Destructor(res);
-       if (result_in && retres != result_in)
+       if (retres)
        {
-               if (!used_passed_result_object)
-                       QR_Destructor(result_in);
+               if (aborted)
+               {
+                       if (clear_result_on_abort)
+                       {
+                               if (!used_passed_result_object)
+                               {
+                                       QR_Destructor(retres);
+                                       retres = NULL;
+                               }
+                       }
+                       else
+                       {
+                               /*
+                                *      discard results other than errors.
+                                */
+                               QResultClass    *qres;
+                               for (qres = retres; qres->next; qres = retres)
+                               {
+                                       if (QR_get_aborted(qres))
+                                               break;
+                                       retres = qres->next;
+                                       qres->next = NULL;
+                                       QR_Destructor(qres);
+                               }
+                       }
+               }
        }
        return retres;
 }
@@ -1591,7 +1640,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
                                SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
 
                                mylog("send_function(G): 'N' - %s\n", msgbuffer);
-                               qlog("WARNING from backend during send_function: '%s'\n", msgbuffer);
+                               qlog("NOTICE from backend during send_function: '%s'\n", msgbuffer);
 
                                continue;               /* dont return a result -- continue
                                                                 * reading */
@@ -1869,7 +1918,7 @@ CC_lookup_pg_version(ConnectionClass *self)
 
 
 void
-CC_log_error(char *func, char *desc, ConnectionClass *self)
+CC_log_error(const char *func, const char *desc, const ConnectionClass *self)
 {
 #ifdef PRN_NULLCHECK
 #define nullcheck(a) (a ? a : "(NULL)")
@@ -1894,7 +1943,10 @@ CC_log_error(char *func, char *desc, ConnectionClass *self)
                }
        }
        else
+{
                qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
+               mylog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
+}
 #undef PRN_NULLCHECK
 }
 
index df40f440d692ca66b83fd1ed24832963a36820cf..408d11836c5c0def54ee43ae9a26b7bc949a80db 100644 (file)
@@ -151,6 +151,8 @@ typedef struct
        char            focus_password;
        char            disallow_premature;
        char            updatable_cursors;
+       char            lf_conversion;
+       char            true_is_minus1;
        GLOBAL_VALUES drivers;          /* moved from driver's option */
 } ConnInfo;
 
@@ -271,6 +273,7 @@ struct ConnectionClass_
        char       *client_encoding;
        char       *server_encoding;
 #endif   /* MULTIBYTE */
+       int     ccsc;
 };
 
 
@@ -290,6 +293,7 @@ struct ConnectionClass_
 
 /*     prototypes */
 ConnectionClass *CC_Constructor(void);
+void           CC_conninfo_init(ConnInfo *conninfo);
 char           CC_Destructor(ConnectionClass *self);
 int                    CC_cursor_count(ConnectionClass *self);
 char           CC_cleanup(ConnectionClass *self);
@@ -301,7 +305,7 @@ char                CC_connect(ConnectionClass *self, char do_password);
 char           CC_add_statement(ConnectionClass *self, StatementClass *stmt);
 char           CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
 char           CC_get_error(ConnectionClass *self, int *number, char **message);
-QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi);
+QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL);
 void           CC_clear_error(ConnectionClass *self);
 char      *CC_create_errormsg(ConnectionClass *self);
 int                    CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs);
@@ -309,7 +313,7 @@ char                CC_send_settings(ConnectionClass *self);
 void           CC_lookup_lo(ConnectionClass *conn);
 void           CC_lookup_pg_version(ConnectionClass *conn);
 void           CC_initialize_pg_version(ConnectionClass *conn);
-void           CC_log_error(char *func, char *desc, ConnectionClass *self);
+void           CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
 int                    CC_get_max_query_len(const ConnectionClass *self);
 
 #endif
index 4291e36c34ca61aabd6f86abe577ed9c0e679bef..a38ffd1de8313605238d294136112c2c5ac3cb3f 100644 (file)
@@ -335,12 +335,15 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
        int                     bind_row = stmt->bind_row;
        int                     bind_size = stmt->options.bind_size;
        int                     result = COPY_OK;
-       BOOL            changed;
+       BOOL            changed, true_is_minus1 = FALSE;
        const char *neut_str = value;
        char            midtemp[2][32];
        int                     mtemp_cnt = 0;
        static BindInfoClass sbic;
        BindInfoClass *pbic;
+#ifdef UNICODE_SUPPORT
+       BOOL    wchanged =   FALSE;
+#endif /* UNICODE_SUPPORT */
 
        if (stmt->current_col >= 0)
        {
@@ -474,15 +477,23 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                                char       *s;
 
                                s = midtemp[mtemp_cnt];
-                               strcpy(s, (char *) value);
-                               if (s[0] == 'f' || s[0] == 'F' || s[0] == 'n' || s[0] == 'N' || s[0] == '0')
-                                       s[0] = '0';
-                               else
-                                       s[0] = '1';
-                               s[1] = '\0';
+                               switch (((char *)value)[0])
+                               {
+                                       case 'f':
+                                       case 'F':
+                                       case 'n':
+                                       case 'N':
+                                       case '0':
+                                               strcpy(s, "0");
+                                               break;
+                                       default:
+                                               if (true_is_minus1)
+                                                       strcpy(s, "-1");
+                                               else
+                                                       strcpy(s, "1");
+                               }
                                neut_str = midtemp[mtemp_cnt];
                                mtemp_cnt++;
-
                        }
                        break;
 
@@ -567,7 +578,11 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
 
        rgbValueBindRow = (char *) rgbValue + rgbValueOffset;
 
+#ifdef UNICODE_SUPPORT
+       if (fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR)
+#else
        if (fCType == SQL_C_CHAR)
+#endif /* UNICODE_SUPPORT */
        {
                /* Special character formatting as required */
 
@@ -599,7 +614,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                                break;
 
                        case PG_TYPE_BOOL:
-                               len = 1;
+                               len = strlen(neut_str);
                                if (cbValueMax > len)
                                {
                                        strcpy(rgbValueBindRow, neut_str);
@@ -637,8 +652,18 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                                        pbic = &stmt->bindings[stmt->current_col];
                                if (pbic->data_left < 0)
                                {
+                                       BOOL lf_conv = SC_get_conn(stmt)->connInfo.lf_conversion;
+#ifdef UNICODE_SUPPORT
+                                       if (fCType == SQL_C_WCHAR)
+                                       {
+                                               len = utf8_to_ucs2(neut_str, -1, NULL, 0);
+                                               len *= 2;
+                                               wchanged = changed = TRUE;
+                                       }
+                                       else
+#endif /* UNICODE_SUPPORT */
                                        /* convert linefeeds to carriage-return/linefeed */
-                                       len = convert_linefeeds(neut_str, NULL, 0, &changed);
+                                       len = convert_linefeeds(neut_str, NULL, 0, lf_conv, &changed);
                                        if (cbValueMax == 0)            /* just returns length
                                                                                                 * info */
                                        {
@@ -654,7 +679,14 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                                                        pbic->ttlbuf = realloc(pbic->ttlbuf, len + 1);
                                                        pbic->ttlbuflen = len + 1;
                                                }
-                                               convert_linefeeds(neut_str, pbic->ttlbuf, pbic->ttlbuflen, &changed);
+#ifdef UNICODE_SUPPORT
+                                               if (fCType == SQL_C_WCHAR)
+                                               {
+                                                       utf8_to_ucs2(neut_str, -1, (SQLWCHAR *) pbic->ttlbuf, len / 2);
+                                               }
+                                               else
+#endif /* UNICODE_SUPPORT */
+                                               convert_linefeeds(neut_str, pbic->ttlbuf, pbic->ttlbuflen, lf_conv, &changed);
                                                ptr = pbic->ttlbuf;
                                        }
                                        else
@@ -715,7 +747,25 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                                mylog("    SQL_C_CHAR, default: len = %d, cbValueMax = %d, rgbValueBindRow = '%s'\n", len, cbValueMax, rgbValueBindRow);
                                break;
                }
-
+#ifdef UNICODE_SUPPORT
+               if (SQL_C_WCHAR == fCType && ! wchanged)
+               {
+                       if (cbValueMax > 2 * len)
+                       {
+                               char *str = strdup(rgbValueBindRow);
+                               UInt4   ucount = utf8_to_ucs2(str, len, (SQLWCHAR *) rgbValueBindRow, cbValueMax / 2);
+                               if (cbValueMax < 2 * (SDWORD) ucount)
+                                       result = COPY_RESULT_TRUNCATED;
+                               len = ucount * 2;
+                               free(str); 
+                       }
+                       else
+                       {
+                               len *= 2;
+                               result = COPY_RESULT_TRUNCATED;
+                       }
+               }
+#endif /* UNICODE_SUPPORT */
 
        }
        else
@@ -1107,11 +1157,11 @@ do { \
  */
 #define CVT_SPECIAL_CHARS(buf, used) \
 do { \
-       int cnvlen = convert_special_chars(buf, NULL, used); \
+       int cnvlen = convert_special_chars(buf, NULL, used, lf_conv, conn->ccsc); \
        unsigned int    newlimit = npos + cnvlen; \
 \
        ENLARGE_NEWSTATEMENT(newlimit); \
-       convert_special_chars(buf, &new_statement[npos], used); \
+       convert_special_chars(buf, &new_statement[npos], used, lf_conv, conn->ccsc); \
        npos += cnvlen; \
 } while (0)
 
@@ -1181,9 +1231,9 @@ table_for_update(const char *stmt, int *endpos)
 }
 
 #ifdef MULTIBYTE
-#define                my_strchr(s1,c1) multibyte_strchr(s1,c1)
+#define                my_strchr(conn, s1,c1) pg_mbschr(conn->ccsc, s1,c1)
 #else
-#define                my_strchr(s1,c1) strchr(s1,c1)
+#define                my_strchr(conn, s1,c1) strchr(s1,c1)
 #endif
 /*
  *     This function inserts parameters into an SQL statements.
@@ -1213,8 +1263,7 @@ copy_statement_with_parameters(StatementClass *stmt)
        time_t          t = time(NULL);
        struct tm  *tim;
        SDWORD          used;
-       char       *buffer,
-                          *buf;
+       char       *buffer, *buf, *allocbuf;
        BOOL            in_quote = FALSE,
                                in_dquote = FALSE,
                                in_escape = FALSE;
@@ -1234,6 +1283,10 @@ copy_statement_with_parameters(StatementClass *stmt)
        BOOL            prev_token_end;
        UInt4   offset = stmt->options.param_offset_ptr ? *stmt->options.param_offset_ptr : 0;
        UInt4   current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
+       BOOL    lf_conv = ci->lf_conversion;
+#ifdef MULTIBYTE
+       encoded_str     encstr;
+#endif   /* MULTIBYTE */
 
 #ifdef DRIVER_CURSOR_IMPLEMENT
        BOOL            search_from_pos = FALSE;
@@ -1311,14 +1364,14 @@ copy_statement_with_parameters(StatementClass *stmt)
        }
        param_number = -1;
 #ifdef MULTIBYTE
-       multibyte_init();
+       make_encoded_str(&encstr, conn, old_statement);
 #endif
 
        for (opos = 0; opos < oldstmtlen; opos++)
        {
-               oldchar = old_statement[opos];
 #ifdef MULTIBYTE
-               if (multibyte_char_check(oldchar) != 0)
+               oldchar = encoded_byte_check(&encstr, opos);
+               if (ENCODE_STATUS(encstr) != 0)
                {
                        CVT_APPEND_CHAR(oldchar);
                        continue;
@@ -1327,6 +1380,8 @@ copy_statement_with_parameters(StatementClass *stmt)
                /*
                 * From here we are guaranteed to handle a 1-byte character.
                 */
+#else
+               oldchar = old_statement[opos];
 #endif
 
                if (in_escape)                  /* escape check */
@@ -1352,7 +1407,7 @@ copy_statement_with_parameters(StatementClass *stmt)
                 * nor a double quote.
                 */
                /* Squeeze carriage-return/linefeed pairs to linefeed only */
-               else if (oldchar == '\r' && opos + 1 < oldstmtlen &&
+               else if (lf_conv && oldchar == '\r' && opos + 1 < oldstmtlen &&
                                 old_statement[opos + 1] == '\n')
                        continue;
 
@@ -1390,11 +1445,12 @@ copy_statement_with_parameters(StatementClass *stmt)
                                }
                                opos += lit_call_len;
                                CVT_APPEND_STR("SELECT ");
-                               if (my_strchr(&old_statement[opos], '('))
+                               if (my_strchr(conn, &old_statement[opos], '('))
                                        proc_no_param = FALSE;
                                continue;
                        }
-                       if (convert_escape(begin, stmt, &npos, &new_stsize, &end) != CONVERT_ESCAPE_OK)
+                       if (convert_escape(begin, stmt, &npos, &new_stsize, &end
+) != CONVERT_ESCAPE_OK)
                        {
                                stmt->errormsg = "ODBC escape convert error";
                                stmt->errornumber = STMT_EXEC_ERROR;
@@ -1585,7 +1641,7 @@ copy_statement_with_parameters(StatementClass *stmt)
                if (param_ctype == SQL_C_DEFAULT)
                        param_ctype = sqltype_to_default_ctype(param_sqltype);
 
-               buf = NULL;
+               allocbuf = buf = NULL;
                param_string[0] = '\0';
                cbuf[0] = '\0';
 
@@ -1597,6 +1653,13 @@ copy_statement_with_parameters(StatementClass *stmt)
                                buf = buffer;
                                break;
 
+#ifdef UNICODE_SUPPORT
+                       case SQL_C_WCHAR:
+                               buf = allocbuf = ucs2_to_utf8((SQLWCHAR *) buffer, used / 2, &used);
+                               used *= 2;
+                               break;
+#endif /* UNICODE_SUPPORT */
+
                        case SQL_C_DOUBLE:
                                sprintf(param_string, "%.15g",
                                                *((SDOUBLE *) buffer));
@@ -1729,6 +1792,11 @@ copy_statement_with_parameters(StatementClass *stmt)
                        case SQL_CHAR:
                        case SQL_VARCHAR:
                        case SQL_LONGVARCHAR:
+#ifdef UNICODE_SUPPORT
+                       case SQL_WCHAR:
+                       case SQL_WVARCHAR:
+                       case SQL_WLONGVARCHAR:
+#endif /* UNICODE_SUPPORT */
 
                                CVT_APPEND_CHAR('\'');  /* Open Quote */
 
@@ -1801,7 +1869,7 @@ copy_statement_with_parameters(StatementClass *stmt)
                                tmp[0] = '\'';
                                /* Time zone stuff is unreliable */
                                stime2timestamp(&st, tmp + 1, USE_ZONE, PG_VERSION_GE(conn, 7.2));
-                               strcat(tmp, "'");
+                               strcat(tmp, "'::timestamp");
 
                                CVT_APPEND_STR(tmp);
 
@@ -1942,6 +2010,10 @@ copy_statement_with_parameters(StatementClass *stmt)
 
                                break;
                }
+#ifdef UNICODE_SUPPORT
+               if (allocbuf)
+                       free(allocbuf);
+#endif /* UNICODE_SUPPORT */
        }                                                       /* end, for */
 
        /* make sure new_statement is always null-terminated */
@@ -2032,7 +2104,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
        while ((*valptr != '\0') && isspace((unsigned char) *valptr))
                valptr++;
      
-       if (end = my_strchr(valptr, '}'), NULL == end)
+       if (end = my_strchr(conn, valptr, '}'), NULL == end)
        {
                mylog("%s couldn't find the ending }\n",func);
                return CONVERT_ESCAPE_ERROR;
@@ -2226,13 +2298,16 @@ int processParameters(const ConnectionClass *conn, const char *value,
        const char      *valptr;
        char    buf[1024];
        BOOL    in_quote, in_dquote, in_escape, leadingSpace;
+#ifdef MULTIBYTE
+       encoded_str     encstr;
+#endif   /* MULTIBYTE */
  
        buf[sizeof(buf)-1] = '\0';
        innerParenthesis = 0;
        in_quote = in_dquote = in_escape = leadingSpace = FALSE;
        param_count = 0;
 #ifdef MULTIBYTE
-       multibyte_init();
+       make_encoded_str(&encstr, conn, value);
 #endif /* MULTIBYTE */
        /* begin with outer '(' */
        for (stop = FALSE, valptr = value, ipos = count = 0; *valptr != '\0'; ipos++, valptr++)
@@ -2250,7 +2325,8 @@ int processParameters(const ConnectionClass *conn, const char *value,
                        return CONVERT_ESCAPE_OVERFLOW;
                }
 #ifdef MULTIBYTE
-               if (multibyte_char_check(*valptr) != 0)
+               encoded_byte_check(&encstr, ipos);
+               if (ENCODE_STATUS(encstr) != 0)
                {
                        result[count++] = *valptr;
                        continue;
@@ -2468,7 +2544,7 @@ parse_datetime(char *buf, SIMPLE_TIME *st)
 
 /*     Change linefeed to carriage-return/linefeed */
 int
-convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed)
+convert_linefeeds(const char *si, char *dst, size_t max, BOOL convlf, BOOL *changed)
 {
        size_t          i = 0,
                                out = 0;
@@ -2478,7 +2554,7 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed)
        *changed = FALSE;
        for (i = 0; si[i] && out < max - 1; i++)
        {
-               if (si[i] == '\n')
+               if (convlf && si[i] == '\n')
                {
                        /* Only add the carriage-return if needed */
                        if (i > 0 && si[i - 1] == '\r')
@@ -2518,12 +2594,15 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed)
  *     Plus, escape any special characters.
  */
 int
-convert_special_chars(const char *si, char *dst, int used)
+convert_special_chars(const char *si, char *dst, int used, BOOL convlf, int ccsc)
 {
        size_t          i = 0,
                                out = 0,
                                max;
        char       *p = NULL;
+#ifdef MULTIBYTE
+       encoded_str     encstr;
+#endif
 
 
        if (used == SQL_NTS)
@@ -2536,13 +2615,14 @@ convert_special_chars(const char *si, char *dst, int used)
                p[0] = '\0';
        }
 #ifdef MULTIBYTE
-       multibyte_init();
+       encoded_str_constr(&encstr, ccsc, si);
 #endif
 
        for (i = 0; i < max && si[i]; i++)
        {
 #ifdef MULTIBYTE
-               if (multibyte_char_check(si[i]) != 0)
+               encoded_nextchar(&encstr);
+               if (ENCODE_STATUS(encstr) != 0)
                {
                        if (p)
                                p[out] = si[i];
@@ -2550,7 +2630,7 @@ convert_special_chars(const char *si, char *dst, int used)
                        continue;
                }
 #endif
-               if (si[i] == '\r' && si[i + 1] == '\n')
+               if (convlf && si[i] == '\r' && si[i + 1] == '\n')
                        continue;
                else if (si[i] == '\'' || si[i] == '\\')
                {
index b06f72f3541e8c514b1d84471b5609b7bd95fd14..2d5f01859f04dd87f253549a7a4f77f371d28151 100644 (file)
@@ -21,7 +21,7 @@
 /* convert_escape results */
 #define CONVERT_ESCAPE_OK                                      0
 #define CONVERT_ESCAPE_OVERFLOW                                        1
-#define CONVERT_ESCAPE_ERROR                                   2
+#define CONVERT_ESCAPE_ERROR                                   -1
 
 typedef struct
 {
@@ -43,8 +43,8 @@ int           convert_escape(const char *value, StatementClass *stmt,
                        int *npos, int *stsize, const char **val_resume);
 BOOL           convert_money(const char *s, char *sout, size_t soutmax);
 char           parse_datetime(char *buf, SIMPLE_TIME *st);
-int                    convert_linefeeds(const char *s, char *dst, size_t max, BOOL *changed);
-int                    convert_special_chars(const char *si, char *dst, int used);
+int                    convert_linefeeds(const char *s, char *dst, size_t max, BOOL convlf, BOOL *changed);
+int                    convert_special_chars(const char *si, char *dst, int used, BOOL convlf,int ccsc);
 
 int                    convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax);
 int                    convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax);
index f23fb9c527f315c7f20f72def0bb641c5f92d6d9..4fbf037cec204d01bedf905d08aea74b9eff3d90 100644 (file)
@@ -123,7 +123,7 @@ driver_optionsDraw(HWND hdlg, const ConnInfo *ci, int src, BOOL enable)
        CheckDlgButton(hdlg, DRV_OPTIMIZER, comval->disable_optimizer);
        CheckDlgButton(hdlg, DRV_KSQO, comval->ksqo);
        CheckDlgButton(hdlg, DRV_UNIQUEINDEX, comval->unique_index);
-       EnableWindow(GetDlgItem(hdlg, DRV_UNIQUEINDEX), enable);
+       /* EnableWindow(GetDlgItem(hdlg, DRV_UNIQUEINDEX), enable); */
        CheckDlgButton(hdlg, DRV_READONLY, comval->onlyread);
        EnableWindow(GetDlgItem(hdlg, DRV_READONLY), enable);
        CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, comval->use_declarefetch);
@@ -332,6 +332,8 @@ ds_optionsProc(HWND hdlg,
                        CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning));
                        CheckDlgButton(hdlg, DS_SHOWSYSTEMTABLES, atoi(ci->show_system_tables));
                        CheckDlgButton(hdlg, DS_DISALLOWPREMATURE, ci->disallow_premature);
+                       CheckDlgButton(hdlg, DS_LFCONVERSION, ci->lf_conversion);
+                       CheckDlgButton(hdlg, DS_TRUEISMINUS1, ci->true_is_minus1);
 
                        EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), atoi(ci->show_oid_column));
 
@@ -367,6 +369,8 @@ ds_optionsProc(HWND hdlg,
 
                                        sprintf(ci->row_versioning, "%d", IsDlgButtonChecked(hdlg, DS_ROWVERSIONING));
                                        ci->disallow_premature = IsDlgButtonChecked(hdlg, DS_DISALLOWPREMATURE);
+                                       ci->lf_conversion = IsDlgButtonChecked(hdlg, DS_LFCONVERSION);
+                                       ci->true_is_minus1 = IsDlgButtonChecked(hdlg, DS_TRUEISMINUS1);
 
                                        /* OID Options */
                                        sprintf(ci->fake_oid_index, "%d", IsDlgButtonChecked(hdlg, DS_FAKEOIDINDEX));
@@ -525,60 +529,186 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
        hlen = strlen(connect_string);
        if (!abbrev)
                sprintf(&connect_string[hlen],
-                               ";READONLY=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s;FETCH=%d;SOCKET=%d;UNKNOWNSIZES=%d;MAXVARCHARSIZE=%d;MAXLONGVARCHARSIZE=%d;DEBUG=%d;COMMLOG=%d;OPTIMIZER=%d;KSQO=%d;USEDECLAREFETCH=%d;TEXTASLONGVARCHAR=%d;UNKNOWNSASLONGVARCHAR=%d;BOOLSASCHAR=%d;PARSE=%d;CANCELASFREESTMT=%d;EXTRASYSTABLEPREFIXES=%s",
+                               ";%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%s;%s=%d;%s=%d;%s=%d;%s=%d",
+                               INI_READONLY,
                                ci->onlyread,
+                               INI_PROTOCOL,
                                ci->protocol,
+                               INI_FAKEOIDINDEX,
                                ci->fake_oid_index,
+                               INI_SHOWOIDCOLUMN,
                                ci->show_oid_column,
+                               INI_ROWVERSIONING,
                                ci->row_versioning,
+                               INI_SHOWSYSTEMTABLES,
                                ci->show_system_tables,
+                               INI_CONNSETTINGS,
                                encoded_conn_settings,
+                               INI_FETCH,
                                ci->drivers.fetch_max,
+                               INI_SOCKET,
                                ci->drivers.socket_buffersize,
+                               INI_UNKNOWNSIZES,
                                ci->drivers.unknown_sizes,
+                               INI_MAXVARCHARSIZE,
                                ci->drivers.max_varchar_size,
+                               INI_MAXLONGVARCHARSIZE,
                                ci->drivers.max_longvarchar_size,
+                               INI_DEBUG,
                                ci->drivers.debug,
+                               INI_COMMLOG,
                                ci->drivers.commlog,
+                               INI_OPTIMIZER,
                                ci->drivers.disable_optimizer,
+                               INI_KSQO,
                                ci->drivers.ksqo,
+                               INI_USEDECLAREFETCH,
                                ci->drivers.use_declarefetch,
+                               INI_TEXTASLONGVARCHAR,
                                ci->drivers.text_as_longvarchar,
+                               INI_UNKNOWNSASLONGVARCHAR,
                                ci->drivers.unknowns_as_longvarchar,
+                               INI_BOOLSASCHAR,
                                ci->drivers.bools_as_char,
+                               INI_PARSE,
                                ci->drivers.parse,
+                               INI_CANCELASFREESTMT,
                                ci->drivers.cancel_as_freestmt,
-                               ci->drivers.extra_systable_prefixes);
+                               INI_EXTRASYSTABLEPREFIXES,
+                               ci->drivers.extra_systable_prefixes,
+                               INI_LFCONVERSION,
+                               ci->lf_conversion,
+                               INI_UPDATABLECURSORS,
+                               ci->updatable_cursors,
+                               INI_DISALLOWPREMATURE,
+                               ci->disallow_premature,
+                               INI_TRUEISMINUS1,
+                               ci->true_is_minus1);
        /* Abbrebiation is needed ? */
        if (abbrev || strlen(connect_string) >= len)
+       {
+               unsigned long flag = 0;
+               if (ci->disallow_premature)
+                       flag |= BIT_DISALLOWPREMATURE;
+               if (ci->updatable_cursors)
+                       flag |= BIT_UPDATABLECURSORS;
+               if (ci->lf_conversion)
+                       flag |= BIT_LFCONVERSION;
+               if (ci->drivers.unique_index)
+                       flag |= BIT_UNIQUEINDEX;
+               if (strncmp(ci->protocol, PG64, strlen(PG64)) == 0)
+                       flag |= BIT_PROTOCOL_64;
+               else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0)
+                       flag |= BIT_PROTOCOL_63;
+               switch (ci->drivers.unknown_sizes)
+               {
+                       case UNKNOWNS_AS_DONTKNOW:
+                               flag |= BIT_UNKNOWN_DONTKNOW;
+                               break;
+                       case UNKNOWNS_AS_MAX:
+                               flag |= BIT_UNKNOWN_ASMAX;
+                               break;
+               }
+               if (ci->drivers.disable_optimizer)
+                       flag |= BIT_OPTIMIZER;
+               if (ci->drivers.ksqo)
+                       flag |= BIT_KSQO;
+               if (ci->drivers.commlog)
+                       flag |= BIT_COMMLOG;
+               if (ci->drivers.debug)
+                       flag |= BIT_DEBUG;
+               if (ci->drivers.parse)
+                       flag |= BIT_PARSE;
+               if (ci->drivers.cancel_as_freestmt)
+                       flag |= BIT_CANCELASFREESTMT;
+               if (ci->drivers.use_declarefetch)
+                       flag |= BIT_USEDECLAREFETCH;
+               if (ci->onlyread[0] == '1')
+                       flag |= BIT_READONLY;
+               if (ci->drivers.text_as_longvarchar)
+                       flag |= BIT_TEXTASLONGVARCHAR;
+               if (ci->drivers.unknowns_as_longvarchar)
+                       flag |= BIT_UNKNOWNSASLONGVARCHAR;
+               if (ci->drivers.bools_as_char)
+                       flag |= BIT_BOOLSASCHAR;
+               if (ci->row_versioning[0] == '1')
+                       flag |= BIT_ROWVERSIONING;
+               if (ci->show_system_tables[0] == '1')
+                       flag |= BIT_SHOWSYSTEMTABLES;
+               if (ci->show_oid_column[0] == '1')
+                       flag |= BIT_SHOWOIDCOLUMN;
+               if (ci->fake_oid_index[0] == '1')
+                       flag |= BIT_FAKEOIDINDEX;
+               if (ci->true_is_minus1)
+                       flag |= BIT_TRUEISMINUS1;
+
                sprintf(&connect_string[hlen],
-                               ";A0=%s;A1=%s;A2=%s;A3=%s;A4=%s;A5=%s;A6=%s;A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s",
-                               ci->onlyread,
-                               ci->protocol,
-                               ci->fake_oid_index,
-                               ci->show_oid_column,
-                               ci->row_versioning,
-                               ci->show_system_tables,
+                               ";A6=%s;A7=%d;A8=%d;B0=%d;B1=%d;C2=%s;CX=%02x%x",
                                encoded_conn_settings,
                                ci->drivers.fetch_max,
                                ci->drivers.socket_buffersize,
-                               ci->drivers.unknown_sizes,
                                ci->drivers.max_varchar_size,
                                ci->drivers.max_longvarchar_size,
-                               ci->drivers.debug,
-                               ci->drivers.commlog,
-                               ci->drivers.disable_optimizer,
-                               ci->drivers.ksqo,
-                               ci->drivers.use_declarefetch,
-                               ci->drivers.text_as_longvarchar,
-                               ci->drivers.unknowns_as_longvarchar,
-                               ci->drivers.bools_as_char,
-                               ci->drivers.parse,
-                               ci->drivers.cancel_as_freestmt,
-                               ci->drivers.extra_systable_prefixes);
+                               ci->drivers.extra_systable_prefixes,
+                               EFFECTIVE_BIT_COUNT,
+                               flag);
+       }
 }
 
+static void
+unfoldCXAttribute(ConnInfo *ci, const char *value)
+{
+       int             count;
+       unsigned long   flag;
 
+       if (strlen(value) < 2)
+       {
+               count = 3;
+               sscanf(value, "%x", &flag);
+       }
+       else
+       {
+               char    cnt[8];
+               memcpy(cnt, value, 2);
+               cnt[2] = '\0';
+               sscanf(cnt, "%x", &count);
+               sscanf(value + 2, "%x", &flag);
+       }
+       ci->disallow_premature = (char)((flag & BIT_DISALLOWPREMATURE) != 0);
+       ci->updatable_cursors = (char)((flag & BIT_UPDATABLECURSORS) != 0);
+       ci->lf_conversion = (char)((flag & BIT_LFCONVERSION) != 0);
+       if (count < 4)
+               return;
+       ci->drivers.unique_index = (char)((flag & BIT_UNIQUEINDEX) != 0);
+       if ((flag & BIT_PROTOCOL_64) != 0)
+               strcpy(ci->protocol, PG64);
+       else if ((flag & BIT_PROTOCOL_63) != 0)
+               strcpy(ci->protocol, PG63);
+       else
+               strcpy(ci->protocol, PG62);
+       if ((flag & BIT_UNKNOWN_DONTKNOW) != 0)
+               ci->drivers.unknown_sizes = UNKNOWNS_AS_DONTKNOW;
+       else if ((flag & BIT_UNKNOWN_ASMAX) != 0)
+               ci->drivers.unknown_sizes = UNKNOWNS_AS_MAX;
+       else 
+               ci->drivers.unknown_sizes = UNKNOWNS_AS_LONGEST;
+       ci->drivers.disable_optimizer = (char)((flag & BIT_OPTIMIZER) != 0);
+       ci->drivers.ksqo = (char)((flag & BIT_KSQO) != 0);
+       ci->drivers.commlog = (char)((flag & BIT_COMMLOG) != 0);
+       ci->drivers.debug = (char)((flag & BIT_DEBUG) != 0);
+       ci->drivers.parse = (char)((flag & BIT_PARSE) != 0);
+       ci->drivers.cancel_as_freestmt = (char)((flag & BIT_CANCELASFREESTMT) != 0);
+       ci->drivers.use_declarefetch = (char)((flag & BIT_USEDECLAREFETCH) != 0);
+       sprintf(ci->onlyread, "%d", (char)((flag & BIT_READONLY) != 0));
+       ci->drivers.text_as_longvarchar = (char)((flag & BIT_TEXTASLONGVARCHAR) !=0);
+       ci->drivers.unknowns_as_longvarchar = (char)((flag & BIT_UNKNOWNSASLONGVARCHAR) !=0);
+       ci->drivers.bools_as_char = (char)((flag & BIT_BOOLSASCHAR) != 0);
+       sprintf(ci->row_versioning, "%d", (char)((flag & BIT_ROWVERSIONING) != 0));
+       sprintf(ci->show_system_tables, "%d", (char)((flag & BIT_SHOWSYSTEMTABLES) != 0));
+       sprintf(ci->show_oid_column, "%d", (char)((flag & BIT_SHOWOIDCOLUMN) != 0));
+       sprintf(ci->fake_oid_index, "%d", (char)((flag & BIT_FAKEOIDINDEX) != 0));
+       ci->true_is_minus1 = (char)((flag & BIT_TRUEISMINUS1) != 0);
+}
 void
 copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
 {
@@ -630,6 +760,12 @@ copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
                ci->disallow_premature = atoi(value);
        else if (stricmp(attribute, INI_UPDATABLECURSORS) == 0 || stricmp(attribute, "C4") == 0)
                ci->updatable_cursors = atoi(value);
+       else if (stricmp(attribute, INI_LFCONVERSION) == 0)
+               ci->lf_conversion = atoi(value);
+       else if (stricmp(attribute, INI_TRUEISMINUS1) == 0)
+               ci->true_is_minus1 = atoi(value);
+       else if (stricmp(attribute, "CX") == 0)
+               unfoldCXAttribute(ci, value);
 
        mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s',conn_settings='%s',disallow_premature=%d)\n", ci->dsn, ci->server, ci->database, ci->username, ci->password, ci->port, ci->onlyread, ci->protocol, ci->conn_settings, ci->disallow_premature);
 }
@@ -720,6 +856,15 @@ getDSNdefaults(ConnInfo *ci)
 
        if (ci->row_versioning[0] == '\0')
                sprintf(ci->row_versioning, "%d", DEFAULT_ROWVERSIONING);
+
+       if (ci->disallow_premature < 0)
+               ci->disallow_premature = DEFAULT_DISALLOWPREMATURE;
+       if (ci->updatable_cursors < 0)
+               ci->updatable_cursors = DEFAULT_UPDATABLECURSORS;
+       if (ci->lf_conversion < 0)
+               ci->lf_conversion = DEFAULT_LFCONVERSION;
+       if (ci->true_is_minus1 < 0)
+               ci->true_is_minus1 = DEFAULT_TRUEISMINUS1;
 }
 
 
@@ -797,16 +942,32 @@ getDSNinfo(ConnInfo *ci, char overwrite)
        if (ci->translation_option[0] == '\0' || overwrite)
                SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI);
 
-       if (ci->disallow_premature == 0 || overwrite)
+       if (ci->disallow_premature < 0 || overwrite)
        {
                SQLGetPrivateProfileString(DSN, INI_DISALLOWPREMATURE, "", temp, sizeof(temp), ODBC_INI);
-               ci->disallow_premature = atoi(temp);
+               if (temp[0])
+                       ci->disallow_premature = atoi(temp);
        }
 
-       if (ci->updatable_cursors == 0 || overwrite)
+       if (ci->updatable_cursors < 0 || overwrite)
        {
                SQLGetPrivateProfileString(DSN, INI_UPDATABLECURSORS, "", temp, sizeof(temp), ODBC_INI);
-               ci->updatable_cursors = atoi(temp);
+               if (temp[0])
+                       ci->updatable_cursors = atoi(temp);
+       }
+
+       if (ci->lf_conversion < 0 || overwrite)
+       {
+               SQLGetPrivateProfileString(DSN, INI_LFCONVERSION, "", temp, sizeof(temp), ODBC_INI);
+               if (temp[0])
+                       ci->lf_conversion = atoi(temp);
+       }
+
+       if (ci->true_is_minus1 < 0 || overwrite)
+       {
+               SQLGetPrivateProfileString(DSN, INI_TRUEISMINUS1, "", temp, sizeof(temp), ODBC_INI);
+               if (temp[0])
+                       ci->true_is_minus1 = atoi(temp);
        }
 
        /* Allow override of odbcinst.ini parameters here */
@@ -927,6 +1088,16 @@ writeDSNinfo(const ConnInfo *ci)
                                                                 INI_UPDATABLECURSORS,
                                                                 temp,
                                                                 ODBC_INI);
+       sprintf(temp, "%d", ci->lf_conversion);
+       SQLWritePrivateProfileString(DSN,
+                                                                INI_LFCONVERSION,
+                                                                temp,
+                                                                ODBC_INI);
+       sprintf(temp, "%d", ci->true_is_minus1);
+       SQLWritePrivateProfileString(DSN,
+                                                                INI_TRUEISMINUS1,
+                                                                temp,
+                                                                ODBC_INI);
 }
 
 
index b3192123d0fe3bafe22cab8d74ffa63128b1ee79..f293079d35f20222586f580d779cdc6e2f043fec 100644 (file)
 #define INI_TRANSLATIONOPTION                  "TranslationOption"
 #define INI_DISALLOWPREMATURE                  "DisallowPremature"
 #define INI_UPDATABLECURSORS                   "UpdatableCursors"
+#define INI_LFCONVERSION                       "LFConversion"
+#define INI_TRUEISMINUS1                       "TrueIsMinus1"
+/* Bit representaion for abbreviated connection strings */
+#define BIT_LFCONVERSION                       (1L)
+#define BIT_UPDATABLECURSORS                   (1L<<1)
+#define BIT_DISALLOWPREMATURE                  (1L<<2)
+#define BIT_UNIQUEINDEX                                (1L<<3)
+#define BIT_PROTOCOL_63                                (1L<<4)
+#define BIT_PROTOCOL_64                                (1L<<5)
+#define BIT_UNKNOWN_DONTKNOW                   (1L<<6)
+#define BIT_UNKNOWN_ASMAX                      (1L<<7)
+#define BIT_OPTIMIZER                          (1L<<8)
+#define BIT_KSQO                               (1L<<9)
+#define BIT_COMMLOG                            (1L<<10)
+#define BIT_DEBUG                              (1L<<11)
+#define BIT_PARSE                              (1L<<12)
+#define BIT_CANCELASFREESTMT                   (1L<<13)
+#define BIT_USEDECLAREFETCH                    (1L<<14)
+#define BIT_READONLY                           (1L<<15)
+#define BIT_TEXTASLONGVARCHAR                  (1L<<16)
+#define BIT_UNKNOWNSASLONGVARCHAR              (1L<<17)
+#define BIT_BOOLSASCHAR                                (1L<<18)
+#define BIT_ROWVERSIONING                      (1L<<19)
+#define BIT_SHOWSYSTEMTABLES                   (1L<<20)
+#define BIT_SHOWOIDCOLUMN                      (1L<<21)
+#define BIT_FAKEOIDINDEX                       (1L<<22)
+#define BIT_TRUEISMINUS1                       (1L<<23)
+
+#define EFFECTIVE_BIT_COUNT                    24
 
 
 /*     Connection Defaults */
 
 #define DEFAULT_EXTRASYSTABLEPREFIXES  "dd_;"
 
+#define DEFAULT_DISALLOWPREMATURE      0
+#define DEFAULT_TRUEISMINUS1           0
+#ifdef DRIVER_CURSOR_IMPLEMENT
+#define DEFAULT_UPDATABLECURSORS       1
+#else
+#define DEFAULT_UPDATABLECURSORS       0
+#endif /* DRIVER_CURSOR_IMPLEMENT */
+#ifdef WIN32
+#define DEFAULT_LFCONVERSION           1
+#else
+#define DEFAULT_LFCONVERSION           0
+#endif /* WIN32 */
+
 /*     prototypes */
 void           getCommonDefaults(const char *section, const char *filename, ConnInfo *ci);
 
index e369525ca02a530802fccf921ae8244656e95c80..e07cec3e8c19ab25decfe7234840045ba08425c0 100644 (file)
@@ -242,7 +242,7 @@ dialog:
        qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, szConnStrOut);
 
 
-       mylog("PGAPI_DRiverConnect: returning %d\n", result);
+       mylog("PGAPI_DriverConnect: returning %d\n", result);
        return result;
 }
 
@@ -351,10 +351,7 @@ dconn_get_connect_attributes(const UCHAR FAR * connect_string, ConnInfo *ci)
                           *equals;
        char       *strtok_arg;
 
-       memset(ci, 0, sizeof(ConnInfo));
-#ifdef DRIVER_CURSOR_IMPLEMENT
-       ci->updatable_cursors = 1;
-#endif   /* DRIVER_CURSOR_IMPLEMENT */
+       CC_conninfo_init(ci);
 
        our_connect_string = strdup(connect_string);
        strtok_arg = our_connect_string;
index 1113ca57ac6e18fd1efa7690954bdfedd17ec291..69718a1914974d33ac120ddcd48c905a2cb732c1 100644 (file)
@@ -78,408 +78,450 @@ PGAPI_FreeEnv(HENV henv)
 }
 
 
+#define        DRVMNGRDIV      511
 /*             Returns the next SQL error information. */
 RETCODE                SQL_API
-PGAPI_Error(
-                       HENV henv,
-                       HDBC hdbc,
-                       HSTMT hstmt,
+PGAPI_StmtError(       HSTMT hstmt,
+                       SWORD   RecNumber,
                        UCHAR FAR * szSqlState,
                        SDWORD FAR * pfNativeError,
                        UCHAR FAR * szErrorMsg,
                        SWORD cbErrorMsgMax,
-                       SWORD FAR * pcbErrorMsg)
+                       SWORD FAR * pcbErrorMsg,
+                       UWORD flag)
 {
-       char       *msg;
-       int                     status;
-       BOOL            once_again = FALSE;
-       SWORD           msglen;
+       /* CC: return an error of a hstmt  */
+       StatementClass *stmt = (StatementClass *) hstmt;
+       char            *msg;
+       int             status;
+       BOOL            once_again = FALSE,
+                       partial_ok = (flag & PODBC_ALLOW_PARTIAL_EXTRACT != 0),
+                       clear_str = (flag & PODBC_ERROR_CLEAR != 0);
+       SWORD           msglen, stapos, wrtlen, pcblen;
 
-       mylog("**** PGAPI_Error: henv=%u, hdbc=%u, hstmt=%u <%d>\n", henv, hdbc, hstmt, cbErrorMsgMax);
+       mylog("**** PGAPI_StmtError: hstmt=%u <%d>\n", hstmt, cbErrorMsgMax);
 
        if (cbErrorMsgMax < 0)
                return SQL_ERROR;
-       if (SQL_NULL_HSTMT != hstmt)
-       {
-               /* CC: return an error of a hstmt  */
-               StatementClass *stmt = (StatementClass *) hstmt;
 
-               if (SC_get_error(stmt, &status, &msg))
-               {
-                       mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg);
-                       if (NULL == msg)
-                       {
-                               if (NULL != szSqlState)
-                                       strcpy(szSqlState, "00000");
-                               if (NULL != pcbErrorMsg)
-                                       *pcbErrorMsg = 0;
-                               if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
-                                       szErrorMsg[0] = '\0';
-
-                               return SQL_NO_DATA_FOUND;
-                       }
-                       msglen = (SWORD) strlen(msg);
-                       if (NULL != pcbErrorMsg)
-                       {
-                               *pcbErrorMsg = msglen;
-                               if (cbErrorMsgMax == 0)
-                                       once_again = TRUE;
-                               else if (msglen >= cbErrorMsgMax)
-                               {
-                                       once_again = TRUE;
-                                       *pcbErrorMsg = cbErrorMsgMax - 1;
-                               }
-                       }
-
-                       if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
-                               strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
-
-                       if (NULL != pfNativeError)
-                               *pfNativeError = status;
-
-                       if (NULL != szSqlState)
-
-                               switch (status)
-                               {
-                                               /* now determine the SQLSTATE to be returned */
-                                       case STMT_ROW_VERSION_CHANGED:
-                                               strcpy(szSqlState, "01001");
-                                               /* data truncated */
-                                               break;
-                                       case STMT_TRUNCATED:
-                                               strcpy(szSqlState, "01004");
-                                               /* data truncated */
-                                               break;
-                                       case STMT_INFO_ONLY:
-                                               strcpy(szSqlState, "00000");
-                                               /* just information that is returned, no error */
-                                               break;
-                                       case STMT_BAD_ERROR:
-                                               strcpy(szSqlState, "08S01");
-                                               /* communication link failure */
-                                               break;
-                                       case STMT_CREATE_TABLE_ERROR:
-                                               strcpy(szSqlState, "S0001");
-                                               /* table already exists */
-                                               break;
-                                       case STMT_STATUS_ERROR:
-                                       case STMT_SEQUENCE_ERROR:
-                                               strcpy(szSqlState, "S1010");
-                                               /* Function sequence error */
-                                               break;
-                                       case STMT_NO_MEMORY_ERROR:
-                                               strcpy(szSqlState, "S1001");
-                                               /* memory allocation failure */
-                                               break;
-                                       case STMT_COLNUM_ERROR:
-                                               strcpy(szSqlState, "S1002");
-                                               /* invalid column number */
-                                               break;
-                                       case STMT_NO_STMTSTRING:
-                                               strcpy(szSqlState, "S1001");
-                                               /* having no stmtstring is also a malloc problem */
-                                               break;
-                                       case STMT_ERROR_TAKEN_FROM_BACKEND:
-                                               strcpy(szSqlState, "S1000");
-                                               /* general error */
-                                               break;
-                                       case STMT_INTERNAL_ERROR:
-                                               strcpy(szSqlState, "S1000");
-                                               /* general error */
-                                               break;
-                                       case STMT_ROW_OUT_OF_RANGE:
-                                               strcpy(szSqlState, "S1107");
-                                               break;
-
-                                       case STMT_OPERATION_CANCELLED:
-                                               strcpy(szSqlState, "S1008");
-                                               break;
-
-                                       case STMT_NOT_IMPLEMENTED_ERROR:
-                                               strcpy(szSqlState, "S1C00");    /* == 'driver not
-                                                                                                                * capable' */
-                                               break;
-                                       case STMT_OPTION_OUT_OF_RANGE_ERROR:
-                                               strcpy(szSqlState, "S1092");
-                                               break;
-                                       case STMT_BAD_PARAMETER_NUMBER_ERROR:
-                                               strcpy(szSqlState, "S1093");
-                                               break;
-                                       case STMT_INVALID_COLUMN_NUMBER_ERROR:
-                                               strcpy(szSqlState, "S1002");
-                                               break;
-                                       case STMT_RESTRICTED_DATA_TYPE_ERROR:
-                                               strcpy(szSqlState, "07006");
-                                               break;
-                                       case STMT_INVALID_CURSOR_STATE_ERROR:
-                                               strcpy(szSqlState, "24000");
-                                               break;
-                                       case STMT_OPTION_VALUE_CHANGED:
-                                               strcpy(szSqlState, "01S02");
-                                               break;
-                                       case STMT_POS_BEFORE_RECORDSET:
-                                               strcpy(szSqlState, "01S06");
-                                               break;
-                                       case STMT_INVALID_CURSOR_NAME:
-                                               strcpy(szSqlState, "34000");
-                                               break;
-                                       case STMT_NO_CURSOR_NAME:
-                                               strcpy(szSqlState, "S1015");
-                                               break;
-                                       case STMT_INVALID_ARGUMENT_NO:
-                                               strcpy(szSqlState, "S1009");
-                                               /* invalid argument value */
-                                               break;
-                                       case STMT_INVALID_CURSOR_POSITION:
-                                               strcpy(szSqlState, "S1109");
-                                               break;
-                                       case STMT_RETURN_NULL_WITHOUT_INDICATOR:
-                                               strcpy(szSqlState, "22002");
-                                               break;
-                                       case STMT_VALUE_OUT_OF_RANGE:
-                                               strcpy(szSqlState, "22003");
-                                               break;
-                                       case STMT_OPERATION_INVALID:
-                                               strcpy(szSqlState, "S1011");
-                                               break;
-                                       case STMT_INVALID_OPTION_IDENTIFIER:
-                                               strcpy(szSqlState, "HY092");
-                                               break;
-                                       case STMT_EXEC_ERROR:
-                                       default:
-                                               strcpy(szSqlState, "S1000");
-                                               /* also a general error */
-                                               break;
-                               }
-                       mylog("       szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg);
-               }
+       if (!SC_get_error(stmt, &status, &msg) || NULL == msg || !msg[0])
+       {
+               mylog("SC_Get_error returned nothing.\n");
+               if (NULL != szSqlState)
+                       strcpy(szSqlState, "00000");
+               if (NULL != pcbErrorMsg)
+                       *pcbErrorMsg = 0;
+               if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
+                       szErrorMsg[0] = '\0';
+
+               return SQL_NO_DATA_FOUND;
+       }
+       mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg);
+       msglen = (SWORD) strlen(msg);
+       /*
+        *      Even though an application specifies a larger error message
+        *      buffer, the driver manager changes it silently.
+        *      Therefore we divide the error message into ... 
+        */
+       if (stmt->error_recsize < 0)
+       {
+               if (cbErrorMsgMax > 0)
+                       stmt->error_recsize = cbErrorMsgMax - 1; /* apply the first request */
                else
-               {
-                       if (NULL != szSqlState)
-                               strcpy(szSqlState, "00000");
-                       if (NULL != pcbErrorMsg)
-                               *pcbErrorMsg = 0;
-                       if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
-                               szErrorMsg[0] = '\0';
+                       stmt->error_recsize = DRVMNGRDIV;
+       }
+       if (RecNumber < 0)
+       {
+               if (0 == stmt->errorpos)
+                       RecNumber = 1;
+               else
+                       RecNumber = 2 + (stmt->errorpos - 1) / stmt->error_recsize;
+       }
+       stapos = (RecNumber - 1) * stmt->error_recsize;
+       if (stapos > msglen)
+               return SQL_NO_DATA_FOUND; 
+       pcblen = wrtlen = msglen - stapos;
+       if (pcblen > stmt->error_recsize)
+               pcblen = stmt->error_recsize;
+       if (0 == cbErrorMsgMax)
+               wrtlen = 0; 
+       else if (wrtlen >= cbErrorMsgMax)
+       {
+               if (partial_ok)
+                       wrtlen = cbErrorMsgMax - 1;
+               else if (cbErrorMsgMax <= stmt->error_recsize)
+                       wrtlen = 0;
+               else 
+                       wrtlen = stmt->error_recsize;
+       }
+       if (wrtlen > pcblen)
+               wrtlen = pcblen;
+       if (NULL != pcbErrorMsg)
+               *pcbErrorMsg = pcblen;
 
-                       mylog("       returning NO_DATA_FOUND\n");
+       if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
+       {
+               memcpy(szErrorMsg, msg + stapos, wrtlen);
+               szErrorMsg[wrtlen] = '\0';
+       }
 
-                       return SQL_NO_DATA_FOUND;
-               }
+       if (NULL != pfNativeError)
+               *pfNativeError = status;
+
+       if (NULL != szSqlState)
 
-               if (once_again)
+               switch (status)
                {
-                       int                     outlen;
-
-                       stmt->errornumber = status;
-                       if (cbErrorMsgMax > 0)
-                               outlen = *pcbErrorMsg;
-                       else
-                               outlen = 0;
-                       if (!stmt->errormsg_malloced || !stmt->errormsg)
-                       {
-                               stmt->errormsg = malloc(msglen - outlen + 1);
-                               stmt->errormsg_malloced = TRUE;
-                       }
-                       memmove(stmt->errormsg, msg + outlen, msglen - outlen + 1);
+                               /* now determine the SQLSTATE to be returned */
+                       case STMT_ROW_VERSION_CHANGED:
+                               strcpy(szSqlState, "01001");
+                               /* data truncated */
+                               break;
+                       case STMT_TRUNCATED:
+                               strcpy(szSqlState, "01004");
+                               /* data truncated */
+                               break;
+                       case STMT_INFO_ONLY:
+                               strcpy(szSqlState, "00000");
+                               /* just information that is returned, no error */
+                               break;
+                       case STMT_BAD_ERROR:
+                               strcpy(szSqlState, "08S01");
+                               /* communication link failure */
+                               break;
+                       case STMT_CREATE_TABLE_ERROR:
+                               strcpy(szSqlState, "S0001");
+                               /* table already exists */
+                               break;
+                       case STMT_STATUS_ERROR:
+                       case STMT_SEQUENCE_ERROR:
+                               strcpy(szSqlState, "S1010");
+                               /* Function sequence error */
+                               break;
+                       case STMT_NO_MEMORY_ERROR:
+                               strcpy(szSqlState, "S1001");
+                               /* memory allocation failure */
+                               break;
+                       case STMT_COLNUM_ERROR:
+                               strcpy(szSqlState, "S1002");
+                               /* invalid column number */
+                               break;
+                       case STMT_NO_STMTSTRING:
+                               strcpy(szSqlState, "S1001");
+                               /* having no stmtstring is also a malloc problem */
+                               break;
+                       case STMT_ERROR_TAKEN_FROM_BACKEND:
+                               strcpy(szSqlState, "S1000");
+                               /* general error */
+                               break;
+                       case STMT_INTERNAL_ERROR:
+                               strcpy(szSqlState, "S1000");
+                               /* general error */
+                               break;
+                       case STMT_ROW_OUT_OF_RANGE:
+                               strcpy(szSqlState, "S1107");
+                               break;
+
+                       case STMT_OPERATION_CANCELLED:
+                               strcpy(szSqlState, "S1008");
+                               break;
+
+                       case STMT_NOT_IMPLEMENTED_ERROR:
+                               strcpy(szSqlState, "S1C00");    /* == 'driver not
+                                                                                                        * capable' */
+                               break;
+                       case STMT_OPTION_OUT_OF_RANGE_ERROR:
+                               strcpy(szSqlState, "S1092");
+                               break;
+                       case STMT_BAD_PARAMETER_NUMBER_ERROR:
+                               strcpy(szSqlState, "S1093");
+                               break;
+                       case STMT_INVALID_COLUMN_NUMBER_ERROR:
+                               strcpy(szSqlState, "S1002");
+                               break;
+                       case STMT_RESTRICTED_DATA_TYPE_ERROR:
+                               strcpy(szSqlState, "07006");
+                               break;
+                       case STMT_INVALID_CURSOR_STATE_ERROR:
+                               strcpy(szSqlState, "24000");
+                               break;
+                       case STMT_OPTION_VALUE_CHANGED:
+                               strcpy(szSqlState, "01S02");
+                               break;
+                       case STMT_POS_BEFORE_RECORDSET:
+                               strcpy(szSqlState, "01S06");
+                               break;
+                       case STMT_INVALID_CURSOR_NAME:
+                               strcpy(szSqlState, "34000");
+                               break;
+                       case STMT_NO_CURSOR_NAME:
+                               strcpy(szSqlState, "S1015");
+                               break;
+                       case STMT_INVALID_ARGUMENT_NO:
+                               strcpy(szSqlState, "S1009");
+                               /* invalid argument value */
+                               break;
+                       case STMT_INVALID_CURSOR_POSITION:
+                               strcpy(szSqlState, "S1109");
+                               break;
+                       case STMT_RETURN_NULL_WITHOUT_INDICATOR:
+                               strcpy(szSqlState, "22002");
+                               break;
+                       case STMT_VALUE_OUT_OF_RANGE:
+                               strcpy(szSqlState, "22003");
+                               break;
+                       case STMT_OPERATION_INVALID:
+                               strcpy(szSqlState, "S1011");
+                               break;
+                       case STMT_INVALID_OPTION_IDENTIFIER:
+                               strcpy(szSqlState, "HY092");
+                               break;
+                       case STMT_EXEC_ERROR:
+                       default:
+                               strcpy(szSqlState, "S1000");
+                               /* also a general error */
+                               break;
                }
-               else if (stmt->errormsg_malloced)
+       mylog("      szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, pcblen, szErrorMsg);
+       if (clear_str)
+       {
+               stmt->errorpos = stapos + wrtlen;
+               if (stmt->errorpos >= msglen)
                        SC_clear_error(stmt);
-               if (cbErrorMsgMax == 0)
-                       return SQL_SUCCESS_WITH_INFO;
-               else
-                       return SQL_SUCCESS;
        }
-       else if (SQL_NULL_HDBC != hdbc)
-       {
-               ConnectionClass *conn = (ConnectionClass *) hdbc;
-
-               mylog("calling CC_get_error\n");
-               if (CC_get_error(conn, &status, &msg))
-               {
-                       mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg);
-                       if (NULL == msg)
-                       {
-                               if (NULL != szSqlState)
-                                       strcpy(szSqlState, "00000");
-                               if (NULL != pcbErrorMsg)
-                                       *pcbErrorMsg = 0;
-                               if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
-                                       szErrorMsg[0] = '\0';
-
-                               return SQL_NO_DATA_FOUND;
-                       }
-
-                       msglen = strlen(msg);
-                       if (NULL != pcbErrorMsg)
-                       {
-                               *pcbErrorMsg = msglen;
-                               if (cbErrorMsgMax == 0)
-                                       once_again = TRUE;
-                               else if (msglen >= cbErrorMsgMax)
-                                       *pcbErrorMsg = cbErrorMsgMax - 1;
-                       }
-                       if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
-                               strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
-                       if (NULL != pfNativeError)
-                               *pfNativeError = status;
-
-                       if (NULL != szSqlState)
-                               switch (status)
-                               {
-                                       case STMT_OPTION_VALUE_CHANGED:
-                                       case CONN_OPTION_VALUE_CHANGED:
-                                               strcpy(szSqlState, "01S02");
-                                               break;
-                                       case STMT_TRUNCATED:
-                                       case CONN_TRUNCATED:
-                                               strcpy(szSqlState, "01004");
-                                               /* data truncated */
-                                               break;
-                                       case CONN_INIREAD_ERROR:
-                                               strcpy(szSqlState, "IM002");
-                                               /* data source not found */
-                                               break;
-                                       case CONN_OPENDB_ERROR:
-                                               strcpy(szSqlState, "08001");
-                                               /* unable to connect to data source */
-                                               break;
-                                       case CONN_INVALID_AUTHENTICATION:
-                                       case CONN_AUTH_TYPE_UNSUPPORTED:
-                                               strcpy(szSqlState, "28000");
-                                               break;
-                                       case CONN_STMT_ALLOC_ERROR:
-                                               strcpy(szSqlState, "S1001");
-                                               /* memory allocation failure */
-                                               break;
-                                       case CONN_IN_USE:
-                                               strcpy(szSqlState, "S1000");
-                                               /* general error */
-                                               break;
-                                       case CONN_UNSUPPORTED_OPTION:
-                                               strcpy(szSqlState, "IM001");
-                                               /* driver does not support this function */
-                                       case CONN_INVALID_ARGUMENT_NO:
-                                               strcpy(szSqlState, "S1009");
-                                               /* invalid argument value */
-                                               break;
-                                       case CONN_TRANSACT_IN_PROGRES:
-                                               strcpy(szSqlState, "S1010");
-
-                                               /*
-                                                * when the user tries to switch commit mode in a
-                                                * transaction
-                                                */
-                                               /* -> function sequence error */
-                                               break;
-                                       case CONN_NO_MEMORY_ERROR:
-                                               strcpy(szSqlState, "S1001");
-                                               break;
-                                       case CONN_NOT_IMPLEMENTED_ERROR:
-                                       case STMT_NOT_IMPLEMENTED_ERROR:
-                                               strcpy(szSqlState, "S1C00");
-                                               break;
-                                       case STMT_RETURN_NULL_WITHOUT_INDICATOR:
-                                               strcpy(szSqlState, "22002");
-                                               break;
-                                       case CONN_VALUE_OUT_OF_RANGE:
-                                       case STMT_VALUE_OUT_OF_RANGE:
-                                               strcpy(szSqlState, "22003");
-                                               break;
-                                       default:
-                                               strcpy(szSqlState, "S1000");
-                                               /* general error */
-                                               break;
-                               }
-               }
-               else
-               {
-                       mylog("CC_Get_error returned nothing.\n");
-                       if (NULL != szSqlState)
-                               strcpy(szSqlState, "00000");
-                       if (NULL != pcbErrorMsg)
-                               *pcbErrorMsg = 0;
-                       if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
-                               szErrorMsg[0] = '\0';
+       if (wrtlen == 0)
+               return SQL_SUCCESS_WITH_INFO;
+       else
+               return SQL_SUCCESS;
+}
 
-                       return SQL_NO_DATA_FOUND;
-               }
+RETCODE                SQL_API
+PGAPI_ConnectError(    HDBC hdbc,
+                       SWORD   RecNumber,
+                       UCHAR FAR * szSqlState,
+                       SDWORD FAR * pfNativeError,
+                       UCHAR FAR * szErrorMsg,
+                       SWORD cbErrorMsgMax,
+                       SWORD FAR * pcbErrorMsg,
+                       UWORD flag)
+{
+       ConnectionClass *conn = (ConnectionClass *) hdbc;
+       char            *msg;
+       int             status;
+       BOOL    once_again = FALSE;
+       SWORD           msglen;
 
-               if (once_again)
-               {
-                       conn->errornumber = status;
-                       return SQL_SUCCESS_WITH_INFO;
-               }
-               else
-                       return SQL_SUCCESS;
+       if (RecNumber != 1)
+               return SQL_NO_DATA_FOUND;
+       if (cbErrorMsgMax < 0)
+               return SQL_ERROR;
+       if (!CC_get_error(conn, &status, &msg) || NULL == msg)
+       {
+               mylog("CC_Get_error returned nothing.\n");
+               if (NULL != szSqlState)
+                       strcpy(szSqlState, "00000");
+               if (NULL != pcbErrorMsg)
+                       *pcbErrorMsg = 0;
+               if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
+                       szErrorMsg[0] = '\0';
+
+               return SQL_NO_DATA_FOUND;
        }
-       else if (SQL_NULL_HENV != henv)
+       mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg);
+
+       msglen = strlen(msg);
+       if (NULL != pcbErrorMsg)
        {
-               EnvironmentClass *env = (EnvironmentClass *) henv;
+               *pcbErrorMsg = msglen;
+               if (cbErrorMsgMax == 0)
+                       once_again = TRUE;
+               else if (msglen >= cbErrorMsgMax)
+                       *pcbErrorMsg = cbErrorMsgMax - 1;
+       }
+       if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
+               strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
+       if (NULL != pfNativeError)
+               *pfNativeError = status;
 
-               if (EN_get_error(env, &status, &msg))
-               {
-                       mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
-                       if (NULL == msg)
-                       {
-                               if (NULL != szSqlState)
-                                       strcpy(szSqlState, "00000");
-                               if (NULL != pcbErrorMsg)
-                                       *pcbErrorMsg = 0;
-                               if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
-                                       szErrorMsg[0] = '\0';
-
-                               return SQL_NO_DATA_FOUND;
-                       }
-
-                       if (NULL != pcbErrorMsg)
-                               *pcbErrorMsg = (SWORD) strlen(msg);
-                       if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
-                               strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
-                       if (NULL != pfNativeError)
-                               *pfNativeError = status;
-
-                       if (szSqlState)
-                       {
-                               switch (status)
-                               {
-                                       case ENV_ALLOC_ERROR:
-                                               /* memory allocation failure */
-                                               strcpy(szSqlState, "S1001");
-                                               break;
-                                       default:
-                                               strcpy(szSqlState, "S1000");
-                                               /* general error */
-                                               break;
-                               }
-                       }
-               }
-               else
+       if (NULL != szSqlState)
+               switch (status)
                {
-                       if (NULL != szSqlState)
-                               strcpy(szSqlState, "00000");
-                       if (NULL != pcbErrorMsg)
-                               *pcbErrorMsg = 0;
-                       if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
-                               szErrorMsg[0] = '\0';
-
-                       return SQL_NO_DATA_FOUND;
+                       case STMT_OPTION_VALUE_CHANGED:
+                       case CONN_OPTION_VALUE_CHANGED:
+                               strcpy(szSqlState, "01S02");
+                               break;
+                       case STMT_TRUNCATED:
+                       case CONN_TRUNCATED:
+                               strcpy(szSqlState, "01004");
+                               /* data truncated */
+                               break;
+                       case CONN_INIREAD_ERROR:
+                               strcpy(szSqlState, "IM002");
+                               /* data source not found */
+                               break;
+                       case CONN_OPENDB_ERROR:
+                               strcpy(szSqlState, "08001");
+                               /* unable to connect to data source */
+                               break;
+                       case CONN_INVALID_AUTHENTICATION:
+                       case CONN_AUTH_TYPE_UNSUPPORTED:
+                               strcpy(szSqlState, "28000");
+                               break;
+                       case CONN_STMT_ALLOC_ERROR:
+                               strcpy(szSqlState, "S1001");
+                               /* memory allocation failure */
+                               break;
+                       case CONN_IN_USE:
+                               strcpy(szSqlState, "S1000");
+                               /* general error */
+                               break;
+                       case CONN_UNSUPPORTED_OPTION:
+                               strcpy(szSqlState, "IM001");
+                               /* driver does not support this function */
+                       case CONN_INVALID_ARGUMENT_NO:
+                               strcpy(szSqlState, "S1009");
+                               /* invalid argument value */
+                               break;
+                       case CONN_TRANSACT_IN_PROGRES:
+                               strcpy(szSqlState, "S1010");
+
+                               /*
+                                * when the user tries to switch commit mode in a
+                                * transaction
+                                */
+                               /* -> function sequence error */
+                               break;
+                       case CONN_NO_MEMORY_ERROR:
+                               strcpy(szSqlState, "S1001");
+                               break;
+                       case CONN_NOT_IMPLEMENTED_ERROR:
+                       case STMT_NOT_IMPLEMENTED_ERROR:
+                               strcpy(szSqlState, "S1C00");
+                               break;
+                       case STMT_RETURN_NULL_WITHOUT_INDICATOR:
+                               strcpy(szSqlState, "22002");
+                               break;
+                       case CONN_VALUE_OUT_OF_RANGE:
+                       case STMT_VALUE_OUT_OF_RANGE:
+                               strcpy(szSqlState, "22003");
+                               break;
+                       default:
+                               strcpy(szSqlState, "S1000");
+                               /* general error */
+                               break;
                }
 
+       if (once_again)
+       {
+               conn->errornumber = status;
+               return SQL_SUCCESS_WITH_INFO;
+       }
+       else
                return SQL_SUCCESS;
+}
+
+RETCODE                SQL_API
+PGAPI_EnvError(                HENV henv,
+                       SWORD   RecNumber,
+                       UCHAR FAR * szSqlState,
+                       SDWORD FAR * pfNativeError,
+                       UCHAR FAR * szErrorMsg,
+                       SWORD cbErrorMsgMax,
+                       SWORD FAR * pcbErrorMsg,
+                       UWORD flag)
+{
+       EnvironmentClass *env = (EnvironmentClass *) henv;
+       char            *msg;
+       int             status;
+
+       if (RecNumber != 1)
+               return SQL_NO_DATA_FOUND;
+       if (cbErrorMsgMax < 0)
+               return SQL_ERROR;
+       if (!EN_get_error(env, &status, &msg) || NULL == msg)
+       {
+                       mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
+               
+               if (NULL != szSqlState)
+                       strcpy(szSqlState, "00000");
+               if (NULL != pcbErrorMsg)
+                       *pcbErrorMsg = 0;
+               if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
+                       szErrorMsg[0] = '\0';
+
+               return SQL_NO_DATA_FOUND;
        }
+       mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
 
-       if (NULL != szSqlState)
-               strcpy(szSqlState, "00000");
        if (NULL != pcbErrorMsg)
-               *pcbErrorMsg = 0;
+               *pcbErrorMsg = (SWORD) strlen(msg);
        if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
-               szErrorMsg[0] = '\0';
+               strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
+       if (NULL != pfNativeError)
+               *pfNativeError = status;
 
-       return SQL_NO_DATA_FOUND;
+       if (szSqlState)
+       {
+               switch (status)
+               {
+                       case ENV_ALLOC_ERROR:
+                               /* memory allocation failure */
+                               strcpy(szSqlState, "S1001");
+                               break;
+                       default:
+                               strcpy(szSqlState, "S1000");
+                               /* general error */
+                               break;
+               }
+       }
+
+       return SQL_SUCCESS;
 }
 
 
+/*             Returns the next SQL error information. */
+RETCODE                SQL_API
+PGAPI_Error(
+                       HENV henv,
+                       HDBC hdbc,
+                       HSTMT hstmt,
+                       UCHAR FAR * szSqlState,
+                       SDWORD FAR * pfNativeError,
+                       UCHAR FAR * szErrorMsg,
+                       SWORD cbErrorMsgMax,
+                       SWORD FAR * pcbErrorMsg)
+{
+       RETCODE ret;
+       UWORD   flag = PODBC_ALLOW_PARTIAL_EXTRACT | PODBC_ERROR_CLEAR;
+
+       mylog("**** PGAPI_Error: henv=%u, hdbc=%u hstmt=%d\n", henv, hdbc, hstmt);
+
+       if (cbErrorMsgMax < 0)
+               return SQL_ERROR;
+       if (SQL_NULL_HSTMT != hstmt)
+               ret = PGAPI_StmtError(hstmt, -1, szSqlState, pfNativeError,
+                        szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
+       else if (SQL_NULL_HDBC != hdbc)
+               ret = PGAPI_ConnectError(hdbc, -1, szSqlState, pfNativeError,
+                        szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
+       else if (SQL_NULL_HENV != hdbc)
+               ret = PGAPI_EnvError(henv, -1, szSqlState, pfNativeError,
+                        szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
+       else
+       {
+               if (NULL != szSqlState)
+                       strcpy(szSqlState, "00000");
+               if (NULL != pcbErrorMsg)
+                       *pcbErrorMsg = 0;
+               if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
+                       szErrorMsg[0] = '\0';
+
+               ret = SQL_NO_DATA_FOUND;
+       }
+       mylog("**** PGAPI_Error exit code=%d\n", ret);
+       return ret;
+}
+
 /*
  * EnvironmentClass implementation
  */
@@ -493,6 +535,7 @@ EN_Constructor(void)
        {
                rv->errormsg = 0;
                rv->errornumber = 0;
+               rv->flag = 0;
        }
 
        return rv;
index 7b463b3e744e093804077c400062d2ed2e61e4c3..24b456d489915d9f479bb3f902d8f3bdf9d8bb61 100644 (file)
@@ -17,7 +17,8 @@
 struct EnvironmentClass_
 {
        char       *errormsg;
-       int                     errornumber;
+       int             errornumber;
+       Int4    flag;
 };
 
 /*     Environment prototypes */
@@ -28,4 +29,10 @@ char         EN_add_connection(EnvironmentClass *self, ConnectionClass *conn);
 char           EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn);
 void           EN_log_error(char *func, char *desc, EnvironmentClass *self);
 
+#define        EN_OV_ODBC2     1L
+#define        EN_is_odbc2(env) ((env->flag & EN_OV_ODBC2) != 0)
+#define        EN_is_odbc3(env) ((env->flag & EN_OV_ODBC2) == 0)
+#define EN_set_odbc2(env) (env->flag |= EN_OV_ODBC2)
+#define EN_set_odbc3(env) (env->flag &= EN_OV_ODBC2)
+
 #endif
index 4c6608923a47805db15c0e80f5b452601bda8fbf..ae095e9691e2698cf7051537ad80fa4eb0d80def 100644 (file)
@@ -267,6 +267,7 @@ PGAPI_Execute(
        if (stmt->status == STMT_FINISHED)
        {
                mylog("%s: recycling statement (should have been done by app)...\n", func);
+/******** Is this really NEEDED ? ******/
                SC_recycle_statement(stmt);
        }
 
@@ -291,6 +292,7 @@ PGAPI_Execute(
        {
                if (stmt->options.param_processed_ptr)
                        *stmt->options.param_processed_ptr = 0;
+               SC_recycle_statement(stmt);
        }
 
 next_param_row:
@@ -434,26 +436,24 @@ next_param_row:
                }
                /* we are now in a transaction */
                CC_set_in_trans(conn);
-               stmt->result = res = CC_send_query(conn, stmt->stmt_with_params, NULL);
-               if (!res || QR_aborted(res))
+               res = CC_send_query(conn, stmt->stmt_with_params, NULL, TRUE);
+               if (!res)
                {
                        CC_abort(conn);
                        stmt->errornumber = STMT_EXEC_ERROR;
                        stmt->errormsg = "Handle prepare error";
                        return SQL_ERROR;
                }
-               else
+               SC_set_Result(stmt, res);
+               if (CC_is_in_autocommit(conn))
                {
-                       if (CC_is_in_autocommit(conn))
-                       {
-                               if (issued_begin)
-                                       CC_commit(conn);
-                               else if (!in_trans && begin_included)
-                                       CC_set_no_trans(conn);
-                       }
-                       stmt->status = STMT_FINISHED;
-                       return SQL_SUCCESS;
+                       if (issued_begin)
+                               CC_commit(conn);
+                       else if (!in_trans && begin_included)
+                               CC_set_no_trans(conn);
                }
+               stmt->status = STMT_FINISHED;
+               return SQL_SUCCESS;
        }
        else
                return SQL_SUCCESS;
@@ -518,7 +518,7 @@ PGAPI_Transact(
        {
                mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string);
 
-               res = CC_send_query(conn, stmt_string, NULL);
+               res = CC_send_query(conn, stmt_string, NULL, TRUE);
                CC_set_no_trans(conn);
 
                if (!res)
@@ -721,7 +721,7 @@ PGAPI_ParamData(
                /* commit transaction if needed */
                if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
                {
-                       if (!CC_commit(stmt->hdbc))
+                       if (CC_commit(stmt->hdbc))
                        {
                                stmt->errormsg = "Could not commit (in-line) a transaction";
                                stmt->errornumber = STMT_EXEC_ERROR;
@@ -902,6 +902,14 @@ PGAPI_PutData(
                }
                else
                {
+                       Int2            ctype = current_param->CType;
+                       if (ctype == SQL_C_DEFAULT)
+                               ctype = sqltype_to_default_ctype(current_param->SQLType);
+
+#ifdef UNICODE_SUPPORT
+                       if (SQL_NTS == cbValue && SQL_C_WCHAR == ctype)
+                               cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
+#endif /* UNICODE_SUPPORT */
                        /* for handling fields */
                        if (cbValue == SQL_NTS)
                        {
@@ -916,11 +924,11 @@ PGAPI_PutData(
                        }
                        else
                        {
-                               Int2            ctype = current_param->CType;
-
-                               if (ctype == SQL_C_DEFAULT)
-                                       ctype = sqltype_to_default_ctype(current_param->SQLType);
+#ifdef UNICODE_SUPPORT
+                               if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
+#else
                                if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
+#endif /* UNICODE_SUPPORT */
                                {
                                        current_param->EXEC_buffer = malloc(cbValue + 1);
                                        if (!current_param->EXEC_buffer)
@@ -965,31 +973,31 @@ PGAPI_PutData(
                }
                else
                {
-                       buffer = current_param->EXEC_buffer;
+                       Int2    ctype = current_param->CType;
 
-                       if (cbValue == SQL_NTS)
+                       if (ctype == SQL_C_DEFAULT)
+                               ctype = sqltype_to_default_ctype(current_param->SQLType);
+                       buffer = current_param->EXEC_buffer;
+                       if (old_pos = *current_param->EXEC_used, SQL_NTS == old_pos)
                        {
-                               buffer = realloc(buffer, strlen(buffer) + strlen(rgbValue) + 1);
-                               if (!buffer)
-                               {
-                                       stmt->errornumber = STMT_NO_MEMORY_ERROR;
-                                       stmt->errormsg = "Out of memory in PGAPI_PutData (3)";
-                                       SC_log_error(func, "", stmt);
-                                       return SQL_ERROR;
-                               }
-                               strcat(buffer, rgbValue);
-
-                               mylog("       cbValue = SQL_NTS: strlen(buffer) = %d\n", strlen(buffer));
-
-                               *current_param->EXEC_used = cbValue;
-
-                               /* reassign buffer incase realloc moved it */
-                               current_param->EXEC_buffer = buffer;
+#ifdef UNICODE_SUPPORT
+                               if (SQL_C_WCHAR == ctype)
+                                       old_pos = 2 * ucs2strlen((SQLWCHAR *) buffer);
+                               else
+#endif /* UNICODE_SUPPORT */
+                               old_pos = strlen(buffer);
                        }
-                       else if (cbValue > 0)
+                       if (SQL_NTS == cbValue)
+                       {
+#ifdef UNICODE_SUPPORT
+                               if (SQL_C_WCHAR == ctype)
+                                       cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
+                               else
+#endif /* UNICODE_SUPPORT */
+                               cbValue = strlen(rgbValue);
+                       }
+                       if (cbValue > 0)
                        {
-                               old_pos = *current_param->EXEC_used;
-
                                *current_param->EXEC_used += cbValue;
 
                                mylog("        cbValue = %d, old_pos = %d, *used = %d\n", cbValue, old_pos, *current_param->EXEC_used);
index d4fda3670b66cda52e67764a07135bff9283c019..fc5dcef34152a309d7b1eaddb45953c3fb3df315 100644 (file)
@@ -10,7 +10,7 @@
  *                                     SQLTables, SQLColumns, SQLStatistics, SQLSpecialColumns,
  *                                     SQLPrimaryKeys, SQLForeignKeys,
  *                                     SQLProcedureColumns(NI), SQLProcedures,
- *                                     SQLTablePrivileges(NI), SQLColumnPrivileges(NI)
+ *                                     SQLTablePrivileges, SQLColumnPrivileges(NI)
  *
  * Comments:           See "notice.txt" for copyright and license information.
  *--------
@@ -231,13 +231,14 @@ PGAPI_GetInfo(
 
                case SQL_FETCH_DIRECTION:               /* ODBC 1.0 */
                        len = 4;
-                       value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) : (SQL_FD_FETCH_NEXT |
-                                                                                                        SQL_FD_FETCH_FIRST |
-                                                                                                         SQL_FD_FETCH_LAST |
-                                                                                                        SQL_FD_FETCH_PRIOR |
-                                                                                                 SQL_FD_FETCH_ABSOLUTE |
-                                                                                                 SQL_FD_FETCH_RELATIVE |
-                                                                                                 SQL_FD_FETCH_BOOKMARK);
+                       value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) :
+                        (SQL_FD_FETCH_NEXT | 
+                        SQL_FD_FETCH_FIRST |
+                        SQL_FD_FETCH_LAST |
+                        SQL_FD_FETCH_PRIOR |
+                        SQL_FD_FETCH_ABSOLUTE |
+                        SQL_FD_FETCH_RELATIVE |
+                        SQL_FD_FETCH_BOOKMARK);
                        break;
 
                case SQL_FILE_USAGE:    /* ODBC 2.0 */
@@ -665,7 +666,6 @@ PGAPI_GetInfo(
                        /* unrecognized key */
                        conn->errormsg = "Unrecognized key passed to PGAPI_GetInfo.";
                        conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
-                       CC_log_error(func, "", conn);
                        return SQL_ERROR;
        }
 
@@ -685,12 +685,20 @@ PGAPI_GetInfo(
 
                if (rgbInfoValue)
                {
+#ifdef UNICODE_SUPPORT
+                       if (conn->unicode)
+                       {
+                               len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / 2);
+                               len *= 2;
+                       }
+                       else
+#endif /* UNICODE_SUPPORT */
                        strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
 
                        if (len >= cbInfoValueMax)
                        {
                                result = SQL_SUCCESS_WITH_INFO;
-                               conn->errornumber = STMT_TRUNCATED;
+                               conn->errornumber = CONN_TRUNCATED;
                                conn->errormsg = "The buffer was too small for tthe InfoValue.";
                        }
                }
@@ -721,6 +729,7 @@ PGAPI_GetTypeInfo(
 {
        static char *func = "PGAPI_GetTypeInfo";
        StatementClass *stmt = (StatementClass *) hstmt;
+       QResultClass    *res;
        TupleNode  *row;
        int                     i;
 
@@ -737,31 +746,31 @@ PGAPI_GetTypeInfo(
        }
 
        stmt->manual_result = TRUE;
-       stmt->result = QR_Constructor();
-       if (!stmt->result)
+       if (res = QR_Constructor(), !res)
        {
                SC_log_error(func, "Error creating result.", stmt);
                return SQL_ERROR;
        }
+       SC_set_Result(stmt, res);
 
        extend_bindings(stmt, 15);
 
-       QR_set_num_fields(stmt->result, 15);
-       QR_set_field_info(stmt->result, 0, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 1, "DATA_TYPE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 2, "PRECISION", PG_TYPE_INT4, 4);
-       QR_set_field_info(stmt->result, 3, "LITERAL_PREFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 4, "LITERAL_SUFFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 5, "CREATE_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 6, "NULLABLE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 10, "MONEY", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 12, "LOCAL_TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
+       QR_set_num_fields(res, 15);
+       QR_set_field_info(res, 0, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 1, "DATA_TYPE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 2, "PRECISION", PG_TYPE_INT4, 4);
+       QR_set_field_info(res, 3, "LITERAL_PREFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 4, "LITERAL_SUFFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 5, "CREATE_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 6, "NULLABLE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 10, "MONEY", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 12, "LOCAL_TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
 
        for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i])
        {
@@ -795,7 +804,7 @@ PGAPI_GetTypeInfo(
                        set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType, PG_STATIC));
                        set_nullfield_int2(&row->tuple[14], pgtype_scale(stmt, pgType, PG_STATIC));
 
-                       QR_add_tuple(stmt->result, row);
+                       QR_add_tuple(res, row);
                }
        }
 
@@ -898,7 +907,7 @@ PGAPI_GetFunctions(
                        pfExists[SQL_API_SQLMORERESULTS] = TRUE;
                        pfExists[SQL_API_SQLNATIVESQL] = TRUE;
                        pfExists[SQL_API_SQLNUMPARAMS] = TRUE;
-                       pfExists[SQL_API_SQLPARAMOPTIONS] = FALSE;
+                       pfExists[SQL_API_SQLPARAMOPTIONS] = TRUE;
                        pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE;
                        pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
                        if (PG_VERSION_LT(conn, 6.5))
@@ -907,7 +916,7 @@ PGAPI_GetFunctions(
                                pfExists[SQL_API_SQLPROCEDURES] = TRUE;
                        pfExists[SQL_API_SQLSETPOS] = TRUE;
                        pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE;           /* odbc 1.0 */
-                       pfExists[SQL_API_SQLTABLEPRIVILEGES] = FALSE;
+                       pfExists[SQL_API_SQLTABLEPRIVILEGES] = TRUE;
                }
        }
        else
@@ -1070,7 +1079,7 @@ PGAPI_GetFunctions(
                                        *pfExists = TRUE;
                                        break;
                                case SQL_API_SQLPARAMOPTIONS:
-                                       *pfExists = FALSE;
+                                       *pfExists = TRUE;
                                        break;
                                case SQL_API_SQLPRIMARYKEYS:
                                        *pfExists = TRUE;
@@ -1091,7 +1100,7 @@ PGAPI_GetFunctions(
                                        *pfExists = TRUE;
                                        break;          /* odbc 1.0 */
                                case SQL_API_SQLTABLEPRIVILEGES:
-                                       *pfExists = FALSE;
+                                       *pfExists = TRUE;
                                        break;
                        }
                }
@@ -1115,6 +1124,7 @@ PGAPI_Tables(
        static char *func = "PGAPI_Tables";
        StatementClass *stmt = (StatementClass *) hstmt;
        StatementClass *tbl_stmt;
+       QResultClass    *res;
        TupleNode  *row;
        HSTMT           htbl_stmt;
        RETCODE         result;
@@ -1291,8 +1301,7 @@ PGAPI_Tables(
                return SQL_ERROR;
        }
 
-       stmt->result = QR_Constructor();
-       if (!stmt->result)
+       if (res = QR_Constructor(), !res)
        {
                stmt->errormsg = "Couldn't allocate memory for PGAPI_Tables result.";
                stmt->errornumber = STMT_NO_MEMORY_ERROR;
@@ -1300,6 +1309,7 @@ PGAPI_Tables(
                PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
                return SQL_ERROR;
        }
+       SC_set_Result(stmt, res);
 
        /* the binding structure for a statement is not set up until */
 
@@ -1310,12 +1320,12 @@ PGAPI_Tables(
        extend_bindings(stmt, 5);
 
        /* set the field names */
-       QR_set_num_fields(stmt->result, 5);
-       QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 3, "TABLE_TYPE", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 4, "REMARKS", PG_TYPE_TEXT, 254);
+       QR_set_num_fields(res, 5);
+       QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 3, "TABLE_TYPE", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 4, "REMARKS", PG_TYPE_TEXT, 254);
 
        /* add the tuples */
        result = PGAPI_Fetch(htbl_stmt);
@@ -1372,6 +1382,7 @@ PGAPI_Tables(
                        row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));
 
                        /*set_tuplefield_string(&row->tuple[0], "");*/
+                       /*set_tuplefield_string(&row->tuple[0], "cat0");*/
                        set_tuplefield_null(&row->tuple[0]);
 
                        /*
@@ -1389,9 +1400,10 @@ PGAPI_Tables(
                        set_tuplefield_null(&row->tuple[1]);
                        set_tuplefield_string(&row->tuple[2], table_name);
                        set_tuplefield_string(&row->tuple[3], systable ? "SYSTEM TABLE" : (view ? "VIEW" : "TABLE"));
-                       set_tuplefield_string(&row->tuple[4], "");
+                       /*set_tuplefield_string(&row->tuple[4], "");*/
+                       set_tuplefield_string(&row->tuple[4], "TABLE");
 
-                       QR_add_tuple(stmt->result, row);
+                       QR_add_tuple(res, row);
                }
                result = PGAPI_Fetch(htbl_stmt);
        }
@@ -1425,11 +1437,14 @@ PGAPI_Tables(
  *     PostgreSQL needs 2 '\\' to escape '_' and '%'. 
  */
 static int
-reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len)
+reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len, int ccsc)
 {
        int     i, outlen;
        const char *in;
        BOOL    escape_in = FALSE;
+#ifdef MULTIBYTE
+       encoded_str     encstr;
+#endif
 
        if (srclen == SQL_NULL_DATA)
        {
@@ -1441,12 +1456,13 @@ reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len)
        if (srclen <= 0)
                return STRCPY_FAIL;
 #ifdef MULTIBYTE
-       multibyte_init();
+       encoded_str_constr(&encstr, ccsc, src);
 #endif
        for (i = 0, in = src, outlen = 0; i < srclen && outlen < dst_len; i++, in++)
        {
 #ifdef MULTIBYTE
-                if (multibyte_char_check(*in) != 0)
+                encoded_nextchar(&encstr);
+                if (ENCODE_STATUS(encstr) != 0)
                 {
                         dest[outlen++] = *in;
                         continue;
@@ -1496,6 +1512,7 @@ PGAPI_Columns(
 {
        static char *func = "PGAPI_Columns";
        StatementClass *stmt = (StatementClass *) hstmt;
+       QResultClass    *res;
        TupleNode  *row;
        HSTMT           hcol_stmt;
        StatementClass *col_stmt;
@@ -1505,7 +1522,7 @@ PGAPI_Columns(
                                table_name[MAX_INFO_STRING],
                                field_name[MAX_INFO_STRING],
                                field_type_name[MAX_INFO_STRING];
-       Int2            field_number,
+       Int2            field_number, sqltype,
                                result_cols,
                                scale;
        Int4            field_type,
@@ -1556,7 +1573,7 @@ PGAPI_Columns(
                char    esc_table_name[MAX_TABLE_LEN * 2];
                int     escTbnamelen;
 
-               escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name));
+               escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name), conn->ccsc);
                my_strcat(columns_query, " and c.relname like '%.*s'", esc_table_name, escTbnamelen);
                my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
                my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName);
@@ -1701,8 +1718,7 @@ PGAPI_Columns(
                return SQL_ERROR;
        }
 
-       stmt->result = QR_Constructor();
-       if (!stmt->result)
+       if (res = QR_Constructor(), !res)
        {
                stmt->errormsg = "Couldn't allocate memory for PGAPI_Columns result.";
                stmt->errornumber = STMT_NO_MEMORY_ERROR;
@@ -1710,6 +1726,7 @@ PGAPI_Columns(
                PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
                return SQL_ERROR;
        }
+       SC_set_Result(stmt, res);
 
        /* the binding structure for a statement is not set up until */
 
@@ -1721,23 +1738,32 @@ PGAPI_Columns(
        extend_bindings(stmt, result_cols);
 
        /* set the field names */
-       QR_set_num_fields(stmt->result, result_cols);
-       QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4);
-       QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4);
-       QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254);
+       QR_set_num_fields(res, result_cols);
+       QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 6, "PRECISION", PG_TYPE_INT4, 4);
+       QR_set_field_info(res, 7, "LENGTH", PG_TYPE_INT4, 4);
+       QR_set_field_info(res, 8, "SCALE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 9, "RADIX", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 10, "NULLABLE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 11, "REMARKS", PG_TYPE_TEXT, 254);
 
        /* User defined fields */
-       QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
-       QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
+#if (ODBCVER >= 0x0300)
+       QR_set_field_info(res, 12, "COLUMN_DEF", PG_TYPE_INT4, 254);
+       QR_set_field_info(res, 13, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 14, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 15, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
+       QR_set_field_info(res, 16, "ORDINAL_POSITION", PG_TYPE_INT4, 4);
+       QR_set_field_info(res, 17, "IS_NULLABLE", PG_TYPE_TEXT, 254);
+#else
+       QR_set_field_info(res, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
+       QR_set_field_info(res, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
+#endif /* ODBCVER */
 
        result = PGAPI_Fetch(hcol_stmt);
 
@@ -1764,7 +1790,8 @@ PGAPI_Columns(
                        set_tuplefield_string(&row->tuple[1], "");
                        set_tuplefield_string(&row->tuple[2], table_name);
                        set_tuplefield_string(&row->tuple[3], "oid");
-                       set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, the_type));
+                       sqltype = pgtype_to_sqltype(stmt, the_type);
+                       set_tuplefield_int2(&row->tuple[4], sqltype);
                        set_tuplefield_string(&row->tuple[5], "OID");
 
                        set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC));
@@ -1775,10 +1802,14 @@ PGAPI_Columns(
                        set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
                        set_tuplefield_string(&row->tuple[11], "");
 
+#if (ODBCVER >= 0x0300)
+                       set_tuplefield_int2(&row->tuple[13], sqltype);
+#else
                        set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
                        set_tuplefield_int4(&row->tuple[13], the_type);
+#endif /* ODBCVER */
 
-                       QR_add_tuple(stmt->result, row);
+                       QR_add_tuple(res, row);
                }
        }
 
@@ -1794,7 +1825,8 @@ PGAPI_Columns(
                set_tuplefield_string(&row->tuple[1], "");
                set_tuplefield_string(&row->tuple[2], table_name);
                set_tuplefield_string(&row->tuple[3], field_name);
-               set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, field_type));
+               sqltype = pgtype_to_sqltype(stmt, field_type);
+               set_tuplefield_int2(&row->tuple[4], sqltype);
                set_tuplefield_string(&row->tuple[5], field_type_name);
 
 
@@ -1812,7 +1844,7 @@ PGAPI_Columns(
                 *----------
                 */
                qlog("PGAPI_Columns: table='%s',field_name='%s',type=%d,sqltype=%d,name='%s'\n",
-                        table_name, field_name, field_type, pgtype_to_sqltype(stmt,field_type), field_type_name);
+                        table_name, field_name, field_type, pgtype_to_sqltype, field_type_name);
 
                useStaticPrecision = TRUE;
 
@@ -1869,9 +1901,31 @@ PGAPI_Columns(
                set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type));
                set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type)));
                set_tuplefield_string(&row->tuple[11], "");
+#if (ODBCVER >= 0x0300)
+               switch (sqltype)
+               {
+                       case SQL_TYPE_DATE:
+                               set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
+                               set_tuplefield_int2(&row->tuple[14], SQL_CODE_DATE);
+                               break;
+                       case SQL_TYPE_TIME:
+                               set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
+                               set_tuplefield_int2(&row->tuple[14], SQL_CODE_TIME);
+                               break;
+                       case SQL_TYPE_TIMESTAMP:
+                               set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
+                               set_tuplefield_int2(&row->tuple[14], SQL_CODE_TIMESTAMP);
+                               break;
+                       default:
+                               set_tuplefield_int2(&row->tuple[13], sqltype);
+                               break;
+               }
+               set_tuplefield_int4(&row->tuple[16], field_number);
+#else
                set_tuplefield_int4(&row->tuple[13], field_type);
+#endif /* ODBCVER */
 
-               QR_add_tuple(stmt->result, row);
+               QR_add_tuple(res, row);
 
 
                result = PGAPI_Fetch(hcol_stmt);
@@ -1913,7 +1967,7 @@ PGAPI_Columns(
                set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
                set_tuplefield_int4(&row->tuple[13], the_type);
 
-               QR_add_tuple(stmt->result, row);
+               QR_add_tuple(res, row);
        }
 
        /*
@@ -1949,6 +2003,7 @@ PGAPI_SpecialColumns(
        static char *func = "PGAPI_SpecialColumns";
        TupleNode  *row;
        StatementClass *stmt = (StatementClass *) hstmt;
+       QResultClass    *res;
        ConnInfo   *ci;
        HSTMT           hcol_stmt;
        StatementClass *col_stmt;
@@ -2017,18 +2072,19 @@ PGAPI_SpecialColumns(
        result = PGAPI_Fetch(hcol_stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
 
-       stmt->result = QR_Constructor();
+       res = QR_Constructor();
+       SC_set_Result(stmt, res);
        extend_bindings(stmt, 8);
 
-       QR_set_num_fields(stmt->result, 8);
-       QR_set_field_info(stmt->result, 0, "SCOPE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 1, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 2, "DATA_TYPE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 3, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 4, "PRECISION", PG_TYPE_INT4, 4);
-       QR_set_field_info(stmt->result, 5, "LENGTH", PG_TYPE_INT4, 4);
-       QR_set_field_info(stmt->result, 6, "SCALE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
+       QR_set_num_fields(res, 8);
+       QR_set_field_info(res, 0, "SCOPE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 1, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 2, "DATA_TYPE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 3, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 4, "PRECISION", PG_TYPE_INT4, 4);
+       QR_set_field_info(res, 5, "LENGTH", PG_TYPE_INT4, 4);
+       QR_set_field_info(res, 6, "SCALE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
 
        if (relhasrules[0] != '1')
        {
@@ -2046,7 +2102,7 @@ PGAPI_SpecialColumns(
                        set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, PG_TYPE_OID, PG_STATIC));
                        set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
 
-                       QR_add_tuple(stmt->result, row);
+                       QR_add_tuple(res, row);
 
                }
                else if (fColType == SQL_ROWVER)
@@ -2066,7 +2122,7 @@ PGAPI_SpecialColumns(
                                set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, the_type, PG_STATIC));
                                set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
 
-                               QR_add_tuple(stmt->result, row);
+                               QR_add_tuple(res, row);
                        }
                }
        }
@@ -2095,6 +2151,7 @@ PGAPI_Statistics(
 {
        static char *func = "PGAPI_Statistics";
        StatementClass *stmt = (StatementClass *) hstmt;
+       QResultClass    *res;
        char            index_query[INFO_INQUIRY_LEN];
        HSTMT           hindx_stmt;
        RETCODE         result;
@@ -2133,14 +2190,14 @@ PGAPI_Statistics(
 
        ci = &(SC_get_conn(stmt)->connInfo);
 
-       stmt->result = QR_Constructor();
-       if (!stmt->result)
+       if (res = QR_Constructor(), !res)
        {
                stmt->errormsg = "Couldn't allocate memory for PGAPI_Statistics result.";
                stmt->errornumber = STMT_NO_MEMORY_ERROR;
                SC_log_error(func, "", stmt);
                return SQL_ERROR;
        }
+       SC_set_Result(stmt, res);
 
        /* the binding structure for a statement is not set up until */
 
@@ -2151,20 +2208,20 @@ PGAPI_Statistics(
        extend_bindings(stmt, 13);
 
        /* set the field names */
-       QR_set_num_fields(stmt->result, 13);
-       QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 3, "NON_UNIQUE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 4, "INDEX_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 5, "INDEX_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 6, "TYPE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 8, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 9, "COLLATION", PG_TYPE_CHAR, 1);
-       QR_set_field_info(stmt->result, 10, "CARDINALITY", PG_TYPE_INT4, 4);
-       QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4);
-       QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_num_fields(res, 13);
+       QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 3, "NON_UNIQUE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 4, "INDEX_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 5, "INDEX_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 6, "TYPE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 8, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 9, "COLLATION", PG_TYPE_CHAR, 1);
+       QR_set_field_info(res, 10, "CARDINALITY", PG_TYPE_INT4, 4);
+       QR_set_field_info(res, 11, "PAGES", PG_TYPE_INT4, 4);
+       QR_set_field_info(res, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);
 
        /*
         * only use the table name... the owner should be redundant, and we
@@ -2395,7 +2452,7 @@ PGAPI_Statistics(
                set_tuplefield_null(&row->tuple[11]);
                set_tuplefield_null(&row->tuple[12]);
 
-               QR_add_tuple(stmt->result, row);
+               QR_add_tuple(res, row);
        }
 
        result = PGAPI_Fetch(hindx_stmt);
@@ -2457,7 +2514,7 @@ PGAPI_Statistics(
                                set_tuplefield_null(&row->tuple[11]);
                                set_tuplefield_null(&row->tuple[12]);
 
-                               QR_add_tuple(stmt->result, row);
+                               QR_add_tuple(res, row);
                                i++;
                        }
                }
@@ -2520,12 +2577,15 @@ PGAPI_ColumnPrivileges(
                                           SWORD cbColumnName)
 {
        static char *func = "PGAPI_ColumnPrivileges";
+       StatementClass  *stmt = (StatementClass *) hstmt;
 
        mylog("%s: entering...\n", func);
 
        /* Neither Access or Borland care about this. */
 
-       SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
+       stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
+       stmt->errormsg = "not implemented";
+       SC_log_error(func, "Function not implemented", stmt);
        return SQL_ERROR;
 }
 
@@ -2547,6 +2607,7 @@ PGAPI_PrimaryKeys(
 {
        static char *func = "PGAPI_PrimaryKeys";
        StatementClass *stmt = (StatementClass *) hstmt;
+       QResultClass    *res;
        ConnectionClass *conn;
        TupleNode  *row;
        RETCODE         result;
@@ -2572,14 +2633,14 @@ PGAPI_PrimaryKeys(
        stmt->manual_result = TRUE;
        stmt->errormsg_created = TRUE;
 
-       stmt->result = QR_Constructor();
-       if (!stmt->result)
+       if (res = QR_Constructor(), !res)
        {
                stmt->errormsg = "Couldn't allocate memory for PGAPI_PrimaryKeys result.";
                stmt->errornumber = STMT_NO_MEMORY_ERROR;
                SC_log_error(func, "", stmt);
                return SQL_ERROR;
        }
+       SC_set_Result(stmt, res);
 
        /* the binding structure for a statement is not set up until */
 
@@ -2591,13 +2652,13 @@ PGAPI_PrimaryKeys(
        extend_bindings(stmt, result_cols);
 
        /* set the field names */
-       QR_set_num_fields(stmt->result, result_cols);
-       QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_num_fields(res, result_cols);
+       QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
 
 
        result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
@@ -2709,7 +2770,7 @@ PGAPI_PrimaryKeys(
                set_tuplefield_int2(&row->tuple[4], (Int2) (++seq));
                set_tuplefield_null(&row->tuple[5]);
 
-               QR_add_tuple(stmt->result, row);
+               QR_add_tuple(res, row);
 
                mylog(">> primaryKeys: pktab = '%s', attname = '%s', seq = %d\n", pktab, attname, seq);
 
@@ -2775,7 +2836,7 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
                return ret;
        if (!conn->server_encoding)
        {
-               if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res)
+               if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, TRUE), res)
                {
                        if (QR_get_num_tuples(res) > 0)
                                conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
@@ -2785,25 +2846,16 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
        if (!conn->server_encoding)
                return ret;
        sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
-       if (res = CC_send_query(conn, query, NULL), res)
-       {
-               bError = QR_get_aborted(res);
-               QR_Destructor(res);
-       }
-       else
-               bError = TRUE;
+       bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
        if (!bError && continueExec)
        {
                sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName);
-               if (res = CC_send_query(conn, query, NULL), res)
+               if (res = CC_send_query(conn, query, NULL, TRUE), res)
                {
                        if (QR_get_num_tuples(res) > 0)
                                strcpy(saveoid, QR_get_value_backend_row(res, 0, 0));
                        else
-                       {
                                continueExec = FALSE;
-                               bError = QR_get_aborted(res);
-                       }
                        QR_Destructor(res);
                }
                else
@@ -2817,17 +2869,11 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
        }
        /* restore the client encoding */
        sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
-       if (res = CC_send_query(conn, query, NULL), res)
-       {
-               bError = QR_get_aborted(res);
-               QR_Destructor(res);
-       }
-       else
-               bError = TRUE;
+       bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
        if (bError || !continueExec)
                return ret;
        sprintf(query, "select relname from pg_class where OID = %s", saveoid);
-       if (res = CC_send_query(conn, query, NULL), res)
+       if (res = CC_send_query(conn, query, NULL, TRUE), res)
        {
                if (QR_get_num_tuples(res) > 0)
                {
@@ -2854,7 +2900,7 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
                return ret;
        if (!conn->server_encoding)
        {
-               if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res)
+               if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, TRUE), res)
                {
                        if (QR_get_num_tuples(res) > 0)
                                conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
@@ -2864,19 +2910,13 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
        if (!conn->server_encoding)
                return ret;
        sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
-       if (res = CC_send_query(conn, query, NULL), res)
-       {
-               bError = QR_get_aborted(res);
-               QR_Destructor(res);
-       }
-       else
-               bError = TRUE;
+       bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
        if (!bError && continueExec)
        {
                sprintf(query, "select attrelid, attnum from pg_class, pg_attribute "
                                "where relname = '%s' and attrelid = pg_class.oid "
                                "and attname = '%s'", serverTableName, serverColumnName);
-               if (res = CC_send_query(conn, query, NULL), res)
+               if (res = CC_send_query(conn, query, NULL, TRUE), res)
                {
                        if (QR_get_num_tuples(res) > 0)
                        {
@@ -2884,10 +2924,7 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
                                strcpy(saveattnum, QR_get_value_backend_row(res, 0, 1));
                        }
                        else
-                       {
                                continueExec = FALSE;
-                               bError = QR_get_aborted(res);
-                       }
                        QR_Destructor(res);
                }
                else
@@ -2901,17 +2938,11 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
        }
        /* restore the cleint encoding */
        sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
-       if (res = CC_send_query(conn, query, NULL), res)
-       {
-               bError = QR_get_aborted(res);
-               QR_Destructor(res);
-       }
-       else
-               bError = TRUE;
+       bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
        if (bError || !continueExec)
                return ret;
        sprintf(query, "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum);
-       if (res = CC_send_query(conn, query, NULL), res)
+       if (res = CC_send_query(conn, query, NULL, TRUE), res)
        {
                if (QR_get_num_tuples(res) > 0)
                {
@@ -2942,6 +2973,7 @@ PGAPI_ForeignKeys(
 {
        static char *func = "PGAPI_ForeignKeys";
        StatementClass *stmt = (StatementClass *) hstmt;
+       QResultClass    *res;
        TupleNode  *row;
        HSTMT           htbl_stmt,
                                hpkey_stmt;
@@ -2997,14 +3029,14 @@ PGAPI_ForeignKeys(
        stmt->manual_result = TRUE;
        stmt->errormsg_created = TRUE;
 
-       stmt->result = QR_Constructor();
-       if (!stmt->result)
+       if (res = QR_Constructor(), !res)
        {
                stmt->errormsg = "Couldn't allocate memory for PGAPI_ForeignKeys result.";
                stmt->errornumber = STMT_NO_MEMORY_ERROR;
                SC_log_error(func, "", stmt);
                return SQL_ERROR;
        }
+       SC_set_Result(stmt, res);
 
        /* the binding structure for a statement is not set up until */
 
@@ -3016,23 +3048,23 @@ PGAPI_ForeignKeys(
        extend_bindings(stmt, result_cols);
 
        /* set the field names */
-       QR_set_num_fields(stmt->result, result_cols);
-       QR_set_field_info(stmt->result, 0, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 2, "PKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 3, "PKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 6, "FKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 7, "FKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 8, "KEY_SEQ", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 9, "UPDATE_RULE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 10, "DELETE_RULE", PG_TYPE_INT2, 2);
-       QR_set_field_info(stmt->result, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 12, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_num_fields(res, result_cols);
+       QR_set_field_info(res, 0, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 2, "PKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 3, "PKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 6, "FKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 7, "FKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 8, "KEY_SEQ", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 9, "UPDATE_RULE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 10, "DELETE_RULE", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 12, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
 #if (ODBCVER >= 0x0300)
-       QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
+       QR_set_field_info(res, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
 #endif   /* ODBCVER >= 0x0300 */
 
        /*
@@ -3369,7 +3401,7 @@ PGAPI_ForeignKeys(
                                set_tuplefield_int2(&row->tuple[14], defer_type);
 #endif   /* ODBCVER >= 0x0300 */
 
-                               QR_add_tuple(stmt->result, row);
+                               QR_add_tuple(res, row);
 #ifdef MULTIBYTE
                                if (fkey_alloced)
                                        free(fkey_text);
@@ -3623,7 +3655,7 @@ PGAPI_ForeignKeys(
                                set_tuplefield_int2(&row->tuple[14], defer_type);
 #endif   /* ODBCVER >= 0x0300 */
 
-                               QR_add_tuple(stmt->result, row);
+                               QR_add_tuple(res, row);
 #ifdef MULTIBYTE
                                if (pkey_alloced)
                                        free(pkey_text);
@@ -3687,10 +3719,13 @@ PGAPI_ProcedureColumns(
                                           SWORD cbColumnName)
 {
        static char *func = "PGAPI_ProcedureColumns";
+       StatementClass  *stmt = (StatementClass *) hstmt;
 
        mylog("%s: entering...\n", func);
 
-       SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
+       stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
+       stmt->errormsg = "not implemented";
+       SC_log_error(func, "Function not implemented", stmt);
        return SQL_ERROR;
 }
 
@@ -3717,7 +3752,7 @@ PGAPI_Procedures(
        {
                stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
                stmt->errormsg = "Version is too old";
-               SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
+               SC_log_error(func, "Function not implemented", stmt);
                return SQL_ERROR;
        }
        if (!SC_recycle_statement(stmt))
@@ -3733,16 +3768,13 @@ PGAPI_Procedures(
                   " case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
        my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName);
 
-       res = CC_send_query(conn, proc_query, NULL);
-       if (!res || QR_aborted(res))
+       if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
        {
-               if (res)
-                       QR_Destructor(res);
                stmt->errornumber = STMT_EXEC_ERROR;
                stmt->errormsg = "PGAPI_Procedures query error";
                return SQL_ERROR;
        }
-       stmt->result = res;
+       SC_set_Result(stmt, res);
 
        /*
         * also, things need to think that this statement is finished so the
@@ -3759,6 +3791,52 @@ PGAPI_Procedures(
 }
 
 
+#define        ACLMAX  8
+#define ALL_PRIVILIGES "arwdRxt"
+static int
+usracl_auth(char *usracl, const char *auth)
+{
+       int     i, j, addcnt = 0;
+
+       for (i = 0; auth[i]; i++)
+       {
+               for (j = 0; j < ACLMAX; j++)
+               {
+                       if (usracl[j] == auth[i])
+                               break;
+                       else if (!usracl[j])
+                       {
+                               usracl[j]= auth[i];
+                               addcnt++;
+                               break;
+                       }
+               }
+       }
+       return addcnt;
+} 
+static void
+useracl_upd(char (*useracl)[ACLMAX], QResultClass *allures, const char *user, const char *auth)
+{
+       int usercount = QR_get_num_tuples(allures), i, addcnt = 0;
+
+mylog("user=%s auth=%s\n", user, auth);
+       if (user[0])
+               for (i = 0; i < usercount; i++)
+               {
+                       if (strcmp(QR_get_value_backend_row(allures, i, 0), user) == 0)
+                       {
+                               addcnt += usracl_auth(useracl[i], auth);
+                               break;
+                       }
+               }
+       else
+               for (i = 0; i < usercount; i++)
+               {
+                       addcnt += usracl_auth(useracl[i], auth);
+               }
+       mylog("addcnt=%d\n", addcnt);
+}
+
 RETCODE                SQL_API
 PGAPI_TablePrivileges(
                                          HSTMT hstmt,
@@ -3767,13 +3845,24 @@ PGAPI_TablePrivileges(
                                          UCHAR FAR * szTableOwner,
                                          SWORD cbTableOwner,
                                          UCHAR FAR * szTableName,
-                                         SWORD cbTableName)
+                                         SWORD cbTableName,
+                                         UWORD flag)
 {
        StatementClass *stmt = (StatementClass *) hstmt;
        static char *func = "PGAPI_TablePrivileges";
+       ConnectionClass *conn = SC_get_conn(stmt);
        Int2            result_cols;
+       char            proc_query[INFO_INQUIRY_LEN];
+       QResultClass    *res, *allures = NULL;
+       TupleNode       *row;
+       int             tablecount, usercount, i, j, k;
+       BOOL            grpauth, sys, su;
+       char            (*useracl)[ACLMAX], *acl, *user, *delim, *auth;
+       char            *reln, *owner, *priv;
 
        mylog("%s: entering...\n", func);
+       if (!SC_recycle_statement(stmt))
+               return SQL_ERROR;
 
        /*
         * a statement is actually executed, so we'll have to do this
@@ -3784,16 +3873,187 @@ PGAPI_TablePrivileges(
 
        /* set the field names */
        stmt->manual_result = TRUE;
-       stmt->result = QR_Constructor();
-       QR_set_num_fields(stmt->result, result_cols);
-       QR_set_field_info(stmt->result, 0, "TABLE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 1, "TABLE_SCHEM", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 3, "GRANTOR", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 4, "GRANTEE", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 5, "PRIVILEGE", PG_TYPE_TEXT, MAX_INFO_STRING);
-       QR_set_field_info(stmt->result, 6, "IS_GRANTABLE", PG_TYPE_TEXT, MAX_INFO_STRING);
-
-       SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
-       return SQL_ERROR;
+       res = QR_Constructor();
+       SC_set_Result(stmt, res);
+       QR_set_num_fields(res, result_cols);
+       QR_set_field_info(res, 0, "TABLE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 1, "TABLE_SCHEM", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 3, "GRANTOR", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 4, "GRANTEE", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 5, "PRIVILEGE", PG_TYPE_TEXT, MAX_INFO_STRING);
+       QR_set_field_info(res, 6, "IS_GRANTABLE", PG_TYPE_TEXT, MAX_INFO_STRING);
+
+       /*
+        * also, things need to think that this statement is finished so the
+        * results can be retrieved.
+        */
+       stmt->status = STMT_FINISHED;
+       /* set up the current tuple pointer for SQLFetch */
+       stmt->currTuple = -1;
+       stmt->rowset_start = -1;
+       stmt->current_col = -1;
+       strncpy_null(proc_query, "select relname, usename, relacl from pg_class , pg_user where", sizeof(proc_query)); 
+       if ((flag & PODBC_NOT_SEARCH_PATTERN) != 0) 
+               my_strcat(proc_query, " relname = '%.*s' and", szTableName, cbTableName);
+       else
+       {
+               char    esc_table_name[MAX_TABLE_LEN * 2];
+               int     escTbnamelen;
+
+               escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name), conn->ccsc);
+               my_strcat(proc_query, " relname like '%.*s' and", esc_table_name, escTbnamelen);
+       }
+       strcat(proc_query, " pg_user.usesysid = relowner"); 
+       if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
+       {
+               stmt->errornumber = STMT_EXEC_ERROR;
+               stmt->errormsg = "PGAPI_TablePrivileges query error";
+               return SQL_ERROR;
+       }
+       strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query));
+       tablecount = QR_get_num_tuples(res);
+       if (allures = CC_send_query(conn, proc_query, NULL, TRUE), !allures)
+       {
+               QR_Destructor(res);
+               stmt->errornumber = STMT_EXEC_ERROR;
+               stmt->errormsg = "PGAPI_TablePrivileges query error";
+               return SQL_ERROR;
+       }
+       usercount = QR_get_num_tuples(allures);
+       useracl = (char (*)[ACLMAX]) malloc(usercount * sizeof(char [ACLMAX]));
+       for (i = 0; i < tablecount; i++)
+       { 
+               memset(useracl, 0, usercount * sizeof(char[ACLMAX]));
+               acl = (char *) QR_get_value_backend_row(res, i, 2);
+               if (acl && acl[0] == '{')
+                       user = acl + 1;
+               else
+                       user = NULL;
+               for (; user && *user;)
+               {
+                       grpauth = FALSE;
+                       if (user[0] == '"' && strncmp(user + 1, "group ", 6) == 0)
+                       {
+                               user += 7;
+                               grpauth = TRUE;
+                       }
+                       if (delim = strchr(user, '='), !delim)
+                               break;
+                       *delim = '\0';
+                       auth = delim + 1;
+                       if (grpauth)
+                       {
+                               if (delim = strchr(auth, '"'), delim)
+                               {
+                                       *delim = '\0';
+                                       delim++;
+                               }
+                       }
+                       else if (delim = strchr(auth, ','), delim)
+                               *delim = '\0';
+                       else if (delim = strchr(auth, '}'), delim)
+                               *delim = '\0';
+                       if (grpauth) /* handle group privilege */
+                       {
+                               QResultClass    *gres;
+                               int             i;
+                               char    *grolist, *uid, *delm;
+
+                               snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user);
+                               if (gres = CC_send_query(conn, proc_query, NULL, TRUE))
+                               {
+                                       grolist = QR_get_value_backend_row(gres, 0, 0);
+                                       if (grolist && grolist[0] == '{')
+                                       {
+                                               for (uid = grolist + 1; *uid;)
+                                               {
+                                                       if (delm = strchr(uid, ','), delm)
+                                                               *delm = '\0';
+                                                       else if (delm = strchr(uid, '}'), delm)
+                                                               *delm = '\0';
+mylog("guid=%s\n", uid);
+                                                       for (i = 0; i < usercount; i++)
+                                                       {
+                                                               if (strcmp(QR_get_value_backend_row(allures, i, 1), uid) == 0)
+                                                                       useracl_upd(useracl, allures, QR_get_value_backend_row(allures, i, 0), auth);
+                                                       }
+                                                       uid = delm + 1;
+                                               }
+                                       }
+                                       QR_Destructor(gres);
+                               }
+                       }
+                       else
+                               useracl_upd(useracl, allures, user, auth);
+                       if (!delim)
+                               break;
+                       user = delim + 1;
+               }
+               reln = QR_get_value_backend_row(res, i, 0);
+               owner = QR_get_value_backend_row(res, i, 1);
+               /* The owner has all privileges */
+               useracl_upd(useracl, allures, owner, ALL_PRIVILIGES);
+               for (j = 0; j < usercount; j++)
+               {
+                       user = QR_get_value_backend_row(allures, j, 0);
+                       su = (strcmp(QR_get_value_backend_row(allures, j, 2), "t") == 0);
+                       sys = (strcmp(user, owner) == 0);
+                       /* Super user has all privileges */
+                       if (su)
+                               useracl_upd(useracl, allures, user, ALL_PRIVILIGES);
+                       for (k = 0; k < ACLMAX; k++)
+                       {
+                               if (!useracl[j][k])
+                                       break;
+                               switch (useracl[j][k])
+                               {
+                                       case 'R': /* rule */
+                                       case 't': /* trigger */
+                                               continue;
+                               }
+                               row = (TupleNode *) malloc(sizeof(TupleNode) + (7 - 1) *sizeof(TupleField));
+                               set_tuplefield_string(&row->tuple[0], "");
+                               set_tuplefield_string(&row->tuple[1], "");
+                               set_tuplefield_string(&row->tuple[2], reln);
+                               if (su || sys)
+                                       set_tuplefield_string(&row->tuple[3], "_SYSTEM");
+                               else
+                                       set_tuplefield_string(&row->tuple[3], owner);
+                               mylog("user=%s\n", user);
+                               set_tuplefield_string(&row->tuple[4], user);
+                               switch (useracl[j][k])
+                               {
+                                       case 'a':
+                                               priv = "INSERT";
+                                               break;
+                                       case 'r':
+                                               priv = "SELECT";
+                                               break;
+                                       case 'w':
+                                               priv = "UPDATE";
+                                               break;
+                                       case 'd':
+                                               priv = "DELETE";
+                                               break;
+                                       case 'x':
+                                               priv = "REFERENCES";
+                                               break;
+                                       default:
+                                               priv = "";
+                               }
+                               set_tuplefield_string(&row->tuple[5], priv);
+                               /* The owner and the super user are grantable */
+                               if (sys || su)
+                                       set_tuplefield_string(&row->tuple[6], "YES");
+                               else
+                                       set_tuplefield_string(&row->tuple[6], "NO");
+                               QR_add_tuple(SC_get_Result(stmt), row);
+                       }
+               }
+       }
+       free(useracl);
+       QR_Destructor(res);
+       QR_Destructor(allures); 
+       return SQL_SUCCESS;
 }
index 8aa2bfdf10b2fe7df753b4818405af732bab2512..b606f0dc62253bc160e0a1d122a781a488a9f287 100644 (file)
@@ -19,6 +19,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
 {
        static char *func = "PGAPI_GetInfo30";
        ConnectionClass *conn = (ConnectionClass *) hdbc;
+       ConnInfo        *ci = &(conn->connInfo);
        char       *p = NULL;
        int                     len = 0,
                                value = 0;
@@ -50,35 +51,60 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
                                | SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
                                | SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
                                | SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
-                               | SQL_CA1_POS_REFRESH
-                               /* | SQL_CA1_BULK_ADD
+                               | SQL_CA1_POS_REFRESH;
+                       if (ci->drivers.lie)
+                               value |=
+                               ( SQL_CA1_BULK_ADD
                                | SQL_CA1_BULK_UPDATE_BY_BOOKMARK
                                | SQL_CA1_BULK_DELETE_BY_BOOKMARK
-                               | SQL_CA1_BULK_FETCH_BY_BOOKMARK */
-                               ;
+                               | SQL_CA1_BULK_FETCH_BY_BOOKMARK
+
+                               | SQL_CA1_LOCK_EXCLUSIVE
+                               | SQL_CA1_LOCK_UNLOCK
+                               | SQL_CA1_POSITIONED_UPDATE
+                               | SQL_CA1_POSITIONED_DELETE
+                               | SQL_CA1_SELECT_FOR_UPDATE
+                               );
                        break;
                case SQL_KEYSET_CURSOR_ATTRIBUTES2:
                        len = 4;
-                       value = SQL_CA2_OPT_ROWVER_CONCURRENCY |
-                               SQL_CA2_SENSITIVITY_ADDITIONS |
-                               SQL_CA2_SENSITIVITY_DELETIONS |
-                               SQL_CA2_SENSITIVITY_UPDATES;
+                       value = SQL_CA2_OPT_ROWVER_CONCURRENCY
+                               | SQL_CA2_SENSITIVITY_ADDITIONS
+                               | SQL_CA2_SENSITIVITY_DELETIONS
+                               | SQL_CA2_SENSITIVITY_UPDATES;
+                       if (ci->drivers.lie)
+                               value |=
+                               ( SQL_CA2_READ_ONLY_CONCURRENCY
+                               | SQL_CA2_LOCK_CONCURRENCY
+                               | SQL_CA2_OPT_VALUES_CONCURRENCY
+                               | SQL_CA2_MAX_ROWS_SELECT
+                               | SQL_CA2_MAX_ROWS_INSERT
+                               | SQL_CA2_MAX_ROWS_DELETE
+                               | SQL_CA2_MAX_ROWS_UPDATE
+                               | SQL_CA2_MAX_ROWS_CATALOG
+                               | SQL_CA2_MAX_ROWS_AFFECTS_ALL
+                               | SQL_CA2_CRC_EXACT
+                               | SQL_CA2_CRC_APPROXIMATE
+                               | SQL_CA2_SIMULATE_NON_UNIQUE
+                               | SQL_CA2_SIMULATE_TRY_UNIQUE
+                               | SQL_CA2_SIMULATE_UNIQUE
+                               );
                        break;
 
                case SQL_STATIC_CURSOR_ATTRIBUTES1:
                        len = 4;
-                       value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
-                               SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK |
-                               SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION |
-                               SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE |
-                               SQL_CA1_POS_REFRESH;
+                       value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE
+                               | SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
+                               | SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
+                               | SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
+                               SQL_CA1_POS_REFRESH;
                        break;
                case SQL_STATIC_CURSOR_ATTRIBUTES2:
                        len = 4;
-                       value = SQL_CA2_OPT_ROWVER_CONCURRENCY |
-                               SQL_CA2_SENSITIVITY_ADDITIONS |
-                               SQL_CA2_SENSITIVITY_DELETIONS |
-                               SQL_CA2_SENSITIVITY_UPDATES;
+                       value = SQL_CA2_OPT_ROWVER_CONCURRENCY
+                               | SQL_CA2_SENSITIVITY_ADDITIONS
+                               | SQL_CA2_SENSITIVITY_DELETIONS
+                               SQL_CA2_SENSITIVITY_UPDATES;
                        break;
 
                case SQL_ODBC_INTERFACE_CONFORMANCE:
@@ -103,11 +129,11 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
                        break;
                case SQL_BATCH_ROW_COUNT:
                        len = 4;
-                       value = SQL_BRC_ROLLED_UP | SQL_BRC_EXPLICIT;
+                       value = SQL_BRC_EXPLICIT;
                        break;
                case SQL_BATCH_SUPPORT:
                        len = 4;
-                       value = SQL_BS_ROW_COUNT_EXPLICIT;
+                       value = SQL_BS_SELECT_EXPLICIT | SQL_BS_ROW_COUNT_EXPLICIT;
                        break;
                case SQL_CATALOG_NAME:
                        len = 0;
@@ -194,7 +220,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
                        len = 4;
                        value = SQL_DT_DROP_TABLE;
                        if (PG_VERSION_GT(conn, 7.2)) /* hopefully */
-                               value |= SQL_DT_RESTRICT | SQL_DT_CASCADE;
+                               value |= (SQL_DT_RESTRICT | SQL_DT_CASCADE);
                        break;
                case SQL_DROP_TRANSLATION:
                        len = 4;
@@ -204,7 +230,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
                        len = 4;
                        value = SQL_DV_DROP_VIEW;
                        if (PG_VERSION_GT(conn, 7.2)) /* hopefully */
-                               value |= SQL_DV_RESTRICT | SQL_DV_CASCADE;
+                               value |= (SQL_DV_RESTRICT | SQL_DV_CASCADE);
                        break;
                case SQL_INDEX_KEYWORDS:
                        len = 4;
@@ -227,11 +253,11 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
                        break;
                case SQL_PARAM_ARRAY_ROW_COUNTS:
                        len = 4;
-                       value = SQL_PARC_NO_BATCH;
+                       value = SQL_PARC_BATCH;
                        break;
                case SQL_PARAM_ARRAY_SELECTS:
                        len = 4;
-                       value = SQL_PAS_NO_SELECT;
+                       value = SQL_PAS_BATCH;
                        break;
                case SQL_SQL_CONFORMANCE:
                        len = 4;
@@ -316,6 +342,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
                        return SQL_ERROR;
        }
        result = SQL_SUCCESS;
+       mylog("%s: p='%s', len=%d, value=%d, cbMax=%d\n", func, p ? p : "<NULL>", len, value, cbInfoValueMax);
        if (p)
        {
                /* char/binary data */
@@ -323,6 +350,14 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
 
                if (rgbInfoValue)
                {
+#ifdef UNICODE_SUPPORT
+                       if (conn->unicode)
+                       {
+                               len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / 2);
+                               len *= 2;
+                       }
+                       else
+#endif /* UNICODE_SUPPORT */
                        strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
 
                        if (len >= cbInfoValueMax)
index dc505115fe39ac0802cdc24059598953c47d9e65..443d1f47b3cfda0cdb64cba4699a5239c82210a8 100644 (file)
@@ -15,7 +15,6 @@
 #include "psqlodbc.h"
 
 #include <stdio.h>
-#include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
 
index 5cedd4c147e8daeb5172b8548a4b0a059c4de95d..b658ed7c91e06d6cc7e5a7756e7b16593ff9febb 100644 (file)
@@ -38,6 +38,7 @@
 #define MYLOGDIR                       "c:"
 #endif
 extern void mylog(char *fmt,...);
+#define        inolog  mylog   /* for really temporary debug */
 
 #else
 #ifndef WIN32
index 464bf244326a52b8403f2c17d2ce99113b31faf5..06e24d0871634db274d70befd001b82addd0570e 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 
-int PG_CCST;                           /* Client Charcter Status */
-
-int PG_SCSC;                           /* Server Charcter Set (code) */
-int PG_CCSC;                           /* Client Charcter Set (code) */
-unsigned char *PG_SCSS;        /* Server Charcter Set (string) */
-unsigned char *PG_CCSS;        /* Client Charcter Set (string) */
-
 pg_CS CS_Table[] =
 {
        { "SQL_ASCII",  SQL_ASCII },
@@ -78,19 +71,29 @@ pg_ismb(int characterset_code)
 int
 pg_CS_code(const unsigned char *characterset_string)
 {
-       int i = 0, c;
+       int i = 0, c = -1;
+       unsigned len = 0;
        for(i = 0; CS_Table[i].code != OTHER; i++)
        {
                if (strstr(characterset_string,CS_Table[i].name))
-                       c = CS_Table[i].code;
+               {
+                       if(strlen(CS_Table[i].name) >= len)
+                        {
+                               len = strlen(CS_Table[i].name);
+                               c = CS_Table[i].code;
+                        }
+
+               }
        }
+       if (c < 0)
+               c = i;
        return (c);
 }
 
 unsigned char *
-pg_CS_name(const int characterset_code)
+pg_CS_name(int characterset_code)
 {
-       int i = 0;
+       int i;
        for (i = 0; CS_Table[i].code != OTHER; i++)
        {
                if (CS_Table[i].code == characterset_code)
@@ -242,7 +245,7 @@ pg_CS_stat(int stat,unsigned int character,int characterset_code)
 
 
 unsigned char *
-pg_mbschr(const unsigned char *string, unsigned int character)
+pg_mbschr(int csc, const unsigned char *string, unsigned int character)
 {
        int                     mb_st = 0;
        unsigned char *s;
@@ -250,7 +253,7 @@ pg_mbschr(const unsigned char *string, unsigned int character)
 
        for(;;) 
        {
-               mb_st = pg_CS_stat(mb_st, (unsigned char) *s,PG_CCSC);
+               mb_st = pg_CS_stat(mb_st, (unsigned char) *s, csc);
                if (mb_st == 0 && (*s == character || *s == 0))
                        break;
                else
@@ -260,13 +263,13 @@ pg_mbschr(const unsigned char *string, unsigned int character)
 }
 
 int
-pg_mbslen(const unsigned char *string)
+pg_mbslen(int csc, const unsigned char *string)
 {
        unsigned char *s;
        int len, cs_stat;
        for (len = 0, cs_stat = 0, s = (unsigned char *) string; *s != 0; s++)
        {
-               cs_stat = pg_CS_stat(cs_stat,(unsigned int) *s, PG_CCSC);
+               cs_stat = pg_CS_stat(cs_stat,(unsigned int) *s, csc);
                if (cs_stat < 2)
                        len++;
        }
@@ -274,12 +277,12 @@ pg_mbslen(const unsigned char *string)
 }
 
 unsigned char *
-pg_mbsinc(const unsigned char *current )
+pg_mbsinc(int csc, const unsigned char *current )
 {
        int mb_stat = 0;
        if (*current != 0)
        {
-               mb_stat = (int) pg_CS_stat(mb_stat, *current, PG_CCSC);
+               mb_stat = (int) pg_CS_stat(mb_stat, *current, csc);
                if (mb_stat == 0)
                        mb_stat = 1;
                return ((unsigned char *) current + mb_stat);
@@ -288,43 +291,100 @@ pg_mbsinc(const unsigned char *current )
                return NULL;
 }
 
-void
-CC_lookup_characterset(ConnectionClass *self)
+static char *
+CC_lookup_cs_new(ConnectionClass *self)
 {
+       char            *encstr = NULL;
+       QResultClass    *res;
+
+       res = CC_send_query(self, "select pg_client_encoding()", NULL, TRUE);
+       if (res)
+       {
+               char    *enc = QR_get_value_backend_row(res, 0, 0);
+
+               if (enc)
+                       encstr = strdup(enc);
+               QR_Destructor(res);
+       }
+       return encstr;
+}
+static char *
+CC_lookup_cs_old(ConnectionClass *self)
+{
+       char            *encstr = NULL;
        HSTMT           hstmt;
-       StatementClass *stmt;
        RETCODE         result;
-       static char *func = "CC_lookup_characterset";
-
-       mylog("%s: entering...\n", func);
-       PG_SCSS = malloc(MAX_CHARACTERSET_NAME);
-       PG_CCSS = malloc(MAX_CHARACTERSET_NAME);
 
        result = PGAPI_AllocStmt(self, &hstmt);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-               return;
-       stmt = (StatementClass *) hstmt;
+               return encstr;
 
        result = PGAPI_ExecDirect(hstmt, "Show Client_Encoding", SQL_NTS);
-       if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+       if (result == SQL_SUCCESS_WITH_INFO)
        {
-               PGAPI_FreeStmt(hstmt, SQL_DROP);
-               return;
+               char sqlState[8], errormsg[128], enc[32];
+
+               if (PGAPI_Error(NULL, NULL, hstmt, sqlState, NULL, errormsg,
+                       sizeof(errormsg), NULL) == SQL_SUCCESS &&
+                   sscanf(errormsg, "%*s %*s %*s %*s %*s %s", enc) > 0)
+                       encstr = strdup(enc);
        }
-       result = PGAPI_AllocStmt(self, &hstmt);
-       if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-               return;
-       stmt = (StatementClass *) hstmt;
+       PGAPI_FreeStmt(hstmt, SQL_DROP);
+       return encstr;
+}
 
-       result = PGAPI_ExecDirect(hstmt, "Show Server_Encoding", SQL_NTS);
-       if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+void
+CC_lookup_characterset(ConnectionClass *self)
+{
+       char            *encstr;
+       static char *func = "CC_lookup_characterset";
+
+       mylog("%s: entering...\n", func);
+       if (PG_VERSION_LT(self, 7.2))
+               encstr = CC_lookup_cs_old(self);
+       else
+               encstr = CC_lookup_cs_new(self);
+       if (self->client_encoding)
+               free(self->client_encoding);
+       if (encstr)
+       {
+               self->client_encoding = encstr;
+               self->ccsc = pg_CS_code(encstr);
+               qlog("    [ Client encoding = '%s' (code = %d) ]\n", self->client_encoding, self->ccsc);
+               if (stricmp(pg_CS_name(self->ccsc), encstr))
+               {
+                       qlog(" Client encoding = '%s' and %s\n", self->client_encoding, pg_CS_name(self->ccsc));
+                       self->errornumber = CONN_VALUE_OUT_OF_RANGE;  
+                       self->errormsg = "client encoding mismatch"; 
+               }
+       }
+       else
        {
-               PGAPI_FreeStmt(hstmt, SQL_DROP);
-               return;
+               self->ccsc = SQL_ASCII;
+               self->client_encoding = NULL;
        }
+}
 
-       strcpy(PG_SCSS , pg_CS_name(PG_SCSC = pg_CS_code(PG_SCSS)));
-       strcpy(PG_CCSS , pg_CS_name(PG_CCSC = pg_CS_code(PG_CCSS)));
+void encoded_str_constr(encoded_str *encstr, int ccsc, const char *str)
+{
+       encstr->ccsc = ccsc;
+       encstr->encstr = str;
+       encstr->pos = -1;
+       encstr->ccst = 0;
+}
+int encoded_nextchar(encoded_str *encstr)
+{
+       int     chr;
+
+       chr = encstr->encstr[++encstr->pos]; 
+       encstr->ccst = pg_CS_stat(encstr->ccst, (unsigned int) chr, encstr->ccsc);
+       return chr; 
+}
+int encoded_byte_check(encoded_str *encstr, int abspos)
+{
+       int     chr;
 
-       qlog("    [ Server encoding = '%s' (code = %d), Client encoding = '%s' (code = %d) ]\n", PG_SCSS, PG_SCSC, PG_CCSS, PG_CCSC);
+       chr = encstr->encstr[encstr->pos = abspos]; 
+       encstr->ccst = pg_CS_stat(encstr->ccst, (unsigned int) chr, encstr->ccsc);
+       return chr; 
 }
index b6d487b634d2da953f02b457be3634eeea21b179..47a57b0ade63f0a20f08fb6316db58e255cc751b 100644 (file)
@@ -4,13 +4,14 @@
  *
  */
 #include "psqlodbc.h"
+#include "qresult.h"
 
 /* PostgreSQL client encoding */
 #define SQL_ASCII                      0       /* SQL/ASCII */
 #define EUC_JP                         1       /* EUC for Japanese */
 #define EUC_CN                         2       /* EUC for Chinese */
 #define EUC_KR                         3       /* EUC for Korean */
-#define EUC_TW                         4       /* EUC for Taiwan */\r
+#define EUC_TW                         4       /* EUC for Taiwan */
 #define JOHAB                          5
 #define UTF8                           6       /* Unicode UTF-8 */
 #define MULE_INTERNAL          7       /* Mule internal code */
 #define LATIN6                         13      /* ISO-8859 Latin 6 */
 #define LATIN7                         14      /* ISO-8859 Latin 7 */
 #define LATIN8                         15      /* ISO-8859 Latin 8 */
-#define LATIN9                         16      /* ISO-8859 Latin 9 */\r
-#define LATIN10                                17      /* ISO-8859 Latin 10 */\r
-#define WIN1256                                18      /* Arabic Windows */\r
-#define TCVN                           19      /* Vietnamese Windows */\r
-#define WIN874                         20      /* Thai Windows */\r
-#define KOI8R                          21      /* KOI8-R/U */\r
+#define LATIN9                         16      /* ISO-8859 Latin 9 */
+#define LATIN10                                17      /* ISO-8859 Latin 10 */
+#define WIN1256                                18      /* Arabic Windows */
+#define TCVN                           19      /* Vietnamese Windows */
+#define WIN874                         20      /* Thai Windows */
+#define KOI8R                          21      /* KOI8-R/U */
 #define WIN1251                                22      /* windows-1251 */
 #define ALT                                    23      /* Alternativny Variant (MS-DOS CP866) */
-#define ISO_8859_5                     24      /* ISO-8859-5 */\r
-#define ISO_8859_6                     25      /* ISO-8859-6 */\r
-#define ISO_8859_7                     26      /* ISO-8859-7 */\r
-#define ISO_8859_8                     27      /* ISO-8859-8 */\r
-\r
+#define ISO_8859_5                     24      /* ISO-8859-5 */
+#define ISO_8859_6                     25      /* ISO-8859-6 */
+#define ISO_8859_7                     26      /* ISO-8859-7 */
+#define ISO_8859_8                     27      /* ISO-8859-8 */
+
 #define SJIS                           28      /* Shift JIS */
-#define BIG5                           29      /* Big5 */\r
-#define GBK                                    30      /* GBK */\r
-#define UHC                                    31  /* UHC */\r
-#define WIN1250                                32      /* windows-1250 */\r
-#define OTHER                          -1\r
-\r
-#define MAX_CHARACTERSET_NAME  24\r
-#define MAX_CHARACTER_LEN      6\r
+#define BIG5                           29      /* Big5 */
+#define GBK                                    30      /* GBK */
+#define UHC                                    31  /* UHC */
+#define WIN1250                                32      /* windows-1250 */
+#define OTHER                          -1
+
+#define MAX_CHARACTERSET_NAME  24
+#define MAX_CHARACTER_LEN      6
 
-/* OLD Type */\r
+/* OLD Type */
 // extern int  multibyte_client_encoding;      /* Multibyte client encoding. */
 // extern int  multibyte_status;       /* Multibyte charcter status. */
 //
 // void                multibyte_init(void);
 // unsigned char *check_client_encoding(unsigned char *sql_string);
 // int                 multibyte_char_check(unsigned char s);
-// unsigned char *multibyte_strchr(const unsigned char *string, unsigned int c);\r
-\r
-/* New Type */\r
-\r
-extern int PG_CCST;                            /* Client Character StaTus */\r
-\r
-extern int PG_SCSC;                            /* Server Character Set (Code) */\r
-extern int PG_CCSC;                            /* Client Character Set (Code) */\r
-extern unsigned char *PG_SCSS; /* Server Character Set (String) */\r
-extern unsigned char *PG_CCSS; /* Client Character Set (String) */\r
-\r
-extern void CC_lookup_characterset(ConnectionClass *self);\r
-\r
-extern int pg_CS_stat(int stat,unsigned int charcter,int characterset_code);\r
-extern int pg_CS_code(const unsigned char *stat_string);\r
-extern unsigned char *pg_CS_name(const int code);\r
-\r
-typedef struct pg_CS\r
-{\r
-       unsigned char *name;\r
-       int code;\r
-}pg_CS;\r
-extern pg_CS CS_Table[];\r
-\r
-extern int pg_mbslen(const unsigned char *string);\r
-extern unsigned char *pg_mbschr(const unsigned char *string, unsigned int character);\r
-extern unsigned char *pg_mbsinc( const unsigned char *current );\r
-\r
-/* Old Type Compatible */\r
-#define multibyte_init() (PG_CCST = 0)\r
-#define multibyte_char_check(X) pg_CS_stat(PG_CCST, (unsigned int) X, PG_CCSC)\r
-#define multibyte_strchr(X,Y) pg_mbschr(X,Y)\r
-#define check_client_encoding(X) pg_CS_name(PG_CCSC = pg_CS_code(X))\r
+// unsigned char *multibyte_strchr(const unsigned char *string, unsigned int c);
+
+/* New Type */
+
+extern void CC_lookup_characterset(ConnectionClass *self);
+
+extern int pg_CS_stat(int stat,unsigned int charcter,int characterset_code);
+extern int pg_CS_code(const unsigned char *stat_string);
+extern unsigned char *pg_CS_name(int code);
+
+typedef struct pg_CS
+{
+       unsigned char *name;
+       int code;
+}pg_CS;
+extern int pg_mbslen(int ccsc, const unsigned char *string);
+extern unsigned char *pg_mbschr(int ccsc, const unsigned char *string, unsigned int character);
+extern unsigned char *pg_mbsinc(int ccsc, const unsigned char *current );
+
+/* Old Type Compatible */
+typedef struct
+{
+       int     ccsc;
+       const char *encstr;
+       int     pos;
+       int     ccst;
+} encoded_str;
+#define ENCODE_STATUS(enc)     ((enc).ccst)
+
+void encoded_str_constr(encoded_str *encstr, int ccsc, const char *str);
+#define make_encoded_str(encstr, conn, str) encoded_str_constr(encstr, conn->ccsc, str)
+extern int encoded_nextchar(encoded_str *encstr);
+extern int encoded_byte_check(encoded_str *encstr, int abspos);
+#define check_client_encoding(X) pg_CS_name(pg_CS_code(X))
index 0527b21c38b3e34fa2a2219a017d523ccfda01a9..cbb31dad0a729895794320ef1fbe93df451b1c1a 100644 (file)
@@ -174,7 +174,8 @@ SQLError(HENV EnvironmentHandle,
 {
        mylog("[SQLError]");
        return PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle,
-                  Sqlstate, NativeError, MessageText, BufferLength, TextLength);
+                  Sqlstate, NativeError, MessageText, BufferLength,
+               TextLength);
 }
 
 RETCODE                SQL_API
@@ -281,23 +282,31 @@ SQLGetInfo(HDBC ConnectionHandle,
                   SQLUSMALLINT InfoType, PTR InfoValue,
                   SQLSMALLINT BufferLength, SQLSMALLINT *StringLength)
 {
-#if (ODBCVER >= 0x0300)
        RETCODE         ret;
+       ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
 
+       CC_clear_error(conn);
+#if (ODBCVER >= 0x0300)
        mylog("[SQLGetInfo(30)]");
        if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
                                                         BufferLength, StringLength)) == SQL_ERROR)
        {
                if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x0300)
-                       return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
+               {
+                       CC_clear_error(conn);
+                       ret = PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
                                                                   BufferLength, StringLength);
+               }
        }
-       return ret;
+       if (SQL_ERROR == ret)
+               CC_log_error("SQLGetInfo30", "", conn);
 #else
        mylog("[SQLGetInfo]");
-       return PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
-                                                BufferLength, StringLength);
+       if (ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
+                       BufferLength, StringLength), SQL_ERROR == ret)
+               CC_log_error("PGAPI_GetInfo", "", conn);
 #endif
+       return ret;
 }
 
 RETCODE                SQL_API
@@ -638,7 +647,7 @@ SQLTablePrivileges(
 {
        mylog("[SQLTablePrivileges]");
        return PGAPI_TablePrivileges(hstmt, szCatalogName, cbCatalogName,
-                                  szSchemaName, cbSchemaName, szTableName, cbTableName);
+                                  szSchemaName, cbSchemaName, szTableName, cbTableName, 0);
 }
 
 RETCODE                SQL_API
index 0bebf5d128c5e0b05ef5ad63c13369e7945500a0..47015a23220cf7275ae927829e7bd4f325bed996 100644 (file)
@@ -25,22 +25,27 @@ RETCODE  SQL_API SQLErrorW(HENV EnvironmentHandle,
            SQLSMALLINT *TextLength)
 {
        RETCODE ret;
-       SWORD   tlen;
+       SWORD   tlen, buflen;
        char    *qst = NULL, *mtxt = NULL;
 
        mylog("[SQLErrorW]");
        if (Sqlstate)
                qst = malloc(8);
-       if (MessageText)
-               mtxt = malloc(BufferLength);    
+       buflen = 0;
+       if (MessageText && BufferLength > 0)
+       {
+               buflen = BufferLength * 3 + 1;
+               mtxt = malloc(buflen);
+       }
        ret = PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle,
-               qst, NativeError, mtxt, BufferLength, &tlen);
+               qst, NativeError, mtxt, buflen, &tlen);
        if (qst)
                utf8_to_ucs2(qst, strlen(qst), Sqlstate, 5);
        if (TextLength)
                *TextLength = utf8_to_ucs2(mtxt, tlen, MessageText, BufferLength);
        free(qst);
-       free(mtxt);
+       if (mtxt)
+               free(mtxt);
        return ret;
 }
 
@@ -56,6 +61,7 @@ RETCODE  SQL_API SQLSetConnectOptionW(HDBC ConnectionHandle,
            SQLUSMALLINT Option, SQLUINTEGER Value)
 {
        mylog("[SQLSetConnectionOptionW]");
+if (!ConnectionHandle) return SQL_ERROR;
        ((ConnectionClass *) ConnectionHandle)->unicode = 1;
        return PGAPI_SetConnectOption(ConnectionHandle, Option, Value);
 }
index 2c5e73bf359e5d5845845e430487e2f9cd8424da..6d4ad1f287714ebd7a3728be469ae3203dfd93eb 100644 (file)
@@ -144,9 +144,7 @@ SQLEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle,
                default:
                        break;
        }
-       return SQL_ERROR;                       /* SQLSTATE HY092 ("Invalid
-                                                                * attribute/option identifier") */
-
+       return SQL_ERROR;
 }
 
 /*     SQLExtendedFetch -> SQLFetchScroll */
@@ -246,39 +244,9 @@ SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
                          SQLINTEGER *NativeError, SQLCHAR *MessageText,
                          SQLSMALLINT BufferLength, SQLSMALLINT *TextLength)
 {
-       RETCODE         ret;
-
        mylog("[[SQLGetDiagRec]]\n");
-       switch (HandleType)
-       {
-               case SQL_HANDLE_ENV:
-                       ret = PGAPI_Error(Handle, NULL, NULL, Sqlstate, NativeError,
-                                                         MessageText, BufferLength, TextLength);
-                       break;
-               case SQL_HANDLE_DBC:
-                       ret = PGAPI_Error(NULL, Handle, NULL, Sqlstate, NativeError,
-                                                         MessageText, BufferLength, TextLength);
-                       break;
-               case SQL_HANDLE_STMT:
-                       ret = PGAPI_Error(NULL, NULL, Handle, Sqlstate, NativeError,
-                                                         MessageText, BufferLength, TextLength);
-                       break;
-               default:
-                       ret = SQL_ERROR;
-       }
-       if (ret == SQL_SUCCESS_WITH_INFO &&
-               BufferLength == 0 &&
-               *TextLength)
-       {
-               SQLSMALLINT BufferLength = *TextLength + 4;
-               SQLCHAR    *MessageText = malloc(BufferLength);
-
-               ret = SQLGetDiagRec(HandleType, Handle, RecNumber, Sqlstate,
-                                                       NativeError, MessageText, BufferLength,
-                                                       TextLength);
-               free(MessageText);
-       }
-       return ret;
+       return PGAPI_GetDiagRec(HandleType, Handle, RecNumber, Sqlstate,
+                       NativeError, MessageText, BufferLength, TextLength);
 }
 
 /*     new function */
@@ -299,7 +267,7 @@ SQLGetEnvAttr(HENV EnvironmentHandle,
                        *((unsigned int *) Value) = SQL_CP_RELAXED_MATCH;
                        break;
                case SQL_ATTR_ODBC_VERSION:
-                       *((unsigned int *) Value) = SQL_OV_ODBC3;
+                       *((unsigned int *) Value) = EN_is_odbc2(env) ? SQL_OV_ODBC2 : SQL_OV_ODBC3;
                        break;
                case SQL_ATTR_OUTPUT_NTS:
                        *((unsigned int *) Value) = SQL_TRUE;
@@ -456,6 +424,7 @@ ARDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
 {
        RETCODE         ret = SQL_SUCCESS;
+       PTR             tptr;
        switch (FieldIdentifier)
        {
                case SQL_DESC_ARRAY_SIZE:
@@ -470,8 +439,34 @@ ARDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                case SQL_DESC_BIND_TYPE:
                        stmt->options.bind_size = (SQLUINTEGER) Value;
                        break;
+
+               case SQL_DESC_DATA_PTR:
+                       if (!RecNumber)
+                               stmt->bookmark.buffer = Value;
+                       else
+                               stmt->bindings[RecNumber - 1].buffer = Value;
+                       break;
+               case SQL_DESC_INDICATOR_PTR:
+                       if (!RecNumber)
+                               tptr = stmt->bookmark.used;
+                       else
+                               tptr = stmt->bindings[RecNumber - 1].used;
+                       if (Value != tptr)
+                       {
+                               ret = SQL_ERROR;
+                               stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; 
+                               stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR"; 
+                       }
+                       break;
+               case SQL_DESC_OCTET_LENGTH_PTR:
+                       if (!RecNumber)
+                               stmt->bookmark.used = Value;
+                       else
+                               stmt->bindings[RecNumber - 1].used = Value;
+                       break;
                default:ret = SQL_ERROR;
                        stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; 
+                       stmt->errormsg = "not implemedted yet"; 
        }
        return ret;
 }
@@ -495,6 +490,26 @@ APDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                case SQL_DESC_BIND_TYPE:
                        stmt->options.param_bind_type = (SQLUINTEGER) Value;
                        break;
+
+               case SQL_DESC_DATA_PTR:
+                       if (stmt->parameters_allocated < RecNumber)
+                               PGAPI_BindParameter(stmt, RecNumber, 0, 0, 0, 0, 0, 0, 0, 0);
+                       stmt->parameters[RecNumber - 1].buffer = Value;
+                       break;
+               case SQL_DESC_INDICATOR_PTR:
+                       if (stmt->parameters_allocated < RecNumber ||
+                           Value != stmt->parameters[RecNumber - 1].used)
+                       {
+                               ret = SQL_ERROR;
+                               stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; 
+                               stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR"; 
+                       }
+                       break;
+               case SQL_DESC_OCTET_LENGTH_PTR:
+                       if (stmt->parameters_allocated < RecNumber)
+                               PGAPI_BindParameter(stmt, RecNumber, 0, 0, 0, 0, 0, 0, 0, 0);
+                       stmt->parameters[RecNumber - 1].used = Value;
+                       break;
                default:ret = SQL_ERROR;
                        stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; 
        }
@@ -549,6 +564,8 @@ SQLSetDescField(SQLHDESC DescriptorHandle,
        HSTMT           hstmt;
        SQLUINTEGER     descType;
        StatementClass *stmt;
+       static const char *func = "SQLSetDescField";
+
        mylog("[[SQLSetDescField]] h=%u rec=%d field=%d val=%x\n", DescriptorHandle, RecNumber, FieldIdentifier, Value);
        hstmt = statementHandleFromDescHandle(DescriptorHandle, &descType);
        mylog("stmt=%x type=%d\n", hstmt, descType);
@@ -569,8 +586,10 @@ SQLSetDescField(SQLHDESC DescriptorHandle,
                        break;
                default:ret = SQL_ERROR;
                        stmt->errornumber = STMT_INTERNAL_ERROR; 
-                       mylog("Error not implemented\n");
+                       stmt->errormsg = "Error not implemented";
        }
+       if (ret == SQL_ERROR)
+               SC_log_error(func, "", stmt);
        return ret;
 }
 
@@ -583,6 +602,8 @@ SQLSetDescRec(SQLHDESC DescriptorHandle,
                          PTR Data, SQLINTEGER *StringLength,
                          SQLINTEGER *Indicator)
 {
+       const char *func = "SQLSetDescField";
+
        mylog("[[SQLSetDescRec]]\n");
        mylog("Error not implemented\n");
        return SQL_ERROR;
@@ -608,7 +629,10 @@ SQLSetEnvAttr(HENV EnvironmentHandle,
                        return SQL_SUCCESS;
                case SQL_ATTR_ODBC_VERSION:
                        if ((SQLUINTEGER) Value == SQL_OV_ODBC2)
-                               return SQL_SUCCESS;
+                               EN_set_odbc2(env);
+                       else
+                               EN_set_odbc3(env);
+                       return SQL_SUCCESS;
                        break;
                case SQL_ATTR_OUTPUT_NTS:
                        if ((SQLUINTEGER) Value == SQL_TRUE)
@@ -652,44 +676,46 @@ SQLSetStmtAttr(HSTMT StatementHandle,
                         * case SQL_ATTR_PREDICATE_PTR: case
                         * SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR:
                         */
-               case SQL_ATTR_PARAM_OPERATION_PTR:              /* 19 */
-               case SQL_ATTR_PARAM_STATUS_PTR:                 /* 20 */
-               case SQL_ATTR_ROW_OPERATION_PTR:                /* 24 */
                        stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
                        stmt->errormsg = "Unsupported statement option (Set)";
                        SC_log_error(func, "", stmt);
                        return SQL_ERROR;
 
-               case SQL_ATTR_PARAM_BIND_OFFSET_PTR:    /* 17 */
-                       stmt->options.param_offset_ptr = (SQLUINTEGER *) Value;
-                       break;
-               case SQL_ATTR_ROW_BIND_OFFSET_PTR:              /* 23 */
-                       stmt->options.row_offset_ptr = (SQLUINTEGER *) Value;
-                       break;
-
                case SQL_ATTR_FETCH_BOOKMARK_PTR:               /* 16 */
                        stmt->options.bookmark_ptr = Value;
                        break;
+               case SQL_ATTR_PARAM_BIND_OFFSET_PTR:    /* 17 */
+                       stmt->options.param_offset_ptr = (SQLUINTEGER *) Value;
+                       break;
                case SQL_ATTR_PARAM_BIND_TYPE:  /* 18 */
                        stmt->options.param_bind_type = (SQLUINTEGER) Value;
                        break;
+               case SQL_ATTR_PARAM_OPERATION_PTR:              /* 19 */
+                       stmt->options.param_operation_ptr = Value;
+                       break;
+               case SQL_ATTR_PARAM_STATUS_PTR:                 /* 20 */
+                       stmt->options.param_status_ptr = (SQLUSMALLINT *) Value;
+                       break;
                case SQL_ATTR_PARAMS_PROCESSED_PTR:             /* 21 */
                        stmt->options.param_processed_ptr = (SQLUINTEGER *) Value;
                        break;
                case SQL_ATTR_PARAMSET_SIZE:    /* 22 */
                        stmt->options.paramset_size = (SQLUINTEGER) Value;
                        break;
+               case SQL_ATTR_ROW_BIND_OFFSET_PTR:              /* 23 */
+                       stmt->options.row_offset_ptr = (SQLUINTEGER *) Value;
+                       break;
+               case SQL_ATTR_ROW_OPERATION_PTR:                /* 24 */
+                       stmt->options.row_operation_ptr = Value;
+                       break;
                case SQL_ATTR_ROW_STATUS_PTR:   /* 25 */
                        stmt->options.rowStatusArray = (SQLUSMALLINT *) Value;
-
                        break;
                case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
                        stmt->options.rowsFetched = (SQLUINTEGER *) Value;
-
                        break;
                case SQL_ATTR_ROW_ARRAY_SIZE:   /* 27 */
                        stmt->options.rowset_size = (SQLUINTEGER) Value;
-
                        break;
                default:
                        return PGAPI_SetStmtOption(StatementHandle, (UWORD) Attribute, (UDWORD) Value);
@@ -704,7 +730,7 @@ SQLSetStmtAttr(HSTMT StatementHandle,
 RETCODE                SQL_API
 PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
 {
-       ConnectionClass *conn = (ConnectionClass *) hdbc;
+       ConnectionClass *conn = (ConnectionClass *) hdbc;
        ConnInfo        *ci = &(conn->connInfo);
 
        if (fFunction != SQL_API_ODBC3_ALL_FUNCTIONS)
@@ -755,17 +781,14 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
        SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMDATA);          /* 48 */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLPUTDATA);            /* 49 */
 
-       /*
-        * SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTIONOPTION); 50
-        * deprecated
-        */
+       /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTIONOPTION); 50 deprecated */
        /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTOPTION); 51 deprecated */
-       SQL_FUNC_ESET(pfExists, SQL_API_SQLSPECIALCOLUMNS); /* 52 */
+       SQL_FUNC_ESET(pfExists, SQL_API_SQLSPECIALCOLUMNS);     /* 52 */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLSTATISTICS);         /* 53 */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLES); /* 54 */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLBROWSECONNECT);      /* 55 */
        if (ci->drivers.lie)
-               SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNPRIVILEGES); /* 56 not implmented yet */
+               SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNPRIVILEGES); /* 56 not implemented yet */ 
        SQL_FUNC_ESET(pfExists, SQL_API_SQLDATASOURCES);        /* 57 */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLDESCRIBEPARAM);      /* 58 */
        /* SQL_FUNC_ESET(pfExists, SQL_API_SQLEXTENDEDFETCH); 59 deprecated */
@@ -781,12 +804,11 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
        /* SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMOPTIONS); 64 deprecated */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLPRIMARYKEYS);        /* 65 */
        if (ci->drivers.lie)
-               SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURECOLUMNS); /* 66 not implmented yet */
+               SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURECOLUMNS); /* 66 not implemeted yet */ 
        SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURES);         /* 67 */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLSETPOS);             /* 68 */
-       SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSCROLLOPTIONS);           /* 69 deprecated */
-       if (ci->drivers.lie)
-               SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLEPRIVILEGES); /* 70 not implemented yet */
+       /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSCROLLOPTIONS); 69 deprecated */
+       SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLEPRIVILEGES);            /* 70 */
        /* SQL_FUNC_ESET(pfExists, SQL_API_SQLDRIVERS); */      /* 71 */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLBINDPARAMETER);      /* 72 */
 
@@ -801,7 +823,7 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
        if (ci->drivers.lie)
        {
                SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCFIELD); /* 1008 not implemented yet */
-               SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCREC); /* 1009 not implemented yet */
+               SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCREC); /* 1009 not implemented yet */
                SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGFIELD); /* 1010 not implemented yet */
        }
        SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGREC);         /* 1011 */
@@ -810,7 +832,9 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
        SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTATTR);     /* 1016 */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCFIELD);       /* 1017 */
        if (ci->drivers.lie)
-               SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCREC); /* 1018 not implemented yet */
+       {
+               SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCREC); /* 1018 not implemented yet */
+       }
        SQL_FUNC_ESET(pfExists, SQL_API_SQLSETENVATTR);         /* 1019 */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTATTR);        /* 1020 */
        SQL_FUNC_ESET(pfExists, SQL_API_SQLFETCHSCROLL);        /* 1021 */
index d2a2005c1b9f47cad12d8bb6d65850f4fdbb2dc5..35237202faa7cbf47ef2113b913f3e111541e7f5 100644 (file)
@@ -85,22 +85,37 @@ RETCODE SQL_API     SQLGetDiagRecW(SWORD fHandleType,
                SQLSMALLINT     *pcbErrorMsg)
 {
        RETCODE ret;
-        SWORD   tlen;
-        char    *qst = NULL, *mtxt = NULL;
+        SWORD   buflen, tlen;
+        char    *qstr = NULL, *mtxt = NULL;
 
        mylog("[SQLGetDiagRecW]");
         if (szSqlState)
-                qst = malloc(8);
-        if (szErrorMsg)
-                mtxt = malloc(cbErrorMsgMax);
-        ret = PGAPI_GetDiagRec(fHandleType, handle, iRecord, qst,
-                pfNativeError, mtxt, cbErrorMsgMax, &tlen);
-        if (qst)
-                utf8_to_ucs2(qst, strlen(qst), szSqlState, 5);
-       if (pcbErrorMsg)
-               *pcbErrorMsg = utf8_to_ucs2(mtxt, tlen, szErrorMsg, cbErrorMsgMax);
-        free(qst);
-        free(mtxt);
+                qstr = malloc(8);
+       buflen = 0;
+        if (szErrorMsg && cbErrorMsgMax > 0)
+       {
+               buflen = cbErrorMsgMax;
+                mtxt = malloc(buflen);
+       }
+        ret = PGAPI_GetDiagRec(fHandleType, handle, iRecord, qstr,
+                pfNativeError, mtxt, buflen, &tlen);
+       if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
+       {
+               if (qstr)
+                       utf8_to_ucs2(qstr, strlen(qstr), szSqlState, 6);
+               if (mtxt && tlen <= cbErrorMsgMax)
+               {
+                       tlen = utf8_to_ucs2(mtxt, tlen, szErrorMsg, cbErrorMsgMax);
+                       if (tlen >= cbErrorMsgMax)
+                               ret = SQL_SUCCESS_WITH_INFO;
+               }
+               if (pcbErrorMsg)
+                       *pcbErrorMsg = tlen;
+       }
+        if (qstr);
+               free(qstr);
+       if (mtxt)
+               free(mtxt);
         return ret;
 }
 
index 637f69f9699c2277cebf7b19c3d969fb5c84986d..ac1e3f28f4e9e8099d4bbdcb724488b1d6f888a6 100755 (executable)
@@ -13,7 +13,7 @@
                        SQLPrepareW, SQLPrimaryKeysW, SQLProcedureColumnsW,
                        SQLProceduresW, SQLSetCursorNameW,
                        SQLSpecialColumnsW, SQLStatisticsW, SQLTablesW,
-                       SQLTablePrivilegesW
+                       SQLTablePrivilegesW, SQLGetTypeInfoW
  *-------
  */
 
@@ -102,7 +102,11 @@ RETCODE SQL_API SQLDriverConnectW(HDBC hdbc,
        ret = PGAPI_DriverConnect(hdbc, hwnd, szIn, (SWORD) inlen,
                szOut, cbConnStrOutMax, &olen, fDriverCompletion);
        if (ret != SQL_ERROR)
-               *pcbConnStrOut = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
+       {
+               UInt4 outlen = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
+               if (pcbConnStrOut)
+                       *pcbConnStrOut = outlen;
+       }
        free(szOut);
        if (szIn);
                free(szIn);
@@ -129,7 +133,11 @@ RETCODE SQL_API SQLBrowseConnectW(
        ret = PGAPI_BrowseConnect(hdbc, szIn, (SWORD) inlen,
                szOut, cbConnStrOutMax, &olen);
        if (ret != SQL_ERROR)
-               *pcbConnStrOut = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
+       {
+               UInt4   outlen = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
+               if (pcbConnStrOut)
+                       *pcbConnStrOut = outlen;
+       }
        free(szOut);
        if (szIn);
                free(szIn);
@@ -158,15 +166,28 @@ RETCODE  SQL_API SQLDescribeColW(HSTMT StatementHandle,
            SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable)
 {
        RETCODE ret;
-       SWORD   nmlen;
+       SWORD   buflen, nmlen;
        char    *clName;
 
        mylog("[SQLDescribeColW]");
-       clName = malloc(BufferLength);
+       buflen = BufferLength * 3 + 1;
+       clName = malloc(buflen);
        ret = PGAPI_DescribeCol(StatementHandle, ColumnNumber,
-               clName, BufferLength, &nmlen,
-               DataType, ColumnSize, DecimalDigits, Nullable);
-       *NameLength = utf8_to_ucs2(clName, nmlen, ColumnName, BufferLength);
+               clName, buflen, &nmlen, DataType, ColumnSize,
+               DecimalDigits, Nullable);
+       if (ret == SQL_SUCCESS)
+       {
+               UInt4   nmcount = utf8_to_ucs2(clName, nmlen, ColumnName, BufferLength);
+               if (nmcount > (UInt4) BufferLength)
+               {
+                       StatementClass  *stmt = (StatementClass *) StatementHandle;
+                       ret = SQL_SUCCESS_WITH_INFO;
+                       stmt->errornumber = STMT_TRUNCATED;
+                       stmt->errormsg = "Column name too large";
+               }
+               if (NameLength)
+                       *NameLength = nmcount;
+       }
        free(clName); 
        return ret;
 }
@@ -192,13 +213,25 @@ RETCODE  SQL_API SQLGetCursorNameW(HSTMT StatementHandle,
 {
        RETCODE ret;
        char    *crName;
-       SWORD   clen;
+       SWORD   clen, buflen;
 
        mylog("[SQLGetCursorNameW]");
-       crName = malloc(BufferLength);
-       ret = PGAPI_GetCursorName(StatementHandle, crName, BufferLength,
-               &clen);
-       *NameLength = utf8_to_ucs2(crName, (Int4) clen, CursorName, BufferLength);
+       buflen = BufferLength * 3 + 1;
+       crName = malloc(buflen);
+       ret = PGAPI_GetCursorName(StatementHandle, crName, buflen, &clen);
+       if (ret == SQL_SUCCESS) 
+       {
+               UInt4   nmcount = utf8_to_ucs2(crName, (Int4) clen, CursorName, BufferLength);
+               if (nmcount > (UInt4) BufferLength)
+               {
+                       StatementClass *stmt = (StatementClass *) StatementHandle;
+                       ret = SQL_SUCCESS_WITH_INFO;
+                       stmt->errornumber = STMT_TRUNCATED;
+                       stmt->errormsg = "Cursor name too large";
+               }
+               if (NameLength)
+                       *NameLength = utf8_to_ucs2(crName, (Int4) clen, CursorName, BufferLength);
+       }
        free(crName);
        return ret;
 }
@@ -207,23 +240,33 @@ RETCODE  SQL_API SQLGetInfoW(HDBC ConnectionHandle,
            SQLUSMALLINT InfoType, PTR InfoValue,
            SQLSMALLINT BufferLength, SQLSMALLINT *StringLength)
 {
+       ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
        RETCODE ret;
-       ((ConnectionClass *) ConnectionHandle)->unicode = 1;
+
+       conn->unicode = 1;
+       CC_clear_error(conn);
 #if (ODBCVER >= 0x0300)
        mylog("[SQLGetInfoW(30)]");
        if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
                BufferLength, StringLength)) == SQL_ERROR)
        {
-               if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x0300)
-                       return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
+               if (conn->driver_version >= 0x0300)
+               {
+                       CC_clear_error(conn);
+                       ret = PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
                                BufferLength, StringLength);
+               }
        }
-       return ret;
+       if (SQL_ERROR == ret)
+               CC_log_error("SQLGetInfoW(30)", "", conn);
 #else
        mylog("[SQLGetInfoW]");
-       return PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
+       ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
                BufferLength, StringLength);
+       if (SQL_ERROR == ret)
+               CC_log_error("SQLGetInfoW", "", conn);
 #endif
+       return ret;
 }
 
 RETCODE  SQL_API SQLPrepareW(HSTMT StatementHandle,
@@ -428,17 +471,31 @@ RETCODE SQL_API SQLNativeSqlW(
        RETCODE         ret;
        char            *szIn, *szOut;
        UInt4           slen;
-       SQLINTEGER      olen;
+       SQLINTEGER      buflen, olen;
 
        mylog("[SQLNativeSqlW]");
        ((ConnectionClass *) hdbc)->unicode = 1;
        szIn = ucs2_to_utf8(szSqlStrIn, cbSqlStrIn, &slen);
-       szOut = malloc(cbSqlStrMax);
+       buflen = 3 * cbSqlStrMax + 1;
+       szOut = malloc(buflen);
        ret = PGAPI_NativeSql(hdbc, szIn, (SQLINTEGER) slen,
-               szOut, cbSqlStrMax, &olen);
+               szOut, buflen, &olen);
        if (szIn);
                free(szIn);
-       *pcbSqlStr = utf8_to_ucs2(szOut, olen, szSqlStr, cbSqlStrMax);
+       if (ret == SQL_SUCCESS)
+       {
+               UInt4   szcount = utf8_to_ucs2(szOut, olen, szSqlStr, cbSqlStrMax);
+               if (szcount > (UInt4) cbSqlStrMax)
+               {
+                       ConnectionClass *conn = (ConnectionClass *) hdbc;
+
+                       ret = SQL_SUCCESS_WITH_INFO;
+                       conn->errornumber = CONN_TRUNCATED;
+                       conn->errormsg = "Sql string too large";
+               }
+               if (pcbSqlStr)
+                       *pcbSqlStr = szcount;
+       }
        free(szOut);
        return ret;
 }
@@ -560,3 +617,10 @@ RETCODE SQL_API SQLTablePrivilegesW(
                free(tbName);
        return ret;
 }
+
+RETCODE SQL_API        SQLGetTypeInfoW(
+               SQLHSTMT        StatementHandle,
+               SQLSMALLINT     DataType)
+{
+       return PGAPI_GetTypeInfo(StatementHandle, DataType);
+}
index 80ec7dac68ecd9b1715f319cb8f84b7d5821db63..d58f84916fc0b8086675882415be48b62a45bde5 100644 (file)
@@ -342,12 +342,13 @@ PGAPI_SetConnectOption(
                        break;
 
                case SQL_AUTOCOMMIT:
-                       if (vParam == SQL_AUTOCOMMIT_ON && CC_is_in_autocommit(conn))
+                       if (vParam == SQL_AUTOCOMMIT_ON && CC_is_in_trans(conn))
                                break;
-                       else if (vParam == SQL_AUTOCOMMIT_OFF && !CC_is_in_autocommit(conn))
+                       else if (vParam == SQL_AUTOCOMMIT_OFF && !CC_is_in_trans(conn))
                                break;
                        if (CC_is_in_trans(conn))
                                CC_commit(conn);
+
                        mylog("PGAPI_SetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%d\n", conn->transact_status, vParam);
 
                        switch (vParam)
@@ -401,8 +402,21 @@ PGAPI_SetConnectOption(
                                sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
                                if (fOption == 30002 && vParam)
                                {
-                                       if (strcmp((char *) vParam, "Microsoft Jet") == 0)
+                                       int     cmp;
+#ifdef UNICODE_SUPPORT
+                                       char *asPara;
+                                       if (conn->unicode)
+                                       {
+                                               asPara = ucs2_to_utf8((SQLWCHAR *) vParam, -1, NULL);
+                                               cmp = strcmp(asPara, "Microsoft Jet");
+                                               free(asPara);
+                                       }
+                                       else
+#endif /* UNICODE_SUPPORT */
+                                       cmp = strncmp((char *) vParam, "Microsoft Jet", 13);
+                                       if (0 == cmp)
                                        {
+                                               mylog("Microsoft Jet !!!!\n");
                                                conn->errornumber = 0;
                                                conn->ms_jet = 1;
                                                return SQL_SUCCESS;
@@ -456,7 +470,7 @@ PGAPI_GetConnectOption(
 
                case SQL_CURRENT_QUALIFIER:             /* don't use qualifiers */
                        if (pvParam)
-                               strcpy(pvParam, "");
+                               ((char *) pvParam)[0] = ((char *) pvParam)[1] = '\0';
 
                        break;
 
@@ -557,7 +571,7 @@ PGAPI_GetStmtOption(
                case SQL_GET_BOOKMARK:
                case SQL_ROW_NUMBER:
 
-                       res = stmt->result;
+                       res = SC_get_Curres(stmt);
 
                        if (stmt->manual_result || !ci->drivers.use_declarefetch)
                        {
index 525fb736fdf611677ee7814dfdfaa5944345abfa..55bb08bd93b44ccb661265f590f2375cdb591d84 100644 (file)
 #define TAB_INCR       8
 #define COL_INCR       16
 
+#ifdef MULTIBYTE
+char      *getNextToken(int ccsc, char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);
+#else
 char      *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);
+#endif /* MULTIBYTE */
 void           getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
 char           searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);
 
 
 char *
-getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
+getNextToken(
+#ifdef MULTIBYTE
+       int ccsc, /* client encoding */
+#endif /* MULTIBYTE */
+       char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
 {
        int                     i = 0;
        int                     out = 0;
        char            qc,
                                in_escape = FALSE;
+#ifdef MULTIBYTE
+       encoded_str     encstr;
+#endif
 
        if (smax <= 1)
                return NULL;
@@ -80,17 +91,22 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
        if (numeric)
                *numeric = FALSE;
 
+#ifdef MULTIBYTE
+       encoded_str_constr(&encstr, ccsc, &s[i]);
+#endif
        /* get the next token */
-       while (!isspace((unsigned char) s[i]) && s[i] != ',' &&
-                  s[i] != '\0' && out != smax)
+       while (s[i] != '\0' && out < smax)
        {
 #ifdef MULTIBYTE
-               if (multibyte_char_check(s[i]) != 0)
+               encoded_nextchar(&encstr);
+               if (ENCODE_STATUS(encstr) != 0)
                {
                        token[out++] = s[i++];
                        continue;
                }
 #endif
+               if (isspace((unsigned char) s[i]) || s[i] == ',')
+                       break;
                /* Handle quoted stuff */
                if (out == 0 && (s[i] == '\"' || s[i] == '\''))
                {
@@ -110,7 +126,8 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
                        while (s[i] != '\0' && out != smax)
                        {
 #ifdef MULTIBYTE
-                               if (multibyte_char_check(s[i]) != 0)
+                               encoded_nextchar(&encstr);
+                               if (ENCODE_STATUS(encstr) != 0)
                                {
                                        token[out++] = s[i++];
                                        continue;
@@ -197,22 +214,22 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
 
 
 #if 0
-QR_set_num_fields(stmt->result, 14);
-QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
-QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
-QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
-QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4);
-QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4);
-QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2);
-QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2);
-QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2);
-QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254);
+QR_set_num_fields(SC_get_Curres(stmt), 14);
+QR_set_field_info(SC_get_Curres(stmt), 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+QR_set_field_info(SC_get_Curres(stmt), 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+QR_set_field_info(SC_get_Curres(stmt), 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+QR_set_field_info(SC_get_Curres(stmt), 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+QR_set_field_info(SC_get_Curres(stmt), 4, "DATA_TYPE", PG_TYPE_INT2, 2);
+QR_set_field_info(SC_get_Curres(stmt), 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+QR_set_field_info(SC_get_Curres(stmt), 6, "PRECISION", PG_TYPE_INT4, 4);
+QR_set_field_info(SC_get_Curres(stmt), 7, "LENGTH", PG_TYPE_INT4, 4);
+QR_set_field_info(SC_get_Curres(stmt), 8, "SCALE", PG_TYPE_INT2, 2);
+QR_set_field_info(SC_get_Curres(stmt), 9, "RADIX", PG_TYPE_INT2, 2);
+QR_set_field_info(SC_get_Curres(stmt), 10, "NULLABLE", PG_TYPE_INT2, 2);
+QR_set_field_info(SC_get_Curres(stmt), 11, "REMARKS", PG_TYPE_TEXT, 254);
 /*     User defined fields */
-QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
-QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
+QR_set_field_info(SC_get_Curres(stmt), 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
+QR_set_field_info(SC_get_Curres(stmt), 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
 #endif
 
 void
@@ -312,9 +329,10 @@ parse_statement(StatementClass *stmt)
        stmt->ntab = 0;
 
 #ifdef MULTIBYTE
-       multibyte_init();
-#endif
+       while (pptr = ptr, (ptr = getNextToken(conn->ccsc, pptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL)
+#else
        while (pptr = ptr, (ptr = getNextToken(pptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL)
+#endif
        {
                unquoted = !(quote || dquote);
 
@@ -607,12 +625,17 @@ parse_statement(StatementClass *stmt)
                                if (!dquote)
                                {
                                        char       *ptr;
+#ifdef MULTIBYTE
+                                       encoded_str     encstr;
+                                       make_encoded_str(&encstr, conn, ti[stmt->ntab]->name);
+#endif   /* MULTIBYTE */
 
                                        /* lower case table name */
                                        for (ptr = ti[stmt->ntab]->name; *ptr; ptr++)
                                        {
 #ifdef MULTIBYTE
-                                               if ((unsigned char) *ptr >= 0x80)
+                                               encoded_nextchar(&encstr);
+                                               if (ENCODE_STATUS(encstr) != 0)
                                                        ptr++;
                                                else
 #endif   /* MULTIBYTE */
@@ -773,13 +796,13 @@ parse_statement(StatementClass *stmt)
                                 * structure
                                 */
                                strcpy(conn->col_info[conn->ntables]->name, ti[i]->name);
-                               conn->col_info[conn->ntables]->result = col_stmt->result;
+                               conn->col_info[conn->ntables]->result = SC_get_Curres(col_stmt);
 
                                /*
                                 * The connection will now free the result structures, so
                                 * make sure that the statement doesn't free it
                                 */
-                               col_stmt->result = NULL;
+                               SC_set_Result(col_stmt, NULL);
 
                                conn->ntables++;
 
index 9ee8c58983b775e62c4a48d0c65f756c1ec7a0bd..6e4c575e31ed6ac7d32a6da08b0df53a75aa3509 100644 (file)
@@ -36,37 +36,92 @@ PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
        RETCODE         ret;
        static const char *func = "PGAPI_GetDiagRec";
 
-       mylog("%s entering ", func);
+       mylog("%s entering rec=%d", func, RecNumber);
        switch (HandleType)
        {
                case SQL_HANDLE_ENV:
-                       ret = PGAPI_Error(Handle, NULL, NULL, Sqlstate, NativeError,
-                                                         MessageText, BufferLength, TextLength);
+                       ret = PGAPI_EnvError(Handle, RecNumber, Sqlstate,
+                                       NativeError, MessageText,
+                                       BufferLength, TextLength, 0);
                        break;
                case SQL_HANDLE_DBC:
-                       ret = PGAPI_Error(NULL, Handle, NULL, Sqlstate, NativeError,
-                                                         MessageText, BufferLength, TextLength);
+                       ret = PGAPI_ConnectError(Handle, RecNumber, Sqlstate,
+                                       NativeError, MessageText, BufferLength,
+                                       TextLength, 0);
                        break;
                case SQL_HANDLE_STMT:
-                       ret = PGAPI_Error(NULL, NULL, Handle, Sqlstate, NativeError,
-                                                         MessageText, BufferLength, TextLength);
+                       ret = PGAPI_StmtError(Handle, RecNumber, Sqlstate,
+                                       NativeError, MessageText, BufferLength,
+                                       TextLength, 0);
                        break;
                default:
                        ret = SQL_ERROR;
        }
-       if (ret == SQL_SUCCESS_WITH_INFO &&
-               BufferLength == 0 &&
-               *TextLength)
-       {
-               SQLSMALLINT BufferLength = *TextLength + 4;
-               SQLCHAR    *MessageText = malloc(BufferLength);
+       mylog("%s exiting %d\n", func, ret);
+       return ret;
+}
+
+RETCODE                SQL_API
+PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
+               SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier,
+               PTR DiagInfoPtr, SQLSMALLINT BufferLength,
+               SQLSMALLINT *StringLengthPtr)
+{
+       RETCODE         ret = SQL_SUCCESS;
+       static const char *func = "PGAPI_GetDiagField";
 
-               ret = PGAPI_GetDiagRec(HandleType, Handle, RecNumber, Sqlstate,
-                                                       NativeError, MessageText, BufferLength,
-                                                       TextLength);
-               free(MessageText);
+       mylog("%s entering rec=%d", func, RecNumber);
+       switch (HandleType)
+       {
+               case SQL_HANDLE_ENV:
+                       switch (DiagIdentifier)
+                       {
+                               case SQL_DIAG_CLASS_ORIGIN:
+                               case SQL_DIAG_SUBCLASS_ORIGIN:
+                               case SQL_DIAG_CONNECTION_NAME:
+                               case SQL_DIAG_MESSAGE_TEXT:
+                               case SQL_DIAG_NATIVE:
+                               case SQL_DIAG_NUMBER:
+                               case SQL_DIAG_RETURNCODE:
+                               case SQL_DIAG_SERVER_NAME:
+                               case SQL_DIAG_SQLSTATE:
+                                       break;
+                       }
+                       break;
+               case SQL_HANDLE_DBC:
+                       switch (DiagIdentifier)
+                       {
+                               case SQL_DIAG_CLASS_ORIGIN:
+                               case SQL_DIAG_SUBCLASS_ORIGIN:
+                               case SQL_DIAG_CONNECTION_NAME:
+                               case SQL_DIAG_MESSAGE_TEXT:
+                               case SQL_DIAG_NATIVE:
+                               case SQL_DIAG_NUMBER:
+                               case SQL_DIAG_RETURNCODE:
+                               case SQL_DIAG_SERVER_NAME:
+                               case SQL_DIAG_SQLSTATE:
+                                       break;
+                       }
+                       break;
+               case SQL_HANDLE_STMT:
+                       switch (DiagIdentifier)
+                       {
+                               case SQL_DIAG_CLASS_ORIGIN:
+                               case SQL_DIAG_SUBCLASS_ORIGIN:
+                               case SQL_DIAG_CONNECTION_NAME:
+                               case SQL_DIAG_MESSAGE_TEXT:
+                               case SQL_DIAG_NATIVE:
+                               case SQL_DIAG_NUMBER:
+                               case SQL_DIAG_RETURNCODE:
+                               case SQL_DIAG_SERVER_NAME:
+                               case SQL_DIAG_SQLSTATE:
+                                       break;
+                       }
+                       break;
+               default:
+                       ret = SQL_ERROR;
        }
-mylog("%s exiting\n", func);
+       mylog("%s exiting %d\n", func, ret);
        return ret;
 }
 
@@ -87,7 +142,7 @@ PGAPI_GetConnectAttr(HDBC ConnectionHandle,
                case SQL_ATTR_CONNECTION_TIMEOUT:
                case SQL_ATTR_METADATA_ID:
                        conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
-                       conn->errormsg = "Unsupported connection option (Set)";
+                       conn->errormsg = "Unsupported connect attribute (Get)";
                        return SQL_ERROR;
        }
        return PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value);
@@ -373,7 +428,7 @@ PGAPI_SetConnectAttr(HDBC ConnectionHandle,
                case SQL_ATTR_CONNECTION_TIMEOUT:
                case SQL_ATTR_METADATA_ID:
                        conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
-                       conn->errormsg = "Unsupported connection option (Set)";
+                       conn->errormsg = "Unsupported connect attribute (Set)";
                        return SQL_ERROR;
        }
        return PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value);
index 3117a6dc379a69e4ecbf3d03b05f20d6fd73994f..f7a72a28e4339ee1948cefc8f89a2c51c9791c4f 100644 (file)
@@ -11,6 +11,8 @@
 #include <string.h>
 
 #define        PODBC_NOT_SEARCH_PATTERN        1L
+#define        PODBC_ALLOW_PARTIAL_EXTRACT     1L
+#define        PODBC_ERROR_CLEAR               (1L << 1)
 
 RETCODE SQL_API PGAPI_AllocConnect(HENV EnvironmentHandle,
                                   HDBC FAR * ConnectionHandle);
@@ -56,6 +58,20 @@ RETCODE SQL_API PGAPI_Error(HENV EnvironmentHandle,
                        SQLCHAR *Sqlstate, SQLINTEGER *NativeError,
                        SQLCHAR *MessageText, SQLSMALLINT BufferLength,
                        SQLSMALLINT *TextLength);
+/* Helper functions for Error handling */
+RETCODE SQL_API PGAPI_EnvError(HENV EnvironmentHandle, SWORD RecNumber,
+                       SQLCHAR *Sqlstate, SQLINTEGER *NativeError,
+                       SQLCHAR *MessageText, SQLSMALLINT BufferLength,
+                       SQLSMALLINT *TextLength, UWORD flag);
+RETCODE SQL_API PGAPI_ConnectError(HDBC ConnectionHandle, SWORD RecNumber,
+                       SQLCHAR *Sqlstate, SQLINTEGER *NativeError,
+                       SQLCHAR *MessageText, SQLSMALLINT BufferLength,
+                       SQLSMALLINT *TextLength, UWORD flag);
+RETCODE SQL_API PGAPI_StmtError(HSTMT StatementHandle, SWORD RecNumber,
+                       SQLCHAR *Sqlstate, SQLINTEGER *NativeError,
+                       SQLCHAR *MessageText, SQLSMALLINT BufferLength,
+                       SQLSMALLINT *TextLength, UWORD flag);
+
 RETCODE SQL_API PGAPI_ExecDirect(HSTMT StatementHandle,
                                 SQLCHAR *StatementText, SQLINTEGER TextLength);
 RETCODE SQL_API PGAPI_Execute(HSTMT StatementHandle);
@@ -225,7 +241,8 @@ RETCODE SQL_API PGAPI_TablePrivileges(
                                          SQLCHAR *szSchemaName,
                                          SQLSMALLINT cbSchemaName,
                                          SQLCHAR *szTableName,
-                                         SQLSMALLINT cbTableName);
+                                         SQLSMALLINT cbTableName,
+                                         UWORD flag);
 RETCODE SQL_API PGAPI_BindParameter(
                                        HSTMT hstmt,
                                        SQLUSMALLINT ipar,
@@ -243,4 +260,25 @@ RETCODE SQL_API PGAPI_SetScrollOptions(
                                           SDWORD crowKeyset,
                                           UWORD crowRowset);
 
+#if (ODBCVER >= 0x0300)
+RETCODE SQL_API PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
+               SQLSMALLINT RecNumber, SQLCHAR *Sqlstate,
+               SQLINTEGER *NativeError, SQLCHAR *MessageText,
+               SQLSMALLINT BufferLength, SQLSMALLINT *TextLength);
+RETCODE SQL_API PGAPI_GetConnectAttr(HDBC ConnectionHandle,
+                       SQLINTEGER Attribute, PTR Value,
+                       SQLINTEGER BufferLength, SQLINTEGER *StringLength);
+RETCODE SQL_API PGAPI_GetStmtAttr(HSTMT StatementHandle,
+               SQLINTEGER Attribute, PTR Value,
+               SQLINTEGER BufferLength, SQLINTEGER *StringLength);
+RETCODE SQL_API PGAPI_SetConnectAttr(HDBC ConnectionHandle,
+                       SQLINTEGER Attribute, PTR Value,
+                       SQLINTEGER StringLength);
+RETCODE SQL_API PGAPI_SetStmtAttr(HSTMT StatementHandle,
+               SQLINTEGER Attribute, PTR Value,
+               SQLINTEGER StringLength);
+RETCODE SQL_API PGAPI_SetDescField(SQLHDESC DescriptorHandle,
+                       SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
+                       PTR Value, SQLINTEGER BufferLength);
+#endif /* ODBCVER */
 #endif   /* define_PG_API_FUNC_H__ */
index be822a2eb4da18b1103b91930c510ebc5f8893ee..8cade89b73f9f87d55d51a8a98f0bbbe37e16f76 100644 (file)
@@ -21,6 +21,7 @@
 #include "dlg_specific.h"
 #include "statement.h"
 #include "connection.h"
+#include "environ.h"
 #include "qresult.h"
 
 
@@ -90,15 +91,26 @@ Int2                sqlTypes[] = {
        SQL_TINYINT,
        SQL_VARBINARY,
        SQL_VARCHAR,
+#ifdef UNICODE_SUPPORT
+       SQL_WCHAR,
+       SQL_WVARCHAR,
+       SQL_WLONGVARCHAR,
+#endif /* UNICODE_SUPPORT */
        0
 };
 
+#if (ODBCVER >= 0x0300) && defined(OBDCINT64)
+#define        ALLOWED_C_BIGINT        SQL_C_SBIGINT
+#else
+#define        ALLOWED_C_BIGINT        SQL_C_CHAR
+#endif
 
 Int4
 sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
 {
        Int4            pgType;
-       ConnInfo   *ci = &(SC_get_conn(stmt)->connInfo);
+       ConnectionClass *conn = SC_get_conn(stmt);
+       ConnInfo        *ci = &(conn->connInfo);
 
        switch (fSqlType)
        {
@@ -110,11 +122,20 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
                        pgType = PG_TYPE_BPCHAR;
                        break;
 
+#ifdef UNICODE_SUPPORT
+               case SQL_WCHAR:
+                       pgType = PG_TYPE_BPCHAR;
+                       break;
+#endif /* UNICODE_SUPPORT */
+
                case SQL_BIT:
                        pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
                        break;
 
                case SQL_DATE:
+#if (ODBCVER >= 0x0300)
+               case SQL_TYPE_DATE:
+#endif /* ODBCVER */
                        pgType = PG_TYPE_DATE;
                        break;
 
@@ -144,6 +165,12 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
                        pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
                        break;
 
+#ifdef UNICODE_SUPPORT
+               case SQL_WLONGVARCHAR:
+                       pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
+                       break;
+#endif /* UNICODE_SUPPORT */
+
                case SQL_REAL:
                        pgType = PG_TYPE_FLOAT4;
                        break;
@@ -154,10 +181,16 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
                        break;
 
                case SQL_TIME:
+#if (ODBCVER >= 0x0300)
+               case SQL_TYPE_TIME:
+#endif /* ODBCVER */
                        pgType = PG_TYPE_TIME;
                        break;
 
                case SQL_TIMESTAMP:
+#if (ODBCVER >= 0x0300)
+               case SQL_TYPE_TIMESTAMP:
+#endif /* ODBCVER */
                        pgType = PG_TYPE_DATETIME;
                        break;
 
@@ -169,6 +202,12 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
                        pgType = PG_TYPE_VARCHAR;
                        break;
 
+#if    UNICODE_SUPPORT
+               case SQL_WVARCHAR:
+                       pgType = PG_TYPE_VARCHAR;
+                       break;
+#endif /* UNICODE_SUPPORT */
+
                default:
                        pgType = 0;                     /* ??? */
                        break;
@@ -193,7 +232,9 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
 Int2
 pgtype_to_sqltype(StatementClass *stmt, Int4 type)
 {
-       ConnInfo   *ci = &(SC_get_conn(stmt)->connInfo);
+       ConnectionClass *conn = SC_get_conn(stmt);
+       ConnInfo        *ci = &(conn->connInfo);
+       EnvironmentClass *env = (EnvironmentClass *) (conn->henv);
 
        switch (type)
        {
@@ -204,6 +245,19 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
                case PG_TYPE_NAME:
                        return SQL_CHAR;
 
+#ifdef UNICODE_SUPPORT
+               case PG_TYPE_BPCHAR:
+                       return conn->unicode ? SQL_WCHAR : SQL_CHAR;
+
+               case PG_TYPE_VARCHAR:
+                       return conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR;
+
+               case PG_TYPE_TEXT:
+                       return ci->drivers.text_as_longvarchar ? 
+                               (conn->unicode ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR) :
+                               (conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR);
+
+#else
                case PG_TYPE_BPCHAR:
                        return SQL_CHAR;
 
@@ -212,6 +266,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
 
                case PG_TYPE_TEXT:
                        return ci->drivers.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
+#endif /* UNICODE_SUPPORT */
 
                case PG_TYPE_BYTEA:
                        return SQL_VARBINARY;
@@ -229,10 +284,10 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
                        /* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
                case PG_TYPE_INT8:
 #if (ODBCVER >= 0x0300)
-                       return SQL_BIGINT;
-#else
-                       return SQL_CHAR;
+                       if (!conn->ms_jet)
+                               return SQL_BIGINT;
 #endif /* ODBCVER */
+                       return SQL_CHAR;
 
                case PG_TYPE_NUMERIC:
                        return SQL_NUMERIC;
@@ -242,12 +297,24 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
                case PG_TYPE_FLOAT8:
                        return SQL_FLOAT;
                case PG_TYPE_DATE:
+#if (ODBCVER >= 0x0300)
+                       if (EN_is_odbc3(env))
+                               return SQL_TYPE_DATE;
+#endif /* ODBCVER */
                        return SQL_DATE;
                case PG_TYPE_TIME:
+#if (ODBCVER >= 0x0300)
+                       if (EN_is_odbc3(env))
+                               return SQL_TYPE_TIME;
+#endif /* ODBCVER */
                        return SQL_TIME;
                case PG_TYPE_ABSTIME:
                case PG_TYPE_DATETIME:
                case PG_TYPE_TIMESTAMP:
+#if (ODBCVER >= 0x0300)
+                       if (EN_is_odbc3(env))
+                               return SQL_TYPE_TIMESTAMP;
+#endif /* ODBCVER */
                        return SQL_TIMESTAMP;
                case PG_TYPE_MONEY:
                        return SQL_FLOAT;
@@ -273,16 +340,18 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
 Int2
 pgtype_to_ctype(StatementClass *stmt, Int4 type)
 {
-       ConnInfo   *ci = &(SC_get_conn(stmt)->connInfo);
+       ConnectionClass *conn = SC_get_conn(stmt);
+       ConnInfo        *ci = &(conn->connInfo);
+       EnvironmentClass *env = (EnvironmentClass *) (conn->henv);
 
        switch (type)
        {
                case PG_TYPE_INT8:
 #if (ODBCVER >= 0x0300)
-                       return SQL_C_SBIGINT;
-#else
+                       if (!conn->ms_jet)
+                               return ALLOWED_C_BIGINT;
+#endif /* ODBCVER */
                        return SQL_C_CHAR;
-#endif
                case PG_TYPE_NUMERIC:
                        return SQL_C_CHAR;
                case PG_TYPE_INT2:
@@ -297,24 +366,24 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
                        return SQL_C_DOUBLE;
                case PG_TYPE_DATE:
 #if (ODBCVER >= 0x0300)
-                       return SQL_C_TYPE_DATE;
-#else
-                       return SQL_C_DATE;
+                       if (EN_is_odbc3(env))
+                               return SQL_C_TYPE_DATE;
 #endif /* ODBCVER */
+                       return SQL_C_DATE;
                case PG_TYPE_TIME:
 #if (ODBCVER >= 0x0300)
-                       return SQL_C_TYPE_TIME;
-#else
-                       return SQL_C_TIME;
+                       if (EN_is_odbc3(env))
+                               return SQL_C_TYPE_TIME;
 #endif /* ODBCVER */
+                       return SQL_C_TIME;
                case PG_TYPE_ABSTIME:
                case PG_TYPE_DATETIME:
                case PG_TYPE_TIMESTAMP:
 #if (ODBCVER >= 0x0300)
-                       return SQL_C_TYPE_TIMESTAMP;
-#else
-                       return SQL_C_TIMESTAMP;
+                       if (EN_is_odbc3(env))
+                               return SQL_C_TYPE_TIMESTAMP;
 #endif /* ODBCVER */
+                       return SQL_C_TIMESTAMP;
                case PG_TYPE_MONEY:
                        return SQL_C_FLOAT;
                case PG_TYPE_BOOL:
@@ -324,6 +393,12 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
                        return SQL_C_BINARY;
                case PG_TYPE_LO:
                        return SQL_C_BINARY;
+#ifdef UNICODE_SUPPORT
+               case PG_TYPE_BPCHAR:
+               case PG_TYPE_VARCHAR:
+               case PG_TYPE_TEXT:
+                       return conn->unicode ? SQL_C_WCHAR : SQL_C_CHAR;
+#endif /* UNICODE_SUPPORT */
 
                default:
                        /* hack until permanent type is available */
@@ -416,7 +491,7 @@ getNumericScale(StatementClass *stmt, Int4 type, int col)
        if (col < 0)
                return PG_NUMERIC_MAX_SCALE;
 
-       result = SC_get_Result(stmt);
+       result = SC_get_Curres(stmt);
 
        /*
         * Manual Result Sets -- use assigned column width (i.e., from
@@ -457,7 +532,7 @@ getNumericPrecision(StatementClass *stmt, Int4 type, int col)
        if (col < 0)
                return PG_NUMERIC_MAX_PRECISION;
 
-       result = SC_get_Result(stmt);
+       result = SC_get_Curres(stmt);
 
        /*
         * Manual Result Sets -- use assigned column width (i.e., from
@@ -520,10 +595,6 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
                        break;
        }
 
-       /*
-        * Static Precision (i.e., the Maximum Precision of the datatype) This
-        * has nothing to do with a result set.
-        */
        if (maxsize == TEXT_FIELD_SIZE + 1) /* magic length for testing */
        {
                if (PG_VERSION_GE(SC_get_conn(stmt), 7.1))
@@ -531,10 +602,14 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
                else
                        maxsize = TEXT_FIELD_SIZE;
        }
+       /*
+        * Static Precision (i.e., the Maximum Precision of the datatype) This
+        * has nothing to do with a result set.
+        */
        if (col < 0)
                return maxsize;
 
-       result = SC_get_Result(stmt);
+       result = SC_get_Curres(stmt);
 
        /*
         * Manual Result Sets -- use assigned column width (i.e., from
@@ -553,16 +628,20 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
        if (QR_get_atttypmod(result, col) > -1)
                return QR_get_atttypmod(result, col);
 
+       /* The type is really unknown */
        if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST)
        {
                p = QR_get_display_size(result, col);
                mylog("getCharPrecision: LONGEST: p = %d\n", p);
+               if (p >= 0)
+                       return p;
        }
 
-       if (p < 0 && handle_unknown_size_as == UNKNOWNS_AS_MAX)
+       if (handle_unknown_size_as == UNKNOWNS_AS_MAX)
                return maxsize;
-       else
-               return p;
+       else /* handle_unknown_size_as == DONT_KNOW */
+               return -1;
+       
 }
 
 static Int2
@@ -580,7 +659,7 @@ getTimestampScale(StatementClass *stmt, Int4 type, int col)
        if (PG_VERSION_LT(conn, 7.2))
                return 0;
 
-       result = SC_get_Result(stmt);
+       result = SC_get_Curres(stmt);
 
        /*
         * Manual Result Sets -- use assigned column width (i.e., from
@@ -615,10 +694,7 @@ getTimestampPrecision(StatementClass *stmt, Int4 type, int col)
                        fixed = 8;
                        break;
                case PG_TYPE_TIME_WITH_TMZONE:
-                       if (USE_ZONE)
-                               fixed = 11;
-                       else
-                               fixed = 8;
+                       fixed = 11;
                        break;
                case PG_TYPE_TIMESTAMP_NO_TMZONE:
                        fixed = 19;
@@ -692,7 +768,10 @@ pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
                        return getTimestampPrecision(stmt, type, col);
 
                case PG_TYPE_BOOL:
-                       return 1;
+               {
+                       BOOL    true_is_minus1 = FALSE;
+                       return true_is_minus1 ? 2 : 1;
+               }
 
                case PG_TYPE_LO:
                        return SQL_NO_TOTAL;
@@ -756,6 +835,8 @@ pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown
 Int4
 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
 {
+       ConnectionClass *conn = SC_get_conn(stmt);
+
        switch (type)
        {
                case PG_TYPE_INT2:
@@ -791,15 +872,27 @@ pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_
                        /* Character types (and NUMERIC) use the default precision */
                case PG_TYPE_VARCHAR:
                case PG_TYPE_BPCHAR:
+                       {
+                       int     coef = 1;
+                       Int4    prec = pgtype_precision(stmt, type, col, handle_unknown_size_as), maxvarc;
+                       if (conn->unicode)
+                               return (prec + 1) * 2;
 #ifdef MULTIBYTE
                        /* after 7.2 */
-                       if (PG_VERSION_GE(SC_get_conn(stmt), 7.2))
-                               return 3 * pgtype_precision(stmt, type, col, handle_unknown_size_as);
+                       if (PG_VERSION_GE(conn, 7.2))
+                               coef = 3;
                        else
-#else
-                       /* CR -> CR/LF */
-                       return 2 * pgtype_precision(stmt, type, col, handle_unknown_size_as);
 #endif   /* MULTIBYTE */
+                       if ((conn->connInfo).lf_conversion)
+                               /* CR -> CR/LF */
+                               coef = 2;
+                       if (coef == 1)
+                               return prec + 1;
+                       maxvarc = conn->connInfo.drivers.max_varchar_size;
+                       if (prec <= maxvarc && prec * coef > maxvarc)
+                               return maxvarc;
+                       return coef * prec;
+                       }
                default:
                        return pgtype_precision(stmt, type, col, handle_unknown_size_as);
        }
@@ -885,8 +978,8 @@ pgtype_auto_increment(StatementClass *stmt, Int4 type)
                case PG_TYPE_NUMERIC:
 
                case PG_TYPE_DATE:
-               case PG_TYPE_TIME:
                case PG_TYPE_TIME_WITH_TMZONE:
+               case PG_TYPE_TIME:
                case PG_TYPE_ABSTIME:
                case PG_TYPE_DATETIME:
                case PG_TYPE_TIMESTAMP:
@@ -1058,9 +1151,16 @@ sqltype_to_default_ctype(Int2 sqltype)
 #else
                        return SQL_C_CHAR;
                case SQL_BIGINT:
-                       return SQL_C_SBIGINT;
+                       return ALLOWED_C_BIGINT;
 #endif
 
+#ifdef UNICODE_SUPPORT
+               case SQL_WCHAR:
+               case SQL_WVARCHAR:
+               case SQL_WLONGVARCHAR:
+                       return SQL_C_WCHAR;
+#endif /* UNICODE_SUPPORT */
+
                case SQL_BIT:
                        return SQL_C_BIT;
 
@@ -1086,24 +1186,23 @@ sqltype_to_default_ctype(Int2 sqltype)
                        return SQL_C_BINARY;
 
                case SQL_DATE:
-#if (ODBCVER >= 0x0300)
-                       return SQL_C_TYPE_DATE;
-#else
                        return SQL_C_DATE;
-#endif /* ODBCVER */
 
                case SQL_TIME:
-#if (ODBCVER >= 0x0300)
-                       return SQL_C_TYPE_TIME;
-#else
                        return SQL_C_TIME;
-#endif /* ODBCVER */
 
                case SQL_TIMESTAMP:
+                       return SQL_C_TIMESTAMP;
+
 #if (ODBCVER >= 0x0300)
+               case SQL_TYPE_DATE:
+                       return SQL_C_TYPE_DATE;
+
+               case SQL_TYPE_TIME:
+                       return SQL_C_TYPE_TIME;
+
+               case SQL_TYPE_TIMESTAMP:
                        return SQL_C_TYPE_TIMESTAMP;
-#else
-                       return SQL_C_TIMESTAMP;
 #endif /* ODBCVER */
 
                default:
@@ -1167,6 +1266,7 @@ ctype_length(Int2 ctype)
 
                case SQL_C_BINARY:
                case SQL_C_CHAR:
+               case SQL_C_WCHAR:
                        return 0;
 
                default:                                /* should never happen */
index fc246b8b77ebf4f14f1ac8e92385c29f0513e9ca..534678e2802e28060924a5e1e084a6074f9e6256 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:           See "notice.txt" for copyright and license information.
  *
- * $Id: psqlodbc.h,v 1.57 2002/02/18 03:16:11 inoue Exp $
+ * $Id: psqlodbc.h,v 1.58 2002/03/08 08:52:53 inoue Exp $
  *
  */
 
@@ -87,7 +87,7 @@ typedef UInt4 Oid;
 #define DBMS_NAME                                      "PostgreSQL"
 #endif   /* ODBCVER */
 
-#define POSTGRESDRIVERVERSION          "07.01.0010"
+#define POSTGRESDRIVERVERSION          "07.01.0011"
 
 #ifdef WIN32
 #if (ODBCVER >= 0x0300)
@@ -254,6 +254,11 @@ void               logs_on_off(int cnopen, int, int);
 
 #include "misc.h"
 
+#ifdef UNICODE_SUPPORT
+UInt4  ucs2strlen(const SQLWCHAR *ucs2str);
+char   *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen);
+UInt4  utf8_to_ucs2(const char * utf8str, Int4 ilen, SQLWCHAR *ucs2str, UInt4 buflen);
+#endif /* UNICODE_SUPPORT */
 #ifdef _MEMORY_DEBUG_
 void      *debug_alloc(size_t);
 void      *debug_realloc(void *, size_t);
index 5b7b53583ebd17aee3fbaeefdc79b851005cbe01..698bd6c74feaf5e3002c0bbf8afa1b14d83dc153 100644 (file)
@@ -138,7 +138,7 @@ BEGIN
                     BS_NOTIFY | WS_TABSTOP,247,205,40,10
 END
 
-DLG_OPTIONS_DS DIALOG DISCARDABLE  0, 0, 267, 161
+DLG_OPTIONS_DS DIALOG DISCARDABLE  0, 0, 267, 176
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Advanced Options (DataSource)"
 FONT 10, "Terminal"
@@ -151,23 +151,27 @@ BEGIN
                     BS_AUTOCHECKBOX | WS_TABSTOP,45,28,88,10
     CONTROL         "Disallow &Premature",DS_DISALLOWPREMATURE,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,149,28,86,10
-    GROUPBOX        "Protocol",IDC_STATIC,43,44,180,25
+    CONTROL         "LF <-> CR/LF convert",DS_LFCONVERSION,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,45,43,92,10
+    CONTROL         "True is -1",DS_TRUEISMINUS1,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,149,43,86,10
+    GROUPBOX        "Protocol",IDC_STATIC,43,59,180,25
     CONTROL         "7.X,6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON | 
-                    WS_GROUP,53,54,47,10
+                    WS_GROUP,53,69,47,10
     CONTROL         "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
-                    131,54,26,10
+                    131,69,26,10
     CONTROL         "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
-                    187,54,26,10
-    GROUPBOX        "OID Options",IDC_STATIC,43,74,180,25
+                    187,69,26,10
+    GROUPBOX        "OID Options",IDC_STATIC,43,89,180,25
     CONTROL         "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX | 
-                    WS_GROUP | WS_TABSTOP,53,85,59,10
+                    WS_GROUP | WS_TABSTOP,53,100,59,10
     CONTROL         "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX | 
-                    WS_GROUP | WS_TABSTOP,161,85,55,10
-    LTEXT           "Connect &Settings:",IDC_STATIC,10,105,35,25
-    EDITTEXT        DS_CONNSETTINGS,50,105,200,20,ES_MULTILINE | 
+                    WS_GROUP | WS_TABSTOP,161,100,55,10
+    LTEXT           "Connect &Settings:",IDC_STATIC,10,120,35,25
+    EDITTEXT        DS_CONNSETTINGS,50,120,200,20,ES_MULTILINE | 
                     ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
-    DEFPUSHBUTTON   "OK",IDOK,71,135,50,14,WS_GROUP
-    PUSHBUTTON      "Cancel",IDCANCEL,146,135,50,14
+    DEFPUSHBUTTON   "OK",IDOK,71,150,50,14,WS_GROUP
+    PUSHBUTTON      "Cancel",IDCANCEL,146,150,50,14
 END
 #else
 DLG_CONFIG DIALOG DISCARDABLE  65, 43, 292, 116
@@ -255,7 +259,7 @@ BEGIN
                     BS_NOTIFY | WS_TABSTOP,233,224,40,10
 END
 
-DLG_OPTIONS_DS DIALOG DISCARDABLE  0, 0, 267, 161
+DLG_OPTIONS_DS DIALOG DISCARDABLE  0, 0, 267, 176
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Advanced Options (DataSource)"
 FONT 8, "MS Sans Serif"
@@ -268,23 +272,27 @@ BEGIN
                     BS_AUTOCHECKBOX | WS_TABSTOP,25,25,85,10
     CONTROL         "Disallow &Premature",DS_DISALLOWPREMATURE,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,130,25,85,10
-    GROUPBOX        "Protocol",IDC_STATIC,15,40,180,25
+    CONTROL         "LF <-> CR/LF convert",DS_LFCONVERSION,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,45,40,92,10
+    CONTROL         "True is -1",DS_TRUEISMINUS1,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,149,40,86,10
+    GROUPBOX        "Protocol",IDC_STATIC,15,55,180,25
     CONTROL         "7.X,6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON | WS_GROUP,25,
-                    50,35,10
+                    65,35,10
     CONTROL         "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
-                    75,50,26,10
+                    75,65,26,10
     CONTROL         "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
-                    130,50,26,10
-    GROUPBOX        "OID Options",IDC_STATIC,15,70,180,25
+                    130,65,26,10
+    GROUPBOX        "OID Options",IDC_STATIC,15,86,180,25
     CONTROL         "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX | 
-                    WS_GROUP | WS_TABSTOP,25,81,59,10
+                    WS_GROUP | WS_TABSTOP,25,96,59,10
     CONTROL         "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX | 
-                    WS_GROUP | WS_TABSTOP,115,81,51,10
-    RTEXT           "Connect &Settings:",IDC_STATIC,10,105,35,25
-    EDITTEXT        DS_CONNSETTINGS,50,105,200,20,ES_MULTILINE | 
+                    WS_GROUP | WS_TABSTOP,115,96,51,10
+    RTEXT           "Connect &Settings:",IDC_STATIC,10,120,35,25
+    EDITTEXT        DS_CONNSETTINGS,50,120,200,20,ES_MULTILINE | 
                     ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
-    DEFPUSHBUTTON   "OK",IDOK,71,135,50,14,WS_GROUP
-    PUSHBUTTON      "Cancel",IDCANCEL,146,135,50,14
+    DEFPUSHBUTTON   "OK",IDOK,71,150,50,14,WS_GROUP
+    PUSHBUTTON      "Cancel",IDCANCEL,146,150,50,14
 END
 #endif
 
@@ -354,8 +362,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 7,1,0,10
- PRODUCTVERSION 7,1,0,10
+ FILEVERSION 7,1,0,11
+ PRODUCTVERSION 7,1,0,11
  FILEFLAGSMASK 0x3L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -377,14 +385,14 @@ BEGIN
             VALUE "CompanyName", "Insight Distribution Systems\0"
 #endif
             VALUE "FileDescription", "PostgreSQL Driver\0"
-            VALUE "FileVersion", " 07.01.0010\0"
+            VALUE "FileVersion", " 07.01.0011\0"
             VALUE "InternalName", "psqlodbc\0"
             VALUE "LegalCopyright", "\0"
             VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation.  Microsoft® is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
             VALUE "OriginalFilename", "psqlodbc.dll\0"
             VALUE "PrivateBuild", "\0"
             VALUE "ProductName", "Microsoft Open Database Connectivity\0"
-            VALUE "ProductVersion", " 07.01.0010\0"
+            VALUE "ProductVersion", " 07.01.0011\0"
             VALUE "SpecialBuild", "\0"
         END
     END
diff --git a/src/interfaces/odbc/psqlodbc_api30w.def b/src/interfaces/odbc/psqlodbc_api30w.def
new file mode 100644 (file)
index 0000000..71ea830
--- /dev/null
@@ -0,0 +1,106 @@
+LIBRARY psqlodbc30
+EXPORTS
+SQLAllocConnect @1
+SQLAllocEnv @2
+SQLAllocStmt @3
+SQLBindCol @4
+SQLCancel @5
+SQLColAttributes @6
+SQLConnect @7
+SQLDescribeCol @8
+SQLDisconnect @9
+SQLError @10
+SQLExecDirect @11
+SQLExecute @12
+SQLFetch @13
+SQLFreeConnect @14
+SQLFreeEnv @15
+SQLFreeStmt @16
+SQLGetCursorName @17
+SQLNumResultCols @18
+SQLPrepare @19
+SQLRowCount @20
+SQLSetCursorName @21
+SQLTransact @23
+SQLColumns @40
+SQLDriverConnect @41
+SQLGetData @43
+SQLGetFunctions @44
+SQLGetInfo @45
+SQLGetStmtOption @46
+SQLGetTypeInfo @47
+SQLParamData @48
+SQLPutData @49
+SQLSpecialColumns @52
+SQLStatistics @53
+SQLTables @54
+SQLBrowseConnect @55
+SQLColumnPrivileges @56
+SQLDescribeParam @58
+SQLExtendedFetch @59
+SQLForeignKeys @60
+SQLMoreResults @61
+SQLNativeSql @62
+SQLNumParams @63
+SQLParamOptions @64
+SQLPrimaryKeys @65
+SQLProcedureColumns @66
+SQLProcedures @67
+SQLSetPos @68
+SQLSetScrollOptions @69
+SQLTablePrivileges @70
+SQLBindParameter @72
+
+SQLAllocHandle @80
+SQLBindParam @81
+SQLCloseCursor @82
+SQLColAttribute @83
+SQLCopyDesc @84
+SQLEndTran @85
+SQLFetchScroll @86
+SQLFreeHandle @87
+SQLGetDescField @88
+SQLGetDescRec @89
+SQLGetDiagField @90
+SQLGetDiagRec @91
+SQLGetEnvAttr @92
+SQLGetConnectAttr @93
+SQLGetStmtAttr @94
+SQLSetConnectAttr @95
+SQLSetDescField @96
+SQLSetDescRec @97
+SQLSetEnvAttr @98
+SQLSetStmtAttr @99
+
+SQLDummyOrdinal @199
+dconn_FDriverConnectProc @200
+DllMain @201
+ConfigDSN @202
+
+SQLColAttributeW       @101
+SQLColumnPrivilegesW   @102
+SQLColumnsW            @103
+SQLConnectW            @104
+SQLDescribeColW                @106
+SQLExecDirectW         @107
+SQLForeignKeysW                @108
+SQLGetConnectAttrW     @109
+SQLGetCursorNameW      @110
+SQLGetInfoW            @111
+SQLNativeSqlW          @112
+SQLPrepareW            @113
+SQLPrimaryKeysW                @114
+SQLProcedureColumnsW   @115
+SQLProceduresW         @116
+SQLSetConnectAttrW     @117
+SQLSetCursorNameW      @118
+SQLSpecialColumnsW     @119
+SQLStatisticsW         @120
+SQLTablesW             @121
+SQLTablePrivilegesW    @122
+SQLDriverConnectW      @123
+SQLGetDiagRecW         @124
+SQLGetStmtAttrW                @125
+SQLSetStmtAttrW                @126
+SQLSetDescFieldW       @127
+SQLGetTypeInfoW                @128
diff --git a/src/interfaces/odbc/psqlodbc_apiw.def b/src/interfaces/odbc/psqlodbc_apiw.def
new file mode 100644 (file)
index 0000000..c719a20
--- /dev/null
@@ -0,0 +1,84 @@
+LIBRARY psqlodbc
+EXPORTS
+SQLAllocConnect @1
+SQLAllocEnv @2
+SQLAllocStmt @3
+SQLBindCol @4
+SQLCancel @5
+SQLColAttributes @6
+SQLConnect @7
+SQLDescribeCol @8
+SQLDisconnect @9
+SQLError @10
+SQLExecDirect @11
+SQLExecute @12
+SQLFetch @13
+SQLFreeConnect @14
+SQLFreeEnv @15
+SQLFreeStmt @16
+SQLGetCursorName @17
+SQLNumResultCols @18
+SQLPrepare @19
+SQLRowCount @20
+SQLSetCursorName @21
+SQLTransact @23
+SQLColumns @40
+SQLDriverConnect @41
+SQLGetConnectOption @42
+SQLGetData @43
+SQLGetFunctions @44
+SQLGetInfo @45
+SQLGetStmtOption @46
+SQLGetTypeInfo @47
+SQLParamData @48
+SQLPutData @49
+SQLSetConnectOption @50
+SQLSetStmtOption @51
+SQLSpecialColumns @52
+SQLStatistics @53
+SQLTables @54
+SQLBrowseConnect @55
+SQLColumnPrivileges @56
+SQLDescribeParam @58
+SQLExtendedFetch @59
+SQLForeignKeys @60
+SQLMoreResults @61
+SQLNativeSql @62
+SQLNumParams @63
+SQLParamOptions @64
+SQLPrimaryKeys @65
+SQLProcedureColumns @66
+SQLProcedures @67
+SQLSetPos @68
+SQLSetScrollOptions @69
+SQLTablePrivileges @70
+SQLBindParameter @72
+
+SQLColAttributesW      @101
+SQLColumnPrivilegesW   @102
+SQLColumnsW            @103
+SQLConnectW            @104
+SQLDescribeColW                @106
+SQLExecDirectW         @107
+SQLForeignKeysW                @108
+SQLGetConnectOptionW   @109
+SQLGetCursorNameW      @110
+SQLGetInfoW            @111
+SQLNativeSqlW          @112
+SQLPrepareW            @113
+SQLPrimaryKeysW                @114
+SQLProcedureColumnsW   @115
+SQLProceduresW         @116
+SQLSetConnectOptionW   @117
+SQLSetCursorNameW      @118
+SQLSpecialColumnsW     @119
+SQLStatisticsW         @120
+SQLTablesW             @121
+SQLTablePrivilegesW    @122
+SQLDriverConnectW      @123
+SQLErrorW              @124
+SQLGetTypeInfoW                @128
+
+dconn_FDriverConnectProc @200
+DllMain @201
+ConfigDSN @202
index 2cbe64f0b4c4af4b8f7528ad205f54397392dee1..2e462bf5d5bec69e27529fbf32ab10a9605f57ed 100644 (file)
@@ -108,6 +108,7 @@ QR_Constructor()
                rv->command = NULL;
                rv->notice = NULL;
                rv->conn = NULL;
+               rv->next = NULL;
                rv->inTuples = FALSE;
                rv->fcount = 0;
                rv->fetch_count = 0;
@@ -160,6 +161,9 @@ QR_Destructor(QResultClass *self)
        /* Free notice info (this is from strdup()) */
        if (self->notice)
                free(self->notice);
+       /* Destruct the result object in the chain */
+       if (self->next)
+               QR_Destructor(self->next);
 
        free(self);
 
@@ -247,6 +251,7 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
 
                if (self->cursor)
                        free(self->cursor);
+               self->cursor = NULL;
 
                if (fetch_cursor)
                {
@@ -342,7 +347,7 @@ QR_close(QResultClass *self)
                sprintf(buf, "close %s", self->cursor);
                mylog("QResult: closing cursor: '%s'\n", buf);
 
-               res = CC_send_query(self->conn, buf, NULL);
+               res = CC_send_query(self->conn, buf, NULL, TRUE);
 
                self->inTuples = FALSE;
                self->currTuple = -1;
@@ -487,13 +492,11 @@ QR_next_tuple(QResultClass *self)
                        qi.row_size = self->cache_size;
                        qi.result_in = self;
                        qi.cursor = NULL;
-                       res = CC_send_query(self->conn, fetch, &qi);
-                       if (res == NULL || QR_get_aborted(res))
+                       res = CC_send_query(self->conn, fetch, &qi, TRUE);
+                       if (res == NULL)
                        {
                                self->status = PGRES_FATAL_ERROR;
                                QR_set_message(self, "Error fetching next group.");
-                               if (res)
-                                       QR_Destructor(res);
                                return FALSE;
                        }
                        self->inTuples = TRUE;
@@ -689,7 +692,7 @@ QR_read_tuple(QResultClass *self, char binary)
                         */
 
                        flds = self->fields;
-                       if (flds->display_size[field_lf] < len)
+                       if (flds && flds->display_size && flds->display_size[field_lf] < len)
                                flds->display_size[field_lf] = len;
                }
 
index 251bc449c126f0d09e84295b8372937bad4b3287..b304fd5d351d718925c646927b3db8464d118a39 100644 (file)
@@ -45,6 +45,7 @@ struct QResultClass_
        TupleListClass *manual_tuples;          /* manual result tuple list */
        ConnectionClass *conn;          /* the connection this result is using
                                                                 * (backend) */
+       QResultClass    *next;          /* the following result class */
 
        /* Stuff for declare/fetch tuples */
        int                     count_allocated;        /* m(re)alloced count */
index b8bbd4fcfc1fa599bdfef45a22cae5cf6f1723b7..4cd1639887ba2229f6657d038a65df0e50585b48 100644 (file)
@@ -52,6 +52,8 @@
 #define DRV_OR_DSN                                             1059\r
 #define DRV_DEBUG                      1060\r
 #define DS_DISALLOWPREMATURE           1061\r
+#define DS_LFCONVERSION                        1062\r
+#define DS_TRUEISMINUS1                        1063\r
 \r
 /*     Next default values for new objects\r */
 /*\r */
index 4d221cacc63a253dc9989427792c4423b7db7081..e43c0e3db45df71f06d6c9ca89f458d7894821a1 100644 (file)
@@ -8,7 +8,7 @@
  *
  * API functions:      SQLRowCount, SQLNumResultCols, SQLDescribeCol,
  *                                     SQLColAttributes, SQLGetData, SQLFetch, SQLExtendedFetch,
- *                                     SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI),
+ *                                     SQLMoreResults, SQLSetPos, SQLSetScrollOptions(NI),
  *                                     SQLSetCursorName, SQLGetCursorName
  *
  * Comments:           See "notice.txt" for copyright and license information.
@@ -45,6 +45,7 @@ PGAPI_RowCount(
                           *ptr;
        ConnInfo   *ci;
 
+       mylog("%s: entering...\n", func);
        if (!stmt)
        {
                SC_log_error(func, "", NULL);
@@ -62,7 +63,7 @@ PGAPI_RowCount(
        {
                if (stmt->status == STMT_FINISHED)
                {
-                       res = SC_get_Result(stmt);
+                       res = SC_get_Curres(stmt);
 
                        if (res && pcrow)
                        {
@@ -73,7 +74,7 @@ PGAPI_RowCount(
        }
        else
        {
-               res = SC_get_Result(stmt);
+               res = SC_get_Curres(stmt);
                if (res && pcrow)
                {
                        msg = QR_get_command(res);
@@ -115,6 +116,7 @@ PGAPI_NumResultCols(
        char            parse_ok;
        ConnInfo   *ci;
 
+       mylog("%s: entering...\n", func);
        if (!stmt)
        {
                SC_log_error(func, "", NULL);
@@ -144,7 +146,7 @@ PGAPI_NumResultCols(
        if (!parse_ok)
        {
                SC_pre_execute(stmt);
-               result = SC_get_Result(stmt);
+               result = SC_get_Curres(stmt);
 
                mylog("PGAPI_NumResultCols: result = %u, status = %d, numcols = %d\n", result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1);
                if ((!result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
@@ -210,6 +212,25 @@ PGAPI_DescribeCol(
 
        SC_clear_error(stmt);
 
+#if (ODBCVER >= 0x0300)
+       if (0 == icol) /* bookmark column */
+       {
+               SQLSMALLINT     fType = SQL_INTEGER;
+               if (szColName && cbColNameMax > 0)
+                       *szColName = '\0';
+               if (pcbColName)
+                       *pcbColName = 0;
+               if (pfSqlType)
+                       *pfSqlType = fType;
+               if (pcbColDef)
+                       *pcbColDef = 10;
+               if (pibScale)
+                       *pibScale = 0;
+               if (pfNullable)
+                       *pfNullable = SQL_NO_NULLS;
+               return SQL_SUCCESS;
+       }
+#endif /* ODBCVER */
        /*
         * Dont check for bookmark column. This is the responsibility of the
         * driver manager.
@@ -262,7 +283,7 @@ PGAPI_DescribeCol(
        {
                SC_pre_execute(stmt);
 
-               res = SC_get_Result(stmt);
+               res = SC_get_Curres(stmt);
 
                mylog("**** PGAPI_DescribeCol: res = %u, stmt->status = %d, !finished=%d, !premature=%d\n", res, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE);
                if ((NULL == res) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
@@ -305,7 +326,7 @@ PGAPI_DescribeCol(
        if (pcbColName)
                *pcbColName = len;
 
-       if (szColName)
+       if (szColName && cbColNameMax > 0)
        {
                strncpy_null(szColName, col_name, cbColNameMax);
 
@@ -379,17 +400,19 @@ PGAPI_ColAttributes(
 {
        static char *func = "PGAPI_ColAttributes";
        StatementClass *stmt = (StatementClass *) hstmt;
-       Int4            field_type = 0;
-       ConnInfo   *ci;
+       Int4            col_idx, field_type = 0;
+       ConnectionClass *conn;
+       ConnInfo        *ci;
        int                     unknown_sizes;
        int                     cols = 0;
        char            parse_ok;
        RETCODE         result;
-       char       *p = NULL;
+       const char   *p = NULL;
        int                     len = 0,
                                value = 0;
+       const   FIELD_INFO      *fi = NULL;
 
-       mylog("%s: entering...\n", func);
+       mylog("%s: entering..col=%d %d.\n", func, icol, fDescType);
 
        if (!stmt)
        {
@@ -397,7 +420,8 @@ PGAPI_ColAttributes(
                return SQL_INVALID_HANDLE;
        }
 
-       ci = &(SC_get_conn(stmt)->connInfo);
+       conn = SC_get_conn(stmt);
+       ci = &(conn->connInfo);
 
        /*
         * Dont check for bookmark column.      This is the responsibility of the
@@ -405,7 +429,24 @@ PGAPI_ColAttributes(
         * is ignored anyway, so it may be 0.
         */
 
-       icol--;
+#if (ODBCVER >= 0x0300)
+       if (0 == icol) /* bookmark column */
+       {
+               switch (fDescType)
+               {
+                       case SQL_DESC_OCTET_LENGTH:
+                               if (pfDesc)
+                                       *pfDesc = 4;
+                               break;
+                       case SQL_DESC_TYPE:
+                               if (pfDesc)
+                                       *pfDesc = SQL_INTEGER;
+                               break;
+               }
+               return SQL_SUCCESS;
+       }
+#endif /* ODBCVER */
+       col_idx = icol - 1;
 
        /* atoi(ci->unknown_sizes); */
        unknown_sizes = ci->drivers.unknown_sizes;
@@ -437,28 +478,30 @@ PGAPI_ColAttributes(
                        return SQL_SUCCESS;
                }
 
-               if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
+               if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[col_idx])
                {
-                       if (icol >= cols)
+                       if (col_idx >= cols)
                        {
                                stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
                                stmt->errormsg = "Invalid column number in ColAttributes.";
                                SC_log_error(func, "", stmt);
                                return SQL_ERROR;
                        }
-                       field_type = stmt->fi[icol]->type;
+                       field_type = stmt->fi[col_idx]->type;
                        if (field_type > 0)
                                parse_ok = TRUE;
                }
        }
 
-       if (!parse_ok)
+       if (parse_ok)
+               fi = stmt->fi[col_idx];
+       else
        {
                SC_pre_execute(stmt);
 
-               mylog("**** PGAPI_ColAtt: result = %u, status = %d, numcols = %d\n", stmt->result, stmt->status, stmt->result != NULL ? QR_NumResultCols(stmt->result) : -1);
+               mylog("**** PGAPI_ColAtt: result = %u, status = %d, numcols = %d\n", SC_get_Curres(stmt), stmt->status, SC_get_Curres(stmt) != NULL ? QR_NumResultCols(SC_get_Curres(stmt)) : -1);
 
-               if ((NULL == stmt->result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
+               if ((NULL == SC_get_Curres(stmt)) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
                {
                        stmt->errormsg = "Can't get column attributes: no result found.";
                        stmt->errornumber = STMT_SEQUENCE_ERROR;
@@ -466,13 +509,17 @@ PGAPI_ColAttributes(
                        return SQL_ERROR;
                }
 
-               cols = QR_NumResultCols(stmt->result);
+               cols = QR_NumResultCols(SC_get_Curres(stmt));
 
                /*
                 * Column Count is a special case.      The Column number is ignored
                 * in this case.
                 */
+#if (ODBCVER >= 0x0300)
+               if (fDescType == SQL_DESC_COUNT)
+#else
                if (fDescType == SQL_COLUMN_COUNT)
+#endif /* ODBCVER */
                {
                        if (pfDesc)
                                *pfDesc = cols;
@@ -480,7 +527,7 @@ PGAPI_ColAttributes(
                        return SQL_SUCCESS;
                }
 
-               if (icol >= cols)
+               if (col_idx >= cols)
                {
                        stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
                        stmt->errormsg = "Invalid column number in ColAttributes.";
@@ -488,21 +535,21 @@ PGAPI_ColAttributes(
                        return SQL_ERROR;
                }
 
-               field_type = QR_get_field_type(stmt->result, icol);
+               field_type = QR_get_field_type(SC_get_Curres(stmt), col_idx);
        }
 
-       mylog("colAttr: col %d field_type = %d\n", icol, field_type);
+       mylog("colAttr: col %d field_type = %d\n", col_idx, field_type);
 
        switch (fDescType)
        {
-               case SQL_COLUMN_AUTO_INCREMENT:
+               case SQL_COLUMN_AUTO_INCREMENT: /* == SQL_DESC_AUTO_UNIQUE_VALUE */
                        value = pgtype_auto_increment(stmt, field_type);
                        if (value == -1)        /* non-numeric becomes FALSE (ODBC Doc) */
                                value = FALSE;
 
                        break;
 
-               case SQL_COLUMN_CASE_SENSITIVE:
+               case SQL_COLUMN_CASE_SENSITIVE: /* == SQL_DESC_CASE_SENSITIVE */
                        value = pgtype_case_sensitive(stmt, field_type);
                        break;
 
@@ -511,17 +558,17 @@ PGAPI_ColAttributes(
                         *
                         * case SQL_COLUMN_COUNT:
                         */
-               case SQL_COLUMN_DISPLAY_SIZE:
-                       value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol, unknown_sizes);
+               case SQL_COLUMN_DISPLAY_SIZE: /* == SQL_DESC_DISPLAY_SIZE */
+                       value = fi ? fi->display_size : pgtype_display_size(stmt, field_type, col_idx, unknown_sizes);
 
-                       mylog("PGAPI_ColAttributes: col %d, display_size= %d\n", icol, value);
+                       mylog("PGAPI_ColAttributes: col %d, display_size= %d\n", col_idx, value);
 
                        break;
 
-               case SQL_COLUMN_LABEL:
-                       if (parse_ok && stmt->fi[icol]->alias[0] != '\0')
+               case SQL_COLUMN_LABEL: /* == SQL_DESC_LABEL */
+                       if (fi && fi->alias[0] != '\0')
                        {
-                               p = stmt->fi[icol]->alias;
+                               p = fi->alias;
 
                                mylog("PGAPI_ColAttr: COLUMN_LABEL = '%s'\n", p);
                                break;
@@ -529,70 +576,78 @@ PGAPI_ColAttributes(
                        }
                        /* otherwise same as column name -- FALL THROUGH!!! */
 
+#if (ODBCVER >= 0x0300)
+               case SQL_DESC_NAME:
+#else
                case SQL_COLUMN_NAME:
-                       p = (parse_ok) ? stmt->fi[icol]->name : QR_get_fieldname(stmt->result, icol);
+#endif /* ODBCVER */
+                       p = fi ? (fi->alias[0] ? fi->alias : fi->name) : QR_get_fieldname(SC_get_Curres(stmt), col_idx);
 
                        mylog("PGAPI_ColAttr: COLUMN_NAME = '%s'\n", p);
                        break;
 
                case SQL_COLUMN_LENGTH:
-                       value = (parse_ok) ? stmt->fi[icol]->length : pgtype_length(stmt, field_type, icol, unknown_sizes);
+                       value = fi ? fi->length : pgtype_length(stmt, field_type, col_idx, unknown_sizes);
 
-                       mylog("PGAPI_ColAttributes: col %d, length = %d\n", icol, value);
+                       mylog("PGAPI_ColAttributes: col %d, length = %d\n", col_idx, value);
                        break;
 
-               case SQL_COLUMN_MONEY:
+               case SQL_COLUMN_MONEY: /* == SQL_DESC_FIXED_PREC_SCALE */
                        value = pgtype_money(stmt, field_type);
                        break;
 
+#if (ODBCVER >= 0x0300)
+               case SQL_DESC_NULLABLE:
+#else
                case SQL_COLUMN_NULLABLE:
-                       value = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, field_type);
+#endif /* ODBCVER */
+                       value = fi ? fi->nullable : pgtype_nullable(stmt, field_type);
                        break;
 
-               case SQL_COLUMN_OWNER_NAME:
+               case SQL_COLUMN_OWNER_NAME: /* == SQL_DESC_SCHEMA_NAME */
                        p = "";
                        break;
 
                case SQL_COLUMN_PRECISION:
-                       value = (parse_ok) ? stmt->fi[icol]->precision : pgtype_precision(stmt, field_type, icol, unknown_sizes);
+                       value = fi ? fi->precision : pgtype_precision(stmt, field_type, col_idx, unknown_sizes);
 
-                       mylog("PGAPI_ColAttributes: col %d, precision = %d\n", icol, value);
+                       mylog("PGAPI_ColAttributes: col %d, precision = %d\n", col_idx, value);
                        break;
 
-               case SQL_COLUMN_QUALIFIER_NAME:
+               case SQL_COLUMN_QUALIFIER_NAME: /* == SQL_DESC_CATALOG_NAME */
                        p = "";
                        break;
 
                case SQL_COLUMN_SCALE:
-                       value = pgtype_scale(stmt, field_type, icol);
+                       value = pgtype_scale(stmt, field_type, col_idx);
                        break;
 
-               case SQL_COLUMN_SEARCHABLE:
+               case SQL_COLUMN_SEARCHABLE: /* SQL_DESC_SEARCHABLE */
                        value = pgtype_searchable(stmt, field_type);
                        break;
 
-               case SQL_COLUMN_TABLE_NAME:
-                       p = (parse_ok && stmt->fi[icol]->ti) ? stmt->fi[icol]->ti->name : "";
+               case SQL_COLUMN_TABLE_NAME: /* == SQL_DESC_TABLE_NAME */
+                       p = fi && (fi->ti) ? fi->ti->name : "";
 
                        mylog("PGAPI_ColAttr: TABLE_NAME = '%s'\n", p);
                        break;
 
-               case SQL_COLUMN_TYPE:
+               case SQL_COLUMN_TYPE: /* == SQL_DESC_CONCISE_TYPE */
                        value = pgtype_to_sqltype(stmt, field_type);
                        break;
 
-               case SQL_COLUMN_TYPE_NAME:
+               case SQL_COLUMN_TYPE_NAME: /* == SQL_DESC_TYPE_NAME */
                        p = pgtype_to_name(stmt, field_type);
                        break;
 
-               case SQL_COLUMN_UNSIGNED:
+               case SQL_COLUMN_UNSIGNED: /* == SQL_DESC_UNSINGED */
                        value = pgtype_unsigned(stmt, field_type);
                        if (value == -1)        /* non-numeric becomes TRUE (ODBC Doc) */
                                value = TRUE;
 
                        break;
 
-               case SQL_COLUMN_UPDATABLE:
+               case SQL_COLUMN_UPDATABLE: /* == SQL_DESC_UPDATABLE */
 
                        /*
                         * Neither Access or Borland care about this.
@@ -604,6 +659,60 @@ PGAPI_ColAttributes(
 
                        mylog("PGAPI_ColAttr: UPDATEABLE = %d\n", value);
                        break;
+#if (ODBCVER >= 0x0300)
+               case SQL_DESC_BASE_COLUMN_NAME:
+
+                       p = fi ? fi->name : QR_get_fieldname(SC_get_Curres(stmt), col_idx);
+
+                       mylog("PGAPI_ColAttr: BASE_COLUMN_NAME = '%s'\n", p);
+                       break;
+               case SQL_DESC_BASE_TABLE_NAME: /* the same as TABLE_NAME ok ? */
+                       p = fi && (fi->ti) ? fi->ti->name : "";
+
+                       mylog("PGAPI_ColAttr: BASE_TABLE_NAME = '%s'\n", p);
+                       break;
+               case SQL_DESC_LENGTH: /* different from SQL_COLUMN_LENGTH */
+                       value = fi ? fi->length : pgtype_length(stmt, field_type, col_idx, unknown_sizes);
+
+                       mylog("PGAPI_ColAttributes: col %d, length = %d\n", col_idx, value);
+                       break;
+               case SQL_DESC_OCTET_LENGTH:
+                       value = fi ? fi->length : pgtype_length(stmt, field_type, col_idx, unknown_sizes);
+
+                       mylog("PGAPI_ColAttributes: col %d, octet_length = %d\n", col_idx, value);
+                       break;
+               case SQL_DESC_PRECISION: /* different from SQL_COLUMN_PRECISION */
+                       value = fi ? fi->precision : pgtype_precision(stmt, field_type, col_idx, unknown_sizes);
+
+                       mylog("PGAPI_ColAttributes: col %d, desc_precision = %d\n", col_idx, value);
+                       break;
+               case SQL_DESC_SCALE: /* different from SQL_COLUMN_SCALE */
+                       value = pgtype_scale(stmt, field_type, col_idx);
+                       break;
+               case SQL_DESC_LOCAL_TYPE_NAME:
+                       p = pgtype_to_name(stmt, field_type);
+                       break;
+               case SQL_DESC_TYPE:
+                       value = pgtype_to_sqltype(stmt, field_type);
+                       switch (value)
+                       {
+                               case SQL_TYPE_DATE:
+                               case SQL_TYPE_TIME:
+                               case SQL_TYPE_TIMESTAMP:
+                                       value = SQL_DATETIME;
+                                       break;
+                       }
+                       break;
+               case SQL_DESC_LITERAL_PREFIX:
+               case SQL_DESC_LITERAL_SUFFIX:
+               case SQL_DESC_NUM_PREC_RADIX:
+               case SQL_DESC_UNNAMED:
+#endif /* ODBCVER */
+               default:
+                       stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
+                       stmt->errormsg = "ColAttribute for this type not implemented yet";
+                       SC_log_error(func, "", stmt);
+                       return SQL_ERROR;
        }
 
        result = SQL_SUCCESS;
@@ -614,6 +723,14 @@ PGAPI_ColAttributes(
 
                if (rgbDesc)
                {
+#ifdef UNICODE_SUPPORT
+                       if (conn->unicode)
+                       {
+                               len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbDesc, cbDescMax / 2);
+                               len *= 2;
+                       }
+                       else
+#endif /* UNICODE_SUPPORT */
                        strncpy_null((char *) rgbDesc, p, (size_t) cbDescMax);
 
                        if (len >= cbDescMax)
@@ -667,7 +784,7 @@ PGAPI_GetData(
                return SQL_INVALID_HANDLE;
        }
        ci = &(SC_get_conn(stmt)->connInfo);
-       res = stmt->result;
+       res = SC_get_Curres(stmt);
 
        if (STMT_EXECUTING == stmt->status)
        {
@@ -834,7 +951,7 @@ PGAPI_Fetch(
        StatementClass *stmt = (StatementClass *) hstmt;
        QResultClass *res;
 
-       mylog("PGAPI_Fetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result);
+       mylog("PGAPI_Fetch: stmt = %u, stmt->result= %u\n", stmt, SC_get_Curres(stmt));
 
        if (!stmt)
        {
@@ -844,7 +961,7 @@ PGAPI_Fetch(
 
        SC_clear_error(stmt);
 
-       if (!(res = stmt->result))
+       if (!(res = SC_get_Curres(stmt)))
        {
                stmt->errormsg = "Null statement result in PGAPI_Fetch.";
                stmt->errornumber = STMT_SEQUENCE_ERROR;
@@ -935,7 +1052,7 @@ PGAPI_ExtendedFetch(
 
        SC_clear_error(stmt);
 
-       if (!(res = stmt->result))
+       if (!(res = SC_get_Curres(stmt)))
        {
                stmt->errormsg = "Null statement result in PGAPI_ExtendedFetch.";
                stmt->errornumber = STMT_SEQUENCE_ERROR;
@@ -1214,6 +1331,15 @@ RETCODE          SQL_API
 PGAPI_MoreResults(
                                  HSTMT hstmt)
 {
+       const char *func = "PGAPI_MoreResults";
+       StatementClass  *stmt = (StatementClass *) hstmt;
+       QResultClass    *res;
+
+       mylog("%s: entering...\n", func);
+       if (stmt && (res = SC_get_Curres(stmt)))
+               SC_get_Curres(stmt) = res->next;
+       if (SC_get_Curres(stmt))
+               return SQL_SUCCESS; 
        return SQL_NO_DATA_FOUND;
 }
 
@@ -1243,12 +1369,7 @@ positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, cons
        }
        sprintf(selstr, "%s oid = %u", selstr, oid),
                mylog("selstr=%s\n", selstr);
-       qres = CC_send_query(SC_get_conn(stmt), selstr, NULL);
-       if (qres && QR_aborted(qres))
-       {
-               QR_Destructor(qres);
-               qres = (QResultClass *) 0;
-       }
+       qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, TRUE);
        return qres;
 }
 
@@ -1270,7 +1391,7 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
        rcnt = 0;
        if (count)
                *count = 0;
-       if (!(res = stmt->result))
+       if (!(res = SC_get_Curres(stmt)))
                return SQL_ERROR;
        if (!stmt->ti)
                parse_statement(stmt);  /* not preferable */
@@ -1339,7 +1460,7 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
        RETCODE         ret = SQL_ERROR;
 
        mylog("positioned new fi=%x ti=%x\n", stmt->fi, stmt->ti);
-       if (!(res = stmt->result))
+       if (!(res = SC_get_Curres(stmt)))
                return SQL_ERROR;
        if (!stmt->ti)
                parse_statement(stmt);  /* not preferable */
@@ -1401,6 +1522,41 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
        return ret;
 }
 
+static RETCODE SQL_API
+irow_update(RETCODE ret, StatementClass *stmt, UWORD irow)
+{
+       if (ret != SQL_ERROR)
+       {
+               int                     updcnt;
+               const char *cmdstr = QR_get_command(SC_get_Curres(stmt));
+
+               if (cmdstr &&
+                       sscanf(cmdstr, "UPDATE %d", &updcnt) == 1)
+               {
+                       if (updcnt == 1)
+                               SC_pos_reload(stmt, irow, (UWORD *) 0);
+                       else if (updcnt == 0)
+                       {
+                               stmt->errornumber = STMT_ROW_VERSION_CHANGED;
+                               stmt->errormsg = "the content was changed before updation";
+                               ret = SQL_ERROR;
+                               if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
+                                       SC_pos_reload(stmt, irow, (UWORD *) 0);
+                       }
+                       else
+                               ret = SQL_ERROR;
+                       stmt->currTuple = stmt->rowset_start + irow;
+               }
+               else
+                       ret = SQL_ERROR;
+               if (ret == SQL_ERROR && stmt->errornumber == 0)
+               {
+                       stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
+                       stmt->errormsg = "SetPos update return error";
+               }
+       }
+       return ret;
+}
 RETCODE                SQL_API
 SC_pos_update(StatementClass *stmt,
                          UWORD irow)
@@ -1419,8 +1575,8 @@ SC_pos_update(StatementClass *stmt,
        UInt4   offset;
        Int4    *used;
 
-       mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, stmt->result->base, stmt->fi, stmt->ti);
-       if (!(res = stmt->result))
+       mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, SC_get_Curres(stmt)->base, stmt->fi, stmt->ti);
+       if (!(res = SC_get_Curres(stmt)))
                return SQL_ERROR;
        if (!stmt->ti)
                parse_statement(stmt);  /* not preferable */
@@ -1510,40 +1666,12 @@ SC_pos_update(StatementClass *stmt,
                        stmt->errormsg = "SetPos with data_at_exec not yet supported";
                        ret = SQL_ERROR;
                }
-               if (ret != SQL_ERROR)
-               {
-                       int                     updcnt;
-                       const char *cmdstr = QR_get_command(qstmt->result);
-
-                       if (cmdstr &&
-                               sscanf(cmdstr, "UPDATE %d", &updcnt) == 1)
-                       {
-                               if (updcnt == 1)
-                                       SC_pos_reload(stmt, irow, (UWORD *) 0);
-                               else if (updcnt == 0)
-                               {
-                                       stmt->errornumber = STMT_ROW_VERSION_CHANGED;
-                                       stmt->errormsg = "the content was changed before updation";
-                                       ret = SQL_ERROR;
-                                       if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
-                                               SC_pos_reload(stmt, irow, (UWORD *) 0);
-                               }
-                               else
-                                       ret = SQL_ERROR;
-                               stmt->currTuple = stmt->rowset_start + irow;
-                       }
-                       else
-                               ret = SQL_ERROR;
-                       if (ret == SQL_ERROR && stmt->errornumber == 0)
-                       {
-                               stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
-                               stmt->errormsg = "SetPos update return error";
-                       }
-               }
+               ret = irow_update(ret, qstmt, irow);
                PGAPI_FreeStmt(hstmt, SQL_DROP);
        }
        else
                ret = SQL_SUCCESS_WITH_INFO;
+#if (ODBCVER >= 0x0300)
        if (stmt->options.rowStatusArray)
        {
                switch (ret)
@@ -1556,6 +1684,7 @@ SC_pos_update(StatementClass *stmt,
                                break;
                }
        }
+#endif /* ODBCVER */
 
        return ret;
 }
@@ -1573,7 +1702,7 @@ SC_pos_delete(StatementClass *stmt,
        char       *oidval;
 
        mylog("POS DELETE fi=%x ti=%x\n", stmt->fi, stmt->ti);
-       if (!(res = stmt->result))
+       if (!(res = SC_get_Curres(stmt)))
                return SQL_ERROR;
        if (!stmt->ti)
                parse_statement(stmt);  /* not preferable */
@@ -1591,11 +1720,11 @@ SC_pos_delete(StatementClass *stmt,
        }
        sprintf(dltstr, "delete from \"%s\" where ctid = '%s' and oid = %s",
                        stmt->ti[0]->name,
-          QR_get_value_backend_row(stmt->result, global_ridx, res_cols - 2),
+          QR_get_value_backend_row(SC_get_Curres(stmt), global_ridx, res_cols - 2),
                        oidval);
 
        mylog("dltstr=%s\n", dltstr);
-       qres = CC_send_query(SC_get_conn(stmt), dltstr, NULL);
+       qres = CC_send_query(SC_get_conn(stmt), dltstr, NULL, TRUE);
        if (qres && QR_command_successful(qres))
        {
                int                     dltcnt;
@@ -1630,6 +1759,7 @@ SC_pos_delete(StatementClass *stmt,
        }
        if (qres)
                QR_Destructor(qres);
+#if (ODBCVER >= 0x0300)
        if (stmt->options.rowStatusArray)
        {
                switch (ret)
@@ -1642,6 +1772,40 @@ SC_pos_delete(StatementClass *stmt,
                                break;
                }
        }
+#endif /* ODBCVER */
+       return ret;
+}
+
+static RETCODE SQL_API
+irow_insert(RETCODE ret, StatementClass *stmt, int addpos)
+{
+       if (ret != SQL_ERROR)
+       {
+               int                     addcnt;
+               UInt4           oid;
+               const char *cmdstr = QR_get_command(SC_get_Curres(stmt));
+
+               if (cmdstr &&
+                       sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
+                       addcnt == 1)
+               {
+                       SC_pos_newload(stmt, oid, NULL);
+                       if (stmt->bookmark.buffer)
+                       {
+                               char            buf[32];
+
+                               sprintf(buf, "%ld", addpos);
+                               copy_and_convert_field(stmt, 0, buf,
+                                SQL_C_ULONG, stmt->bookmark.buffer,
+                                0, stmt->bookmark.used);
+                       }
+               }
+               else
+               {
+                       stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
+                       stmt->errormsg = "SetPos insert return error";
+               }
+       }
        return ret;
 }
 RETCODE                SQL_API
@@ -1661,7 +1825,7 @@ SC_pos_add(StatementClass *stmt,
        Int4            *used;
 
        mylog("POS ADD fi=%x ti=%x\n", stmt->fi, stmt->ti);
-       if (!(res = stmt->result))
+       if (!(res = SC_get_Curres(stmt)))
                return SQL_ERROR;
        if (!stmt->ti)
                parse_statement(stmt);  /* not preferable */
@@ -1721,50 +1885,24 @@ SC_pos_add(StatementClass *stmt,
                mylog("addstr=%s\n", addstr);
                qstmt->exec_start_row = qstmt->exec_end_row = irow; 
                ret = PGAPI_ExecDirect(hstmt, addstr, strlen(addstr));
-               if (ret == SQL_NEED_DATA)               /* must be fixed */
-               {
-                       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
-                       stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
-                       stmt->errormsg = "SetPos with data_at_exec not yet supported";
-                       ret = SQL_ERROR;
-               }
                if (ret == SQL_ERROR)
                {
                        stmt->errornumber = qstmt->errornumber;
                        stmt->errormsg = qstmt->errormsg;
                }
-               else
+               else if (ret == SQL_NEED_DATA)          /* must be fixed */
                {
-                       int                     addcnt;
-                       UInt4           oid;
-                       const char *cmdstr = QR_get_command(qstmt->result);
-
-                       if (cmdstr &&
-                               sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
-                               addcnt == 1)
-                       {
-                               SC_pos_newload(stmt, oid, NULL);
-                               if (stmt->bookmark.buffer)
-                               {
-                                       char            buf[32];
-
-                                       sprintf(buf, "%ld", res->fcount);
-                                       copy_and_convert_field(stmt, 0, buf,
-                                                                         SQL_C_ULONG, stmt->bookmark.buffer,
-                                                                                  0, stmt->bookmark.used);
-                               }
-                       }
-                       else
-                       {
-                               stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
-                               stmt->errormsg = "SetPos insert return error";
-                               ret = SQL_ERROR;
-                       }
+                       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+                       stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
+                       stmt->errormsg = "SetPos with data_at_exec not yet supported";
+                       ret = SQL_ERROR;
                }
+               ret = irow_insert(ret, qstmt, res->fcount);
        }
        else
                ret = SQL_SUCCESS_WITH_INFO;
        PGAPI_FreeStmt(hstmt, SQL_DROP);
+#if (ODBCVER >= 0x0300)
        if (stmt->options.rowStatusArray)
        {
                switch (ret)
@@ -1777,6 +1915,8 @@ SC_pos_add(StatementClass *stmt,
                                break;
                }
        }
+#endif /* ODBCVER */
+
        return ret;
 }
 
@@ -1823,7 +1963,7 @@ PGAPI_SetPos(
                return SQL_ERROR;
        }
 
-       if (!(res = stmt->result))
+       if (!(res = SC_get_Curres(stmt)))
        {
                stmt->errormsg = "Null statement result in PGAPI_SetPos.";
                stmt->errornumber = STMT_SEQUENCE_ERROR;
index 6bcc01bd89219eb06663ee63bff2b89786ee3fbb..0175d69f32bbedabe16dc408459b4ca64f17a724 100644 (file)
@@ -90,7 +90,6 @@ ConfigDSN(HWND hwnd,
        if (!hglbAttr)
                return FALSE;
        lpsetupdlg = (LPSETUPDLG) GlobalLock(hglbAttr);
-
        /* Parse attribute string */
        if (lpszAttributes)
                ParseAttributes(lpszAttributes, lpsetupdlg);
@@ -339,7 +338,7 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
        int                     cbKey;
        char            value[MAXPGPATH];
 
-       memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo));
+       CC_conninfo_init(&(lpsetupdlg->ci));
 
        for (lpsz = lpszAttributes; *lpsz; lpsz++)
        {
index 2b2e5f0634e1cc1a8cb931caaa33462e8504f820..513c916019a51bb95cdf2bd3a5d17e788fa9bb6e 100644 (file)
@@ -159,10 +159,10 @@ PGAPI_FreeStmt(HSTMT hstmt,
                        }
 
                        /* Free any cursors and discard any result info */
-                       if (stmt->result)
+                       if (SC_get_Result(stmt))
                        {
-                               QR_Destructor(stmt->result);
-                               stmt->result = NULL;
+                               QR_Destructor(SC_get_Result(stmt));
+                               SC_set_Result(stmt,  NULL);
                        }
                }
 
@@ -230,6 +230,7 @@ SC_Constructor(void)
                rv->hdbc = NULL;                /* no connection associated yet */
                rv->phstmt = NULL;
                rv->result = NULL;
+               rv->curres = NULL;
                rv->manual_result = FALSE;
                rv->prepare = FALSE;
                rv->status = STMT_ALLOCATED;
@@ -238,7 +239,6 @@ SC_Constructor(void)
                rv->errormsg = NULL;
                rv->errornumber = 0;
                rv->errormsg_created = FALSE;
-               rv->errormsg_malloced = FALSE;
 
                rv->statement = NULL;
                rv->stmt_with_params = NULL;
@@ -292,7 +292,9 @@ SC_Constructor(void)
 char
 SC_Destructor(StatementClass *self)
 {
-       mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, self->result, self->hdbc);
+       QResultClass    *res = SC_get_Result(self);
+
+       mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, res, self->hdbc);
        SC_clear_error(self);
        if (STMT_EXECUTING == self->status)
        {
@@ -301,12 +303,12 @@ SC_Destructor(StatementClass *self)
                return FALSE;
        }
 
-       if (self->result)
+       if (res)
        {
                if (!self->hdbc)
-                       self->result->conn = NULL;      /* prevent any dbase activity */
+                       res->conn = NULL;       /* prevent any dbase activity */
 
-               QR_Destructor(self->result);
+               QR_Destructor(res);
        }
 
        if (self->statement)
@@ -442,6 +444,7 @@ char
 SC_recycle_statement(StatementClass *self)
 {
        ConnectionClass *conn;
+       QResultClass    *res;
 
        mylog("recycle statement: self= %u\n", self);
 
@@ -514,10 +517,10 @@ SC_recycle_statement(StatementClass *self)
        self->parse_status = STMT_PARSE_NONE;
 
        /* Free any cursors */
-       if (self->result)
+       if (res = SC_get_Result(self), res)
        {
-               QR_Destructor(self->result);
-               self->result = NULL;
+               QR_Destructor(res);
+               SC_set_Result(self, NULL);
        }
        self->inaccurate_result = FALSE;
 
@@ -533,12 +536,9 @@ SC_recycle_statement(StatementClass *self)
        self->bind_row = 0;
        self->last_fetch_count = 0;
 
-       if (self->errormsg_malloced && self->errormsg)
-               free(self->errormsg);
        self->errormsg = NULL;
        self->errornumber = 0;
        self->errormsg_created = FALSE;
-       self->errormsg_malloced = FALSE;
 
        self->lobj_fd = -1;
 
@@ -583,8 +583,8 @@ SC_pre_execute(StatementClass *self)
                }
                if (!SC_is_pre_executable(self))
                {
-                       self->result = QR_Constructor();
-                       QR_set_status(self->result, PGRES_TUPLES_OK);
+                       SC_set_Result(self, QR_Constructor());
+                       QR_set_status(SC_get_Result(self), PGRES_TUPLES_OK);
                        self->inaccurate_result = TRUE;
                        self->status = STMT_PREMATURE;
                }
@@ -617,12 +617,11 @@ SC_unbind_cols(StatementClass *self)
 void
 SC_clear_error(StatementClass *self)
 {
-       if (self->errormsg_malloced && self->errormsg)
-               free(self->errormsg);
        self->errornumber = 0;
        self->errormsg = NULL;
        self->errormsg_created = FALSE;
-       self->errormsg_malloced = FALSE;
+       self->errorpos = 0;
+       self->error_recsize = -1;
 }
 
 
@@ -633,7 +632,7 @@ SC_clear_error(StatementClass *self)
 char *
 SC_create_errormsg(StatementClass *self)
 {
-       QResultClass *res = self->result;
+       QResultClass *res = SC_get_Curres(self);
        ConnectionClass *conn = self->hdbc;
        int                     pos;
        static char msg[4096];
@@ -642,10 +641,21 @@ SC_create_errormsg(StatementClass *self)
 
        if (res && res->message)
                strcpy(msg, res->message);
-
        else if (self->errormsg)
                strcpy(msg, self->errormsg);
 
+       if (!msg[0] && res && QR_get_notice(res))
+       {
+               char *notice = QR_get_notice(res);
+               int len = strlen(notice);
+               if (len < sizeof(msg))
+               {
+                       memcpy(msg, notice, len);
+                       msg[len] = '\0';
+               }
+               else
+                       return notice;
+       }
        if (conn)
        {
                SocketClass *sock = conn->sock;
@@ -653,7 +663,7 @@ SC_create_errormsg(StatementClass *self)
                if (conn->errormsg && conn->errormsg[0] != '\0')
                {
                        pos = strlen(msg);
-                       sprintf(&msg[pos], ";\n%s", conn->errormsg);
+                       /*sprintf(&msg[pos], ";\n%s", conn->errormsg);*/
                }
 
                if (sock && sock->errormsg && sock->errormsg[0] != '\0')
@@ -662,9 +672,6 @@ SC_create_errormsg(StatementClass *self)
                        sprintf(&msg[pos], ";\n%s", sock->errormsg);
                }
        }
-       if (!msg[0] && res && QR_get_notice(res))
-               return QR_get_notice(res);
-
        return msg;
 }
 
@@ -679,18 +686,17 @@ SC_get_error(StatementClass *self, int *number, char **message)
        {
                self->errormsg = SC_create_errormsg(self);
                self->errormsg_created = TRUE;
+               self->errorpos = 0;
+               self->error_recsize = -1;
        }
 
        if (self->errornumber)
        {
                *number = self->errornumber;
                *message = self->errormsg;
-               if (!self->errormsg_malloced)
-                       self->errormsg = NULL;
        }
 
        rv = (self->errornumber != 0);
-       self->errornumber = 0;
 
        return rv;
 }
@@ -712,7 +718,7 @@ RETCODE
 SC_fetch(StatementClass *self)
 {
        static char *func = "SC_fetch";
-       QResultClass *res = self->result;
+       QResultClass *res = SC_get_Curres(self);
        int                     retval,
                                result;
 
@@ -901,6 +907,7 @@ SC_execute(StatementClass *self)
        static char *func = "SC_execute";
        ConnectionClass *conn;
        char            was_ok, was_nonfatal;
+       QResultClass    *res = NULL;
        Int2            oldstatus,
                                numcols;
        QueryInfo       qi;
@@ -952,12 +959,12 @@ SC_execute(StatementClass *self)
                mylog("       Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
 
                /* send the declare/select */
-               self->result = CC_send_query(conn, self->stmt_with_params, NULL);
+               res = CC_send_query(conn, self->stmt_with_params, NULL, TRUE);
 
-               if (SC_is_fetchcursor(self) && self->result != NULL &&
-                       QR_command_successful(self->result))
+               if (SC_is_fetchcursor(self) && res != NULL &&
+                       QR_command_successful(res))
                {
-                       QR_Destructor(self->result);
+                       QR_Destructor(res);
 
                        /*
                         * That worked, so now send the fetch to start getting data
@@ -976,7 +983,7 @@ SC_execute(StatementClass *self)
                         */
                        sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);
 
-                       self->result = CC_send_query(conn, fetch, &qi);
+                       res = CC_send_query(conn, fetch, &qi, FALSE);
                }
                mylog("     done sending the query:\n");
        }
@@ -984,7 +991,7 @@ SC_execute(StatementClass *self)
        {
                /* not a SELECT statement so don't use a cursor */
                mylog("      it's NOT a select statement: stmt=%u\n", self);
-               self->result = CC_send_query(conn, self->stmt_with_params, NULL);
+               res = CC_send_query(conn, self->stmt_with_params, NULL, FALSE);
 
                /*
                 * We shouldn't send COMMIT. Postgres backend does the autocommit
@@ -1003,10 +1010,10 @@ SC_execute(StatementClass *self)
        self->status = STMT_FINISHED;
 
        /* Check the status of the result */
-       if (self->result)
+       if (res)
        {
-               was_ok = QR_command_successful(self->result);
-               was_nonfatal = QR_command_nonfatal(self->result);
+               was_ok = QR_command_successful(res);
+               was_nonfatal = QR_command_nonfatal(res);
 
                if (was_ok)
                        self->errornumber = STMT_OK;
@@ -1018,24 +1025,30 @@ SC_execute(StatementClass *self)
                self->current_col = -1;
                self->rowset_start = -1;
 
-               /* see if the query did return any result columns */
-               numcols = QR_NumResultCols(self->result);
-
-               /* now allocate the array to hold the binding info */
-               if (numcols > 0)
+               /* issue "ABORT" when query aborted */
+               if (QR_get_aborted(res))
                {
-                       extend_bindings(self, numcols);
-                       if (self->bindings == NULL)
+                       if (!self->internal)
+                               CC_abort(conn);
+               }
+               else
+               {
+                       /* see if the query did return any result columns */
+                       numcols = QR_NumResultCols(res);
+                       /* now allocate the array to hold the binding info */
+                       if (numcols > 0)
                        {
-                               self->errornumber = STMT_NO_MEMORY_ERROR;
-                               self->errormsg = "Could not get enough free memory to store the binding information";
-                               SC_log_error(func, "", self);
-                               return SQL_ERROR;
+                               extend_bindings(self, numcols);
+                               if (self->bindings == NULL)
+                               {
+                                       QR_Destructor(res);
+                                       self->errornumber = STMT_NO_MEMORY_ERROR;
+                                       self->errormsg = "Could not get enough free memory to store the binding information";
+                                       SC_log_error(func, "", self);
+                                       return SQL_ERROR;
+                               }
                        }
                }
-               /* issue "ABORT" when query aborted */
-               if (QR_get_aborted(self->result) && !self->internal)
-                       CC_abort(conn);
        }
        else
        {
@@ -1061,6 +1074,15 @@ SC_execute(StatementClass *self)
                if (!self->internal)
                        CC_abort(conn);
        }
+       if (!SC_get_Result(self))
+               SC_set_Result(self, res);
+       else
+       {
+               QResultClass    *last;
+               for (last = SC_get_Result(self); last->next; last = last->next)
+                       ;
+               last->next = res;
+       }
 
        if (self->statement_type == STMT_TYPE_PROCCALL &&
                (self->errornumber == STMT_OK ||
@@ -1095,7 +1117,8 @@ SC_execute(StatementClass *self)
                return SQL_SUCCESS_WITH_INFO;
        else
        {
-               self->errormsg = "Error while executing the query";
+               if (!self->errormsg || !self->errormsg[0])
+                       self->errormsg = "Error while executing the query";
                SC_log_error(func, "", self);
                return SQL_ERROR;
        }
@@ -1103,17 +1126,19 @@ SC_execute(StatementClass *self)
 
 
 void
-SC_log_error(char *func, char *desc, StatementClass *self)
+SC_log_error(const char *func, const char *desc, const StatementClass *self)
 {
 #ifdef PRN_NULLCHECK
 #define nullcheck(a) (a ? a : "(NULL)")
 #endif
        if (self)
        {
+               QResultClass *res = SC_get_Result(self);
+
                qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
                mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
                qlog("                 ------------------------------------------------------------\n");
-               qlog("                 hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, self->result);
+               qlog("                 hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, res);
                qlog("                 manual_result=%d, prepare=%d, internal=%d\n", self->manual_result, self->prepare, self->internal);
                qlog("                 bindings=%u, bindings_allocated=%d\n", self->bindings, self->bindings_allocated);
                qlog("                 parameters=%u, parameters_allocated=%d\n", self->parameters, self->parameters_allocated);
@@ -1126,10 +1151,8 @@ SC_log_error(char *func, char *desc, StatementClass *self)
 
                qlog("                 ----------------QResult Info -------------------------------\n");
 
-               if (self->result)
+               if (res)
                {
-                       QResultClass *res = self->result;
-
                        qlog("                 fields=%u, manual_tuples=%u, backend_tuples=%u, tupleField=%d, conn=%u\n", res->fields, res->manual_tuples, res->backend_tuples, res->tupleField, res->conn);
                        qlog("                 fetch_count=%d, fcount=%d, num_fields=%d, cursor='%s'\n", res->fetch_count, res->fcount, res->num_fields, nullcheck(res->cursor));
                        qlog("                 message='%s', command='%s', notice='%s'\n", nullcheck(res->message), nullcheck(res->command), nullcheck(res->notice));
@@ -1140,6 +1163,9 @@ SC_log_error(char *func, char *desc, StatementClass *self)
                CC_log_error(func, desc, self->hdbc);
        }
        else
+       {
                qlog("INVALID STATEMENT HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
+               mylog("INVALID STATEMENT HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
+       }
 #undef PRN_NULLCHECK
 }
index 534c8db4d8aa4982fa023ae97f342257024e5347..cf104aa7d1314b1b88dde1058a4cf86bc218a569 100644 (file)
@@ -103,7 +103,7 @@ enum
        STMT_PARSE_NONE = 0,
        STMT_PARSE_COMPLETE,
        STMT_PARSE_INCOMPLETE,
-       STMT_PARSE_FATAL
+       STMT_PARSE_FATAL,
 };
 
 /*     Result style */
@@ -111,7 +111,7 @@ enum
 {
        STMT_FETCH_NONE = 0,
        STMT_FETCH_NORMAL,
-       STMT_FETCH_EXTENDED
+       STMT_FETCH_EXTENDED,
 };
 
 typedef struct
@@ -147,6 +147,7 @@ struct StatementClass_
        ConnectionClass *hdbc;          /* pointer to ConnectionClass this
                                                                 * statement belongs to */
        QResultClass *result;           /* result of the current statement */
+       QResultClass *curres;           /* the current result in the chain */
        HSTMT FAR  *phstmt;
        StatementOptions options;
 
@@ -215,14 +216,15 @@ struct StatementClass_
        char            pre_executing;  /* This statement is prematurely executing */
        char            inaccurate_result;              /* Current status is PREMATURE but
                                                                                 * result is inaccurate */
-       char            errormsg_malloced;              /* Current error message is
-                                                                                * malloed (not in a static
-                                                                                * variable) ? */
        char            miscinfo;
+       SWORD           errorpos;
+       SWORD           error_recsize;
 };
 
 #define SC_get_conn(a)   (a->hdbc)
-#define SC_get_Result(a)  (a->result);
+#define SC_set_Result(a, b)  (a->result = a->curres = b)
+#define SC_get_Result(a)  (a->result)
+#define SC_get_Curres(a)  (a->curres)
 
 /*     options for SC_free_params() */
 #define STMT_FREE_PARAMS_ALL                           0
@@ -252,7 +254,7 @@ char           *SC_create_errormsg(StatementClass *self);
 RETCODE                SC_execute(StatementClass *self);
 RETCODE                SC_fetch(StatementClass *self);
 void           SC_free_params(StatementClass *self, char option);
-void           SC_log_error(char *func, char *desc, StatementClass *self);
+void           SC_log_error(const char *func, const char *desc, const StatementClass *self);
 unsigned long SC_get_bookmark(StatementClass *self);
 
 #endif
index 1d92eec1bb421ba51b5203a61a7e04ba35b29483..637e37633760099ad0175dcea2ee6b7a7a903085 100644 (file)
@@ -31,7 +31,7 @@ CFG=Release
 !MESSAGE "Release" (Win32 Release DLL)
 !MESSAGE "Debug" (Win32 Debug DLL)
 !MESSAGE "MultibyteRelease" (Win32 Release DLL with Multibyte support)
-!MESSAGE "MultibyteDebug" (Win32 Release DLL with Multibyte support)
+!MESSAGE "MultibyteDebug" (Win32 Debug DLL with Multibyte support)
 !MESSAGE 
 !ERROR An invalid configuration was specified.
 !ENDIF 
@@ -46,13 +46,15 @@ NULL=nul
 
 !IF "$(CFG)" == "MultibyteRelease"
 OUTDIR=.\MultibyteRelease
+OUTDIRBIN=.\MultibyteRelease
 INTDIR=.\MultibyteRelease
 !ELSE
 OUTDIR=.\Release
+OUTDIRBIN=.\Release
 INTDIR=.\Release
 !ENDIF
 
-ALL : "$(OUTDIR)\psqlodbc.dll"
+ALL : "$(OUTDIRBIN)\psqlodbc.dll"
 
 
 CLEAN :
@@ -64,7 +66,6 @@ CLEAN :
        -@erase "$(INTDIR)\drvconn.obj"
        -@erase "$(INTDIR)\environ.obj"
        -@erase "$(INTDIR)\execute.obj"
-       -@erase "$(INTDIR)\gpps.obj"
        -@erase "$(INTDIR)\info.obj"
        -@erase "$(INTDIR)\lobj.obj"
        -@erase "$(INTDIR)\win_md5.obj"
@@ -139,7 +140,7 @@ BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
 BSC32_SBRS= \
        
 LINK32=link.exe
-LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIR)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" 
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIRBIN)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" 
 DEF_FILE= "psqlodbc_win32.def"
 LINK32_OBJS= \
        "$(INTDIR)\bind.obj" \
@@ -150,7 +151,6 @@ LINK32_OBJS= \
        "$(INTDIR)\drvconn.obj" \
        "$(INTDIR)\environ.obj" \
        "$(INTDIR)\execute.obj" \
-       "$(INTDIR)\gpps.obj" \
        "$(INTDIR)\info.obj" \
        "$(INTDIR)\lobj.obj" \
        "$(INTDIR)\win_md5.obj" \
@@ -172,7 +172,7 @@ LINK32_OBJS= \
        "$(INTDIR)\odbcapi.obj" \
        "$(INTDIR)\psqlodbc.res"
 
-"$(OUTDIR)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+"$(OUTDIRBIN)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
     $(LINK32) @<<
   $(LINK32_FLAGS) $(LINK32_OBJS)
 <<
@@ -199,7 +199,6 @@ CLEAN :
        -@erase "$(INTDIR)\drvconn.obj"
        -@erase "$(INTDIR)\environ.obj"
        -@erase "$(INTDIR)\execute.obj"
-       -@erase "$(INTDIR)\gpps.obj"
        -@erase "$(INTDIR)\info.obj"
        -@erase "$(INTDIR)\lobj.obj"
        -@erase "$(INTDIR)\win_md5.obj"
@@ -288,7 +287,6 @@ LINK32_OBJS= \
        "$(INTDIR)\drvconn.obj" \
        "$(INTDIR)\environ.obj" \
        "$(INTDIR)\execute.obj" \
-       "$(INTDIR)\gpps.obj" \
        "$(INTDIR)\info.obj" \
        "$(INTDIR)\lobj.obj" \
        "$(INTDIR)\win_md5.obj"
@@ -367,12 +365,6 @@ SOURCE=execute.c
        $(CPP) $(CPP_PROJ) $(SOURCE)
 
 
-SOURCE=gpps.c
-
-"$(INTDIR)\gpps.obj" : $(SOURCE) "$(INTDIR)"
-       $(CPP) $(CPP_PROJ) $(SOURCE)
-
-
 SOURCE=info.c
 
 "$(INTDIR)\info.obj" : $(SOURCE) "$(INTDIR)"
index 021b22c3bd1968bd6d657953358a12e02cda7969..355d5a3a1abbb4176c8ef37d5ec3e6e5f44138b4 100755 (executable)
@@ -88,6 +88,7 @@ CLEAN :
        -@erase "$(INTDIR)\tuplelist.obj"
        -@erase "$(INTDIR)\odbcapi.obj"
        -@erase "$(INTDIR)\odbcapi30.obj"
+       -@erase "$(INTDIR)\pgapi30.obj"
        -@erase "$(INTDIR)\vc60.idb"
        -@erase "$(OUTDIR)\psqlodbc30.dll"
        -@erase "$(OUTDIR)\psqlodbc.exp"
@@ -174,6 +175,7 @@ LINK32_OBJS= \
        "$(INTDIR)\tuplelist.obj" \
        "$(INTDIR)\odbcapi.obj" \
        "$(INTDIR)\odbcapi30.obj" \
+       "$(INTDIR)\pgapi30.obj" \
        "$(INTDIR)\psqlodbc.res"
 
 "$(OUTDIRBIN)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
@@ -225,6 +227,7 @@ CLEAN :
        -@erase "$(INTDIR)\tuplelist.obj"
        -@erase "$(INTDIR)\odbcapi.obj"
        -@erase "$(INTDIR)\odbcapi30.obj"
+       -@erase "$(INTDIR)\pgapi30.obj"
        -@erase "$(INTDIR)\vc60.idb"
        -@erase "$(INTDIR)\vc60.pdb"
        -@erase "$(OUTDIR)\psqlodbc30.dll"
@@ -314,6 +317,7 @@ LINK32_OBJS= \
        "$(INTDIR)\tuplelist.obj" \
        "$(INTDIR)\odbcapi.obj" \
        "$(INTDIR)\odbcapi30.obj" \
+       "$(INTDIR)\pgapi30.obj" \
        "$(INTDIR)\psqlodbc.res"
 
 "$(OUTDIR)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
@@ -513,7 +517,10 @@ SOURCE=odbcapi30.c
 "$(INTDIR)\odbcapi30.obj" : $(SOURCE) "$(INTDIR)"
        $(CPP) $(CPP_PROJ) $(SOURCE)
 
+SOURCE=pgcapi30.c
 
+"$(INTDIR)\pgcapi30.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
 
 
 !ENDIF 
diff --git a/src/interfaces/odbc/win32_30w.mak b/src/interfaces/odbc/win32_30w.mak
new file mode 100644 (file)
index 0000000..4455069
--- /dev/null
@@ -0,0 +1,508 @@
+#
+# File:                        win32_30w.mak
+#
+# Description:         psqlodbc30 Unicode version Makefile for Win32.
+#
+# Configurations:      Unicode30Debug, Unicode30
+# Build Types:         ALL, CLEAN
+# Usage:               NMAKE /f win32_30.mak CFG=[Unicode30 | Unicode30Debug] [ALL | CLEAN]
+#
+# Comments:            Created by Dave Page, 2001-02-12
+#
+
+!MESSAGE Building the PostgreSQL Unicode 3.0 Driver for Win32...
+!MESSAGE
+!IF "$(CFG)" == ""
+CFG=Unicode30
+!MESSAGE No configuration specified. Defaulting to Unicode30.
+!MESSAGE
+!ENDIF 
+
+!IF "$(CFG)" != "Unicode30" && "$(CFG)" != "Unicode30Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f win32_30.mak CFG=[Unicode30 | Unicode30Debug] [ALL | CLEAN]
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "Unicode30" (Win32 Release DLL)
+!MESSAGE "Unicode30Debug" (Win32 Debug DLL)
+!MESSAGE 
+!ERROR An invalid configuration was specified.
+!ENDIF 
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE 
+NULL=nul
+!ENDIF 
+
+!IF  "$(CFG)" == "Unicode30"
+
+OUTDIR=.\Unicode30
+OUTDIRBIN=.\Unicode30
+INTDIR=.\Unicode30
+
+ALL : "$(OUTDIRBIN)\psqlodbc30.dll"
+
+
+CLEAN :
+       -@erase "$(INTDIR)\bind.obj"
+       -@erase "$(INTDIR)\columninfo.obj"
+       -@erase "$(INTDIR)\connection.obj"
+       -@erase "$(INTDIR)\convert.obj"
+       -@erase "$(INTDIR)\dlg_specific.obj"
+       -@erase "$(INTDIR)\drvconn.obj"
+       -@erase "$(INTDIR)\environ.obj"
+       -@erase "$(INTDIR)\execute.obj"
+       -@erase "$(INTDIR)\info.obj"
+       -@erase "$(INTDIR)\info30.obj"
+       -@erase "$(INTDIR)\lobj.obj"
+       -@erase "$(INTDIR)\win_md5.obj"
+       -@erase "$(INTDIR)\misc.obj"
+       -@erase "$(INTDIR)\pgapi30.obj"
+       -@erase "$(INTDIR)\multibyte.obj"
+       -@erase "$(INTDIR)\odbcapiw.obj"
+       -@erase "$(INTDIR)\odbcapi30w.obj"
+       -@erase "$(INTDIR)\win_unicode.obj"
+       -@erase "$(INTDIR)\options.obj"
+       -@erase "$(INTDIR)\parse.obj"
+       -@erase "$(INTDIR)\pgtypes.obj"
+       -@erase "$(INTDIR)\psqlodbc.obj"
+       -@erase "$(INTDIR)\psqlodbc.res"
+       -@erase "$(INTDIR)\qresult.obj"
+       -@erase "$(INTDIR)\results.obj"
+       -@erase "$(INTDIR)\setup.obj"
+       -@erase "$(INTDIR)\socket.obj"
+       -@erase "$(INTDIR)\statement.obj"
+       -@erase "$(INTDIR)\tuple.obj"
+       -@erase "$(INTDIR)\tuplelist.obj"
+       -@erase "$(INTDIR)\odbcapi.obj"
+       -@erase "$(INTDIR)\odbcapi30.obj"
+       -@erase "$(INTDIR)\vc60.idb"
+       -@erase "$(OUTDIR)\psqlodbc30.dll"
+       -@erase "$(OUTDIR)\psqlodbc.exp"
+       -@erase "$(OUTDIR)\psqlodbc.lib"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "ODBCVER=0x0300" /D "MULTIBYTE" /D "UNICODE_SUPPORT" /D "DRIVER_CURSOR_IMPLEMENT" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+
+.c{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.c{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" 
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc" 
+BSC32_SBRS= \
+       
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_api30w.def" /out:"$(OUTDIRBIN)\psqlodbc30.dll" /implib:"$(OUTDIR)\psqlodbc.lib" 
+DEF_FILE= "psqlodbc_api30w.def"
+LINK32_OBJS= \
+       "$(INTDIR)\bind.obj" \
+       "$(INTDIR)\columninfo.obj" \
+       "$(INTDIR)\connection.obj" \
+       "$(INTDIR)\convert.obj" \
+       "$(INTDIR)\dlg_specific.obj" \
+       "$(INTDIR)\drvconn.obj" \
+       "$(INTDIR)\environ.obj" \
+       "$(INTDIR)\execute.obj" \
+       "$(INTDIR)\info.obj" \
+       "$(INTDIR)\info30.obj" \
+       "$(INTDIR)\lobj.obj" \
+       "$(INTDIR)\win_md5.obj" \
+       "$(INTDIR)\misc.obj" \
+       "$(INTDIR)\pgapi30.obj" \
+       "$(INTDIR)\multibyte.obj" \
+       "$(INTDIR)\odbcapiw.obj" \
+       "$(INTDIR)\odbcapi30w.obj" \
+       "$(INTDIR)\win_unicode.obj" \
+       "$(INTDIR)\options.obj" \
+       "$(INTDIR)\parse.obj" \
+       "$(INTDIR)\pgtypes.obj" \
+       "$(INTDIR)\psqlodbc.obj" \
+       "$(INTDIR)\qresult.obj" \
+       "$(INTDIR)\results.obj" \
+       "$(INTDIR)\setup.obj" \
+       "$(INTDIR)\socket.obj" \
+       "$(INTDIR)\statement.obj" \
+       "$(INTDIR)\tuple.obj" \
+       "$(INTDIR)\tuplelist.obj" \
+       "$(INTDIR)\odbcapi.obj" \
+       "$(INTDIR)\odbcapi30.obj" \
+       "$(INTDIR)\psqlodbc.res"
+
+"$(OUTDIRBIN)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF  "$(CFG)" == "Unicode30Debug"
+
+ALL : "$(OUTDIR)\psqlodbc30.dll"
+
+
+CLEAN :
+       -@erase "$(INTDIR)\bind.obj"
+       -@erase "$(INTDIR)\columninfo.obj"
+       -@erase "$(INTDIR)\connection.obj"
+       -@erase "$(INTDIR)\convert.obj"
+       -@erase "$(INTDIR)\dlg_specific.obj"
+       -@erase "$(INTDIR)\drvconn.obj"
+       -@erase "$(INTDIR)\environ.obj"
+       -@erase "$(INTDIR)\execute.obj"
+       -@erase "$(INTDIR)\info.obj"
+       -@erase "$(INTDIR)\info30.obj"
+       -@erase "$(INTDIR)\lobj.obj"
+       -@erase "$(INTDIR)\win_md5.obj"
+       -@erase "$(INTDIR)\misc.obj"
+       -@erase "$(INTDIR)\pgapi30.obj"
+       -@erase "$(INTDIR)\multibyte.obj"
+       -@erase "$(INTDIR)\odbcapiw.obj"
+       -@erase "$(INTDIR)\odbcapi30w.obj"
+       -@erase "$(INTDIR)\win_unicode.obj"
+       -@erase "$(INTDIR)\options.obj"
+       -@erase "$(INTDIR)\parse.obj"
+       -@erase "$(INTDIR)\pgtypes.obj"
+       -@erase "$(INTDIR)\psqlodbc.obj"
+       -@erase "$(INTDIR)\psqlodbc.res"
+       -@erase "$(INTDIR)\qresult.obj"
+       -@erase "$(INTDIR)\results.obj"
+       -@erase "$(INTDIR)\setup.obj"
+       -@erase "$(INTDIR)\socket.obj"
+       -@erase "$(INTDIR)\statement.obj"
+       -@erase "$(INTDIR)\tuple.obj"
+       -@erase "$(INTDIR)\tuplelist.obj"
+       -@erase "$(INTDIR)\odbcapi.obj"
+       -@erase "$(INTDIR)\odbcapi30.obj"
+       -@erase "$(INTDIR)\vc60.idb"
+       -@erase "$(INTDIR)\vc60.pdb"
+       -@erase "$(OUTDIR)\psqlodbc30.dll"
+       -@erase "$(OUTDIR)\psqlodbc.exp"
+       -@erase "$(OUTDIR)\psqlodbc.ilk"
+       -@erase "$(OUTDIR)\psqlodbc.lib"
+       -@erase "$(OUTDIR)\psqlodbc.pdb"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "ODBCVER=0x0300" /D "MULTIBYTE" /D "UNICODE_SUPPORT" /D "DRIVER_CURSOR_IMPLEMENT" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+
+.c{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.c{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" 
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc" 
+BSC32_SBRS= \
+       
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbc.pdb" /debug /machine:I386 /def:"psqlodbc_api30w.def" /out:"$(OUTDIR)\psqlodbc30.dll" /implib:"$(OUTDIR)\psqlodbc.lib" /pdbtype:sept 
+DEF_FILE= "psqlodbc_api30w.def"
+LINK32_OBJS= \
+       "$(INTDIR)\bind.obj" \
+       "$(INTDIR)\columninfo.obj" \
+       "$(INTDIR)\connection.obj" \
+       "$(INTDIR)\convert.obj" \
+       "$(INTDIR)\dlg_specific.obj" \
+       "$(INTDIR)\drvconn.obj" \
+       "$(INTDIR)\environ.obj" \
+       "$(INTDIR)\execute.obj" \
+       "$(INTDIR)\info.obj" \
+       "$(INTDIR)\info30.obj" \
+       "$(INTDIR)\lobj.obj" \
+       "$(INTDIR)\win_md5.obj"
+       "$(INTDIR)\misc.obj" \
+       "$(INTDIR)\pgapi30.obj" \
+       "$(INTDIR)\multibyte.obj" \
+       "$(INTDIR)\odbcapiw.obj" \
+       "$(INTDIR)\odbcapi30w.obj" \
+       "$(INTDIR)\win_unicode.obj" \
+       "$(INTDIR)\options.obj" \
+       "$(INTDIR)\parse.obj" \
+       "$(INTDIR)\pgtypes.obj" \
+       "$(INTDIR)\psqlodbc.obj" \
+       "$(INTDIR)\qresult.obj" \
+       "$(INTDIR)\results.obj" \
+       "$(INTDIR)\setup.obj" \
+       "$(INTDIR)\socket.obj" \
+       "$(INTDIR)\statement.obj" \
+       "$(INTDIR)\tuple.obj" \
+       "$(INTDIR)\tuplelist.obj" \
+       "$(INTDIR)\odbcapi.obj" \
+       "$(INTDIR)\odbcapi30.obj" \
+       "$(INTDIR)\psqlodbc.res"
+
+"$(OUTDIR)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF 
+
+!IF "$(CFG)" == "Unicode30" || "$(CFG)" == "Unicode30Debug"
+
+SOURCE=bind.c
+
+"$(INTDIR)\bind.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=columninfo.c
+
+"$(INTDIR)\columninfo.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=connection.c
+
+"$(INTDIR)\connection.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=convert.c
+
+"$(INTDIR)\convert.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=dlg_specific.c
+
+"$(INTDIR)\dlg_specific.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=drvconn.c
+
+"$(INTDIR)\drvconn.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=environ.c
+
+"$(INTDIR)\environ.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=execute.c
+
+"$(INTDIR)\execute.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=info.c
+
+"$(INTDIR)\info.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=info30.c
+
+"$(INTDIR)\info30.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=lobj.c
+
+"$(INTDIR)\lobj.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=misc.c
+
+"$(INTDIR)\misc.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=multibyte.c
+
+"$(INTDIR)\multibyte.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+SOURCE=odbcapiw.c
+
+"$(INTDIR)\odbcapiw.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+SOURCE=pgapi30.c
+
+"$(INTDIR)\pgapi30.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+SOURCE=odbcapi30w.c
+
+"$(INTDIR)\odbcapi30w.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+SOURCE=win_unicode.c
+
+"$(INTDIR)\win_unicode.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=options.c
+
+"$(INTDIR)\options.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=parse.c
+
+"$(INTDIR)\parse.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=pgtypes.c
+
+"$(INTDIR)\pgtypes.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=psqlodbc.c
+
+"$(INTDIR)\psqlodbc.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=psqlodbc.rc
+
+!IF "$(CFG)" == "Unicode30"
+"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
+       $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" /d "MULTIBYTE" $(SOURCE)
+!ENDIF
+
+!IF "$(CFG)" == "Unicode30Debug"
+"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
+       $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" $(SOURCE)
+!ENDIF
+
+
+SOURCE=qresult.c
+
+"$(INTDIR)\qresult.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=results.c
+
+"$(INTDIR)\results.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=setup.c
+
+"$(INTDIR)\setup.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=socket.c
+
+"$(INTDIR)\socket.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=statement.c
+
+"$(INTDIR)\statement.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=tuple.c
+
+"$(INTDIR)\tuple.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=tuplelist.c
+
+"$(INTDIR)\tuplelist.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=win_md5.c
+
+"$(INTDIR)\win_md5.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=odbcapi.c
+
+"$(INTDIR)\odbcapi.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=odbcapi30.c
+
+"$(INTDIR)\odbcapi30.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+
+!ENDIF 
diff --git a/src/interfaces/odbc/win32w.mak b/src/interfaces/odbc/win32w.mak
new file mode 100644 (file)
index 0000000..24a57a1
--- /dev/null
@@ -0,0 +1,478 @@
+#
+# File:                        win32w.mak
+#
+# Description:         psqlodbc Unicode version Makefile for Win32.
+#
+# Configurations:      UnicodeDebug, Unicode
+# Build Types:         ALL, CLEAN
+# Usage:               NMAKE /f win32w.mak CFG=[Unicode | UnicodeDebug] [ALL | CLEAN]
+#
+# Comments:            Created by Dave Page, 2001-02-12
+#
+
+!MESSAGE Building the PostgreSQL Unicode Driver for Win32...
+!MESSAGE
+!IF "$(CFG)" == ""
+CFG=Unicode
+!MESSAGE No configuration specified. Defaulting to Unicode.
+!MESSAGE
+!ENDIF 
+
+!IF "$(CFG)" != "Unicode" && "$(CFG)" != "UnicodeDebug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f win32w.mak CFG=[Unicode | UnicodeDebug] [ALL | CLEAN]
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "Unicode" (Win32 Release DLL)
+!MESSAGE "UnicodeDebug" (Win32 Debug DLL)
+!MESSAGE 
+!ERROR An invalid configuration was specified.
+!ENDIF 
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE 
+NULL=nul
+!ENDIF 
+
+!IF  "$(CFG)" == "Unicode"
+
+OUTDIR=.\Unicode
+OUTDIRBIN=.\Unicode
+INTDIR=.\Unicode
+
+ALL : "$(OUTDIRBIN)\psqlodbc.dll"
+
+
+CLEAN :
+       -@erase "$(INTDIR)\bind.obj"
+       -@erase "$(INTDIR)\columninfo.obj"
+       -@erase "$(INTDIR)\connection.obj"
+       -@erase "$(INTDIR)\convert.obj"
+       -@erase "$(INTDIR)\dlg_specific.obj"
+       -@erase "$(INTDIR)\drvconn.obj"
+       -@erase "$(INTDIR)\environ.obj"
+       -@erase "$(INTDIR)\execute.obj"
+       -@erase "$(INTDIR)\info.obj"
+       -@erase "$(INTDIR)\lobj.obj"
+       -@erase "$(INTDIR)\win_md5.obj"
+       -@erase "$(INTDIR)\misc.obj"
+       -@erase "$(INTDIR)\multibyte.obj"
+       -@erase "$(INTDIR)\odbcapiw.obj"
+       -@erase "$(INTDIR)\odbcapi25w.obj"
+       -@erase "$(INTDIR)\win_unicode.obj"
+       -@erase "$(INTDIR)\options.obj"
+       -@erase "$(INTDIR)\parse.obj"
+       -@erase "$(INTDIR)\pgtypes.obj"
+       -@erase "$(INTDIR)\psqlodbc.obj"
+       -@erase "$(INTDIR)\psqlodbc.res"
+       -@erase "$(INTDIR)\qresult.obj"
+       -@erase "$(INTDIR)\results.obj"
+       -@erase "$(INTDIR)\setup.obj"
+       -@erase "$(INTDIR)\socket.obj"
+       -@erase "$(INTDIR)\statement.obj"
+       -@erase "$(INTDIR)\tuple.obj"
+       -@erase "$(INTDIR)\tuplelist.obj"
+       -@erase "$(INTDIR)\odbcapi.obj"
+       -@erase "$(INTDIR)\vc60.idb"
+       -@erase "$(OUTDIR)\psqlodbc.dll"
+       -@erase "$(OUTDIR)\psqlodbc.exp"
+       -@erase "$(OUTDIR)\psqlodbc.lib"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "ODBCVER=0x0250" /D "MULTIBYTE" /D "UNICODE_SUPPORT" /D "DRIVER_CURSOR_IMPLEMENT" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+
+.c{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.c{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" 
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc" 
+BSC32_SBRS= \
+       
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_apiw.def" /out:"$(OUTDIRBIN)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" 
+DEF_FILE= "psqlodbc_apiw.def"
+LINK32_OBJS= \
+       "$(INTDIR)\bind.obj" \
+       "$(INTDIR)\columninfo.obj" \
+       "$(INTDIR)\connection.obj" \
+       "$(INTDIR)\convert.obj" \
+       "$(INTDIR)\dlg_specific.obj" \
+       "$(INTDIR)\drvconn.obj" \
+       "$(INTDIR)\environ.obj" \
+       "$(INTDIR)\execute.obj" \
+       "$(INTDIR)\info.obj" \
+       "$(INTDIR)\lobj.obj" \
+       "$(INTDIR)\win_md5.obj" \
+       "$(INTDIR)\misc.obj" \
+       "$(INTDIR)\multibyte.obj" \
+       "$(INTDIR)\odbcapiw.obj" \
+       "$(INTDIR)\odbcapi25w.obj" \
+       "$(INTDIR)\win_unicode.obj" \
+       "$(INTDIR)\options.obj" \
+       "$(INTDIR)\parse.obj" \
+       "$(INTDIR)\pgtypes.obj" \
+       "$(INTDIR)\psqlodbc.obj" \
+       "$(INTDIR)\qresult.obj" \
+       "$(INTDIR)\results.obj" \
+       "$(INTDIR)\setup.obj" \
+       "$(INTDIR)\socket.obj" \
+       "$(INTDIR)\statement.obj" \
+       "$(INTDIR)\tuple.obj" \
+       "$(INTDIR)\tuplelist.obj" \
+       "$(INTDIR)\odbcapi.obj" \
+       "$(INTDIR)\psqlodbc.res"
+
+"$(OUTDIRBIN)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF  "$(CFG)" == "UnicodeDebug"
+
+ALL : "$(OUTDIR)\psqlodbc.dll"
+
+
+CLEAN :
+       -@erase "$(INTDIR)\bind.obj"
+       -@erase "$(INTDIR)\columninfo.obj"
+       -@erase "$(INTDIR)\connection.obj"
+       -@erase "$(INTDIR)\convert.obj"
+       -@erase "$(INTDIR)\dlg_specific.obj"
+       -@erase "$(INTDIR)\drvconn.obj"
+       -@erase "$(INTDIR)\environ.obj"
+       -@erase "$(INTDIR)\execute.obj"
+       -@erase "$(INTDIR)\info.obj"
+       -@erase "$(INTDIR)\lobj.obj"
+       -@erase "$(INTDIR)\win_md5.obj"
+       -@erase "$(INTDIR)\misc.obj"
+       -@erase "$(INTDIR)\multibyte.obj"
+       -@erase "$(INTDIR)\odbcapiw.obj"
+       -@erase "$(INTDIR)\odbcapi25w.obj"
+       -@erase "$(INTDIR)\win_unicode.obj"
+       -@erase "$(INTDIR)\options.obj"
+       -@erase "$(INTDIR)\parse.obj"
+       -@erase "$(INTDIR)\pgtypes.obj"
+       -@erase "$(INTDIR)\psqlodbc.obj"
+       -@erase "$(INTDIR)\psqlodbc.res"
+       -@erase "$(INTDIR)\qresult.obj"
+       -@erase "$(INTDIR)\results.obj"
+       -@erase "$(INTDIR)\setup.obj"
+       -@erase "$(INTDIR)\socket.obj"
+       -@erase "$(INTDIR)\statement.obj"
+       -@erase "$(INTDIR)\tuple.obj"
+       -@erase "$(INTDIR)\tuplelist.obj"
+       -@erase "$(INTDIR)\odbcapi.obj"
+       -@erase "$(INTDIR)\vc60.idb"
+       -@erase "$(INTDIR)\vc60.pdb"
+       -@erase "$(OUTDIR)\psqlodbc.dll"
+       -@erase "$(OUTDIR)\psqlodbc.exp"
+       -@erase "$(OUTDIR)\psqlodbc.ilk"
+       -@erase "$(OUTDIR)\psqlodbc.lib"
+       -@erase "$(OUTDIR)\psqlodbc.pdb"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "ODBCVER=0x0250" /D "MULTIBYTE" /D "UNICODE_SUPPORT" /D "DRIVER_CURSOR_IMPLEMENT" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+
+.c{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.c{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" 
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc" 
+BSC32_SBRS= \
+       
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbc.pdb" /debug /machine:I386 /def:"psqlodbc_apiw.def" /out:"$(OUTDIR)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" /pdbtype:sept 
+DEF_FILE= "psqlodbc_apiw.def"
+LINK32_OBJS= \
+       "$(INTDIR)\bind.obj" \
+       "$(INTDIR)\columninfo.obj" \
+       "$(INTDIR)\connection.obj" \
+       "$(INTDIR)\convert.obj" \
+       "$(INTDIR)\dlg_specific.obj" \
+       "$(INTDIR)\drvconn.obj" \
+       "$(INTDIR)\environ.obj" \
+       "$(INTDIR)\execute.obj" \
+       "$(INTDIR)\info.obj" \
+       "$(INTDIR)\lobj.obj" \
+       "$(INTDIR)\win_md5.obj"
+       "$(INTDIR)\misc.obj" \
+       "$(INTDIR)\multibyte.obj" \
+       "$(INTDIR)\odbcapiw.obj" \
+       "$(INTDIR)\odbcapi25w.obj" \
+       "$(INTDIR)\win_unicode.obj" \
+       "$(INTDIR)\options.obj" \
+       "$(INTDIR)\parse.obj" \
+       "$(INTDIR)\pgtypes.obj" \
+       "$(INTDIR)\psqlodbc.obj" \
+       "$(INTDIR)\qresult.obj" \
+       "$(INTDIR)\results.obj" \
+       "$(INTDIR)\setup.obj" \
+       "$(INTDIR)\socket.obj" \
+       "$(INTDIR)\statement.obj" \
+       "$(INTDIR)\tuple.obj" \
+       "$(INTDIR)\tuplelist.obj" \
+       "$(INTDIR)\odbcapi.obj" \
+       "$(INTDIR)\psqlodbc.res"
+
+"$(OUTDIR)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF 
+
+!IF "$(CFG)" == "Unicode" || "$(CFG)" == "UnicodeDebug"
+
+SOURCE=bind.c
+
+"$(INTDIR)\bind.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=columninfo.c
+
+"$(INTDIR)\columninfo.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=connection.c
+
+"$(INTDIR)\connection.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=convert.c
+
+"$(INTDIR)\convert.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=dlg_specific.c
+
+"$(INTDIR)\dlg_specific.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=drvconn.c
+
+"$(INTDIR)\drvconn.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=environ.c
+
+"$(INTDIR)\environ.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=execute.c
+
+"$(INTDIR)\execute.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=info.c
+
+"$(INTDIR)\info.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=lobj.c
+
+"$(INTDIR)\lobj.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=misc.c
+
+"$(INTDIR)\misc.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=multibyte.c
+
+"$(INTDIR)\multibyte.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+SOURCE=odbcapiw.c
+
+"$(INTDIR)\odbcapiw.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+SOURCE=odbcapi25w.c
+
+"$(INTDIR)\odbcapi25w.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+SOURCE=win_unicode.c
+
+"$(INTDIR)\win_unicode.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=options.c
+
+"$(INTDIR)\options.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=parse.c
+
+"$(INTDIR)\parse.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=pgtypes.c
+
+"$(INTDIR)\pgtypes.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=psqlodbc.c
+
+"$(INTDIR)\psqlodbc.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=psqlodbc.rc
+
+!IF "$(CFG)" == "Unicode"
+"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
+       $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" /d "MULTIBYTE" $(SOURCE)
+!ENDIF
+
+!IF "$(CFG)" == "UnicodeDebug"
+"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
+       $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" $(SOURCE)
+!ENDIF
+
+
+SOURCE=qresult.c
+
+"$(INTDIR)\qresult.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=results.c
+
+"$(INTDIR)\results.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=setup.c
+
+"$(INTDIR)\setup.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=socket.c
+
+"$(INTDIR)\socket.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=statement.c
+
+"$(INTDIR)\statement.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=tuple.c
+
+"$(INTDIR)\tuple.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=tuplelist.c
+
+"$(INTDIR)\tuplelist.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=win_md5.c
+
+"$(INTDIR)\win_md5.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=odbcapi.c
+
+"$(INTDIR)\odbcapi.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF 
index 11a8e396a59d9a7b63557fb0ac4596980693b778..3dfc9ff43d4e5ad2fcd79b54ab9713cebf217663 100644 (file)
 #define        byte3_mask2     0x0fc0
 #define        byte3_mask3     0x003f
 
+UInt4  ucs2strlen(const SQLWCHAR *ucs2str)
+{
+       UInt4   len;
+       for (len = 0; ucs2str[len]; len++)
+               ;
+       return len;
+}
 char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen)
 {
        char *  utf8str;
@@ -28,24 +35,21 @@ char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen)
        if (!ucs2str)
                return NULL;
        if (ilen < 0)
-       {
-               for (ilen = 0; ucs2str[ilen]; ilen++)
-                       ;
-       }
+               ilen = ucs2strlen(ucs2str);
 /*mylog(" newlen=%d", ilen);*/
        utf8str = (char *) malloc(ilen * 3 + 1);
        if (utf8str)
        {
                int     i, len = 0;
-               Int2            byte2code;
-               Int4            byte4code;
-
+               UInt2   byte2code;
+               Int4    byte4code;
                const SQLWCHAR  *wstr;
+
                for (i = 0, wstr = ucs2str; i < ilen; i++, wstr++)
                {
                        if (!*wstr)
                                break;
-                       else if (iswascii(*wstr))
+                       else if (0 == (*wstr & 0xff80))
                                utf8str[len++] = (char) *wstr;
                        else if ((*wstr & byte3check) == 0)
                        {
@@ -66,7 +70,8 @@ char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen)
                        }
                } 
                utf8str[len] = '\0';
-               *olen = len;
+               if (olen)
+                       *olen = len;
        }
 /*mylog(" olen=%d %s\n", *olen, utf8str ? utf8str : "");*/
        return utf8str;
@@ -109,7 +114,7 @@ UInt4       utf8_to_ucs2(const char *utf8str, Int4 ilen, SQLWCHAR *ucs2str, UInt4 bufc
                        {
                                wcode = ((((UInt4) *str) & byte3_m1) << 12) |
                                        ((((UInt4) str[1]) & byte3_m2) << 6) |
-                                       ((UInt4) str[2]) & byte3_m3;
+                                       (((UInt4) str[2]) & byte3_m3);
                                ucs2str[ocount] = (SQLWCHAR) wcode;
                        }
                        ocount++;
@@ -121,7 +126,7 @@ UInt4       utf8_to_ucs2(const char *utf8str, Int4 ilen, SQLWCHAR *ucs2str, UInt4 bufc
                        if (ocount < bufcount)
                        {
                                wcode = ((((UInt4) *str) & byte2_m1) << 6) |
-                                       ((UInt4) str[1]) & byte2_m2;
+                                       (((UInt4) str[1]) & byte2_m2);
                                ucs2str[ocount] = (SQLWCHAR) wcode;
                        }
                        ocount++;