diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index c1633ecd8346db393988a6d8eb7c14e4719dbfd2..6557335d994b0bd8dfb3695d3a518556dc2e7caf 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.40 2000/01/26 05:56:11 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.41 2000/04/04 21:44:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -61,7 +61,6 @@ ProcedureCreate(char *procedureName, Oid typeObjectId; List *x; List *querytree_list; - List *plan_list; Oid typev[FUNC_MAX_ARGS]; Oid relid; Oid toid; @@ -222,9 +221,8 @@ ProcedureCreate(char *procedureName, if (strcmp(languageName, "sql") == 0) { - plan_list = pg_parse_and_plan(prosrc, typev, parameterCount, - &querytree_list, dest, FALSE); - + querytree_list = pg_parse_and_rewrite(prosrc, typev, parameterCount, + FALSE); /* typecheck return value */ pg_checkretval(typeObjectId, querytree_list); } diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 5a7f4c0889fb72aae4ff3b8b1781e594c9f73c80..3854978029b2393a7f5c1f0f3b59d905164c027d 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.31 2000/01/26 05:56:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.32 2000/04/04 21:44:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -84,7 +84,6 @@ init_execution_state(FunctionCachePtr fcache, execution_state *nextes; execution_state *preves; List *queryTree_list, - *planTree_list, *qtl_item; int nargs = fcache->nargs; @@ -92,15 +91,17 @@ init_execution_state(FunctionCachePtr fcache, nextes = newes; preves = (execution_state *) NULL; - planTree_list = pg_parse_and_plan(fcache->src, fcache->argOidVect, - nargs, &queryTree_list, None, FALSE); + queryTree_list = pg_parse_and_rewrite(fcache->src, fcache->argOidVect, + nargs, FALSE); foreach(qtl_item, queryTree_list) { Query *queryTree = lfirst(qtl_item); - Plan *planTree = lfirst(planTree_list); + Plan *planTree; EState *estate; + planTree = pg_plan_query(queryTree); + if (!nextes) nextes = (execution_state *) palloc(sizeof(execution_state)); if (preves) @@ -141,8 +142,6 @@ init_execution_state(FunctionCachePtr fcache, nextes->estate = estate; preves = nextes; nextes = (execution_state *) NULL; - - planTree_list = lnext(planTree_list); } return newes; @@ -151,15 +150,12 @@ init_execution_state(FunctionCachePtr fcache, static TupleDesc postquel_start(execution_state *es) { -#ifdef FUNC_UTIL_PATCH - /* * Do nothing for utility commands. (create, destroy...) DZ - * 30-8-1996 */ if (es->qd->operation == CMD_UTILITY) return (TupleDesc) NULL; -#endif return ExecutorStart(es->qd, es->estate); } @@ -168,12 +164,10 @@ postquel_getnext(execution_state *es) { int feature; -#ifdef FUNC_UTIL_PATCH if (es->qd->operation == CMD_UTILITY) { - /* - * Process an utility command. (create, destroy...) DZ - + * Process a utility command. (create, destroy...) DZ - * 30-8-1996 */ ProcessUtility(es->qd->parsetree->utilityStmt, es->qd->dest); @@ -181,7 +175,6 @@ postquel_getnext(execution_state *es) CommandCounterIncrement(); return (TupleTableSlot *) NULL; } -#endif feature = (LAST_POSTQUEL_COMMAND(es)) ? EXEC_RETONE : EXEC_RUN; @@ -191,15 +184,12 @@ postquel_getnext(execution_state *es) static void postquel_end(execution_state *es) { -#ifdef FUNC_UTIL_PATCH - /* * Do nothing for utility commands. (create, destroy...) DZ - * 30-8-1996 */ if (es->qd->operation == CMD_UTILITY) return; -#endif ExecutorEnd(es->qd, es->estate); } diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 7c65c66814f863bdaa590c88af77936c27d0e3ea..016d15ae8ac56a0c6a4b38aeda401240ed7160d2 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -3,7 +3,7 @@ * spi.c * Server Programming Interface * - * $Id: spi.c,v 1.44 1999/12/16 22:19:44 wieck Exp $ + * $Id: spi.c,v 1.45 2000/04/04 21:44:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -622,7 +622,6 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan) List *queryTree_list; List *planTree_list; List *queryTree_list_item; - List *ptlist; QueryDesc *qdesc; Query *queryTree; Plan *planTree; @@ -645,18 +644,20 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan) nargs = plan->nargs; argtypes = plan->argtypes; } - ptlist = planTree_list = - pg_parse_and_plan(src, argtypes, nargs, &queryTree_list, None, FALSE); + + queryTree_list = pg_parse_and_rewrite(src, argtypes, nargs, FALSE); _SPI_current->qtlist = queryTree_list; + planTree_list = NIL; + foreach(queryTree_list_item, queryTree_list) { queryTree = (Query *) lfirst(queryTree_list_item); - planTree = lfirst(planTree_list); - planTree_list = lnext(planTree_list); - islastquery = (planTree_list == NIL); /* assume lists are same - * len */ + islastquery = (lnext(queryTree_list_item) == NIL); + + planTree = pg_plan_query(queryTree); + planTree_list = lappend(planTree_list, planTree); if (queryTree->commandType == CMD_UTILITY) { @@ -707,7 +708,7 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan) } plan->qtlist = queryTree_list; - plan->ptlist = ptlist; + plan->ptlist = planTree_list; return res; } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index a70418637f729ae4c2225996a2591893155f2485..65b6bfbd6c0016036ea44629b694b7097261d0bc 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.148 2000/03/23 23:16:48 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.149 2000/04/04 21:44:39 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -377,22 +377,23 @@ ReadCommand(StringInfo inBuf) return result; } + +/* + * Parse a query string and pass it through the rewriter. + * + * A list of Query nodes is returned, since the string might contain + * multiple queries and/or the rewriter might expand one query to several. + */ List * -pg_parse_and_plan(char *query_string, /* string to execute */ - Oid *typev, /* argument types */ - int nargs, /* number of arguments */ - List **queryListP, /* returned pointer to the parse - * trees */ - CommandDest dest, /* where results should go */ - bool aclOverride) +pg_parse_and_rewrite(char *query_string, /* string to execute */ + Oid *typev, /* argument types */ + int nargs, /* number of arguments */ + bool aclOverride) { - List *querytree_list = NIL; - List *plan_list = NIL; + List *querytree_list; List *querytree_list_item; Query *querytree; - Plan *plan; List *new_list; - List *rewritten; if (DebugPrintQuery) { @@ -448,15 +449,16 @@ pg_parse_and_plan(char *query_string, /* string to execute */ else { /* rewrite regular queries */ - rewritten = QueryRewrite(querytree); + List *rewritten = QueryRewrite(querytree); new_list = nconc(new_list, rewritten); } } querytree_list = new_list; - /* - * Override ACL checking if requested + /* ---------------- + * (3) If ACL override is requested, mark queries for no ACL check. + * ---------------- */ if (aclOverride) { @@ -503,87 +505,54 @@ pg_parse_and_plan(char *query_string, /* string to execute */ } } - foreach(querytree_list_item, querytree_list) - { - querytree = (Query *) lfirst(querytree_list_item); - - /* - * For each query that isn't a utility invocation, generate a - * plan. - */ - - if (querytree->commandType != CMD_UTILITY) - { + return querytree_list; +} - if (IsAbortedTransactionBlockState()) - { - /* ---------------- - * the EndCommand() stuff is to tell the frontend - * that the command ended. -cim 6/1/90 - * ---------------- - */ - char *tag = "*ABORT STATE*"; - EndCommand(tag, dest); +/* Generate a plan for a single query. */ +Plan * +pg_plan_query(Query *querytree) +{ + Plan *plan; - elog(NOTICE, "(transaction aborted): %s", - "queries ignored until END"); + /* Utility commands have no plans. */ + if (querytree->commandType == CMD_UTILITY) + return NULL; - if (queryListP) - *queryListP = NIL; - return NIL; - } + if (ShowPlannerStats) + ResetUsage(); - if (ShowPlannerStats) - ResetUsage(); + /* call that optimizer */ + plan = planner(querytree); - /* call that optimizer */ - plan = planner(querytree); + if (ShowPlannerStats) + { + fprintf(stderr, "! Planner Stats:\n"); + ShowUsage(); + } - if (ShowPlannerStats) - { - fprintf(stderr, "! Planner Stats:\n"); - ShowUsage(); - } - plan_list = lappend(plan_list, plan); -#ifdef INDEXSCAN_PATCH - /* ---------------- - * Print plan if debugging. - * This has been moved here to get debugging output - * also for queries in functions. DZ - 27-8-1996 - * ---------------- - */ - if (DebugPrintPlan || DebugPPrintPlan) - { - if (DebugPPrintPlan) - { - TPRINTF(TRACE_PRETTY_PLAN, "plan:"); - nodeDisplay(plan); - } - else - { - TPRINTF(TRACE_PLAN, "plan:"); - printf("\n%s\n\n", nodeToString(plan)); - } - } -#endif + /* ---------------- + * Print plan if debugging. + * ---------------- + */ + if (DebugPrintPlan || DebugPPrintPlan) + { + if (DebugPPrintPlan) + { + TPRINTF(TRACE_PRETTY_PLAN, "plan:"); + nodeDisplay(plan); } - - /* - * If the command is an utility append a null plan. This is needed - * to keep the plan_list aligned with the querytree_list or the - * function executor will crash. DZ - 30-8-1996 - */ else - plan_list = lappend(plan_list, NULL); + { + TPRINTF(TRACE_PLAN, "plan:"); + printf("\n%s\n\n", nodeToString(plan)); + } } - if (queryListP) - *queryListP = querytree_list; - - return plan_list; + return plan; } + /* ---------------------------------------------------------------- * pg_exec_query() * @@ -620,39 +589,31 @@ pg_exec_query_dest(char *query_string, /* string to execute */ * of superusers */ { List *querytree_list; - List *plan_list; - Query *querytree; - Plan *plan; - int j; - /* plan the queries */ - plan_list = pg_parse_and_plan(query_string, NULL, 0, - &querytree_list, dest, aclOverride); - - /* if we got a cancel signal whilst planning, quit */ - if (QueryCancel) - CancelQuery(); - - /* OK, do it to it! */ + /* parse and rewrite the queries */ + querytree_list = pg_parse_and_rewrite(query_string, NULL, 0, + aclOverride); /* * NOTE: we do not use "foreach" here because we want to be sure the - * list pointers have been advanced before the query is executed. We + * list pointer has been advanced before the query is executed. We * need to do that because VACUUM has a nasty little habit of doing * CommitTransactionCommand at startup, and that will release the - * memory holding our parse/plan lists :-(. This needs a better + * memory holding our parse list :-(. This needs a better * solution --- currently, the code will crash if someone submits * "vacuum; something-else" in a single query string. But memory * allocation needs redesigned anyway, so this will have to do for * now. */ - while (querytree_list) { - querytree = (Query *) lfirst(querytree_list); + Query *querytree = (Query *) lfirst(querytree_list); + querytree_list = lnext(querytree_list); - plan = (Plan *) lfirst(plan_list); - plan_list = lnext(plan_list); + + /* if we got a cancel signal in parsing or prior command, quit */ + if (QueryCancel) + CancelQuery(); if (querytree->commandType == CMD_UTILITY) { @@ -668,42 +629,38 @@ pg_exec_query_dest(char *query_string, /* string to execute */ else if (Verbose) TPRINTF(TRACE_VERBOSE, "ProcessUtility"); - /* - * We have to set query SnapShot in the case of FETCH or COPY TO. - */ - if (nodeTag(querytree->utilityStmt) == T_FetchStmt || - (nodeTag(querytree->utilityStmt) == T_CopyStmt && - ((CopyStmt *)(querytree->utilityStmt))->direction != FROM)) - SetQuerySnapshot(); ProcessUtility(querytree->utilityStmt, dest); } else { -#ifdef INDEXSCAN_PATCH + Plan *plan; + int j; - /* - * Print moved in pg_parse_and_plan. DZ - 27-8-1996 - */ -#else - /* ---------------- - * print plan if debugging - * ---------------- - */ - if (DebugPrintPlan || DebugPPrintPlan) + /* If aborted transaction, quit now */ + if (IsAbortedTransactionBlockState()) { - if (DebugPPrintPlan) - { - TPRINTF(TRACE_PRETTY_PLAN, "plan:"); - nodeDisplay(plan); - } - else - { - TPRINTF(TRACE_PLAN, "plan:"); - printf("\n%s\n\n", nodeToString(plan)); - } + /* ---------------- + * the EndCommand() stuff is to tell the frontend + * that the command ended. -cim 6/1/90 + * ---------------- + */ + char *tag = "*ABORT STATE*"; + + elog(NOTICE, "current transaction is aborted, " + "queries ignored until end of transaction block"); + + EndCommand(tag, dest); + + break; } -#endif + plan = pg_plan_query(querytree); + + /* if we got a cancel signal whilst planning, quit */ + if (QueryCancel) + CancelQuery(); + + /* Initialize snapshot state for query */ SetQuerySnapshot(); /* @@ -1505,7 +1462,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.148 $ $Date: 2000/03/23 23:16:48 $\n"); + puts("$Revision: 1.149 $ $Date: 2000/04/04 21:44:39 $\n"); } /* diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 62ad6d8f9571bd780b49c74ecfd8009857c68f28..d3ba5b319dd7a8072726d61ba698eb1bb02b20bd 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.84 2000/02/19 02:29:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.85 2000/04/04 21:44:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -136,6 +136,8 @@ ProcessUtility(Node *parsetree, PS_SET_STATUS(commandTag = (stmt->ismove) ? "MOVE" : "FETCH"); CHECK_IF_ABORTED(); + SetQuerySnapshot(); + forward = (bool) (stmt->direction == FORWARD); /* @@ -255,6 +257,9 @@ ProcessUtility(Node *parsetree, PS_SET_STATUS(commandTag = "COPY"); CHECK_IF_ABORTED(); + if (stmt->direction != FROM) + SetQuerySnapshot(); + DoCopy(stmt->relname, stmt->binary, stmt->oids, diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h index 283e517ccce18d726f88cbc183a90501d56a4500..8255770068fe80e73c0ff6b78b758b2ff354fdc4 100644 --- a/src/include/tcop/tcopprot.h +++ b/src/include/tcop/tcopprot.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: tcopprot.h,v 1.25 2000/02/20 14:28:28 petere Exp $ + * $Id: tcopprot.h,v 1.26 2000/04/04 21:44:37 tgl Exp $ * * OLD COMMENTS * This file was created so that other c files could get the two @@ -29,12 +29,15 @@ extern bool InError; extern bool ExitAfterAbort; #ifndef BOOTSTRAP_INCLUDE -extern List *pg_parse_and_plan(char *query_string, Oid *typev, int nargs, - List **queryListP, CommandDest dest, - bool aclOverride); + +extern List *pg_parse_and_rewrite(char *query_string, + Oid *typev, int nargs, + bool aclOverride); +extern Plan *pg_plan_query(Query *querytree); extern void pg_exec_query_acl_override(char *query_string); -extern void - pg_exec_query_dest(char *query_string, CommandDest dest, bool aclOverride); +extern void pg_exec_query_dest(char *query_string, + CommandDest dest, + bool aclOverride); #endif /* BOOTSTRAP_INCLUDE */