Hi Tom, While going through few test-cases, I found that we cannot have two opened cursors with same name even though they are in two different functions. Here is what I mean:
1. I have two functions func1 and func2. 2. func1 calls func2 3. Both has cursor with same name, say mycursor 4. Somehow I forgot closing it 5. executing func1 throws an error 'cursor "mycursor" already in use' Is this expected behavior??? I just mingled around the code and later appended a cursor count to the cursor name to allow same cursor name in nested levels. I have run make check and didn't find any side-effect other than one expected output change. PFA, patch for the same. Please let me know your views / suggestions. Thanks Test-case: === CREATE OR REPLACE FUNCTION func1() RETURNS void AS $$ DECLARE res int; mycursor CURSOR FOR SELECT 'foo'; BEGIN OPEN mycursor; SELECT func2() INTO res; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION func2() RETURNS int AS $$ DECLARE mycursor CURSOR FOR SELECT 'bar'; BEGIN OPEN mycursor; return 1; END; $$ LANGUAGE plpgsql; SELECT func1(); ERROR: cursor "mycursor" already in use CONTEXT: PL/pgSQL function "func2" line 5 at OPEN SQL statement "SELECT func2()" PL/pgSQL function "func1" line 7 at SQL statement -- Jeevan B Chalke Senior Software Engineer, R&D EnterpriseDB Corporation The Enterprise PostgreSQL Company Phone: +91 20 30589500 Website: www.enterprisedb.com EnterpriseDB Blog: http://blogs.enterprisedb.com/ Follow us on Twitter: http://www.twitter.com/enterprisedb This e-mail message (and any attachment) is intended for the use of the individual or entity to whom it is addressed. This message contains information from EnterpriseDB Corporation that may be privileged, confidential, or exempt from disclosure under applicable law. If you are not the intended recipient or authorized to receive this for the intended recipient, any use, dissemination, distribution, retention, archiving, or copying of this communication is strictly prohibited. If you have received this e-mail in error, please notify the sender immediately by reply e-mail and delete this message.
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index 92b54dd..46e7442 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -509,6 +509,7 @@ decl_statement : decl_varname decl_const decl_datatype decl_collate decl_notnull char buf[1024]; char *cp1; char *cp2; + static unsigned int cursor_count = 0; /* pop local namespace for cursor args */ plpgsql_ns_pop(); @@ -539,7 +540,13 @@ decl_statement : decl_varname decl_const decl_datatype decl_collate decl_notnull *cp2++ = *cp1; *cp2++ = *cp1++; } - strcpy(cp2, "'::pg_catalog.refcursor"); + + /* + * Append cursor count after cursor name to remove + * conflict of same named cursor in different + * nested levels. + */ + snprintf(cp2, sizeof(buf) - strlen(buf), ":%u'::pg_catalog.refcursor", cursor_count++); curname_def->query = pstrdup(buf); new->default_val = curname_def; diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index bed34c8..4bdccf3 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -3284,15 +3284,15 @@ begin end; $$ language plpgsql; select forc01(); -NOTICE: 5 from c -NOTICE: 6 from c -NOTICE: 7 from c -NOTICE: 9 from c -NOTICE: 10 from c -NOTICE: 41 from c2 -NOTICE: 42 from c2 -NOTICE: 43 from c2 -NOTICE: after loop, c2 = c2 +NOTICE: 5 from c:5 +NOTICE: 6 from c:5 +NOTICE: 7 from c:5 +NOTICE: 9 from c:5 +NOTICE: 10 from c:5 +NOTICE: 41 from c2:6 +NOTICE: 42 from c2:6 +NOTICE: 43 from c2:6 +NOTICE: after loop, c2 = c2:6 NOTICE: 41 from special_name NOTICE: 42 from special_name NOTICE: 43 from special_name
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers