Пример #1
0
/*
 * 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);
	}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
/*
 * 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();
}