/* * Function dumping dependent relation & function oids for a given SQL text */ Datum gp_dump_query_oids(PG_FUNCTION_ARGS) { char *sqlText = text_to_cstring(PG_GETARG_TEXT_P(0)); List *queryList = pg_parse_and_rewrite(sqlText, NULL, 0); ListCell *plc; StringInfoData relbuf, funcbuf; initStringInfo(&relbuf); initStringInfo(&funcbuf); typedef struct OidHashEntry { Oid key; bool value; } OidHashEntry; HASHCTL ctl; ctl.keysize = sizeof(Oid); ctl.entrysize = sizeof(OidHashEntry); ctl.hash = oid_hash; HTAB *relhtab = hash_create("relid hash table", 100, &ctl, HASH_ELEM | HASH_FUNCTION); HTAB *funchtab = hash_create("funcid hash table", 100, &ctl, HASH_ELEM | HASH_FUNCTION); foreach(plc, queryList) { Query *query = (Query *) lfirst(plc); if (CMD_UTILITY == query->commandType && T_ExplainStmt == query->utilityStmt->type) { Node *queryExplain = ((ExplainStmt *)query->utilityStmt)->query; List *queryTree = pg_analyze_and_rewrite(queryExplain, sqlText, NULL, 0); Assert(1 == list_length(queryTree)); query = (Query *) lfirst(list_head(queryTree)); } traverseQueryOids(query, relhtab, &relbuf, funchtab, &funcbuf); }
static Query *parseSQL(char *szSqlText) { Assert(szSqlText); Assert(szSqlText); List *plQueryTree = pg_parse_and_rewrite(szSqlText, NULL, 0); if (1 != gpdb::UlListLength(plQueryTree)) { elog(ERROR, "problem parsing query %s", szSqlText); } Query *pquery = (Query *) lfirst(gpdb::PlcListHead(plQueryTree)); return pquery; }
static PlannedStmt *planQuery(char *szSqlText) { Assert(szSqlText); Assert(szSqlText); List *plQueryTree = pg_parse_and_rewrite(szSqlText, NULL, 0); if (1 != gpdb::UlListLength(plQueryTree)) { elog(ERROR, "problem parsing query %s", szSqlText); } Query *pqueryTree = (Query *) lfirst(gpdb::PlcListHead(plQueryTree)); PlannedStmt *pplstmt = pg_plan_query(pqueryTree, NULL); if (!pplstmt) { elog(ERROR, "problem planned query %s. query tree is %s", szSqlText, gpdb::SzNodeToString(pqueryTree)); } return pplstmt; }
/* * Validator for SQL language functions * * Parse it here in order to be sure that it contains no syntax errors. */ Datum fmgr_sql_validator(PG_FUNCTION_ARGS) { Oid funcoid = PG_GETARG_OID(0); HeapTuple tuple; Form_pg_proc proc; List *querytree_list; bool isnull; Datum tmp; char *prosrc; ErrorContextCallback sqlerrcontext; bool haspolyarg; int i; tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcoid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for function %u", funcoid); proc = (Form_pg_proc) GETSTRUCT(tuple); /* Disallow pseudotype result */ /* except for RECORD, VOID, ANYARRAY, or ANYELEMENT */ if (get_typtype(proc->prorettype) == 'p' && proc->prorettype != RECORDOID && proc->prorettype != VOIDOID && proc->prorettype != ANYARRAYOID && proc->prorettype != ANYELEMENTOID) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("SQL functions cannot return type %s", format_type_be(proc->prorettype)))); /* Disallow pseudotypes in arguments */ /* except for ANYARRAY or ANYELEMENT */ haspolyarg = false; for (i = 0; i < proc->pronargs; i++) { if (get_typtype(proc->proargtypes.values[i]) == 'p') { if (proc->proargtypes.values[i] == ANYARRAYOID || proc->proargtypes.values[i] == ANYELEMENTOID) haspolyarg = true; else ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("SQL functions cannot have arguments of type %s", format_type_be(proc->proargtypes.values[i])))); } } /* Postpone body checks if !check_function_bodies */ if (check_function_bodies) { tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); if (isnull) elog(ERROR, "null prosrc"); prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp)); /* * Setup error traceback support for ereport(). */ sqlerrcontext.callback = sql_function_parse_error_callback; sqlerrcontext.arg = tuple; sqlerrcontext.previous = error_context_stack; error_context_stack = &sqlerrcontext; /* * We can't do full prechecking of the function definition if there * are any polymorphic input types, because actual datatypes of * expression results will be unresolvable. The check will be done at * runtime instead. * * We can run the text through the raw parser though; this will at * least catch silly syntactic errors. */ if (!haspolyarg) { querytree_list = pg_parse_and_rewrite(prosrc, proc->proargtypes.values, proc->pronargs); (void) check_sql_fn_retval(funcoid, proc->prorettype, querytree_list, NULL); } else querytree_list = pg_parse_query(prosrc); error_context_stack = sqlerrcontext.previous; } ReleaseSysCache(tuple); PG_RETURN_VOID(); }