diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-07-18 20:26:06 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-07-18 20:26:06 +0000 |
commit | a1c692358bb9958b7cb67e4284aae6aa3aabf714 (patch) | |
tree | 30e5c80eabbbce990ec44aac20f37ff3d8fd80ca /src/backend/commands | |
parent | 6cc88f0af5b12b22ce1826a26b1a953c434bd165 (diff) | |
download | postgresql-a1c692358bb9958b7cb67e4284aae6aa3aabf714.tar.gz postgresql-a1c692358bb9958b7cb67e4284aae6aa3aabf714.zip |
Adjust things so that the query_string of a cached plan and the sourceText of
a portal are never NULL, but reliably provide the source text of the query.
It turns out that there was only one place that was really taking a short-cut,
which was the 'EXECUTE' utility statement. That doesn't seem like a
sufficiently critical performance hotspot to justify not offering a guarantee
of validity of the portal source text. Fix it to copy the source text over
from the cached plan. Add Asserts in the places that set up cached plans and
portals to reject null source strings, and simplify a bunch of places that
formerly needed to guard against nulls.
There may be a few places that cons up statements for execution without
having any source text at all; I found one such in ConvertTriggerToFK().
It seems sufficient to inject a phony source string in such a case,
for instance
ProcessUtility((Node *) atstmt,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
NULL, false, None_Receiver, NULL);
We should take a second look at the usage of debug_query_string,
particularly the recently added current_query() SQL function.
ITAGAKI Takahiro and Tom Lane
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/portalcmds.c | 7 | ||||
-rw-r--r-- | src/backend/commands/prepare.c | 20 | ||||
-rw-r--r-- | src/backend/commands/trigger.c | 5 |
3 files changed, 14 insertions, 18 deletions
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c index 3e5e573c605..1d33b78cde7 100644 --- a/src/backend/commands/portalcmds.c +++ b/src/backend/commands/portalcmds.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.74 2008/05/12 20:01:59 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.75 2008/07/18 20:26:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -68,7 +68,7 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params, RequireTransactionChain(isTopLevel, "DECLARE CURSOR"); /* - * Create a portal and copy the plan into its memory context. + * Create a portal and copy the plan and queryString into its memory. */ portal = CreatePortal(cstmt->portalname, false, false); @@ -77,8 +77,7 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params, stmt = copyObject(stmt); stmt->utilityStmt = NULL; /* make it look like plain SELECT */ - if (queryString) /* copy the source text too for safety */ - queryString = pstrdup(queryString); + queryString = pstrdup(queryString); PortalDefineQuery(portal, NULL, diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index 8361fc67554..bf6aad1ac14 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -10,7 +10,7 @@ * Copyright (c) 2002-2008, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.87 2008/05/12 20:01:59 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.88 2008/07/18 20:26:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -174,6 +174,7 @@ ExecuteQuery(ExecuteStmt *stmt, const char *queryString, ParamListInfo paramLI = NULL; EState *estate = NULL; Portal portal; + char *query_string; /* Look it up in the hash table */ entry = FetchPreparedStatement(stmt->name, true); @@ -203,6 +204,10 @@ ExecuteQuery(ExecuteStmt *stmt, const char *queryString, /* Don't display the portal in pg_cursors, it is for internal use only */ portal->visible = false; + /* Copy the plan's saved query string into the portal's memory */ + query_string = MemoryContextStrdup(PortalGetHeapMemory(portal), + entry->plansource->query_string); + /* * For CREATE TABLE / AS EXECUTE, we must make a copy of the stored query * so that we can modify its destination (yech, but this has always been @@ -249,13 +254,9 @@ ExecuteQuery(ExecuteStmt *stmt, const char *queryString, plan_list = cplan->stmt_list; } - /* - * Note: we don't bother to copy the source query string into the portal. - * Any errors it might be useful for will already have been reported. - */ PortalDefineQuery(portal, NULL, - NULL, + query_string, entry->plansource->commandTag, plan_list, cplan); @@ -777,12 +778,7 @@ pg_prepared_statement(PG_FUNCTION_ARGS) MemSet(nulls, 0, sizeof(nulls)); values[0] = CStringGetTextDatum(prep_stmt->stmt_name); - - if (prep_stmt->plansource->query_string == NULL) - nulls[1] = true; - else - values[1] = CStringGetTextDatum(prep_stmt->plansource->query_string); - + values[1] = CStringGetTextDatum(prep_stmt->plansource->query_string); values[2] = TimestampTzGetDatum(prep_stmt->prepare_time); values[3] = build_regtype_array(prep_stmt->plansource->param_types, prep_stmt->plansource->num_params); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index cc9fd5d08da..44f13df3614 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.235 2008/07/13 20:45:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.236 2008/07/18 20:26:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -728,7 +728,8 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) /* ... and execute it */ ProcessUtility((Node *) atstmt, - NULL, NULL, false, None_Receiver, NULL); + "(generated ALTER TABLE ADD FOREIGN KEY command)", + NULL, false, None_Receiver, NULL); /* Remove the matched item from the list */ info_list = list_delete_ptr(info_list, info); |