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;