Skip to content

Commit 37276b7

Browse files
committed
Updated code to assign stmt conditionally, free up memory context, added
comments and code refactoring Signed-off-by: Shard Gupta <shardga@amazon.com>
1 parent fd04eaf commit 37276b7

File tree

1 file changed

+42
-12
lines changed

1 file changed

+42
-12
lines changed

contrib/babelfishpg_tsql/src/cursor.c

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,20 +1450,9 @@ execute_sp_cursoropen_common(int *stmt_handle, int *cursor_handle, const char *s
14501450
MemoryContext oldcontext;
14511451
MemoryContext savedPortalCxt;
14521452
PLtsql_stmt_execsql *parse_result;
1453-
PLtsql_function *function;
1453+
PLtsql_function *func;
14541454
char *stmt_copy;
14551455

1456-
/*
1457-
* Parse the function's text
1458-
*/
1459-
if(stmt)
1460-
{
1461-
stmt_copy = pstrdup(stmt);
1462-
function = pltsql_compile_inline(stmt_copy, NULL);
1463-
parse_result = (PLtsql_stmt_execsql *) lsecond(function->action->body);
1464-
stmt = parse_result->sqlstmt->query;
1465-
}
1466-
14671456
/*
14681457
* Connect to SPI manager. should be handled in the same way with
14691458
* pltsql_inline_handler()
@@ -1482,6 +1471,47 @@ execute_sp_cursoropen_common(int *stmt_handle, int *cursor_handle, const char *s
14821471

14831472
if (prepare)
14841473
{
1474+
/*
1475+
* This entire block is to parse the statement by antlr and use the resultant
1476+
* statement to sent to Postgres cursor execution. This is necessary in some use case,
1477+
* for example when we have PostgreSQL reversed keywords in query which is valid in TSQL.
1478+
* Antlr parser will add the quotes at necessary places in query so that Postgres engine
1479+
* can resolve this query correctly.
1480+
*/
1481+
if (stmt)
1482+
{
1483+
// Copy the original statement, because we don't want to use the resultant query in every case.
1484+
stmt_copy = pstrdup(stmt);
1485+
// Send to antlr parser
1486+
func = pltsql_compile_inline(stmt_copy, NULL);
1487+
// Increase function use count, so that we don't deallocate function memory accidently
1488+
func->use_count++;
1489+
1490+
/*
1491+
* Check the node list of type PLtsql_stmt_type. Cursor only support single statement.
1492+
* If there are more than 1 statement we will through the error. func->action-body
1493+
* returned by pltsql_compile_inline contains two default nodes, PLTSQL_STMT_INIT being first
1494+
* and PLTSQL_STMT_RETURN being last. So total number of nodes should be 3 for cursor. Actual
1495+
* query statement will be at second position of type PLTSQL_STMT_EXECSQL.
1496+
1497+
* This is defensive code, where we only reassign the stmt variable to parsed query,
1498+
* if the cmd_type is PLTSQL_STMT_EXECSQL. There might be other types of cmd_type like
1499+
* PLTSQL_STMT_EXECSQL (for procedures), for them we will keep the old behavior.
1500+
*/
1501+
if((( (PLtsql_stmt *) lsecond(func->action->body))->cmd_type ==
1502+
PLTSQL_STMT_EXECSQL) && list_length(func->action->body) == 3)
1503+
{
1504+
parse_result = (PLtsql_stmt_execsql *) lsecond(func->action->body);
1505+
stmt = pstrdup(parse_result->sqlstmt->query);
1506+
}
1507+
1508+
//Function is not need anymore, so decrease the usage count and free function memory.
1509+
func->use_count--;
1510+
Assert(func->use_count == 0);
1511+
pltsql_free_function_memory(func);
1512+
}
1513+
1514+
14851515
/* prepare plan and insert a cursor entry */
14861516
plan = SPI_prepare_cursor(stmt, nBindParams, boundParamsOidList, cursor_options);
14871517
if (plan == NULL)

0 commit comments

Comments
 (0)