Hi All,

Consider the following testcase:

postgres=# select version();

version
-------------------------------------------------------------------------------------------------
 PostgreSQL 9.3devel on i686-pc-linux-gnu, compiled by gcc (Ubuntu
4.4.3-4ubuntu5) 4.4.3, 32-bit
(1 row)

postgres=# do $$
declare
 t cursor for explain SELECT n into tbl from generate_series(1,10) n;
begin
 open t;
end
$$;
The connection to the server was lost. Attempting reset: Failed.

Above testcase endup with server crash. Crash is due to following assert
into ScanQueryForLocks()

Assert(parsetree->commandType != CMD_UTILITY);

Testcase works fine with earlier version.

Description :
==========

Here is the stack for the crash:

#0  ScanQueryForLocks (parsetree=0xa304ea4, acquire=1 '\001') at
plancache.c:1324
#1  0x08447e81 in AcquirePlannerLocks (stmt_list=0xa304dcc, acquire=1
'\001') at plancache.c:1306
#2  0x08446c34 in RevalidateCachedQuery (plansource=0xa3041bc) at
plancache.c:460
#3  0x0844743a in GetCachedPlan (plansource=0xa3041bc, boundParams=0x0,
useResOwner=0 '\000') at plancache.c:936
#4  0x0827047a in SPI_cursor_open_internal (name=0xa2fc124 "t",
plan=0xa3059dc, paramLI=0x0, read_only=0 '\000') at spi.c:1187
#5  0x0827024e in SPI_cursor_open_with_paramlist (name=0xa2fc124 "t",
plan=0xa3059dc, params=0x0, read_only=0 '\000') at spi.c:1112
#6  0x002c59ec in exec_stmt_open (estate=0xbfc3c4d0, stmt=0xa2fd4c0) at
pl_exec.c:3534


Here query->commandType is CMD_UTILITY, and its utilitystmt contain
CreateTableAsStmt. Now looking further I found that for any SELECT .. INTO
.. clause we create CreateTableAsStmt to remove the into clause from the
select stmt.

In the above mentioned stack before calling ScanQueryForLocks(),
AcquirePlannerLocks() do having check for CMD_UTILITY and it fetch Query
from the utility stmt. To get the Query stmt from Utilty command it calls
UtilityContainsQuery().

Into UtilityContainsQuery() we need to handle ExplainStmt properlly for the
the SELECT INTO so that it returns proper contained Query Stmt.

PFA patch for the same.

Thanks,


-- 
Rushabh Lathia
www.EnterpriseDB.com
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 8b73858..9286ce5 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1362,9 +1362,20 @@ UtilityContainsQuery(Node *parsetree)
 	switch (nodeTag(parsetree))
 	{
 		case T_ExplainStmt:
-			Assert(IsA(((ExplainStmt *) parsetree)->query, Query));
-			return (Query *) ((ExplainStmt *) parsetree)->query;
-
+			{
+				Query *qry;
+				Assert(IsA(((ExplainStmt *) parsetree)->query, Query));
+				qry = (Query *) ((ExplainStmt *) parsetree)->query;
+				/*
+				 * Any SELECT..INTO clause get transformed to CreateTableAsStmt,
+				 * and thats CMD_UTILITY stmt. So if CMD_UTILITY found for any
+				 * ExplainStmt Query then call UtilityConainsQuery() again
+				 * to fetch the proper contained query.
+				 */
+				if (qry->commandType == CMD_UTILITY)
+					qry = UtilityContainsQuery(qry->utilityStmt);
+				return qry;
+			}
 		case T_CreateTableAsStmt:
 			/* might or might not contain a Query ... */
 			if (IsA(((CreateTableAsStmt *) parsetree)->query, Query))
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to