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, &quote, &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 + -
显示快捷键?