aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/odbc/convert.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/odbc/convert.c')
-rw-r--r--src/interfaces/odbc/convert.c2096
1 files changed, 1157 insertions, 939 deletions
diff --git a/src/interfaces/odbc/convert.c b/src/interfaces/odbc/convert.c
index 39998cc0c57..433f4b3fe17 100644
--- a/src/interfaces/odbc/convert.c
+++ b/src/interfaces/odbc/convert.c
@@ -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)
+ if (0 == qb->errornumber)
{
- 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;
+ qb->errornumber = STMT_EXEC_ERROR;
+ qb->errormsg = "ODBC escape convert error";
}
- if (convert_escape(begin, stmt, &npos, &new_stsize, &end
-) != CONVERT_ESCAPE_OK)
- {
- stmt->errormsg = "ODBC escape convert error";
- stmt->errornumber = STMT_EXEC_ERROR;
- return SQL_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)
- {
- CVT_APPEND_STR("NULL");
- stmt->inaccurate_result = TRUE;
- continue;
}
- else
+ else if (qp->prev_token_end)
{
- 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;
- /* Assign correct buffers based on data at exec param or not */
- if (opts->parameters[param_number].data_at_exec)
+ return SQL_SUCCESS;
+}
+
+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)
+ {
+ CVT_APPEND_STR(qb, "NULL");
+ return SQL_SUCCESS;
+ }
- /* Handle NULL parameter data */
- if (used == SQL_NULL_DATA)
+ /*
+ * 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))
- {
- 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)
+ if (!CC_begin(conn))
{
- 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;
+
+ /* 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;
-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]);
+ }
+ 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) == '?')
{
- mylog("%s %d bytes buffer overflow\n", func, maxLen);
- return CONVERT_ESCAPE_OVERFLOW;
+ 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]));
}
- *result = ' ';
- result++;
- *result = '\0';
- maxLen--;
- extra_len++;
+ if (strnicmp(F_OldPtr(qp), "call", lit_call_len) ||
+ !isspace((unsigned char) F_OldPtr(qp)[lit_call_len]))
+ {
+ F_OldPrior(qp);
+ return SQL_SUCCESS;
+ }
+ 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 (0 == qb->errornumber)
{
- if (isspace(*valptr))
- continue;
- leadingSpace = FALSE;
+ qb->errornumber = nqb.errornumber;
+ qb->errormsg = nqb.errormsg;
}
- if (count + 1 >= maxLen) /* buffer overflow */
+ if (SQL_ERROR != retval)
{
- *input_consumed = 0;
- result[count++] = '\0';
- return CONVERT_ESCAPE_OVERFLOW;
- }
-#ifdef MULTIBYTE
- encoded_byte_check(&encstr, ipos);
- if (ENCODE_STATUS(encstr) != 0)
- {
- result[count++] = *valptr;
- continue;
- }
- /*
- * From here we are guaranteed to handle a 1-byte character.
- */
-#endif
- if (in_quote)
- {
- if (in_escape)
- in_escape = FALSE;
- else if (*valptr == '\\')
- in_escape = TRUE;
- else if (*valptr == '\'')
- in_quote = FALSE;
- result[count++] = *valptr;
- continue;
- }
- 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;
+ qb->param_number = nqb.param_number;
+ qb->flags = nqb.flags;
}
- if (stop) /* returns with the last } position */
- break;
- result[count++] = *valptr;
- }
- if (param_pos[param_count][0] >= 0)
- {
- mylog("processParameters closing ) not found %d\n", innerParenthesis);
- return CONVERT_ESCAPE_ERROR;
+ QB_Destructor(&nqb);
}
- 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] == '{')