aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/odbc/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/odbc/parse.c')
-rw-r--r--src/interfaces/odbc/parse.c233
1 files changed, 158 insertions, 75 deletions
diff --git a/src/interfaces/odbc/parse.c b/src/interfaces/odbc/parse.c
index cb77fddd836..2ca0ef00f99 100644
--- a/src/interfaces/odbc/parse.c
+++ b/src/interfaces/odbc/parse.c
@@ -50,6 +50,29 @@ char *getNextToken(char *s, char *token, int smax, char *delim, char *quote,
void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);
+Int4 FI_precision(const FIELD_INFO *fi)
+{
+ if (!fi) return -1;
+ switch (fi->type)
+ {
+ case PG_TYPE_NUMERIC:
+ return fi->column_size;
+ case PG_TYPE_DATETIME:
+ case PG_TYPE_TIMESTAMP_NO_TMZONE:
+ return fi->decimal_digits;
+ }
+ return 0;
+}
+Int4 FI_scale(const FIELD_INFO *fi)
+{
+ if (!fi) return -1;
+ switch (fi->type)
+ {
+ case PG_TYPE_NUMERIC:
+ return fi->decimal_digits;
+ }
+ return 0;
+}
char *
getNextToken(
@@ -265,7 +288,7 @@ searchColInfo(COL_INFO *col_info, FIELD_INFO *fi)
cmp;
char *col;
- for (k = 0; k < QR_get_num_tuples(col_info->result); k++)
+ for (k = 0; k < QR_get_num_backend_tuples(col_info->result); k++)
{
col = QR_get_value_manual(col_info->result, k, 3);
if (fi->dquote)
@@ -291,7 +314,7 @@ char
parse_statement(StatementClass *stmt)
{
static char *func = "parse_statement";
- char token[256];
+ char token[256], stoken[256];
char delim,
quote,
dquote,
@@ -315,7 +338,7 @@ parse_statement(StatementClass *stmt)
i,
k = 0,
n,
- blevel = 0;
+ blevel = 0, old_blevel, subqlevel = 0;
FIELD_INFO **fi;
TABLE_INFO **ti;
char parse;
@@ -347,42 +370,43 @@ parse_statement(StatementClass *stmt)
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)
+ old_blevel = blevel;
+ if (unquoted && blevel == 0)
{
- if (!stricmp(token, "distinct"))
+ if (in_select)
{
- in_distinct = TRUE;
- updatable = FALSE;
+ if (!stricmp(token, "distinct"))
+ {
+ in_distinct = TRUE;
+ updatable = FALSE;
- 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 (stmt->from_pos < 0 &&
- (!strnicmp(pptr, "from", 4)))
+ mylog("DISTINCT\n");
+ continue;
+ }
+ else if (!stricmp(token, "into"))
{
- mylog("First ");
- stmt->from_pos = pptr - stmt->statement;
+ in_select = FALSE;
+ mylog("INTO\n");
+ stmt->statement_type = STMT_TYPE_CREATE;
+ stmt->parse_status = STMT_PARSE_FATAL;
+ return FALSE;
}
+ else if (!stricmp(token, "from"))
+ {
+ in_select = FALSE;
+ in_from = TRUE;
+ if (stmt->from_pos < 0 &&
+ (!strnicmp(pptr, "from", 4)))
+ {
+ mylog("First ");
+ stmt->from_pos = pptr - stmt->statement;
+ }
- mylog("FROM\n");
- continue;
- }
- } /* in_select && unquoted && blevel == 0 */
- if (unquoted && blevel == 0)
- {
- if ((!stricmp(token, "where") ||
+ mylog("FROM\n");
+ continue;
+ }
+ } /* in_select && unquoted && blevel == 0 */
+ else if ((!stricmp(token, "where") ||
!stricmp(token, "union") ||
!stricmp(token, "intersect") ||
!stricmp(token, "except") ||
@@ -390,7 +414,6 @@ parse_statement(StatementClass *stmt)
!stricmp(token, "group") ||
!stricmp(token, "having")))
{
- in_select = FALSE;
in_from = FALSE;
in_where = TRUE;
@@ -406,54 +429,82 @@ parse_statement(StatementClass *stmt)
continue;
}
} /* unquoted && blevel == 0 */
- if (in_select && (in_expr || in_func))
+ /* check the change of blevel etc */
+ if (unquoted)
{
- /* just eat the expression */
- mylog("in_expr=%d or func=%d\n", in_expr, in_func);
-
- if (unquoted)
+ if (!stricmp(token, "select"))
{
- if (token[0] == '(')
+ stoken[0] = '\0';
+ if (0 == blevel)
{
- blevel++;
- mylog("blevel++ = %d\n", blevel);
+ in_select = TRUE;
+ mylog("SELECT\n");
+ continue;
}
- else if (token[0] == ')')
+ else
{
- blevel--;
- mylog("blevel-- = %d\n", blevel);
+ mylog("SUBSELECT\n");
+ if (0 == subqlevel)
+ subqlevel = blevel;
}
}
- if (blevel == 0)
+ else if (token[0] == '(')
{
- if (delim == ',')
+ blevel++;
+ mylog("blevel++ = %d\n", blevel);
+ /* aggregate function ? */
+ if (stoken[0] && updatable && 0 == subqlevel)
{
- 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;
+ if (stricmp(stoken, "count") == 0 ||
+ stricmp(stoken, "sum") == 0 ||
+ stricmp(stoken, "avg") == 0 ||
+ stricmp(stoken, "max") == 0 ||
+ stricmp(stoken, "min") == 0 ||
+ stricmp(stoken, "variance") == 0 ||
+ stricmp(stoken, "stddev") == 0)
+ updatable = FALSE;
}
}
- continue;
- } /* in_select && (in_expr || in_func) */
-
- if (unquoted && !stricmp(token, "select"))
- {
- in_select = TRUE;
-
- mylog("SELECT\n");
- continue;
+ else if (token[0] == ')')
+ {
+ blevel--;
+ mylog("blevel-- = %d\n", blevel);
+ if (blevel < subqlevel)
+ subqlevel = 0;
+ }
+ if (blevel >= old_blevel && ',' != delim)
+ strcpy(stoken, token);
+ else
+ stoken[0] = '\0';
}
if (in_select)
{
+ if (in_expr || in_func)
+ {
+ /* just eat the expression */
+ mylog("in_expr=%d or func=%d\n", in_expr, in_func);
+
+ 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;
+ } /* (in_expr || in_func) && in_select */
+
if (in_distinct)
{
mylog("in distinct\n");
@@ -515,12 +566,11 @@ parse_statement(StatementClass *stmt)
mylog("**** got numeric: nfld = %d\n", irdflds->nfields);
fi[irdflds->nfields]->numeric = TRUE;
}
- else if (token[0] == '(')
+ else if (0 == old_blevel && blevel > 0)
{ /* expression */
mylog("got EXPRESSION\n");
fi[irdflds->nfields++]->expr = TRUE;
in_expr = TRUE;
- blevel = 1;
continue;
}
else
@@ -579,11 +629,10 @@ parse_statement(StatementClass *stmt)
}
/* Function */
- if (token[0] == '(')
+ if (0 == old_blevel && blevel > 0)
{
in_dot = FALSE;
in_func = TRUE;
- blevel = 1;
fi[irdflds->nfields - 1]->func = TRUE;
/*
@@ -654,6 +703,7 @@ parse_statement(StatementClass *stmt)
ti[stmt->ntab]->schema[0] = '\0';
ti[stmt->ntab]->alias[0] = '\0';
+ ti[stmt->ntab]->updatable = 1;
strcpy(ti[stmt->ntab]->name, token);
if (!dquote)
@@ -845,6 +895,37 @@ parse_statement(StatementClass *stmt)
col_stmt = (StatementClass *) hcol_stmt;
col_stmt->internal = TRUE;
+ if (!ti[i]->schema[0] && conn->schema_support)
+ {
+ QResultClass *res;
+ BOOL tblFound = FALSE;
+
+ /* Unfortunately CURRENT_SCHEMA doesn't exist
+ * in PostgreSQL and we have to check as follows.
+ */
+ sprintf(token, "select nspname from pg_namespace n, pg_class c"
+ " where c.relnamespace=n.oid and c.oid='%s'::regclass", ti[i]->name);
+ res = CC_send_query(conn, token, NULL, CLEAR_RESULT_ON_ABORT);
+ if (res)
+ {
+ if (QR_get_num_total_tuples(res) == 1)
+ {
+ tblFound = TRUE;
+ strcpy(ti[i]->schema, QR_get_value_backend_row(res, 0, 0));
+ }
+ QR_Destructor(res);
+ }
+ else
+ CC_abort(conn);
+ if (!tblFound)
+ {
+ stmt->parse_status = STMT_PARSE_FATAL;
+ stmt->errornumber = STMT_EXEC_ERROR;
+ stmt->errormsg = "Table not found";
+ stmt->updatable = FALSE;
+ return FALSE;
+ }
+ }
result = PGAPI_Columns(hcol_stmt, "", 0, ti[i]->schema,
SQL_NTS, ti[i]->name, SQL_NTS, "", 0, PODBC_NOT_SEARCH_PATTERN);
@@ -907,6 +988,8 @@ parse_statement(StatementClass *stmt)
/*
* Now resolve the fields to point to column info
*/
+ if (updatable && 1 == stmt->ntab)
+ updatable = stmt->ti[0]->updatable;
for (i = 0; i < (int) irdflds->nfields;)
{
fi[i]->updatable = updatable;
@@ -934,14 +1017,14 @@ parse_statement(StatementClass *stmt)
if (fi[i]->ti) /* The star represents only the qualified
* table */
- total_cols = QR_get_num_tuples(fi[i]->ti->col_info->result);
+ total_cols = QR_get_num_backend_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);
+ total_cols += QR_get_num_backend_tuples(ti[k]->col_info->result);
}
increased_cols = total_cols - 1;
@@ -988,7 +1071,7 @@ parse_statement(StatementClass *stmt)
{
TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti;
- cols = QR_get_num_tuples(the_ti->col_info->result);
+ cols = QR_get_num_backend_tuples(the_ti->col_info->result);
for (n = 0; n < cols; n++)
{