The version is now 8.2.0002.
authorHiroshi Inoue <inoue@tpf.co.jp>
Thu, 27 Apr 2006 14:49:04 +0000 (14:49 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Thu, 27 Apr 2006 14:49:04 +0000 (14:49 +0000)
1.Prevent SQL injections via ODBC catalog function calls.
2.Fix SQLNumParams problem related to literal or dollar quote.
3.Call libpq in case of Kerberos authentication.
4.Add E' before literal for after 8.1 severs.
5.Return the correct error message in case of no password.
6.Take E'...' literal expression into account.
7.Fix an SQL_C_WCHAR -> numeric type conversion problem.
8.Refine the handling of io or output parameters.
9.Refine the dollar quote handling.
10.Fix the client_encoding mismatch problem.
11.Fix for SQLStatistics returns UNKNOWN instead of real column names.

25 files changed:
bind.c
catfunc.h
connection.c
connection.h
convert.c
convert.h
dlg_specific.c
drvconn.c
info.c
info30.c
misc.c
multibyte.c
multibyte.h
odbcapi.c
odbcapi25w.c
odbcapiw.c
options.c
parse.c
pgapi30.c
pgapifunc.h
pgtypes.c
psqlodbc.h
psqlodbc.rc
version.h
win_unicode.c

diff --git a/bind.c b/bind.c
index aba623ec60d9af914e8ec411566699fa9b2dce7c..ddd703ab85322cd7312b917fbe957db9ca4f6030 100644 (file)
--- a/bind.c
+++ b/bind.c
@@ -420,7 +420,7 @@ PGAPI_NumParams(
 {
    StatementClass *stmt = (StatementClass *) hstmt;
    CSTR func = "PGAPI_NumParams";
-   char    literal_quote = LITERAL_QUOTE, identifier_quote = IDENTIFIER_QUOTE, escape_in_literal = ESCAPE_IN_LITERAL, dollar_quote = '$';
+   char    literal_quote = LITERAL_QUOTE, identifier_quote = IDENTIFIER_QUOTE, dollar_quote = DOLLAR_QUOTE;
 
    mylog("%s: entering...\n", func);
 
@@ -449,21 +449,23 @@ inolog("num_params=%d,%d\n", stmt->num_params, stmt->proc_return);
    else
    {
        const   char *sptr, *tag = NULL;
+       ConnectionClass *conn = SC_get_conn(stmt);
        int taglen;
-       char    tchar, bchar;
+       char    tchar, bchar, escape_in_literal;
        char    in_literal = FALSE, in_identifier = FALSE,
            in_dollar_quote = FALSE, in_escape = FALSE,
            multi = FALSE, del_found = FALSE;
        encoded_str encstr;
 
        stmt->proc_return = 0;
-       make_encoded_str(&encstr, SC_get_conn(stmt), stmt->statement);
+       make_encoded_str(&encstr, conn, stmt->statement);
        for (sptr = stmt->statement, bchar = '\0'; *sptr; sptr++)
        {
            tchar = encoded_nextchar(&encstr);
            if (ENCODE_STATUS(encstr) != 0) /* multibyte char */
            {
-               bchar = tchar;
+               if ((UCHAR) tchar >= 0x80)
+                   bchar = tchar;
                continue;
            }
            if (!multi && del_found)
@@ -481,6 +483,7 @@ inolog("num_params=%d,%d\n", stmt->num_params, stmt->proc_return);
                        tag = NULL;
                        sptr += taglen;
                        sptr--;
+                       encoded_position_shift(&encstr, taglen - 1);
                    }
                }
            }
@@ -519,10 +522,19 @@ inolog("num_params=%d,%d\n", stmt->num_params, stmt->proc_return);
                    {
                        taglen = dollar_next - sptr + 1;
                        sptr = dollar_next;
+                       encoded_position_shift(&encstr, taglen - 1);
                    }
                }
                else if (tchar == literal_quote)
+               {
                    in_literal = TRUE;
+                   escape_in_literal = CC_get_escape(conn);
+                   if (!escape_in_literal)
+                   {
+                       if (LITERAL_EXT == sptr[-1])
+                           escape_in_literal = ESCAPE_IN_LITERAL;
+                   }
+               }
                else if (tchar == identifier_quote)
                    in_identifier = TRUE;
                if (!isspace(tchar))
index 09ad69d0e87818569d8210923190cd5ffdc245bf..87d3c054448ecc1caf4c2e73257efa685f99ff70 100644 (file)
--- a/catfunc.h
+++ b/catfunc.h
@@ -36,7 +36,8 @@ enum {
    ,COLUMNS_DISPLAY_SIZE
    ,COLUMNS_FIELD_TYPE
    ,COLUMNS_AUTO_INCREMENT
-   ,COLUMNS_LAST = COLUMNS_AUTO_INCREMENT
+   ,COLUMNS_PHYSICAL_NUMBER
+   ,NUM_OF_COLUMNS_FIELDS
 };
 /* SQLForeignKeys field position   */
 enum {
@@ -57,7 +58,7 @@ enum {
    ,FKS_DEFERRABILITY
 #endif /* ODBCVER */
    ,FKS_TRIGGER_NAME
-   ,FKS_LAST = FKS_TRIGGER_NAME
+   ,NUM_OF_FKS_FIELDS
 };
 /* SQLColAttribute */
 enum {
@@ -90,4 +91,22 @@ enum {
    ,COLATTR_DESC_UNSIGNED
    ,COLATTR_DESC_UPDATABLE
 };
+
+/* SQLStatistics field position    */
+enum {
+   STATS_CATALOG_NAME  = 0
+   ,STATS_SCHEMA_NAME
+   ,STATS_TABLE_NAME
+   ,STATS_NON_UNIQUE
+   ,STATS_INDEX_QUALIFIER
+   ,STATS_INDEX_NAME
+   ,STATS_TYPE
+   ,STATS_SEQ_IN_INDEX
+   ,STATS_COLUMN_NAME
+   ,STATS_COLLATION
+   ,STATS_CARDINALITY
+   ,STATS_PAGES
+   ,STATS_FILTER_CONDITION
+   ,NUM_OF_STATS_FIELDS
+};
 #endif /* __CARFUNC_H__ */
index c78b0d65afe6e4bbcac768d24b17d64ba7c1936b..8625412a76ef32a0fedba36477bc902fe4e57b3a 100644 (file)
@@ -136,6 +136,9 @@ PGAPI_Connect(
        CC_log_error(func, "Error on CC_connect", conn);
        ret = SQL_ERROR;
    }
+   if (CC_is_in_unicode_driver(conn)
+       && 0 != ci->bde_environment)
+       conn->unicode |= CONN_DISALLOW_WCHAR;
 
    mylog("%s: returning..%d.\n", func, ret);
 
@@ -320,6 +323,7 @@ CC_Constructor()
        // rv->discardp = NULL;
        rv->mb_maxbyte_per_char = 1;
        rv->max_identifier_length = -1;
+       rv->escape_in_literal = ESCAPE_IN_LITERAL;
 
        /* Initialize statement options to defaults */
        /* Statements under this conn will inherit these options */
@@ -1179,7 +1183,7 @@ original_CC_connect(ConnectionClass *self, char password_req, char *salt_para)
    int         beresp;
    char        msgbuffer[ERROR_MSG_LENGTH];
    char        salt[5], notice[512];
-   CSTR        func = "original_connect";
+   CSTR        func = "original_CC_connect";
    // char    *encoding;
    BOOL    startPacketReceived = FALSE;
 
@@ -1467,15 +1471,12 @@ inolog("Ekita\n");
        QR_Destructor(res);
 
        mylog("empty query seems to be OK.\n");
-   }
 
-   /* 
-    * Get the version number first so we can check it before
-    * sending options that are now obsolete. DJP 21/06/2002
-    */
+       /* 
+        * Get the version number first so we can check it before
+        * sending options that are now obsolete. DJP 21/06/2002
+        */
 inolog("CC_lookup_pg_version\n");
-   if (!PROTOCOL_74(ci))
-   {
        CC_lookup_pg_version(self); /* Get PostgreSQL version for
                           SQLGetInfo use */
        CC_setenv(self);
@@ -1505,13 +1506,24 @@ CC_connect(ConnectionClass *self, char password_req, char *salt_para)
    mylog("%s: entering...\n", func);
 
    mylog("sslmode=%s\n", self->connInfo.sslmode);
-   if (self->connInfo.sslmode[0] != 'd')
+   if (self->connInfo.sslmode[0] != 'd' ||
+       self->connInfo.username[0] == '\0')
        ret = LIBPQ_CC_connect(self, password_req, salt_para);
    else
+   {
        ret = original_CC_connect(self, password_req, salt_para);
+       if (0 == ret && CONN_AUTH_TYPE_UNSUPPORTED == CC_get_errornumber(self))
+       {
+           SOCK_Destructor(self->sock);
+           self->sock = (SocketClass *) 0;
+           ret = LIBPQ_CC_connect(self, password_req, salt_para);
+       }
+   }
    if (ret <= 0)
        return ret;
 
+   if (PG_VERSION_GE(self, 8.4)) /* maybe */
+       self->escape_in_literal = '\0';
    CC_set_translation(self);
 
    /*
@@ -1540,7 +1552,7 @@ inolog("CC_send_settings\n");
        if (CC_get_errornumber(self) != 0)
            return 0;
 #ifdef UNICODE_SUPPORT
-       if (self->unicode)
+       if (CC_is_in_unicode_driver(self))
        {
            if (!self->original_client_encoding ||
                (stricmp(self->original_client_encoding, "UNICODE") &&
@@ -1569,7 +1581,7 @@ inolog("CC_send_settings\n");
 #endif /* UNICODE_SUPPORT */
    }
 #ifdef UNICODE_SUPPORT
-   else if (self->unicode)
+   else if (CC_is_in_unicode_driver(self))
    {
        CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "Unicode isn't supported before 6.4", func);
        return 0;
@@ -2741,10 +2753,10 @@ CC_lookup_lo(ConnectionClass *self)
    mylog("%s: entering...\n", func);
 
    if (PG_VERSION_GE(self, 7.4))
-       res = CC_send_query(self, "select oid, typbasetype from pg_type where oid = '"  PG_TYPE_LO_NAME "'::regtype::oid", 
+       res = CC_send_query(self, "select oid, typbasetype from pg_type where typname = '"  PG_TYPE_LO_NAME "'", 
            NULL, IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR, NULL);
    else
-       res = CC_send_query(self, "select oid from pg_type where typname='" PG_TYPE_LO_NAME "'",
+       res = CC_send_query(self, "select oid, 0 from pg_type where typname='" PG_TYPE_LO_NAME "'",
            NULL, IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR, NULL);
    if (QR_command_maybe_successful(res) && QR_get_num_cached_tuples(res) > 0)
    {
@@ -3102,6 +3114,7 @@ inolog("sock=%x\n", sock);
        const char  *errmsg;
 inolog("status=%d\n", pqret);
        errmsg = PQerrorMessage(pqconn);
+       CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, errmsg, func);
        if (CONNECTION_BAD == pqret && strstr(errmsg, "no password"))
        {
            mylog("password retry\n");
@@ -3109,7 +3122,6 @@ inolog("status=%d\n", pqret);
            self->sock = sock;
            return -1;
        }
-       CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, errmsg, func);
        mylog("Could not establish connection to the database; LIBPQ returned -> %s\n", errmsg);
        goto cleanup1;
    }
index be102ae337066303c85d79c00b213f324f381932..81fcdcaff9cc857aec1f76d5a8d5106d3c075088 100644 (file)
@@ -109,10 +109,12 @@ enum
 /* Unicode handling */
 #define    CONN_UNICODE_DRIVER (1L)
 #define    CONN_ANSI_APP       (1L << 1)
+#define    CONN_DISALLOW_WCHAR (1L << 2)
 #define    CC_set_in_unicode_driver(x) (x->unicode |= CONN_UNICODE_DRIVER)
 #define    CC_set_in_ansi_app(x)   (x->unicode |= CONN_ANSI_APP)
 #define    CC_is_in_unicode_driver(x)  (0 != (x->unicode & CONN_UNICODE_DRIVER))
 #define    CC_is_in_ansi_app(x)    (0 != (x->unicode & CONN_ANSI_APP))
+#define    ALLOW_WCHAR(x)  (0 != (x->unicode & CONN_UNICODE_DRIVER) && 0 == (x->unicode & CONN_DISALLOW_WCHAR))
 
 #define CC_MALLOC_return_with_error(t, tp, s, x, m, ret) \
 do { \
@@ -285,6 +287,7 @@ typedef struct
    signed char lower_case_identifier;
    signed char rollback_on_error;
    signed char force_abbrev_connstr;
+   signed char bde_environment;
 #ifdef _HANDLE_ENLIST_IN_DTC_
    signed char xa_opt;
    signed char autocommit_normal;
@@ -407,6 +410,7 @@ struct ConnectionClass_
    char        result_uncommitted;
    char        schema_support;
    char        lo_is_domain;
+   char        escape_in_literal;
    char        *original_client_encoding;
    char        *current_client_encoding;
    char        *server_encoding;
@@ -441,6 +445,7 @@ struct ConnectionClass_
 #define CC_get_DSN(x)              (x->connInfo.dsn)
 #define CC_get_username(x)         (x->connInfo.username)
 #define CC_is_onlyread(x)          (x->connInfo.onlyread[0] == '1')
+#define CC_get_escape(x)           (x->escape_in_literal)
  
 /* for CC_DSN_info */
 #define CONN_DONT_OVERWRITE        0
index 8cc01db1439c36162b1d4160545da3ae068b1d43..a67a874d6801f0a452256ec8df33b64e71aad8f5 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -133,7 +133,6 @@ char       *mapFuncs[][2] = {
 
 static const char *mapFunction(const char *func, int param_count);
 static unsigned int conv_from_octal(const UCHAR *s);
-static char *conv_to_octal(UCHAR val, char *octal);
 static int pg_bin2hex(UCHAR *src, UCHAR *dst, int length);
 
 /*---------
@@ -698,22 +697,30 @@ inolog("2stime fr=%d\n", std_time.fr);
    }
 
    text_handling = localize_needed = FALSE;
-   if (fCType == INTERNAL_ASIS_TYPE
+   switch (fCType)
+   {
+       case INTERNAL_ASIS_TYPE:
 #ifdef UNICODE_SUPPORT
-       || fCType == SQL_C_WCHAR
+           case SQL_C_WCHAR:
 #endif /* UNICODE_SUPPORT */
-       || fCType == SQL_C_CHAR)
-       text_handling = TRUE;
-   else if (fCType == SQL_C_BINARY &&
-        (field_type == PG_TYPE_UNKNOWN
-         || field_type == PG_TYPE_BPCHAR
-         || field_type == PG_TYPE_VARCHAR
-         || field_type == PG_TYPE_TEXT
-         || field_type == PG_TYPE_BPCHARARRAY
-         || field_type == PG_TYPE_VARCHARARRAY
-         || field_type == PG_TYPE_TEXTARRAY
-        ))
-       text_handling = TRUE;
+           case SQL_C_CHAR:
+           text_handling = TRUE;
+           break;
+       case SQL_C_BINARY:
+           switch (field_type)
+           { 
+               case PG_TYPE_UNKNOWN:
+               case PG_TYPE_BPCHAR:
+               case PG_TYPE_VARCHAR:
+               case PG_TYPE_TEXT:
+               case PG_TYPE_BPCHARARRAY:
+               case PG_TYPE_VARCHARARRAY:
+               case PG_TYPE_TEXTARRAY:
+                   text_handling = TRUE;
+                   break;
+           }
+           break;
+   }
    if (text_handling)
    {
 #ifdef WIN_UNICODE_SUPPORT
@@ -1505,6 +1512,7 @@ QP_initialize(QueryParse *q, const StatementClass *stmt)
 #define    FLGB_CONVERT_LF     (1L << 7)
 #define    FLGB_DISCARD_OUTPUT (1L << 8)
 #define    FLGB_BINARY_AS_POSSIBLE (1L << 9)
+#define    FLGB_LITERAL_EXTENSION  (1L << 10)
 typedef struct _QueryBuild {
    char    *query_statement;
    UInt4   str_size_limit;
@@ -1575,6 +1583,9 @@ QB_initialize(QueryBuild *qb, UInt4 size, StatementClass *stmt, ConnectionClass
    if (qb->conn->connInfo.lf_conversion)
        qb->flags |= FLGB_CONVERT_LF;
    qb->ccsc = qb->conn->ccsc;
+   if (CC_get_escape(qb->conn) &&
+       PG_VERSION_GE(qb->conn, 8.1))
+       qb->flags |= FLGB_LITERAL_EXTENSION;
        
    if (stmt)
        qb->str_size_limit = stmt->stmt_size_limit;
@@ -1708,7 +1719,9 @@ static int
 ResolveOneParam(QueryBuild *qb);
 static int
 processParameters(QueryParse *qp, QueryBuild *qb,
-UInt4 *output_count, Int4 param_pos[][2]);
+   UInt4 *output_count, Int4 param_pos[][2]);
+static int
+convert_to_pgbinary(const UCHAR *in, char *out, int len, QueryBuild *qb);
 
 static int
 enlarge_query_statement(QueryBuild *qb, unsigned int newsize)
@@ -1815,7 +1828,7 @@ do { \
 do { \
    unsigned int    newlimit = qb->npos + 5 * used; \
    ENLARGE_NEWSTATEMENT(qb, newlimit); \
-   qb->npos += convert_to_pgbinary(buf, &qb->query_statement[qb->npos], used, qb->flags); \
+   qb->npos += convert_to_pgbinary(buf, &qb->query_statement[qb->npos], used, qb); \
 } while (0)
 
 /*----------
@@ -1824,13 +1837,31 @@ do { \
  */
 #define CVT_SPECIAL_CHARS(qb, buf, used) \
 do { \
-   int cnvlen = convert_special_chars(buf, NULL, used, qb->flags, qb->ccsc); \
+   int cnvlen = convert_special_chars(buf, NULL, used, qb->flags, qb->ccsc, CC_get_escape(qb->conn)); \
    unsigned int    newlimit = qb->npos + cnvlen; \
 \
    ENLARGE_NEWSTATEMENT(qb, newlimit); \
-   convert_special_chars(buf, &qb->query_statement[qb->npos], used, qb->flags, qb->ccsc); \
+   convert_special_chars(buf, &qb->query_statement[qb->npos], used, qb->flags, qb->ccsc, CC_get_escape(qb->conn)); \
+   qb->npos += cnvlen; \
+} while (0)
+
+#ifdef NOT_USED
+#define CVT_TEXT_FIELD(qb, buf, used) \
+do { \
+   char    escape_ch = CC_get_escape(qb->conn); \
+   int flags = ((0 != qb->flags & FLGB_CONVERT_LF) ? CONVERT_CRLF_TO_LF : 0) | ((0 != qb->flags & FLGB_BUILDING_BIND_REQUEST) ? 0 : DOUBLE_LITERAL_QUOTE | (escape_ch ? DOUBLE_LITERAL_IN_ESCAPE : 0)); \
+   int cnvlen = (flags & (DOUBLE_LITERAL_QUOTE | DOUBLE_LITERAL_IN_ESCAPE)) != 0 ? used * 2 : used; \
+   if (used > 0 && qb->npos + cnvlen >= qb->str_alsize) \
+   { \
+       cnvlen = convert_text_field(buf, NULL, used, qb->ccsc, escape_ch, &flags); \
+       unsigned int    newlimit = qb->npos + cnvlen; \
+\
+       ENLARGE_NEWSTATEMENT(qb, newlimit); \
+   } \
+   cnvlen = convert_text_field(buf, &qb->query_statement[qb->npos], used, qb->ccsc, escape_ch, &flags); \
    qb->npos += cnvlen; \
 } while (0)
+#endif /* NOT_USED */
 
 /*----------
  * Check if the statement is
@@ -2373,7 +2404,7 @@ inner_process_tokens(QueryParse *qp, QueryBuild *qb)
    RETCODE retval;
    char       oldchar;
    StatementClass  *stmt = qb->stmt;
-   char    literal_quote = LITERAL_QUOTE, escape_in_literal = ESCAPE_IN_LITERAL, dollar_quote = '$';
+   char    literal_quote = LITERAL_QUOTE, dollar_quote = DOLLAR_QUOTE, escape_in_literal = '\0';
 
    if (stmt && stmt->ntab > 0)
        bestitem = GET_NAME(stmt->ti[0]->bestitem);
@@ -2459,8 +2490,10 @@ inner_process_tokens(QueryParse *qp, QueryBuild *qb)
     * a literal_quote nor an idetifier_quote.
     */
    /* Squeeze carriage-return/linefeed pairs to linefeed only */
-   else if (lf_conv && oldchar == '\r' && qp->opos + 1 < qp->stmt_len &&
-           qp->statement[qp->opos + 1] == '\n')
+   else if (lf_conv &&
+        PG_CARRIAGE_RETURN == oldchar &&
+        qp->opos + 1 < qp->stmt_len &&
+        PG_LINEFEED == qp->statement[qp->opos + 1])
        return SQL_SUCCESS;
 
    /*
@@ -2522,7 +2555,15 @@ inner_process_tokens(QueryParse *qp, QueryBuild *qb)
        else if (oldchar == literal_quote)
        {
            if (!qp->in_identifier)
+           {
                qp->in_literal = TRUE;
+               escape_in_literal = CC_get_escape(qb->conn);
+               if (!escape_in_literal)
+               {
+                   if (LITERAL_EXT == F_OldPtr(qp)[-1])
+                       escape_in_literal = ESCAPE_IN_LITERAL;
+               }
+           }
        }
        else if (oldchar == IDENTIFIER_QUOTE)
        {
@@ -2938,7 +2979,7 @@ ResolveOneParam(QueryBuild *qb)
     */
    param_number = ++qb->param_number;
 
-inolog("resolveOnParam %d(%d,%d)\n", param_number, ipdopts->allocated, apdopts->allocated);
+inolog("resolveOneParam %d(%d,%d)\n", param_number, ipdopts->allocated, apdopts->allocated);
    apara = NULL;
    ipara = NULL;
    if (param_number < apdopts->allocated)
@@ -3169,7 +3210,7 @@ inolog("ipara=%x paramType=%d %d proc_return=%d\n", ipara, ipara ? ipara->paramT
        case SQL_C_WCHAR:
 mylog("C_WCHAR=%s(%d)\n", buffer, used);
            buf = allocbuf = ucs2_to_utf8((SQLWCHAR *) buffer, used > 0 ? used / WCLEN : used, &used, FALSE);
-           used *= WCLEN;
+           /* used *= WCLEN; */
            break;
 #endif /* UNICODE_SUPPORT */
 
@@ -3303,18 +3344,30 @@ mylog("C_WCHAR=%s(%d)\n", buffer, used);
     * the desired output format (sqltype)
     */
 
-   switch (param_sqltype)
+   if (!req_bind)
    {
-       case SQL_INTEGER:
-       case SQL_SMALLINT:
-           break;
-       default:
-           if (!req_bind)
-           {
+       switch (param_sqltype)
+       {
+           case SQL_INTEGER:
+           case SQL_SMALLINT:
+               break;
+           case SQL_CHAR:
+           case SQL_VARCHAR:
+           case SQL_LONGVARCHAR:
+#ifdef UNICODE_SUPPORT
+           case SQL_WCHAR:
+           case SQL_WVARCHAR:
+           case SQL_WLONGVARCHAR:
+#endif /* UNICODE_SUPPORT */
+               if (buf && (qb->flags & FLGB_LITERAL_EXTENSION) != 0)
+               {
+                   CVT_APPEND_CHAR(qb, LITERAL_EXT);
+               }
+           default:
                CVT_APPEND_CHAR(qb, LITERAL_QUOTE);
                add_quote = TRUE;
-           }
            break;
+       }
    }
    switch (param_sqltype)
    {
@@ -3330,7 +3383,6 @@ mylog("C_WCHAR=%s(%d)\n", buffer, used);
            /* it was a SQL_C_CHAR */
            if (buf)
                CVT_SPECIAL_CHARS(qb, buf, used);
-
            /* it was a numeric type */
            else if (param_string[0] != '\0')
                CVT_APPEND_STR(qb, param_string);
@@ -3338,7 +3390,7 @@ mylog("C_WCHAR=%s(%d)\n", buffer, used);
            /* it was date,time,timestamp -- use m,d,y,hh,mm,ss */
            else
            {
-               sprintf(tmp, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
+               snprintf(tmp, sizeof(tmp), "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
                        st.y, st.m, st.d, st.hh, st.mm, st.ss);
 
                CVT_APPEND_STR(qb, tmp);
@@ -4033,7 +4085,7 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL convlf, BOOL *chan
        if (convlf && si[i] == '\n')
        {
            /* Only add the carriage-return if needed */
-           if (i > 0 && si[i - 1] == '\r')
+           if (i > 0 && PG_CARRIAGE_RETURN == si[i - 1])
            {
                if (dst)
                    dst[out++] = si[i];
@@ -4045,7 +4097,7 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL convlf, BOOL *chan
 
            if (dst)
            {
-               dst[out++] = '\r';
+               dst[out++] = PG_CARRIAGE_RETURN;
                dst[out++] = '\n';
            }
            else
@@ -4070,15 +4122,15 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL convlf, BOOL *chan
  * Plus, escape any special characters.
  */
 int
-convert_special_chars(const char *si, char *dst, int used, UInt4 flags, int ccsc)
+convert_special_chars(const char *si, char *dst, int used, UInt4 flags, int ccsc, int escape_in_literal)
 {
    size_t      i = 0,
                out = 0,
                max;
-   char       *p = NULL, literal_quote = LITERAL_QUOTE;
+   char       *p = NULL, literal_quote = LITERAL_QUOTE, tchar;
    encoded_str encstr;
    BOOL    convlf = (0 != (flags & FLGB_CONVERT_LF)),
-       escadd = (0 == (flags & FLGB_BUILDING_BIND_REQUEST));
+       double_special = (0 == (flags & FLGB_BUILDING_BIND_REQUEST));
 
    if (used == SQL_NTS)
        max = strlen(si);
@@ -4093,25 +4145,29 @@ convert_special_chars(const char *si, char *dst, int used, UInt4 flags, int ccsc
 
    for (i = 0; i < max && si[i]; i++)
    {
-       encoded_nextchar(&encstr);
+       tchar = encoded_nextchar(&encstr);
        if (ENCODE_STATUS(encstr) != 0)
        {
            if (p)
-               p[out] = si[i];
+               p[out] = tchar;
            out++;
            continue;
        }
-       if (convlf && si[i] == '\r' && si[i + 1] == '\n')
+       if (convlf &&   /* CR/LF -> LF */
+           PG_CARRIAGE_RETURN == tchar &&
+           PG_LINEFEED == si[i + 1])
            continue;
-       else if (escadd && (si[i] == literal_quote || si[i] == ESCAPE_IN_LITERAL))
+       else if (double_special && /* double special chars ? */
+            (tchar == literal_quote ||
+             tchar == escape_in_literal))
        {
            if (p)
-               p[out++] = ESCAPE_IN_LITERAL;
+               p[out++] = tchar;
            else
                out++;
        }
        if (p)
-           p[out++] = si[i];
+           p[out++] = tchar;
        else
            out++;
    }
@@ -4120,6 +4176,83 @@ convert_special_chars(const char *si, char *dst, int used, UInt4 flags, int ccsc
    return out;
 }
 
+#ifdef NOT_USED
+#define    CVT_CRLF_TO_LF          1L
+#define    DOUBLE_LITERAL_QUOTE        (1L << 1)
+#define    DOUBLE_ESCAPE_IN_LITERAL    (1L << 2)
+static int
+convert_text_field(const char *si, char *dst, int used, int ccsc, int escape_in_literal, UInt4 *flags)
+{
+   size_t      i = 0, out = 0, max;
+   UInt4   iflags = *flags;
+   char    *p = NULL, literal_quote = LITERAL_QUOTE, tchar;
+   encoded_str encstr;
+   BOOL    convlf = (0 != (iflags & CVT_CRLF_TO_LF)),
+       double_literal_quote = (0 != (iflags & DOUBLE_LITERAL_QUOTE)),
+       double_escape_in_literal = (0 != (iflags & DOUBLE_ESCAPE_IN_LITERAL));
+
+   if (SQL_NTS == used)
+       max = strlen(si);
+   else
+       max = used;
+   if (0 == iflags)
+   {
+       if (dst)
+           strncpy_null(dst, si, max + 1);
+       else
+           return max;
+   }
+   if (dst)
+   {
+       p = dst;
+       p[0] = '\0';
+   }
+   encoded_str_constr(&encstr, ccsc, si);
+
+   *flags = 0;
+   for (i = 0; i < max && si[i]; i++)
+   {
+       tchar = encoded_nextchar(&encstr);
+       if (ENCODE_STATUS(encstr) != 0)
+       {
+           if (p)
+               p[out] = tchar;
+           out++;
+           continue;
+       }
+       if (convlf &&   /* CR/LF -> LF */
+           PG_CARRIAGE_RETURN == tchar &&
+           PG_LINEFEED == si[i + 1])
+       {
+           *flags |= CVT_CRLF_TO_LF;
+           continue;
+       }
+       else if (double_literal_quote && /* double literal quote ? */
+            tchar == literal_quote)
+       {
+           if (p)
+               p[out] = tchar;
+           out++;
+           *flags |= DOUBLE_LITERAL_QUOTE;
+       }
+       else if (double_escape_in_literal && /* double escape ? */
+            tchar == escape_in_literal)
+       {
+           if (p)
+               p[out] = tchar;
+           out++;
+           *flags |= DOUBLE_ESCAPE_IN_LITERAL;
+       }
+       if (p)
+           p[out] = tchar;
+       out++;
+   }
+   if (p)
+       p[out] = '\0';
+   return out;
+}
+#endif /* NOT_USED */
+
 
 /* !!! Need to implement this function !!!  */
 int
@@ -4157,7 +4290,7 @@ convert_from_pgbinary(const UCHAR *value, UCHAR *rgbValue, int cbValueMax)
 
    for (i = 0; i < ilen;)
    {
-       if (value[i] == ESCAPE_IN_LITERAL)
+       if (value[i] == BYTEA_ESCAPE_CHAR)
        {
            if (value[i + 1] == BYTEA_ESCAPE_CHAR)
            {
@@ -4192,22 +4325,24 @@ convert_from_pgbinary(const UCHAR *value, UCHAR *rgbValue, int cbValueMax)
 }
 
 
-static char *
-conv_to_octal(UCHAR val, char *octal)
+static int
+conv_to_octal(UCHAR val, char *octal, char escape_ch)
 {
-   int         i;
+   int i, pos = 0, len;
 
-   octal[0] = ESCAPE_IN_LITERAL;
-   octal[1] = BYTEA_ESCAPE_CHAR;
-   octal[5] = '\0';
+   if (escape_ch)
+       octal[pos++] = escape_ch;
+   octal[pos + 1] = BYTEA_ESCAPE_CHAR;
+   len = 4 + pos;
+   octal[len] = '\0';
 
-   for (i = 4; i > 1; i--)
+   for (i = len - 1; i > pos; i--)
    {
        octal[i] = (val & 7) + '0';
        val >>= 3;
    }
 
-   return octal;
+   return len;
 }
 
 
@@ -4230,24 +4365,25 @@ conv_to_octal2(UCHAR val, char *octal)
 
 
 /* convert non-ascii bytes to octal escape sequences */
-int
-convert_to_pgbinary(const UCHAR *in, char *out, int len, UInt4 flags)
+static int
+convert_to_pgbinary(const UCHAR *in, char *out, int len, QueryBuild *qb)
 {
+   CSTR    func = "convert_to_pgbinary";
    int         i,
                o = 0;
-   BOOL    esc_double = (0 == (flags & FLGB_BUILDING_BIND_REQUEST));
+   char    escape_in_literal = CC_get_escape(qb->conn);
+   BOOL    esc_double = (0 == (qb->flags & FLGB_BUILDING_BIND_REQUEST) && 0 != escape_in_literal);
 
    for (i = 0; i < len; i++)
    {
-       mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]);
+       mylog("%s: in[%d] = %d, %c\n", func, i, in[i], in[i]);
        if (isalnum(in[i]) || in[i] == ' ')
            out[o++] = in[i];
        else
        {
            if (esc_double)
            {
-               conv_to_octal(in[i], &out[o]);
-               o += 5;
+               o += conv_to_octal(in[i], &out[o], escape_in_literal);
            }
            else
            {
@@ -4257,7 +4393,7 @@ convert_to_pgbinary(const UCHAR *in, char *out, int len, UInt4 flags)
        }
    }
 
-   mylog("convert_to_pgbinary: returning %d, out='%.*s'\n", o, o, out);
+   mylog("%s: returning %d, out='%.*s'\n", func, o, o, out);
 
    return o;
 }
index 9c0c81d903dd424b4416770e6b84db6796fb5ecc..c5251e1a64ad1831d45ae8dd81249edf66ada86c 100644 (file)
--- a/convert.h
+++ b/convert.h
@@ -43,11 +43,10 @@ int     copy_statement_with_parameters(StatementClass *stmt, BOOL);
 BOOL       convert_money(const char *s, char *sout, size_t soutmax);
 char       parse_datetime(const char *buf, SIMPLE_TIME *st);
 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, UInt4 flags,int ccsc);
+int        convert_special_chars(const char *si, char *dst, int used, UInt4 flags,int ccsc, int escape_ch);
 
 int            convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax);
 int            convert_from_pgbinary(const UCHAR *value, UCHAR *rgbValue, int cbValueMax);
-int        convert_to_pgbinary(const UCHAR *in, char *out, int len, UInt4 flags);
 int        pg_hex2bin(const UCHAR *in, UCHAR *out, int len);
 int convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
           SDWORD cbValueMax, SDWORD *pcbValue);
index 0db4f0247a3d6c6aa5a5b33b6d0b1cacd2c1eee6..3271e46fdca894c4b77801afdb57aa7d0a07a63f 100644 (file)
@@ -467,7 +467,10 @@ copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value)
    else if (stricmp(attribute, INI_EXTRASYSTABLEPREFIXES) == 0 || stricmp(attribute, ABBR_EXTRASYSTABLEPREFIXES) == 0)
        strcpy(ci->drivers.extra_systable_prefixes, value);
    else if (stricmp(attribute, INI_FORCEABBREVCONNSTR) == 0)
-       ci->force_abbrev_connstr = atoi(value);
+   {
+       ci->force_abbrev_connstr = atoi(value) & 1;
+       ci->bde_environment = atoi(value) & 2;
+   }
    mylog("CopyCommonAttributes: 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->drivers.fetch_max,
          ci->drivers.socket_buffersize,
index 1be465156ae5be670b94e020fa4072c0a515bb6d..6db9435eb6526afc5762bb0375b56427878a00f2 100644 (file)
--- a/drvconn.c
+++ b/drvconn.c
@@ -87,7 +87,7 @@ PGAPI_DriverConnect(
 #ifdef WIN32
    RETCODE     dialog_result;
 #endif
-   BOOL        paramRequired;
+   BOOL        paramRequired, didUI = FALSE;
    RETCODE     result;
    char        *connStrIn = NULL;
    char        connStrOut[MAX_CONNECT_STRING];
@@ -159,6 +159,7 @@ inolog("DriverCompletion=%d\n", fDriverCompletion);
 #ifdef WIN32
        case SQL_DRIVER_PROMPT:
            dialog_result = dconn_DoDialog(hwnd, ci);
+           didUI = TRUE;
            if (dialog_result != SQL_SUCCESS)
                return dialog_result;
            break;
@@ -171,15 +172,6 @@ inolog("DriverCompletion=%d\n", fDriverCompletion);
 
            paramRequired = password_required;
            /* Password is not a required parameter. */
-#ifdef NOT_USED
-           if (ci->username[0] == '\0' ||
-#ifdef WIN32
-               ci->server[0] == '\0' ||
-#endif /* WIN32 */
-               ci->database[0] == '\0' ||
-               ci->port[0] == '\0' ||
-               password_required)
-#endif /* NOT_USED */
            if (ci->database[0] == '\0')
                paramRequired = TRUE;
            else if (ci->port[0] == '\0')
@@ -188,11 +180,10 @@ inolog("DriverCompletion=%d\n", fDriverCompletion);
            else if (ci->server[0] == '\0')
                paramRequired = TRUE;
 #endif /* WIN32 */
-           else if (ci->username[0] == '\0' && 'd' == ci->sslmode[0])
-               paramRequired = TRUE;
            if (paramRequired)
            {
                dialog_result = dconn_DoDialog(hwnd, ci);
+               didUI = TRUE;
                if (dialog_result != SQL_SUCCESS)
                    return dialog_result;
            }
@@ -212,14 +203,6 @@ inolog("DriverCompletion=%d\n", fDriverCompletion);
     * over and over until a password is entered (the user can always hit
     * Cancel to get out)
     */
-#ifdef NOT_USED
-   if (ci->username[0] == '\0' ||
-#ifdef WIN32
-       ci->server[0] == '\0' ||
-#endif /* WIN32 */
-       ci->database[0] == '\0' ||
-       ci->port[0] == '\0')
-#endif /* NOT_USED */
    paramRequired = FALSE;
    if (ci->database[0] == '\0')
        paramRequired = TRUE;
@@ -229,13 +212,12 @@ inolog("DriverCompletion=%d\n", fDriverCompletion);
    else if (ci->server[0] == '\0')
        paramRequired = TRUE;
 #endif /* WIN32 */
-   else if (ci->username[0] == '\0' && 'd' == ci->sslmode[0])
-       paramRequired = TRUE;
    if (paramRequired)
    {
-       /* (password_required && ci->password[0] == '\0')) */
-
-       return SQL_NO_DATA_FOUND;
+       if (didUI)
+           return SQL_NO_DATA_FOUND;
+       CC_set_error(conn, CONN_OPENDB_ERROR, "connction string lacks some options", func);
+       return SQL_ERROR;
    }
 
 inolog("before CC_connect\n");
diff --git a/info.c b/info.c
index 6f6c2dfb2d6ef2514e5c30cc3236933a7a56ea45..ab0cf894ed4ffb2eeeef752b11ad0368b22f1778 100644 (file)
--- a/info.c
+++ b/info.c
@@ -249,7 +249,7 @@ PGAPI_GetInfo(
            break;
 
        case SQL_DRIVER_ODBC_VER:
-           sprintf(odbcver, "%02x.%02x", ODBCVER / 256, ODBCVER % 256);
+           snprintf(odbcver, sizeof(odbcver), "%02x.%02x", ODBCVER / 256, ODBCVER % 256);
            /* p = DRIVER_ODBC_VER; */
            p = odbcver;
            break;
@@ -762,7 +762,7 @@ PGAPI_GetInfo(
        if (rgbInfoValue)
        {
 #ifdef UNICODE_SUPPORT
-           if (conn->unicode)
+           if (CC_is_in_unicode_driver(conn))
            {
                len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / WCLEN);
                len *= WCLEN;
@@ -778,7 +778,7 @@ PGAPI_GetInfo(
            }
        }
 #ifdef UNICODE_SUPPORT
-       else if (conn->unicode)
+       else if (CC_is_in_unicode_driver(conn))
            len *= WCLEN;
 #endif /* UNICODE_SUPPORT */
    }
@@ -831,7 +831,6 @@ PGAPI_GetTypeInfo(
    SC_set_Result(stmt, res);
 
 #define    return  DONT_CALL_RETURN_FROM_HERE???
-   /* StartRollbackState(stmt); */
 #if (ODBCVER >= 0x0300)
    result_cols = 19;
 #else
@@ -1314,6 +1313,114 @@ PGAPI_GetFunctions(
 }
 
 
+static char    *
+simpleCatalogEscape(const char *src, int srclen, int *result_len, const ConnectionClass *conn)
+{
+   int i, outlen;
+   const char *in;
+   char    *dest = NULL, escape_ch = CC_get_escape(conn);
+   BOOL    escape_in = FALSE;
+   encoded_str encstr;
+
+   if (result_len)
+       *result_len = 0;
+   if (!src || srclen == SQL_NULL_DATA)
+       return dest;
+   else if (srclen == SQL_NTS)
+       srclen = strlen(src);
+   if (srclen <= 0)
+       return dest;
+mylog("simple in=%s(%d)\n", src, srclen);
+   encoded_str_constr(&encstr, conn->ccsc, src);
+   dest = malloc(2 * srclen + 1);
+   for (i = 0, in = src, outlen = 0; i < srclen; i++, in++)
+   {
+                encoded_nextchar(&encstr);
+                if (ENCODE_STATUS(encstr) != 0)
+                {
+                        dest[outlen++] = *in;
+                        continue;
+                }
+       if (LITERAL_QUOTE == *in ||
+           escape_ch == *in)
+           dest[outlen++] = *in;
+       dest[outlen++] = *in;
+   }
+   dest[outlen] = '\0';
+   if (result_len)
+       *result_len = outlen;
+mylog("simple output=%s(%d)\n", dest, outlen);
+   return dest;
+}
+
+/*
+ * PostgreSQL needs 2 '\\' to escape '_' and '%'. 
+ */
+static char    *
+adjustLikePattern(const char *src, int srclen, char escape_ch, int *result_len, const ConnectionClass *conn)
+{
+   int i, outlen;
+   const char *in;
+   char    *dest = NULL, escape_in_literal = CC_get_escape(conn);
+   BOOL    escape_in = FALSE;
+   encoded_str encstr;
+
+   if (result_len)
+       *result_len = 0;
+   if (!src || srclen == SQL_NULL_DATA)
+       return dest;
+   else if (srclen == SQL_NTS)
+       srclen = strlen(src);
+   if (srclen <= 0)
+       return dest;
+mylog("adjust in=%s(%d)\n", src, srclen);
+   encoded_str_constr(&encstr, conn->ccsc, src);
+   dest = malloc(2 * srclen + 1);
+   for (i = 0, in = src, outlen = 0; i < srclen; i++, in++)
+   {
+                encoded_nextchar(&encstr);
+                if (ENCODE_STATUS(encstr) != 0)
+                {
+                        dest[outlen++] = *in;
+                        continue;
+                }
+       if (escape_in)
+       {
+           switch (*in)
+           {
+               case '%':
+               case '_':
+                   if (escape_ch == escape_in_literal)
+                       dest[outlen++] = escape_in_literal; /* and insert 1 more LEXER escape */
+                   dest[outlen++] = escape_ch;
+                   break;
+               default:
+                   if (escape_ch == escape_in_literal)
+                       dest[outlen++] = escape_in_literal;
+                   dest[outlen++] = escape_ch;
+                   if (escape_ch == escape_in_literal)
+                       dest[outlen++] = escape_in_literal;
+                   dest[outlen++] = escape_ch;
+                   break;
+           }
+       }
+       if (*in == escape_ch)
+           escape_in = TRUE;
+       else
+       {
+           escape_in = FALSE;
+           if (LITERAL_QUOTE == *in)
+               dest[outlen++] = *in;
+           dest[outlen++] = *in;
+       }
+   }
+   dest[outlen] = '\0';
+   if (result_len)
+       *result_len = outlen;
+mylog("adjust output=%s(%d)\n", dest, outlen);
+   return dest;
+}
+
 #define    CSTR_SYS_TABLE  "SYSTEM TABLE"
 #define    CSTR_TABLE  "TABLE"
 #define    CSTR_VIEW   "VIEW"
@@ -1321,14 +1428,15 @@ PGAPI_GetFunctions(
 RETCODE        SQL_API
 PGAPI_Tables(
             HSTMT hstmt,
-            const SQLCHAR FAR * szTableQualifier, /* PV */
+            const SQLCHAR FAR * szTableQualifier, /* PV X*/
             SQLSMALLINT cbTableQualifier,
-            const SQLCHAR FAR * szTableOwner, /* PV */
+            const SQLCHAR FAR * szTableOwner, /* PV E*/
             SQLSMALLINT cbTableOwner,
-            const SQLCHAR FAR * szTableName, /* PV */
+            const SQLCHAR FAR * szTableName, /* PV E*/
             SQLSMALLINT cbTableName,
             const SQLCHAR FAR * szTableType,
-            SQLSMALLINT cbTableType)
+            SQLSMALLINT cbTableType,
+            UWORD  flag)
 {
    CSTR func = "PGAPI_Tables";
    StatementClass *stmt = (StatementClass *) hstmt;
@@ -1347,6 +1455,7 @@ PGAPI_Tables(
 #endif /* HAVE_STRTOK_R */
    ConnectionClass *conn;
    ConnInfo   *ci;
+   char    *escSchemaName = NULL, *escTableName = NULL;
    char       *prefix[32],
                prefixes[MEDIUM_REGISTRY_LEN];
    char       *table_type[32],
@@ -1359,8 +1468,9 @@ PGAPI_Tables(
                systable;
    int         i;
    SQLSMALLINT     internal_asis_type = SQL_C_CHAR, cbSchemaName;
-   CSTR    likeeq = "like";
+   const char  *like_or_eq;
    const char  *szSchemaName;
+   BOOL    search_pattern;
 
    mylog("%s: entering...stmt=%x scnm=%x len=%d\n", func, stmt, NULL_IF_NULL(szTableOwner), cbTableOwner);
 
@@ -1381,8 +1491,24 @@ PGAPI_Tables(
    cbSchemaName = cbTableOwner;
 
 #define    return  DONT_CALL_RETURN_FROM_HERE???
-   /* StartRollbackState(stmt); */
+   search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
+   if (search_pattern) 
+   {
+       like_or_eq = likeop;
+       escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn);
+   }
+   else
+   {
+       like_or_eq = eqop;
+       escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
+   }
 retry_public_schema:
+   if (escSchemaName)
+       free(escSchemaName);
+   if (search_pattern) 
+       escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn);
+   else
+       escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
    /*
     * Create the query to find out the tables
     */
@@ -1408,12 +1534,12 @@ retry_public_schema:
 
    if (conn->schema_support)
    {
-       schema_strcat1(tables_query, " and nspname %s '%.*s'", likeeq, szSchemaName, cbSchemaName, szTableName, cbTableName, conn);
+       schema_strcat1(tables_query, " and nspname %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
        /* strcat(tables_query, " and pg_catalog.pg_table_is_visible(c.oid)"); */
    }
    else
-       my_strcat1(tables_query, " and usename %s '%.*s'", likeeq, szSchemaName, cbSchemaName);
-   my_strcat1(tables_query, " and relname %s '%.*s'", likeeq, szTableName, cbTableName);
+       my_strcat1(tables_query, " and usename %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS);
+   my_strcat1(tables_query, " and relname %s '%.*s'", like_or_eq, escTableName, SQL_NTS);
 
    /* Parse the extra systable prefix  */
    strcpy(prefixes, ci->drivers.extra_systable_prefixes);
@@ -1543,7 +1669,7 @@ retry_public_schema:
        }
    }
 #ifdef UNICODE_SUPPORT
-   if (conn->unicode)
+   if (CC_is_in_unicode_driver(conn))
        internal_asis_type = INTERNAL_ASIS_TYPE;
 #endif /* UNICODE_SUPPORT */
    result = PGAPI_BindCol(htbl_stmt, 1, internal_asis_type,
@@ -1687,6 +1813,10 @@ cleanup:
     */
    stmt->status = STMT_FINISHED;
 
+   if (escSchemaName)
+       free(escSchemaName);
+   if (escTableName)
+       free(escTableName);
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    SC_set_rowset_start(stmt, -1, FALSE);
@@ -1701,124 +1831,16 @@ cleanup:
    return ret;
 }
 
-static char    *
-simpleCatalogEscape(const char *src, int srclen, char escape_ch, int *result_len, int ccsc)
-{
-   int i, outlen;
-   const char *in;
-   char    *dest = NULL;
-   BOOL    escape_in = FALSE;
-   encoded_str encstr;
-
-   if (result_len)
-       *result_len = 0;
-   if (!src || srclen == SQL_NULL_DATA)
-       return dest;
-   else if (srclen == SQL_NTS)
-       srclen = strlen(src);
-   if (srclen <= 0)
-       return dest;
-mylog("simple in=%s(%d)\n", src, srclen);
-   encoded_str_constr(&encstr, ccsc, src);
-   dest = malloc(2 * srclen + 1);
-   for (i = 0, in = src, outlen = 0; i < srclen; i++, in++)
-   {
-                encoded_nextchar(&encstr);
-                if (ENCODE_STATUS(encstr) != 0)
-                {
-                        dest[outlen++] = *in;
-                        continue;
-                }
-       if (LITERAL_QUOTE == *in ||
-           escape_ch == *in)
-           dest[outlen++] = *in;
-       dest[outlen++] = *in;
-   }
-   dest[outlen] = '\0';
-   if (result_len)
-       *result_len = outlen;
-mylog("simple output=%s(%d)\n", dest, outlen);
-   return dest;
-}
-
-/*
- * PostgreSQL needs 2 '\\' to escape '_' and '%'. 
- */
-static char    *
-adjustLikePattern(const char *src, int srclen, char escape_ch, int *result_len, int ccsc)
-{
-   int i, outlen;
-   const char *in;
-   char    *dest = NULL;
-   BOOL    escape_in = FALSE;
-   encoded_str encstr;
-
-   if (result_len)
-       *result_len = 0;
-   if (!src || srclen == SQL_NULL_DATA)
-       return dest;
-   else if (srclen == SQL_NTS)
-       srclen = strlen(src);
-   if (srclen <= 0)
-       return dest;
-mylog("adjust in=%s(%d)\n", src, srclen);
-   encoded_str_constr(&encstr, ccsc, src);
-   dest = malloc(2 * srclen + 1);
-   for (i = 0, in = src, outlen = 0; i < srclen; i++, in++)
-   {
-                encoded_nextchar(&encstr);
-                if (ENCODE_STATUS(encstr) != 0)
-                {
-                        dest[outlen++] = *in;
-                        continue;
-                }
-       if (escape_in)
-       {
-           switch (*in)
-           {
-               case '%':
-               case '_':
-                   if (escape_ch == ESCAPE_IN_LITERAL)
-                       dest[outlen++] = ESCAPE_IN_LITERAL; /* and insert 1 more LEXER escape */
-                   dest[outlen++] = escape_ch;
-                   break;
-               default:
-                   if (escape_ch == ESCAPE_IN_LITERAL)
-                       dest[outlen++] = ESCAPE_IN_LITERAL;
-                   dest[outlen++] = escape_ch;
-                   if (escape_ch == ESCAPE_IN_LITERAL)
-                       dest[outlen++] = ESCAPE_IN_LITERAL;
-                   dest[outlen++] = escape_ch;
-                   break;
-           }
-       }
-       if (*in == escape_ch)
-           escape_in = TRUE;
-       else
-       {
-           escape_in = FALSE;
-           if (LITERAL_QUOTE == *in)
-               dest[outlen++] = *in;
-           dest[outlen++] = *in;
-       }
-   }
-   dest[outlen] = '\0';
-   if (result_len)
-       *result_len = outlen;
-mylog("adjust output=%s(%d)\n", dest, outlen);
-   return dest;
-}
-
 RETCODE        SQL_API
 PGAPI_Columns(
              HSTMT hstmt,
-             const SQLCHAR FAR * szTableQualifier, /* OA */
+             const SQLCHAR FAR * szTableQualifier, /* OA X*/
              SQLSMALLINT cbTableQualifier,
-             const SQLCHAR FAR * szTableOwner, /* PV */
+             const SQLCHAR FAR * szTableOwner, /* PV E*/
              SQLSMALLINT cbTableOwner,
-             const SQLCHAR FAR * szTableName, /* PV */
+             const SQLCHAR FAR * szTableName, /* PV E*/
              SQLSMALLINT cbTableName,
-             const SQLCHAR FAR * szColumnName, /* PV */
+             const SQLCHAR FAR * szColumnName, /* PV E*/
              SQLSMALLINT cbColumnName,
              UWORD flag,
              UInt4 reloid,
@@ -1837,7 +1859,6 @@ PGAPI_Columns(
                field_name[MAX_INFO_STRING],
                field_type_name[MAX_INFO_STRING];
    Int2        field_number, sqltype, concise_type,
-               reserved_cols,
                result_cols,
                decimal_digits;
    Int4        field_type,
@@ -1865,14 +1886,11 @@ PGAPI_Columns(
    conn = SC_get_conn(stmt);
    ci = &(conn->connInfo);
 #ifdef UNICODE_SUPPORT
-   if (conn->unicode)
+   if (CC_is_in_unicode_driver(conn))
        internal_asis_type = INTERNAL_ASIS_TYPE;
 #endif /* UNICODE_SUPPORT */
-   szSchemaName = szTableOwner;
-   cbSchemaName = cbTableOwner;
 
 #define    return  DONT_CALL_RETURN_FROM_HERE???
-   /* StartRollbackState(stmt); */
    search_by_ids = ((flag & PODBC_SEARCH_BY_IDS) != 0);
    if (search_by_ids)
    {
@@ -1892,19 +1910,26 @@ PGAPI_Columns(
        if (search_pattern) 
        {
            like_or_eq = likeop;
-           escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn->ccsc);
-           escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn->ccsc);
-           escColumnName = adjustLikePattern(szColumnName, cbColumnName, SEARCH_PATTERN_ESCAPE, NULL, conn->ccsc);
+           escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn);
+           escColumnName = adjustLikePattern(szColumnName, cbColumnName, SEARCH_PATTERN_ESCAPE, NULL, conn);
        }
        else
        {
            like_or_eq = eqop;
-           escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, ESCAPE_IN_LITERAL, NULL, conn->ccsc);
-           escTableName = simpleCatalogEscape(szTableName, cbTableName, ESCAPE_IN_LITERAL, NULL, conn->ccsc);
-           escColumnName = simpleCatalogEscape(szColumnName, cbColumnName, ESCAPE_IN_LITERAL, NULL, conn->ccsc);
+           escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
+           escColumnName = simpleCatalogEscape(szColumnName, cbColumnName, NULL, conn);
        }
    }
 retry_public_schema:
+   if (!search_by_ids)
+   {
+       if (escSchemaName)
+           free(escSchemaName);
+       if (search_pattern) 
+           escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn);
+       else
+           escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
+   }
    /*
     * Create the query to find out the columns (Note: pre 6.3 did not
     * have the atttypmod field)
@@ -1949,7 +1974,7 @@ retry_public_schema:
            PG_VERSION_LE(conn, 6.2) ? "a.attlen" : "a.atttypmod");
        if (escTableName)
            snprintf(columns_query, sizeof(columns_query), "%s and c.relname %s '%s'", columns_query, like_or_eq, escTableName);
-       my_strcat1(columns_query, " and u.usename %s '%.*s'", like_or_eq, szSchemaName, cbSchemaName);
+       my_strcat1(columns_query, " and u.usename %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS);
        if (escColumnName)
            snprintf(columns_query, sizeof(columns_query), "%s and a.attname %s '%s'", columns_query, like_or_eq, escColumnName);
        strcat(columns_query, " order by c.relname, attnum");
@@ -1995,11 +2020,8 @@ retry_public_schema:
        {
            PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
            hcol_stmt = NULL;
-           if (escSchemaName)
-               free(escSchemaName);
            szSchemaName = pubstr;
            cbSchemaName = SQL_NTS;
-           escSchemaName = strdup(szSchemaName);
            goto retry_public_schema;
        }
    }
@@ -2105,12 +2127,7 @@ retry_public_schema:
     * a statement is actually executed, so we'll have to do this
     * ourselves.
     */
-#if (ODBCVER >= 0x0300)
-   reserved_cols = 18;
-#else
-   reserved_cols = 12;
-#endif /* ODBCVER */
-   result_cols = COLUMNS_LAST + 1;
+   result_cols = NUM_OF_COLUMNS_FIELDS;
    extend_column_bindings(SC_get_ARDF(stmt), result_cols);
 
    stmt->catalog_result = TRUE;
@@ -2141,11 +2158,7 @@ retry_public_schema:
    QR_set_field_info_v(res, COLUMNS_DISPLAY_SIZE, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
    QR_set_field_info_v(res, COLUMNS_FIELD_TYPE, "FIELD_TYPE", PG_TYPE_INT4, 4);
    QR_set_field_info_v(res, COLUMNS_AUTO_INCREMENT, "AUTO_INCREMENT", PG_TYPE_INT4, 4);
-   if (reserved_cols != COLUMNS_DISPLAY_SIZE)
-   {
-       SC_set_error(stmt, STMT_INTERNAL_ERROR, "reserved_cols unmatch", func);
-       goto cleanup;
-   }
+   QR_set_field_info_v(res, COLUMNS_PHYSICAL_NUMBER, "PHYSICAL NUMBER", PG_TYPE_INT2, 2);
 
    ordinal = 1;
    result = PGAPI_Fetch(hcol_stmt);
@@ -2199,6 +2212,7 @@ retry_public_schema:
            set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
            set_tuplefield_int4(&tuple[COLUMNS_FIELD_TYPE], the_type);
            set_tuplefield_int4(&tuple[COLUMNS_AUTO_INCREMENT], TRUE);
+           set_tuplefield_int2(&tuple[COLUMNS_PHYSICAL_NUMBER], OID_ATTNUM);
            ordinal++;
        }
    }
@@ -2304,9 +2318,9 @@ mylog(" and the data=%s\n", attdef);
                sqltype = (field_type == PG_TYPE_BPCHAR) ? SQL_CHAR : SQL_VARCHAR;
 #else
            if (mod_length > ci->drivers.max_varchar_size)
-               sqltype = (conn->unicode ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR);
+               sqltype = (ALLOW_WCHAR(conn) ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR);
            else
-               sqltype = (field_type == PG_TYPE_BPCHAR) ? (conn->unicode ? SQL_WCHAR : SQL_CHAR) : (conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR);
+               sqltype = (field_type == PG_TYPE_BPCHAR) ? (ALLOW_WCHAR(conn) ? SQL_WCHAR : SQL_CHAR) : (ALLOW_WCHAR(conn) ? SQL_WVARCHAR : SQL_VARCHAR);
 #endif /* __MS_LOVES_REPORTS_CHAR__ */
 
            mylog("%s: field type is VARCHAR,BPCHAR: field_type = %d, mod_length = %d\n", func, field_type, mod_length);
@@ -2367,6 +2381,7 @@ mylog(" and the data=%s\n", attdef);
                    auto_unique = TRUE;
        }
        set_tuplefield_int4(&tuple[COLUMNS_AUTO_INCREMENT], auto_unique);
+       set_tuplefield_int2(&tuple[COLUMNS_PHYSICAL_NUMBER], field_number);
        ordinal++;
 
        result = PGAPI_Fetch(hcol_stmt);
@@ -2417,6 +2432,7 @@ mylog(" and the data=%s\n", attdef);
        set_tuplefield_int4(&tuple[COLUMNS_DISPLAY_SIZE], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
        set_tuplefield_int4(&tuple[COLUMNS_FIELD_TYPE], the_type);
        set_tuplefield_int4(&tuple[COLUMNS_AUTO_INCREMENT], FALSE);
+       set_tuplefield_int2(&tuple[COLUMNS_PHYSICAL_NUMBER], XMIN_ATTNUM);
        ordinal++;
    }
    result = SQL_SUCCESS;
@@ -2455,9 +2471,9 @@ PGAPI_SpecialColumns(
                SQLUSMALLINT fColType,
                const SQLCHAR FAR * szTableQualifier,
                SQLSMALLINT cbTableQualifier,
-               const SQLCHAR FAR * szTableOwner, /* OA */
+               const SQLCHAR FAR * szTableOwner, /* OA E*/
                SQLSMALLINT cbTableOwner,
-               const SQLCHAR FAR * szTableName, /* OA(R) */
+               const SQLCHAR FAR * szTableName, /* OA(R) E*/
                SQLSMALLINT cbTableName,
                SQLUSMALLINT fScope,
                SQLUSMALLINT fNullable)
@@ -2471,7 +2487,7 @@ PGAPI_SpecialColumns(
    HSTMT       hcol_stmt = NULL;
    StatementClass *col_stmt;
    char        columns_query[INFO_INQUIRY_LEN];
-   char        *table_name = NULL, *escTableName = NULL;
+   char        *escSchemaName = NULL, *escTableName = NULL;
    RETCODE     result = SQL_SUCCESS;
    char        relhasrules[MAX_INFO_STRING], relkind[8], relhasoids[8];
    BOOL        relisaview;
@@ -2485,21 +2501,25 @@ PGAPI_SpecialColumns(
    conn = SC_get_conn(stmt);
    ci = &(conn->connInfo);
 #ifdef UNICODE_SUPPORT
-   if (conn->unicode)
+   if (CC_is_in_unicode_driver(conn))
        internal_asis_type = INTERNAL_ASIS_TYPE;
 #endif /* UNICODE_SUPPORT */
 
    szSchemaName = szTableOwner;
    cbSchemaName = cbTableOwner;
 
-   if (!szTableName)
+   escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
+   if (!escTableName)
    {
        SC_set_error(stmt, STMT_INVALID_NULL_ARG, "The table name is required", func);
        return result;
    }
 #define    return  DONT_CALL_RETURN_FROM_HERE???
-   /* StartRollbackState(stmt); */
 retry_public_schema:
+   if (escSchemaName)
+       free(escSchemaName);
+   escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn); 
    /*
     * Create the query to find out if this is a view or not...
     */
@@ -2515,16 +2535,14 @@ retry_public_schema:
            "u.usesysid = c.relowner");
 
    /* TableName cannot contain a string search pattern */
-   table_name = make_string(szTableName, cbTableName, NULL, 0);
-   escTableName = simpleCatalogEscape(table_name, SQL_NTS, ESCAPE_IN_LITERAL, NULL, conn->ccsc); 
    /* my_strcat(columns_query, " and c.relname = '%.*s'", szTableName, cbTableName); */
    if (escTableName)
        snprintf(columns_query, sizeof(columns_query), "%s and c.relname = '%s'", columns_query, escTableName);
    /* SchemaName cannot contain a string search pattern */
    if (conn->schema_support)
-       schema_strcat(columns_query, " and u.nspname = '%.*s'", szSchemaName, cbSchemaName, szTableName, cbTableName, conn);
+       schema_strcat(columns_query, " and u.nspname = '%.*s'", escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
    else
-       my_strcat(columns_query, " and u.usename = '%.*s'", szSchemaName, cbSchemaName);
+       my_strcat(columns_query, " and u.usename = '%.*s'", escSchemaName, SQL_NTS);
 
 
    result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt);
@@ -2693,8 +2711,8 @@ inolog("Add ctid\n");
 
 cleanup:
 #undef return
-   if (table_name)
-       free(table_name);
+   if (escSchemaName)
+       free(escSchemaName);
    if (escTableName)
        free(escTableName);
    stmt->status = STMT_FINISHED;
@@ -2713,11 +2731,11 @@ cleanup:
 RETCODE        SQL_API
 PGAPI_Statistics(
            HSTMT hstmt,
-           const SQLCHAR FAR * szTableQualifier, /* OA */
+           const SQLCHAR FAR * szTableQualifier, /* OA X*/
            SQLSMALLINT cbTableQualifier,
-           const SQLCHAR FAR * szTableOwner, /* OA */
+           const SQLCHAR FAR * szTableOwner, /* OA E*/
            SQLSMALLINT cbTableOwner,
-           const SQLCHAR FAR * szTableName, /* OA(R) */
+           const SQLCHAR FAR * szTableName, /* OA(R) E*/
            SQLSMALLINT cbTableName,
            SQLUSMALLINT fUnique,
            SQLUSMALLINT fAccuracy)
@@ -2729,7 +2747,7 @@ PGAPI_Statistics(
    char        index_query[INFO_INQUIRY_LEN];
    HSTMT       hcol_stmt = NULL, hindx_stmt = NULL;
    RETCODE     ret = SQL_ERROR, result;
-   char        *table_name = NULL, *escTableName = NULL;
+   char        *escSchemaName = NULL, *table_name = NULL, *escTableName = NULL;
    char        index_name[MAX_INFO_STRING];
    short       fields_vector[INDEX_KEYS_STORAGE_COUNT];
    char        isunique[10],
@@ -2744,20 +2762,26 @@ PGAPI_Statistics(
    char        column_name[MAX_INFO_STRING],
            table_schemaname[MAX_INFO_STRING],
                relhasrules[10], relkind[8];
-   char      **column_names = NULL;
+   struct columns_idx {
+       int pnum;
+       char    *col_name;
+   } *column_names = NULL;
+   /* char   **column_names = NULL; */
    SQLINTEGER  column_name_len;
-   int         total_columns = 0;
+   int     total_columns = 0, alcount;
    ConnInfo   *ci;
    char        buf[256];
-   SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName;
+   SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName, field_number;
    const char  *szSchemaName;
+   BOOL        unknownf;
 
    mylog("%s: entering...stmt=%x scnm=%x len=%d\n", func, stmt, NULL_IF_NULL(szTableOwner), cbTableOwner);
 
    if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
 
-   if (!szTableName)
+   table_name = make_string(szTableName, cbTableName, NULL, 0);
+   if (!table_name)
    {
        SC_set_error(stmt, STMT_INVALID_NULL_ARG, "The table name is required", func);
        return result;
@@ -2765,7 +2789,7 @@ PGAPI_Statistics(
    conn = SC_get_conn(stmt);
    ci = &(conn->connInfo);
 #ifdef UNICODE_SUPPORT
-   if (conn->unicode)
+   if (CC_is_in_unicode_driver(conn))
        internal_asis_type = INTERNAL_ASIS_TYPE;
 #endif /* UNICODE_SUPPORT */
 
@@ -2786,36 +2810,25 @@ PGAPI_Statistics(
 
    stmt->catalog_result = TRUE;
    /* set the field names */
-   QR_set_num_fields(res, 13);
-   QR_set_field_info_v(res, 0, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
-   QR_set_field_info_v(res, 1, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
-   QR_set_field_info_v(res, 2, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
-   QR_set_field_info_v(res, 3, "NON_UNIQUE", PG_TYPE_INT2, 2);
-   QR_set_field_info_v(res, 4, "INDEX_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
-   QR_set_field_info_v(res, 5, "INDEX_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
-   QR_set_field_info_v(res, 6, "TYPE", PG_TYPE_INT2, 2);
-   QR_set_field_info_v(res, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
-   QR_set_field_info_v(res, 8, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
-   QR_set_field_info_v(res, 9, "COLLATION", PG_TYPE_CHAR, 1);
-   QR_set_field_info_v(res, 10, "CARDINALITY", PG_TYPE_INT4, 4);
-   QR_set_field_info_v(res, 11, "PAGES", PG_TYPE_INT4, 4);
-   QR_set_field_info_v(res, 12, "FILTER_CONDITION", PG_TYPE_VARCHAR, MAX_INFO_STRING);
+   QR_set_num_fields(res, NUM_OF_STATS_FIELDS);
+   QR_set_field_info_v(res, STATS_CATALOG_NAME, "TABLE_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
+   QR_set_field_info_v(res, STATS_SCHEMA_NAME, "TABLE_OWNER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
+   QR_set_field_info_v(res, STATS_TABLE_NAME, "TABLE_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
+   QR_set_field_info_v(res, STATS_NON_UNIQUE, "NON_UNIQUE", PG_TYPE_INT2, 2);
+   QR_set_field_info_v(res, STATS_INDEX_QUALIFIER, "INDEX_QUALIFIER", PG_TYPE_VARCHAR, MAX_INFO_STRING);
+   QR_set_field_info_v(res, STATS_INDEX_NAME, "INDEX_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
+   QR_set_field_info_v(res, STATS_TYPE, "TYPE", PG_TYPE_INT2, 2);
+   QR_set_field_info_v(res, STATS_SEQ_IN_INDEX, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
+   QR_set_field_info_v(res, STATS_COLUMN_NAME, "COLUMN_NAME", PG_TYPE_VARCHAR, MAX_INFO_STRING);
+   QR_set_field_info_v(res, STATS_COLLATION, "COLLATION", PG_TYPE_CHAR, 1);
+   QR_set_field_info_v(res, STATS_CARDINALITY, "CARDINALITY", PG_TYPE_INT4, 4);
+   QR_set_field_info_v(res, STATS_PAGES, "PAGES", PG_TYPE_INT4, 4);
+   QR_set_field_info_v(res, STATS_FILTER_CONDITION, "FILTER_CONDITION", PG_TYPE_VARCHAR, MAX_INFO_STRING);
 
-   /*
-    * only use the table name... the owner should be redundant, and we
-    * never use qualifiers.
-    */
-   table_name = make_string(szTableName, cbTableName, NULL, 0);
-   if (!table_name)
-   {
-       SC_set_error(stmt, STMT_INTERNAL_ERROR, "No table name passed to PGAPI_Statistics.", func);
-       goto cleanup;
-   }
+#define    return  DONT_CALL_RETURN_FROM_HERE???
    szSchemaName = szTableOwner;
    cbSchemaName = cbTableOwner;
 
-#define    return  DONT_CALL_RETURN_FROM_HERE???
-   /* StartRollbackState(stmt); */
    table_schemaname[0] = '\0';
    if (conn->schema_support)
        schema_strcat(table_schemaname, "%.*s", szSchemaName, cbSchemaName, szTableName, cbTableName, conn);
@@ -2850,28 +2863,43 @@ PGAPI_Statistics(
        SC_error_copy(stmt, col_stmt, TRUE);
        goto cleanup;
    }
-   result = PGAPI_BindCol(hcol_stmt, 4, internal_asis_type,
+   result = PGAPI_BindCol(hcol_stmt, COLUMNS_COLUMN_NAME + 1, internal_asis_type,
                         column_name, sizeof(column_name), &column_name_len);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_error_copy(stmt, col_stmt, TRUE);
        goto cleanup;
-
+   }
+   result = PGAPI_BindCol(hcol_stmt, COLUMNS_PHYSICAL_NUMBER + 1, SQL_C_SHORT,
+           &field_number, sizeof(field_number), NULL);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+   {
+       SC_error_copy(stmt, col_stmt, TRUE);
+       goto cleanup;
    }
 
+   alcount = 0;
    result = PGAPI_Fetch(hcol_stmt);
    while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
    {
        if (0 == total_columns)
            PGAPI_GetData(hcol_stmt, 2, internal_asis_type, table_schemaname, sizeof(table_schemaname), NULL);
-       total_columns++;
 
-       column_names =
-           (char **) realloc(column_names,
-                             total_columns * sizeof(char *));
-       column_names[total_columns - 1] =
+       if (total_columns >= alcount)
+       {
+           if (0 == alcount)
+               alcount = 4;
+           else
+               alcount *= 2;
+           column_names =
+               (struct columns_idx *) realloc(column_names,
+                             alcount * sizeof(struct columns_idx));
+       }
+       column_names[total_columns].col_name =
            (char *) malloc(strlen(column_name) + 1);
-       strcpy(column_names[total_columns - 1], column_name);
+       strcpy(column_names[total_columns].col_name, column_name);
+       column_names[total_columns].pnum = field_number;
+       total_columns++;
 
        mylog("%s: column_name = '%s'\n", func, column_name);
 
@@ -2903,8 +2931,10 @@ PGAPI_Statistics(
    indx_stmt = (StatementClass *) hindx_stmt;
 
    /* TableName cannot contain a string search pattern */
-   escTableName = simpleCatalogEscape(table_name, SQL_NTS, ESCAPE_IN_LITERAL, NULL, conn->ccsc); 
+   escTableName = simpleCatalogEscape(table_name, SQL_NTS, NULL, conn); 
    if (conn->schema_support)
+   {
+       escSchemaName = simpleCatalogEscape(table_schemaname, SQL_NTS, NULL, conn); 
        snprintf(index_query, sizeof(index_query), "select c.relname, i.indkey, i.indisunique"
            ", i.indisclustered, a.amname, c.relhasrules, n.nspname"
            " from pg_catalog.pg_index i, pg_catalog.pg_class c,"
@@ -2916,7 +2946,8 @@ PGAPI_Statistics(
            " and d.oid = i.indrelid"
            " and i.indexrelid = c.oid"
            " and c.relam = a.oid order by"
-           ,escTableName, table_schemaname);
+           ,escTableName, escSchemaName);
+   }
    else
        snprintf(index_query, sizeof(index_query), "select c.relname, i.indkey, i.indisunique"
            ", i.indisclustered, a.amname, c.relhasrules"
@@ -3012,31 +3043,31 @@ PGAPI_Statistics(
        tuple = QR_AddNew(res);
 
        /* no table qualifier */
-       set_tuplefield_string(&tuple[0], "");
+       set_tuplefield_string(&tuple[STATS_CATALOG_NAME], "");
        /* don't set the table owner, else Access tries to use it */
-       set_tuplefield_string(&tuple[1], GET_SCHEMA_NAME(table_schemaname));
-       set_tuplefield_string(&tuple[2], table_name);
+       set_tuplefield_string(&tuple[STATS_SCHEMA_NAME], GET_SCHEMA_NAME(table_schemaname));
+       set_tuplefield_string(&tuple[STATS_TABLE_NAME], table_name);
 
        /* non-unique index? */
-       set_tuplefield_int2(&tuple[3], (Int2) (ci->drivers.unique_index ? FALSE : TRUE));
+       set_tuplefield_int2(&tuple[STATS_NON_UNIQUE], (Int2) (ci->drivers.unique_index ? FALSE : TRUE));
 
        /* no index qualifier */
-       set_tuplefield_string(&tuple[4], "");
+       set_tuplefield_string(&tuple[STATS_INDEX_QUALIFIER], "");
 
-       sprintf(buf, "%s_idx_fake_oid", table_name);
-       set_tuplefield_string(&tuple[5], buf);
+       snprintf(buf, sizeof(table_name), "%s_idx_fake_oid", table_name);
+       set_tuplefield_string(&tuple[STATS_INDEX_NAME], buf);
 
        /*
         * Clustered/HASH index?
         */
-       set_tuplefield_int2(&tuple[6], (Int2) SQL_INDEX_OTHER);
-       set_tuplefield_int2(&tuple[7], (Int2) 1);
-
-       set_tuplefield_string(&tuple[8], "oid");
-       set_tuplefield_string(&tuple[9], "A");
-       set_tuplefield_null(&tuple[10]);
-       set_tuplefield_null(&tuple[11]);
-       set_tuplefield_null(&tuple[12]);
+       set_tuplefield_int2(&tuple[STATS_TYPE], (Int2) SQL_INDEX_OTHER);
+       set_tuplefield_int2(&tuple[STATS_SEQ_IN_INDEX], (Int2) 1);
+
+       set_tuplefield_string(&tuple[STATS_COLUMN_NAME], "oid");
+       set_tuplefield_string(&tuple[STATS_COLLATION], "A");
+       set_tuplefield_null(&tuple[STATS_CARDINALITY]);
+       set_tuplefield_null(&tuple[STATS_PAGES]);
+       set_tuplefield_null(&tuple[STATS_FILTER_CONDITION]);
    }
 
    while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
@@ -3052,49 +3083,67 @@ PGAPI_Statistics(
                tuple = QR_AddNew(res);
 
                /* no table qualifier */
-               set_tuplefield_string(&tuple[0], "");
+               set_tuplefield_string(&tuple[STATS_CATALOG_NAME], "");
                /* don't set the table owner, else Access tries to use it */
-               set_tuplefield_string(&tuple[1], GET_SCHEMA_NAME(table_schemaname));
-               set_tuplefield_string(&tuple[2], table_name);
+               set_tuplefield_string(&tuple[STATS_SCHEMA_NAME], GET_SCHEMA_NAME(table_schemaname));
+               set_tuplefield_string(&tuple[STATS_TABLE_NAME], table_name);
 
                /* non-unique index? */
                if (ci->drivers.unique_index)
-                   set_tuplefield_int2(&tuple[3], (Int2) (atoi(isunique) ? FALSE : TRUE));
+                   set_tuplefield_int2(&tuple[STATS_NON_UNIQUE], (Int2) (atoi(isunique) ? FALSE : TRUE));
                else
-                   set_tuplefield_int2(&tuple[3], TRUE);
+                   set_tuplefield_int2(&tuple[STATS_NON_UNIQUE], TRUE);
 
                /* no index qualifier */
-               set_tuplefield_string(&tuple[4], "");
-               set_tuplefield_string(&tuple[5], index_name);
+               set_tuplefield_string(&tuple[STATS_INDEX_QUALIFIER], "");
+               set_tuplefield_string(&tuple[STATS_INDEX_NAME], index_name);
 
                /*
                 * Clustered/HASH index?
                 */
-               set_tuplefield_int2(&tuple[6], (Int2)
+               set_tuplefield_int2(&tuple[STATS_TYPE], (Int2)
                               (atoi(isclustered) ? SQL_INDEX_CLUSTERED :
                                (!strncmp(ishash, "hash", 4)) ? SQL_INDEX_HASHED : SQL_INDEX_OTHER));
-               set_tuplefield_int2(&tuple[7], (Int2) (i + 1));
+               set_tuplefield_int2(&tuple[STATS_SEQ_IN_INDEX], (Int2) (i + 1));
 
                if (fields_vector[i] == OID_ATTNUM)
                {
-                   set_tuplefield_string(&tuple[8], "oid");
+                   set_tuplefield_string(&tuple[STATS_COLUMN_NAME], "oid");
                    mylog("%s: column name = oid\n", func);
                }
-               else if (fields_vector[i] < 0 || fields_vector[i] > total_columns)
-               {
-                   set_tuplefield_string(&tuple[8], "UNKNOWN");
-                   mylog("%s: column name = UNKNOWN\n", func);
-               }
                else
                {
-                   set_tuplefield_string(&tuple[8], column_names[fields_vector[i] - 1]);
-                   mylog("%s: column name = '%s'\n", func, column_names[fields_vector[i] - 1]);
+                   int j, matchidx;
+
+                   unknownf = TRUE;
+                   if (fields_vector[i] >= 0)
+                   {
+                       for (j = 0; j < total_columns; j++)
+                       {
+                           if (fields_vector[i] == column_names[j].pnum)
+                           {
+                               matchidx = j;
+                               unknownf = FALSE;
+                               break;
+                           }
+                       }
+                   }
+                   if (unknownf)
+                   {
+                       set_tuplefield_string(&tuple[STATS_COLUMN_NAME], "UNKNOWN");
+                       mylog("%s: column name = UNKNOWN\n", func);
+                   }
+                   else
+                   {
+                       set_tuplefield_string(&tuple[STATS_COLUMN_NAME], column_names[matchidx].col_name);
+                       mylog("%s: column name = '%s'\n", func, column_names[matchidx].col_name);
+                   }
                }
 
-               set_tuplefield_string(&tuple[9], "A");
-               set_tuplefield_null(&tuple[10]);
-               set_tuplefield_null(&tuple[11]);
-               set_tuplefield_null(&tuple[12]);
+               set_tuplefield_string(&tuple[STATS_COLLATION], "A");
+               set_tuplefield_null(&tuple[STATS_CARDINALITY]);
+               set_tuplefield_null(&tuple[STATS_PAGES]);
+               set_tuplefield_null(&tuple[STATS_FILTER_CONDITION]);
                i++;
            }
        }
@@ -3126,10 +3175,12 @@ cleanup:
        free(table_name);
    if (escTableName)
        free(escTableName);
+   if (escSchemaName)
+       free(escSchemaName);
    if (column_names)
    {
        for (i = 0; i < total_columns; i++)
-           free(column_names[i]);
+           free(column_names[i].col_name);
        free(column_names);
    }
 
@@ -3149,13 +3200,13 @@ cleanup:
 RETCODE        SQL_API
 PGAPI_ColumnPrivileges(
            HSTMT hstmt,
-           const SQLCHAR FAR * szTableQualifier, /* OA */
+           const SQLCHAR FAR * szTableQualifier, /* OA X*/
            SQLSMALLINT cbTableQualifier,
-           const SQLCHAR FAR * szTableOwner, /* OA */
+           const SQLCHAR FAR * szTableOwner, /* OA E*/
            SQLSMALLINT cbTableOwner,
-           const SQLCHAR FAR * szTableName, /* OA(R) */
+           const SQLCHAR FAR * szTableName, /* OA(R) E*/
            SQLSMALLINT cbTableName,
-           const SQLCHAR FAR * szColumnName, /* PV */
+           const SQLCHAR FAR * szColumnName, /* PV E*/
            SQLSMALLINT cbColumnName,
            UWORD flag)
 {
@@ -3177,18 +3228,18 @@ PGAPI_ColumnPrivileges(
        return result;
    if (PG_VERSION_LT(conn, 7.4))
        SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Function not implementedyet", func);
-   escSchemaName = simpleCatalogEscape(szTableOwner, cbTableOwner, ESCAPE_IN_LITERAL, NULL, conn->ccsc);
-   escTableName = simpleCatalogEscape(szTableName, cbTableName, ESCAPE_IN_LITERAL, NULL, conn->ccsc);
+   escSchemaName = simpleCatalogEscape(szTableOwner, cbTableOwner, NULL, conn);
+   escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
    search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
    if (search_pattern) 
    {
        like_or_eq = likeop;
-       escColumnName = adjustLikePattern(szColumnName, cbColumnName, SEARCH_PATTERN_ESCAPE, NULL, conn->ccsc);
+       escColumnName = adjustLikePattern(szColumnName, cbColumnName, SEARCH_PATTERN_ESCAPE, NULL, conn);
    }
    else
    {
        like_or_eq = eqop;
-       escColumnName = simpleCatalogEscape(szColumnName, cbColumnName, ESCAPE_IN_LITERAL, NULL, conn->ccsc);
+       escColumnName = simpleCatalogEscape(szColumnName, cbColumnName, NULL, conn);
    }
    strcpy(column_query, "select '' as TABLE_CAT, table_schema as TABLE_SCHEM,"
            " table_name, column_name, grantor, grantee,"
@@ -3241,11 +3292,11 @@ cleanup:
 RETCODE        SQL_API
 PGAPI_PrimaryKeys(
            HSTMT hstmt,
-           const SQLCHAR FAR * szTableQualifier, /* OA */
+           const SQLCHAR FAR * szTableQualifier, /* OA X*/
            SQLSMALLINT cbTableQualifier,
-           const SQLCHAR FAR * szTableOwner, /* OA */
+           const SQLCHAR FAR * szTableOwner, /* OA E*/
            SQLSMALLINT cbTableOwner,
-           const SQLCHAR FAR * szTableName, /* OA(R) */
+           const SQLCHAR FAR * szTableName, /* OA(R) E*/
            SQLSMALLINT cbTableName)
 {
    CSTR func = "PGAPI_PrimaryKeys";
@@ -3267,6 +3318,7 @@ PGAPI_PrimaryKeys(
                qend;
    SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName;
    const char  *szSchemaName;
+   char    *escSchemaName = NULL, *escTableName = NULL;
 
    mylog("%s: entering...stmt=%x scnm=%x len=%d\n", func, stmt, NULL_IF_NULL(szTableOwner), cbTableOwner);
 
@@ -3310,7 +3362,7 @@ PGAPI_PrimaryKeys(
 
    conn = SC_get_conn(stmt);
 #ifdef UNICODE_SUPPORT
-   if (conn->unicode)
+   if (CC_is_in_unicode_driver(conn))
        internal_asis_type = INTERNAL_ASIS_TYPE;
 #endif /* UNICODE_SUPPORT */
 
@@ -3325,11 +3377,15 @@ PGAPI_PrimaryKeys(
    cbSchemaName = cbTableOwner;
 
 #define    return  DONT_CALL_RETURN_FROM_HERE???
-   /* StartRollbackState(stmt); */
+   escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
+
 retry_public_schema:
+   if (escSchemaName)
+       free(escSchemaName);
+   escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
    pkscm[0] = '\0';
    if (conn->schema_support)
-       schema_strcat(pkscm, "%.*s", szSchemaName, cbSchemaName, szTableName, cbTableName, conn);
+       schema_strcat(pkscm, "%.*s", escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
 
    result = PGAPI_BindCol(htbl_stmt, 1, internal_asis_type,
                           attname, MAX_INFO_STRING, &attname_len);
@@ -3371,7 +3427,7 @@ retry_public_schema:
                        " AND ta.attnum = i.indkey[ia.attnum-1]"
                        " AND (NOT ta.attisdropped)"
                        " AND (NOT ia.attisdropped)"
-                       " order by ia.attnum", pktab, pkscm);
+                       " order by ia.attnum", escTableName, pkscm);
                else
                    snprintf(tables_query, sizeof(tables_query), "select ta.attname, ia.attnum"
                        " from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i"
@@ -3381,7 +3437,7 @@ retry_public_schema:
                        " AND ia.attrelid = i.indexrelid"
                        " AND ta.attrelid = i.indrelid"
                        " AND ta.attnum = i.indkey[ia.attnum-1]"
-                       " order by ia.attnum", pktab);
+                       " order by ia.attnum", escTableName);
                break;
            case 2:
 
@@ -3402,7 +3458,7 @@ retry_public_schema:
                        " AND ta.attnum = i.indkey[ia.attnum-1]"
                        " AND (NOT ta.attisdropped)"
                        " AND (NOT ia.attisdropped)"
-                       " order by ia.attnum", pktab, pkscm);
+                       " order by ia.attnum", escTableName, pkscm);
                else
                    snprintf(tables_query, sizeof(tables_query), "select ta.attname, ia.attnum"
                        " from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i"
@@ -3411,7 +3467,7 @@ retry_public_schema:
                        " AND ia.attrelid = i.indexrelid"
                        " AND ta.attrelid = i.indrelid"
                        " AND ta.attnum = i.indkey[ia.attnum-1]"
-                       " order by ia.attnum", pktab);
+                       " order by ia.attnum", escTableName);
                break;
        }
        mylog("%s: tables_query='%s'\n", func, tables_query);
@@ -3496,6 +3552,10 @@ cleanup:
 
    if (pktab)
        free(pktab);
+   if (escSchemaName)
+       free(escSchemaName);
+   if (escTableName)
+       free(escTableName);
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    SC_set_rowset_start(stmt, -1, FALSE);
@@ -3523,148 +3583,6 @@ isMultibyte(const UCHAR *str)
    }
    return FALSE;
 }
-#ifdef NOT_USED
-static char *
-getClientTableName(ConnectionClass *conn, const char *serverSchemaName, char *serverTableName, BOOL *nameAlloced)
-{
-   char        query[1024],
-               saveoid[24],
-              *ret = serverTableName;
-   BOOL        continueExec = TRUE,
-               bError = FALSE;
-   QResultClass *res;
-
-   *nameAlloced = FALSE;
-   if (!conn->origianl_client_encoding || !isMultibyte(serverTableName))
-       return ret;
-   if (!conn->server_encoding)
-   {
-       if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR, NULL), QR_command_maybe_successsful(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;
-   snprintf(query, sizeof(query), "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
-   bError = (!QR_command_maybe_successful(res = CC_send_query(conn, query, NULL, IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR, NULL));
-   QR_Destrctor(res);
-   if (!bError && continueExec)
-   {
-       if (conn->schema_support)
-           snprintf(query, sizeof(query), "select OID from pg_catalog.pg_class,"
-           " pg_catalog.pg_namespace"
-           " where relname = '%s' and pg_namespace.oid = relnamespace and"
-           " pg_namespace.nspname = '%s'", serverTableName, serverSchemaName);
-       else
-           snprintf(query, sizeof(query), "select OID from pg_class where relname = '%s'", serverTableName);
-       if (res = CC_send_query(conn, query, NULL, ROLLBACK_ON_ERROR | GNORE_ABORT_ON_CONN), QR_command_maybe_successful(res))
-       {
-           if (QR_get_num_tuples(res) > 0)
-               strcpy(saveoid, QR_get_value_backend_row(res, 0, 0));
-           else
-               continueExec = FALSE;
-       }
-       else
-           bError = TRUE;
-       QR_Destructor(res);
-   }
-   continueExec = (continueExec && !bError);
-   /* restore the client encoding */
-   snprintf(query, sizeof(query), "SET CLIENT_ENCODING TO '%s'", conn->original_client_encoding);
-   bError = (QR_command_maybe_successful(res = CC_send_query(conn, query, NULL, IGNORE_ABORT_ON_CONN, NULL));
-   QR_Destrcutor(res);
-   if (bError || !continueExec)
-       return ret;
-   snprintf(query, sizeof(query), "select relname from pg_class where OID = %s", saveoid);
-   if (res = CC_send_query(conn, query, NULL, IGNORE_ABORT_ON_CONN, NULL), QR_command_maybe_successful(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 * serverSchemaName, 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->original_client_encoding || !isMultibyte(serverColumnName))
-       return ret;
-   if (!conn->server_encoding)
-   {
-       if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, IGNORE_ABORT_ON_CONN, NULL), QR_command_maybe_successful(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;
-   snprintf(query, sizeof(query), "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
-   bError = (!QR_command_maybe_successful(res = CC_send_query(conn, query, NULL, IGNORE_ABORT_ON_CONN, NULL));
-   QR_Destructor(res);
-   if (!bError && continueExec)
-   {
-       if (conn->schema_support)
-           snprintf(query, sizeof(query), "select attrelid, attnum from pg_catalog.pg_class,"
-           " pg_catalog.pg_attribute, pg_catalog.pg_namespace "
-               "where relname = '%s' and attrelid = pg_class.oid "
-               "and (not attisdropped) "
-               "and attname = '%s' and pg_namespace.oid = relnamespace and"
-               " pg_namespace.nspname = '%s'", serverTableName, serverColumnName, serverSchemaName);
-       else
-           snprintf(query, sizeof(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, ROLLBACK_ON_ERROR | IGNORE_ABORT_ON_CONN, NULL), QR_command_maybe_successful(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;
-       }
-       else
-           bError = TRUE;
-       QR_Destructor(res);
-   }
-   continueExec = (continueExec && !bError);
-   /* restore the cleint encoding */
-   snprintf(query, sizeof(query), "SET CLIENT_ENCODING TO '%s'", conn->original_client_encoding);
-   bError = (!QR_command_maybe_successful(res = CC_send_query(conn, query, NULL, IGNORE_ABORT_ON_CONN, NULL));
-   QR_Destructor(res);
-   if (bError || !continueExec)
-       return ret;
-   snprintf(query, sizeof(query), "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum);
-   if (res = CC_send_query(conn, query, NULL, IGNORE_ABORT_ON_CONN, NULL), QR_command_maybe_successful(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 /* NOT_USED */
 static char *
 getClientColumnName(ConnectionClass *conn, UInt4 relid, char *serverColumnName, BOOL *nameAlloced)
 {
@@ -3733,17 +3651,17 @@ getClientColumnName(ConnectionClass *conn, UInt4 relid, char *serverColumnName,
 RETCODE        SQL_API
 PGAPI_ForeignKeys(
            HSTMT hstmt,
-           const SQLCHAR FAR * szPkTableQualifier, /* OA */
+           const SQLCHAR FAR * szPkTableQualifier, /* OA X*/
            SQLSMALLINT cbPkTableQualifier,
-           const SQLCHAR FAR * szPkTableOwner, /* OA */
+           const SQLCHAR FAR * szPkTableOwner, /* OA E*/
            SQLSMALLINT cbPkTableOwner,
-           const SQLCHAR FAR * szPkTableName, /* OA(R) */
+           const SQLCHAR FAR * szPkTableName, /* OA(R) E*/
            SQLSMALLINT cbPkTableName,
-           const SQLCHAR FAR * szFkTableQualifier, /* OA */
+           const SQLCHAR FAR * szFkTableQualifier, /* OA X*/
            SQLSMALLINT cbFkTableQualifier,
-           const SQLCHAR FAR * szFkTableOwner, /* OA */
+           const SQLCHAR FAR * szFkTableOwner, /* OA E*/
            SQLSMALLINT cbFkTableOwner,
-           const SQLCHAR FAR * szFkTableName, /* OA(R) */
+           const SQLCHAR FAR * szFkTableName, /* OA(R) E*/
            SQLSMALLINT cbFkTableName)
 {
    CSTR func = "PGAPI_ForeignKeys";
@@ -3759,9 +3677,9 @@ PGAPI_ForeignKeys(
    char        trig_args[1024];
    char        upd_rule[TABLE_NAME_STORAGE_LEN],
                del_rule[TABLE_NAME_STORAGE_LEN];
-   char        *pk_table_needed = NULL;
+   char        *pk_table_needed = NULL, *escPkTableName = NULL;
    char        fk_table_fetched[TABLE_NAME_STORAGE_LEN + 1];
-   char        *fk_table_needed = NULL;
+   char        *fk_table_needed = NULL, *escFkTableName = NULL;
    char        pk_table_fetched[TABLE_NAME_STORAGE_LEN + 1];
    char        schema_needed[SCHEMA_NAME_STORAGE_LEN + 1];
    char        schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
@@ -3807,12 +3725,7 @@ PGAPI_ForeignKeys(
     * a statement is actually executed, so we'll have to do this
     * ourselves.
     */
-#if (ODBCVER >= 0x0300)
-   result_cols = 15;
-#else
-   result_cols = 14;
-#endif /* ODBCVER */
-   result_cols = FKS_LAST + 1;
+   result_cols = NUM_OF_FKS_FIELDS;
    extend_column_bindings(SC_get_ARDF(stmt), result_cols);
 
    stmt->catalog_result = TRUE;
@@ -3856,7 +3769,6 @@ PGAPI_ForeignKeys(
    }
 
 #define    return  DONT_CALL_RETURN_FROM_HERE???
-   /* StartRollbackState(stmt); */
 
    tbl_stmt = (StatementClass *) htbl_stmt;
    schema_needed[0] = '\0';
@@ -3867,7 +3779,7 @@ PGAPI_ForeignKeys(
 
    conn = SC_get_conn(stmt);
 #ifdef UNICODE_SUPPORT
-   if (conn->unicode)
+   if (CC_is_in_unicode_driver(conn))
        internal_asis_type = INTERNAL_ASIS_TYPE;
 #endif /* UNICODE_SUPPORT */
    pkey_alloced = fkey_alloced = FALSE;
@@ -3879,9 +3791,13 @@ PGAPI_ForeignKeys(
    if (fk_table_needed && fk_table_needed[0] != '\0')
    {
        mylog("%s: entering Foreign Key Case #2", func);
+       escFkTableName = simpleCatalogEscape(fk_table_needed, SQL_NTS, NULL, conn);
        if (conn->schema_support)
        {
+           char    *escSchemaName;
+
            schema_strcat(schema_needed, "%.*s", szFkTableOwner, cbFkTableOwner, szFkTableName, cbFkTableName, conn);
+           escSchemaName = simpleCatalogEscape(schema_needed, SQL_NTS, NULL, conn);
            snprintf(tables_query, sizeof(tables_query), "SELECT    pt.tgargs, "
                "       pt.tgnargs, "
                "       pt.tgdeferrable, "
@@ -3920,7 +3836,8 @@ PGAPI_ForeignKeys(
                "AND (pt2.tgconstrname=pt.tgconstrname) "
                "AND (pt.tgconstrrelid=pc1.oid) "
                "AND (pc1.relnamespace=pn.oid))",
-               fk_table_needed, schema_needed);
+               escFkTableName, escSchemaName);
+           free(escSchemaName);
        }
        else
            snprintf(tables_query, sizeof(tables_query), "SELECT    pt.tgargs, "
@@ -3955,7 +3872,7 @@ PGAPI_ForeignKeys(
                "AND (pt2.tgrelid=pt.tgconstrrelid) "
                "AND (pt2.tgconstrname=pt.tgconstrname) "
                "AND (pt.tgconstrrelid=pc1.oid)) ",
-               fk_table_needed);
+               escFkTableName);
 
        result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
 
@@ -4229,9 +4146,13 @@ PGAPI_ForeignKeys(
     */
    else if (pk_table_needed[0] != '\0')
    {
+       escPkTableName = simpleCatalogEscape(pk_table_needed, SQL_NTS, NULL, conn);
        if (conn->schema_support)
        {
+           char    *escSchemaName;
+
            schema_strcat(schema_needed, "%.*s", szPkTableOwner, cbPkTableOwner, szPkTableName, cbPkTableName, conn);
+           escSchemaName = simpleCatalogEscape(schema_needed, SQL_NTS, NULL, conn);
            snprintf(tables_query, sizeof(tables_query), "SELECT    pt.tgargs, "
                "       pt.tgnargs, "
                "       pt.tgdeferrable, "
@@ -4269,7 +4190,8 @@ PGAPI_ForeignKeys(
                "   AND  (pt2.tgrelid = pt.tgconstrrelid) "
                "   AND (pn.oid = pc1.relnamespace) "
                "       )",
-               pk_table_needed, schema_needed);
+               escPkTableName, escSchemaName);
+           free(escSchemaName);
        }
        else
            snprintf(tables_query, sizeof(tables_query), "SELECT    pt.tgargs, "
@@ -4303,7 +4225,7 @@ PGAPI_ForeignKeys(
                "   AND  (pt1.tgrelid = pt.tgconstrrelid) "
                "   AND  (pt2.tgrelid = pt.tgconstrrelid) "
                "       )",
-               pk_table_needed);
+               escPkTableName);
 
        result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
@@ -4531,8 +4453,12 @@ cleanup:
        free(fkey_text);
    if (pk_table_needed)
        free(pk_table_needed);
+   if (escPkTableName)
+       free(escPkTableName);
    if (fk_table_needed)
        free(fk_table_needed);
+   if (escFkTableName)
+       free(escFkTableName);
 
    if (htbl_stmt)
        PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
@@ -4552,16 +4478,17 @@ cleanup:
 
 
 #define    PRORET_COUNT
+#define    DISPLAY_ARGNAME
 RETCODE        SQL_API
 PGAPI_ProcedureColumns(
                HSTMT hstmt,
-               const SQLCHAR FAR * szProcQualifier, /* OA */
+               const SQLCHAR FAR * szProcQualifier, /* OA X*/
                SQLSMALLINT cbProcQualifier,
-               const SQLCHAR FAR * szProcOwner, /* PV */
+               const SQLCHAR FAR * szProcOwner, /* PV E*/
                SQLSMALLINT cbProcOwner,
-               const SQLCHAR FAR * szProcName, /* PV */
+               const SQLCHAR FAR * szProcName, /* PV E*/
                SQLSMALLINT cbProcName,
-               const SQLCHAR FAR * szColumnName, /* PV */
+               const SQLCHAR FAR * szColumnName, /* PV X*/
                SQLSMALLINT cbColumnName,
                UWORD flag)
 {
@@ -4572,7 +4499,7 @@ PGAPI_ProcedureColumns(
    Int2        result_cols;
    TupleField  *tuple;
    char        *schema_name, *procname;
-   char        *escProcName = NULL;
+   char        *escSchemaName = NULL, *escProcName = NULL;
    char        *params, *proargnames, *proargmodes, *delim;
    char        *atttypid, *attname, *column_name;
    QResultClass *res, *tres;
@@ -4596,12 +4523,14 @@ PGAPI_ProcedureColumns(
    if (search_pattern) 
    {
        like_or_eq = likeop;
-       escProcName = adjustLikePattern(szProcName, cbProcName, SEARCH_PATTERN_ESCAPE, NULL, conn->ccsc);
+       escSchemaName = adjustLikePattern(szProcOwner, cbProcOwner, SEARCH_PATTERN_ESCAPE, NULL, conn);
+       escProcName = adjustLikePattern(szProcName, cbProcName, SEARCH_PATTERN_ESCAPE, NULL, conn);
    }
    else
    {
        like_or_eq = eqop;
-       escProcName = simpleCatalogEscape(szProcName, cbProcName, ESCAPE_IN_LITERAL, NULL, conn->ccsc);
+       escSchemaName = simpleCatalogEscape(szProcOwner, cbProcOwner, NULL, conn);
+       escProcName = simpleCatalogEscape(szProcName, cbProcName, NULL, conn);
    }
    if (conn->schema_support)
    {
@@ -4624,7 +4553,7 @@ PGAPI_ProcedureColumns(
        if (PG_VERSION_GE(conn, 8.1))
        {
            strcat(proc_query, ", proargmodes, proallargtypes");
-           ret_col++;
+           ret_col += 2;
        }
 #ifdef PRORET_COUNT
        strcat(proc_query, " from ((pg_catalog.pg_namespace n inner join"
@@ -4639,8 +4568,9 @@ PGAPI_ProcedureColumns(
                   " (not proretset) and");
 #endif /* PRORET_COUNT */
        strcat(proc_query, " has_function_privilege(p.oid, 'EXECUTE')");
-       my_strcat1(proc_query, " and nspname %s '%.*s'", like_or_eq, szProcOwner, cbProcOwner);
-       snprintf(proc_query, sizeof(proc_query), "%s and proname %s '%s'", proc_query, like_or_eq, escProcName);
+       my_strcat1(proc_query, " and nspname %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS);
+       if (escProcName)
+           snprintf(proc_query, sizeof(proc_query), "%s and proname %s '%s'", proc_query, like_or_eq, escProcName);
        strcat(proc_query, " order by nspname, proname, p.oid, attnum");
    }
    else
@@ -4649,8 +4579,8 @@ PGAPI_ProcedureColumns(
                "pronargs, proargtypes from pg_proc where "
                "(not proretset)");
        ret_col = 5;
-       /* my_strcat1(proc_query, " and proname %s '%.*s'", like_or_eq, szProcName, cbProcName); */
-       snprintf(proc_query, sizeof(proc_query), " and proname %s '%s'", proc_query, like_or_eq, escProcName);
+       if (escProcName)
+           snprintf(proc_query, sizeof(proc_query), " and proname %s '%s'", proc_query, like_or_eq, escProcName);
        strcat(proc_query, " order by proname, proretset");
    }
    if (tres = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(tres))
@@ -4736,10 +4666,10 @@ mylog("atttypid=%s\n", atttypid ? atttypid : "(null)");
            proargnames = NULL;
            if (ext_pos >=0)
            {
-#ifdef NOT_USED /* !! named parameter is unavailable !! */
+#ifdef DISPLAY_ARGNAME /* !! named parameter is unavailable !! */
                if (PG_VERSION_GE(conn, 8.0))
                    proargnames = QR_get_value_backend_row(tres, i, ext_pos);
-#endif /* NOT_USED */
+#endif /* DISPLAY_ARGNAME */
                if (PG_VERSION_GE(conn, 8.1))
                    proargmodes = QR_get_value_backend_row(tres, i, ext_pos + 1);
            }
@@ -4780,7 +4710,7 @@ mylog("atttypid=%s\n", atttypid ? atttypid : "(null)");
                        paramcount++;
                }
                paramcount++;
-               params = QR_get_value_backend_row(tres, i, 8);
+               params = QR_get_value_backend_row(tres, i, ext_pos + 2);
                if ('{' == *proargmodes)
                    proargmodes++;
                if ('{' == *params)
@@ -4864,6 +4794,7 @@ mylog("atttypid=%s\n", atttypid ? atttypid : "(null)");
                    {
                        case 'o':
                            ptype = SQL_PARAM_OUTPUT;
+                           break;
                        case 'b':
                            ptype = SQL_PARAM_INPUT_OUTPUT;
                            break;
@@ -4929,6 +4860,8 @@ mylog("atttypid=%s\n", atttypid ? atttypid : "(null)");
     * also, things need to think that this statement is finished so the
     * results can be retrieved.
     */
+   if (escSchemaName)
+       free(escSchemaName);
    if (escProcName)
        free(escProcName);
    stmt->status = STMT_FINISHED;
@@ -4944,20 +4877,23 @@ mylog("atttypid=%s\n", atttypid ? atttypid : "(null)");
 RETCODE        SQL_API
 PGAPI_Procedures(
                 HSTMT hstmt,
-                const SQLCHAR FAR * szProcQualifier, /* OA */
+                const SQLCHAR FAR * szProcQualifier, /* OA X*/
                 SQLSMALLINT cbProcQualifier,
-                const SQLCHAR FAR * szProcOwner, /* PV */
+                const SQLCHAR FAR * szProcOwner, /* PV E*/
                 SQLSMALLINT cbProcOwner,
-                const SQLCHAR FAR * szProcName, /* PV */
-                SQLSMALLINT cbProcName)
+                const SQLCHAR FAR * szProcName, /* PV E*/
+                SQLSMALLINT cbProcName,
+                UWORD flag)
 {
    CSTR func = "PGAPI_Procedures";
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn = SC_get_conn(stmt);
    char        proc_query[INFO_INQUIRY_LEN];
+   char    *escSchemaName = NULL, *escProcName = NULL;
    QResultClass *res;
    RETCODE     result;
-   CSTR    likeeq = "like";
+   const char  *like_or_eq;
+   BOOL    search_pattern;
 
    mylog("%s: entering... scnm=%x len=%d\n", func, szProcOwner, cbProcOwner);
 
@@ -4969,6 +4905,19 @@ PGAPI_Procedures(
    if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
 
+   search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
+   if (search_pattern) 
+   {
+       like_or_eq = likeop;
+       escSchemaName = adjustLikePattern(szProcOwner, cbProcOwner, SEARCH_PATTERN_ESCAPE, NULL, conn);
+       escProcName = adjustLikePattern(szProcName, cbProcName, SEARCH_PATTERN_ESCAPE, NULL, conn);
+   }
+   else
+   {
+       like_or_eq = eqop;
+       escSchemaName = simpleCatalogEscape(szProcOwner, cbProcOwner, NULL, conn);
+       escProcName = simpleCatalogEscape(szProcName, cbProcName, NULL, conn);
+   }
    /*
     * The following seems the simplest implementation
     */
@@ -4982,8 +4931,8 @@ PGAPI_Procedures(
           " as "         "PROCEDURE_TYPE" " from pg_catalog.pg_namespace,"
           " pg_catalog.pg_proc"
          " where pg_proc.pronamespace = pg_namespace.oid");
-       schema_strcat1(proc_query, " and nspname %s '%.*s'", likeeq, szProcOwner, cbProcOwner, szProcName, cbProcName, conn);
-       my_strcat1(proc_query, " and proname %s '%.*s'", likeeq, szProcName, cbProcName);
+       schema_strcat1(proc_query, " and nspname %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS, szProcName, cbProcName, conn);
+       my_strcat1(proc_query, " and proname %s '%.*s'", like_or_eq, escProcName, SQL_NTS);
    }
    else
    {
@@ -4992,7 +4941,7 @@ PGAPI_Procedures(
           " '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" ","
           " '' as " "REMARKS" ","
           " case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
-       my_strcat1(proc_query, " where proname %s '%.*s'", likeeq, szProcName, cbProcName);
+       my_strcat1(proc_query, " where proname %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS);
    }
 
    if (res = CC_send_query(conn, proc_query, NULL, IGNORE_ABORT_ON_CONN, stmt), !QR_command_maybe_successful(res))
@@ -5009,6 +4958,10 @@ PGAPI_Procedures(
     */
    stmt->status = STMT_FINISHED;
    extend_column_bindings(SC_get_ARDF(stmt), 8);
+   if (escSchemaName)
+       free(escSchemaName);
+   if (escProcName)
+       free(escProcName);
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    SC_set_rowset_start(stmt, -1, FALSE);
@@ -5067,11 +5020,11 @@ mylog("user=%s auth=%s\n", user, auth);
 RETCODE        SQL_API
 PGAPI_TablePrivileges(
                HSTMT hstmt,
-               const SQLCHAR FAR * szTableQualifier, /* OA */
+               const SQLCHAR FAR * szTableQualifier, /* OA X*/
                SQLSMALLINT cbTableQualifier,
-               const SQLCHAR FAR * szTableOwner, /* PV */
+               const SQLCHAR FAR * szTableOwner, /* PV E*/
                SQLSMALLINT cbTableOwner,
-               const SQLCHAR FAR * szTableName, /* PV */
+               const SQLCHAR FAR * szTableName, /* PV E*/
                SQLSMALLINT cbTableName,
                UWORD flag)
 {
@@ -5130,28 +5083,32 @@ PGAPI_TablePrivileges(
    cbSchemaName = cbTableOwner;
 
 #define    return  DONT_CALL_RETURN_FROM_HERE???
-   /* StartRollbackState(stmt); */
-retry_public_schema:
-   if (conn->schema_support)
-       strncpy_null(proc_query, "select relname, usename, relacl, nspname"
-       " from pg_catalog.pg_namespace, pg_catalog.pg_class ,"
-       " pg_catalog.pg_user where", sizeof(proc_query));
-   else
-       strncpy_null(proc_query, "select relname, usename, relacl"
-       " from pg_class , pg_user where", sizeof(proc_query));
    search_pattern = (0 == (flag & PODBC_NOT_SEARCH_PATTERN));
    if (search_pattern) 
    {
        like_or_eq = likeop;
-       escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn->ccsc);
-       escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn->ccsc);
+       escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn);
    }
    else
    {
        like_or_eq = eqop;
-       escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, ESCAPE_IN_LITERAL, NULL, conn->ccsc);
-       escTableName = simpleCatalogEscape(szTableName, cbTableName, ESCAPE_IN_LITERAL, NULL, conn->ccsc);
+       escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
    }
+
+retry_public_schema:
+   if (escSchemaName)
+       free(escSchemaName);
+   if (search_pattern) 
+       escSchemaName = adjustLikePattern(szSchemaName, cbSchemaName, SEARCH_PATTERN_ESCAPE, NULL, conn);
+   else
+       escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, NULL, conn);
+   if (conn->schema_support)
+       strncpy_null(proc_query, "select relname, usename, relacl, nspname"
+       " from pg_catalog.pg_namespace, pg_catalog.pg_class ,"
+       " pg_catalog.pg_user where", sizeof(proc_query));
+   else
+       strncpy_null(proc_query, "select relname, usename, relacl"
+       " from pg_class , pg_user where", sizeof(proc_query));
    if (conn->schema_support)
    {
        if (escSchemaName)
@@ -5162,7 +5119,7 @@ retry_public_schema:
    if (conn->schema_support)
    {
        strcat(proc_query, " pg_namespace.oid = relnamespace and relkind in ('r', 'v') and");
-       if ((!szTableName || !cbTableName) && (!szTableOwner || !cbTableOwner))
+       if ((!escTableName) && (!escSchemaName))
            strcat(proc_query, " nspname not in ('pg_catalog', 'information_schema') and");
    }
    strcat(proc_query, " pg_user.usesysid = relowner");
@@ -5358,8 +5315,3 @@ cleanup:
        ret = DiscardStatementSvp(stmt, ret, FALSE);
    return ret;
 }
-
-#ifdef NOT_USED
-select n.nspname, c.relname, a.attname, a.atttypid, t.typname, a.attnotnull from ((pg_class c inner join pg_namespace n on c.oid = %u and c.relnamespace = n.oid) inner join pg_attribute a on a.attrelid = c.oid and a.attnum = %u) inner join pg_type t on t.oid = a.atttypid;
-#endif /* NOT USED */
-
index 7ef6f8a45ee9db4f23891095156404d9604813a3..721758edc7097298799d7143111cfbaec2df150c 100644 (file)
--- a/info30.c
+++ b/info30.c
@@ -385,7 +385,7 @@ PGAPI_GetInfo30(HDBC hdbc, SQLUSMALLINT fInfoType, PTR rgbInfoValue,
        if (rgbInfoValue)
        {
 #ifdef UNICODE_SUPPORT
-           if (conn->unicode)
+           if (CC_is_in_unicode_driver(conn))
            {
                len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / WCLEN);
                len *= WCLEN;
@@ -401,7 +401,7 @@ PGAPI_GetInfo30(HDBC hdbc, SQLUSMALLINT fInfoType, PTR rgbInfoValue,
            }
        }
 #ifdef UNICODE_SUPPORT
-       else if (conn->unicode)
+       else if (CC_is_in_unicode_driver(conn))
            len *= WCLEN;
 #endif /* UNICODE_SUPPORT */
    }
diff --git a/misc.c b/misc.c
index 6ddd95256a6df0b9e5474e9b1d7895178d27e278..4baf4980eb3fd5c96af0369a0f39d54fe7b42a75 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -231,12 +231,12 @@ schema_strcat(char *buf, const char *fmt, const char *s, int len, const char *tb
 void
 remove_newlines(char *string)
 {
-   unsigned int i;
+   unsigned int i, len = strlen(string);
 
-   for (i = 0; i < strlen(string); i++)
+   for (i = 0; i < len; i++)
    {
-       if ((string[i] == '\n') ||
-           (string[i] == '\r'))
+       if ((PG_LINEFEED == string[i]) ||
+           (PG_CARRIAGE_RETURN == string[i]))
            string[i] = ' ';
    }
 }
index fcfc293f97adf6ac8b717377e78c7d0107435a12..9124e4538e4d038a1839e24b889d37db175adffc 100644 (file)
@@ -40,13 +40,10 @@ pg_CS CS_Table[] =
    { "LATIN9", LATIN9 },
    { "LATIN10",    LATIN10 },
    { "WIN1256",    WIN1256 },
-   { "TCVN",   TCVN },
    { "WIN1258",    WIN1258 },  /* since 8.1 */
    { "WIN874", WIN874 },
    { "KOI8",   KOI8R },
-   { "WIN",    WIN },
    { "WIN1251",    WIN1251 },
-   { "ALT",    ALT },
    { "WIN866", WIN866 },   /* since 8.1 */
    { "ISO_8859_5", ISO_8859_5 },
    { "ISO_8859_6", ISO_8859_6 },
@@ -61,40 +58,39 @@ pg_CS CS_Table[] =
    { "WIN1250",    WIN1250 },
    { "GB18030",    GB18030 },
    { "UNICODE",    UNICODE_PODBC },
+   { "TCVN",   TCVN },
+   { "ALT",    ALT },
+   { "WIN",    WIN },
    { "OTHER",  OTHER }
 };
 
-#ifdef NOT_USED
-static int
-pg_ismb(int characterset_code)
-{
-   int i=0,MB_CHARACTERSET[]={EUC_JP,EUC_CN,EUC_KR,EUC_TW,UTF8,MULE_INTERNAL,SJIS,BIG5,GBK,UHC,JOHAB};
-
-   while (MB_CHARACTERSET[i] != characterset_code || OTHER != MB_CHARACTERSET[i] )
-   {
-       i++;
-   }
-   return (MB_CHARACTERSET[i]);
-}
-#endif
 
 int
 pg_CS_code(const UCHAR *characterset_string)
 {
-   int i = 0, c = -1;
+   int i, c = -1;
    unsigned len = 0;
+
    for(i = 0; CS_Table[i].code != OTHER; i++)
    {
-       if (strstr(characterset_string,CS_Table[i].name))
+       if (0 == stricmp(characterset_string, CS_Table[i].name))
        {
-                   if(strlen(CS_Table[i].name) >= len)
-                        {
-                           len = strlen(CS_Table[i].name);
-                           c = CS_Table[i].code;
-                        }
-
+                           c = CS_Table[i].code;
+           break;
        }
    }
+   if (c < 0)
+       for(i = 0; CS_Table[i].code != OTHER; i++)
+       {
+           if (strstr(characterset_string, CS_Table[i].name))
+           {
+                       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);
@@ -402,7 +398,7 @@ const char * get_environment_encoding(const ConnectionClass *conn, const char *o
    const char *wenc = NULL;
 
 #ifdef UNICODE_SUPPORT
-   if (conn->unicode)
+   if (CC_is_in_unicode_driver(conn))
        return "UTF8";
 #endif /* UNICODE_SUPPORT */
 #ifdef WIN32
@@ -513,6 +509,11 @@ int encoded_nextchar(encoded_str *encstr)
    encstr->ccst = pg_CS_stat(encstr->ccst, (unsigned int) chr, encstr->ccsc);
    return chr; 
 }
+int encoded_position_shift(encoded_str *encstr, int shift)
+{
+   encstr->pos += shift; 
+   return encstr->pos; 
+}
 int encoded_byte_check(encoded_str *encstr, int abspos)
 {
    int chr;
index f13decf445aee89dee5f734a0f5b4b63349a1588..c5f0f182dc5e202b4f1b2f5bd24724155da8844c 100644 (file)
@@ -93,6 +93,7 @@ typedef struct
 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_position_shift(encoded_str *encstr, int shift);
 extern int encoded_byte_check(encoded_str *encstr, int abspos);
 #define check_client_encoding(X) pg_CS_name(pg_CS_code(X))
 #endif /* __MULTIBUYTE_H__ */
index 866608aee273fdb06d2710f59703190797befa15..951049e362432888964b53f93f5cdb06b3c3bb1c 100644 (file)
--- a/odbcapi.c
+++ b/odbcapi.c
@@ -889,17 +889,22 @@ SQLTables(HSTMT StatementHandle,
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) StatementHandle;
    SQLCHAR *ctName = CatalogName, *scName = SchemaName, *tbName = TableName;
+   UWORD   flag = 0;
 
    mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
    StartRollbackState(stmt);
+#if (ODBCVER >= 0x0300)
+   if (stmt->options.metadata_id)
+       flag |= PODBC_NOT_SEARCH_PATTERN;
+#endif
    if (SC_opencheck(stmt, func))
        ret = SQL_ERROR;
    else
        ret = PGAPI_Tables(StatementHandle, ctName, NameLength1,
                scName, NameLength2, tbName, NameLength3,
-                       TableType, NameLength4);
+                   TableType, NameLength4, flag);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
@@ -927,7 +932,7 @@ SQLTables(HSTMT StatementHandle,
        {
            ret = PGAPI_Tables(StatementHandle, ctName, NameLength1,
                scName, NameLength2, tbName, NameLength3,
-                       TableType, NameLength4);
+                       TableType, NameLength4, flag);
            if (newCt)
                free(newCt);
            if (newSc)
@@ -1445,16 +1450,22 @@ SQLProcedures(
    StatementClass *stmt = (StatementClass *) hstmt;
    SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
        *prName = szProcName;
+   UWORD   flag = 0;
 
    mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
    StartRollbackState(stmt);
+#if (ODBCVER >= 0x0300)
+   if (stmt->options.metadata_id)
+       flag |= PODBC_NOT_SEARCH_PATTERN;
+#endif
    if (SC_opencheck(stmt, func))
        ret = SQL_ERROR;
    else
        ret = PGAPI_Procedures(hstmt, ctName, cbCatalogName,
-                    scName, cbSchemaName, prName, cbProcName);
+                    scName, cbSchemaName, prName,
+                    cbProcName, flag);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
@@ -1481,7 +1492,7 @@ SQLProcedures(
        if (reexec)
        {
            ret = PGAPI_Procedures(hstmt, ctName, cbCatalogName,
-                    scName, cbSchemaName, prName, cbProcName);
+                    scName, cbSchemaName, prName, cbProcName, flag);
            if (newCt)
                free(newCt);
            if (newSc)
index e0ff398f2223516814dd4d4d7329ce4405af4f07..0228e0ccab7064a7c9a5317dd87092086c5951e3 100644 (file)
@@ -62,7 +62,7 @@ RETCODE  SQL_API SQLSetConnectOptionW(HDBC ConnectionHandle,
 {
    mylog("[SQLSetConnectionOptionW]");
 if (!ConnectionHandle) return SQL_ERROR;
-   ((ConnectionClass *) ConnectionHandle)->unicode = 1;
+   CC_set_in_unicode_driver((ConnectionClass *) ConnectionHandle);
    return PGAPI_SetConnectOption(ConnectionHandle, Option, Value);
 }
 
index ff5a0fef3b6893c790f4a3fc42a4712eb78ef821..4dfa119603abca7d5c32369c6327d4f06f26db38 100644 (file)
@@ -503,6 +503,7 @@ RETCODE  SQL_API SQLTablesW(HSTMT StatementHandle,
    StatementClass *stmt = (StatementClass *) StatementHandle;
    ConnectionClass *conn;
    BOOL lower_id;
+   UWORD   flag = 0;
 
    mylog("[%s]", func);
    conn = SC_get_conn(stmt);
@@ -514,12 +515,16 @@ RETCODE  SQL_API SQLTablesW(HSTMT StatementHandle,
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
    StartRollbackState(stmt);
+#if (ODBCVER >= 0x0300)
+   if (stmt->options.metadata_id)
+       flag |= PODBC_NOT_SEARCH_PATTERN;
+#endif
    if (SC_opencheck(stmt, func))
        ret = SQL_ERROR;
    else
        ret = PGAPI_Tables(StatementHandle, ctName, (SQLSMALLINT) nmlen1,
                    scName, (SQLSMALLINT) nmlen2, tbName, (SQLSMALLINT) nmlen3,
-                   tbType, (SQLSMALLINT) nmlen4);
+                   tbType, (SQLSMALLINT) nmlen4, flag);
    ret = DiscardStatementSvp(stmt, ret, FALSE);
    LEAVE_STMT_CS(stmt);
    if (ctName)
@@ -807,7 +812,8 @@ RETCODE SQL_API SQLProceduresW(
    Int4    nmlen1, nmlen2, nmlen3;
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn;
-   BOOL    lower_id; 
+   BOOL    lower_id;
+   UWORD   flag = 0; 
 
    mylog("[%s]", func);
    conn = SC_get_conn(stmt);
@@ -818,11 +824,16 @@ RETCODE SQL_API SQLProceduresW(
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
    StartRollbackState(stmt);
+#if (ODBCVER >= 0x0300)
+   if (stmt->options.metadata_id)
+       flag |= PODBC_NOT_SEARCH_PATTERN;
+#endif
    if (SC_opencheck(stmt, func))
        ret = SQL_ERROR;
    else
        ret = PGAPI_Procedures(hstmt, ctName, (SQLSMALLINT) nmlen1,
-           scName, (SQLSMALLINT) nmlen2, prName, (SQLSMALLINT) nmlen3);
+                   scName, (SQLSMALLINT) nmlen2, prName,
+                    (SQLSMALLINT) nmlen3, flag);
    ret = DiscardStatementSvp(stmt, ret, FALSE);
    LEAVE_STMT_CS(stmt);
    if (ctName)
index 5146e1163299bd068a13684b996c7521bbebb23a..ace6011c35014beae220ebb1caf00dc7b17b5e21 100644 (file)
--- a/options.c
+++ b/options.c
@@ -458,7 +458,7 @@ PGAPI_SetConnectOption(
                {
                    int cmp;
 #ifdef UNICODE_SUPPORT
-                   if (conn->unicode)
+                   if (CC_is_in_unicode_driver(conn))
                    {
                        char *asPara = ucs2_to_utf8((SQLWCHAR *) vParam, SQL_NTS, NULL, FALSE);
                        cmp = strcmp(asPara, "Microsoft Jet");
diff --git a/parse.c b/parse.c
index d21f28f6aa74ffb702cf2274c4c5b6c877d706b0..30c856d741f5daa14a765f14c2159f383bde16f5 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -41,7 +41,7 @@
 #define TAB_INCR   8
 #define COL_INCR   16
 
-static char    *getNextToken(int ccsc, char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);
+static char    *getNextToken(int ccsc, char escape_in_literal, char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);
 static void    getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
 static char    searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);
 
@@ -69,9 +69,10 @@ Int4 FI_scale(const FIELD_INFO *fi)
    return 0;
 }
 
-char *
+static char *
 getNextToken(
    int ccsc, /* client encoding */
+   char escape_ch,
    char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
 {
    int         i = 0;
@@ -79,7 +80,7 @@ getNextToken(
    char        qc, in_quote, in_dollar_quote, in_escape;
    const   char    *tag, *tagend;
    encoded_str encstr;
-   char    literal_quote = LITERAL_QUOTE, identifier_quote = IDENTIFIER_QUOTE, escape_in_literal = ESCAPE_IN_LITERAL, dollar_quote = '$';
+   char    literal_quote = LITERAL_QUOTE, identifier_quote = IDENTIFIER_QUOTE, dollar_quote = DOLLAR_QUOTE, escape_in_literal;
 
    if (smax <= 1)
        return NULL;
@@ -131,6 +132,7 @@ getNextToken(
                if (tagend = strchr(s + i + 1, dollar_quote))
                    taglen = tagend - s - i + 1;
                i += (taglen - 1);
+               encoded_position_shift(&encstr, taglen - 1);
                if (quote)
                    *quote = TRUE;
            }
@@ -139,6 +141,12 @@ getNextToken(
                in_quote = TRUE;
                if (quote)
                    *quote = TRUE;
+               escape_in_literal = escape_ch;
+               if (!escape_in_literal)
+               {
+                   if (LITERAL_EXT == s[i - 1])
+                       escape_in_literal = ESCAPE_IN_LITERAL;
+               }
            }
            else if (qc == identifier_quote)
            {
@@ -168,12 +176,15 @@ getNextToken(
                    if (strncmp(s + i, tag, taglen) == 0)
                    {
                        i += (taglen - 1);
+                       encoded_position_shift(&encstr, taglen - 1);
                        break;
                    }
                    token[out++] = s[i];
                }
                else if (literal_quote == qc && s[i] == escape_in_literal)
+               {
                    in_escape = TRUE;
+               }
                else
                {
                    token[out++] = s[i];
@@ -454,7 +465,7 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
    stmt->from_pos = -1;
    stmt->where_pos = -1;
 
-   while (pptr = ptr, (ptr = getNextToken(conn->ccsc, pptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL)
+   while (pptr = ptr, (ptr = getNextToken(conn->ccsc, CC_get_escape(conn), pptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL)
    {
        unquoted = !(quote || dquote);
 
index 8c999bcd573f9a2ec86954ef336a64706b7b19e0..ae32368153b6fd336117c5c33ec72713ab677a86 100644 (file)
--- a/pgapi30.c
+++ b/pgapi30.c
@@ -1546,9 +1546,11 @@ PGAPI_GetStmtAttr(HSTMT StatementHandle,
        case SQL_ATTR_METADATA_ID:      /* 10014 */
            *((SQLUINTEGER *) Value) = stmt->options.metadata_id;
            break;
+       case SQL_ATTR_ENABLE_AUTO_IPD:  /* 15 */
+           *((SQLUINTEGER *) Value) = SQL_FALSE;
+           break;
        case SQL_ATTR_AUTO_IPD: /* 10001 */
            /* case SQL_ATTR_ROW_BIND_TYPE: ** == SQL_BIND_TYPE(ODBC2.0) */
-       case SQL_ATTR_ENABLE_AUTO_IPD:  /* 15 */
            SC_set_error(stmt, DESC_INVALID_OPTION_IDENTIFIER, "Unsupported statement option (Get)", func);
            return SQL_ERROR;
        default:
@@ -1598,8 +1600,10 @@ PGAPI_SetConnectAttr(HDBC ConnectionHandle,
            return EnlistInDtc(conn, Value, conn->connInfo.xa_opt); /* telling a lie */
 #endif /* _HANDLE_ENLIST_IN_DTC_ */
 #endif /* WIN32 */
-       case SQL_ATTR_ASYNC_ENABLE:
        case SQL_ATTR_AUTO_IPD:
+           if (SQL_FALSE == Value)
+               break;
+       case SQL_ATTR_ASYNC_ENABLE:
        case SQL_ATTR_CONNECTION_DEAD:
        case SQL_ATTR_CONNECTION_TIMEOUT:
            CC_set_error(conn, CONN_OPTION_NOT_FOR_THE_DRIVER, "Unsupported connect attribute (Set)", func);
@@ -1724,11 +1728,11 @@ PGAPI_SetStmtAttr(HSTMT StatementHandle,
    mylog("%s Handle=%x %d,%u\n", func, StatementHandle, Attribute, Value);
    switch (Attribute)
    {
+       case SQL_ATTR_ENABLE_AUTO_IPD:  /* 15 */
+           if (SQL_FALSE == Value)
+               break;
        case SQL_ATTR_CURSOR_SCROLLABLE:        /* -1 */
        case SQL_ATTR_CURSOR_SENSITIVITY:       /* -2 */
-
-       case SQL_ATTR_ENABLE_AUTO_IPD:  /* 15 */
-
        case SQL_ATTR_AUTO_IPD: /* 10001 */
            SC_set_error(stmt, DESC_OPTION_NOT_FOR_THE_DRIVER, "Unsupported statement option (Set)", func);
            return SQL_ERROR;
index 8341de82528011c1b01396684648eca3e761b226..8c0bc2c18ded2d57f4ea52a30352bc32037e9946 100644 (file)
@@ -148,7 +148,8 @@ RETCODE SQL_API PGAPI_Tables(HSTMT StatementHandle,
             const SQLCHAR *CatalogName, SQLSMALLINT NameLength1,
             const SQLCHAR *SchemaName, SQLSMALLINT NameLength2,
             const SQLCHAR *TableName, SQLSMALLINT NameLength3,
-            const SQLCHAR *TableType, SQLSMALLINT NameLength4);
+            const SQLCHAR *TableType, SQLSMALLINT NameLength4,
+           UWORD flag);
 RETCODE SQL_API PGAPI_Transact(HENV EnvironmentHandle,
               HDBC ConnectionHandle, SQLUSMALLINT CompletionType);
 RETCODE SQL_API PGAPI_ColAttributes(
@@ -241,7 +242,8 @@ RETCODE SQL_API PGAPI_Procedures(
                 const SQLCHAR *szSchemaName,
                 SQLSMALLINT cbSchemaName,
                 const SQLCHAR *szProcName,
-                SQLSMALLINT cbProcName);
+                SQLSMALLINT cbProcName,
+               UWORD flag);
 RETCODE SQL_API PGAPI_SetPos(
             HSTMT hstmt,
             SQLSETPOSIROW irow,
index fbde73aef126ddc17a682828d6857163862b6040..9f3aed64f2c970f955037927fef2d646ff21e30b 100644 (file)
--- a/pgtypes.c
+++ b/pgtypes.c
@@ -258,27 +258,27 @@ pgtype_to_concise_type(StatementClass *stmt, Int4 type, int col)
        case PG_TYPE_CHAR2:
        case PG_TYPE_CHAR4:
        case PG_TYPE_CHAR8:
-           return conn->unicode ? SQL_WCHAR : SQL_CHAR;
+           return ALLOW_WCHAR(conn) ? SQL_WCHAR : SQL_CHAR;
        case PG_TYPE_NAME:
-           return conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR;
+           return ALLOW_WCHAR(conn) ? SQL_WVARCHAR : SQL_VARCHAR;
 
 #ifdef UNICODE_SUPPORT
        case PG_TYPE_BPCHAR:
            if (col >= 0 &&
                getCharColumnSize(stmt, type, col, UNKNOWNS_AS_MAX) > ci->drivers.max_varchar_size)
-               return conn->unicode ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR;
-           return conn->unicode ? SQL_WCHAR : SQL_CHAR;
+               return ALLOW_WCHAR(conn) ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR;
+           return ALLOW_WCHAR(conn) ? SQL_WCHAR : SQL_CHAR;
 
        case PG_TYPE_VARCHAR:
            if (col >= 0 &&
                getCharColumnSize(stmt, type, col, UNKNOWNS_AS_MAX) > ci->drivers.max_varchar_size)
-               return conn->unicode ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR;
-           return conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR;
+               return ALLOW_WCHAR(conn) ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR;
+           return ALLOW_WCHAR(conn) ? 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);
+               (ALLOW_WCHAR(conn) ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR) :
+               (ALLOW_WCHAR(conn) ? SQL_WVARCHAR : SQL_VARCHAR);
 
 #else
        case PG_TYPE_BPCHAR:
@@ -370,7 +370,7 @@ pgtype_to_concise_type(StatementClass *stmt, Int4 type, int col)
                return SQL_LONGVARBINARY;
 
 #ifdef EXPERIMENTAL_CURRENTLY
-           if (conn->unicode)
+           if (ALLOW_WCHAR(conn))
                return ci->drivers.unknowns_as_longvarchar ? SQL_WLONGVARCHAR : SQL_WVARCHAR;
 #endif /* EXPERIMENTAL_CURRENTLY */
            return ci->drivers.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
@@ -491,7 +491,7 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
 
            /* Experimental, Does this work ? */
 #ifdef EXPERIMENTAL_CURRENTLY
-           if (conn->unicode)
+           if (ALLOW_WCHAR(conn))
                return SQL_C_WCHAR;
 #endif /* EXPERIMENTAL_CURRENTLY */
            return SQL_C_CHAR;
@@ -737,7 +737,7 @@ getCharColumnSize(StatementClass *stmt, Int4 type, int col, int handle_unknown_s
        {
            case PG_TYPE_VARCHAR:
            case PG_TYPE_BPCHAR:
-               if (conn->unicode || conn->ms_jet)
+               if (CC_is_in_unicode_driver(conn) || conn->ms_jet)
                    return attlen;
 #if (ODBCVER >= 0x0300)
                return attlen;
@@ -1048,7 +1048,7 @@ pgtype_buffer_length(StatementClass *stmt, Int4 type, int col, int handle_unknow
            if (SQL_NO_TOTAL == prec)
                return prec;
 #ifdef UNICODE_SUPPORT
-           if (conn->unicode)
+           if (CC_is_in_unicode_driver(conn))
                return prec * WCLEN;
 #endif /* UNICODE_SUPPORT */
            /* after 7.2 */
@@ -1129,7 +1129,7 @@ pgtype_transfer_octet_length(StatementClass *stmt, Int4 type, int col, int handl
            if (SQL_NO_TOTAL == prec)
                return prec;
 #ifdef UNICODE_SUPPORT
-           if (conn->unicode)
+           if (CC_is_in_unicode_driver(conn))
                return prec * WCLEN;
 #endif /* UNICODE_SUPPORT */
            /* after 7.2 */
@@ -1491,7 +1491,7 @@ sqltype_to_default_ctype(const ConnectionClass *conn, Int2 sqltype)
        case SQL_WCHAR:
        case SQL_WVARCHAR:
        case SQL_WLONGVARCHAR:
-           if (!conn->unicode)
+           if (!ALLOW_WCHAR(conn))
                return SQL_C_CHAR;
            return SQL_C_WCHAR;
 #endif /* UNICODE_SUPPORT */
index 202ad2cacca6ebcbcf1d518bd1e31918efff725e..34cff7fa644f7c5bc8877db3f7db8891b648572c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: psqlodbc.h,v 1.99 2006/04/14 03:30:01 h-saito Exp $
+ * $Id: psqlodbc.h,v 1.100 2006/04/27 14:49:04 hinoue Exp $
  *
  */
 
@@ -172,6 +172,10 @@ typedef double SDOUBLE;
 #define    SEARCH_PATTERN_ESCAPE               '\\'
 #define    LITERAL_QUOTE                   '\''
 #define    IDENTIFIER_QUOTE                '\"'
+#define    DOLLAR_QUOTE                    '$'
+#define    LITERAL_EXT                 'E'
+#define    PG_CARRIAGE_RETURN              '\r'
+#define    PG_LINEFEED                 '\n'
 
 /* Limits */
 #define BLCKSZ                     4096
@@ -336,8 +340,8 @@ void        logs_on_off(int cnopen, int, int);
 #define PG_TYPE_LO_UNDEFINED           (-999)      /* hack until permanent
                                                 * type available */
 #define PG_TYPE_LO_NAME                "lo"
-#define OID_ATTNUM                 (-2)        /* the attnum in pg_index
-                                                * of the oid */
+#define OID_ATTNUM             (-2)    /* the attnum of oid */
+#define XMIN_ATTNUM                (-3)    /* the attnum of xmin */
 
 /* sizes */
 #define TEXT_FIELD_SIZE                8190        /* size of text fields
index dae1970fe6c1e09a4617d4f2242e1d7329685a89..463d64e7e23aabb0a45dc864d33f82be7f67cba2 100644 (file)
@@ -311,8 +311,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 8,2,0,1
- PRODUCTVERSION 8,2,0,1
+ FILEVERSION PG_DRVFILE_VERSION
+ PRODUCTVERSION PG_DRVFILE_VERSION
  FILEFLAGSMASK 0x3L
 #ifdef _DEBUG
  FILEFLAGS 0x9L
@@ -330,14 +330,14 @@ BEGIN
             VALUE "Comments", "PostgreSQL ODBC driver Japanese\0"
             VALUE "CompanyName", "PostgreSQL Global Development Group\0"
             VALUE "FileDescription", "PostgreSQL ODBC Driver (Japanese)\0"
-            VALUE "FileVersion", "08.02.0001\0"
+            VALUE "FileVersion", POSTGRES_RESOURCE_VERSION
             VALUE "InternalName", "psqlodbc35w\0"
             VALUE "LegalCopyright", "\0"
             VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation.  Microsoft\83\87 is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
             VALUE "OriginalFilename", "psqlodbc35w.dll\0"
             VALUE "PrivateBuild", "for Japanese by Hiroshi Inoue & Hiroshi Saito\0"
             VALUE "ProductName", "PostgreSQL\0"
-            VALUE "ProductVersion", "08.02.0001\0"
+            VALUE "ProductVersion", POSTGRES_RESOURCE_VERSION
             VALUE "SpecialBuild", "\0"
         END
     END
@@ -636,8 +636,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 8,2,0,1
- PRODUCTVERSION 8,2,0,1
+ FILEVERSION PG_DRVFILE_VERSION
+ PRODUCTVERSION PG_DRVFILE_VERSION
  FILEFLAGSMASK 0x3L
 #ifdef _DEBUG
  FILEFLAGS 0x9L
@@ -655,14 +655,14 @@ BEGIN
             VALUE "Comments", "PostgreSQL ODBC driver\0"
             VALUE "CompanyName", "PostgreSQL Global Development Group\0"
             VALUE "FileDescription", "PostgreSQL ODBC Driver (English)\0"
-            VALUE "FileVersion", "08.02.0001\0"
+            VALUE "FileVersion", POSTGRES_RESOURCE_VERSION
             VALUE "InternalName", "psqlodbc35w\0"
             VALUE "LegalCopyright", "Copyright \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", "psqlodbc35w.dll\0"
             VALUE "PrivateBuild", "\0"
             VALUE "ProductName", "PostgreSQL\0"
-            VALUE "ProductVersion", "08.02.0001\0"
+            VALUE "ProductVersion", POSTGRES_RESOURCE_VERSION
             VALUE "SpecialBuild", "\0"
         END
     END
index 3b02a10feef6c328fda945389cbea19d7c5fcd76..c27d670a875fb4c173937594355c07f3a7e52945 100644 (file)
--- a/version.h
+++ b/version.h
@@ -9,8 +9,8 @@
 #ifndef __VERSION_H__
 #define __VERSION_H__
 
-#define POSTGRESDRIVERVERSION      "08.02.0001"
-#define POSTGRES_RESOURCE_VERSION  "08.02.0001\0"
-#define PG_DRVFILE_VERSION     8,2,0,01 
+#define POSTGRESDRIVERVERSION      "08.02.0002"
+#define POSTGRES_RESOURCE_VERSION  "08.02.0002\0"
+#define PG_DRVFILE_VERSION     8,2,0,02 
 
 #endif
index cd510e8fff505ecee8f326ec95fe443160270e9d..d59a2311b4c67ea9dc72f6660b85c7afbef696c7 100644 (file)
@@ -123,11 +123,11 @@ UInt4 utf8_to_ucs2_lf(const char *utf8str, Int4 ilen, BOOL lfconv, SQLWCHAR *ucs
    {
        if (iswascii(*str))
        {
-           if (lfconv && *str == '\n' &&
-               (i == 0 || str[-1] != '\r'))
+           if (lfconv && PG_LINEFEED == *str &&
+               (i == 0 || PG_CARRIAGE_RETURN != str[-1]))
            {
                if (ocount < bufcount)
-                   ucs2str[ocount] = '\r';
+                   ucs2str[ocount] = PG_CARRIAGE_RETURN;
                ocount++;
            }
            if (ocount < bufcount)