@@ -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