Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions contrib/babelfishpg_tsql/src/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1449,6 +1449,10 @@ execute_sp_cursoropen_common(int *stmt_handle, int *cursor_handle, const char *s
Portal portal;
MemoryContext oldcontext;
MemoryContext savedPortalCxt;
PLtsql_stmt_execsql *parse_result;
PLtsql_function *func;
char *stmt_copy;
char *tsql_stmt = NULL; /* Use this for potentially modified statement */

/*
* Connect to SPI manager. should be handled in the same way with
Expand All @@ -1468,10 +1472,53 @@ execute_sp_cursoropen_common(int *stmt_handle, int *cursor_handle, const char *s

if (prepare)
{
/*
* This entire block is to parse the statement by antlr and use the statement for
* cursor execution. This is necessary in some use case, for example when we have
* PostgreSQL reversed keywords in query which is valid in TSQL.
* Antlr parser will add the quotes at necessary places in query so that Postgres engine
* can resolve this query correctly.
*/
if (stmt)
{
/* Copy the original statement, because we don't want to use the resultant query in every case. */
stmt_copy = pstrdup(stmt);
/* Send to antlr parser */
func = pltsql_compile_inline(stmt_copy, NULL);

/*
* Check the node list of type PLtsql_stmt_type. Cursor only support single statement.
* If there are more than 1 statement we will through the error. func->action-body
* returned by pltsql_compile_inline generally contains two default nodes, PLTSQL_STMT_INIT being first
* and PLTSQL_STMT_RETURN being last. In case of empty statement only PLTSQL_STMT_RETURN node will be present.
* So total number of nodes should be 3 for valid cursor execution. Actual query statement will be at second
* position of type PLTSQL_STMT_EXECSQL.
*
* This is defensive code, where we only assign the tsql_stmt variable to parsed query,
* if the cmd_type is PLTSQL_STMT_EXECSQL. There might be other types of cmd_type like
* PLTSQL_STMT_EXECSQL (for procedures), for them we will keep the old behavior.
* list length should be checked first before trying to deference second node from the list.
* FIXME:We are handling only PLtsql_stmt_execsql type statement, but TSQL support procedure with
* single statement. We also need to explore all other statement types for completion.
*/
if(list_length(func->action->body) == 3 &&
((PLtsql_stmt *) lsecond(func->action->body))->cmd_type == PLTSQL_STMT_EXECSQL)
{
parse_result = (PLtsql_stmt_execsql *) lsecond(func->action->body);
tsql_stmt = pstrdup(parse_result->sqlstmt->query);
}

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

/* prepare plan and insert a cursor entry */
plan = SPI_prepare_cursor(stmt, nBindParams, boundParamsOidList, cursor_options);
plan = SPI_prepare_cursor(tsql_stmt?tsql_stmt:stmt, nBindParams, boundParamsOidList, cursor_options);
if (plan == NULL)
return 1; /* procedure failed */
/* Free memory if tsql_stmt is not null */
if (tsql_stmt)
pfree((void *)tsql_stmt);

if (save_plan)
{
Expand Down Expand Up @@ -1887,4 +1934,4 @@ reset_cached_cursor(void)

/* Reset sp_cursor_params. */
reset_sp_cursor_params();
}
}
21 changes: 21 additions & 0 deletions test/JDBC/expected/BABEL-SPCURSOR.out
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,28 @@ int#!#int#!#int#!#int#!#int
~~END~~


# cursor with procedure execution test
CREATE PROCEDURE p1 AS BEGIN select * from babel_cursor_t1 end
go
DECLARE @cursor_handle int;
EXEC sp_cursoropen @cursor_handle OUTPUT, N'exec p1', 2, 8193;
go
~~ERROR (Code: 33557097)~~

~~ERROR (Message: cannot open CALL query as cursor)~~


# cursor with empty statement will result in error
DECLARE @cursor_handle int;
EXEC sp_cursoropen @cursor_handle OUTPUT, N'', 2, 8193;
go
~~ERROR (Code: 33557097)~~

~~ERROR (Message: cannot open multi-query plan as cursor)~~


DROP TABLE babel_cursor_t1
DROP TABLE t1812
DROP PROCEDURE p1
GO

38 changes: 38 additions & 0 deletions test/JDBC/expected/TestCursorFetchNext.out
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,44 @@ int#!#smallint#!#bigint#!#tinyint#!#bit
#cursor#!#fetch#!#next
#cursor#!#fetch#!#afterlast
#cursor#!#fetch#!#next
cursor#!#close
~~SUCCESS~~
cursor#!#open#!#SELECT a year, b month, c quarter FROM test_cursors_fetch_next#!#TYPE_SCROLL_INSENSITIVE#!#CONCUR_READ_ONLY#!#CLOSE_CURSORS_AT_COMMIT
~~SUCCESS~~
cursor#!#fetch#!#next
~~START~~
int#!#smallint#!#bigint
0#!#0#!#0
~~END~~

cursor#!#fetch#!#first
~~START~~
int#!#smallint#!#bigint
0#!#0#!#0
~~END~~

cursor#!#fetch#!#next
~~START~~
int#!#smallint#!#bigint
<NULL>#!#<NULL>#!#<NULL>
~~END~~

cursor#!#fetch#!#last
~~START~~
int#!#smallint#!#bigint
211234#!#9780#!#891372401
~~END~~

cursor#!#close
~~SUCCESS~~
cursor#!#open#!#DECLARE @var INT; select @var = 5; select @var + 1;#!#CONCUR_READ_ONLY#!#CLOSE_CURSORS_AT_COMMIT
~~SUCCESS~~
cursor#!#fetch#!#next
~~START~~
int
6
~~END~~

cursor#!#close
~~SUCCESS~~
DROP TABLE test_cursors_fetch_next
Expand Down
39 changes: 39 additions & 0 deletions test/JDBC/expected/TestCursorPrepExecFetchNext.out
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,38 @@ int#!#smallint#!#bigint#!#tinyint#!#bit
#cursor#!#fetch#!#next
#cursor#!#fetch#!#afterlast
#cursor#!#fetch#!#next
cursor#!#close
~~SUCCESS~~
cursor#!#open#!#prepst#!#SELECT a year, b month, c quarter from test_cursor_prep_exec_fetch_next#!#TYPE_SCROLL_INSENSITIVE#!#CONCUR_READ_ONLY#!#CLOSE_CURSORS_AT_COMMIT
~~SUCCESS~~
cursor#!#fetch#!#next
~~START~~
int#!#smallint#!#bigint
0#!#0#!#0
~~END~~

cursor#!#fetch#!#first
~~START~~
int#!#smallint#!#bigint
0#!#0#!#0
~~END~~

cursor#!#fetch#!#next
~~START~~
int#!#smallint#!#bigint
<NULL>#!#<NULL>#!#<NULL>
~~END~~

cursor#!#close
~~SUCCESS~~
cursor#!#open#!#DECLARE @var INT; select @var = 5; select @var + 1;#!#CONCUR_READ_ONLY#!#CLOSE_CURSORS_AT_COMMIT
~~SUCCESS~~
cursor#!#fetch#!#next
~~START~~
int
6
~~END~~

cursor#!#close
~~SUCCESS~~
DROP TABLE test_cursor_prep_exec_fetch_next
Expand Down Expand Up @@ -285,4 +317,11 @@ float#!#real#!#money#!#smallmoney
#cursor#!#fetch#!#next
cursor#!#close
~~SUCCESS~~
# Cursor with multiple selects should return error
cursor#!#open#!#prepst#!#SELECT * FROM test_cursor_prep_exec_fetch_next;SELECT a FROM test_cursor_prep_exec_fetch_next#!#TYPE_SCROLL_INSENSITIVE#!#CONCUR_READ_ONLY#!#CLOSE_CURSORS_AT_COMMIT
~~ERROR (Code: 33557097)~~

~~ERROR (Message: cannot open multi-query plan as cursor)~~


DROP TABLE test_cursor_prep_exec_fetch_next
13 changes: 13 additions & 0 deletions test/JDBC/input/BABEL-SPCURSOR.sql
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,20 @@ exec sp_cursorclose @p2;
exec sp_cursorunprepare @p1;
go

# cursor with procedure execution test
CREATE PROCEDURE p1 AS BEGIN select * from babel_cursor_t1 end
go
DECLARE @cursor_handle int;
EXEC sp_cursoropen @cursor_handle OUTPUT, N'exec p1', 2, 8193;
go

# cursor with empty statement will result in error
DECLARE @cursor_handle int;
EXEC sp_cursoropen @cursor_handle OUTPUT, N'', 2, 8193;
go

DROP TABLE babel_cursor_t1
DROP TABLE t1812
DROP PROCEDURE p1
GO

9 changes: 9 additions & 0 deletions test/JDBC/input/cursors/TestCursorFetchNext.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ cursor#!#fetch#!#next
#cursor#!#fetch#!#afterlast
#cursor#!#fetch#!#next
cursor#!#close
cursor#!#open#!#SELECT a year, b month, c quarter FROM test_cursors_fetch_next#!#TYPE_SCROLL_INSENSITIVE#!#CONCUR_READ_ONLY#!#CLOSE_CURSORS_AT_COMMIT
cursor#!#fetch#!#next
cursor#!#fetch#!#first
cursor#!#fetch#!#next
cursor#!#fetch#!#last
cursor#!#close
cursor#!#open#!#DECLARE @var INT; select @var = 5; select @var + 1;#!#CONCUR_READ_ONLY#!#CLOSE_CURSORS_AT_COMMIT
cursor#!#fetch#!#next
cursor#!#close
DROP TABLE test_cursors_fetch_next

CREATE TABLE test_cursors_fetch_next(a CHAR(30), b VARCHAR(30), c NCHAR(30), d NVARCHAR(30));
Expand Down
11 changes: 11 additions & 0 deletions test/JDBC/input/cursors/TestCursorPrepExecFetchNext.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ cursor#!#fetch#!#next
#cursor#!#fetch#!#afterlast
#cursor#!#fetch#!#next
cursor#!#close
cursor#!#open#!#prepst#!#SELECT a year, b month, c quarter from test_cursor_prep_exec_fetch_next#!#TYPE_SCROLL_INSENSITIVE#!#CONCUR_READ_ONLY#!#CLOSE_CURSORS_AT_COMMIT
cursor#!#fetch#!#next
cursor#!#fetch#!#first
cursor#!#fetch#!#next
cursor#!#close
cursor#!#open#!#DECLARE @var INT; select @var = 5; select @var + 1;#!#CONCUR_READ_ONLY#!#CLOSE_CURSORS_AT_COMMIT
cursor#!#fetch#!#next
cursor#!#close
DROP TABLE test_cursor_prep_exec_fetch_next

CREATE TABLE test_cursor_prep_exec_fetch_next(a CHAR(30), b VARCHAR(30), c NCHAR(30), d NVARCHAR(30));
Expand Down Expand Up @@ -94,4 +102,7 @@ cursor#!#fetch#!#next
#cursor#!#fetch#!#afterlast
#cursor#!#fetch#!#next
cursor#!#close
# Cursor with multiple selects should return error
cursor#!#open#!#prepst#!#SELECT * FROM test_cursor_prep_exec_fetch_next;SELECT a FROM test_cursor_prep_exec_fetch_next#!#TYPE_SCROLL_INSENSITIVE#!#CONCUR_READ_ONLY#!#CLOSE_CURSORS_AT_COMMIT

DROP TABLE test_cursor_prep_exec_fetch_next
Loading