parse.c
来自「postgresql-odbc,跨平台应用」· C语言 代码 · 共 1,872 行 · 第 1/3 页
C
1,872 行
mylog("->%d\n", updatable); for (i = 0; i < num_fields; i++) { if (reloid == (OID) QR_get_relid(res, i)) { if (wfi = fi[i], NULL == wfi) { wfi = (FIELD_INFO *) malloc(sizeof(FIELD_INFO)); fi_reuse = FALSE; fi[i] = wfi; } else if (FI_is_applicable(wfi)) continue; else fi_reuse = TRUE; FI_Constructor(wfi, fi_reuse); attid = (Int2) QR_get_attid(res, i); wfi->attnum = attid; if (searchColInfo(col_info, wfi)) { STR_TO_NAME(wfi->column_alias, QR_get_fieldname(res, i)); wfi->basetype = QR_get_field_type(res, i); wfi->updatable = updatable; } else { xxxxx(wfi, res, i); } wfi->ti = rti; wfi->flag |= FIELD_COL_ATTRIBUTE; } } if (rti) rti->flags |= TI_COLATTRIBUTE; return TRUE;}static BOOLgetCOLIfromTable(ConnectionClass *conn, pgNAME *schema_name, pgNAME table_name, COL_INFO **coli){ int colidx; BOOL found = FALSE; *coli = NULL; if (NAME_IS_NULL(table_name)) return TRUE; if (conn->schema_support) { if (NAME_IS_NULL(*schema_name)) { const char *curschema = CC_get_current_schema(conn); /* * Though current_schema() doesn't have * much sense in PostgreSQL, we first * check the current_schema() when no * explicit schema name was specified. */ for (colidx = 0; colidx < conn->ntables; colidx++) { if (!NAMEICMP(conn->col_info[colidx]->table_name, table_name) && !stricmp(SAFE_NAME(conn->col_info[colidx]->schema_name), curschema)) { mylog("FOUND col_info table='%s' current schema='%s'\n", PRINT_NAME(table_name), curschema); found = TRUE; STR_TO_NAME(*schema_name, curschema); break; } } if (!found) { QResultClass *res; char token[256]; BOOL tblFound = FALSE; /* * We also 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", SAFE_NAME(table_name)); res = CC_send_query(conn, token, NULL, ROLLBACK_ON_ERROR | IGNORE_ABORT_ON_CONN, NULL); if (QR_command_maybe_successful(res)) { if (QR_get_num_total_tuples(res) == 1) { tblFound = TRUE; STR_TO_NAME(*schema_name, QR_get_value_backend_text(res, 0, 0)); } } QR_Destructor(res); if (!tblFound) return FALSE; } } if (!found && NAME_IS_VALID(*schema_name)) { for (colidx = 0; colidx < conn->ntables; colidx++) { if (!NAMEICMP(conn->col_info[colidx]->table_name, table_name) && !NAMEICMP(conn->col_info[colidx]->schema_name, *schema_name)) { mylog("FOUND col_info table='%s' schema='%s'\n", PRINT_NAME(table_name), PRINT_NAME(*schema_name)); found = TRUE; break; } } } } else { for (colidx = 0; colidx < conn->ntables; colidx++) { if (!NAMEICMP(conn->col_info[colidx]->table_name, table_name)) { mylog("FOUND col_info table='%s'\n", table_name); found = TRUE; break; } } } *coli = found ? conn->col_info[colidx] : NULL; return TRUE; /* success */}BOOL getCOLIfromTI(const char *func, ConnectionClass *conn, StatementClass *stmt, const OID reloid, TABLE_INFO **pti){ BOOL colatt = FALSE, found = FALSE; OID greloid = reloid; TABLE_INFO *wti = *pti; COL_INFO *coli; HSTMT hcol_stmt = NULL; QResultClass *res;inolog("getCOLIfromTI reloid=%u ti=%p\n", reloid, wti); if (!conn) conn = SC_get_conn(stmt); if (!wti) /* SQLColAttribute case */ { int i; if (0 == greloid) return FALSE; colatt = TRUE; for (i = 0; i < stmt->ntab; i++) { if (stmt->ti[i]->table_oid == greloid) { wti = stmt->ti[i]; break; } } if (!wti) {inolog("before increaseNtab\n"); if (!increaseNtab(stmt, func)) return FALSE; wti = stmt->ti[stmt->ntab - 1]; wti->table_oid = greloid; } *pti = wti; }inolog("fi=%p greloid=%d col_info=%p\n", wti, greloid, wti->col_info); if (0 == greloid) greloid = wti->table_oid; if (NULL != wti->col_info) { found = TRUE; goto cleanup; } if (greloid != 0) { int colidx; for (colidx = 0; colidx < conn->ntables; colidx++) { if (conn->col_info[colidx]->table_oid == greloid) { mylog("FOUND col_info table=%ul\n", greloid); found = TRUE; wti->col_info = conn->col_info[colidx]; break; } } } else { if (!getCOLIfromTable(conn, &wti->schema_name, wti->table_name, &coli)) { if (stmt) { SC_set_parse_status(stmt, STMT_PARSE_FATAL); SC_set_error(stmt, STMT_EXEC_ERROR, "Table not found", func); stmt->updatable = FALSE; } return FALSE; } else if (NULL != coli) { found = TRUE; wti->col_info = coli; } } if (found) goto cleanup; else if (0 != greloid || NAME_IS_VALID(wti->table_name)) { RETCODE result; StatementClass *col_stmt; mylog("PARSE: Getting PG_Columns for table='%s'\n", wti->table_name); result = PGAPI_AllocStmt(conn, &hcol_stmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if (stmt) SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for columns.", func); goto cleanup; } col_stmt = (StatementClass *) hcol_stmt; col_stmt->internal = TRUE; if (greloid) result = PGAPI_Columns(hcol_stmt, NULL, 0, NULL, 0, NULL, 0, NULL, 0, PODBC_SEARCH_BY_IDS, greloid, 0); else result = PGAPI_Columns(hcol_stmt, NULL, 0, SAFE_NAME(wti->schema_name), SQL_NTS, SAFE_NAME(wti->table_name), SQL_NTS, NULL, 0, PODBC_NOT_SEARCH_PATTERN, 0, 0); mylog(" Past PG_Columns\n"); res = SC_get_Curres(col_stmt); if ((SQL_SUCCESS == result || SQL_SUCCESS_WITH_INFO == result) && res && QR_get_num_cached_tuples(res) > 0) { COL_INFO *coli; mylog(" Success\n"); if (conn->ntables >= conn->coli_allocated) { Int2 new_alloc; new_alloc = conn->coli_allocated * 2; if (new_alloc <= conn->ntables) new_alloc = COLI_INCR; mylog("PARSE: Allocating col_info at ntables=%d\n", conn->ntables); conn->col_info = (COL_INFO **) realloc(conn->col_info, new_alloc * sizeof(COL_INFO *)); if (!conn->col_info) { if (stmt) SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for col_info.", func); goto cleanup; } conn->coli_allocated = new_alloc; } mylog("PARSE: malloc at conn->col_info[%d]\n", conn->ntables); coli = conn->col_info[conn->ntables] = (COL_INFO *) malloc(sizeof(COL_INFO)); if (!coli) { if (stmt) SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for col_info(2).", func); goto cleanup; } col_info_initialize(coli); coli->result = res; if (res && QR_get_num_cached_tuples(res) > 0) { if (!greloid) greloid = (OID) strtoul(QR_get_value_backend_text(res, 0, COLUMNS_TABLE_OID), NULL, 10); if (!wti->table_oid) wti->table_oid = greloid; if (NAME_IS_NULL(wti->schema_name)) STR_TO_NAME(wti->schema_name, QR_get_value_backend_text(res, 0, COLUMNS_SCHEMA_NAME)); if (NAME_IS_NULL(wti->table_name)) STR_TO_NAME(wti->table_name, QR_get_value_backend_text(res, 0, COLUMNS_TABLE_NAME)); }inolog("#2 %p->table_name=%s(%u)\n", wti, PRINT_NAME(wti->table_name), wti->table_oid); /* * Store the table name and the SQLColumns result * structure */ if (NAME_IS_VALID(wti->schema_name)) { NAME_TO_NAME(coli->schema_name, wti->schema_name); } else NULL_THE_NAME(coli->schema_name); NAME_TO_NAME(coli->table_name, wti->table_name); coli->table_oid = wti->table_oid; /* * The connection will now free the result structures, so * make sure that the statement doesn't free it */ SC_init_Result(col_stmt); conn->ntables++;if (res && QR_get_num_cached_tuples(res) > 0)inolog("oid item == %s\n", QR_get_value_backend_text(res, 0, 3)); mylog("Created col_info table='%s', ntables=%d\n", PRINT_NAME(wti->table_name), conn->ntables); /* Associate a table from the statement with a SQLColumn info */ found = TRUE; wti->col_info = coli; } }cleanup: if (hcol_stmt) PGAPI_FreeStmt(hcol_stmt, SQL_DROP); if (found) { QResultClass *res = wti->col_info->result; if (res && QR_get_num_cached_tuples(res) > 0) { if (!greloid) greloid = (OID) strtoul(QR_get_value_backend_text(res, 0, COLUMNS_TABLE_OID), NULL, 10); if (!wti->table_oid) wti->table_oid = greloid; if (NAME_IS_NULL(wti->schema_name)) STR_TO_NAME(wti->schema_name, QR_get_value_backend_text(res, 0, COLUMNS_SCHEMA_NAME)); if (NAME_IS_NULL(wti->table_name)) STR_TO_NAME(wti->table_name, QR_get_value_backend_text(res, 0, COLUMNS_TABLE_NAME)); }inolog("#1 %p->table_name=%s(%u)\n", wti, PRINT_NAME(wti->table_name), wti->table_oid); if (colatt /* SQLColAttribute case */ && 0 == (wti->flags & TI_COLATTRIBUTE)) { if (stmt) ColAttSet(stmt, wti); } } else if (!colatt && stmt) SC_set_parse_status(stmt, STMT_PARSE_FATAL);inolog("getCOLIfromTI returns %d\n", found); return found;}SQLRETURNSC_set_SS_columnkey(StatementClass *stmt){ CSTR func = "SC_set_SS_columnkey"; IRDFields *irdflds = SC_get_IRDF(stmt); FIELD_INFO **fi = irdflds->fi, *tfi; size_t nfields = irdflds->nfields; StatementClass *pstmt = NULL; SQLRETURN ret = SQL_SUCCESS; BOOL contains_key = FALSE; int i;inolog("%s:fields=%d ntab=%d\n", func, nfields, stmt->ntab); if (!fi) return ret; if (0 >= nfields) return ret; if (!has_multi_table(stmt) && 1 == stmt->ntab) { TABLE_INFO **ti = stmt->ti, *oneti; ConnectionClass *conn = SC_get_conn(stmt); OID internal_asis_type = SQL_C_CHAR; char keycolnam[MAX_INFO_STRING]; SQLLEN keycollen; ret = PGAPI_AllocStmt(conn, &pstmt); if (!SQL_SUCCEEDED(ret)) return ret; oneti = ti[0]; ret = PGAPI_PrimaryKeys(pstmt, NULL, 0, NULL, 0, NULL, 0, oneti->table_oid); if (!SQL_SUCCEEDED(ret)) goto cleanup;#ifdef UNICODE_SUPPORT if (CC_is_in_unicode_driver(conn)) internal_asis_type = INTERNAL_ASIS_TYPE;#endif /* UNICODE_SUPPORT */ ret = PGAPI_BindCol(pstmt, 4, internal_asis_type, keycolnam, MAX_INFO_STRING, &keycollen); if (!SQL_SUCCEEDED(ret)) goto cleanup; contains_key = TRUE; ret = PGAPI_Fetch(pstmt); while (SQL_SUCCEEDED(ret)) { for (i = 0; i < nfields; i++) { if (tfi = fi[i], NULL == tfi) continue; if (!FI_is_applicable(tfi)) continue; if (oneti == tfi->ti && strcmp(keycolnam, SAFE_NAME(tfi->column_name)) == 0) {inolog("%s:key %s found at %p\n", func, keycolnam, fi + i); tfi->columnkey = TRUE; break; } } if (i >= nfields) { mylog("%s: %s not found\n", func, keycolnam); break; } ret = PGAPI_Fetch(pstmt); } if (SQL_SUCCEEDED(ret)) contains_key = FALSE; else if (SQL_NO_DATA_FOUND != ret) goto cleanup; ret = SQL_SUCCESS; }inolog("%s: contains_key=%d\n", func, contains_key); for (i = 0; i < nfields; i++) { if (tfi = fi[i], NULL == tfi) continue; if (!FI_is_applicable(tfi)) continue; if (!contains_key || tfi->columnkey < 0) tfi->columnkey = FALSE; } cleanup: if (pstmt) PGAPI_FreeStmt(pstmt, SQL_DROP); return ret;}charparse_statement(StatementClass *stmt, BOOL check_hasoids){ CSTR func = "parse_statement"; char token[256], stoken[256]; char delim, quote, dquote, numeric, unquoted; char *ptr, *pptr = NULL; char in_select = FALSE, in_distinct = FALSE, in_on = FALSE, in_from = FALSE, in_where = FALSE, in_table = FALSE, out_table = TRUE; char in_field = FALSE, in_expr = FALSE, in_func = FALSE, in_dot = FALSE, in_as = FALSE; int j, i, k = 0, n, blevel = 0, old_blevel, subqlevel = 0, allocated_size, new_size; FIELD_INFO **fi, *wfi; TABLE_INFO **ti, *wti; char parse, maybe_join = 0; ConnectionClass *conn = SC_get_conn(stmt); IRDFields *irdflds = SC_get_IRDF(stmt); BOOL updatable = TRUE; mylog("%s: entering...\n", func); if (SC_parsed_status(stmt) != STMT_PARSE_NONE) { if (check_hasoids) CheckHasOids(stmt); return TRUE; } stmt->updatable = FALSE; ptr = stmt->statement; fi = irdflds->fi; ti = stmt->ti; allocated_size = irdflds->allocated; SC_initialize_cols_info(stmt, FALSE, TRUE); stmt->from_pos = -1; stmt->where_pos = -1;#define return DONT_CALL_RETURN_FROM_HERE??? while (pptr = ptr, (ptr = getNextToken(conn->ccsc, CC_get_escape(conn), 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); old_blevel = blevel; if (unquoted && blevel == 0) { if (in_select) { if (!stricmp(token, "distinct")) { in_distinct = TRUE; updatable = FALSE; mylog("DISTINCT\n"); continue; } else if (!stricmp(token, "into")) { in_select = FALSE; mylog("INTO\n"); stmt->statement_type = STMT_TYPE_CREATE; SC_set_parse_status(stmt, STMT_PARSE_FATAL); goto cleanup; } 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 */ else if ((!stricmp(token, "where") || !stricmp(token, "union") || !stricmp(token, "intersect") || !stricmp(token, "except") || !stricmp(token, "order") || !stricmp(token, "group") || !stricmp(token, "having"))) { in_from = FALSE; in_where = TRUE; if (stmt->where_pos < 0) stmt->where_pos = pptr - stmt->statement; mylog("%s...\n", token); if (stricmp(token, "where") && stricmp(token, "order")) { updatable = FALSE; break; } continue; } } /* unquoted && blevel == 0 */ /* check the change of blevel etc */ if (unquoted) { if (!stricmp(token, "select")) { stoken[0] = '\0'; if (0 == blevel) { in_select = TRUE; mylog("SELECT\n"); continue; } else { mylog("SUBSELECT\n"); if (0 == subqlevel) subqlevel = blevel; } } else if (token[0] == '(') { blevel++; mylog("blevel++ = %d\n", blevel); /* aggregate function ? */ if (stoken[0] && updatable && 0 == subqlevel) { 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; } } 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?