parse.c
来自「postgresql-odbc,跨平台应用」· C语言 代码 · 共 1,872 行 · 第 1/3 页
C
1,872 行
} /* (in_expr || in_func) && 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; } /* in_distinct */ if (!in_field) { BOOL fi_reuse = FALSE; if (!token[0]) continue; /* if (!(irdflds->nfields % FLD_INCR)) */ if (irdflds->nfields >= allocated_size) { mylog("reallocing at nfld=%d\n", irdflds->nfields); new_size = irdflds->nfields + 1; if (!allocateFields(irdflds, new_size)) { SC_set_parse_status(stmt, STMT_PARSE_FATAL); SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for FIELD_INFO.", func); goto cleanup; } fi = irdflds->fi; allocated_size = irdflds->allocated; } wfi = fi[irdflds->nfields]; if (wfi) fi_reuse = TRUE; else wfi = fi[irdflds->nfields] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO)); if (wfi == NULL) { SC_set_parse_status(stmt, STMT_PARSE_FATAL); SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for FIELD_INFO(2).", func); goto cleanup; } /* Initialize the field info */ FI_Constructor(wfi, fi_reuse); wfi->flag = FIELD_PARSING; /* double quotes are for qualifiers */ if (dquote) wfi->dquote = TRUE; if (quote) { wfi->quote = TRUE; wfi->column_size = (int) strlen(token); } else if (numeric) { mylog("**** got numeric: nfld = %d\n", irdflds->nfields); wfi->numeric = TRUE; } else if (0 == old_blevel && blevel > 0) { /* expression */ mylog("got EXPRESSION\n"); wfi->expr = TRUE; in_expr = TRUE; /* continue; */ } else { STR_TO_NAME(wfi->column_name, token); NULL_THE_NAME(wfi->before_dot); } mylog("got field='%s', dot='%s'\n", PRINT_NAME(wfi->column_name), PRINT_NAME(wfi->before_dot)); if (delim == ',') mylog("comma (1)\n"); else in_field = TRUE; irdflds->nfields++; continue; } /* !in_field */ /* * We are in a field now */ wfi = fi[irdflds->nfields - 1]; if (in_dot) { if (NAME_IS_VALID(wfi->before_dot)) { MOVE_NAME(wfi->schema_name, wfi->before_dot); } MOVE_NAME(wfi->before_dot, wfi->column_name); STR_TO_NAME(wfi->column_name, token); if (delim == ',') { mylog("in_dot: got comma\n"); in_field = FALSE; } in_dot = FALSE; continue; } if (in_as) { STR_TO_NAME(wfi->column_alias, token); mylog("alias for field '%s' is '%s'\n", PRINT_NAME(wfi->column_name), PRINT_NAME(wfi->column_alias)); in_as = FALSE; in_field = FALSE; if (delim == ',') mylog("comma(2)\n"); continue; } /* Function */ if (0 == old_blevel && blevel > 0) { in_dot = FALSE; in_func = TRUE; wfi->func = TRUE; /* * name will have the function name -- maybe useful some * day */ mylog("**** got function = '%s'\n", PRINT_NAME(wfi->column_name)); continue; } if (token[0] == '.') { in_dot = TRUE; mylog("got dot\n"); continue; } in_dot = FALSE; if (!stricmp(token, "as")) { in_as = TRUE; mylog("got AS\n"); continue; } /* otherwise, it's probably an expression */ in_expr = TRUE; wfi->expr = TRUE; NULL_THE_NAME(wfi->column_name); wfi->column_size = 0; mylog("*** setting expression\n"); } /* in_select end */ if (in_from || in_where) { if (token[0] == ';') /* end of the first command */ { in_select = in_from = in_where = in_table = FALSE; break; } } if (in_from) { switch (token[0]) { case '\0': continue; case ',': out_table = TRUE; continue; } if (out_table && !in_table) /* new table */ { in_dot = FALSE; maybe_join = 0; if (!dquote) { if (token[0] == '(' || token[0] == ')') continue; } if (!increaseNtab(stmt, func)) { SC_set_parse_status(stmt, STMT_PARSE_FATAL); goto cleanup; } ti = stmt->ti; wti = ti[stmt->ntab - 1]; if (dquote || stricmp(token, "select")) { STR_TO_NAME(wti->table_name, token); lower_the_name(GET_NAME(wti->table_name), conn, dquote); } else { NULL_THE_NAME(wti->table_name); TI_no_updatable(wti); } mylog("got table = '%s'\n", PRINT_NAME(wti->table_name)); if (0 == blevel && delim == ',') { out_table = TRUE; mylog("more than 1 tables\n"); } else { out_table = FALSE; in_table = TRUE; } continue; } if (0 != blevel) continue; /* out_table is FALSE here */ if (!dquote && !in_dot) { if (')' == token[0]) continue; if (stricmp(token, "LEFT") == 0 || stricmp(token, "RIGHT") == 0 || stricmp(token, "OUTER") == 0 || stricmp(token, "FULL") == 0) { maybe_join = 1; in_table = FALSE; continue; } else if (stricmp(token, "INNER") == 0 || stricmp(token, "CROSS") == 0) { maybe_join = 2; in_table = FALSE; continue; } else if (stricmp(token, "JOIN") == 0) { in_table = FALSE; out_table = TRUE; switch (maybe_join) { case 1: SC_set_outer_join(stmt); break; case 2: SC_set_inner_join(stmt); break; } maybe_join = 0; continue; } } maybe_join = 0; if (in_table) { wti = ti[stmt->ntab - 1]; if (in_dot) { MOVE_NAME(wti->schema_name, wti->table_name); STR_TO_NAME(wti->table_name, token); lower_the_name(GET_NAME(wti->table_name), conn, dquote); in_dot = FALSE; continue; } if (strcmp(token, ".") == 0) { in_dot = TRUE; continue; } if (dquote || stricmp(token, "as")) { if (!dquote) { if (stricmp(token, "ON") == 0) { in_table = FALSE; continue; } } STR_TO_NAME(wti->table_alias, token); mylog("alias for table '%s' is '%s'\n", PRINT_NAME(wti->table_name), PRINT_NAME(wti->table_alias)); in_table = FALSE; if (delim == ',') { out_table = TRUE; mylog("more than 1 tables\n"); } } } } /* in_from */ } /* * Resolve any possible field names with tables */ parse = TRUE; /* Resolve field names with tables */ for (i = 0; i < (int) irdflds->nfields; i++) { wfi = fi[i]; if (wfi->func || wfi->expr || wfi->numeric) { wfi->ti = NULL; wfi->columntype = wfi->basetype = (OID) 0; parse = FALSE; continue; } else if (wfi->quote) { /* handle as text */ wfi->ti = NULL; /* * wfi->type = PG_TYPE_TEXT; wfi->column_size = 0; the * following may be better */ wfi->basetype = PG_TYPE_UNKNOWN; if (wfi->column_size == 0) { wfi->basetype = PG_TYPE_VARCHAR; wfi->column_size = 254; } wfi->length = wfi->column_size; continue; } /* field name contains the schema name */ else if (NAME_IS_VALID(wfi->schema_name)) { int matchidx = -1; for (k = 0; k < stmt->ntab; k++) { wti = ti[k]; if (!NAMEICMP(wti->table_name, wfi->before_dot)) { if (!NAMEICMP(wti->schema_name, wfi->schema_name)) { wfi->ti = wti; break; } else if (NAME_IS_NULL(wti->schema_name)) { if (matchidx < 0) matchidx = k; else { SC_set_parse_status(stmt, STMT_PARSE_FATAL); SC_set_error(stmt, STMT_EXEC_ERROR, "duplicated Table name", func); stmt->updatable = FALSE; goto cleanup; } } } } if (matchidx >= 0) wfi->ti = ti[matchidx]; } /* it's a dot, resolve to table or alias */ else if (NAME_IS_VALID(wfi->before_dot)) { for (k = 0; k < stmt->ntab; k++) { wti = ti[k]; if (!NAMEICMP(wti->table_alias, wfi->before_dot)) { wfi->ti = wti; break; } else if (!NAMEICMP(wti->table_name, wfi->before_dot)) { wfi->ti = wti; break; } } } else if (stmt->ntab == 1) wfi->ti = ti[0]; } mylog("--------------------------------------------\n"); mylog("nfld=%d, ntab=%d\n", irdflds->nfields, stmt->ntab); if (0 == stmt->ntab) { SC_set_parse_status(stmt, STMT_PARSE_FATAL); goto cleanup; } for (i = 0; i < (int) irdflds->nfields; i++) { wfi = fi[i]; mylog("Field %d: expr=%d, func=%d, quote=%d, dquote=%d, numeric=%d, name='%s', alias='%s', dot='%s'\n", i, wfi->expr, wfi->func, wfi->quote, wfi->dquote, wfi->numeric, PRINT_NAME(wfi->column_name), PRINT_NAME(wfi->column_alias), PRINT_NAME(wfi->before_dot)); if (wfi->ti) mylog(" ----> table_name='%s', table_alias='%s'\n", PRINT_NAME(wfi->ti->table_name), PRINT_NAME(wfi->ti->table_alias)); } for (i = 0; i < stmt->ntab; i++) { wti = ti[i]; mylog("Table %d: name='%s', alias='%s'\n", i, PRINT_NAME(wti->table_name), PRINT_NAME(wti->table_alias)); } /* * Now save the SQLColumns Info for the parse tables */ /* Call SQLColumns for each table and store the result */ if (stmt->ntab > 1) updatable = FALSE; else if (stmt->from_pos < 0) updatable = FALSE; for (i = 0; i < stmt->ntab; i++) { /* See if already got it */ wti = ti[i]; if (!getCOLIfromTI(func, NULL, stmt, 0, &wti)) break; } if (STMT_PARSE_FATAL == SC_parsed_status(stmt)) { goto cleanup; } mylog("Done PG_Columns\n"); /* * Now resolve the fields to point to column info */ if (updatable && 1 == stmt->ntab) updatable = TI_is_updatable(stmt->ti[0]); for (i = 0; i < (int) irdflds->nfields;) { wfi = fi[i]; wfi->updatable = updatable; /* Dont worry about functions or quotes */ if (wfi->func || wfi->quote || wfi->numeric) { wfi->updatable = FALSE; i++; continue; } /* Stars get expanded to all fields in the table */ else if (SAFE_NAME(wfi->column_name)[0] == '*') { char do_all_tables; Int2 total_cols, cols, increased_cols; mylog("expanding field %d\n", i); total_cols = 0; if (wfi->ti) /* The star represents only the qualified * table */ total_cols = (Int2) QR_get_num_cached_tuples(wfi->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 += (Int2) QR_get_num_cached_tuples(ti[k]->col_info->result); } increased_cols = total_cols - 1; /* Allocate some more field pointers if necessary */ new_size = irdflds->nfields + increased_cols; mylog("k=%d, increased_cols=%d, allocated_size=%d, new_size=%d\n", k, increased_cols, allocated_size, new_size); if (new_size > allocated_size) { int new_alloc = new_size; mylog("need more cols: new_alloc = %d\n", new_alloc); if (!allocateFields(irdflds, new_alloc)) { SC_set_parse_status(stmt, STMT_PARSE_FATAL); goto cleanup; } fi = irdflds->fi; allocated_size = irdflds->allocated; } /* * copy any other fields (if there are any) up past the * expansion */ for (j = irdflds->nfields - 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 */ irdflds->nfields += increased_cols; mylog("irdflds->nfields now at %d\n", irdflds->nfields); /* copy the new field info */ do_all_tables = (wfi->ti ? FALSE : TRUE); wfi = NULL; for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++) { TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti; cols = (Int2) QR_get_num_cached_tuples(the_ti->col_info->result); for (n = 0; n < cols; n++) { FIELD_INFO *afi; BOOL reuse = TRUE; 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) { SC_set_parse_status(stmt, STMT_PARSE_FATAL); goto cleanup; } reuse = FALSE; } afi = fi[n + i]; /* Initialize the new space (or the * field) */ FI_Constructor(afi, reuse); afi->ti = the_ti; mylog("about to copy at %d\n", n + i); getColInfo(the_ti->col_info, afi, n); afi->updatable = updatable; 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 (wfi->ti) { if (!searchColInfo(fi[i]->ti->col_info, wfi)) { parse = FALSE; wfi->updatable = FALSE; } i++; } /* Don't know the table -- search all tables in "from" list */ else { for (k = 0; k < stmt->ntab; k++) { if (searchColInfo(ti[k]->col_info, wfi)) { wfi->ti = ti[k]; /* now know the table */ break; } } if (k >= stmt->ntab) { parse = FALSE; wfi->updatable = FALSE; } i++; } } if (check_hasoids && updatable) CheckHasOids(stmt); SC_set_parse_status(stmt, parse ? STMT_PARSE_COMPLETE : STMT_PARSE_INCOMPLETE); for (i = 0; i < (int) irdflds->nfields; i++) { wfi = fi[i]; wfi->flag &= ~FIELD_PARSING; if (0 != wfi->columntype || 0 != wfi->basetype) wfi->flag |= FIELD_PARSED_OK; } stmt->updatable = updatable;cleanup:#undef return if (STMT_PARSE_FATAL == SC_parsed_status(stmt)) { SC_initialize_cols_info(stmt, FALSE, FALSE); parse = FALSE; } mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, SC_parsed_status(stmt)); return parse;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?