Reduce the use of snprintfcat(or SPRINTFCAT_FIXED macro) as much as possible.
authorHiroshi Inoue <h-inoue@dream.email.ne.jp>
Tue, 15 Aug 2017 05:19:08 +0000 (14:19 +0900)
committerHiroshi Inoue <h-inoue@dream.email.ne.jp>
Tue, 15 Aug 2017 05:19:08 +0000 (14:19 +0900)
Instead use PQExpBuffer library without having to worry about buffer length.

configure.ac
connection.c
connection.h
info.c
results.c
winbuild/psqlodbc.vcxproj

index dfd3d405ec11231d6fd11f1a6bd09e17c36b4f37..53b9a4813106da5e9b97c2a52cae1276a77af9c0 100644 (file)
@@ -139,7 +139,7 @@ fi
 if test "$with_libpq" != yes; then
    if test -d "$with_libpq"; then
        PATH="$PATH:$with_libpq/bin"
-       CPPFLAGS="$CPPFLAGS -I$with_libpq/include"
+       CPPFLAGS="$CPPFLAGS -I$with_libpq/include -I$with_libpq/include/postgresql/internal"
        LDFLAGS="$LDFLAGS -L$with_libpq/lib"
    else
        if test -x "$with_libpq"; then
@@ -171,8 +171,9 @@ fi
 
 if test -n "$PG_CONFIG"; then
   pg_includedir=`"$PG_CONFIG" --includedir`
+  pg_pkg_includedir=`"$PG_CONFIG" --pkgincludedir`
   pg_libdir=`"$PG_CONFIG" --libdir`
-  CPPFLAGS="$CPPFLAGS -I$pg_includedir"
+  CPPFLAGS="$CPPFLAGS -I$pg_includedir -I$pg_pkg_includedir/internal"
   LDFLAGS="$LDFLAGS -L$pg_libdir"
 fi
 
index d43bc332da5fcc98a33af50828392c005796dc75..ed115319dacd9c621675b3e30465eab3e066eaf4 100644 (file)
@@ -20,7 +20,6 @@
 #endif /* _WIN32_WINNT */
 
 #include "connection.h"
-#include <libpq-fe.h>
 
 #include "misc.h"
 
@@ -1699,9 +1698,8 @@ CC_send_query_append(ConnectionClass *self, const char *query, QueryInfo *qi, UD
            discard_next_savepoint = FALSE,
            discard_next_release = FALSE,
            consider_rollback;
-   int     func_cs_count = 0, i;
-   size_t      query_buf_len = 0;
-   char       *query_buf = NULL, prepend_cmd[128];
+   int     func_cs_count = 0;
+   PQExpBufferData     query_buf = {0};
    size_t      query_len;
 
    /* QR_set_command() dups this string so doesn't need static */
@@ -1796,70 +1794,41 @@ CC_send_query_append(ConnectionClass *self, const char *query, QueryInfo *qi, UD
    query_len = strlen(query);
    mylog("%s:query_len=%u\n", __FUNCTION__, query_len);
 
-   for (i = 0; i < 2; i++) /* 0:calculate& alloc 1:snprint */
+   initPQExpBuffer(&query_buf);
+   /* issue_begin, query_rollback and prepend_savepoint are exclusive */
+   if (issue_begin)
    {
-       /* issue_begin, query_rollback and prepend_savepoint are exclusive */
-       if (issue_begin)
-       {
-           if (0 == i)
-               query_buf_len += (strlen(bgncmd) + 1);
-           else
-           {
-               snprintfcat(query_buf, query_buf_len, "%s;", bgncmd);
-               discard_next_begin = TRUE;
-           }
-       }
-       else if (query_rollback)
-       {
-           if (0 == i)
-               query_buf_len += (strlen(svpcmd) + 1 + strlen(per_query_svp) + 1);
-           else
-           {
-               snprintfcat(query_buf, query_buf_len, "%s %s;", svpcmd, per_query_svp);
-               discard_next_savepoint = TRUE;
-           }
-       }
-       else if (prepend_savepoint)
-       {
-           if (0 == i)
-               query_buf_len += (GenerateSvpCommand(self, INTERNAL_SAVEPOINT_OPERATION, prepend_cmd, sizeof(prepend_cmd)) + 1);
-           else
-           {
-               snprintfcat(query_buf, query_buf_len, "%s;", prepend_cmd);
-               self->internal_op = SAVEPOINT_IN_PROGRESS;
-           }
-       }
-       if (0 == i)
-           query_buf_len += query_len;
-       else
-           strlcat(query_buf, query, query_buf_len);
-       if (appendq)
-       {
-           if (0 == i)
-               query_buf_len += (1 + strlen(appendq));
-           else
-               snprintfcat(query_buf, query_buf_len, ";%s", appendq);
-       }
-       if (query_rollback)
-       {
-           if (0 == i)
-               query_buf_len += (1 + strlen(rlscmd) + 1 + strlen(per_query_svp));
-           else
-               snprintfcat(query_buf, query_buf_len, ";%s %s", rlscmd, per_query_svp);
-       }
-       if (0 == i)
-       {
-           query_buf_len++;
-           query_buf = malloc(query_buf_len);
-           if (!query_buf)
-           {
-               CC_set_error(self, CONN_NO_MEMORY_ERROR, "Couldn't alloc buffer for query.", "");
-               goto cleanup;
-           }
-           query_buf[0] = '\0';
-       }
+       appendPQExpBuffer(&query_buf, "%s;", bgncmd);
+       discard_next_begin = TRUE;
+   }
+   else if (query_rollback)
+   {
+       appendPQExpBuffer(&query_buf, "%s %s;", svpcmd, per_query_svp);
+       discard_next_savepoint = TRUE;
    }
-inolog("!!!! %s:query_buf=%s(%d)\n", __FUNCTION__, query_buf, query_buf_len);
+   else if (prepend_savepoint)
+   {
+       char    prepend_cmd[128];
+
+       GenerateSvpCommand(self, INTERNAL_SAVEPOINT_OPERATION, prepend_cmd, sizeof(prepend_cmd));
+       appendPQExpBuffer(&query_buf, "%s;", prepend_cmd);
+       self->internal_op = SAVEPOINT_IN_PROGRESS;
+   }
+   appendPQExpBufferStr(&query_buf, query);
+   if (appendq)
+   {
+       appendPQExpBuffer(&query_buf, ";%s", appendq);
+   }
+   if (query_rollback)
+   {
+       appendPQExpBuffer(&query_buf, ";%s %s", rlscmd, per_query_svp);
+   }
+   if (PQExpBufferDataBroken(query_buf))
+   {
+       CC_set_error(self, CONN_NO_MEMORY_ERROR, "Couldn't alloc buffer for query.", "");
+       goto cleanup;
+   }
+mylog("!!!! %s:query_buf=%s(%d)\n", __FUNCTION__, query_buf.data, strlen(query_buf.data));
 
    /* Set up notice receiver */
    nrarg.conn = self;
@@ -1867,7 +1836,7 @@ inolog("!!!! %s:query_buf=%s(%d)\n", __FUNCTION__, query_buf, query_buf_len);
    nrarg.res = NULL;
    PQsetNoticeReceiver(self->pqconn, receive_libpq_notice, &nrarg);
 
-   if (!PQsendQuery(self->pqconn, query_buf))
+   if (!PQsendQuery(self->pqconn, query_buf.data))
    {
        char *errmsg = PQerrorMessage(self->pqconn);
        CC_set_error(self, CONNECTION_COMMUNICATION_ERROR, errmsg, func);
@@ -2172,8 +2141,8 @@ inolog(" !!!! %s:rollback_on_error=%d CC_is_in_trans=%d discard_next_savepoint=%
    if (!ReadyToReturn)
        retres = cmdres;
 
-   if (query_buf)
-       free(query_buf);
+   if (!PQExpBufferDataBroken(query_buf))
+       termPQExpBuffer(&query_buf);
 
    /*
     * Cleanup garbage results before returning.
@@ -2939,41 +2908,70 @@ make_lstring_ifneeded(ConnectionClass *conn, const SQLCHAR *s, ssize_t len, BOOL
  * This is heavily used in creating queries for info routines (SQLTables, SQLColumns).
  * This routine could be modified to use vsprintf() to handle multiple arguments.
  */
-static char *
-my_strcat(char *buf, int buflen, const char *fmt, const char *s, ssize_t len)
+static int
+my_str(char *buf, int buflen, const char *fmt, const char *s, ssize_t len)
 {
    if (s && (len > 0 || (len == SQL_NTS && *s != 0)))
    {
        size_t  length = (len > 0) ? len : strlen(s);
 
-       snprintfcat(buf, buflen, fmt, length, s);
-       return buf;
+       return snprintf(buf, buflen, fmt, length, s);
+   }
+   buf[0] = '\0';
+   return 0;
+}
+
+int
+schema_str(char *buf, int buflen, const SQLCHAR *s, SQLLEN len, BOOL table_is_valid, ConnectionClass *conn)
+{
+   CSTR    fmt = "%.*s";
+
+   buf[0] = '\0';
+   if (!s || 0 == len)
+   {
+       /*
+        * Note that this driver assumes the implicit schema is
+        * the CURRENT_SCHEMA() though it doesn't worth the
+        * naming.
+        */
+       if (table_is_valid)
+           return my_str(buf, buflen, fmt, CC_get_current_schema(conn), SQL_NTS);
+       return 0;
+   }
+   return my_str(buf, buflen, fmt, (char *) s, len);
+}
+
+static void
+my_appendPQExpBuffer(PQExpBufferData *buf, const char *fmt, const char *s, ssize_t len)
+{
+   if (s && (len > 0 || (len == SQL_NTS && *s != 0)))
+   {
+       size_t  length = (len > 0) ? len : strlen(s);
+
+       appendPQExpBuffer(buf, fmt, length, s);
    }
-   return NULL;
 }
 
 /*
- * my_strcat1 is a extension of my_strcat.
- * It can have 1 more parameter than my_strcat.
+ * my_appendPQExpBuffer1 is a extension of my_appendPQExpBuffer.
+ * It can have 1 more parameter than my_aapendPQExpBuffer.
  */
-static char *
-my_strcat1(char *buf, int buflen, const char *fmt, const char *s1, const char *s)
+static void
+my_appendPQExpBuffer1(PQExpBufferData *buf, const char *fmt, const char *s1, const char *s)
 {
    if (s && s[0] != '\0')
    {
        ssize_t length = strlen(s);
 
        if (s1)
-           snprintfcat(buf, buflen, fmt, s1, length, s);
+           appendPQExpBuffer(buf, fmt, s1, length, s);
        else
-           snprintfcat(buf, buflen, fmt, length, s);
-       return buf;
+           appendPQExpBuffer(buf, fmt, length, s);
    }
-   return NULL;
 }
 
-char *
-schema_strcat(char *buf, int buflen, const char *fmt, const SQLCHAR *s, SQLLEN len, const SQLCHAR *tbname, SQLLEN tbnmlen, ConnectionClass *conn)
+void
+schema_appendPQExpBuffer(PQExpBufferData *buf, const char *fmt, const SQLCHAR *s, SQLLEN len, BOOL table_is_valid, ConnectionClass *conn)
 {
    if (!s || 0 == len)
    {
@@ -2982,23 +2980,23 @@ schema_strcat(char *buf, int buflen, const char *fmt, const SQLCHAR *s, SQLLEN l
         * the CURRENT_SCHEMA() though it doesn't worth the
         * naming.
         */
-       if (tbname && (tbnmlen > 0 || tbnmlen == SQL_NTS))
-           return my_strcat(buf, buflen, fmt, CC_get_current_schema(conn), SQL_NTS);
-       return NULL;
+       if (table_is_valid)
+           my_appendPQExpBuffer(buf, fmt, CC_get_current_schema(conn), SQL_NTS);
+       return;
    }
-   return my_strcat(buf, buflen, fmt, (char *) s, len);
+   my_appendPQExpBuffer(buf, fmt, (char *) s, len);
 }
 
-char *
-schema_strcat1(char *buf, int buflen, const char *fmt, const char *s1, const char *s, const SQLCHAR *tbname, int tbnmlen, ConnectionClass *conn)
+void
+schema_appendPQExpBuffer1(PQExpBufferData *buf, const char *fmt, const char *s1, const char *s, BOOL table_is_valid, ConnectionClass *conn)
 {
    if (!s || s[0] == '\0')
    {
-       if (tbname && (tbnmlen > 0 || tbnmlen == SQL_NTS))
-           return my_strcat1(buf, buflen, fmt, s1, CC_get_current_schema(conn));
-       return NULL;
+       if (table_is_valid)
+           my_appendPQExpBuffer1(buf, fmt, s1, CC_get_current_schema(conn));
+       return;
    }
-   return my_strcat1(buf, buflen, fmt, s1, s);
+   my_appendPQExpBuffer1(buf, fmt, s1, s);
 }
 
 #ifdef _HANDLE_ENLIST_IN_DTC_
index e7c7294cdd2fe904618e3c2978ea84d8c8b6c9fe..6e41fe564cd4bdf47d04a4e9a9e2fd1637da1ebe 100644 (file)
@@ -9,6 +9,23 @@
 #ifndef __CONNECTION_H__
 #define __CONNECTION_H__
 
+#ifdef __INCLUDE_POSTGRES_FE_H__ /* currently not defined */
+/*
+ * Unfortunately #including postgres_fe.h causes various trobles.
+ */
+#include "postgres_fe.h"
+#else /* currently */
+#if defined(__GNUC__) || defined(__IBMC__)
+#define PG_PRINTF_ATTRIBUTE gnu_printf
+#define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a)))
+#else
+#define pg_attribute_printf(f,a)
+#endif /* __GNUC__ || __IBMC__ */
+#endif /* __INCLUDE_POSTGRES_FE_H__ */
+
+#include <libpq-fe.h>
+#include "pqexpbuffer.h"
+
 #include "psqlodbc.h"
 #include <time.h>
 
@@ -16,8 +33,6 @@
 #include <string.h>
 #include "descriptor.h"
 
-#include <libpq-fe.h>
-
 #if defined (POSIX_MULTITHREAD_SUPPORT)
 #include <pthread.h>
 #endif
@@ -441,12 +456,20 @@ const     char *CurrCatString(const ConnectionClass *self);
 SQLUINTEGER    CC_get_isolation(ConnectionClass *self);
 
 SQLCHAR    *make_lstring_ifneeded(ConnectionClass *, const SQLCHAR *s, ssize_t len, BOOL);
+
+#define    TABLE_IS_VALID(tbname, tblen)   ((tbname) && (tblen > 0 || SQL_NTS == tblen))
+int    schema_str(char *buf, int buflen, const SQLCHAR *s, SQLLEN len, BOOL table_is_valid, ConnectionClass *conn);
 char   *schema_strcat(char *buf, int buflen, const char *fmt, const SQLCHAR *s, SQLLEN len,
-       const SQLCHAR *, SQLLEN, ConnectionClass *conn);
+       BOOL table_is_valid, ConnectionClass *conn);
 char   *schema_strcat1(char *buf, int buflen, const char *fmt, const char *s1,
                const char *s,
                const SQLCHAR *, int, ConnectionClass *conn);
 
+void   schema_appendPQExpBuffer(PQExpBufferData *buf, const char *fmt, const SQLCHAR *s, SQLLEN len,
+       BOOL table_is_valid, ConnectionClass *conn);
+void   schema_appendPQExpBuffer1(PQExpBufferData *buf, const char *fmt, const char *s1, const char *s,
+               BOOL table_is_valid, ConnectionClass *conn);
+
 void   CC_examine_global_transaction(ConnectionClass *self);
 
 
diff --git a/info.c b/info.c
index 0ddafd4a7f8c878bf9e71678e8b6ee008d834f1e..7e91e1013de4907c4544ab7e2775d010103acd40 100644 (file)
--- a/info.c
+++ b/info.c
@@ -1690,7 +1690,7 @@ PGAPI_Tables(HSTMT hstmt,
    RETCODE     ret = SQL_ERROR, result;
    int     result_cols;
    char        *tableType = NULL;
-   char        tables_query[INFO_INQUIRY_LEN];
+   PQExpBufferData     tables_query = {0};
    char        table_name[MAX_INFO_STRING],
                table_owner[MAX_INFO_STRING],
                relkind_or_hasrules[MAX_INFO_STRING];
@@ -1787,9 +1787,10 @@ retry_public_schema:
    }
    list_some = (list_cat || list_schemas || list_table_types);
 
-   tables_query[0] = '\0';
+   initPQExpBuffer(&tables_query);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
    if (list_cat)
-       STRCPY_FIXED(tables_query, "select NULL, NULL, NULL");
+       appendPQExpBufferStr(&tables_query, "select NULL, NULL, NULL");
    else if (list_table_types)
    {
        /*
@@ -1797,7 +1798,7 @@ retry_public_schema:
         * - 9.3 and newer versions have materialized views
         * - 9.1 and newer versions have foreign tables
         */
-       STRCPY_FIXED(tables_query,
+       appendPQExpBufferStr(&tables_query,
                "select NULL, NULL, relkind from (select 'r' as relkind "
                "union select 'v' "
                "union select 'm' "
@@ -1805,7 +1806,7 @@ retry_public_schema:
    }
    else if (list_schemas)
    {
-       STRCPY_FIXED(tables_query, "select NULL, nspname, NULL"
+       appendPQExpBufferStr(&tables_query, "select NULL, nspname, NULL"
            " from pg_catalog.pg_namespace n where true");
    }
    else
@@ -1815,7 +1816,7 @@ retry_public_schema:
         * Materialized views are added in 9.3, and foreign
         * tables in 9.1.
         */
-       STRCPY_FIXED(tables_query, "select relname, nspname, relkind "
+       appendPQExpBufferStr(&tables_query, "select relname, nspname, relkind "
            "from pg_catalog.pg_class c, pg_catalog.pg_namespace n "
            "where relkind in ('r', 'v', 'm', 'f')");
    }
@@ -1823,9 +1824,9 @@ retry_public_schema:
    op_string = gen_opestr(like_or_eq, conn);
    if (!list_some)
    {
-       schema_strcat1(tables_query, sizeof(tables_query), " and nspname %s'%.*s'", op_string, escSchemaName, szTableName, cbTableName, conn);
+       schema_appendPQExpBuffer1(&tables_query, " and nspname %s'%.*s'", op_string, escSchemaName, TABLE_IS_VALID(szTableName, cbTableName), conn);
        if (IS_VALID_NAME(escTableName))
-           SPRINTFCAT_FIXED(tables_query,
+           appendPQExpBuffer(&tables_query,
                     " and relname %s'%s'", op_string, escTableName);
    }
 
@@ -1911,21 +1912,26 @@ retry_public_schema:
     * tables, then dont filter either.
     */
    if ((list_schemas || !list_some) && !atoi(ci->show_system_tables) && !show_system_tables)
-       STRCAT_FIXED(tables_query, " and nspname not in ('pg_catalog', 'information_schema', 'pg_toast', 'pg_temp_1')");
+       appendPQExpBufferStr(&tables_query, " and nspname not in ('pg_catalog', 'information_schema', 'pg_toast', 'pg_temp_1')");
 
    if (!list_some)
    {
        if (CC_accessible_only(conn))
-           STRCAT_FIXED(tables_query, " and has_table_privilege(c.oid, 'select')");
+           appendPQExpBufferStr(&tables_query, " and has_table_privilege(c.oid, 'select')");
    }
    if (list_schemas)
-       STRCAT_FIXED(tables_query, " order by nspname");
+       appendPQExpBufferStr(&tables_query, " order by nspname");
    else if (list_some)
        ;
    else
-       STRCAT_FIXED(tables_query, " and n.oid = relnamespace order by nspname, relname");
+       appendPQExpBufferStr(&tables_query, " and n.oid = relnamespace order by nspname, relname");
 
-   result = PGAPI_ExecDirect(htbl_stmt, (SQLCHAR *) tables_query, SQL_NTS, PODBC_RDONLY);
+   if (PQExpBufferDataBroken(tables_query))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_Tables()", func);
+       goto cleanup;
+   }
+   result = PGAPI_ExecDirect(htbl_stmt, (SQLCHAR *) tables_query.data, SQL_NTS, PODBC_RDONLY);
    if (!SQL_SUCCEEDED(result))
    {
        SC_full_error_copy(stmt, htbl_stmt, FALSE);
@@ -2119,6 +2125,8 @@ cleanup:
     */
    stmt->status = STMT_FINISHED;
 
+   if (!PQExpBufferDataBroken(tables_query))
+       termPQExpBuffer(&tables_query);
    if (escCatName)
        free(escCatName);
    if (escSchemaName)
@@ -2210,7 +2218,7 @@ PGAPI_Columns(HSTMT hstmt,
    TupleField  *tuple;
    HSTMT       hcol_stmt = NULL;
    StatementClass *col_stmt;
-   char        columns_query[INFO_INQUIRY_LEN];
+   PQExpBufferData     columns_query = {0};
    RETCODE     result;
    char        table_owner[MAX_INFO_STRING],
                table_name[MAX_INFO_STRING],
@@ -2287,12 +2295,14 @@ retry_public_schema:
        else
            escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, conn);
    }
+   initPQExpBuffer(&columns_query);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
    /*
     * Create the query to find out the columns (Note: pre 6.3 did not
     * have the atttypmod field)
     */
    op_string = gen_opestr(like_or_eq, conn);
-   SPRINTF_FIXED(columns_query,
+   printfPQExpBuffer(&columns_query,
        "select n.nspname, c.relname, a.attname, a.atttypid, "
        "t.typname, a.attnum, a.attlen, a.atttypmod, a.attnotnull, "
        "c.relhasrules, c.relkind, c.oid, pg_get_expr(d.adbin, d.adrelid), "
@@ -2301,30 +2311,35 @@ retry_public_schema:
        "from (((pg_catalog.pg_class c "
        "inner join pg_catalog.pg_namespace n on n.oid = c.relnamespace");
    if (search_by_ids)
-       SPRINTFCAT_FIXED(columns_query, " and c.oid = %u", reloid);
+       appendPQExpBuffer(&columns_query, " and c.oid = %u", reloid);
    else
    {
        if (escTableName)
-           SPRINTFCAT_FIXED(columns_query, " and c.relname %s'%s'", op_string, escTableName);
-       schema_strcat1(columns_query, sizeof(columns_query), " and n.nspname %s'%.*s'", op_string, escSchemaName, szTableName, cbTableName, conn);
+           appendPQExpBuffer(&columns_query, " and c.relname %s'%s'", op_string, escTableName);
+       schema_appendPQExpBuffer1(&columns_query, " and n.nspname %s'%.*s'", op_string, escSchemaName, TABLE_IS_VALID(szTableName, cbTableName), conn);
    }
-   STRCAT_FIXED(columns_query, ") inner join pg_catalog.pg_attribute a"
+   appendPQExpBufferStr(&columns_query, ") inner join pg_catalog.pg_attribute a"
        " on (not a.attisdropped)");
    if (0 == attnum && (NULL == escColumnName || like_or_eq != eqop))
-       STRCAT_FIXED(columns_query, " and a.attnum > 0");
+       appendPQExpBufferStr(&columns_query, " and a.attnum > 0");
    if (search_by_ids)
    {
        if (attnum != 0)
-           SPRINTFCAT_FIXED(columns_query, " and a.attnum = %d", attnum);
+           appendPQExpBuffer(&columns_query, " and a.attnum = %d", attnum);
    }
    else if (escColumnName)
-       SPRINTFCAT_FIXED(columns_query, " and a.attname %s'%s'", op_string, escColumnName);
-   STRCAT_FIXED(columns_query,
+       appendPQExpBuffer(&columns_query, " and a.attname %s'%s'", op_string, escColumnName);
+   appendPQExpBufferStr(&columns_query,
        " and a.attrelid = c.oid) inner join pg_catalog.pg_type t"
        " on t.oid = a.atttypid) left outer join pg_attrdef d"
        " on a.atthasdef and d.adrelid = a.attrelid and d.adnum = a.attnum");
-   STRCAT_FIXED(columns_query, " order by n.nspname, c.relname, attnum");
-
+   appendPQExpBufferStr(&columns_query, " order by n.nspname, c.relname, attnum");
+   if (PQExpBufferDataBroken(columns_query))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_Columns()", func);
+       result = SQL_ERROR;
+       goto cleanup;
+   }
    result = PGAPI_AllocStmt(conn, &hcol_stmt, 0);
    if (!SQL_SUCCEEDED(result))
    {
@@ -2336,7 +2351,7 @@ retry_public_schema:
 
    mylog("%s: hcol_stmt = %p, col_stmt = %p\n", func, hcol_stmt, col_stmt);
 
-   result = PGAPI_ExecDirect(hcol_stmt, (SQLCHAR *) columns_query, SQL_NTS, PODBC_RDONLY);
+   result = PGAPI_ExecDirect(hcol_stmt, (SQLCHAR *) columns_query.data, SQL_NTS, PODBC_RDONLY);
    if (!SQL_SUCCEEDED(result))
    {
        SC_full_error_copy(stmt, col_stmt, FALSE);
@@ -2730,6 +2745,8 @@ cleanup:
    SC_set_rowset_start(stmt, -1, FALSE);
    SC_set_current_col(stmt, -1);
 
+   if (!PQExpBufferDataBroken(columns_query))
+       termPQExpBuffer(&columns_query);
    if (escSchemaName)
        free(escSchemaName);
    if (escTableName)
@@ -2762,7 +2779,7 @@ PGAPI_SpecialColumns(HSTMT hstmt,
    QResultClass    *res;
    HSTMT       hcol_stmt = NULL;
    StatementClass *col_stmt;
-   char        columns_query[INFO_INQUIRY_LEN];
+   PQExpBufferData     columns_query = {0};
    char        *escSchemaName = NULL, *escTableName = NULL;
    RETCODE     result = SQL_SUCCESS;
    char        relhasrules[MAX_INFO_STRING], relkind[8], relhasoids[8];
@@ -2798,20 +2815,22 @@ retry_public_schema:
        free(escSchemaName);
    escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, conn);
    eq_string = gen_opestr(eqop, conn);
+   initPQExpBuffer(&columns_query);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
    /*
     * Create the query to find out if this is a view or not...
     */
-   STRCPY_FIXED(columns_query, "select c.relhasrules, c.relkind, c.relhasoids");
-   STRCAT_FIXED(columns_query, " from pg_catalog.pg_namespace u,"
+   appendPQExpBufferStr(&columns_query, "select c.relhasrules, c.relkind, c.relhasoids");
+   appendPQExpBufferStr(&columns_query, " from pg_catalog.pg_namespace u,"
                    " pg_catalog.pg_class c where "
                    "u.oid = c.relnamespace");
 
    /* TableName cannot contain a string search pattern */
    if (escTableName)
-       SPRINTFCAT_FIXED(columns_query,
+       appendPQExpBuffer(&columns_query,
                     " and c.relname %s'%s'", eq_string, escTableName);
    /* SchemaName cannot contain a string search pattern */
-   schema_strcat1(columns_query, sizeof(columns_query), " and u.nspname %s'%.*s'", eq_string, escSchemaName, szTableName, cbTableName, conn);
+   schema_appendPQExpBuffer1(&columns_query, " and u.nspname %s'%.*s'", eq_string, escSchemaName, TABLE_IS_VALID(szTableName, cbTableName), conn);
 
    result = PGAPI_AllocStmt(conn, &hcol_stmt, 0);
    if (!SQL_SUCCEEDED(result))
@@ -2824,7 +2843,13 @@ retry_public_schema:
 
    mylog("%s: hcol_stmt = %p, col_stmt = %p\n", func, hcol_stmt, col_stmt);
 
-   result = PGAPI_ExecDirect(hcol_stmt, (SQLCHAR *) columns_query, SQL_NTS, PODBC_RDONLY);
+   if (PQExpBufferDataBroken(columns_query))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_SpecialColumns()", func);
+       result = SQL_ERROR;
+       goto cleanup;
+   }
+   result = PGAPI_ExecDirect(hcol_stmt, (SQLCHAR *) columns_query.data, SQL_NTS, PODBC_RDONLY);
    if (!SQL_SUCCEEDED(result))
    {
        SC_full_error_copy(stmt, col_stmt, FALSE);
@@ -2968,6 +2993,8 @@ inolog("Add ctid\n");
 
 cleanup:
 #undef return
+   if (!PQExpBufferDataBroken(columns_query))
+       termPQExpBuffer(&columns_query);
    if (escSchemaName)
        free(escSchemaName);
    if (escTableName)
@@ -2999,7 +3026,7 @@ PGAPI_Statistics(HSTMT hstmt,
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn;
    QResultClass    *res;
-   char        index_query[INFO_INQUIRY_LEN];
+   PQExpBufferData     index_query = {0};
    HSTMT       hcol_stmt = NULL, hindx_stmt = NULL;
    RETCODE     ret = SQL_ERROR, result;
    char        *escSchemaName = NULL, *table_name = NULL, *escTableName = NULL;
@@ -3088,7 +3115,7 @@ PGAPI_Statistics(HSTMT hstmt,
    cbSchemaName = cbTableOwner;
 
    table_schemaname[0] = '\0';
-   schema_strcat(table_schemaname, sizeof(table_schemaname), "%.*s", szSchemaName, cbSchemaName, szTableName, cbTableName, conn);
+   schema_str(table_schemaname, sizeof(table_schemaname), szSchemaName, cbSchemaName, TABLE_IS_VALID(szTableName, cbTableName), conn);
 
    /*
     * we need to get a list of the field names first, so we can return
@@ -3191,7 +3218,8 @@ PGAPI_Statistics(HSTMT hstmt,
    escTableName = simpleCatalogEscape((SQLCHAR *) table_name, SQL_NTS, conn);
    eq_string = gen_opestr(eqop, conn);
    escSchemaName = simpleCatalogEscape((SQLCHAR *) table_schemaname, SQL_NTS, conn);
-   SPRINTF_FIXED(index_query, "select c.relname, i.indkey, i.indisunique"
+   initPQExpBuffer(&index_query);
+   printfPQExpBuffer(&index_query, "select c.relname, i.indkey, i.indisunique"
        ", i.indisclustered, a.amname, c.relhasrules, n.nspname"
        ", c.oid, d.relhasoids, %s"
        " from pg_catalog.pg_index i, pg_catalog.pg_class c,"
@@ -3205,10 +3233,15 @@ PGAPI_Statistics(HSTMT hstmt,
        " and c.relam = a.oid order by"
        , PG_VERSION_GE(conn, 8.3) ? "i.indoption" : "0"
        , eq_string, escTableName, eq_string, escSchemaName);
-   STRCAT_FIXED(index_query, " i.indisprimary desc,");
-   STRCAT_FIXED(index_query, " i.indisunique, n.nspname, c.relname");
+   appendPQExpBufferStr(&index_query, " i.indisprimary desc,");
+   appendPQExpBufferStr(&index_query, " i.indisunique, n.nspname, c.relname");
+   if (PQExpBufferDataBroken(index_query))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_Columns()", func);
+       goto cleanup;
+   }
 
-   result = PGAPI_ExecDirect(hindx_stmt, (SQLCHAR *) index_query, SQL_NTS, PODBC_RDONLY);
+   result = PGAPI_ExecDirect(hindx_stmt, (SQLCHAR *) index_query.data, SQL_NTS, PODBC_RDONLY);
    if (!SQL_SUCCEEDED(result))
    {
        /*
@@ -3460,6 +3493,8 @@ cleanup:
    if (hindx_stmt)
        PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
    /* These things should be freed on any error ALSO! */
+   if (!PQExpBufferDataBroken(index_query))
+       termPQExpBuffer(&index_query);
    if (table_name)
        free(table_name);
    if (escTableName)
@@ -3502,9 +3537,7 @@ PGAPI_ColumnPrivileges(HSTMT hstmt,
    RETCODE result = SQL_ERROR;
    char    *escSchemaName = NULL, *escTableName = NULL, *escColumnName = NULL;
    const char  *like_or_eq, *op_string, *eq_string;
-   char    column_query[INFO_INQUIRY_LEN];
-   size_t      cq_len,cq_size;
-   char        *col_query;
+   PQExpBufferData column_query = {0};
    BOOL    search_pattern;
    QResultClass    *res = NULL;
 
@@ -3527,37 +3560,29 @@ PGAPI_ColumnPrivileges(HSTMT hstmt,
        like_or_eq = eqop;
        escColumnName = simpleCatalogEscape(szColumnName, cbColumnName, conn);
    }
-   STRCPY_FIXED(column_query, "select '' as TABLE_CAT, table_schema as TABLE_SCHEM,"
+   initPQExpBuffer(&column_query);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
+   appendPQExpBufferStr(&column_query, "select '' as TABLE_CAT, table_schema as TABLE_SCHEM,"
            " table_name, column_name, grantor, grantee,"
            " privilege_type as PRIVILEGE, is_grantable from"
            " information_schema.column_privileges where true");
-   cq_len = strlen(column_query);
+   /* cq_len = strlen(column_query);
    cq_size = sizeof(column_query);
-   col_query = column_query;
+   col_query = column_query; */
    op_string = gen_opestr(like_or_eq, conn);
    eq_string = gen_opestr(eqop, conn);
    if (escSchemaName)
-   {
-       col_query += cq_len;
-       cq_size -= cq_len;
-       cq_len = snprintf_len(col_query, cq_size,
-           " and table_schem %s'%s'", eq_string, escSchemaName);
-   }
+       appendPQExpBuffer(&column_query, " and table_schem %s'%s'", eq_string, escSchemaName);
    if (escTableName)
-   {
-       col_query += cq_len;
-       cq_size -= cq_len;
-       cq_len += snprintf_len(col_query, cq_size,
-           " and table_name %s'%s'", eq_string, escTableName);
-   }
+       appendPQExpBuffer(&column_query, " and table_name %s'%s'", eq_string, escTableName);
    if (escColumnName)
+       appendPQExpBuffer(&column_query, " and column_name %s'%s'", op_string, escColumnName);
+   if (PQExpBufferDataBroken(column_query))
    {
-       col_query += cq_len;
-       cq_size -= cq_len;
-       cq_len += snprintf_len(col_query, cq_size,
-           " and column_name %s'%s'", op_string, escColumnName);
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_ColumnPriviles()", func);
+       goto cleanup;
    }
-   if (res = CC_send_query(conn, column_query, NULL, READ_ONLY_QUERY, stmt), !QR_command_maybe_successful(res))
+   if (res = CC_send_query(conn, column_query.data, NULL, READ_ONLY_QUERY, stmt), !QR_command_maybe_successful(res))
    {
        SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ColumnPrivileges query error", func);
        goto cleanup;
@@ -3572,12 +3597,15 @@ PGAPI_ColumnPrivileges(HSTMT hstmt,
    /* set up the current tuple pointer for SQLFetch */
    result = SQL_SUCCESS;
 cleanup:
+#undef return
    if (!SQL_SUCCEEDED(result))
        QR_Destructor(res);
    /* set up the current tuple pointer for SQLFetch */
    stmt->status = STMT_FINISHED;
    stmt->currTuple = -1;
    SC_set_rowset_start(stmt, -1, FALSE);
+   if (!PQExpBufferDataBroken(column_query))
+       termPQExpBuffer(&column_query);
    if (escSchemaName)
        free(escSchemaName);
    if (escTableName)
@@ -3612,7 +3640,7 @@ PGAPI_PrimaryKeys(HSTMT hstmt,
    int         seq = 0;
    HSTMT       htbl_stmt = NULL;
    StatementClass *tbl_stmt;
-   char        tables_query[INFO_INQUIRY_LEN];
+   PQExpBufferData     tables_query = {0};
    char        attname[MAX_INFO_STRING];
    SQLLEN      attname_len;
    char        *pktab = NULL, *pktbname;
@@ -3703,7 +3731,7 @@ retry_public_schema:
        if (escSchemaName)
            free(escSchemaName);
        escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, conn);
-       schema_strcat(pkscm, sizeof(pkscm), "%.*s", (SQLCHAR *) escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
+       schema_str(pkscm, sizeof(pkscm), (SQLCHAR *) escSchemaName, SQL_NTS, TABLE_IS_VALID(szTableName, cbTableName), conn);
    }
 
    result = PGAPI_BindCol(htbl_stmt, 1, internal_asis_type,
@@ -3739,6 +3767,7 @@ retry_public_schema:
        goto cleanup;
    }
 
+   initPQExpBuffer(&tables_query);
    qstart = 1;
    if (0 == reloid)
        qend = 2;
@@ -3746,9 +3775,6 @@ retry_public_schema:
        qend = 1;
    for (qno = qstart; qno <= qend; qno++)
    {
-       size_t  qsize, tsize;
-       char    *tbqry;
-
        switch (qno)
        {
            case 1:
@@ -3758,24 +3784,21 @@ retry_public_schema:
                 * possible index columns. Courtesy of Tom Lane - thomas
                 * 2000-03-21
                 */
-               STRCPY_FIXED(tables_query,
+               appendPQExpBufferStr(&tables_query,
                    "select ta.attname, ia.attnum, ic.relname, n.nspname, tc.relname"
                    " from pg_catalog.pg_attribute ta,"
                    " pg_catalog.pg_attribute ia, pg_catalog.pg_class tc,"
                    " pg_catalog.pg_index i, pg_catalog.pg_namespace n"
                    ", pg_catalog.pg_class ic");
-               qsize = strlen(tables_query);
-               tsize = sizeof(tables_query) - qsize;
-               tbqry = tables_query + qsize;
                if (0 == reloid)
-                   snprintf(tbqry, tsize,
+                   appendPQExpBuffer(&tables_query,
                    " where tc.relname %s'%s'"
                    " AND n.nspname %s'%s'"
                    , eq_string, escTableName, eq_string, pkscm);
                else
-                   snprintf(tbqry, tsize, " where tc.oid = %u", reloid);
+                   appendPQExpBuffer(&tables_query, " where tc.oid = %u", reloid);
 
-               STRCAT_FIXED(tables_query,
+               appendPQExpBufferStr(&tables_query,
                    " AND tc.oid = i.indrelid"
                    " AND n.oid = tc.relnamespace"
                    " AND i.indisprimary = 't'"
@@ -3792,7 +3815,7 @@ retry_public_schema:
                /*
                 * Simplified query to search old fashoned primary key
                 */
-               SPRINTF_FIXED(tables_query, "select ta.attname, ia.attnum, ic.relname, n.nspname, NULL"
+               appendPQExpBuffer(&tables_query, "select ta.attname, ia.attnum, ic.relname, n.nspname, NULL"
                    " from pg_catalog.pg_attribute ta,"
                    " pg_catalog.pg_attribute ia, pg_catalog.pg_class ic,"
                    " pg_catalog.pg_index i, pg_catalog.pg_namespace n"
@@ -3808,9 +3831,15 @@ retry_public_schema:
                    " order by ia.attnum", eq_string, escTableName, eq_string, pkscm);
                break;
        }
-       mylog("%s: tables_query='%s'\n", func, tables_query);
+       if (PQExpBufferDataBroken(tables_query))
+       {
+           SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PrimaryKeys()", func);
+           ret = SQL_ERROR;
+           goto cleanup;
+       }
+       mylog("%s: tables_query='%s'\n", func, tables_query.data);
 
-       result = PGAPI_ExecDirect(htbl_stmt, (SQLCHAR *) tables_query, SQL_NTS, PODBC_RDONLY);
+       result = PGAPI_ExecDirect(htbl_stmt, (SQLCHAR *) tables_query.data, SQL_NTS, PODBC_RDONLY);
        if (!SQL_SUCCEEDED(result))
        {
            SC_full_error_copy(stmt, tbl_stmt, FALSE);
@@ -3882,6 +3911,8 @@ cleanup:
    if (htbl_stmt)
        PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
 
+   if (!PQExpBufferDataBroken(tables_query))
+       termPQExpBuffer(&tables_query);
    if (pktab)
        free(pktab);
    if (escSchemaName)
@@ -4024,7 +4055,7 @@ PGAPI_ForeignKeys_old(HSTMT hstmt,
    HSTMT       htbl_stmt = NULL, hpkey_stmt = NULL;
    StatementClass *tbl_stmt;
    RETCODE     ret = SQL_ERROR, result, keyresult;
-   char        tables_query[INFO_INQUIRY_LEN];
+   PQExpBufferData     tables_query = {0};
    char        trig_deferrable[2];
    char        trig_initdeferred[2];
    char        trig_args[1024];
@@ -4134,6 +4165,7 @@ PGAPI_ForeignKeys_old(HSTMT hstmt,
    pkey_alloced = fkey_alloced = FALSE;
 
    eq_string = gen_opestr(eqop, conn);
+   initPQExpBuffer(&tables_query);
    /*
     * Case #2 -- Get the foreign keys in the specified table (fktab) that
     * refer to the primary keys of other table(s).
@@ -4144,9 +4176,9 @@ PGAPI_ForeignKeys_old(HSTMT hstmt,
 
        mylog("%s: entering Foreign Key Case #2", func);
        escFkTableName = simpleCatalogEscape((SQLCHAR *) fk_table_needed, SQL_NTS, conn);
-       schema_strcat(schema_needed, sizeof(schema_needed), "%.*s", szFkTableOwner, cbFkTableOwner, szFkTableName, cbFkTableName, conn);
+       schema_str(schema_needed, sizeof(schema_needed), szFkTableOwner, cbFkTableOwner, TABLE_IS_VALID(szFkTableName, cbFkTableName), conn);
        escSchemaName = simpleCatalogEscape((SQLCHAR *) schema_needed, SQL_NTS, conn);
-       SPRINTF_FIXED(tables_query, "SELECT pt.tgargs, "
+       printfPQExpBuffer(&tables_query, "SELECT    pt.tgargs, "
            "       pt.tgnargs, "
            "       pt.tgdeferrable, "
            "       pt.tginitdeferred, "
@@ -4188,8 +4220,13 @@ PGAPI_ForeignKeys_old(HSTMT hstmt,
            " order by pt.tgconstrname",
            eq_string, escFkTableName, eq_string, escSchemaName);
        free(escSchemaName);
+       if (PQExpBufferDataBroken(tables_query))
+       {
+           SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_ForeignKeys()", func);
+           goto cleanup;
+       }
 
-       result = PGAPI_ExecDirect(htbl_stmt, (SQLCHAR *) tables_query, SQL_NTS, PODBC_RDONLY);
+       result = PGAPI_ExecDirect(htbl_stmt, (SQLCHAR *) tables_query.data, SQL_NTS, PODBC_RDONLY);
 
        if (!SQL_SUCCEEDED(result))
        {
@@ -4472,9 +4509,9 @@ PGAPI_ForeignKeys_old(HSTMT hstmt,
        char    *escSchemaName;
 
        escPkTableName = simpleCatalogEscape((SQLCHAR *) pk_table_needed, SQL_NTS, conn);
-       schema_strcat(schema_needed, sizeof(schema_needed), "%.*s", szPkTableOwner, cbPkTableOwner, szPkTableName, cbPkTableName, conn);
+       schema_str(schema_needed, sizeof(schema_needed), szPkTableOwner, cbPkTableOwner, TABLE_IS_VALID(szPkTableName, cbPkTableName), conn);
        escSchemaName = simpleCatalogEscape((SQLCHAR *) schema_needed, SQL_NTS, conn);
-       SPRINTF_FIXED(tables_query, "SELECT pt.tgargs, "
+       printfPQExpBuffer(&tables_query, "SELECT    pt.tgargs, "
            "   pt.tgnargs, "
            "   pt.tgdeferrable, "
            "   pt.tginitdeferred, "
@@ -4516,8 +4553,13 @@ PGAPI_ForeignKeys_old(HSTMT hstmt,
            " order by pt.tgconstrname",
            eq_string, escPkTableName, eq_string, escSchemaName);
        free(escSchemaName);
+       if (PQExpBufferDataBroken(tables_query))
+       {
+           SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_ForeignKeys()", func);
+           goto cleanup;
+       }
 
-       result = PGAPI_ExecDirect(htbl_stmt, (SQLCHAR *) tables_query, SQL_NTS, PODBC_RDONLY);
+       result = PGAPI_ExecDirect(htbl_stmt, (SQLCHAR *) tables_query.data, SQL_NTS, PODBC_RDONLY);
        if (!SQL_SUCCEEDED(result))
        {
            SC_error_copy(stmt, tbl_stmt, TRUE);
@@ -4764,6 +4806,8 @@ cleanup:
     */
    stmt->status = STMT_FINISHED;
 
+   if (!PQExpBufferDataBroken(tables_query))
+       termPQExpBuffer(&tables_query);
    if (pkey_alloced)
        free(pkey_text);
    if (fkey_alloced)
@@ -4864,7 +4908,7 @@ PGAPI_ProcedureColumns(HSTMT hstmt,
    CSTR func = "PGAPI_ProcedureColumns";
    StatementClass  *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn = SC_get_conn(stmt);
-   char        proc_query[INFO_INQUIRY_LEN];
+   PQExpBufferData     proc_query = {0};
    Int2        result_cols;
    TupleField  *tuple;
    char        *schema_name, *procname;
@@ -4873,7 +4917,7 @@ PGAPI_ProcedureColumns(HSTMT hstmt,
    char        *proargmodes;
    char        *delim = NULL;
    char        *atttypid, *attname, *column_name;
-   QResultClass *res, *tres;
+   QResultClass *res, *tres = NULL;
    SQLLEN      tcount;
    OID         pgtype;
    Int4        paramcount, column_size, i, j;
@@ -4901,12 +4945,14 @@ PGAPI_ProcedureColumns(HSTMT hstmt,
        escProcName = simpleCatalogEscape(szProcName, cbProcName, conn);
    }
    op_string = gen_opestr(like_or_eq, conn);
-   STRCPY_FIXED(proc_query, "select proname, proretset, prorettype, "
+   initPQExpBuffer(&proc_query);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
+   appendPQExpBufferStr(&proc_query, "select proname, proretset, prorettype, "
            "pronargs, proargtypes, nspname, p.oid");
    ret_col = ext_pos = 7;
    poid_pos = 6;
 #ifdef PRORET_COUNT
-   STRCAT_FIXED(proc_query, ", atttypid, attname");
+   appendPQExpBufferStr(&proc_query, ", atttypid, attname");
    attid_pos = ext_pos;
    attname_pos = ext_pos + 1;
    ret_col += 2;
@@ -4914,36 +4960,36 @@ PGAPI_ProcedureColumns(HSTMT hstmt,
 #endif /* PRORET_COUNT */
    if (PG_VERSION_GE(conn, 8.0))
    {
-       STRCAT_FIXED(proc_query, ", proargnames");
+       appendPQExpBufferStr(&proc_query, ", proargnames");
        ret_col++;
    }
    if (PG_VERSION_GE(conn, 8.1))
    {
-       STRCAT_FIXED(proc_query, ", proargmodes, proallargtypes");
+       appendPQExpBufferStr(&proc_query, ", proargmodes, proallargtypes");
        ret_col += 2;
    }
 #ifdef PRORET_COUNT
-   STRCAT_FIXED(proc_query, " from ((pg_catalog.pg_namespace n inner join"
+   appendPQExpBufferStr(&proc_query, " from ((pg_catalog.pg_namespace n inner join"
               " pg_catalog.pg_proc p on p.pronamespace = n.oid)"
        " inner join pg_type t on t.oid = p.prorettype)"
        " left outer join pg_attribute a on a.attrelid = t.typrelid "
        " and attnum > 0 and not attisdropped where");
 #else
-   STRCAT_FIXED(proc_query, " from pg_catalog.pg_namespace n,"
+   appendPQExpBufferStr(&proc_query, " from pg_catalog.pg_namespace n,"
               " pg_catalog.pg_proc p where");
               " p.pronamespace = n.oid  and"
               " (not proretset) and");
 #endif /* PRORET_COUNT */
-   SPRINTFCAT_FIXED(proc_query,
+   appendPQExpBuffer(&proc_query,
                 " has_function_privilege(p.oid, 'EXECUTE')");
    if (IS_VALID_NAME(escSchemaName))
-       SPRINTFCAT_FIXED(proc_query,
+       appendPQExpBuffer(&proc_query,
                 " and nspname %s'%s'",
                 op_string, escSchemaName);
    if (escProcName)
-       SPRINTFCAT_FIXED(proc_query,
+       appendPQExpBuffer(&proc_query,
                     " and proname %s'%s'", op_string, escProcName);
-   SPRINTFCAT_FIXED(proc_query,
+   appendPQExpBuffer(&proc_query,
                 " order by nspname, proname, p.oid, attnum");
 
    if (escSchemaName)
@@ -4951,18 +4997,26 @@ PGAPI_ProcedureColumns(HSTMT hstmt,
    if (escProcName)
        free(escProcName);
 
-   tres = CC_send_query(conn, proc_query, NULL, READ_ONLY_QUERY, stmt);
+   if (PQExpBufferDataBroken(proc_query))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_ProcedureColumns()", func);
+       result = SQL_ERROR;
+       goto cleanup;
+   }
+   tres = CC_send_query(conn, proc_query.data, NULL, READ_ONLY_QUERY, stmt);
    if (!QR_command_maybe_successful(tres))
    {
        SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ProcedureColumns query error", func);
        QR_Destructor(tres);
-       return SQL_ERROR;
+       result = SQL_ERROR;
+       goto cleanup;
    }
 
    if (res = QR_Constructor(), !res)
    {
        SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_ProcedureColumns result.", func);
-       return SQL_ERROR;
+       result = SQL_ERROR;
+       goto cleanup;
    }
    SC_set_Result(stmt, res);
 
@@ -5228,7 +5282,12 @@ mylog("atttypid=%s\n", atttypid ? atttypid : "(null)");
            set_tuplefield_string(&tuple[PROCOLS_IS_NULLABLE], NULL_STRING);
        }
    }
-   QR_Destructor(tres);
+cleanup:
+#undef return
+   if (tres)
+       QR_Destructor(tres);
+   if (!PQExpBufferDataBroken(proc_query))
+       termPQExpBuffer(&proc_query);
    /*
     * also, things need to think that this statement is finished so the
     * results can be retrieved.
@@ -5239,7 +5298,7 @@ mylog("atttypid=%s\n", atttypid ? atttypid : "(null)");
    SC_set_rowset_start(stmt, -1, FALSE);
    SC_set_current_col(stmt, -1);
 
-   return SQL_SUCCESS;
+   return result;
 }
 
 
@@ -5256,7 +5315,7 @@ PGAPI_Procedures(HSTMT hstmt,
    CSTR func = "PGAPI_Procedures";
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn = SC_get_conn(stmt);
-   char        proc_query[INFO_INQUIRY_LEN];
+   PQExpBufferData     proc_query = {0};
    char    *escSchemaName = NULL, *escProcName = NULL;
    QResultClass *res;
    RETCODE     result;
@@ -5285,7 +5344,9 @@ PGAPI_Procedures(HSTMT hstmt,
     * The following seems the simplest implementation
     */
    op_string = gen_opestr(like_or_eq, conn);
-   STRCPY_FIXED(proc_query, "select '' as " "PROCEDURE_CAT" ", nspname as " "PROCEDURE_SCHEM" ","
+   initPQExpBuffer(&proc_query);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
+   appendPQExpBufferStr(&proc_query, "select '' as " "PROCEDURE_CAT" ", nspname as " "PROCEDURE_SCHEM" ","
    " proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" ","
       " '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" ","
       " '' as " "REMARKS" ","
@@ -5293,21 +5354,24 @@ PGAPI_Procedures(HSTMT hstmt,
       " as "         "PROCEDURE_TYPE" " from pg_catalog.pg_namespace,"
       " pg_catalog.pg_proc"
      " where pg_proc.pronamespace = pg_namespace.oid");
-   schema_strcat1(proc_query, sizeof(proc_query), " and nspname %s'%.*s'", op_string, escSchemaName, szProcName, cbProcName, conn);
+   schema_appendPQExpBuffer1(&proc_query, " and nspname %s'%.*s'", op_string, escSchemaName, TABLE_IS_VALID(szProcName, cbProcName), conn);
    if (IS_VALID_NAME(escProcName))
-       SPRINTFCAT_FIXED(proc_query,
+       appendPQExpBuffer(&proc_query,
                 " and proname %s'%s'", op_string, escProcName);
 
-   res = CC_send_query(conn, proc_query, NULL, READ_ONLY_QUERY, stmt);
+   if (PQExpBufferDataBroken(proc_query))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_Procedures()", func);
+       result = SQL_ERROR;
+       goto cleanup;
+   }
+   res = CC_send_query(conn, proc_query.data, NULL, READ_ONLY_QUERY, stmt);
    if (!QR_command_maybe_successful(res))
    {
        SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_Procedures query error", func);
        QR_Destructor(res);
-       if (escSchemaName)
-           free(escSchemaName);
-       if (escProcName)
-           free(escProcName);
-       return SQL_ERROR;
+       result = SQL_ERROR;
+       goto cleanup;
    }
    SC_set_Result(stmt, res);
 
@@ -5315,18 +5379,22 @@ PGAPI_Procedures(HSTMT hstmt,
     * also, things need to think that this statement is finished so the
     * results can be retrieved.
     */
+cleanup:
+#undef return
    stmt->status = STMT_FINISHED;
    extend_column_bindings(SC_get_ARDF(stmt), 8);
    if (escSchemaName)
        free(escSchemaName);
    if (escProcName)
        free(escProcName);
+   if (!PQExpBufferDataBroken(proc_query))
+       termPQExpBuffer(&proc_query);
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    SC_set_rowset_start(stmt, -1, FALSE);
    SC_set_current_col(stmt, -1);
 
-   return SQL_SUCCESS;
+   return result;
 }
 
 
@@ -5390,7 +5458,7 @@ PGAPI_TablePrivileges(HSTMT hstmt,
    CSTR func = "PGAPI_TablePrivileges";
    ConnectionClass *conn = SC_get_conn(stmt);
    Int2        result_cols;
-   char        proc_query[INFO_INQUIRY_LEN];
+   PQExpBufferData     proc_query = {0};
    QResultClass    *res, *wres = NULL, *allures = NULL;
    TupleField  *tuple;
    Int4        tablecount, usercount, i, j, k;
@@ -5467,20 +5535,27 @@ retry_public_schema:
        escSchemaName = simpleCatalogEscape(szSchemaName, cbSchemaName, conn);
 
    op_string = gen_opestr(like_or_eq, conn);
-   STRCPY_FIXED(proc_query, "select relname, usename, relacl, nspname"
+   initPQExpBuffer(&proc_query);
+   appendPQExpBufferStr(&proc_query, "select relname, usename, relacl, nspname"
    " from pg_catalog.pg_namespace, pg_catalog.pg_class ,"
    " pg_catalog.pg_user where");
    if (escSchemaName)
-       schema_strcat1(proc_query, sizeof(proc_query), " nspname %s'%.*s' and", op_string, escSchemaName, szTableName, cbTableName, conn);
+       schema_appendPQExpBuffer1(&proc_query, " nspname %s'%.*s' and", op_string, escSchemaName, TABLE_IS_VALID(szTableName, cbTableName), conn);
 
    if (escTableName)
-       SPRINTFCAT_FIXED(proc_query, " relname %s'%s' and", op_string, escTableName);
-   STRCAT_FIXED(proc_query, " pg_namespace.oid = relnamespace and relkind in ('r', 'v') and");
+       appendPQExpBuffer(&proc_query, " relname %s'%s' and", op_string, escTableName);
+   appendPQExpBufferStr(&proc_query, " pg_namespace.oid = relnamespace and relkind in ('r', 'v') and");
    if ((!escTableName) && (!escSchemaName))
-       STRCAT_FIXED(proc_query, " nspname not in ('pg_catalog', 'information_schema') and");
+       appendPQExpBufferStr(&proc_query, " nspname not in ('pg_catalog', 'information_schema') and");
 
-   STRCAT_FIXED(proc_query, " pg_user.usesysid = relowner");
-   if (wres = CC_send_query(conn, proc_query, NULL, READ_ONLY_QUERY, stmt), !QR_command_maybe_successful(wres))
+   appendPQExpBufferStr(&proc_query, " pg_user.usesysid = relowner");
+   if (PQExpBufferDataBroken(proc_query))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_TablePrivileges()", func);
+       result = SQL_ERROR;
+       goto cleanup;
+   }
+   if (wres = CC_send_query(conn, proc_query.data, NULL, READ_ONLY_QUERY, stmt), !QR_command_maybe_successful(wres))
    {
        SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_TablePrivileges query error", func);
        ret = SQL_ERROR;
@@ -5501,8 +5576,15 @@ retry_public_schema:
        }
    }
 
-   STRCPY_FIXED(proc_query, "select usename, usesysid, usesuper from pg_user");
-   if (allures = CC_send_query(conn, proc_query, NULL, READ_ONLY_QUERY, stmt), !QR_command_maybe_successful(allures))
+   resetPQExpBuffer(&proc_query);
+   appendPQExpBufferStr(&proc_query, "select usename, usesysid, usesuper from pg_user");
+   if (PQExpBufferDataBroken(proc_query))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_TablePrivileges()", func);
+       ret = SQL_ERROR;
+       goto cleanup;
+   }
+   if (allures = CC_send_query(conn, proc_query.data, NULL, READ_ONLY_QUERY, stmt), !QR_command_maybe_successful(allures))
    {
        SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_TablePrivileges query error", func);
        ret = SQL_ERROR;
@@ -5554,8 +5636,15 @@ retry_public_schema:
                int     i;
                char    *grolist, *uid, *delm;
 
-               SPRINTF_FIXED(proc_query, "select grolist from pg_group where groname = '%s'", user);
-               if (gres = CC_send_query(conn, proc_query, NULL, READ_ONLY_QUERY, stmt), !QR_command_maybe_successful(gres))
+               resetPQExpBuffer(&proc_query);
+               appendPQExpBuffer(&proc_query, "select grolist from pg_group where groname = '%s'", user);
+               if (PQExpBufferDataBroken(proc_query))
+               {
+                   SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_TablePrivileges()", func);
+                   ret = SQL_ERROR;
+                   goto cleanup;
+               }
+               if (gres = CC_send_query(conn, proc_query.data, NULL, READ_ONLY_QUERY, stmt), !QR_command_maybe_successful(gres))
                {
                    grolist = QR_get_value_backend_text(gres, 0, 0);
                    if (grolist && grolist[0] == '{')
@@ -5654,6 +5743,8 @@ cleanup:
        free(escTableName);
    if (useracl)
        free(useracl);
+   if (!PQExpBufferDataBroken(proc_query))
+       termPQExpBuffer(&proc_query);
    if (wres)
        QR_Destructor(wres);
    if (allures)
@@ -5681,7 +5772,7 @@ PGAPI_ForeignKeys_new(HSTMT hstmt,
    StatementClass  *stmt = (StatementClass *) hstmt;
    QResultClass    *res = NULL;
    RETCODE     ret = SQL_ERROR, result;
-   char        tables_query[INFO_INQUIRY_LEN];
+   PQExpBufferData     tables_query = {0};
    char        *pk_table_needed = NULL, *escTableName = NULL;
    char        *fk_table_needed = NULL;
    char        schema_needed[SCHEMA_NAME_STORAGE_LEN + 1];
@@ -5715,7 +5806,7 @@ PGAPI_ForeignKeys_new(HSTMT hstmt,
    {
        mylog("%s: entering Foreign Key Case #2", func);
        escTableName = simpleCatalogEscape((SQLCHAR *) fk_table_needed, SQL_NTS, conn);
-       schema_strcat(schema_needed, sizeof(schema_needed), "%.*s", szFkTableOwner, cbFkTableOwner, szFkTableName, cbFkTableName, conn);
+       schema_str(schema_needed, sizeof(schema_needed), szFkTableOwner, cbFkTableOwner, TABLE_IS_VALID(szFkTableName, cbFkTableName), conn);
        relqual = "\n   and  conrelid = c.oid";
    }
    /*
@@ -5726,7 +5817,7 @@ PGAPI_ForeignKeys_new(HSTMT hstmt,
    else if (NULL != pk_table_needed)
    {
        escTableName = simpleCatalogEscape((SQLCHAR *) pk_table_needed, SQL_NTS, conn);
-       schema_strcat(schema_needed, sizeof(schema_needed), "%.*s", szPkTableOwner, cbPkTableOwner, szPkTableName, cbPkTableName, conn);
+       schema_str(schema_needed, sizeof(schema_needed), szPkTableOwner, cbPkTableOwner, TABLE_IS_VALID(szPkTableName, cbPkTableName), conn);
        relqual = "\n   and  confrelid = c.oid";
    }
    else
@@ -5743,7 +5834,9 @@ PGAPI_ForeignKeys_new(HSTMT hstmt,
    STRCPY_FIXED(scmName2, "n1.nspname");
    escSchemaName = simpleCatalogEscape((SQLCHAR *) schema_needed, SQL_NTS, conn);
 
-   SPRINTF_FIXED(tables_query,
+   initPQExpBuffer(&tables_query);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
+   printfPQExpBuffer(&tables_query,
        "select"
        "   %s as PKTABLE_CAT"
        ",\n    %s as PKTABLE_SCHEM"
@@ -5836,13 +5929,18 @@ PGAPI_ForeignKeys_new(HSTMT hstmt,
    {
        free(escTableName);
        escTableName = simpleCatalogEscape((SQLCHAR *) pk_table_needed, SQL_NTS, conn);
-       SPRINTFCAT_FIXED(tables_query,
+       appendPQExpBuffer(&tables_query,
                "\n where c2.relname %s'%s'",
                eq_string, escTableName);
    }
-   STRCAT_FIXED(tables_query, "\n  order by ref.oid, ref.i");
+   appendPQExpBufferStr(&tables_query, "\n  order by ref.oid, ref.i");
 
-   if (res = CC_send_query(conn, tables_query, NULL, READ_ONLY_QUERY, stmt), !QR_command_maybe_successful(res))
+   if (PQExpBufferDataBroken(tables_query))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_SpecialColumns()", func);
+       goto cleanup;
+   }
+   if (res = CC_send_query(conn, tables_query.data, NULL, READ_ONLY_QUERY, stmt), !QR_command_maybe_successful(res))
    {
        SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ForeignKeys query error", func);
        QR_Destructor(res);
@@ -5869,6 +5967,8 @@ cleanup:
        free(escTableName);
    if (fk_table_needed)
        free(fk_table_needed);
+   if (!PQExpBufferDataBroken(tables_query))
+       termPQExpBuffer(&tables_query);
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    SC_set_rowset_start(stmt, -1, FALSE);
index 82d8a5b658b946057e48a4bfad2314aab9ea2020..0bbc664942f19d21cf7395cdd0a252c43abeb247 100644 (file)
--- a/results.c
+++ b/results.c
@@ -2195,26 +2195,35 @@ ti_quote(StatementClass *stmt, OID tableoid, char *buf, int buf_size)
 
 static BOOL    tupleExists(StatementClass *stmt, const KeySet *keyset)
 {
-   char    selstr[256];
+   PQExpBufferData selstr = {0};
    const TABLE_INFO    *ti = stmt->ti[0];
    QResultClass    *res;
    RETCODE     ret = FALSE;
    const char *bestqual = GET_NAME(ti->bestqual);
    char table_fqn[256];
 
-   SPRINTF_FIXED(selstr,
+   initPQExpBuffer(&selstr);
+   printfPQExpBuffer(&selstr,
             "select 1 from %s where ctid = '(%u,%u)'",
             ti_quote(stmt, keyset->oid, table_fqn, sizeof(table_fqn)),
             keyset->blocknum, keyset->offset);
    if (NULL != bestqual && 0 != keyset->oid && !TI_has_subclass(ti))
    {
-       SPRINTFCAT_FIXED(selstr, " and ");
-       SPRINTFCAT_FIXED(selstr, bestqual, keyset->oid);
+       appendPQExpBuffer(&selstr, " and ");
+       appendPQExpBuffer(&selstr, bestqual, keyset->oid);
    }
-   res = CC_send_query(SC_get_conn(stmt), selstr, NULL, READ_ONLY_QUERY, NULL);
+   if (PQExpBufferDataBroken(selstr))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in tupleExists()", __FUNCTION__);
+       goto cleanup;
+   }
+   res = CC_send_query(SC_get_conn(stmt), selstr.data, NULL, READ_ONLY_QUERY, NULL);
    if (QR_command_maybe_successful(res) && 1 == res->num_cached_rows)
        ret = TRUE;
    QR_Destructor(res);
+cleanup:
+   if (!PQExpBufferDataBroken(selstr))
+       termPQExpBuffer(&selstr);
    return ret;
 }
 
@@ -3002,38 +3011,17 @@ static QResultClass *
 positioned_load(StatementClass *stmt, UInt4 flag, const UInt4 *oidint, const char *tidval)
 {
    CSTR    func = "positioned_load";
-   CSTR    andqual = " and ";
    QResultClass *qres = NULL;
-   char    *selstr, oideqstr[256];
+   PQExpBufferData selstr = {0};
    BOOL    latest = ((flag & LATEST_TUPLE_LOAD) != 0);
-   size_t  len;
    TABLE_INFO  *ti = stmt->ti[0];
    const char *bestqual = GET_NAME(ti->bestqual);
    const ssize_t   from_pos = stmt->load_from_pos;
    const char *load_stmt = stmt->load_statement;
 
 inolog("%s bestitem=%s bestqual=%s\n", func, SAFE_NAME(ti->bestitem), SAFE_NAME(ti->bestqual));
-   if (!bestqual || !oidint)
-       *oideqstr = '\0';
-   else
-   {
-       STRCPY_FIXED(oideqstr, andqual);
-       SPRINTFCAT_FIXED(oideqstr, bestqual, *oidint);
-   }
-   len = strlen(load_stmt);
-   len += strlen(oideqstr);
-   if (tidval)
-       len += 100;
-   else if ((flag & USE_INSERTED_TID) != 0)
-       len += 50;
-   else
-       len += 20;
-   selstr = malloc(len);
-   if (!selstr)
-   {
-       SC_set_error(stmt,STMT_NO_MEMORY_ERROR, "Could not allocate memory for query", func);
-       goto cleanup;
-   }
+   initPQExpBuffer(&selstr);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
    if (TI_has_subclass(ti))
    {
        OID tableoid = *oidint;
@@ -3045,7 +3033,7 @@ inolog("%s bestitem=%s bestqual=%s\n", func, SAFE_NAME(ti->bestitem), SAFE_NAME(
        {
            if (latest)
            {
-               snprintf(selstr, len,
+               printfPQExpBuffer(&selstr,
                     "%.*sfrom %s where ctid = currtid2('%s', '%s')",
                     (int) from_pos, load_stmt,
                     quoted_table,
@@ -3053,10 +3041,10 @@ inolog("%s bestitem=%s bestqual=%s\n", func, SAFE_NAME(ti->bestitem), SAFE_NAME(
                     tidval);
            }
            else
-               snprintf(selstr, len, "%.*sfrom %s where ctid = '%s'", (int) from_pos, load_stmt, quoted_table, tidval);
+               printfPQExpBuffer(&selstr, "%.*sfrom %s where ctid = '%s'", (int) from_pos, load_stmt, quoted_table, tidval);
        }
        else if ((flag & USE_INSERTED_TID) != 0)
-           snprintf(selstr, len, "%.*sfrom %s where ctid = currtid(0, '(0,0)')", (int) from_pos, load_stmt, quoted_table);
+           printfPQExpBuffer(&selstr, "%.*sfrom %s where ctid = currtid(0, '(0,0)')", (int) from_pos, load_stmt, quoted_table);
        /*
        else if (bestitem && oidint)
        {
@@ -3070,39 +3058,55 @@ inolog("%s bestitem=%s bestqual=%s\n", func, SAFE_NAME(ti->bestitem), SAFE_NAME(
    }
    else
    {
+       CSTR    andqual = " and ";
+       BOOL    andExist = TRUE;
+
        if (tidval)
        {
            if (latest)
            {
                char table_fqn[256];
 
-               snprintf(selstr, len,
-                    "%s where ctid = currtid2('%s', '%s') %s",
+               printfPQExpBuffer(&selstr,
+                    "%s where ctid = currtid2('%s', '%s')",
                     load_stmt,
                     ti_quote(stmt, 0, table_fqn, sizeof(table_fqn)),
-                    tidval, oideqstr);
+                    tidval);
            }
            else
-               snprintf(selstr, len, "%s where ctid = '%s' %s", load_stmt, tidval, oideqstr);
+               printfPQExpBuffer(&selstr, "%s where ctid = '%s'", load_stmt, tidval);
        }
        else if ((flag & USE_INSERTED_TID) != 0)
-           snprintf(selstr, len, "%s where ctid = currtid(0, '(0,0)') %s", load_stmt, oideqstr);
-       else if (bestqual && oidint)
+           printfPQExpBuffer(&selstr, "%s where ctid = currtid(0, '(0,0)')", load_stmt);
+       else if (bestqual)
        {
-           snprintf(selstr, len, "%s where ", load_stmt);
-           snprintfcat(selstr, len, bestqual, *oidint);
+           andExist = FALSE;
+           printfPQExpBuffer(&selstr, "%s where ", load_stmt);
        }
        else
        {
            SC_set_error(stmt,STMT_INTERNAL_ERROR, "can't find the add and updating row because of the lack of oid", func);
            goto cleanup;
        }
+       if (bestqual && oidint)
+       {
+           if (andExist)
+               appendPQExpBufferStr(&selstr, andqual);
+           appendPQExpBuffer(&selstr, bestqual, *oidint);
+       }
    }
 
-   mylog("selstr=%s\n", selstr);
-   qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, READ_ONLY_QUERY, stmt);
+   if (PQExpBufferDataBroken(selstr))
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Could not allocate memory positioned_load()", func);
+       goto cleanup;
+   }
+   mylog("selstr=%s\n", selstr.data);
+   qres = CC_send_query(SC_get_conn(stmt), selstr.data, NULL, READ_ONLY_QUERY, stmt);
 cleanup:
-   free(selstr);
+#undef return
+   if (!PQExpBufferDataBroken(selstr))
+       termPQExpBuffer(&selstr);
    return qres;
 }
 
@@ -3293,10 +3297,10 @@ static SQLLEN LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_
    UInt4   blocknum;
    SQLLEN  kres_ridx;
    UInt2   offset;
-   char    *qval = NULL;
+   PQExpBufferData qval = {0};
    int keys_per_fetch = 10;
-   size_t  allen = 0;
 
+#define    return  DONT_CALL_RETURN_FROM_HERE???
    for (i = SC_get_rowset_start(stmt), kres_ridx = GIdx2KResIdx(i, stmt, res), rowc = 0;; i++, kres_ridx++)
    {
        if (i >= limitrow)
@@ -3307,7 +3311,7 @@ static SQLLEN LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_
            {
                for (j = rowc; j < keys_per_fetch; j++)
                {
-                   strlcat(qval, j ? ",NULL" : "NULL", allen);
+                   appendPQExpBufferStr(&qval, j ? ",NULL" : "NULL");
                }
            }
            rowc = -1; /* end of loop */
@@ -3316,8 +3320,14 @@ static SQLLEN LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_
        {
            QResultClass    *qres;
 
-           strlcat(qval, ")", allen);
-           qres = CC_send_query(conn, qval, NULL, CREATE_KEYSET | READ_ONLY_QUERY, stmt);
+           appendPQExpBufferStr(&qval, ")");
+           if (PQExpBufferDataBroken(qval))
+           {
+               rcnt = -1;
+               SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in LoadFromKeyset()", func);
+               goto cleanup;
+           }
+           qres = CC_send_query(conn, qval.data, NULL, CREATE_KEYSET | READ_ONLY_QUERY, stmt);
            if (QR_command_maybe_successful(qres))
            {
                SQLLEN      j, k, l;
@@ -3369,10 +3379,9 @@ static SQLLEN LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_
        }
        if (!rowc)
        {
-           size_t lodlen = 0;
-
-           if (!qval)
+           if (PQExpBufferDataBroken(qval))
            {
+               initPQExpBuffer(&qval);
 
                if (res->reload_count > 0)
                    keys_per_fetch = res->reload_count;
@@ -3388,29 +3397,28 @@ static SQLLEN LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_
                        keys_per_fetch = rows_per_fetch;
                    if (!keys_per_fetch)
                        keys_per_fetch = 2;
-                   lodlen = strlen(stmt->load_statement);
                    SPRINTF_FIXED(planname, "_KEYSET_%p", res);
-                   allen = 8 + strlen(planname) +
-                       3 + 4 * keys_per_fetch + 1
-                       + 1 + 2 + lodlen + 20 +
-                       4 * keys_per_fetch + 1;
-                   SC_MALLOC_return_with_error(qval, char, allen,
-                       stmt, "Couldn't alloc qval", -1);
-                   snprintf(qval, allen, "PREPARE \"%s\"", planname);
+                   printfPQExpBuffer(&qval, "PREPARE \"%s\"", planname);
                    for (j = 0; j < keys_per_fetch; j++)
                    {
-                       strlcat(qval, j ? ",tid" : "(tid", allen);
+                       appendPQExpBufferStr(&qval, j ? ",tid" : "(tid");
                    }
-                   snprintfcat(qval, allen, ") as %s where ctid in ", stmt->load_statement);
+                   appendPQExpBuffer(&qval, ") as %s where ctid in ", stmt->load_statement);
                    for (j = 0; j < keys_per_fetch; j++)
                    {
                        if (j == 0)
-                           strlcat(qval, "($1", allen);
+                           appendPQExpBufferStr(&qval, "($1");
                        else
-                           snprintfcat(qval, allen, ",$%d", j + 1);
+                           appendPQExpBuffer(&qval, ",$%d", j + 1);
+                   }
+                   appendPQExpBufferStr(&qval, ")");
+                   if (PQExpBufferDataBroken(qval))
+                   {
+                       rcnt = -1;
+                       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in LoadFromKeyset()", func);
+                       goto cleanup;
                    }
-                   strlcat(qval, ")", allen);
-                   qres = CC_send_query(conn, qval, NULL, READ_ONLY_QUERY, stmt);
+                   qres = CC_send_query(conn, qval.data, NULL, READ_ONLY_QUERY, stmt);
                    if (QR_command_maybe_successful(qres))
                    {
                        res->reload_count = keys_per_fetch;
@@ -3424,33 +3432,31 @@ static SQLLEN LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_
                    }
                    QR_Destructor(qres);
                }
-               allen = 25 + 23 * keys_per_fetch;
-
-               SC_REALLOC_return_with_error(qval, char, allen,
-                   stmt, "Couldn't alloc qval", -1);
            }
            if (res->reload_count > 0)
            {
-               snprintf(qval, allen, "EXECUTE \"_KEYSET_%p\"(", res);
+               printfPQExpBuffer(&qval, "EXECUTE \"_KEYSET_%p\"(", res);
            }
            else
            {
-               snprintf(qval, allen, "%s where ctid in (", stmt->load_statement);
+               printfPQExpBuffer(&qval, "%s where ctid in (", stmt->load_statement);
            }
        }
        if (0 != (res->keyset[kres_ridx].status & CURS_NEEDS_REREAD))
        {
            getTid(res, kres_ridx, &blocknum, &offset);
            if (rowc)
-               snprintfcat(qval, allen, ",'(%u,%u)'", blocknum, offset);
+               appendPQExpBuffer(&qval, ",'(%u,%u)'", blocknum, offset);
            else
-               snprintfcat(qval, allen, "'(%u,%u)'", blocknum, offset);
+               appendPQExpBuffer(&qval, "'(%u,%u)'", blocknum, offset);
            rowc++;
            rcnt++;
        }
    }
-   if (qval)
-       free(qval);
+cleanup:
+#undef return
+   if (!PQExpBufferDataBroken(qval))
+       termPQExpBuffer(&qval);
    return rcnt;
 }
 
@@ -3463,15 +3469,14 @@ static SQLLEN LoadFromKeyset_inh(StatementClass *stmt, QResultClass * res, int r
    UInt4   blocknum;
    SQLLEN  kres_ridx;
    UInt2   offset;
-   char    *qval = NULL;
+   PQExpBufferData qval = {0};
    int keys_per_fetch = 10;
    const char *load_stmt = stmt->load_statement;
    const ssize_t   from_pos = stmt->load_from_pos;
-   const int   max_identifier = 100;
-   size_t  allen = 0;
 
 mylog(" %s in rows_per_fetch=%d limitrow=%d\n", __FUNCTION__, rows_per_fetch, limitrow);
    new_oid = 0;
+#define    return  DONT_CALL_RETURN_FROM_HERE???
    for (i = SC_get_rowset_start(stmt), kres_ridx = GIdx2KResIdx(i, stmt, res), rowc = 0, oid = 0;; i++, kres_ridx++)
    {
        if (i >= limitrow)
@@ -3491,8 +3496,14 @@ mylog(" %s in rows_per_fetch=%d limitrow=%d\n", __FUNCTION__, rows_per_fetch, li
        {
            QResultClass    *qres;
 
-           strlcat(qval, ")", allen);
-           qres = CC_send_query(conn, qval, NULL, CREATE_KEYSET | READ_ONLY_QUERY, stmt);
+           appendPQExpBufferStr(&qval, ")");
+           if (PQExpBufferDataBroken(qval))
+           {
+               rcnt = -1;
+               SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in LoadFromKeyset_inh()", __FUNCTION__);
+               goto cleanup;
+           }
+           qres = CC_send_query(conn, qval.data, NULL, CREATE_KEYSET | READ_ONLY_QUERY, stmt);
            if (QR_command_maybe_successful(qres))
            {
                SQLLEN      k, l;
@@ -3547,7 +3558,7 @@ mylog(" %s in rows_per_fetch=%d limitrow=%d\n", __FUNCTION__, rows_per_fetch, li
        {
            char table_fqn[256];
 
-           if (!qval)
+           if (PQExpBufferDataBroken(qval))
            {
                if (rows_per_fetch >= pre_fetch_count * 2)
                    keys_per_fetch = pre_fetch_count;
@@ -3555,27 +3566,24 @@ mylog(" %s in rows_per_fetch=%d limitrow=%d\n", __FUNCTION__, rows_per_fetch, li
                    keys_per_fetch = rows_per_fetch;
                if (!keys_per_fetch)
                    keys_per_fetch = 2;
-               allen = from_pos + sizeof("from ") +
-                   2 * (2 + max_identifier) + 1 *
-                   + sizeof(" where ctid in ") +
-                   20 * keys_per_fetch + 2;
-               SC_MALLOC_return_with_error(qval, char, allen,
-                   stmt, "Couldn't alloc qval", -1);
+               initPQExpBuffer(&qval);
            }
-           snprintf(qval, allen, "%.*sfrom %s where ctid in (", (int) from_pos, load_stmt, ti_quote(stmt, new_oid, table_fqn, sizeof(table_fqn)));
+           printfPQExpBuffer(&qval, "%.*sfrom %s where ctid in (", (int) from_pos, load_stmt, ti_quote(stmt, new_oid, table_fqn, sizeof(table_fqn)));
        }
        if (new_oid != oid)
            oid = new_oid;
        getTid(res, kres_ridx, &blocknum, &offset);
        if (rowc)
-           snprintfcat(qval, allen, ",'(%u,%u)'", blocknum, offset);
+           appendPQExpBuffer(&qval, ",'(%u,%u)'", blocknum, offset);
        else
-           snprintfcat(qval, allen, "'(%u,%u)'", blocknum, offset);
+           appendPQExpBuffer(&qval, "'(%u,%u)'", blocknum, offset);
        rowc++;
        rcnt++;
    }
-   if (qval)
-       free(qval);
+cleanup:
+#undef return
+   if (!PQExpBufferDataBroken(qval))
+       termPQExpBuffer(&qval);
    return rcnt;
 }
 
@@ -3919,8 +3927,8 @@ SC_pos_update(StatementClass *stmt,
    BindInfoClass *bindings = opts->bindings;
    TABLE_INFO  *ti;
    FIELD_INFO  **fi;
-   char        updstr[4096];
-   RETCODE     ret;
+   PQExpBufferData     updstr = {0};
+   RETCODE     ret = SQL_ERROR;
    OID oid;
    UInt4   blocknum;
    UInt2   pgoffset;
@@ -3982,7 +3990,9 @@ SC_pos_update(StatementClass *stmt,
 
    ti = s.stmt->ti[0];
 
-   SPRINTF_FIXED(updstr,
+   initPQExpBuffer(&updstr);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
+   printfPQExpBuffer(&updstr,
             "update %s set", ti_quote(stmt, oid, table_fqn, sizeof(table_fqn)));
 
    num_cols = s.irdflds->nfields;
@@ -4000,10 +4010,10 @@ SC_pos_update(StatementClass *stmt,
            if (*used != SQL_IGNORE && fi[i]->updatable)
            {
                if (upd_cols)
-                   SPRINTFCAT_FIXED(updstr,
+                   appendPQExpBuffer(&updstr,
                                 ", \"%s\" = ?", GET_NAME(fi[i]->column_name));
                else
-                   SPRINTFCAT_FIXED(updstr,
+                   appendPQExpBuffer(&updstr,
                                 " \"%s\" = ?", GET_NAME(fi[i]->column_name));
                upd_cols++;
            }
@@ -4025,28 +4035,28 @@ SC_pos_update(StatementClass *stmt,
        const char *bestqual = GET_NAME(ti->bestqual);
        int unknown_sizes = ci->drivers.unknown_sizes;
 
-       SPRINTFCAT_FIXED(updstr,
+       appendPQExpBuffer(&updstr,
                     " where ctid = '(%u, %u)'",
                     blocknum, pgoffset);
        if (bestqual)
        {
-           SPRINTFCAT_FIXED(updstr, " and ");
-           SPRINTFCAT_FIXED(updstr, bestqual, oid);
+           appendPQExpBuffer(&updstr, " and ");
+           appendPQExpBuffer(&updstr, bestqual, oid);
        }
        if (PG_VERSION_GE(conn, 8.2))
        {
-           SPRINTFCAT_FIXED(updstr, " returning ctid");
+           appendPQExpBuffer(&updstr, " returning ctid");
            if (bestitem)
            {
-               SPRINTFCAT_FIXED(updstr, ", ");
-               SPRINTFCAT_FIXED(updstr, "\"%s\"", bestitem);
+               appendPQExpBuffer(&updstr, ", ");
+               appendPQExpBuffer(&updstr, "\"%s\"", bestitem);
            }
        }
        mylog("updstr=%s\n", updstr);
        if (PGAPI_AllocStmt(conn, &hstmt, 0) != SQL_SUCCESS)
        {
            SC_set_error(s.stmt, STMT_NO_MEMORY_ERROR, "internal AllocStmt error", func);
-           return SQL_ERROR;
+           goto cleanup;
        }
        s.qstmt = (StatementClass *) hstmt;
        apdopts = SC_get_APDF(s.qstmt);
@@ -4085,19 +4095,25 @@ SC_pos_update(StatementClass *stmt,
        }
        s.qstmt->exec_start_row = s.qstmt->exec_end_row = s.irow;
        s.updyes = TRUE;
-       ret = PGAPI_ExecDirect(hstmt, (SQLCHAR *) updstr, SQL_NTS, 0);
+       if (PQExpBufferDataBroken(updstr))
+       {
+           SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in SC_pos_updatet()", func);
+           goto cleanup;
+       }
+       ret = PGAPI_ExecDirect(hstmt, (SQLCHAR *) updstr.data, SQL_NTS, 0);
        if (ret == SQL_NEED_DATA)
        {
            pup_cdata *cbdata = (pup_cdata *) malloc(sizeof(pup_cdata));
            if (!cbdata)
            {
                SC_set_error(s.stmt, STMT_NO_MEMORY_ERROR, "Could not allocate memory for cbdata", func);
-               return SQL_ERROR;
+               ret = SQL_ERROR;
+               goto cleanup;
            }
            memcpy(cbdata, &s, sizeof(pup_cdata));
            if (0 == enqueueNeedDataCallback(s.stmt, pos_update_callback, cbdata))
                ret = SQL_ERROR;
-           return ret;
+           goto cleanup;
        }
        /* else if (ret != SQL_SUCCESS) this is unneccesary
            SC_error_copy(s.stmt, s.qstmt, TRUE); */
@@ -4109,6 +4125,11 @@ SC_pos_update(StatementClass *stmt,
    }
 
    ret = pos_update_callback(ret, &s);
+
+cleanup:
+#undef return
+   if (!PQExpBufferDataBroken(updstr))
+       termPQExpBuffer(&updstr);
    return ret;
 }
 RETCODE
@@ -4120,7 +4141,7 @@ SC_pos_delete(StatementClass *stmt,
    QResultClass *res, *qres;
    ConnectionClass *conn = SC_get_conn(stmt);
    IRDFields   *irdflds = SC_get_IRDF(stmt);
-   char        dltstr[4096];
+   PQExpBufferData     dltstr = {0};
    RETCODE     ret;
    SQLLEN      kres_ridx;
    OID     oid;
@@ -4177,21 +4198,29 @@ SC_pos_delete(StatementClass *stmt,
        blocknum = keyset->blocknum;
        offset = keyset->offset;
    }
-   SPRINTF_FIXED(dltstr,
+   initPQExpBuffer(&dltstr);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
+   printfPQExpBuffer(&dltstr,
             "delete from %s where ctid = '(%u, %u)'",
             ti_quote(stmt, oid, table_fqn, sizeof(table_fqn)), blocknum, offset);
    if (bestqual && !TI_has_subclass(ti))
    {
-       SPRINTFCAT_FIXED(dltstr, " and ");
-       SPRINTFCAT_FIXED(dltstr, bestqual, oid);
+       appendPQExpBuffer(&dltstr, " and ");
+       appendPQExpBuffer(&dltstr, bestqual, oid);
    }
 
-   mylog("dltstr=%s\n", dltstr);
+   if (PQExpBufferDataBroken(dltstr))
+   {
+       ret = SQL_ERROR;
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in SC_pos_delete()", func);
+       goto cleanup;
+   }
+   mylog("dltstr=%s\n", dltstr.data);
    qflag = 0;
         if (stmt->external && !CC_is_in_trans(conn) &&
                  (!CC_does_autocommit(conn)))
        qflag |= GO_INTO_TRANSACTION;
-   qres = CC_send_query(conn, dltstr, NULL, qflag, stmt);
+   qres = CC_send_query(conn, dltstr.data, NULL, qflag, stmt);
    ret = SQL_SUCCESS;
    if (QR_command_maybe_successful(qres))
    {
@@ -4260,6 +4289,11 @@ inolog(".status[%d]=%x\n", global_ridx, res->keyset[kres_ridx].status);
                irdflds->rowStatusArray[irow] = ret;
        }
    }
+
+cleanup:
+#undef return
+   if (!PQExpBufferDataBroken(dltstr))
+       termPQExpBuffer(&dltstr);
    return ret;
 }
 
@@ -4411,7 +4445,7 @@ SC_pos_add(StatementClass *stmt,
    IPDFields   *ipdopts;
    BindInfoClass *bindings = opts->bindings;
    FIELD_INFO  **fi = SC_get_IRDF(stmt)->fi;
-   char        addstr[4096];
+   PQExpBufferData     addstr = {0};
    RETCODE     ret;
    SQLULEN     offset;
    SQLLEN      *used;
@@ -4441,14 +4475,16 @@ SC_pos_add(StatementClass *stmt,
    num_cols = s.irdflds->nfields;
    conn = SC_get_conn(s.stmt);
 
-   SPRINTF_FIXED(addstr,
-            "insert into %s (",
-            ti_quote(s.stmt, 0, table_fqn, sizeof(table_fqn)));
    if (PGAPI_AllocStmt(conn, &hstmt, 0) != SQL_SUCCESS)
    {
        SC_set_error(s.stmt, STMT_NO_MEMORY_ERROR, "internal AllocStmt error", func);
        return SQL_ERROR;
    }
+   initPQExpBuffer(&addstr);
+#define    return  DONT_CALL_RETURN_FROM_HERE???
+   printfPQExpBuffer(&addstr,
+            "insert into %s (",
+            ti_quote(s.stmt, 0, table_fqn, sizeof(table_fqn)));
    if (opts->row_offset_ptr)
        offset = *opts->row_offset_ptr;
    else
@@ -4477,10 +4513,10 @@ SC_pos_add(StatementClass *stmt,
                /* fieldtype = QR_get_field_type(s.res, i); */
                fieldtype = getEffectiveOid(conn, fi[i]);
                if (add_cols)
-                   SPRINTFCAT_FIXED(addstr,
+                   appendPQExpBuffer(&addstr,
                                 ", \"%s\"", GET_NAME(fi[i]->column_name));
                else
-                   SPRINTFCAT_FIXED(addstr,
+                   appendPQExpBuffer(&addstr,
                                 "\"%s\"", GET_NAME(fi[i]->column_name));
                PIC_set_pgtype(ipdopts->parameters[add_cols], fieldtype);
                PGAPI_BindParameter(hstmt,
@@ -4499,35 +4535,40 @@ SC_pos_add(StatementClass *stmt,
            mylog("%d null bind\n", i);
    }
    s.updyes = FALSE;
-#define    return  DONT_CALL_RETURN_FROM_HERE???
    ENTER_INNER_CONN_CS(conn, func_cs_count);
    if (add_cols > 0)
    {
-       SPRINTFCAT_FIXED(addstr, ") values (");
+       appendPQExpBuffer(&addstr, ") values (");
        for (i = 0; i < add_cols; i++)
        {
            if (i)
-               SPRINTFCAT_FIXED(addstr, ", ?");
+               appendPQExpBuffer(&addstr, ", ?");
            else
-               SPRINTFCAT_FIXED(addstr, "?");
+               appendPQExpBuffer(&addstr, "?");
        }
-       SPRINTFCAT_FIXED(addstr, ")");
+       appendPQExpBuffer(&addstr, ")");
        if (PG_VERSION_GE(conn, 8.2))
        {
            TABLE_INFO  *ti = stmt->ti[0];
            const char *bestitem = GET_NAME(ti->bestitem);
 
-           SPRINTFCAT_FIXED(addstr, " returning ctid");
+           appendPQExpBuffer(&addstr, " returning ctid");
            if (bestitem)
            {
-               SPRINTFCAT_FIXED(addstr, ", ");
-               SPRINTFCAT_FIXED(addstr, "\"%s\"", bestitem);
+               appendPQExpBuffer(&addstr, ", ");
+               appendPQExpBuffer(&addstr, "\"%s\"", bestitem);
            }
        }
-       mylog("addstr=%s\n", addstr);
+       if (PQExpBufferDataBroken(addstr))
+       {
+           ret = SQL_ERROR;
+           SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in SC_pos_add()", func);
+           goto cleanup;
+       }
+       mylog("addstr=%s\n", addstr.data);
        s.qstmt->exec_start_row = s.qstmt->exec_end_row = s.irow;
        s.updyes = TRUE;
-       ret = PGAPI_ExecDirect(hstmt, (SQLCHAR *) addstr, SQL_NTS, 0);
+       ret = PGAPI_ExecDirect(hstmt, (SQLCHAR *) addstr.data, SQL_NTS, 0);
        if (ret == SQL_NEED_DATA)
        {
            padd_cdata *cbdata = (padd_cdata *) malloc(sizeof(padd_cdata));
@@ -4556,6 +4597,8 @@ SC_pos_add(StatementClass *stmt,
 cleanup:
 #undef return
    CLEANUP_FUNC_CONN_CS(func_cs_count, conn);
+   if (!PQExpBufferDataBroken(addstr))
+       termPQExpBuffer(&addstr);
    return ret;
 }
 
index d31f81e4e173636325953286b235a549215e1be5..cf7537f22a911bc6c2f09835999c19e12914f18a 100755 (executable)
@@ -83,7 +83,7 @@
     <DELAY_LOAD_DLLS>secur32.dll</DELAY_LOAD_DLLS>\r
   </PropertyGroup>\r
   <PropertyGroup Condition="'$(PG_INC)'!=''">\r
-    <ADD_INC>$(ADD_INC);$(PG_INC)</ADD_INC>\r
+    <ADD_INC>$(ADD_INC);$(PG_INC);$(PG_INC)/internal;$(PG_INC)/server;$(PG_INC)/server/port/win32</ADD_INC>\r
     <ADD_LIBPATH>$(ADD_LIBPATH);$(PG_LIB)</ADD_LIBPATH>\r
     <ADD_DEFINES>$(ADD_DEFINES)</ADD_DEFINES>\r
   </PropertyGroup>\r