]> granicus.if.org Git - postgresql/commitdiff
1) Fix SQLForeignKeys() in multibyte mode.
authorHiroshi Inoue <inoue@tpf.co.jp>
Mon, 10 Sep 2001 08:53:27 +0000 (08:53 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Mon, 10 Sep 2001 08:53:27 +0000 (08:53 +0000)
2) Fix a bug with NUMERIC scale in case of Parse
  statement option.
3) Remove a no longer needed loop in CC_send_query().

Hiroshi Inoue

src/interfaces/odbc/connection.c
src/interfaces/odbc/connection.h
src/interfaces/odbc/info.c
src/interfaces/odbc/parse.c
src/interfaces/odbc/results.c
src/interfaces/odbc/statement.h

index 3c784ead445221bbb0faa283c121ccab2f35249f..9685c9358b5dea69ec64d8c2e1bb9af695481101 100644 (file)
  */
 /* Multibyte support   Eiji Tokuya 2001-03-15 */
 
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
 #include "connection.h"
 
 #include "environ.h"
@@ -27,9 +31,6 @@
 #include "multibyte.h"
 #endif
 
-#include <stdio.h>
-#include <string.h>
-
 #ifdef WIN32
 #include <odbcinst.h>
 #endif
@@ -277,6 +278,10 @@ memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
                rv->pg_version_number = .0;
                rv->pg_version_major = 0;
                rv->pg_version_minor = 0;
+#ifdef MULTIBYTE
+               rv->client_encoding = NULL;
+               rv->server_encoding = NULL;
+#endif /* MULTIBYTE */
 
 
                /* Initialize statement options to defaults */
@@ -302,6 +307,12 @@ CC_Destructor(ConnectionClass *self)
 
        mylog("after CC_Cleanup\n");
 
+#ifdef MULTIBYTE
+       if (self->client_encoding)
+               free(self->client_encoding);
+       if (self->server_encoding)
+               free(self->server_encoding);
+#endif /* MULTIBYTE */
        /* Free up statement holders */
        if (self->stmts)
        {
@@ -510,6 +521,9 @@ CC_connect(ConnectionClass *self, char do_password)
        char            msgbuffer[ERROR_MSG_LENGTH];
        char            salt[5];
        static char *func = "CC_connect";
+#ifdef MULTIBYTE
+       char    *encoding;
+#endif /* MULTIBYTE */
 
        mylog("%s: entering...\n", func);
 
@@ -537,7 +551,9 @@ CC_connect(ConnectionClass *self, char do_password)
                         ci->drivers.bools_as_char);
 
 #ifdef MULTIBYTE
-               check_client_encoding(ci->drivers.conn_settings);
+               encoding = check_client_encoding(ci->drivers.conn_settings);
+               if (encoding && strcmp(encoding, "OTHER"))
+                       self->client_encoding = strdup(encoding);
                qlog("                extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n",
                         ci->drivers.extra_systable_prefixes,
                         ci->drivers.conn_settings,
@@ -1041,7 +1057,6 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                                        CC_set_no_trans(self);
                                        ReadyToReturn = TRUE;
                                        retres = NULL;
-                                       break;
                                }
                                else
                                {
@@ -1059,6 +1074,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                                                QR_set_status(res, PGRES_COMMAND_OK);
                                        QR_set_command(res, cmdbuffer);
                                        query_completed = TRUE;
+                                       mylog("send_query: returning res = %u\n", res);
                                        if (!before_64)
                                                break;
                                        /*
@@ -1069,71 +1085,14 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
                                         * an 'I' is received
                                         */
 
-
                                        if (empty_reqs == 0)
                                        {
                                                SOCK_put_string(sock, "Q ");
                                                SOCK_flush_output(sock);
                                                empty_reqs++;
                                        }
-                                       break;
-
-                                       while (!clear)
-                                       {
-                                               id = SOCK_get_char(sock);
-                                               mylog("got clear id = '%c'\n", id);
-                                               switch (id)
-                                               {
-                                                       case 'I':
-                                                               (void) SOCK_get_char(sock);
-                                                               clear = TRUE;
-                                                               break;
-                                                       case 'Z':
-                                                               break;
-                                                       case 'C':
-                                                               SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
-                                                               qlog("Command response: '%s'\n", cmdbuffer);
-                                                               break;
-                                                       case 'N':
-                                                               msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
-                                                               if (QR_command_successful(res))
-                                                                       QR_set_status(res, PGRES_NONFATAL_ERROR);
-                                                               QR_set_notice(res, cmdbuffer);  /* will dup this string */
-                                                               qlog("NOTICE from backend during clear: '%s'\n", cmdbuffer);
-                                                               while (msg_truncated)
-                                                                       msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
-                                                               break;
-                                                       case 'E':
-                                                               msg_truncated = SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-                                                               mylog("ERROR from backend during clear: '%s'\n", msgbuffer);
-                                                               qlog("ERROR from backend during clear: '%s'\n", msgbuffer);
-
-                                                               /*
-                                                                * We must report this type of error as
-                                                                * well (practically for reference
-                                                                * integrity violation error reporting,
-                                                                * from PostgreSQL 7.0). (Zoltan Kovacs,
-                                                                * 04/26/2000)
-                                                                */
-                                                               self->errormsg = msgbuffer;
-                                                               if (!strncmp(self->errormsg, "FATAL", 5))
-                                                               {
-                                                                       self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
-                                                                       CC_set_no_trans(self);
-                                                               }
-                                                               else
-                                                                       self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
-                                                               QR_set_status(res, PGRES_FATAL_ERROR);
-                                                               QR_set_aborted(res, TRUE);
-                                                               while (msg_truncated)
-                                                                       msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
-                                                               break;
-                                               }
-                                       }
-
-                                       mylog("send_query: returning res = %u\n", res);
-                                       break;
                                }
+                               break;
                        case 'Z':                       /* Backend is ready for new query (6.4) */
                                if (empty_reqs == 0)
                                {
index 24931cef2b26600ead245c16d752e23f31750150..fc77bc8a7b490b5bf95a8b809236a31c1d6d6445 100644 (file)
@@ -274,6 +274,10 @@ struct ConnectionClass_
        float           pg_version_number;
        Int2            pg_version_major;
        Int2            pg_version_minor;
+#ifdef MULTIBYTE
+       char            *client_encoding;
+       char            *server_encoding;
+#endif /* MULTIBYTE */
 };
 
 
index 2f5d4c88d0318e8deb48606808b0ffd3c2d0030b..663e207abb57eb1405dffbc9c09704595338e297 100644 (file)
@@ -2666,6 +2666,180 @@ PGAPI_PrimaryKeys(
 }
 
 
+#ifdef MULTIBYTE
+/*
+ *     Multibyte support stuff for SQLForeignKeys().
+ *     There may be much more effective way in the
+ *     future version. The way is very forcive currently.
+ */
+static BOOL isMultibyte(const unsigned char *str)
+{
+       for (; *str; str++)
+       {
+               if (*str >= 0x80)
+                       return TRUE;
+       }
+       return FALSE;
+}
+static char *getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloced)
+{
+       char    query[1024], saveoid[24], *ret = serverTableName;
+       BOOL    continueExec = TRUE, bError = FALSE;
+       QResultClass    *res;
+
+       *nameAlloced = FALSE;
+       if (!conn->client_encoding || !isMultibyte(serverTableName))
+               return ret;
+       if (!conn->server_encoding)
+       {
+               if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res)
+               {
+                       if (QR_get_num_tuples(res) > 0)
+                               conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
+                       QR_Destructor(res);
+               }
+       }
+       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;
+       if (!bError && continueExec)
+       {
+               sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName);
+               if (res = CC_send_query(conn, query, NULL), 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
+                       bError = TRUE;
+       }
+       continueExec = (continueExec && !bError);
+       if (bError && CC_is_in_trans(conn))
+       {
+               if (res = CC_send_query(conn, "abort", NULL), res)
+                       QR_Destructor(res);
+               CC_set_no_trans(conn);
+               bError = FALSE;
+       }
+       /* 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;
+       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 (QR_get_num_tuples(res) > 0)
+               {
+                       ret = strdup(QR_get_value_backend_row(res, 0, 0));
+                       *nameAlloced = TRUE;
+               }
+               QR_Destructor(res);
+       }
+       return ret;
+}
+static char *getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *serverColumnName, BOOL *nameAlloced)
+{
+       char    query[1024], saveattrelid[24], saveattnum[16], *ret = serverColumnName;
+       BOOL    continueExec = TRUE, bError = FALSE;
+       QResultClass    *res;
+
+       *nameAlloced = FALSE;
+       if (!conn->client_encoding || !isMultibyte(serverColumnName))
+               return ret;
+       if (!conn->server_encoding)
+       {
+               if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res)
+               {
+                       if (QR_get_num_tuples(res) > 0)
+                               conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
+                       QR_Destructor(res);
+               }
+       }
+       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;
+       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 (QR_get_num_tuples(res) > 0)
+                       {
+                               strcpy(saveattrelid, QR_get_value_backend_row(res, 0, 0));
+                               strcpy(saveattnum, QR_get_value_backend_row(res, 0, 1));
+                       }
+                       else
+                       {
+                               continueExec = FALSE;
+                               bError = QR_get_aborted(res);
+                       }
+                       QR_Destructor(res);
+               }
+               else
+                       bError = TRUE;
+       }
+       continueExec = (continueExec && !bError);
+       if (bError && CC_is_in_trans(conn))
+       {
+               if (res = CC_send_query(conn, "abort", NULL), res)
+                       QR_Destructor(res);
+               CC_set_no_trans(conn);
+               bError = FALSE;
+       }
+       /* 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;
+       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 (QR_get_num_tuples(res) > 0)
+               {
+                       ret = strdup(QR_get_value_backend_row(res, 0, 0));
+                       *nameAlloced = TRUE;
+               }
+               QR_Destructor(res);
+       }
+       return ret;
+}
+#endif /* MULTIBYTE */
+
 RETCODE SQL_API
 PGAPI_ForeignKeys(
                           HSTMT hstmt,
@@ -2698,10 +2872,14 @@ PGAPI_ForeignKeys(
                                del_rule[MAX_TABLE_LEN];
        char            pk_table_needed[MAX_TABLE_LEN + 1];
        char            fk_table_needed[MAX_TABLE_LEN + 1];
-       char       *pkey_ptr,
-                          *fkey_ptr,
-                          *pk_table,
-                          *fk_table;
+       char            *pkey_ptr, *pkey_text,
+                       *fkey_ptr, *fkey_text,
+                       *pk_table, *pkt_text,
+                       *fk_table, *fkt_text;
+#ifdef MULTIBYTE
+       BOOL            pkey_alloced, fkey_alloced, pkt_alloced, fkt_alloced;
+       ConnectionClass *conn;
+#endif /* MULTIBYTE */
        int                     i,
                                j,
                                k,
@@ -2795,6 +2973,10 @@ PGAPI_ForeignKeys(
        make_string(szPkTableName, cbPkTableName, pk_table_needed);
        make_string(szFkTableName, cbFkTableName, fk_table_needed);
 
+#ifdef MULTIBYTE
+       pkey_alloced = fkey_alloced = pkt_alloced = fkt_alloced = FALSE;
+       conn = SC_get_conn(stmt);
+#endif /* MULTIBYTE */
        /*
         * Case #2 -- Get the foreign keys in the specified table (fktab) that
         * refer to the primary keys of other table(s).
@@ -2954,18 +3136,24 @@ PGAPI_ForeignKeys(
                        for (k = 0; k < 2; k++)
                                pk_table += strlen(pk_table) + 1;
 
+#ifdef MULTIBYTE
+                       fk_table = trig_args + strlen(trig_args) + 1;
+                       pkt_text = getClientTableName(conn, pk_table, &pkt_alloced);
+#else
+                       pkt_text = pk_table;
+#endif /* MULTIBYTE */
                        /* If there is a pk table specified, then check it. */
                        if (pk_table_needed[0] != '\0')
                        {
                                /* If it doesn't match, then continue */
-                               if (strcmp(pk_table, pk_table_needed))
+                               if (strcmp(pkt_text, pk_table_needed))
                                {
                                        result = PGAPI_Fetch(htbl_stmt);
                                        continue;
                                }
                        }
 
-                       keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, pk_table, SQL_NTS);
+                       keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, pkt_text, SQL_NTS);
                        if (keyresult != SQL_SUCCESS)
                        {
                                stmt->errornumber = STMT_NO_MEMORY_ERROR;
@@ -2975,8 +3163,6 @@ PGAPI_ForeignKeys(
                                return SQL_ERROR;
                        }
 
-                       /* Check that the key listed is the primary key */
-                       keyresult = PGAPI_Fetch(hpkey_stmt);
 
                        /* Get to first primary key */
                        pkey_ptr = trig_args;
@@ -2985,17 +3171,32 @@ PGAPI_ForeignKeys(
 
                        for (k = 0; k < num_keys; k++)
                        {
-                               mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_ptr, pkey);
-                               if (keyresult != SQL_SUCCESS || strcmp(pkey_ptr, pkey))
+                               /* Check that the key listed is the primary key */
+                               keyresult = PGAPI_Fetch(hpkey_stmt);
+                               if (keyresult != SQL_SUCCESS)
                                {
                                        num_keys = 0;
                                        break;
                                }
+#ifdef MULTIBYTE
+                               pkey_text = getClientColumnName(conn, pk_table, pkey_ptr, &pkey_alloced);
+#else
+                               pkey_text = pkey_ptr;
+#endif /* MULTIBYTE */
+                               mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_text, pkey);
+                               if (strcmp(pkey_text, pkey))
+                               {
+                                       num_keys = 0;
+                                       break;
+                               }
+#ifdef MULTIBYTE
+                               if (pkey_alloced)
+                                       free(pkey_text);
+#endif /* MULTIBYTE */
                                /* Get to next primary key */
                                for (k = 0; k < 2; k++)
                                        pkey_ptr += strlen(pkey_ptr) + 1;
 
-                               keyresult = PGAPI_Fetch(hpkey_stmt);
                        }
 
                        /* Set to first fk column */
@@ -3045,17 +3246,24 @@ PGAPI_ForeignKeys(
                        {
                                row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
 
-                               mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table, pkey_ptr);
+#ifdef MULTIBYTE
+                               pkey_text = getClientColumnName(conn, pk_table, pkey_ptr, &pkey_alloced);
+                               fkey_text = getClientColumnName(conn, fk_table, fkey_ptr, &fkey_alloced);
+#else
+                               pkey_text = pkey_ptr;
+                               fkey_text = fkey_ptr;
+#endif /* MULTIBYTE */
+                               mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pkt_text, pkey_text);
                                set_tuplefield_null(&row->tuple[0]);
                                set_tuplefield_string(&row->tuple[1], "");
-                               set_tuplefield_string(&row->tuple[2], pk_table);
-                               set_tuplefield_string(&row->tuple[3], pkey_ptr);
+                               set_tuplefield_string(&row->tuple[2], pkt_text);
+                               set_tuplefield_string(&row->tuple[3], pkey_text);
 
-                               mylog("%s: fk_table_needed = '%s', fkey_ptr = '%s'\n", func, fk_table_needed, fkey_ptr);
+                               mylog("%s: fk_table_needed = '%s', fkey_ptr = '%s'\n", func, fk_table_needed, fkey_text);
                                set_tuplefield_null(&row->tuple[4]);
                                set_tuplefield_string(&row->tuple[5], "");
                                set_tuplefield_string(&row->tuple[6], fk_table_needed);
-                               set_tuplefield_string(&row->tuple[7], fkey_ptr);
+                               set_tuplefield_string(&row->tuple[7], fkey_text);
 
                                mylog("%s: upd_rule_type = '%i', del_rule_type = '%i'\n, trig_name = '%s'", func, upd_rule_type, del_rule_type, trig_args);
                                set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
@@ -3069,7 +3277,14 @@ PGAPI_ForeignKeys(
 #endif  /* ODBCVER >= 0x0300 */
 
                                QR_add_tuple(stmt->result, row);
-
+#ifdef MULTIBYTE
+                               if (fkey_alloced)
+                                       free(fkey_text);
+                               fkey_alloced = FALSE;
+                               if (pkey_alloced)
+                                       free(pkey_text);
+                               pkey_alloced = FALSE;
+#endif /* MULTIBYTE */
                                /* next primary/foreign key */
                                for (i = 0; i < 2; i++)
                                {
@@ -3077,6 +3292,11 @@ PGAPI_ForeignKeys(
                                        pkey_ptr += strlen(pkey_ptr) + 1;
                                }
                        }
+#ifdef MULTIBYTE
+                       if (pkt_alloced)
+                               free(pkt_text);
+                       pkt_alloced = FALSE;
+#endif /* MULTIBYTE */
 
                        result = PGAPI_Fetch(htbl_stmt);
                }
@@ -3257,6 +3477,12 @@ PGAPI_ForeignKeys(
                        /* Get to first foreign table */
                        fk_table = trig_args;
                        fk_table += strlen(fk_table) + 1;
+#ifdef MULTIBYTE
+                       pk_table = fk_table + strlen(fk_table) + 1;
+                       fkt_text = getClientTableName(conn, fk_table, &fkt_alloced);
+#else
+                       fkt_text = fk_table;
+#endif /* MULTIBYTE */ 
 
                        /* Get to first foreign key */
                        fkey_ptr = trig_args;
@@ -3265,21 +3491,28 @@ PGAPI_ForeignKeys(
 
                        for (k = 0; k < num_keys; k++)
                        {
-                               mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_ptr, fk_table, fkey_ptr);
+#ifdef MULTIBYTE
+                               pkey_text = getClientColumnName(conn, pk_table, pkey_ptr, &pkey_alloced);
+                               fkey_text = getClientColumnName(conn, fk_table, fkey_ptr, &fkey_alloced);
+#else
+                               pkey_text = pkey_ptr;
+                               fkey_text = fkey_ptr;
+#endif /* MULTIBYTE */ 
+                               mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_text, fkt_text, fkey_text);
 
                                row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
 
-                               mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_ptr);
+                               mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_text);
                                set_tuplefield_null(&row->tuple[0]);
                                set_tuplefield_string(&row->tuple[1], "");
                                set_tuplefield_string(&row->tuple[2], pk_table_needed);
-                               set_tuplefield_string(&row->tuple[3], pkey_ptr);
+                               set_tuplefield_string(&row->tuple[3], pkey_text);
 
-                               mylog("fk_table = '%s', fkey_ptr = '%s'\n", fk_table, fkey_ptr);
+                               mylog("fk_table = '%s', fkey_ptr = '%s'\n", fkt_text, fkey_text);
                                set_tuplefield_null(&row->tuple[4]);
                                set_tuplefield_string(&row->tuple[5], "");
-                               set_tuplefield_string(&row->tuple[6], fk_table);
-                               set_tuplefield_string(&row->tuple[7], fkey_ptr);
+                               set_tuplefield_string(&row->tuple[6], fkt_text);
+                               set_tuplefield_string(&row->tuple[7], fkey_text);
 
                                set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
 
@@ -3298,6 +3531,14 @@ PGAPI_ForeignKeys(
 #endif  /* ODBCVER >= 0x0300 */
 
                                QR_add_tuple(stmt->result, row);
+#ifdef MULTIBYTE
+                               if (pkey_alloced)
+                                       free(pkey_text);
+                               pkey_alloced = FALSE;
+                               if (fkey_alloced)
+                                       free(fkey_text);
+                               fkey_alloced = FALSE;
+#endif /* MULTIBYTE */
 
                                /* next primary/foreign key */
                                for (j = 0; j < 2; j++)
@@ -3306,6 +3547,11 @@ PGAPI_ForeignKeys(
                                        fkey_ptr += strlen(fkey_ptr) + 1;
                                }
                        }
+#ifdef MULTIBYTE
+                       if (fkt_alloced)
+                               free(fkt_text);
+                       fkt_alloced = FALSE;
+#endif /* MULTIBYTE */ 
                        result = PGAPI_Fetch(htbl_stmt);
                }
        }
@@ -3317,6 +3563,16 @@ PGAPI_ForeignKeys(
                PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
                return SQL_ERROR;
        }
+#ifdef MULTIBYTE
+       if (pkt_alloced)
+               free(pkt_text);
+       if (pkey_alloced)
+               free(pkey_text);
+       if (fkt_alloced)
+               free(fkt_text);
+       if (fkey_alloced)
+               free(fkey_text);
+#endif /* MULTIBYTE */
 
        PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
 
index eb0589e4c4b241eb4991f7d45cd7ad6c1b13972a..f6254cae9470c955874dec9dbb72c2b7a43125a5 100644 (file)
@@ -227,12 +227,17 @@ QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
 void
 getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k)
 {
+       char *str;
        if (fi->name[0] == '\0')
                strcpy(fi->name, QR_get_value_manual(col_info->result, k, 3));
 
        fi->type = atoi(QR_get_value_manual(col_info->result, k, 13));
        fi->precision = atoi(QR_get_value_manual(col_info->result, k, 6));
        fi->length = atoi(QR_get_value_manual(col_info->result, k, 7));
+       if (str = QR_get_value_manual(col_info->result, k, 8), str)
+               fi->scale = atoi(str);
+       else
+               fi->scale = -1;
        fi->nullable = atoi(QR_get_value_manual(col_info->result, k, 10));
        fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12));
 }
index 7d29fb0ce22b3857213472424745a08ec719b0e8..3cfe5fb74b147eda27792391f23fae5775bec20c 100644 (file)
@@ -199,7 +199,7 @@ PGAPI_DescribeCol(
        QResultClass *res;
        char       *col_name = NULL;
        Int4            fieldtype = 0;
-       int                     precision = 0;
+       int             precision = 0, scale = 0;
        ConnInfo   *ci;
        char            parse_ok;
        char            buf[255];
@@ -250,6 +250,7 @@ PGAPI_DescribeCol(
                        fieldtype = stmt->fi[icol]->type;
                        col_name = stmt->fi[icol]->name;
                        precision = stmt->fi[icol]->precision;
+                       scale = stmt->fi[icol]->scale;
 
                        mylog("PARSE: fieldtype=%d, col_name='%s', precision=%d\n", fieldtype, col_name, precision);
                        if (fieldtype > 0)
@@ -292,6 +293,7 @@ PGAPI_DescribeCol(
 
                /* atoi(ci->unknown_sizes) */
                precision = pgtype_precision(stmt, fieldtype, icol, ci->drivers.unknown_sizes);
+               scale = pgtype_scale(stmt, fieldtype, icol);
        }
 
        mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
@@ -348,10 +350,7 @@ PGAPI_DescribeCol(
         */
        if (pibScale)
        {
-               Int2            scale;
-
-               scale = pgtype_scale(stmt, fieldtype, icol);
-               if (scale == -1)
+               if (scale < 0)
                        scale = 0;
 
                *pibScale = scale;
index bea157b1187084188a4c56b6d1e96a276a0c881f..834eb005b3d6e6be793fd8ce9ccd245cc7a2aa1c 100644 (file)
@@ -131,6 +131,7 @@ typedef struct
 {
        TABLE_INFO *ti;                         /* resolve to explicit table names */
        int                     precision;
+       int                     scale;
        int                     display_size;
        int                     length;
        int                     type;