Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FETCH from CURSOR inside a function should be disabled without a destination #2506

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
6 changes: 6 additions & 0 deletions contrib/babelfishpg_tsql/src/tsqlIface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4777,6 +4777,12 @@ makeFetchCurosrStatement(TSqlParser::Fetch_cursorContext *ctx)
auto targetText = ::getFullText(ctx->cursor_name());
result->curvar = lookup_cursor_variable(targetText.c_str())->dno;

/* FETCH CURSOR without destination should be blocked inside a function. */

if (is_compiling_create_function() && !ctx->INTO())
{
throw PGErrorWrapperException(ERROR, ERRCODE_INVALID_FUNCTION_DEFINITION, "SELECT statements included within a function cannot return data to a client.", getLineAndPos(ctx));
}
/* fetch option */
if (ctx->NEXT()) {
result->direction = FETCH_FORWARD;
Expand Down
131 changes: 130 additions & 1 deletion test/JDBC/expected/BABEL-2218.out
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ go

CREATE TABLE t2218(c1 INT)
INSERT INTO t2218 VALUES (2218);
INSERT INTO t2218 VALUES (2219);
GO
~~ROW COUNT: 1~~

~~ROW COUNT: 1~~


-- should throw an error
CREATE FUNCTION f2218()
Expand Down Expand Up @@ -42,10 +45,136 @@ DECLARE @ret INT;
SET @ret = f2218();
SELECT @ret;
DROP FUNCTION f2218;
DROP TABLE t2218;
GO
~~START~~
int
2219
~~END~~


-- Throw error if cursor for select doesn't have a destination(INTO @variable) inside a function BABEL-4586
CREATE FUNCTION f_getval()RETURNS INTEGER
AS
BEGIN
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor
FETCH NEXT FROM temp_cursor
CLOSE temp_cursor
RETURN 1
END
go
~~ERROR (Code: 33557097)~~

~~ERROR (Message: SELECT statements included within a function cannot return data to a client.)~~


-- cursor for select work if the destination(INTO @variable) is provided inside a function BABEL-4586
CREATE FUNCTION f_getval() RETURNS INTEGER
AS
BEGIN
DECLARE @my_var int
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor
FETCH NEXT FROM temp_cursor INTO @my_var
CLOSE temp_cursor
RETURN @my_var
END
go

DROP FUNCTION f_getval;
GO

-- cursor for select work with multiple fetch if the destination(INTO @variable) is provided inside a function BABEL-4586
CREATE FUNCTION f_getval() RETURNS INTEGER
AS
BEGIN
DECLARE @my_var int
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor
FETCH NEXT FROM temp_cursor INTO @my_var
FETCH NEXT FROM temp_cursor INTO @my_var
CLOSE temp_cursor
RETURN @my_var
END
go

DROP FUNCTION f_getval;
GO

-- cursor for select should throw error even if one fetch tries to return results to client
CREATE FUNCTION f_getval() RETURNS INTEGER
AS
BEGIN
DECLARE @my_var int
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor
FETCH NEXT FROM temp_cursor INTO @my_var
FETCH NEXT FROM temp_cursor
CLOSE temp_cursor
RETURN @my_var
END
GO
~~ERROR (Code: 33557097)~~

~~ERROR (Message: SELECT statements included within a function cannot return data to a client.)~~


-- cursor for select should work for procedure
CREATE PROCEDURE proc_with_cursor_fetch
AS
BEGIN
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor
FETCH NEXT FROM temp_cursor
CLOSE temp_cursor
END
GO

DROP PROCEDURE proc_with_cursor_fetch;
GO

-- cursor for select should work for procedure with INTO
CREATE PROCEDURE proc_with_cursor_fetch
AS
BEGIN
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
DECLARE @my_var int
OPEN temp_cursor
FETCH NEXT FROM temp_cursor INTO @my_var
CLOSE temp_cursor
END
GO

DROP PROCEDURE proc_with_cursor_fetch;
GO

CREATE TRIGGER trg1 ON t2218 AFTER INSERT AS
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
DECLARE @my_var int
OPEN temp_cursor
FETCH NEXT FROM temp_cursor INTO @my_var
CLOSE temp_cursor
GO

CREATE TRIGGER trg2 ON t2218 AFTER INSERT AS
DECLARE temp_cursor1 CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor1
FETCH NEXT FROM temp_cursor1
CLOSE temp_cursor1
GO

-- Trigger after insert
INSERT INTO t2218 VALUES (2218);
GO
~~START~~
int
2218
~~END~~

~~ROW COUNT: 1~~


DROP TRIGGER trg1
DROP TRIGGER trg2
DROP TABLE t2218
GO
114 changes: 113 additions & 1 deletion test/JDBC/input/BABEL-2218.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ go

CREATE TABLE t2218(c1 INT)
INSERT INTO t2218 VALUES (2218);
INSERT INTO t2218 VALUES (2219);
GO

-- should throw an error
Expand Down Expand Up @@ -36,5 +37,116 @@ SET @ret = f2218();
SELECT @ret;

DROP FUNCTION f2218;
DROP TABLE t2218;
GO

-- Throw error if cursor for select doesn't have a destination(INTO @variable) inside a function BABEL-4586
CREATE FUNCTION f_getval()RETURNS INTEGER
AS
BEGIN
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor
FETCH NEXT FROM temp_cursor
CLOSE temp_cursor
RETURN 1
END
go

-- cursor for select work if the destination(INTO @variable) is provided inside a function BABEL-4586
CREATE FUNCTION f_getval() RETURNS INTEGER
AS
BEGIN
DECLARE @my_var int
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor
FETCH NEXT FROM temp_cursor INTO @my_var
CLOSE temp_cursor
RETURN @my_var
END
go

DROP FUNCTION f_getval;
GO

-- cursor for select work with multiple fetch if the destination(INTO @variable) is provided inside a function BABEL-4586
CREATE FUNCTION f_getval() RETURNS INTEGER
AS
BEGIN
DECLARE @my_var int
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor
FETCH NEXT FROM temp_cursor INTO @my_var
FETCH NEXT FROM temp_cursor INTO @my_var
CLOSE temp_cursor
RETURN @my_var
END
go

DROP FUNCTION f_getval;
GO

-- cursor for select should throw error even if one fetch tries to return results to client
CREATE FUNCTION f_getval() RETURNS INTEGER
AS
BEGIN
DECLARE @my_var int
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor
FETCH NEXT FROM temp_cursor INTO @my_var
FETCH NEXT FROM temp_cursor
CLOSE temp_cursor
RETURN @my_var
END
GO

-- cursor for select should work for procedure
CREATE PROCEDURE proc_with_cursor_fetch
AS
BEGIN
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor
FETCH NEXT FROM temp_cursor
CLOSE temp_cursor
END
GO

DROP PROCEDURE proc_with_cursor_fetch;
GO

-- cursor for select should work for procedure with INTO
CREATE PROCEDURE proc_with_cursor_fetch
AS
BEGIN
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
DECLARE @my_var int
OPEN temp_cursor
FETCH NEXT FROM temp_cursor INTO @my_var
CLOSE temp_cursor
END
GO

DROP PROCEDURE proc_with_cursor_fetch;
GO

CREATE TRIGGER trg1 ON t2218 AFTER INSERT AS
DECLARE temp_cursor CURSOR FOR SELECT c1 FROM t2218
DECLARE @my_var int
OPEN temp_cursor
FETCH NEXT FROM temp_cursor INTO @my_var
CLOSE temp_cursor
GO

CREATE TRIGGER trg2 ON t2218 AFTER INSERT AS
DECLARE temp_cursor1 CURSOR FOR SELECT c1 FROM t2218
OPEN temp_cursor1
FETCH NEXT FROM temp_cursor1
CLOSE temp_cursor1
GO

-- Trigger after insert
INSERT INTO t2218 VALUES (2218);
GO

DROP TRIGGER trg1
DROP TRIGGER trg2
DROP TABLE t2218
GO
4 changes: 3 additions & 1 deletion test/python/sql_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,9 @@ def find_tests(fname, logger):
inst_scripts = list_files(inpPath, "*.sql")

# removing scripts having helper functions and redundant script
for i in inst_scripts:
# create a copy of list inst_scripts for iterating to safely remove the items from list

for i in inst_scripts[:]:
if re.search("sys_function_helpers.sql", str(i)):
inst_scripts.remove(Path(inpPath).joinpath("sys_function_helpers.sql"))
if re.search("babelfishpg_tsql--1.0.0.sql", str(i)):
Expand Down
Loading