]> granicus.if.org Git - postgresql/commitdiff
Fix for the following items about escape sequence
authorHiroshi Inoue <inoue@tpf.co.jp>
Thu, 25 Apr 2002 02:50:08 +0000 (02:50 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Thu, 25 Apr 2002 02:50:08 +0000 (02:50 +0000)
   by Marcelo Aceto <aceto@newinf.com.br> .

1) Wrong translations of embedded escape sequences inside outer join escape
sequences.
2) Wrong translation of parameter markers inside outer joins and function
escape sequences.
3) Bad concatenation of date, time, timestamp constants with next word in
statement:

src/interfaces/odbc/convert.c
src/interfaces/odbc/convert.h

index 39998cc0c5737021b0b70f14073fcbe77e90d25c..433f4b3fe17a4820771f7941260bddd4f31efe45 100644 (file)
@@ -28,6 +28,9 @@
 #endif
 
 #include <time.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
 #include <math.h>
 #include <stdlib.h>
 #include "statement.h"
@@ -350,6 +353,9 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
        int                     bind_row = stmt->bind_row;
        int                     bind_size = opts->bind_size;
        int                     result = COPY_OK;
+#ifdef HAVE_LOCALE_H
+       char saved_locale[256];
+#endif /* HAVE_LOCALE_H */
        BOOL            changed, true_is_minus1 = FALSE;
        const char *neut_str = value;
        char            midtemp[2][32];
@@ -491,6 +497,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                                 */
                                bZone = FALSE;  /* time zone stuff is unreliable */
                                timestamp2stime(value, &st, &bZone, &zone);
+inolog("2stime fr=%d\n", st.fr);
                        }
                        else
                        {
@@ -757,9 +764,41 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                                {
                                        copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;
 
+#ifdef HAVE_LOCALE_H
+                                       switch (field_type)
+                                       {
+                                               case PG_TYPE_FLOAT4:
+                                               case PG_TYPE_FLOAT8:
+                                               case PG_TYPE_NUMERIC:
+                                               {
+                                                       struct lconv    *lc;
+                                                       char            *new_string;
+                                                       int             i, j;
+
+                                                       new_string = malloc( cbValueMax );
+                                                       lc = localeconv();
+                                                       for (i = 0, j = 0; ptr[i]; i++)
+                                                               if (ptr[i] == '.')
+                                                               {
+                                                                       strncpy(&new_string[j], lc->decimal_point, strlen(lc->decimal_point));
+                                                                       j += strlen(lc->decimal_point);
+                                                               }
+                                                               else
+                                                                       new_string[j++] = ptr[i];
+                                                       new_string[j] = '\0';
+                                                       strncpy_null(rgbValueBindRow, new_string, copy_len + 1);
+                                                       free(new_string);
+                                                       break;
+                                               }
+                                               default:
+                                               /*      Copy the data */
+                                               strncpy_null(rgbValueBindRow, ptr, copy_len + 1);
+                                       }
+#else /* HAVE_LOCALE_H */
                                        /* Copy the data */
                                        memcpy(rgbValueBindRow, ptr, copy_len);
                                        rgbValueBindRow[copy_len] = '\0';
+#endif /* HAVE_LOCALE_H */
 
                                        /* Adjust data_left for next time */
                                        if (stmt->current_col >= 0)
@@ -916,19 +955,33 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                                break;
 
                        case SQL_C_FLOAT:
+#ifdef HAVE_LOCALE_H
+                               strcpy(saved_locale, setlocale(LC_ALL, NULL));
+                               setlocale(LC_ALL, "C");
+#endif /* HAVE_LOCALE_H */
                                len = 4;
                                if (bind_size > 0)
                                        *(SFLOAT *) ((char *) rgbValue + (bind_row * bind_size)) = (float) atof(neut_str);
                                else
                                        *((SFLOAT *) rgbValue + bind_row) = (float) atof(neut_str);
+#ifdef HAVE_LOCALE_H
+                               setlocale(LC_ALL, saved_locale);
+#endif /* HAVE_LOCALE_H */
                                break;
 
                        case SQL_C_DOUBLE:
+#ifdef HAVE_LOCALE_H
+                               strcpy(saved_locale, setlocale(LC_ALL, NULL));
+                               setlocale(LC_ALL, "C");
+#endif /* HAVE_LOCALE_H */
                                len = 8;
                                if (bind_size > 0)
                                        *(SDOUBLE *) ((char *) rgbValue + (bind_row * bind_size)) = atof(neut_str);
                                else
                                        *((SDOUBLE *) rgbValue + bind_row) = atof(neut_str);
+#ifdef HAVE_LOCALE_H
+                               setlocale(LC_ALL, saved_locale);
+#endif /* HAVE_LOCALE_H */
                                break;
 
                        case SQL_C_SSHORT:
@@ -1077,29 +1130,265 @@ inolog("rgb=%x + %d, pcb=%x, set %s\n", rgbValue, bind_row * bind_size, pcbValue
  *     if you have a better way.       Hiroshi 2001/05/22
  *--------------------------------------------------------------------
  */
+
+#define        FLGP_PREPARE_DUMMY_CURSOR       1L
+#define        FLGP_CURSOR_CHECK_OK    (1L << 1)
+#define        FLGP_SELECT_INTO                (1L << 2)
+#define        FLGP_SELECT_FOR_UPDATE  (1L << 3)
+typedef struct _QueryParse {
+       const char      *statement;
+       int             statement_type;
+       UInt4           opos;
+       int             from_pos;
+       int             where_pos;
+       UInt4           stmt_len;
+       BOOL            in_quote, in_dquote, in_escape;
+       char            token_save[64];
+       int             token_len;
+       BOOL            prev_token_end;
+       BOOL            proc_no_param;
+       unsigned        int declare_pos;
+       UInt4           flags;
+#ifdef MULTIBYTE
+       encoded_str     encstr;
+#endif   /* MULTIBYTE */
+}      QueryParse;
+
+static int
+QP_initialize(QueryParse *q, const StatementClass *stmt)
+{
+       q->statement = stmt->statement;
+       q->statement_type = stmt->statement_type;
+       q->opos = 0;
+       q->from_pos = -1;
+       q->where_pos = -1;
+       q->stmt_len = (q->statement) ? strlen(q->statement) : -1;
+       q->in_quote = q->in_dquote = q->in_escape = FALSE;
+       q->token_save[0] = '\0';
+       q->token_len = 0;
+       q->prev_token_end = TRUE;
+       q->proc_no_param = TRUE;
+       q->declare_pos = 0;
+       q->flags = 0;
+#ifdef MULTIBYTE
+       make_encoded_str(&q->encstr, SC_get_conn(stmt), q->statement);
+#endif   /* MULTIBYTE */
+
+       return q->stmt_len;
+}
+
+#define        FLGB_PRE_EXECUTING      1L
+#define        FLGB_INACCURATE_RESULT  (1L << 1)
+typedef struct _QueryBuild {
+       char    *query_statement;
+       UInt4   str_size_limit;
+       UInt4   str_alsize;
+       UInt4   npos;
+       int     current_row;
+       int     param_number;
+       APDFields *apdopts;
+       UInt4   load_stmt_len;
+       UInt4   flags;
+       BOOL    lf_conv;
+       int     ccsc;
+       int     errornumber;
+       const char *errormsg;
+
+       ConnectionClass *conn; /* mainly needed for LO handling */
+       StatementClass  *stmt; /* needed to set error info in ENLARGE_.. */ 
+}      QueryBuild;
+
 #define INIT_MIN_ALLOC 4096
 static int
-enlarge_statement(StatementClass *stmt, unsigned int newsize)
+QB_initialize(QueryBuild *qb, UInt4 size, StatementClass *stmt, ConnectionClass *conn)
+{
+       UInt4   newsize = 0;
+
+       qb->flags = 0;
+       qb->load_stmt_len = 0;
+       qb->stmt = stmt;
+       qb->apdopts = NULL;
+       if (conn)
+               qb->conn = conn;
+       else if (stmt)
+       {
+               qb->apdopts = SC_get_APD(stmt);
+               qb->conn = SC_get_conn(stmt);
+               if (stmt->pre_executing)
+                       qb->flags |= FLGB_PRE_EXECUTING;
+       }
+       else
+       {
+               qb->conn = NULL;
+               return -1;
+       }
+       qb->lf_conv = qb->conn->connInfo.lf_conversion;
+       qb->ccsc = qb->conn->ccsc;
+               
+       if (stmt)
+               qb->str_size_limit = stmt->stmt_size_limit;
+       else
+               qb->str_size_limit = -1;
+       if (qb->str_size_limit > 0)
+       {
+               if (size > qb->str_size_limit)
+                       return -1;
+               newsize = qb->str_size_limit;
+       }
+       else 
+       {
+               newsize = INIT_MIN_ALLOC;
+               while (newsize <= size)
+                       newsize *= 2;
+       }
+       if ((qb->query_statement = malloc(newsize)) == NULL)
+       {
+               qb->str_alsize = 0;
+               return -1;
+       }       
+       qb->query_statement[0] = '\0';
+       qb->str_alsize = newsize;
+       qb->npos = 0;
+       qb->current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
+       qb->param_number = -1;
+       qb->errornumber = 0;
+       qb->errormsg = NULL;
+
+       return newsize;
+}
+
+static int
+QB_initialize_copy(QueryBuild *qb_to, const QueryBuild *qb_from, UInt4 size)
+{
+       memcpy(qb_to, qb_from, sizeof(QueryBuild));
+
+       if (qb_to->str_size_limit > 0)
+       {
+               if (size > qb_to->str_size_limit)
+                       return -1;
+       }
+       if ((qb_to->query_statement = malloc(size)) == NULL)
+       {
+               qb_to->str_alsize = 0;
+               return -1;
+       }       
+       qb_to->query_statement[0] = '\0';
+       qb_to->str_alsize = size;
+       qb_to->npos = 0;
+
+       return size;
+}
+
+static void
+QB_Destructor(QueryBuild *qb)
+{
+       if (qb->query_statement)
+       {
+               free(qb->query_statement);
+               qb->query_statement = NULL;
+               qb->str_alsize = 0;
+       }
+}
+
+/*
+ * New macros (Aceto)
+ *--------------------
+ */
+
+#define F_OldChar(qp) \
+qp->statement[qp->opos]
+
+#define F_OldPtr(qp) \
+(qp->statement + qp->opos)
+
+#define F_OldNext(qp) \
+(++qp->opos)
+
+#define F_OldPrior(qp) \
+(--qp->opos)
+
+#define F_OldPos(qp) \
+qp->opos
+
+#define F_ExtractOldTo(qp, buf, ch, maxsize) \
+do { \
+       unsigned int    c = 0; \
+       while (qp->statement[qp->opos] != '\0' && qp->statement[qp->opos] != ch) \
+       { \
+           buf[c++] = qp->statement[qp->opos++]; \
+               if (c >= maxsize) \
+                       break; \
+       } \
+       if (qp->statement[qp->opos] == '\0') \
+               return SQL_ERROR; \
+       buf[c] = '\0'; \
+} while (0)
+
+#define F_NewChar(qb) \
+qb->query_statement[qb->npos]
+
+#define F_NewPtr(qb) \
+(qb->query_statement + qb->npos)
+
+#define F_NewNext(qb) \
+(++qb->npos)
+
+#define F_NewPos(qb) \
+(qb->npos)
+
+
+static int
+convert_escape(QueryParse *qp, QueryBuild *qb);
+static int
+inner_process_tokens(QueryParse *qp, QueryBuild *qb);
+static int
+ResolveOneParam(QueryBuild *qb);
+static int
+processParameters(QueryParse *qp, QueryBuild *qb,
+UInt4 *output_count, Int4 param_pos[][2]);
+
+static int
+enlarge_query_statement(QueryBuild *qb, unsigned int newsize)
 {
        unsigned int newalsize = INIT_MIN_ALLOC;
        static char *func = "enlarge_statement";
 
-       if (stmt->stmt_size_limit > 0 && stmt->stmt_size_limit < (int) newsize)
+       if (qb->str_size_limit > 0 && qb->str_size_limit < (int) newsize)
        {
-               stmt->errormsg = "Query buffer overflow in copy_statement_with_parameters";
-               stmt->errornumber = STMT_EXEC_ERROR;
-               SC_log_error(func, "", stmt);
+               free(qb->query_statement);
+               qb->query_statement = NULL;
+               qb->str_alsize = 0;
+               if (qb->stmt)
+               {
+                       qb->stmt->errormsg = "Query buffer overflow in copy_statement_with_parameters";
+                       qb->stmt->errornumber = STMT_EXEC_ERROR;
+                       SC_log_error(func, "", qb->stmt);
+               }
+               else
+               {
+                       qb->errormsg = "Query buffer overflow in copy_statement_with_parameters";
+                       qb->errornumber = STMT_EXEC_ERROR;
+               }
                return -1;
        }
        while (newalsize <= newsize)
                newalsize *= 2;
-       if (!(stmt->stmt_with_params = realloc(stmt->stmt_with_params, newalsize)))
+       if (!(qb->query_statement = realloc(qb->query_statement, newalsize)))
        {
-               stmt->errormsg = "Query buffer allocate error in copy_statement_with_parameters";
-               stmt->errornumber = STMT_EXEC_ERROR;
-               SC_log_error(func, "", stmt);
+               qb->str_alsize = 0;
+               if (qb->stmt)
+               {
+                       qb->stmt->errormsg = "Query buffer allocate error in copy_statement_with_parameters";
+                       qb->stmt->errornumber = STMT_EXEC_ERROR;
+               }
+               else
+               {
+                       qb->errormsg = "Query buffer allocate error in copy_statement_with_parameters";
+                       qb->errornumber = STMT_EXEC_ERROR;
+               }
                return 0;
        }
+       qb->str_alsize = newalsize;
        return newalsize;
 }
 
@@ -1107,75 +1396,53 @@ enlarge_statement(StatementClass *stmt, unsigned int newsize)
  *     Enlarge stmt_with_params if necessary.
  *----------
  */
-#define ENLARGE_NEWSTATEMENT(newpos) \
-       if (newpos >= new_stsize) \
+#define ENLARGE_NEWSTATEMENT(qb, newpos) \
+       if (newpos >= qb->str_alsize) \
        { \
-               if ((new_stsize = enlarge_statement(stmt, newpos)) <= 0) \
+               if (enlarge_query_statement(qb, newpos) <= 0) \
                        return SQL_ERROR; \
-               new_statement = stmt->stmt_with_params; \
        }
-/*----------
- *     Initialize stmt_with_params, new_statement etc.
- *----------
- */
-#define CVT_INIT(size) \
-do { \
-       if (stmt->stmt_with_params) \
-               free(stmt->stmt_with_params); \
-       if (stmt->stmt_size_limit > 0) \
-               new_stsize = stmt->stmt_size_limit; \
-       else \
-       { \
-               new_stsize = INIT_MIN_ALLOC; \
-               while (new_stsize <= size) \
-                       new_stsize *= 2; \
-       } \
-       new_statement = malloc(new_stsize); \
-       stmt->stmt_with_params = new_statement; \
-       npos = 0; \
-       new_statement[0] = '\0'; \
-} while (0)
 
 /*----------
  *     Terminate the stmt_with_params string with NULL.
  *----------
  */
-#define CVT_TERMINATE \
+#define CVT_TERMINATE(qb) \
 do { \
-       new_statement[npos] = '\0'; \
+       qb->query_statement[qb->npos] = '\0'; \
 } while (0)
 
 /*----------
  *     Append a data.
  *----------
  */
-#define CVT_APPEND_DATA(s, len) \
+#define CVT_APPEND_DATA(qb, s, len) \
 do { \
-       unsigned int    newpos = npos + len; \
-       ENLARGE_NEWSTATEMENT(newpos) \
-       memcpy(&new_statement[npos], s, len); \
-       npos = newpos; \
-       new_statement[npos] = '\0'; \
+       unsigned int    newpos = qb->npos + len; \
+       ENLARGE_NEWSTATEMENT(qb, newpos) \
+       memcpy(&qb->query_statement[qb->npos], s, len); \
+       qb->npos = newpos; \
+       qb->query_statement[newpos] = '\0'; \
 } while (0)
 
 /*----------
  *     Append a string.
  *----------
  */
-#define CVT_APPEND_STR(s) \
+#define CVT_APPEND_STR(qb, s) \
 do { \
        unsigned int len = strlen(s); \
-       CVT_APPEND_DATA(s, len); \
+       CVT_APPEND_DATA(qb, s, len); \
 } while (0)
 
 /*----------
  *     Append a char.
  *----------
  */
-#define CVT_APPEND_CHAR(c) \
+#define CVT_APPEND_CHAR(qb, c) \
 do { \
-       ENLARGE_NEWSTATEMENT(npos + 1); \
-       new_statement[npos++] = c; \
+       ENLARGE_NEWSTATEMENT(qb, qb->npos + 1); \
+       qb->query_statement[qb->npos++] = c; \
 } while (0)
 
 /*----------
@@ -1183,25 +1450,25 @@ do { \
  *     Newly reqeuired size may be overestimated currently.
  *----------
  */
-#define CVT_APPEND_BINARY(buf, used) \
+#define CVT_APPEND_BINARY(qb, buf, used) \
 do { \
-       unsigned int    newlimit = npos + 5 * used; \
-       ENLARGE_NEWSTATEMENT(newlimit); \
-       npos += convert_to_pgbinary(buf, &new_statement[npos], used); \
+       unsigned int    newlimit = qb->npos + 5 * used; \
+       ENLARGE_NEWSTATEMENT(qb, newlimit); \
+       qb->npos += convert_to_pgbinary(buf, &qb->query_statement[qb->npos], used); \
 } while (0)
 
 /*----------
  *
  *----------
  */
-#define CVT_SPECIAL_CHARS(buf, used) \
+#define CVT_SPECIAL_CHARS(qb, buf, used) \
 do { \
-       int cnvlen = convert_special_chars(buf, NULL, used, lf_conv, conn->ccsc); \
-       unsigned int    newlimit = npos + cnvlen; \
+       int cnvlen = convert_special_chars(buf, NULL, used, qb->lf_conv, qb->ccsc); \
+       unsigned int    newlimit = qb->npos + cnvlen; \
 \
-       ENLARGE_NEWSTATEMENT(newlimit); \
-       convert_special_chars(buf, &new_statement[npos], used, lf_conv, conn->ccsc); \
-       npos += cnvlen; \
+       ENLARGE_NEWSTATEMENT(qb, newlimit); \
+       convert_special_chars(buf, &qb->query_statement[qb->npos], used, qb->lf_conv, qb->ccsc); \
+       qb->npos += cnvlen; \
 } while (0)
 
 /*----------
@@ -1283,69 +1550,32 @@ int
 copy_statement_with_parameters(StatementClass *stmt)
 {
        static char *func = "copy_statement_with_parameters";
-       unsigned int opos,
-                               npos,
-                               oldstmtlen;
-       char            param_string[128],
-                               tmp[256],
-                               cbuf[PG_NUMERIC_MAX_PRECISION * 2];             /* seems big enough to
-                                                                                                                * handle the data in
-                                                                                                                * this function */
-       int                     param_number;
-       Int2            param_ctype,
-                               param_sqltype;
-       char       *old_statement = stmt->statement,
-                               oldchar;
-       char       *new_statement = stmt->stmt_with_params;
-       unsigned int new_stsize = 0;
-       SIMPLE_TIME st;
-       time_t          t = time(NULL);
-       struct tm  *tim;
-       SDWORD          used;
-       char       *buffer, *buf, *allocbuf;
-       BOOL            in_quote = FALSE,
-                               in_dquote = FALSE,
-                               in_escape = FALSE;
-       Oid                     lobj_oid;
-       int                     lobj_fd,
-                               retval;
-       BOOL            check_cursor_ok = FALSE;                /* check cursor
-                                                                                                * restriction */
-       BOOL            proc_no_param = TRUE;
-       unsigned int declare_pos = 0;
-       ConnectionClass *conn = SC_get_conn(stmt);
-       ConnInfo   *ci = &(conn->connInfo);
-       BOOL            prepare_dummy_cursor = FALSE,
-                               begin_first = FALSE;
-       char            token_save[64];
-       int                     token_len;
-       BOOL            prev_token_end;
-       APDFields       *opts = SC_get_APD(stmt);
-       UInt4   offset = opts->param_offset_ptr ? *opts->param_offset_ptr : 0;
-       UInt4   current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
-       BOOL    lf_conv = ci->lf_conversion;
-#ifdef MULTIBYTE
-       encoded_str     encstr;
-#endif   /* MULTIBYTE */
+       RETCODE         retval;
+       QueryParse      query_org, *qp;
+       QueryBuild      query_crt, *qb;
 
-       Int4    from_pos = -1, where_pos = -1;
+       char       *new_statement;
 
-       if (ci->disallow_premature)
-               prepare_dummy_cursor = stmt->pre_executing;
+       BOOL    begin_first = FALSE, prepare_dummy_cursor = FALSE;
+       ConnectionClass *conn = SC_get_conn(stmt);
+       ConnInfo   *ci = &(conn->connInfo);
+       int             current_row;
 
-       if (!old_statement)
+       if (!stmt->statement)
        {
                SC_log_error(func, "No statement string", stmt);
                return SQL_ERROR;
        }
 
-       memset(&st, 0, sizeof(SIMPLE_TIME));
+       current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
+       qp = &query_org;
+       QP_initialize(qp, stmt);
+
+       if (ci->disallow_premature)
+               prepare_dummy_cursor = stmt->pre_executing;
+       if (prepare_dummy_cursor);
+               qp->flags |= FLGP_PREPARE_DUMMY_CURSOR;
 
-       /* Initialize current date */
-       tim = localtime(&t);
-       st.m = tim->tm_mon + 1;
-       st.d = tim->tm_mday;
-       st.y = tim->tm_year + 1900;
 
 #ifdef DRIVER_CURSOR_IMPLEMENT
        if (stmt->statement_type != STMT_TYPE_SELECT)
@@ -1365,8 +1595,8 @@ copy_statement_with_parameters(StatementClass *stmt)
                        stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
                else
                {
-                       from_pos = stmt->from_pos;
-                       where_pos = stmt->where_pos;
+                       qp->from_pos = stmt->from_pos;
+                       qp->where_pos = stmt->where_pos;
                }
        }
 #else
@@ -1378,12 +1608,17 @@ copy_statement_with_parameters(StatementClass *stmt)
        /* If the application hasn't set a cursor name, then generate one */
        if (stmt->cursor_name[0] == '\0')
                sprintf(stmt->cursor_name, "SQL_CUR%p", stmt);
-       oldstmtlen = strlen(old_statement);
-       CVT_INIT(oldstmtlen);
+       if (stmt->stmt_with_params)
+       {
+               free(stmt->stmt_with_params);
+               stmt->stmt_with_params = NULL;
+       }
+       qb = &query_crt;
+       if (QB_initialize(qb, qp->stmt_len, stmt, NULL) < 0)
+               return SQL_ERROR;
+       new_statement = qb->query_statement;
 
        stmt->miscinfo = 0;
-       token_len = 0;
-       prev_token_end = TRUE;
        /* For selects, prepend a declare cursor to the statement */
        if (stmt->statement_type == STMT_TYPE_SELECT)
        {
@@ -1402,702 +1637,743 @@ copy_statement_with_parameters(StatementClass *stmt)
                                SC_set_fetchcursor(stmt);
                        sprintf(new_statement, "%sdeclare %s cursor for ",
                                        new_statement, stmt->cursor_name);
-                       npos = strlen(new_statement);
-                       check_cursor_ok = TRUE;
-                       declare_pos = npos;
+                       qb->npos = strlen(new_statement);
+                       qp->flags |= FLGP_CURSOR_CHECK_OK;
+                       qp->declare_pos = qb->npos;
                }
        }
-       param_number = -1;
-#ifdef MULTIBYTE
-       make_encoded_str(&encstr, conn, old_statement);
-#endif
-       for (opos = 0; opos < oldstmtlen; opos++)
+
+       for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)
        {
-               if (from_pos == (Int4) opos)
+               retval = inner_process_tokens(qp, qb);
+               if (SQL_ERROR == retval)
                {
-                       CVT_APPEND_STR(", CTID, OID ");
+                       if (0 == stmt->errornumber)
+                       {
+                               stmt->errornumber = qb->errornumber;
+                               stmt->errormsg = qb->errormsg;
+                       }
+                       SC_log_error(func, "", stmt);
+                       QB_Destructor(qb);
+                       return retval;
                }
-               else if (where_pos == (Int4) opos)
-               {
-                       stmt->load_statement = malloc(npos + 1);
-                       memcpy(stmt->load_statement, new_statement, npos);
+       }
+       /* make sure new_statement is always null-terminated */
+       CVT_TERMINATE(qb);
+
+       new_statement = qb->query_statement;
+       stmt->statement_type = qp->statement_type;
+       stmt->inaccurate_result = (0 != (qb->flags & FLGB_INACCURATE_RESULT));
+       if (0 != (qp->flags & FLGP_SELECT_INTO))
+       {
+               SC_no_pre_executable(stmt);
+               SC_no_fetchcursor(stmt);
+               stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+       }
+       if (0 != (qp->flags & FLGP_SELECT_FOR_UPDATE))
+       {
+               SC_no_fetchcursor(stmt);
+               stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+       }
+
+       if (conn->DriverToDataSource != NULL)
+       {
+               int                     length = strlen(new_statement);
+
+               conn->DriverToDataSource(conn->translation_option,
+                                                                SQL_CHAR,
+                                                                new_statement, length,
+                                                                new_statement, length, NULL,
+                                                                NULL, 0, NULL);
+       }
+
+#ifdef DRIVER_CURSOR_IMPLEMENT
+       if (!stmt->load_statement && qp->from_pos >= 0)
+       {
+               UInt4   npos = qb->load_stmt_len;
+
+               if (0 == npos)
+                       npos = qb->npos;
+               stmt->load_statement = malloc(npos + 1);
+               memcpy(stmt->load_statement, new_statement, npos);
+               if (stmt->load_statement[npos - 1] == ';')
+                       stmt->load_statement[npos - 1] = '\0';
+               else
                        stmt->load_statement[npos] = '\0';
-               }
+       }
+#endif   /* DRIVER_CURSOR_IMPLEMENT */
+       if (prepare_dummy_cursor && SC_is_pre_executable(stmt))
+       {
+               char            fetchstr[128];
+
+               sprintf(fetchstr, ";fetch backward in %s;close %s;",
+                               stmt->cursor_name, stmt->cursor_name);
+               if (begin_first && CC_is_in_autocommit(conn))
+                       strcat(fetchstr, "COMMIT;");
+               CVT_APPEND_STR(qb, fetchstr);
+               stmt->inaccurate_result = TRUE;
+       }
+
+       stmt->stmt_with_params = qb->query_statement;
+       return SQL_SUCCESS;
+}
+
+static int
+inner_process_tokens(QueryParse *qp, QueryBuild *qb)
+{
+       static char *func = "inner_process_tokens";
+       BOOL    lf_conv = qb->lf_conv;
+
+       RETCODE retval;
+       char       oldchar;
+
+       if (qp->from_pos == (Int4) qp->opos)
+       {
+               CVT_APPEND_STR(qb, ", CTID, OID ");
+       }
+       else if (qp->where_pos == (Int4) qp->opos)
+               qb->load_stmt_len = qb->npos;
 #ifdef MULTIBYTE
-               oldchar = encoded_byte_check(&encstr, opos);
-               if (ENCODE_STATUS(encstr) != 0)
-               {
-                       CVT_APPEND_CHAR(oldchar);
-                       continue;
-               }
+       oldchar = encoded_byte_check(&qp->encstr, qp->opos);
+       if (ENCODE_STATUS(qp->encstr) != 0)
+       {
+               CVT_APPEND_CHAR(qb, oldchar);
+               return SQL_SUCCESS;
+       }
 
-               /*
-                * From here we are guaranteed to handle a 1-byte character.
-                */
+       /*
+        * From here we are guaranteed to handle a 1-byte character.
+        */
 #else
-               oldchar = old_statement[opos];
+       oldchar = qp->statement[qp->opos];
 #endif
 
-               if (in_escape)                  /* escape check */
-               {
-                       in_escape = FALSE;
-                       CVT_APPEND_CHAR(oldchar);
-                       continue;
-               }
-               else if (in_quote || in_dquote) /* quote/double quote check */
-               {
-                       if (oldchar == '\\')
-                               in_escape = TRUE;
-                       else if (oldchar == '\'' && in_quote)
-                               in_quote = FALSE;
-                       else if (oldchar == '\"' && in_dquote)
-                               in_dquote = FALSE;
-                       CVT_APPEND_CHAR(oldchar);
-                       continue;
-               }
+       if (qp->in_escape)                      /* escape check */
+       {
+               qp->in_escape = FALSE;
+               CVT_APPEND_CHAR(qb, oldchar);
+               return SQL_SUCCESS;
+       }
+       else if (qp->in_quote || qp->in_dquote) /* quote/double quote check */
+       {
+               if (oldchar == '\\')
+                       qp->in_escape = TRUE;
+               else if (oldchar == '\'' && qp->in_quote)
+                       qp->in_quote = FALSE;
+               else if (oldchar == '\"' && qp->in_dquote)
+                       qp->in_dquote = FALSE;
+               CVT_APPEND_CHAR(qb, oldchar);
+               return SQL_SUCCESS;
+       }
 
-               /*
-                * From here we are guranteed to be in neither an escape, a quote
-                * nor a double quote.
-                */
-               /* Squeeze carriage-return/linefeed pairs to linefeed only */
-               else if (lf_conv && oldchar == '\r' && opos + 1 < oldstmtlen &&
-                                old_statement[opos + 1] == '\n')
-                       continue;
+       /*
+        * From here we are guranteed to be in neither an escape, a quote
+        * nor a double 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')
+               return SQL_SUCCESS;
 
-               /*
-                * Handle literals (date, time, timestamp) and ODBC scalar
-                * functions
-                */
-               else if (oldchar == '{')
+       /*
+        * Handle literals (date, time, timestamp) and ODBC scalar
+        * functions
+        */
+       else if (oldchar == '{')
+       {
+               if (SQL_ERROR == convert_escape(qp, qb))
                {
-                       const char      *begin = &old_statement[opos], *end;
-
-                       /* procedure calls */
-                       if (stmt->statement_type == STMT_TYPE_PROCCALL)
-                       {
-                               int     lit_call_len = 4;
-
-                               while (isspace((unsigned char) old_statement[++opos]));
-                               /* '?=' to accept return values exists ? */
-                               if (old_statement[opos] == '?')
-                               {
-                                       param_number++;
-                                       while (isspace((unsigned char) old_statement[++opos]));
-                                       if (old_statement[opos] != '=')
-                                       {
-                                               opos--;
-                                               continue;
-                                       }
-                                       while (isspace((unsigned char) old_statement[++opos]));
-                               }
-                               if (strnicmp(&old_statement[opos], "call", lit_call_len) ||
-                                       !isspace((unsigned char) old_statement[opos + lit_call_len]))
-                               {
-                                       opos--;
-                                       continue;
-                               }
-                               opos += lit_call_len;
-                               CVT_APPEND_STR("SELECT ");
-                               if (my_strchr(conn, &old_statement[opos], '('))
-                                       proc_no_param = FALSE;
-                               continue;
-                       }
-                       if (convert_escape(begin, stmt, &npos, &new_stsize, &end
-) != CONVERT_ESCAPE_OK)
+                       if (0 == qb->errornumber)
                        {
-                               stmt->errormsg = "ODBC escape convert error";
-                               stmt->errornumber = STMT_EXEC_ERROR;
-                               return SQL_ERROR;
+                               qb->errornumber = STMT_EXEC_ERROR;
+                               qb->errormsg = "ODBC escape convert error";
                        }
-                       opos = end - old_statement; /* positioned at the last } */
-                       new_statement = stmt->stmt_with_params;
-                       if (isalnum(end[1]))
-                               CVT_APPEND_CHAR(' ');
-                       continue;
+                       mylog("%s convert_escape error\n", func);
+                       return SQL_ERROR;
                }
-               /* End of a procedure call */
-               else if (oldchar == '}' && stmt->statement_type == STMT_TYPE_PROCCALL)
+               if (isalnum(F_OldPtr(qp)[1]))
+                       CVT_APPEND_CHAR(qb, ' ');
+               return SQL_SUCCESS;
+       }
+       /* End of an escape sequence */
+       else if (oldchar == '}')
+       {
+               if (qp->statement_type == STMT_TYPE_PROCCALL)
                {
-                       if (proc_no_param)
-                               CVT_APPEND_STR("()");
-                       continue;
+                       if (qp->proc_no_param)
+                               CVT_APPEND_STR(qb, "()");
                }
+               else if (!isspace(F_OldPtr(qp)[1]))
+                       CVT_APPEND_CHAR(qb, ' ');
+               return SQL_SUCCESS;
+       }
 
-               /*
-                * Can you have parameter markers inside of quotes?  I dont think
-                * so. All the queries I've seen expect the driver to put quotes
-                * if needed.
-                */
-               else if (oldchar == '?')
-                       ;                                       /* ok */
+       /*
+        * Can you have parameter markers inside of quotes?  I dont think
+        * so. All the queries I've seen expect the driver to put quotes
+        * if needed.
+        */
+       else if (oldchar != '?')
+       {
+               if (oldchar == '\'')
+                       qp->in_quote = TRUE;
+               else if (oldchar == '\\')
+                       qp->in_escape = TRUE;
+               else if (oldchar == '\"')
+                       qp->in_dquote = TRUE;
                else
                {
-                       if (oldchar == '\'')
-                               in_quote = TRUE;
-                       else if (oldchar == '\\')
-                               in_escape = TRUE;
-                       else if (oldchar == '\"')
-                               in_dquote = TRUE;
-                       else
+                       if (isspace((unsigned char) oldchar))
                        {
-                               if (isspace((unsigned char) oldchar))
+                               if (!qp->prev_token_end)
                                {
-                                       if (!prev_token_end)
+                                       qp->prev_token_end = TRUE;
+                                       qp->token_save[qp->token_len] = '\0';
+                                       if (qp->token_len == 4)
                                        {
-                                               prev_token_end = TRUE;
-                                               token_save[token_len] = '\0';
-                                               if (token_len == 4)
+                                               if (0 != (qp->flags & FLGP_CURSOR_CHECK_OK) &&
+                                                       into_table_from(&qp->statement[qp->opos - qp->token_len]))
                                                {
-                                                       if (check_cursor_ok &&
-                                                               into_table_from(&old_statement[opos - token_len]))
-                                                       {
-                                                               stmt->statement_type = STMT_TYPE_CREATE;
-                                                               SC_no_pre_executable(stmt);
-                                                               SC_no_fetchcursor(stmt);
-                                                               stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
-                                                               memmove(new_statement, new_statement + declare_pos, npos - declare_pos);
-                                                               npos -= declare_pos;
-                                                       }
+                                                       qp->flags |= FLGP_SELECT_INTO;
+                                                       qp->flags &= ~FLGP_CURSOR_CHECK_OK;
+                                                       qp->statement_type = STMT_TYPE_CREATE;
+                                                       memmove(qb->query_statement, qb->query_statement + qp->declare_pos, qb->npos - qp->declare_pos);
+                                                       qb->npos -= qp->declare_pos;
                                                }
-                                               if (token_len == 3)
-                                               {
-                                                       int                     endpos;
+                                       }
+                                       if (qp->token_len == 3)
+                                       {
+                                               int                     endpos;
 
-                                                       if (check_cursor_ok &&
-                                                               strnicmp(token_save, "for", 3) == 0 &&
-                                                               table_for_update(&old_statement[opos], &endpos))
+                                               if (0 != (qp->flags & FLGP_CURSOR_CHECK_OK) &&
+                                                       strnicmp(qp->token_save, "for", 3) == 0 &&
+                                                       table_for_update(&qp->statement[qp->opos], &endpos))
+                                               {
+                                                       qp->flags |= FLGP_SELECT_FOR_UPDATE;
+                                                       qp->flags &= ~FLGP_CURSOR_CHECK_OK;
+                                                       if (qp->flags & FLGP_PREPARE_DUMMY_CURSOR)
                                                        {
-                                                               SC_no_fetchcursor(stmt);
-                                                               stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
-                                                               if (prepare_dummy_cursor)
-                                                               {
-                                                                       npos -= 4;
-                                                                       opos += endpos;
-                                                               }
-                                                               else
-                                                               {
-                                                                       memmove(new_statement, new_statement + declare_pos, npos - declare_pos);
-                                                                       npos -= declare_pos;
-                                                               }
+                                                               qb->npos -= 4;
+                                                               qp->opos += endpos;
+                                                       }
+                                                       else
+                                                       {
+                                                               memmove(qb->query_statement, qb->query_statement + qp->declare_pos, qb->npos - qp->declare_pos);
+                                                               qb->npos -= qp->declare_pos;
                                                        }
                                                }
                                        }
                                }
-                               else if (prev_token_end)
-                               {
-                                       prev_token_end = FALSE;
-                                       token_save[0] = oldchar;
-                                       token_len = 1;
-                               }
-                               else if (token_len + 1 < sizeof(token_save))
-                                       token_save[token_len++] = oldchar;
                        }
-                       CVT_APPEND_CHAR(oldchar);
-                       continue;
-               }
-
-               /*
-                * Its a '?' parameter alright
-                */
-               param_number++;
-
-               if (param_number >= opts->allocated)
-               {
-                       if (stmt->pre_executing)
+                       else if (qp->prev_token_end)
                        {
-                               CVT_APPEND_STR("NULL");
-                               stmt->inaccurate_result = TRUE;
-                               continue;
-                       }
-                       else
-                       {
-                               CVT_APPEND_CHAR('?');
-                               continue;
+                               qp->prev_token_end = FALSE;
+                               qp->token_save[0] = oldchar;
+                               qp->token_len = 1;
                        }
+                       else if (qp->token_len + 1 < sizeof(qp->token_save))
+                               qp->token_save[qp->token_len++] = oldchar;
                }
+               CVT_APPEND_CHAR(qb, oldchar);
+               return SQL_SUCCESS;
+       }
+
+       /*
+        * Its a '?' parameter alright
+        */
+       if (retval = ResolveOneParam(qb), retval < 0)
+               return retval;
+
+       return SQL_SUCCESS;
+}
 
-               /* Assign correct buffers based on data at exec param or not */
-               if (opts->parameters[param_number].data_at_exec)
+static int
+ResolveOneParam(QueryBuild *qb)
+{
+       const char *func = "ResolveOneParam";
+
+       ConnectionClass *conn = qb->conn;
+       ConnInfo   *ci = &(conn->connInfo);
+       APDFields *opts = qb->apdopts;
+
+       int             param_number;
+       char            param_string[128], tmp[256],
+                       cbuf[PG_NUMERIC_MAX_PRECISION * 2]; /* seems big enough to handle the data in this function */
+       Int2            param_ctype, param_sqltype;
+       SIMPLE_TIME     st;
+       time_t          t;
+       struct tm       *tim;
+       SDWORD          used;
+       char            *buffer, *buf, *allocbuf;
+       Oid             lobj_oid;
+       int             lobj_fd, retval;
+       UInt4   offset = opts->param_offset_ptr ? *opts->param_offset_ptr : 0;
+       UInt4   current_row = qb->current_row;
+
+       /*
+        * Its a '?' parameter alright
+        */
+       param_number = ++qb->param_number;
+
+       if (param_number >= opts->allocated)
+       {
+               if (0 != (qb->flags & FLGB_PRE_EXECUTING))
                {
-                       used = opts->parameters[param_number].EXEC_used ? *opts->parameters[param_number].EXEC_used : SQL_NTS;
-                       buffer = opts->parameters[param_number].EXEC_buffer;
+                       CVT_APPEND_STR(qb, "NULL");
+                       qb->flags |= FLGB_INACCURATE_RESULT;
+                       return SQL_SUCCESS;
                }
                else
                {
-                       UInt4   bind_size = opts->param_bind_type;
-                       UInt4   ctypelen;
+                       CVT_APPEND_CHAR(qb, '?');
+                       return SQL_SUCCESS;
+               }
+       }
 
-                       buffer = opts->parameters[param_number].buffer + offset;
-                       if (current_row > 0)
-                       {
-                               if (bind_size > 0)
-                                       buffer += (bind_size * current_row);
-                               else if (ctypelen = ctype_length(opts->parameters[param_number].CType), ctypelen > 0)
-                                       buffer += current_row * ctypelen;
-                               else 
-                                       buffer += current_row * opts->parameters[param_number].buflen;
-                       }
-                       if (opts->parameters[param_number].used)
-                       {
-                               UInt4   p_offset = offset;
-                               if (bind_size > 0)
-                                       p_offset = offset + bind_size * current_row;
-                               else
-                                       p_offset = offset + sizeof(SDWORD) * current_row;
-                               used = *(SDWORD *)((char *)opts->parameters[param_number].used + p_offset);
-                       }
+       /* Assign correct buffers based on data at exec param or not */
+       if (opts->parameters[param_number].data_at_exec)
+       {
+               used = opts->parameters[param_number].EXEC_used ? *opts->parameters[param_number].EXEC_used : SQL_NTS;
+               buffer = opts->parameters[param_number].EXEC_buffer;
+       }
+       else
+       {
+               UInt4   bind_size = opts->param_bind_type;
+               UInt4   ctypelen;
+
+               buffer = opts->parameters[param_number].buffer + offset;
+               if (current_row > 0)
+               {
+                       if (bind_size > 0)
+                               buffer += (bind_size * current_row);
+                       else if (ctypelen = ctype_length(opts->parameters[param_number].CType), ctypelen > 0)
+                               buffer += current_row * ctypelen;
+                       else 
+                               buffer += current_row * opts->parameters[param_number].buflen;
+               }
+               if (opts->parameters[param_number].used)
+               {
+                       UInt4   p_offset = offset;
+                       if (bind_size > 0)
+                               p_offset = offset + bind_size * current_row;
                        else
-                               used = SQL_NTS;
+                               p_offset = offset + sizeof(SDWORD) * current_row;
+                       used = *(SDWORD *)((char *)opts->parameters[param_number].used + p_offset);
                }
+               else
+                       used = SQL_NTS;
+       }       
 
-               /* Handle NULL parameter data */
-               if (used == SQL_NULL_DATA)
+       /* Handle NULL parameter data */
+       if (used == SQL_NULL_DATA)
+       {
+               CVT_APPEND_STR(qb, "NULL");
+               return SQL_SUCCESS;
+       }
+
+       /*
+        * If no buffer, and it's not null, then what the hell is it? Just
+        * leave it alone then.
+        */
+       if (!buffer)
+       {
+               if (0 != (qb->flags & FLGB_PRE_EXECUTING))
                {
-                       CVT_APPEND_STR("NULL");
-                       continue;
+                       CVT_APPEND_STR(qb, "NULL");
+                       qb->flags |= FLGB_INACCURATE_RESULT;
+                       return SQL_SUCCESS;
                }
-
-               /*
-                * If no buffer, and it's not null, then what the hell is it? Just
-                * leave it alone then.
-                */
-               if (!buffer)
+               else
                {
-                       if (stmt->pre_executing)
-                       {
-                               CVT_APPEND_STR("NULL");
-                               stmt->inaccurate_result = TRUE;
-                               continue;
-                       }
-                       else
-                       {
-                               CVT_APPEND_CHAR('?');
-                               continue;
-                       }
+                       CVT_APPEND_CHAR(qb, '?');
+                       return SQL_SUCCESS;
                }
+       }
 
-               param_ctype = opts->parameters[param_number].CType;
-               param_sqltype = opts->parameters[param_number].SQLType;
+       param_ctype = opts->parameters[param_number].CType;
+       param_sqltype = opts->parameters[param_number].SQLType;
 
-               mylog("copy_statement_with_params: from(fcType)=%d, to(fSqlType)=%d\n", param_ctype, param_sqltype);
+       mylog("%s: from(fcType)=%d, to(fSqlType)=%d\n", func,
+                               param_ctype, param_sqltype);
 
-               /* replace DEFAULT with something we can use */
-               if (param_ctype == SQL_C_DEFAULT)
-                       param_ctype = sqltype_to_default_ctype(param_sqltype);
+       /* replace DEFAULT with something we can use */
+       if (param_ctype == SQL_C_DEFAULT)
+               param_ctype = sqltype_to_default_ctype(param_sqltype);
 
-               allocbuf = buf = NULL;
-               param_string[0] = '\0';
-               cbuf[0] = '\0';
+       allocbuf = buf = NULL;
+       param_string[0] = '\0';
+       cbuf[0] = '\0';
+       memset(&st, 0, sizeof(st));
+       t = time(NULL);
+       tim = localtime(&t);
+       st.m = tim->tm_mon + 1;
+       st.d = tim->tm_mday;
+       st.y = tim->tm_year + 1900;
 
-               /* Convert input C type to a neutral format */
-               switch (param_ctype)
-               {
-                       case SQL_C_BINARY:
-                       case SQL_C_CHAR:
-                               buf = buffer;
-                               break;
+       /* Convert input C type to a neutral format */
+       switch (param_ctype)
+       {
+               case SQL_C_BINARY:
+               case SQL_C_CHAR:
+                       buf = buffer;
+                       break;
 
 #ifdef UNICODE_SUPPORT
-                       case SQL_C_WCHAR:
-                               buf = allocbuf = ucs2_to_utf8((SQLWCHAR *) buffer, used / 2, &used);
-                               used *= 2;
-                               break;
+               case SQL_C_WCHAR:
+                       buf = allocbuf = ucs2_to_utf8((SQLWCHAR *) buffer, used / 2, &used);
+                       used *= 2;
+                       break;
 #endif /* UNICODE_SUPPORT */
 
-                       case SQL_C_DOUBLE:
-                               sprintf(param_string, "%.15g",
+               case SQL_C_DOUBLE:
+                       sprintf(param_string, "%.15g",
                                                *((SDOUBLE *) buffer));
-                               break;
+                       break;
 
-                       case SQL_C_FLOAT:
-                               sprintf(param_string, "%.6g",
-                                               *((SFLOAT *) buffer));
-                               break;
+               case SQL_C_FLOAT:
+                       sprintf(param_string, "%.6g",
+                                       *((SFLOAT *) buffer));
+                       break;
 
-                       case SQL_C_SLONG:
-                       case SQL_C_LONG:
-                               sprintf(param_string, "%ld",
-                                               *((SDWORD *) buffer));
-                               break;
+               case SQL_C_SLONG:
+               case SQL_C_LONG:
+                       sprintf(param_string, "%ld",
+                                       *((SDWORD *) buffer));
+                       break;
 
 #if (ODBCVER >= 0x0300) && defined(ODBCINT64)
 #ifdef WIN32
-                       case SQL_C_SBIGINT:
-                               sprintf(param_string, "%I64d",
-                                               *((SQLBIGINT *) buffer));
-                               break;
+               case SQL_C_SBIGINT:
+                       sprintf(param_string, "%I64d",
+                                       *((SQLBIGINT *) buffer));
+                       break;
 
-                       case SQL_C_UBIGINT:
-                               sprintf(param_string, "%I64u",
-                                               *((SQLUBIGINT *) buffer));
-                               break;
+               case SQL_C_UBIGINT:
+                       sprintf(param_string, "%I64u",
+                                       *((SQLUBIGINT *) buffer));
+                       break;
 
 #endif /* WIN32 */
 #endif /* ODBCINT64 */
-                       case SQL_C_SSHORT:
-                       case SQL_C_SHORT:
-                               sprintf(param_string, "%d",
-                                               *((SWORD *) buffer));
-                               break;
+               case SQL_C_SSHORT:
+               case SQL_C_SHORT:
+                       sprintf(param_string, "%d",
+                                       *((SWORD *) buffer));
+                       break;
 
-                       case SQL_C_STINYINT:
-                       case SQL_C_TINYINT:
-                               sprintf(param_string, "%d",
-                                               *((SCHAR *) buffer));
-                               break;
+               case SQL_C_STINYINT:
+               case SQL_C_TINYINT:
+                       sprintf(param_string, "%d",
+                                       *((SCHAR *) buffer));
+                       break;
 
-                       case SQL_C_ULONG:
-                               sprintf(param_string, "%lu",
-                                               *((UDWORD *) buffer));
-                               break;
+               case SQL_C_ULONG:
+                       sprintf(param_string, "%lu",
+                                       *((UDWORD *) buffer));
+                       break;
 
-                       case SQL_C_USHORT:
-                               sprintf(param_string, "%u",
-                                               *((UWORD *) buffer));
-                               break;
+               case SQL_C_USHORT:
+                       sprintf(param_string, "%u",
+                                       *((UWORD *) buffer));
+                       break;
 
-                       case SQL_C_UTINYINT:
-                               sprintf(param_string, "%u",
-                                               *((UCHAR *) buffer));
-                               break;
+               case SQL_C_UTINYINT:
+                       sprintf(param_string, "%u",
+                                       *((UCHAR *) buffer));
+                       break;
 
-                       case SQL_C_BIT:
-                               {
-                                       int                     i = *((UCHAR *) buffer);
+               case SQL_C_BIT:
+                       {
+                               int                     i = *((UCHAR *) buffer);
 
                                        sprintf(param_string, "%d", i ? 1 : 0);
                                        break;
-                               }
+                       }
 
-                       case SQL_C_DATE:
+               case SQL_C_DATE:
 #if (ODBCVER >= 0x0300)
-                       case SQL_C_TYPE_DATE:           /* 91 */
+               case SQL_C_TYPE_DATE:           /* 91 */
 #endif
-                               {
-                                       DATE_STRUCT *ds = (DATE_STRUCT *) buffer;
+                       {
+                               DATE_STRUCT *ds = (DATE_STRUCT *) buffer;
 
-                                       st.m = ds->month;
-                                       st.d = ds->day;
-                                       st.y = ds->year;
+                               st.m = ds->month;
+                               st.d = ds->day;
+                               st.y = ds->year;
 
-                                       break;
-                               }
+                               break;
+                       }
 
-                       case SQL_C_TIME:
+               case SQL_C_TIME:
 #if (ODBCVER >= 0x0300)
-                       case SQL_C_TYPE_TIME:           /* 92 */
+               case SQL_C_TYPE_TIME:           /* 92 */
 #endif
-                               {
-                                       TIME_STRUCT *ts = (TIME_STRUCT *) buffer;
+                       {
+                               TIME_STRUCT *ts = (TIME_STRUCT *) buffer;
 
-                                       st.hh = ts->hour;
-                                       st.mm = ts->minute;
-                                       st.ss = ts->second;
+                               st.hh = ts->hour;
+                               st.mm = ts->minute;
+                               st.ss = ts->second;
 
-                                       break;
-                               }
+                               break;
+                       }
 
-                       case SQL_C_TIMESTAMP:
+               case SQL_C_TIMESTAMP:
 #if (ODBCVER >= 0x0300)
-                       case SQL_C_TYPE_TIMESTAMP:      /* 93 */
+               case SQL_C_TYPE_TIMESTAMP:      /* 93 */
 #endif
-                               {
-                                       TIMESTAMP_STRUCT *tss = (TIMESTAMP_STRUCT *) buffer;
+                       {
+                               TIMESTAMP_STRUCT *tss = (TIMESTAMP_STRUCT *) buffer;
 
-                                       st.m = tss->month;
-                                       st.d = tss->day;
-                                       st.y = tss->year;
-                                       st.hh = tss->hour;
-                                       st.mm = tss->minute;
-                                       st.ss = tss->second;
-                                       st.fr = tss->fraction;
+                               st.m = tss->month;
+                               st.d = tss->day;
+                               st.y = tss->year;
+                               st.hh = tss->hour;
+                               st.mm = tss->minute;
+                               st.ss = tss->second;
+                               st.fr = tss->fraction;
 
-                                       mylog("m=%d,d=%d,y=%d,hh=%d,mm=%d,ss=%d,fr=%d\n", st.m, st.d, st.y, st.hh, st.mm, st.ss, st.fr);
+                               mylog("m=%d,d=%d,y=%d,hh=%d,mm=%d,ss=%d\n", st.m, st.d, st.y, st.hh, st.mm, st.ss);
 
-                                       break;
+                               break;
 
-                               }
-                       default:
-                               /* error */
-                               stmt->errormsg = "Unrecognized C_parameter type in copy_statement_with_parameters";
-                               stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-                               CVT_TERMINATE;  /* just in case */
-                               SC_log_error(func, "", stmt);
-                               return SQL_ERROR;
-               }
+                       }
+               default:
+                       /* error */
+                       qb->errormsg = "Unrecognized C_parameter type in copy_statement_with_parameters";
+                       qb->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
+                       CVT_TERMINATE(qb);      /* just in case */
+                       return SQL_ERROR;
+       }
 
-               /*
-                * Now that the input data is in a neutral format, convert it to
-                * the desired output format (sqltype)
-                */
+       /*
+        * Now that the input data is in a neutral format, convert it to
+        * the desired output format (sqltype)
+        */
 
-               switch (param_sqltype)
-               {
-                       case SQL_CHAR:
-                       case SQL_VARCHAR:
-                       case SQL_LONGVARCHAR:
+       switch (param_sqltype)
+       {
+               case SQL_CHAR:
+               case SQL_VARCHAR:
+               case SQL_LONGVARCHAR:
 #ifdef UNICODE_SUPPORT
-                       case SQL_WCHAR:
-                       case SQL_WVARCHAR:
-                       case SQL_WLONGVARCHAR:
+               case SQL_WCHAR:
+               case SQL_WVARCHAR:
+               case SQL_WLONGVARCHAR:
 #endif /* UNICODE_SUPPORT */
 
-                               CVT_APPEND_CHAR('\'');  /* Open Quote */
+                       CVT_APPEND_CHAR(qb, '\'');      /* Open Quote */
 
-                               /* it was a SQL_C_CHAR */
-                               if (buf)
-                                       CVT_SPECIAL_CHARS(buf, 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(param_string);
+                       /* it was a numeric type */
+                       else if (param_string[0] != '\0')
+                               CVT_APPEND_STR(qb, param_string);
 
-                               /* it was date,time,timestamp -- use m,d,y,hh,mm,ss */
-                               else
-                               {
-                                       sprintf(tmp, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
-                                                       st.y, st.m, st.d, st.hh, st.mm, st.ss);
+                       /* it was date,time,timestamp -- use m,d,y,hh,mm,ss */
+                       else
+                       {
+                               sprintf(tmp, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
+                                               st.y, st.m, st.d, st.hh, st.mm, st.ss);
 
-                                       CVT_APPEND_STR(tmp);
-                               }
+                               CVT_APPEND_STR(qb, tmp);
+                       }
 
-                               CVT_APPEND_CHAR('\'');  /* Close Quote */
+                       CVT_APPEND_CHAR(qb, '\'');      /* Close Quote */
 
-                               break;
+                       break;
 
-                       case SQL_DATE:
+               case SQL_DATE:
 #if (ODBCVER >= 0x0300)
-                       case SQL_TYPE_DATE:     /* 91 */
+               case SQL_TYPE_DATE:     /* 91 */
 #endif
-                               if (buf)
-                               {                               /* copy char data to time */
-                                       my_strcpy(cbuf, sizeof(cbuf), buf, used);
-                                       parse_datetime(cbuf, &st);
-                               }
+                       if (buf)
+                       {                               /* copy char data to time */
+                               my_strcpy(cbuf, sizeof(cbuf), buf, used);
+                               parse_datetime(cbuf, &st);
+                       }
 
-                               sprintf(tmp, "'%.4d-%.2d-%.2d'::date", st.y, st.m, st.d);
+                       sprintf(tmp, "'%.4d-%.2d-%.2d'::date", st.y, st.m, st.d);
 
-                               CVT_APPEND_STR(tmp);
-                               break;
+                       CVT_APPEND_STR(qb, tmp);
+                       break;
 
-                       case SQL_TIME:
+               case SQL_TIME:
 #if (ODBCVER >= 0x0300)
-                       case SQL_TYPE_TIME:     /* 92 */
+               case SQL_TYPE_TIME:     /* 92 */
 #endif
-                               if (buf)
-                               {                               /* copy char data to time */
-                                       my_strcpy(cbuf, sizeof(cbuf), buf, used);
-                                       parse_datetime(cbuf, &st);
-                               }
+                       if (buf)
+                       {                               /* copy char data to time */
+                               my_strcpy(cbuf, sizeof(cbuf), buf, used);
+                               parse_datetime(cbuf, &st);
+                       }
 
-                               sprintf(tmp, "'%.2d:%.2d:%.2d'::time", st.hh, st.mm, st.ss);
+                       sprintf(tmp, "'%.2d:%.2d:%.2d'::time", st.hh, st.mm, st.ss);
 
-                               CVT_APPEND_STR(tmp);
-                               break;
+                       CVT_APPEND_STR(qb, tmp);
+                       break;
 
-                       case SQL_TIMESTAMP:
+               case SQL_TIMESTAMP:
 #if (ODBCVER >= 0x0300)
-                       case SQL_TYPE_TIMESTAMP:        /* 93 */
+               case SQL_TYPE_TIMESTAMP:        /* 93 */
 #endif
 
-                               if (buf)
-                               {
-                                       my_strcpy(cbuf, sizeof(cbuf), buf, used);
-                                       parse_datetime(cbuf, &st);
-                               }
+                       if (buf)
+                       {
+                               my_strcpy(cbuf, sizeof(cbuf), buf, used);
+                               parse_datetime(cbuf, &st);
+                       }
 
-                               /*
-                                * sprintf(tmp, "'%.4d-%.2d-%.2d %.2d:%.2d:%.2d'", st.y,
-                                * st.m, st.d, st.hh, st.mm, st.ss);
-                                */
-                               tmp[0] = '\'';
-                               /* Time zone stuff is unreliable */
-                               stime2timestamp(&st, tmp + 1, USE_ZONE, PG_VERSION_GE(conn, 7.2));
-                               strcat(tmp, "'::timestamp");
+                       /*
+                        * sprintf(tmp, "'%.4d-%.2d-%.2d %.2d:%.2d:%.2d'", st.y,
+                        * st.m, st.d, st.hh, st.mm, st.ss);
+                        */
+                       tmp[0] = '\'';
+                       /* Time zone stuff is unreliable */
+                       stime2timestamp(&st, tmp + 1, USE_ZONE, PG_VERSION_GE(conn, 7.2));
+                       strcat(tmp, "'::timestamp");
 
-                               CVT_APPEND_STR(tmp);
+                       CVT_APPEND_STR(qb, tmp);
 
-                               break;
+                       break;
 
-                       case SQL_BINARY:
-                       case SQL_VARBINARY:/* non-ascii characters should be
-                                                                * converted to octal */
-                               CVT_APPEND_CHAR('\'');  /* Open Quote */
+               case SQL_BINARY:
+               case SQL_VARBINARY:/* non-ascii characters should be
+                                                       * converted to octal */
+                       CVT_APPEND_CHAR(qb, '\'');      /* Open Quote */
 
-                               mylog("SQL_VARBINARY: about to call convert_to_pgbinary, used = %d\n", used);
+                       mylog("SQL_VARBINARY: about to call convert_to_pgbinary, used = %d\n", used);
 
-                               CVT_APPEND_BINARY(buf, used);
+                       CVT_APPEND_BINARY(qb, buf, used);
 
-                               CVT_APPEND_CHAR('\'');  /* Close Quote */
+                       CVT_APPEND_CHAR(qb, '\'');      /* Close Quote */
 
-                               break;
+                       break;
 
-                       case SQL_LONGVARBINARY:
+               case SQL_LONGVARBINARY:
 
-                               if (opts->parameters[param_number].data_at_exec)
-                                       lobj_oid = opts->parameters[param_number].lobj_oid;
-                               else
+                       if (opts->parameters[param_number].data_at_exec)
+                               lobj_oid = opts->parameters[param_number].lobj_oid;
+                       else
+                       {
+                               /* begin transaction if needed */
+                               if (!CC_is_in_trans(conn))
                                {
-                                       /* begin transaction if needed */
-                                       if (!CC_is_in_trans(conn))
+                                       if (!CC_begin(conn))
                                        {
-                                               if (!CC_begin(conn))
-                                               {
-                                                       stmt->errormsg = "Could not begin (in-line) a transaction";
-                                                       stmt->errornumber = STMT_EXEC_ERROR;
-                                                       SC_log_error(func, "", stmt);
-                                                       return SQL_ERROR;
-                                               }
-                                       }
-
-                                       /* store the oid */
-                                       lobj_oid = lo_creat(conn, INV_READ | INV_WRITE);
-                                       if (lobj_oid == 0)
-                                       {
-                                               stmt->errornumber = STMT_EXEC_ERROR;
-                                               stmt->errormsg = "Couldnt create (in-line) large object.";
-                                               SC_log_error(func, "", stmt);
+                                               qb->errormsg = "Could not begin (in-line) a transaction";
+                                               qb->errornumber = STMT_EXEC_ERROR;
                                                return SQL_ERROR;
                                        }
+                               }
 
-                                       /* store the fd */
-                                       lobj_fd = lo_open(conn, lobj_oid, INV_WRITE);
-                                       if (lobj_fd < 0)
-                                       {
-                                               stmt->errornumber = STMT_EXEC_ERROR;
-                                               stmt->errormsg = "Couldnt open (in-line) large object for writing.";
-                                               SC_log_error(func, "", stmt);
-                                               return SQL_ERROR;
-                                       }
+                               /* store the oid */
+                               lobj_oid = lo_creat(conn, INV_READ | INV_WRITE);
+                               if (lobj_oid == 0)
+                               {
+                                       qb->errornumber = STMT_EXEC_ERROR;
+                                       qb->errormsg = "Couldnt create (in-line) large object.";
+                                       return SQL_ERROR;
+                               }
 
-                                       retval = lo_write(conn, lobj_fd, buffer, used);
+                               /* store the fd */
+                               lobj_fd = lo_open(conn, lobj_oid, INV_WRITE);
+                               if (lobj_fd < 0)
+                               {
+                                       qb->errornumber = STMT_EXEC_ERROR;
+                                       qb->errormsg = "Couldnt open (in-line) large object for writing.";
+                                       return SQL_ERROR;
+                               }
 
-                                       lo_close(conn, lobj_fd);
+                               retval = lo_write(conn, lobj_fd, buffer, used);
 
-                                       /* commit transaction if needed */
-                                       if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
+                               lo_close(conn, lobj_fd);
+
+                               /* commit transaction if needed */
+                               if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
+                               {
+                                       if (!CC_commit(conn))
                                        {
-                                               if (!CC_commit(conn))
-                                               {
-                                                       stmt->errormsg = "Could not commit (in-line) a transaction";
-                                                       stmt->errornumber = STMT_EXEC_ERROR;
-                                                       SC_log_error(func, "", stmt);
-                                                       return SQL_ERROR;
-                                               }
+                                               qb->errormsg = "Could not commit (in-line) a transaction";
+                                               qb->errornumber = STMT_EXEC_ERROR;
+                                               return SQL_ERROR;
                                        }
                                }
+                       }
 
-                               /*
-                                * the oid of the large object -- just put that in for the
-                                * parameter marker -- the data has already been sent to
-                                * the large object
-                                */
-                               sprintf(param_string, "'%d'", lobj_oid);
-                               CVT_APPEND_STR(param_string);
+                       /*
+                        * the oid of the large object -- just put that in for the
+                        * parameter marker -- the data has already been sent to
+                        * the large object
+                        */
+                       sprintf(param_string, "'%d'", lobj_oid);
+                       CVT_APPEND_STR(qb, param_string);
 
-                               break;
+                       break;
 
-                               /*
-                                * because of no conversion operator for bool and int4,
-                                * SQL_BIT
-                                */
-                               /* must be quoted (0 or 1 is ok to use inside the quotes) */
+                       /*
+                        * because of no conversion operator for bool and int4,
+                        * SQL_BIT
+                        */
+                       /* must be quoted (0 or 1 is ok to use inside the quotes) */
 
-                       case SQL_REAL:
-                               if (buf)
-                                       my_strcpy(param_string, sizeof(param_string), buf, used);
-                               sprintf(tmp, "'%s'::float4", param_string);
-                               CVT_APPEND_STR(tmp);
-                               break;
-                       case SQL_FLOAT:
-                       case SQL_DOUBLE:
-                               if (buf)
-                                       my_strcpy(param_string, sizeof(param_string), buf, used);
-                               sprintf(tmp, "'%s'::float8", param_string);
-                               CVT_APPEND_STR(tmp);
-                               break;
-                       case SQL_NUMERIC:
-                               if (buf)
-                               {
-                                       cbuf[0] = '\'';
-                                       my_strcpy(cbuf + 1, sizeof(cbuf) - 12, buf, used);      /* 12 = 1('\'') +
-                                                                                                                                                * strlen("'::numeric")
-                                                                                                                                                * + 1('\0') */
-                                       strcat(cbuf, "'::numeric");
-                               }
-                               else
-                                       sprintf(cbuf, "'%s'::numeric", param_string);
-                               CVT_APPEND_STR(cbuf);
-                               break;
+               case SQL_REAL:
+                       if (buf)
+                               my_strcpy(param_string, sizeof(param_string), buf, used);
+                       sprintf(tmp, "'%s'::float4", param_string);
+                       CVT_APPEND_STR(qb, tmp);
+                       break;
+               case SQL_FLOAT:
+               case SQL_DOUBLE:
+                       if (buf)
+                               my_strcpy(param_string, sizeof(param_string), buf, used);
+                       sprintf(tmp, "'%s'::float8", param_string);
+                       CVT_APPEND_STR(qb, tmp);
+                       break;
+               case SQL_NUMERIC:
+                       if (buf)
+                       {
+                               cbuf[0] = '\'';
+                               my_strcpy(cbuf + 1, sizeof(cbuf) - 12, buf, used);      /* 12 = 1('\'') +
+                                                                                                                                       * strlen("'::numeric")
+                                                                                                                                       * + 1('\0') */
+                               strcat(cbuf, "'::numeric");
+                       }
+                       else
+                               sprintf(cbuf, "'%s'::numeric", param_string);
+                       CVT_APPEND_STR(qb, cbuf);
+                       break;
                        default:                        /* a numeric type or SQL_BIT */
-                               if (param_sqltype == SQL_BIT)
-                                       CVT_APPEND_CHAR('\'');          /* Open Quote */
+                       if (param_sqltype == SQL_BIT)
+                               CVT_APPEND_CHAR(qb, '\'');              /* Open Quote */
 
-                               if (buf)
+                       if (buf)
+                       {
+                               switch (used)
                                {
-                                       switch (used)
-                                       {
-                                               case SQL_NULL_DATA:
-                                                       break;
-                                               case SQL_NTS:
-                                                       CVT_APPEND_STR(buf);
-                                                       break;
-                                               default:
-                                                       CVT_APPEND_DATA(buf, used);
-                                       }
+                                       case SQL_NULL_DATA:
+                                               break;
+                                       case SQL_NTS:
+                                               CVT_APPEND_STR(qb, buf);
+                                               break;
+                                       default:
+                                               CVT_APPEND_DATA(qb, buf, used);
                                }
-                               else
-                                       CVT_APPEND_STR(param_string);
+                       }
+                       else
+                               CVT_APPEND_STR(qb, param_string);
 
-                               if (param_sqltype == SQL_BIT)
-                                       CVT_APPEND_CHAR('\'');          /* Close Quote */
+                       if (param_sqltype == SQL_BIT)
+                               CVT_APPEND_CHAR(qb, '\'');              /* Close Quote */
 
-                               break;
-               }
+                       break;
+       }
 #ifdef UNICODE_SUPPORT
-               if (allocbuf)
-                       free(allocbuf);
+       if (allocbuf)
+               free(allocbuf);
 #endif /* UNICODE_SUPPORT */
-       }                                                       /* end, for */
-
-       /* make sure new_statement is always null-terminated */
-       CVT_TERMINATE;
-
-       if (conn->DriverToDataSource != NULL)
-       {
-               int                     length = strlen(new_statement);
-
-               conn->DriverToDataSource(conn->translation_option,
-                                                                SQL_CHAR,
-                                                                new_statement, length,
-                                                                new_statement, length, NULL,
-                                                                NULL, 0, NULL);
-       }
-
-#ifdef DRIVER_CURSOR_IMPLEMENT
-       if (!stmt->load_statement && from_pos >=0)
-       {
-               stmt->load_statement = malloc(npos + 1);
-               memcpy(stmt->load_statement, new_statement, npos);
-               if (stmt->load_statement[npos - 1] == ';')
-                       stmt->load_statement[npos - 1] = '\0';
-               else
-                       stmt->load_statement[npos] = '\0';
-       }
-#endif   /* DRIVER_CURSOR_IMPLEMENT */
-       if (prepare_dummy_cursor && SC_is_pre_executable(stmt))
-       {
-               char            fetchstr[128];
-
-               sprintf(fetchstr, ";fetch backward in %s;close %s;",
-                               stmt->cursor_name, stmt->cursor_name);
-               if (begin_first && CC_is_in_autocommit(conn))
-                       strcat(fetchstr, "COMMIT;");
-               CVT_APPEND_STR(fetchstr);
-               stmt->inaccurate_result = TRUE;
-       }
-
        return SQL_SUCCESS;
 }
 
@@ -2122,120 +2398,224 @@ mapFunction(const char *func, int param_count)
        return NULL;
 }
 
+/*
+ * processParameters()
+ * Process function parameters and work with embedded escapes sequences.
+ */
+static int
+processParameters(QueryParse *qp, QueryBuild *qb,
+               UInt4 *output_count, Int4 param_pos[][2])
+{
+       static const char *func = "processParameters";
+       int retval, innerParenthesis, param_count;
+       BOOL stop;
 
-static int inner_convert_escape(const ConnectionClass *conn, const char *value, char *result, UInt4 maxLen, const char **input_resume, UInt4 *count);
-static int processParameters(const ConnectionClass *conn, const char *value, char *result, UInt4 maxLen, UInt4 *input_consumed, UInt4 *count, Int4 param_pos[][2]);
+       /* begin with outer '(' */
+       innerParenthesis = 0;
+       param_count = 0;
+       stop = FALSE;
+       for (; F_OldPos(qp) < qp->stmt_len; F_OldNext(qp))
+       {
+               retval = inner_process_tokens(qp, qb);
+               if (retval == SQL_ERROR)
+                       return retval;
+#ifdef MULTIBYTE
+               if (ENCODE_STATUS(qp->encstr) != 0)
+                       continue;
+#endif
+               if (qp->in_dquote || qp->in_quote || qp->in_escape)
+                       continue;
+
+               switch (F_OldChar(qp))
+               {
+                       case ',':
+                               if (1 == innerParenthesis)
+                               {
+                                       param_pos[param_count][1] = F_NewPos(qb) - 2;
+                                       param_count++;
+                                       param_pos[param_count][0] = F_NewPos(qb);
+                                       param_pos[param_count][1] = -1;
+                               }
+                               break;
+                       case '(':
+                               if (0 == innerParenthesis)
+                               {
+                                       param_pos[param_count][0] = F_NewPos(qb);
+                                       param_pos[param_count][1] = -1;
+                               }
+                               innerParenthesis++;
+                               break;
+     
+                       case ')':
+                               innerParenthesis--;
+                               if (0 == innerParenthesis)
+                               {
+                                       param_pos[param_count][1] = F_NewPos(qb) - 2;
+                                       param_count++;
+                                       param_pos[param_count][0] =
+                                       param_pos[param_count][1] = -1;
+                               }
+                               if (output_count)
+                                       *output_count = F_NewPos(qb);
+                               break;
+
+                       case '}':
+                               stop = (0 == innerParenthesis);
+                               break;
+
+               }
+               if (stop) /* returns with the last } position */
+                       break;
+       }
+       if (param_pos[param_count][0] >= 0)
+       {
+               mylog("%s closing ) not found %d\n", func, innerParenthesis);
+               qb->errornumber = STMT_EXEC_ERROR;
+               qb->errormsg = "processParameters closing ) not found";
+               return SQL_ERROR;
+       }
+       else if (1 == param_count) /* the 1 parameter is really valid ? */
+       {
+               BOOL    param_exist = FALSE;
+               int     i;
+
+               for (i = param_pos[0][0]; i <= param_pos[0][1]; i++)
+               {
+                       if (!isspace(qb->query_statement[i]))
+                       {
+                               param_exist = TRUE;
+                               break;
+                       }
+               }
+               if (!param_exist)
+               {
+                       param_pos[0][0] = param_pos[0][1] = -1;
+               }
+       }
+
+       return SQL_SUCCESS;
+}
 
 /*
- * inner_convert_escape()
- * work with embedded escapes sequences
+ * convert_escape()
+ * This function doesn't return a pointer to static memory any longer !
  */
-     
-static
-int inner_convert_escape(const ConnectionClass *conn, const char *value,
-               char *result, UInt4 maxLen, const char **input_resume,
-               UInt4 *count)
+static int
+convert_escape(QueryParse *qp, QueryBuild *qb)
 {
-       static const char *func = "inner_convert_escape";
-       int     subret, param_count;
-       char valnts[1024], params[1024];
-       char key[33], *end;
-       const char *valptr;
-       UInt4   vlen, prtlen, input_consumed, param_consumed, extra_len;
-       Int4    param_pos[16][2];
+       static const char *func = "convert_escape";
+       RETCODE retval = SQL_SUCCESS;
+       char            buf[1024], key[65];
+       unsigned char   ucv;
+       UInt4           prtlen;
  
-       valptr = value;
-       if (*valptr == '{') /* skip the first { */
-               valptr++;
+       if (F_OldChar(qp) == '{') /* skip the first { */
+               F_OldNext(qp);
        /* Separate off the key, skipping leading and trailing whitespace */
-       while ((*valptr != '\0') && isspace((unsigned char) *valptr))
-               valptr++;
-       sscanf(valptr, "%32s", key);
-       while ((*valptr != '\0') && (!isspace((unsigned char) *valptr)))
-               valptr++;
-       while ((*valptr != '\0') && isspace((unsigned char) *valptr))
-               valptr++;
-     
-       if (end = my_strchr(conn, valptr, '}'), NULL == end)
-       {
-               mylog("%s couldn't find the ending }\n",func);
-               return CONVERT_ESCAPE_ERROR;
-       }
-       if (vlen = (UInt4)(end - valptr), maxLen <= vlen)
-               return CONVERT_ESCAPE_OVERFLOW;
-       memcpy(valnts, valptr, vlen);
-       valnts[vlen] = '\0';
-       *input_resume = valptr + vlen; /* resume from the last } */
-       mylog("%s: key='%s', val='%s'\n", func, key, valnts);
-     
-       extra_len = 0;
-       if (isalnum(result[-1])) /* Avoid the concatenation of the function name with the previous word. Aceto */
+       while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))
+               F_OldNext(qp);
+       /*
+        * procedure calls
+        */
+       if (qp->statement_type == STMT_TYPE_PROCCALL)
        {
-               if (1 >= maxLen)
+               int     lit_call_len = 4;
+               ConnectionClass *conn = qb->conn;
+
+               /* '?=' to accept return values exists ? */
+               if (F_OldChar(qp) == '?')
+               {
+                       qb->param_number++;
+                       while (isspace((unsigned char) qp->statement[++qp->opos]));
+                       if (F_OldChar(qp) != '=')
+                       {
+                               F_OldPrior(qp);
+                               return SQL_SUCCESS;
+                       }
+                       while (isspace((unsigned char) qp->statement[++qp->opos]));
+               }
+               if (strnicmp(F_OldPtr(qp), "call", lit_call_len) ||
+                       !isspace((unsigned char) F_OldPtr(qp)[lit_call_len]))
                {
-                       mylog("%s %d bytes buffer overflow\n", func, maxLen);
-                       return CONVERT_ESCAPE_OVERFLOW;
+                       F_OldPrior(qp);
+                       return SQL_SUCCESS;
                }
-               *result = ' ';
-               result++;
-               *result = '\0';
-               maxLen--;
-               extra_len++;
+               qp->opos += lit_call_len;
+               CVT_APPEND_STR(qb, "SELECT ");
+               if (my_strchr(conn, F_OldPtr(qp), '('))
+                       qp->proc_no_param = FALSE;
+               return SQL_SUCCESS;
        }
+
+       sscanf(F_OldPtr(qp), "%32s", key);
+       while ((ucv = F_OldChar(qp)) != '\0' && (!isspace(ucv)))
+               F_OldNext(qp);
+       while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))
+               F_OldNext(qp);
+    
+       /* Avoid the concatenation of the function name with the previous word. Aceto */
+
+       if (F_NewPos(qb) > 0 && isalnum(F_NewPtr(qb)[-1]))
+               CVT_APPEND_CHAR(qb, ' ');
+       
        if (strcmp(key, "d") == 0)
        {
                /* Literal; return the escape part adding type cast */
-               prtlen = snprintf(result, maxLen, "%s::date", valnts);
+               F_ExtractOldTo(qp, buf, '}', sizeof(buf));
+               prtlen = snprintf(buf, sizeof(buf), "%s::date ", buf);
+               CVT_APPEND_DATA(qb, buf, prtlen);
        }
        else if (strcmp(key, "t") == 0)
        {
                /* Literal; return the escape part adding type cast */
-               prtlen = snprintf(result, maxLen, "%s::time", valnts);
+               F_ExtractOldTo(qp, buf, '}', sizeof(buf));
+               prtlen = snprintf(buf, sizeof(buf), "%s::time", buf);
+               CVT_APPEND_DATA(qb, buf, prtlen);
        }
        else if (strcmp(key, "ts") == 0)
        {
                /* Literal; return the escape part adding type cast */
-               if (PG_VERSION_LT(conn, 7.1))
-                       prtlen = snprintf(result, maxLen, "%s::datetime", valnts);
+               F_ExtractOldTo(qp, buf, '}', sizeof(buf));
+               if (PG_VERSION_LT(qb->conn, 7.1))
+                       prtlen = snprintf(buf, sizeof(buf), "%s::datetime", buf);
                else
-                       prtlen = snprintf(result, maxLen, "%s::timestamp", valnts);
+                       prtlen = snprintf(buf, sizeof(buf), "%s::timestamp", buf);
+               CVT_APPEND_DATA(qb, buf, prtlen);
        }
        else if (strcmp(key, "oj") == 0) /* {oj syntax support for 7.1 * servers */
        {
-               /* Literal; return the escape part as-is */
-               strncpy(result, valnts, maxLen);
-               prtlen = vlen; 
+               F_OldPrior(qp);
+               return SQL_SUCCESS; /* Continue at inner_process_tokens loop */
        }
        else if (strcmp(key, "fn") == 0)
        {
-               /*
-                * Function invocation Separate off the func name, skipping
-                * trailing whitespace.
-                */
-               char    *funcEnd = valnts;
-               char     svchar;
-               const char      *mapExpr;
-     
-               params[sizeof(params)-1] = '\0';
-
-               while ((*funcEnd != '\0') && (*funcEnd != '(') &&
-                       (!isspace((unsigned char) *funcEnd)))
-                       funcEnd++;
-               svchar = *funcEnd;
-               *funcEnd = '\0';
-               sscanf(valnts, "%32s", key);
-               *funcEnd = svchar;
-               while ((*funcEnd != '\0') && isspace((unsigned char) *funcEnd))
-                       funcEnd++;
+               QueryBuild      nqb;
+               const char *mapExpr;
+               int     i, param_count;
+               UInt4   param_consumed;
+               Int4    param_pos[16][2];
+
+               /* Separate off the func name, skipping leading and trailing whitespace */
+               i = 0;
+               while ((ucv = F_OldChar(qp)) != '\0' && ucv != '(' &&
+                          (!isspace(ucv)))
+               {
+                       if (i < sizeof(key)-1)
+                               key[i++] = ucv;
+                       F_OldNext(qp);
+               }
+               key[i] = '\0';
+               while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))
+                       F_OldNext(qp);
 
                /*
                 * We expect left parenthesis here, else return fn body as-is
                 * since it is one of those "function constants".
                 */
-               if (*funcEnd != '(')
+               if (F_OldChar(qp) != '(')
                {
-                       strncpy(result, valnts, maxLen);
-                       return CONVERT_ESCAPE_OK;
+                       CVT_APPEND_STR(qb, key);
+                       return SQL_SUCCESS;
                }
 
                /*
@@ -2244,9 +2624,14 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
                 * Aceto 2002-01-29
                 */
 
-               valptr += (UInt4)(funcEnd - valnts);
-               if (subret = processParameters(conn, valptr, params, sizeof(params) - 1, &input_consumed, &param_consumed, param_pos), CONVERT_ESCAPE_OK != subret) 
-                       return CONVERT_ESCAPE_ERROR;
+               QB_initialize_copy(&nqb, qb, 1024);
+               if (retval = processParameters(qp, &nqb, &param_consumed, param_pos), retval == SQL_ERROR)
+               {
+                       qb->errornumber = nqb.errornumber;
+                       qb->errormsg = nqb.errormsg;
+                       QB_Destructor(&nqb);
+                       return retval;
+               }
 
                for (param_count = 0;; param_count++)
                {
@@ -2256,10 +2641,13 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
                if (param_count == 1 &&
                    param_pos[0][1] < param_pos[0][0])
                        param_count = 0;
-               
+
                mapExpr = mapFunction(key, param_count);
                if (mapExpr == NULL)
-                       prtlen = snprintf(result, maxLen, "%s%s", key, params);
+               {
+                       CVT_APPEND_STR(qb, key);
+                       CVT_APPEND_DATA(qb, nqb.query_statement, nqb.npos);
+               }
                else
                {
                        const char *mapptr;
@@ -2267,15 +2655,9 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
 
                        for (prtlen = 0, mapptr = mapExpr; *mapptr; mapptr++)
                        {
-                               if (prtlen + 1 >= maxLen) /* buffer overflow */
-                               {
-                                       result[prtlen] = '\0';
-                                       prtlen++;
-                                       break;
-                               }
                                if (*mapptr != '$')
                                {
-                                       result[prtlen++] = *mapptr;
+                                       CVT_APPEND_CHAR(qb, *mapptr);
                                        continue;
                                }
                                mapptr++;
@@ -2290,215 +2672,49 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
                                        if (pidx < 0 ||
                                            param_pos[pidx][0] < 0)
                                        {
+                                               qb->errornumber = STMT_EXEC_ERROR;
+                                               qb->errormsg = "param not found";
                                                qlog("%s %dth param not found for the expression %s\n", pidx + 1, mapExpr);
-                                               return CONVERT_ESCAPE_ERROR;
+                                               retval = SQL_ERROR;
+                                               break;
                                        }
                                        from = param_pos[pidx][0];
                                        to = param_pos[pidx][1];
                                }
                                else
                                {
+                                       qb->errornumber = STMT_EXEC_ERROR;
+                                       qb->errormsg = "internal expression error";
                                        qlog("%s internal expression error %s\n", func, mapExpr);
-                                       return CONVERT_ESCAPE_ERROR;
-                               }
-                               paramlen = to - from + 1;
-                               if (prtlen + paramlen >= maxLen) /* buffer overflow */
-                               {
-                                       prtlen = maxLen;
+                                       retval = SQL_ERROR;
                                        break;
                                }
+                               paramlen = to - from + 1;
                                if (paramlen > 0)
-                                       memcpy(&result[prtlen], params + from, paramlen);
-                               prtlen += paramlen;
+                                       CVT_APPEND_DATA(qb, nqb.query_statement+ from, paramlen);
                        }
-                       if (prtlen < maxLen)
-                               result[prtlen] = '\0';
-                       /** prtlen = snprintf(result, maxLen, "%s%s", mapExpr, params); **/
                }
-               valptr += input_consumed;
-               *input_resume = valptr;
-       }
-       else
-       {
-               /* Bogus key, leave untranslated */
-               return CONVERT_ESCAPE_ERROR;
-       }
-     
-       if (count)
-               *count = prtlen + extra_len;
-       if (prtlen < 0 || prtlen >= maxLen) /* buffer overflow */
-       {
-               mylog("%s %d bytes buffer overflow\n", func, maxLen);
-               return CONVERT_ESCAPE_OVERFLOW;
-       }
-       return CONVERT_ESCAPE_OK;
-}
-     
-/*
- * processParameters()
- * Process function parameters and work with embedded escapes sequences.
- */
-     
-static
-int processParameters(const ConnectionClass *conn, const char *value,
-               char *result, UInt4 maxLen, UInt4 *input_consumed,
-               UInt4 *output_count, Int4 param_pos[][2])
-{
-       int             innerParenthesis, subret, param_count;
-       UInt4   ipos, count, inner_count;
-       unsigned char   stop;
-       const char      *valptr;
-       char    buf[1024];
-       BOOL    in_quote, in_dquote, in_escape, leadingSpace;
-#ifdef MULTIBYTE
-       encoded_str     encstr;
-#endif   /* MULTIBYTE */
-       buf[sizeof(buf)-1] = '\0';
-       innerParenthesis = 0;
-       in_quote = in_dquote = in_escape = leadingSpace = FALSE;
-       param_count = 0;
-#ifdef MULTIBYTE
-       make_encoded_str(&encstr, conn, value);
-#endif /* MULTIBYTE */
-       /* begin with outer '(' */
-       for (stop = FALSE, valptr = value, ipos = count = 0; *valptr != '\0'; ipos++, valptr++)
-       {
-               if (leadingSpace)
-               {
-                       if (isspace(*valptr))
-                               continue;
-                       leadingSpace = FALSE;
-               }
-               if (count + 1 >= maxLen) /* buffer overflow */
-               {
-                       *input_consumed = 0;
-                       result[count++] = '\0';
-                       return CONVERT_ESCAPE_OVERFLOW;
-               }
-#ifdef MULTIBYTE
-               encoded_byte_check(&encstr, ipos);
-               if (ENCODE_STATUS(encstr) != 0)
+               if (0 == qb->errornumber)
                {
-                       result[count++] = *valptr;
-                       continue;
+                       qb->errornumber = nqb.errornumber;
+                       qb->errormsg = nqb.errormsg;
                }
-               /*
-                * From here we are guaranteed to handle a 1-byte character.
-                */
-#endif
-               if (in_quote)
+               if (SQL_ERROR != retval)
                {
-                       if (in_escape)
-                               in_escape = FALSE;
-                       else if (*valptr == '\\')
-                               in_escape = TRUE;
-                       else if (*valptr == '\'')
-                               in_quote = FALSE;
-                       result[count++] = *valptr;
-                       continue;
+                       qb->param_number = nqb.param_number;
+                       qb->flags = nqb.flags;
                }
-               else if (in_dquote)
-               {
-                       if (*valptr == '\"')
-                               in_dquote = FALSE;
-                       result[count++] = *valptr;
-                       continue;
-               }
-               switch (*valptr)
-               {
-                       case '\'':
-                               in_quote = TRUE;
-                               break;
-                       case '\"':
-                               in_dquote = TRUE;
-                               break;
-                       case ',':
-                               if (1 == innerParenthesis)
-                               {
-                                       param_pos[param_count][1] = count - 1;
-                                       param_count++;
-                                       param_pos[param_count][0] = count + 1;
-                                       param_pos[param_count][1] = -1;
-                                       leadingSpace = TRUE;
-                               }
-                               break;
-                       case '(':
-                               if (0 == innerParenthesis)
-                               {
-                                       param_pos[param_count][0] = count + 1;
-                                       param_pos[param_count][1] = -1;
-                                       leadingSpace = TRUE;
-                               }
-                               innerParenthesis++;
-                               break;
-     
-                       case ')':
-                               innerParenthesis--;
-                               if (0 == innerParenthesis)
-                               {
-                                       param_pos[param_count][1] = count - 1;
-                                       param_count++;
-                                       param_pos[param_count][0] =
-                                       param_pos[param_count][1] = -1;
-                               }
-                               break;
-     
-                       case '}':
-                               stop = TRUE;
-                               break;
-     
-                       case '{':
-                               if (subret = inner_convert_escape(conn, valptr, buf, sizeof(buf) - 1, &valptr, &inner_count), CONVERT_ESCAPE_OK != subret)
-                                       return CONVERT_ESCAPE_ERROR;
-     
-                               if (inner_count + count >= maxLen)
-                                       return CONVERT_ESCAPE_OVERFLOW;
-                               memcpy(&result[count], buf, inner_count); 
-                               count += inner_count;
-                               ipos = (UInt4) (valptr - value);
-                               continue;
-               }
-               if (stop) /* returns with the last } position */
-                       break;
-               result[count++] = *valptr;
+               QB_Destructor(&nqb);
        }
-       if (param_pos[param_count][0] >= 0)
-       {
-               mylog("processParameters closing ) not found %d\n", innerParenthesis);
-               return CONVERT_ESCAPE_ERROR;
-       }
-       result[count] = '\0';
-       *input_consumed = ipos;
-       if (output_count)
-               *output_count = count;
-       return CONVERT_ESCAPE_OK;
-}
-     
-/*
- * convert_escape()
- * This function returns a pointer to static memory!
- */
-     
-int
-convert_escape(const char *value, StatementClass *stmt, int *npos, int *stsize, const char **val_resume)
-{
-       int     ret, pos = *npos;
-       UInt4   count;
-
-       while (ret = inner_convert_escape(SC_get_conn(stmt), value,
-               stmt->stmt_with_params + pos, *stsize - pos, val_resume, &count),
-               CONVERT_ESCAPE_OVERFLOW == ret)
+       else
        {
-               if ((*stsize = enlarge_statement(stmt, *stsize * 2)) <= 0)
-                       return CONVERT_ESCAPE_ERROR;
+               /* Bogus key, leave untranslated */
+               return SQL_ERROR;
        }
-       if (CONVERT_ESCAPE_OK == ret)
-               *npos += count;
-       return ret;
+       return retval;
 }
 
-
 BOOL
 convert_money(const char *s, char *sout, size_t soutmax)
 {
@@ -2540,6 +2756,8 @@ parse_datetime(const char *buf, SIMPLE_TIME *st)
        int                     nf;
 
        y = m = d = hh = mm = ss = 0;
+       st->fr = 0;
+       st->infinity = 0;
 
        /* escape sequence ? */
        if (buf[0] == '{')
index 1ca0b1bb0c94e251271eaccf2b4554b0ffc4ebf2..8f65472e1f27d916214eee750ccf8bf08a28ac97 100644 (file)
@@ -40,8 +40,6 @@ int copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, I
                                           PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue);
 
 int                    copy_statement_with_parameters(StatementClass *stmt);
-int            convert_escape(const char *value, StatementClass *stmt,
-                       int *npos, int *stsize, const char **val_resume);
 BOOL           convert_money(const char *s, char *sout, size_t soutmax);
 char           parse_datetime(const char *buf, SIMPLE_TIME *st);
 int                    convert_linefeeds(const char *s, char *dst, size_t max, BOOL convlf, BOOL *changed);