@@ -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+ }
0 commit comments