/** * @brief Create a table in Postgres * @params table_name table name * @return table_oid */ oid_t BridgeTest::CreateTableInPostgres(std::string table_name) { std::string queryString = "create table " + table_name + "(id int, name char(64), time timestamp, salary double precision);"; ObjectAddress address; List *parsetree_list; ListCell *parsetree_item; // FIXME Do we need now? // StartTransactionCommand(); parsetree_list = pg_parse_query(queryString.c_str()); foreach (parsetree_item, parsetree_list) { Node *parsetree = (Node *)lfirst(parsetree_item); List *stmts; /* Run parse analysis ... */ stmts = transformCreateStmt((CreateStmt *)parsetree, queryString.c_str()); /* ... and do it */ ListCell *l; foreach (l, stmts) { Node *stmt = (Node *)lfirst(l); if (IsA(stmt, CreateStmt)) { /* Create the table itself */ address = DefineRelation((CreateStmt *)stmt, RELKIND_RELATION, InvalidOid, NULL); } }
static PlannedStmt* get_combiner_plan(ContinuousView *view) { List *parsetree_list; SelectStmt *selectstmt; PlannedStmt *result; parsetree_list = pg_parse_query(view->query); Assert(list_length(parsetree_list) == 1); selectstmt = (SelectStmt *) linitial(parsetree_list); selectstmt = TransformSelectStmtForContProcess(view->matrel, selectstmt, NULL, Combiner); join_search_hook = get_combiner_join_rel; PG_TRY(); { result = get_plan_from_stmt(view->id, (Node *) selectstmt, view->query, true); join_search_hook = NULL; post_parse_analyze_hook = NULL; } PG_CATCH(); { /* * These hooks won't be reset if there's an error, so we need to make * sure that they're not set for whatever query is run next in this xact. */ join_search_hook = NULL; post_parse_analyze_hook = NULL; PG_RE_THROW(); } PG_END_TRY(); return result; }
static enum proto_parse_status pg_sbuf_parse(struct parser *parser, struct proto_info *parent, unsigned way, uint8_t const *payload, size_t cap_len, size_t wire_len, struct timeval const *now, size_t tot_cap_len, uint8_t const *tot_packet) { struct pgsql_parser *pg_parser = DOWNCAST(parser, parser, pgsql_parser); // If this is the first time we are called, init c2s_way if (pg_parser->c2s_way == UNSET) { SLOG(LOG_DEBUG, "First packet, init c2s_way to %u", way); pg_parser->c2s_way = way; } // Now build the proto_info struct sql_proto_info info; proto_info_ctor(&info.info, parser, parent, wire_len, 0); info.is_query = way == pg_parser->c2s_way; info.set_values = 0; switch (pg_parser->phase) { case NONE: return pg_parse_init (pg_parser, &info, way, payload, cap_len, wire_len, now, tot_cap_len, tot_packet); case STARTUP: return pg_parse_startup(pg_parser, &info, way, payload, cap_len, wire_len, now, tot_cap_len, tot_packet); case QUERY: return pg_parse_query (pg_parser, &info, way, payload, cap_len, wire_len, now, tot_cap_len, tot_packet); case EXIT: return PROTO_PARSE_ERR; // we do not expect payload after a termination message } return PROTO_PARSE_ERR; }
/* * Parse and plan a querystring. * * At entry, plan->argtypes and plan->nargs must be valid. * * Query and plan lists are stored into *plan. */ static void _SPI_prepare_plan(const char *src, _SPI_plan *plan) { List *raw_parsetree_list; List *query_list_list; List *plan_list; ListCell *list_item; ErrorContextCallback spierrcontext; Oid *argtypes = plan->argtypes; int nargs = plan->nargs; /* * Increment CommandCounter to see changes made by now. We must do * this to be sure of seeing any schema changes made by a just-preceding * SPI command. (But we don't bother advancing the snapshot, since the * planner generally operates under SnapshotNow rules anyway.) */ CommandCounterIncrement(); /* * Setup error traceback support for ereport() */ spierrcontext.callback = _SPI_error_callback; spierrcontext.arg = (void *) src; spierrcontext.previous = error_context_stack; error_context_stack = &spierrcontext; /* * Parse the request string into a list of raw parse trees. */ raw_parsetree_list = pg_parse_query(src); /* * Do parse analysis and rule rewrite for each raw parsetree. * * We save the querytrees from each raw parsetree as a separate * sublist. This allows _SPI_execute_plan() to know where the * boundaries between original queries fall. */ query_list_list = NIL; plan_list = NIL; foreach(list_item, raw_parsetree_list) { Node *parsetree = (Node *) lfirst(list_item); List *query_list; query_list = pg_analyze_and_rewrite(parsetree, argtypes, nargs); query_list_list = lappend(query_list_list, query_list); plan_list = list_concat(plan_list, pg_plan_queries(query_list, NULL, false)); }
static PlannedStmt* get_worker_plan(ContinuousView *view) { List *parsetree_list; SelectStmt *selectstmt; parsetree_list = pg_parse_query(view->query); Assert(list_length(parsetree_list) == 1); selectstmt = (SelectStmt *) linitial(parsetree_list); selectstmt = TransformSelectStmtForContProcess(view->matrel, selectstmt, NULL, Worker); return get_plan_from_stmt(view->id, (Node *) selectstmt, view->query, selectstmt->forCombiner); }
static SelectStmt * get_worker_select_stmt(ContinuousView* view, SelectStmt** viewptr) { List *parsetree_list; SelectStmt *selectstmt; parsetree_list = pg_parse_query(view->query); Assert(list_length(parsetree_list) == 1); selectstmt = (SelectStmt *) linitial(parsetree_list); selectstmt->swStepFactor = view->sw_step_factor; selectstmt = TransformSelectStmtForContProcess(view->matrel, selectstmt, viewptr, Worker); return selectstmt; }
/* * 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(); }
/* * import_stats_from_file * load data from file or stdin into work table, and delete unnecessary * records. */ static void import_stats_from_file(char *filename, char *nspname, char *relname, char *attname) { StringInfoData buf; List *parsetree_list; uint64 processed; Datum values[3]; Oid argtypes[3] = { CSTRINGOID, CSTRINGOID, CSTRINGOID }; char nulls[3] = { 'n', 'n', 'n' }; int nargs; int ret; /* for debug use */ elog(DEBUG3, "%s() f=%s n=%s r=%s a=%s", __FUNCTION__, filename ? filename : "(null)", nspname ? nspname : "(null)", relname ? relname : "(null)", attname ? attname : "(null)"); /* * Construct COPY statement. NULL for filename indicates that source is * stdin. */ initStringInfo(&buf); appendStringInfoString(&buf, "COPY dbms_stats_work_stats FROM "); if (filename == NULL) appendStringInfoString(&buf, "stdin"); else appendLiteral(&buf, filename); appendStringInfoString(&buf, " (FORMAT 'binary')"); /* Execute COPY FROM command. */ parsetree_list = pg_parse_query(buf.data); #if PG_VERSION_NUM >= 90300 DoCopy((CopyStmt *)linitial(parsetree_list), buf.data, &processed); #else processed = DoCopy((CopyStmt *)linitial(parsetree_list), buf.data); #endif if (processed == 0) elog(ERROR, "no data to be imported"); /* * Delete the statistics other than the specified object's statistic from * the temp table. We can skip DELETEing staging data when schemaname is * NULL, because it means database-wise import. */ if (nspname == NULL) return; resetStringInfo(&buf); appendStringInfoString(&buf, "DELETE FROM dbms_stats_work_stats " " WHERE nspname <> $1::text "); values[0] = CStringGetDatum(nspname); nulls[0] = 't'; nargs = 1; if (relname != NULL) { values[1] = CStringGetDatum(relname); nulls[1] = 't'; nargs++; appendStringInfoString(&buf, " OR (relname <> $2::text) "); if (attname != NULL) { values[2] = CStringGetDatum(attname); nulls[2] = 't'; nargs++; appendStringInfoString(&buf, " OR (attname <> $3::text) "); } } ret = SPI_execute_with_args(buf.data, nargs, argtypes, values, nulls, false, 0); if (ret != SPI_OK_DELETE) elog(ERROR, "pg_dbms_stats: SPI_execute_with_args => %d", ret); }