Skip to content

Commit 3604933

Browse files
committed
Address review comments
Signed-off-by: Shard Gupta <shardga@amazon.com>
1 parent eaa28d3 commit 3604933

File tree

3 files changed

+41
-13
lines changed

3 files changed

+41
-13
lines changed

contrib/babelfishpg_tsql/src/cursor.c

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,7 @@ execute_sp_cursoropen_common(int *stmt_handle, int *cursor_handle, const char *s
14521452
PLtsql_stmt_execsql *parse_result;
14531453
PLtsql_function *func;
14541454
char *stmt_copy;
1455+
const char *tsql_stmt = stmt; /* Use this for potentially modified statement */
14551456

14561457
/*
14571458
* Connect to SPI manager. should be handled in the same way with
@@ -1472,9 +1473,9 @@ execute_sp_cursoropen_common(int *stmt_handle, int *cursor_handle, const char *s
14721473
if (prepare)
14731474
{
14741475
/*
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.
1476+
* This entire block is to parse the statement by antlr and use the statement for
1477+
* cursor execution. This is necessary in some use case, for example when we have
1478+
* PostgreSQL reversed keywords in query which is valid in TSQL.
14781479
* Antlr parser will add the quotes at necessary places in query so that Postgres engine
14791480
* can resolve this query correctly.
14801481
*/
@@ -1488,29 +1489,38 @@ execute_sp_cursoropen_common(int *stmt_handle, int *cursor_handle, const char *s
14881489
/*
14891490
* Check the node list of type PLtsql_stmt_type. Cursor only support single statement.
14901491
* If there are more than 1 statement we will through the error. func->action-body
1491-
* returned by pltsql_compile_inline contains two default nodes, PLTSQL_STMT_INIT being first
1492-
* and PLTSQL_STMT_RETURN being last. So total number of nodes should be 3 for cursor. Actual
1493-
* query statement will be at second position of type PLTSQL_STMT_EXECSQL.
1494-
1495-
* This is defensive code, where we only reassign the stmt variable to parsed query,
1492+
* returned by pltsql_compile_inline generally contains two default nodes, PLTSQL_STMT_INIT being first
1493+
* and PLTSQL_STMT_RETURN being last. In case of empty statement only PLTSQL_STMT_RETURN node will be present.
1494+
* So total number of nodes should be 3 for valid cursor execution. Actual query statement will be at second
1495+
* position of type PLTSQL_STMT_EXECSQL.
1496+
1497+
* This is defensive code, where we only assign the tsql_stmt variable to parsed query,
14961498
* if the cmd_type is PLTSQL_STMT_EXECSQL. There might be other types of cmd_type like
14971499
* PLTSQL_STMT_EXECSQL (for procedures), for them we will keep the old behavior.
1500+
* list length should be checked first before trying to deference second node from the list.
1501+
* FIXME:We are handling only PLtsql_stmt_execsql type statement, but TSQL support procedure with
1502+
* single statement. We also need to explore all other statement types for completion.
14981503
*/
1499-
if((( (PLtsql_stmt *) lsecond(func->action->body))->cmd_type == PLTSQL_STMT_EXECSQL)
1500-
&& list_length(func->action->body) == 3)
1504+
if(list_length(func->action->body) == 3 &&
1505+
((PLtsql_stmt *) lsecond(func->action->body))->cmd_type == PLTSQL_STMT_EXECSQL)
15011506
{
15021507
parse_result = (PLtsql_stmt_execsql *) lsecond(func->action->body);
1503-
stmt = pstrdup(parse_result->sqlstmt->query);
1508+
tsql_stmt = pstrdup(parse_result->sqlstmt->query);
15041509
}
15051510

15061511
/*Free up function memory as this is not needed anymore */
15071512
pltsql_free_function_memory(func);
15081513
}
15091514

15101515
/* prepare plan and insert a cursor entry */
1511-
plan = SPI_prepare_cursor(stmt, nBindParams, boundParamsOidList, cursor_options);
1516+
plan = SPI_prepare_cursor(tsql_stmt, nBindParams, boundParamsOidList, cursor_options);
15121517
if (plan == NULL)
1518+
{
1519+
/* Free memory if tsql_stmt is different from stmt */
1520+
if (tsql_stmt != stmt)
1521+
pfree((void *)tsql_stmt);
15131522
return 1; /* procedure failed */
1523+
}
15141524

15151525
if (save_plan)
15161526
{
@@ -1525,6 +1535,10 @@ execute_sp_cursoropen_common(int *stmt_handle, int *cursor_handle, const char *s
15251535

15261536
SPI_keepplan(plan);
15271537
}
1538+
1539+
/* Free memory if tsql_stmt is different from stmt */
1540+
if (tsql_stmt != stmt)
1541+
pfree((void *)tsql_stmt);
15281542
}
15291543
else /* !prepare */
15301544
{
@@ -1926,4 +1940,4 @@ reset_cached_cursor(void)
19261940

19271941
/* Reset sp_cursor_params. */
19281942
reset_sp_cursor_params();
1929-
}
1943+
}

test/JDBC/expected/BABEL-SPCURSOR.out

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,15 @@ go
479479
~~ERROR (Message: cannot open CALL query as cursor)~~
480480

481481

482+
# cursor with empty statement will result in error
483+
DECLARE @cursor_handle int;
484+
EXEC sp_cursoropen @cursor_handle OUTPUT, N'', 2, 8193;
485+
go
486+
~~ERROR (Code: 33557097)~~
487+
488+
~~ERROR (Message: cannot open multi-query plan as cursor)~~
489+
490+
482491
DROP TABLE babel_cursor_t1
483492
DROP TABLE t1812
484493
DROP PROCEDURE p1

test/JDBC/input/BABEL-SPCURSOR.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,11 @@ DECLARE @cursor_handle int;
232232
EXEC sp_cursoropen @cursor_handle OUTPUT, N'exec p1', 2, 8193;
233233
go
234234

235+
# cursor with empty statement will result in error
236+
DECLARE @cursor_handle int;
237+
EXEC sp_cursoropen @cursor_handle OUTPUT, N'', 2, 8193;
238+
go
239+
235240
DROP TABLE babel_cursor_t1
236241
DROP TABLE t1812
237242
DROP PROCEDURE p1

0 commit comments

Comments
 (0)