diff options
author | Hiroshi Inoue <inoue@tpf.co.jp> | 2002-01-11 02:50:01 +0000 |
---|---|---|
committer | Hiroshi Inoue <inoue@tpf.co.jp> | 2002-01-11 02:50:01 +0000 |
commit | f43b5de649cdf8a36f7d90a96932800cb0e34162 (patch) | |
tree | 6fb1ec57cff266680ab2adaf8c0976a643627b7c /src/interfaces/odbc/windev/parse.c | |
parent | 5370cd6b03610bdb6c6dee0fbf87ad9cdf524395 (diff) |
Add a directory to save the changes until 7.3-tree is branched.
Diffstat (limited to 'src/interfaces/odbc/windev/parse.c')
-rw-r--r-- | src/interfaces/odbc/windev/parse.c | 954 |
1 files changed, 954 insertions, 0 deletions
diff --git a/src/interfaces/odbc/windev/parse.c b/src/interfaces/odbc/windev/parse.c new file mode 100644 index 00000000000..e73cb82a325 --- /dev/null +++ b/src/interfaces/odbc/windev/parse.c @@ -0,0 +1,954 @@ +/*-------- + * Module: parse.c + * + * Description: This module contains routines related to parsing SQL + * statements. This can be useful for two reasons: + * + * 1. So the query does not actually have to be executed + * to return data about it + * + * 2. To be able to return information about precision, + * nullability, aliases, etc. in the functions + * SQLDescribeCol and SQLColAttributes. Currently, + * Postgres doesn't return any information about + * these things in a query. + * + * Classes: none + * + * API functions: none + * + * Comments: See "notice.txt" for copyright and license information. + *-------- + */ +/* Multibyte support Eiji Tokuya 2001-03-15 */ + +#include "psqlodbc.h" + +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include "statement.h" +#include "connection.h" +#include "qresult.h" +#include "pgtypes.h" +#include "pgapifunc.h" + +#ifdef MULTIBYTE +#include "multibyte.h" +#endif + +#define FLD_INCR 32 +#define TAB_INCR 8 +#define COL_INCR 16 + +char *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric); +void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k); +char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi); + + +char * +getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric) +{ + int i = 0; + int out = 0; + char qc, + in_escape = FALSE; + + if (smax <= 1) + return NULL; + + smax--; + + /* skip leading delimiters */ + while (isspace((unsigned char) s[i]) || s[i] == ',') + { + /* mylog("skipping '%c'\n", s[i]); */ + i++; + } + + if (s[i] == '\0') + { + token[0] = '\0'; + return NULL; + } + + if (quote) + *quote = FALSE; + if (dquote) + *dquote = FALSE; + if (numeric) + *numeric = FALSE; + + /* get the next token */ + while (!isspace((unsigned char) s[i]) && s[i] != ',' && + s[i] != '\0' && out != smax) + { +#ifdef MULTIBYTE + if (multibyte_char_check(s[i]) != 0) + { + token[out++] = s[i++]; + continue; + } +#endif + /* Handle quoted stuff */ + if (out == 0 && (s[i] == '\"' || s[i] == '\'')) + { + qc = s[i]; + if (qc == '\"') + { + if (dquote) + *dquote = TRUE; + } + if (qc == '\'') + { + if (quote) + *quote = TRUE; + } + + i++; /* dont return the quote */ + while (s[i] != '\0' && out != smax) + { +#ifdef MULTIBYTE + if (multibyte_char_check(s[i]) != 0) + { + token[out++] = s[i++]; + continue; + } +#endif + if (s[i] == qc && !in_escape) + break; + if (s[i] == '\\' && !in_escape) + in_escape = TRUE; + else + { + in_escape = FALSE; + token[out++] = s[i]; + } + i++; + } + if (s[i] == qc) + i++; + break; + } + + /* Check for numeric literals */ + if (out == 0 && isdigit((unsigned char) s[i])) + { + if (numeric) + *numeric = TRUE; + token[out++] = s[i++]; + while (isalnum((unsigned char) s[i]) || s[i] == '.') + token[out++] = s[i++]; + + break; + } + + if (ispunct((unsigned char) s[i]) && s[i] != '_') + { + mylog("got ispunct: s[%d] = '%c'\n", i, s[i]); + + if (out == 0) + { + token[out++] = s[i++]; + break; + } + else + break; + } + + if (out != smax) + token[out++] = s[i]; + + i++; + } + + /* mylog("done -- s[%d] = '%c'\n", i, s[i]); */ + + token[out] = '\0'; + + /* find the delimiter */ + while (isspace((unsigned char) s[i])) + i++; + + /* return the most priority delimiter */ + if (s[i] == ',') + { + if (delim) + *delim = s[i]; + } + else if (s[i] == '\0') + { + if (delim) + *delim = '\0'; + } + else + { + if (delim) + *delim = ' '; + } + + /* skip trailing blanks */ + while (isspace((unsigned char) s[i])) + i++; + + return &s[i]; +} + + +#if 0 +QR_set_num_fields(stmt->result, 14); +QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); +QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); +QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); +QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); +QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2); +QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); +QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4); +QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4); +QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2); +QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2); +QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2); +QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254); +/* User defined fields */ +QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4); +QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4); +#endif + +void +getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k) +{ + char *str; + + if (fi->name[0] == '\0') + strcpy(fi->name, QR_get_value_manual(col_info->result, k, 3)); + + fi->type = atoi(QR_get_value_manual(col_info->result, k, 13)); + fi->precision = atoi(QR_get_value_manual(col_info->result, k, 6)); + fi->length = atoi(QR_get_value_manual(col_info->result, k, 7)); + if (str = QR_get_value_manual(col_info->result, k, 8), str) + fi->scale = atoi(str); + else + fi->scale = -1; + fi->nullable = atoi(QR_get_value_manual(col_info->result, k, 10)); + fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12)); +} + + +char +searchColInfo(COL_INFO *col_info, FIELD_INFO *fi) +{ + int k, + cmp; + char *col; + + for (k = 0; k < QR_get_num_tuples(col_info->result); k++) + { + col = QR_get_value_manual(col_info->result, k, 3); + if (fi->dquote) + cmp = strcmp(col, fi->name); + else + cmp = stricmp(col, fi->name); + if (!cmp) + { + if (!fi->dquote) + strcpy(fi->name, col); + getColInfo(col_info, fi, k); + + mylog("PARSE: searchColInfo: \n"); + return TRUE; + } + } + + return FALSE; +} + + +char +parse_statement(StatementClass *stmt) +{ + static char *func = "parse_statement"; + char token[256]; + char delim, + quote, + dquote, + numeric, + unquoted; + char *ptr, + *pptr = NULL; + char in_select = FALSE, + in_distinct = FALSE, + in_on = FALSE, + in_from = FALSE, + from_found = FALSE, + in_where = FALSE, + in_table = FALSE; + char in_field = FALSE, + in_expr = FALSE, + in_func = FALSE, + in_dot = FALSE, + in_as = FALSE; + int j, + i, + k = 0, + n, + first_where = 0, + blevel = 0; + FIELD_INFO **fi; + TABLE_INFO **ti; + char parse; + ConnectionClass *conn = stmt->hdbc; + HSTMT hcol_stmt; + StatementClass *col_stmt; + RETCODE result; + + mylog("%s: entering...\n", func); + + ptr = stmt->statement; + fi = stmt->fi; + ti = stmt->ti; + + stmt->nfld = 0; + stmt->ntab = 0; + +#ifdef MULTIBYTE + multibyte_init(); +#endif + while (pptr = ptr, (ptr = getNextToken(pptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL) + { + unquoted = !(quote || dquote); + + mylog("unquoted=%d, quote=%d, dquote=%d, numeric=%d, delim='%c', token='%s', ptr='%s'\n", unquoted, quote, dquote, numeric, delim, token, ptr); + + if (in_select && unquoted && blevel == 0) + { + if (!stricmp(token, "distinct")) + { + in_distinct = TRUE; + + mylog("DISTINCT\n"); + continue; + } + if (!stricmp(token, "into")) + { + in_select = FALSE; + mylog("INTO\n"); + stmt->statement_type = STMT_TYPE_CREATE; + stmt->parse_status = STMT_PARSE_FATAL; + return FALSE; + } + if (!stricmp(token, "from")) + { + in_select = FALSE; + in_from = TRUE; + if (!from_found && + (!strnicmp(pptr, "from", 4))) + { + mylog("First "); + from_found = TRUE; + } + + mylog("FROM\n"); + continue; + } + } + if (unquoted && blevel == 0) + { + if ((!stricmp(token, "where") || + !stricmp(token, "union") || + !stricmp(token, "intersect") || + !stricmp(token, "except") || + !stricmp(token, "order") || + !stricmp(token, "group") || + !stricmp(token, "having"))) + { + in_select = FALSE; + in_from = FALSE; + in_where = TRUE; + + if (!first_where && + (!stricmp(token, "where"))) + first_where = ptr - stmt->statement; + + mylog("WHERE...\n"); + break; + } + } + if (in_select && (in_expr || in_func)) + { + /* just eat the expression */ + mylog("in_expr=%d or func=%d\n", in_expr, in_func); + + if (unquoted) + { + if (token[0] == '(') + { + blevel++; + mylog("blevel++ = %d\n", blevel); + } + else if (token[0] == ')') + { + blevel--; + mylog("blevel-- = %d\n", blevel); + } + } + if (blevel == 0) + { + if (delim == ',') + { + mylog("**** Got comma in_expr/func\n"); + in_func = FALSE; + in_expr = FALSE; + in_field = FALSE; + } + else if (unquoted && !stricmp(token, "as")) + { + mylog("got AS in_expr\n"); + in_func = FALSE; + in_expr = FALSE; + in_as = TRUE; + in_field = TRUE; + } + } + continue; + } + + if (unquoted && !stricmp(token, "select")) + { + in_select = TRUE; + + mylog("SELECT\n"); + continue; + } + if (in_select) + { + if (in_distinct) + { + mylog("in distinct\n"); + + if (unquoted && !stricmp(token, "on")) + { + in_on = TRUE; + mylog("got on\n"); + continue; + } + if (in_on) + { + in_distinct = FALSE; + in_on = FALSE; + continue; /* just skip the unique on field */ + } + mylog("done distinct\n"); + in_distinct = FALSE; + } + + if (!in_field) + { + if (!token[0]) + continue; + + if (!(stmt->nfld % FLD_INCR)) + { + mylog("reallocing at nfld=%d\n", stmt->nfld); + fi = (FIELD_INFO **) realloc(fi, (stmt->nfld + FLD_INCR) * sizeof(FIELD_INFO *)); + if (!fi) + { + stmt->parse_status = STMT_PARSE_FATAL; + return FALSE; + } + stmt->fi = fi; + } + + fi[stmt->nfld] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO)); + if (fi[stmt->nfld] == NULL) + { + stmt->parse_status = STMT_PARSE_FATAL; + return FALSE; + } + + /* Initialize the field info */ + memset(fi[stmt->nfld], 0, sizeof(FIELD_INFO)); + + /* double quotes are for qualifiers */ + if (dquote) + fi[stmt->nfld]->dquote = TRUE; + + if (quote) + { + fi[stmt->nfld]->quote = TRUE; + fi[stmt->nfld]->precision = strlen(token); + } + else if (numeric) + { + mylog("**** got numeric: nfld = %d\n", stmt->nfld); + fi[stmt->nfld]->numeric = TRUE; + } + else if (token[0] == '(') + { /* expression */ + mylog("got EXPRESSION\n"); + fi[stmt->nfld++]->expr = TRUE; + in_expr = TRUE; + blevel = 1; + continue; + } + else + { + strcpy(fi[stmt->nfld]->name, token); + fi[stmt->nfld]->dot[0] = '\0'; + } + mylog("got field='%s', dot='%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->dot); + + if (delim == ',') + mylog("comma (1)\n"); + else + in_field = TRUE; + stmt->nfld++; + continue; + } + + /* + * We are in a field now + */ + if (in_dot) + { + stmt->nfld--; + strcpy(fi[stmt->nfld]->dot, fi[stmt->nfld]->name); + strcpy(fi[stmt->nfld]->name, token); + stmt->nfld++; + in_dot = FALSE; + + if (delim == ',') + { + mylog("in_dot: got comma\n"); + in_field = FALSE; + } + continue; + } + + if (in_as) + { + stmt->nfld--; + strcpy(fi[stmt->nfld]->alias, token); + mylog("alias for field '%s' is '%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->alias); + in_as = FALSE; + in_field = FALSE; + + stmt->nfld++; + + if (delim == ',') + mylog("comma(2)\n"); + continue; + } + + /* Function */ + if (token[0] == '(') + { + in_func = TRUE; + blevel = 1; + fi[stmt->nfld - 1]->func = TRUE; + + /* + * name will have the function name -- maybe useful some + * day + */ + mylog("**** got function = '%s'\n", fi[stmt->nfld - 1]->name); + continue; + } + + if (token[0] == '.') + { + in_dot = TRUE; + mylog("got dot\n"); + continue; + } + + if (!stricmp(token, "as")) + { + in_as = TRUE; + mylog("got AS\n"); + continue; + } + + /* otherwise, it's probably an expression */ + in_expr = TRUE; + fi[stmt->nfld - 1]->expr = TRUE; + fi[stmt->nfld - 1]->name[0] = '\0'; + fi[stmt->nfld - 1]->precision = 0; + mylog("*** setting expression\n"); + } + + if (in_from) + { + if (!in_table) + { + if (!token[0]) + continue; + + if (!(stmt->ntab % TAB_INCR)) + { + ti = (TABLE_INFO **) realloc(ti, (stmt->ntab + TAB_INCR) * sizeof(TABLE_INFO *)); + if (!ti) + { + stmt->parse_status = STMT_PARSE_FATAL; + return FALSE; + } + stmt->ti = ti; + } + ti[stmt->ntab] = (TABLE_INFO *) malloc(sizeof(TABLE_INFO)); + if (ti[stmt->ntab] == NULL) + { + stmt->parse_status = STMT_PARSE_FATAL; + return FALSE; + } + + ti[stmt->ntab]->alias[0] = '\0'; + + strcpy(ti[stmt->ntab]->name, token); + if (!dquote) + { + char *ptr; + + /* lower case table name */ + for (ptr = ti[stmt->ntab]->name; *ptr; ptr++) + { +#ifdef MULTIBYTE + if ((unsigned char) *ptr >= 0x80) + ptr++; + else +#endif /* MULTIBYTE */ + *ptr = tolower((unsigned char) *ptr); + } + } + mylog("got table = '%s'\n", ti[stmt->ntab]->name); + + if (delim == ',') + mylog("more than 1 tables\n"); + else + in_table = TRUE; + stmt->ntab++; + continue; + } + + strcpy(ti[stmt->ntab - 1]->alias, token); + mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab - 1]->name, ti[stmt->ntab - 1]->alias); + in_table = FALSE; + if (delim == ',') + mylog("more than 1 tables\n"); + } + } + + /* + * Resolve any possible field names with tables + */ + + parse = TRUE; + + /* Resolve field names with tables */ + for (i = 0; i < stmt->nfld; i++) + { + if (fi[i]->func || fi[i]->expr || fi[i]->numeric) + { + fi[i]->ti = NULL; + fi[i]->type = -1; + parse = FALSE; + continue; + } + else if (fi[i]->quote) + { /* handle as text */ + fi[i]->ti = NULL; + + /* + * fi[i]->type = PG_TYPE_TEXT; fi[i]->precision = 0; the + * following may be better + */ + fi[i]->type = PG_TYPE_UNKNOWN; + if (fi[i]->precision == 0) + { + fi[i]->type = PG_TYPE_VARCHAR; + fi[i]->precision = 254; + } + fi[i]->length = fi[i]->precision; + continue; + } + /* it's a dot, resolve to table or alias */ + else if (fi[i]->dot[0]) + { + for (k = 0; k < stmt->ntab; k++) + { + if (!stricmp(ti[k]->name, fi[i]->dot)) + { + fi[i]->ti = ti[k]; + break; + } + else if (!stricmp(ti[k]->alias, fi[i]->dot)) + { + fi[i]->ti = ti[k]; + break; + } + } + } + else if (stmt->ntab == 1) + fi[i]->ti = ti[0]; + } + + mylog("--------------------------------------------\n"); + mylog("nfld=%d, ntab=%d\n", stmt->nfld, stmt->ntab); + + for (i = 0; i < stmt->nfld; i++) + { + mylog("Field %d: expr=%d, func=%d, quote=%d, dquote=%d, numeric=%d, name='%s', alias='%s', dot='%s'\n", i, fi[i]->expr, fi[i]->func, fi[i]->quote, fi[i]->dquote, fi[i]->numeric, fi[i]->name, fi[i]->alias, fi[i]->dot); + if (fi[i]->ti) + mylog(" ----> table_name='%s', table_alias='%s'\n", fi[i]->ti->name, fi[i]->ti->alias); + } + + for (i = 0; i < stmt->ntab; i++) + mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias); + + + /* + * Now save the SQLColumns Info for the parse tables + */ + + /* Call SQLColumns for each table and store the result */ + for (i = 0; i < stmt->ntab; i++) + { + /* See if already got it */ + char found = FALSE; + + for (k = 0; k < conn->ntables; k++) + { + if (!stricmp(conn->col_info[k]->name, ti[i]->name)) + { + mylog("FOUND col_info table='%s'\n", ti[i]->name); + found = TRUE; + break; + } + } + + if (!found) + { + mylog("PARSE: Getting PG_Columns for table[%d]='%s'\n", i, ti[i]->name); + + result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt); + if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) + { + stmt->errormsg = "PGAPI_AllocStmt failed in parse_statement for columns."; + stmt->errornumber = STMT_NO_MEMORY_ERROR; + stmt->parse_status = STMT_PARSE_FATAL; + return FALSE; + } + + col_stmt = (StatementClass *) hcol_stmt; + col_stmt->internal = TRUE; + + result = PGAPI_Columns(hcol_stmt, "", 0, "", 0, + ti[i]->name, (SWORD) strlen(ti[i]->name), "", 0); + + mylog(" Past PG_Columns\n"); + if (result == SQL_SUCCESS) + { + mylog(" Success\n"); + if (!(conn->ntables % COL_INCR)) + { + mylog("PARSE: Allocing col_info at ntables=%d\n", conn->ntables); + + conn->col_info = (COL_INFO **) realloc(conn->col_info, (conn->ntables + COL_INCR) * sizeof(COL_INFO *)); + if (!conn->col_info) + { + stmt->parse_status = STMT_PARSE_FATAL; + return FALSE; + } + } + + mylog("PARSE: malloc at conn->col_info[%d]\n", conn->ntables); + conn->col_info[conn->ntables] = (COL_INFO *) malloc(sizeof(COL_INFO)); + if (!conn->col_info[conn->ntables]) + { + stmt->parse_status = STMT_PARSE_FATAL; + return FALSE; + } + + /* + * Store the table name and the SQLColumns result + * structure + */ + strcpy(conn->col_info[conn->ntables]->name, ti[i]->name); + conn->col_info[conn->ntables]->result = col_stmt->result; + + /* + * The connection will now free the result structures, so + * make sure that the statement doesn't free it + */ + col_stmt->result = NULL; + + conn->ntables++; + + PGAPI_FreeStmt(hcol_stmt, SQL_DROP); + mylog("Created col_info table='%s', ntables=%d\n", ti[i]->name, conn->ntables); + } + else + { + PGAPI_FreeStmt(hcol_stmt, SQL_DROP); + break; + } + } + + /* Associate a table from the statement with a SQLColumn info */ + ti[i]->col_info = conn->col_info[k]; + mylog("associate col_info: i=%d, k=%d\n", i, k); + } + + mylog("Done PG_Columns\n"); + + /* + * Now resolve the fields to point to column info + */ + for (i = 0; i < stmt->nfld;) + { + /* Dont worry about functions or quotes */ + if (fi[i]->func || fi[i]->quote || fi[i]->numeric) + { + i++; + continue; + } + + /* Stars get expanded to all fields in the table */ + else if (fi[i]->name[0] == '*') + { + char do_all_tables; + int total_cols, + old_alloc, + new_size, + cols; + int increased_cols; + + mylog("expanding field %d\n", i); + + total_cols = 0; + + if (fi[i]->ti) /* The star represents only the qualified + * table */ + total_cols = QR_get_num_tuples(fi[i]->ti->col_info->result); + + else + { /* The star represents all tables */ + + /* Calculate the total number of columns after expansion */ + for (k = 0; k < stmt->ntab; k++) + total_cols += QR_get_num_tuples(ti[k]->col_info->result); + } + increased_cols = total_cols - 1; + + /* Allocate some more field pointers if necessary */ + old_alloc = ((stmt->nfld - 1) / FLD_INCR + 1) * FLD_INCR; + new_size = stmt->nfld + increased_cols; + + mylog("k=%d, increased_cols=%d, old_alloc=%d, new_size=%d\n", k, increased_cols, old_alloc, new_size); + + if (new_size > old_alloc) + { + int new_alloc = ((new_size / FLD_INCR) + 1) * FLD_INCR; + + mylog("need more cols: new_alloc = %d\n", new_alloc); + fi = (FIELD_INFO **) realloc(fi, new_alloc * sizeof(FIELD_INFO *)); + if (!fi) + { + stmt->parse_status = STMT_PARSE_FATAL; + return FALSE; + } + stmt->fi = fi; + } + + /* + * copy any other fields (if there are any) up past the + * expansion + */ + for (j = stmt->nfld - 1; j > i; j--) + { + mylog("copying field %d to %d\n", j, increased_cols + j); + fi[increased_cols + j] = fi[j]; + } + mylog("done copying fields\n"); + + /* Set the new number of fields */ + stmt->nfld += increased_cols; + mylog("stmt->nfld now at %d\n", stmt->nfld); + + + /* copy the new field info */ + do_all_tables = (fi[i]->ti ? FALSE : TRUE); + + for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++) + { + TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti; + + cols = QR_get_num_tuples(the_ti->col_info->result); + + for (n = 0; n < cols; n++) + { + mylog("creating field info: n=%d\n", n); + /* skip malloc (already did it for the Star) */ + if (k > 0 || n > 0) + { + mylog("allocating field info at %d\n", n + i); + fi[n + i] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO)); + if (fi[n + i] == NULL) + { + stmt->parse_status = STMT_PARSE_FATAL; + return FALSE; + } + } + /* Initialize the new space (or the * field) */ + memset(fi[n + i], 0, sizeof(FIELD_INFO)); + fi[n + i]->ti = the_ti; + + mylog("about to copy at %d\n", n + i); + + getColInfo(the_ti->col_info, fi[n + i], n); + + mylog("done copying\n"); + } + + i += cols; + mylog("i now at %d\n", i); + } + } + + /* + * We either know which table the field was in because it was + * qualified with a table name or alias -OR- there was only 1 + * table. + */ + else if (fi[i]->ti) + { + if (!searchColInfo(fi[i]->ti->col_info, fi[i])) + parse = FALSE; + + i++; + } + + /* Don't know the table -- search all tables in "from" list */ + else + { + parse = FALSE; + for (k = 0; k < stmt->ntab; k++) + { + if (searchColInfo(ti[k]->col_info, fi[i])) + { + fi[i]->ti = ti[k]; /* now know the table */ + parse = TRUE; + break; + } + } + i++; + } + } + + if (!parse) + stmt->parse_status = STMT_PARSE_INCOMPLETE; + else + stmt->parse_status = STMT_PARSE_COMPLETE; + + mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, stmt->parse_status); + return parse; +} |