Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
8690ebc2
Commit
8690ebc2
authored
Apr 29, 2007
by
Neil Conway
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support for MOVE in PL/PgSQL. Initial patch from Magnus, some improvements
by Pavel Stehule, and reviewed by Neil Conway.
parent
f2321a3f
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
226 additions
and
47 deletions
+226
-47
doc/src/sgml/plpgsql.sgml
doc/src/sgml/plpgsql.sgml
+55
-1
src/pl/plpgsql/src/gram.y
src/pl/plpgsql/src/gram.y
+18
-2
src/pl/plpgsql/src/pl_exec.c
src/pl/plpgsql/src/pl_exec.c
+44
-32
src/pl/plpgsql/src/pl_funcs.c
src/pl/plpgsql/src/pl_funcs.c
+54
-9
src/pl/plpgsql/src/plpgsql.h
src/pl/plpgsql/src/plpgsql.h
+3
-2
src/pl/plpgsql/src/scan.l
src/pl/plpgsql/src/scan.l
+2
-1
src/test/regress/expected/plpgsql.out
src/test/regress/expected/plpgsql.out
+27
-0
src/test/regress/sql/plpgsql.sql
src/test/regress/sql/plpgsql.sql
+23
-0
No files found.
doc/src/sgml/plpgsql.sgml
View file @
8690ebc2
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.10
8 2007/04/28 23:54:5
8 neilc Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.10
9 2007/04/29 01:21:0
8 neilc Exp $ -->
<chapter id="plpgsql">
<title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
...
...
@@ -1522,6 +1522,13 @@ GET DIAGNOSTICS integer_var = ROW_COUNT;
true if it returns a row, false if no row is returned.
</para>
</listitem>
<listitem>
<para>
A <command>MOVE</> statement sets <literal>FOUND</literal>
true if it successfully repositions the cursor, false otherwise.
</para>
</listitem>
<listitem>
<para>
A <command>FOR</> statement sets <literal>FOUND</literal> true
...
...
@@ -2562,6 +2569,53 @@ FETCH curs1 INTO rowvar;
FETCH curs2 INTO foo, bar, baz;
FETCH LAST FROM curs3 INTO x, y;
FETCH RELATIVE -2 FROM curs4 INTO x;
</programlisting>
</para>
</sect3>
<sect3>
<title><literal>MOVE</></title>
<synopsis>
MOVE <optional> <replaceable>direction</replaceable> { FROM | IN } </optional> <replaceable>cursor</replaceable>;
</synopsis>
<para>
<command>MOVE</command> repositions a cursor without retrieving
any data. <command>MOVE</command> works exactly like the
<command>FETCH</command> command, except it only positions the
cursor and does not return rows. As with <command>SELECT
INTO</command>, the special variable <literal>FOUND</literal> can
be checked to see whether the cursor was successfully
repositioned or not.
</para>
<para>
The <replaceable>direction</replaceable> clause can be any of the
variants allowed in the SQL <xref linkend="sql-move"
endterm="sql-move-title"> command except the ones that can move by
more than one row; namely, it can be
<literal>NEXT</>,
<literal>PRIOR</>,
<literal>FIRST</>,
<literal>LAST</>,
<literal>ABSOLUTE</> <replaceable>count</replaceable>,
<literal>RELATIVE</> <replaceable>count</replaceable>,
<literal>FORWARD</>, or
<literal>BACKWARD</>.
Omitting <replaceable>direction</replaceable> is the same
as specifying <literal>NEXT</>.
<replaceable>direction</replaceable> values that require moving
backward are likely to fail unless the cursor was declared or opened
with the <literal>SCROLL</> option.
</para>
<para>
Examples:
<programlisting>
MOVE curs1;
MOVE LAST FROM curs3;
MOVE RELATIVE -2 FROM curs4;
</programlisting>
</para>
</sect3>
...
...
src/pl/plpgsql/src/gram.y
View file @
8690ebc2
...
...
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.10
1 2007/04/28 23:54:5
9 neilc Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.10
2 2007/04/29 01:21:0
9 neilc Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -125,7 +125,7 @@ static void check_labels(const char *start_label,
%type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
%type <stmt> stmt_return stmt_raise stmt_execsql stmt_execsql_insert
%type <stmt> stmt_dynexecute stmt_for stmt_perform stmt_getdiag
%type <stmt> stmt_open stmt_fetch stmt_close stmt_null
%type <stmt> stmt_open stmt_fetch stmt_
move stmt_
close stmt_null
%type <list> proc_exceptions
%type <exception_block> exception_sect
...
...
@@ -179,6 +179,7 @@ static void check_labels(const char *start_label,
%token K_IS
%token K_LOG
%token K_LOOP
%token K_MOVE
%token K_NEXT
%token K_NOSCROLL
%token K_NOT
...
...
@@ -635,6 +636,8 @@ proc_stmt : pl_block ';'
{ $$ = $1; }
| stmt_fetch
{ $$ = $1; }
| stmt_move
{ $$ = $1; }
| stmt_close
{ $$ = $1; }
| stmt_null
...
...
@@ -1478,6 +1481,19 @@ stmt_fetch : K_FETCH lno opt_fetch_direction cursor_variable K_INTO
fetch->rec = rec;
fetch->row = row;
fetch->curvar = $4->varno;
fetch->is_move = false;
$$ = (PLpgSQL_stmt *)fetch;
}
;
stmt_move : K_MOVE lno opt_fetch_direction cursor_variable ';'
{
PLpgSQL_stmt_fetch *fetch = $3;
fetch->lineno = $2;
fetch->curvar = $4->varno;
fetch->is_move = true;
$$ = (PLpgSQL_stmt *)fetch;
}
...
...
src/pl/plpgsql/src/pl_exec.c
View file @
8690ebc2
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.19
5 2007/04/19 16:33:24 tgl
Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.19
6 2007/04/29 01:21:09 neilc
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -3114,7 +3114,8 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
/* ----------
* exec_stmt_fetch Fetch from a cursor into a target
* exec_stmt_fetch Fetch from a cursor into a target, or just
* move the current position of the cursor
* ----------
*/
static
int
...
...
@@ -3163,46 +3164,57 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
exec_eval_cleanup
(
estate
);
}
/* ----------
* Determine if we fetch into a record or a row
* ----------
*/
if
(
stmt
->
rec
!=
NULL
)
rec
=
(
PLpgSQL_rec
*
)
(
estate
->
datums
[
stmt
->
rec
->
recno
]);
else
if
(
stmt
->
row
!=
NULL
)
row
=
(
PLpgSQL_row
*
)
(
estate
->
datums
[
stmt
->
row
->
rowno
]);
else
elog
(
ERROR
,
"unsupported target"
);
if
(
!
stmt
->
is_move
)
{
/* ----------
* Determine if we fetch into a record or a row
* ----------
*/
if
(
stmt
->
rec
!=
NULL
)
rec
=
(
PLpgSQL_rec
*
)
(
estate
->
datums
[
stmt
->
rec
->
recno
]);
else
if
(
stmt
->
row
!=
NULL
)
row
=
(
PLpgSQL_row
*
)
(
estate
->
datums
[
stmt
->
row
->
rowno
]);
else
elog
(
ERROR
,
"unsupported target"
);
/* ----------
* Fetch 1 tuple from the cursor
* ----------
*/
SPI_scroll_cursor_fetch
(
portal
,
stmt
->
direction
,
how_many
);
tuptab
=
SPI_tuptable
;
n
=
SPI_processed
;
/* ----------
* Fetch 1 tuple from the cursor
* ----------
*/
SPI_scroll_cursor_fetch
(
portal
,
stmt
->
direction
,
how_many
);
tuptab
=
SPI_tuptable
;
n
=
SPI_processed
;
/* ----------
* Set the target and the global FOUND variable appropriately.
* ----------
*/
if
(
n
==
0
)
{
exec_move_row
(
estate
,
rec
,
row
,
NULL
,
tuptab
->
tupdesc
);
exec_set_found
(
estate
,
false
);
/* ----------
* Set the target and the global FOUND variable appropriately.
* ----------
*/
if
(
n
==
0
)
{
exec_move_row
(
estate
,
rec
,
row
,
NULL
,
tuptab
->
tupdesc
);
exec_set_found
(
estate
,
false
);
}
else
{
exec_move_row
(
estate
,
rec
,
row
,
tuptab
->
vals
[
0
],
tuptab
->
tupdesc
);
exec_set_found
(
estate
,
true
);
}
SPI_freetuptable
(
tuptab
);
}
else
{
exec_move_row
(
estate
,
rec
,
row
,
tuptab
->
vals
[
0
],
tuptab
->
tupdesc
);
exec_set_found
(
estate
,
true
);
}
/* Move the cursor */
SPI_scroll_cursor_move
(
portal
,
stmt
->
direction
,
how_many
);
n
=
SPI_processed
;
SPI_freetuptable
(
tuptab
);
/* Set the global FOUND variable appropriately. */
exec_set_found
(
estate
,
n
!=
0
);
}
return
PLPGSQL_RC_OK
;
}
/* ----------
* exec_stmt_close Close a cursor
* ----------
...
...
src/pl/plpgsql/src/pl_funcs.c
View file @
8690ebc2
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.5
8 2007/03/18 05:36:4
9 neilc Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.5
9 2007/04/29 01:21:0
9 neilc Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -493,6 +493,7 @@ static void dump_dynfors(PLpgSQL_stmt_dynfors *stmt);
static
void
dump_getdiag
(
PLpgSQL_stmt_getdiag
*
stmt
);
static
void
dump_open
(
PLpgSQL_stmt_open
*
stmt
);
static
void
dump_fetch
(
PLpgSQL_stmt_fetch
*
stmt
);
static
void
dump_cursor_direction
(
PLpgSQL_stmt_fetch
*
stmt
);
static
void
dump_close
(
PLpgSQL_stmt_close
*
stmt
);
static
void
dump_perform
(
PLpgSQL_stmt_perform
*
stmt
);
static
void
dump_expr
(
PLpgSQL_expr
*
expr
);
...
...
@@ -761,21 +762,64 @@ static void
dump_fetch
(
PLpgSQL_stmt_fetch
*
stmt
)
{
dump_ind
();
printf
(
"FETCH curvar=%d
\n
"
,
stmt
->
curvar
);
if
(
!
stmt
->
is_move
)
{
printf
(
"FETCH curvar=%d
\n
"
,
stmt
->
curvar
);
dump_cursor_direction
(
stmt
);
dump_indent
+=
2
;
if
(
stmt
->
rec
!=
NULL
)
{
dump_ind
();
printf
(
" target = %d %s
\n
"
,
stmt
->
rec
->
recno
,
stmt
->
rec
->
refname
);
}
if
(
stmt
->
row
!=
NULL
)
{
dump_ind
();
printf
(
" target = %d %s
\n
"
,
stmt
->
row
->
rowno
,
stmt
->
row
->
refname
);
}
dump_indent
-=
2
;
}
else
{
printf
(
"MOVE curvar=%d
\n
"
,
stmt
->
curvar
);
dump_cursor_direction
(
stmt
);
}
}
static
void
dump_cursor_direction
(
PLpgSQL_stmt_fetch
*
stmt
)
{
dump_indent
+=
2
;
if
(
stmt
->
rec
!=
NULL
)
dump_ind
();
switch
(
stmt
->
direction
)
{
dump_ind
();
printf
(
" target = %d %s
\n
"
,
stmt
->
rec
->
recno
,
stmt
->
rec
->
refname
);
case
FETCH_FORWARD
:
printf
(
" FORWARD "
);
break
;
case
FETCH_BACKWARD
:
printf
(
" BACKWARD "
);
break
;
case
FETCH_ABSOLUTE
:
printf
(
" ABSOLUTE "
);
break
;
case
FETCH_RELATIVE
:
printf
(
" RELATIVE "
);
break
;
default:
printf
(
"??? unknown cursor direction %d"
,
stmt
->
direction
);
}
if
(
stmt
->
row
!=
NULL
)
if
(
stmt
->
expr
)
{
dump_
ind
(
);
printf
(
"
target = %d %s
\n
"
,
stmt
->
row
->
rowno
,
stmt
->
row
->
refname
);
dump_
expr
(
stmt
->
expr
);
printf
(
"
\n
"
);
}
else
printf
(
"%d
\n
"
,
stmt
->
how_many
);
dump_indent
-=
2
;
}
static
void
...
...
@@ -1067,3 +1111,4 @@ plpgsql_dumptree(PLpgSQL_function *func)
printf
(
"
\n
End of execution tree of function %s
\n\n
"
,
func
->
fn_name
);
fflush
(
stdout
);
}
src/pl/plpgsql/src/plpgsql.h
View file @
8690ebc2
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.8
7 2007/04/16 17:21:23 tgl
Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.8
8 2007/04/29 01:21:09 neilc
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -446,7 +446,7 @@ typedef struct
typedef
struct
{
/* FETCH statement */
{
/* FETCH
or MOVE
statement */
int
cmd_type
;
int
lineno
;
PLpgSQL_rec
*
rec
;
/* target, as record or row */
...
...
@@ -455,6 +455,7 @@ typedef struct
FetchDirection
direction
;
/* fetch direction */
int
how_many
;
/* count, if constant (expr is NULL) */
PLpgSQL_expr
*
expr
;
/* count, if expression */
bool
is_move
;
/* is this a fetch or move? */
}
PLpgSQL_stmt_fetch
;
...
...
src/pl/plpgsql/src/scan.l
View file @
8690ebc2
...
...
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.5
6 2007/04/16 17:21:23 tgl
Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.5
7 2007/04/29 01:21:09 neilc
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -142,6 +142,7 @@ into { return K_INTO; }
is { return K_IS; }
log { return K_LOG; }
loop { return K_LOOP; }
move { return K_MOVE; }
next { return K_NEXT; }
no{space}+scroll { return K_NOSCROLL; }
not { return K_NOT; }
...
...
src/test/regress/expected/plpgsql.out
View file @
8690ebc2
...
...
@@ -3023,4 +3023,31 @@ select * from sc_test();
0
(3 rows)
create or replace function sc_test() returns setof integer as $$
declare
c cursor for select * from generate_series(1, 10);
x integer;
begin
open c;
loop
move relative 2 in c;
if not found then
exit;
end if;
fetch next from c into x;
if found then
return next x;
end if;
end loop;
close c;
end;
$$ language plpgsql;
select * from sc_test();
sc_test
---------
3
6
9
(3 rows)
drop function sc_test();
src/test/regress/sql/plpgsql.sql
View file @
8690ebc2
...
...
@@ -2511,4 +2511,27 @@ $$ language plpgsql;
select
*
from
sc_test
();
create
or
replace
function
sc_test
()
returns
setof
integer
as
$$
declare
c
cursor
for
select
*
from
generate_series
(
1
,
10
);
x
integer
;
begin
open
c
;
loop
move
relative
2
in
c
;
if
not
found
then
exit
;
end
if
;
fetch
next
from
c
into
x
;
if
found
then
return
next
x
;
end
if
;
end
loop
;
close
c
;
end
;
$$
language
plpgsql
;
select
*
from
sc_test
();
drop
function
sc_test
();
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment