Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit07c2572

Browse files
committed
Add BY clause to PL/PgSQL FOR loop, to control the iteration increment.
Jaime Casanova
1 parente6a7b01 commit07c2572

File tree

6 files changed

+73
-13
lines changed

6 files changed

+73
-13
lines changed

‎doc/src/sgml/plpgsql.sgml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.94 2006/05/30 13:40:55 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.95 2006/06/12 16:45:30 momjian Exp $ -->
22

33
<chapter id="plpgsql">
44
<title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
@@ -1975,7 +1975,7 @@ END LOOP;
19751975

19761976
<synopsis>
19771977
<optional> &lt;&lt;<replaceable>label</replaceable>&gt;&gt; </optional>
1978-
FOR <replaceable>name</replaceable> IN <optional> REVERSE </optional> <replaceable>expression</replaceable> .. <replaceable>expression</replaceable> LOOP
1978+
FOR <replaceable>name</replaceable> IN <optional> REVERSE </optional> <replaceable>expression</replaceable> .. <replaceable>expression</replaceable><optional> BY <replaceable>expression</replaceable> </optional>LOOP
19791979
<replaceable>statements</replaceable>
19801980
END LOOP <optional> <replaceable>label</replaceable> </optional>;
19811981
</synopsis>
@@ -1988,8 +1988,10 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>;
19881988
definition of the variable name is ignored within the loop).
19891989
The two expressions giving
19901990
the lower and upper bound of the range are evaluated once when entering
1991-
the loop. The iteration step is normally 1, but is -1 when <literal>REVERSE</> is
1992-
specified.
1991+
the loop. If the <literal>BY</> clause isn't specified the iteration
1992+
step is 1 otherwise it's the value specified in the <literal>BY</>
1993+
clause. If <literal>REVERSE</> is specified then the step value is
1994+
considered negative.
19931995
</para>
19941996

19951997
<para>
@@ -2003,6 +2005,11 @@ END LOOP;
20032005
FOR i IN REVERSE 10..1 LOOP
20042006
-- some computations here
20052007
END LOOP;
2008+
2009+
FOR i IN REVERSE 10..1 BY 2 LOOP
2010+
-- some computations here
2011+
RAISE NOTICE 'i is %', i;
2012+
END LOOP;
20062013
</programlisting>
20072014
</para>
20082015

‎src/pl/plpgsql/src/gram.y

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.90 2006/05/27 19:45:52 tgl Exp $
12+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.91 2006/06/12 16:45:30 momjian Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -144,6 +144,7 @@ staticvoid check_labels(const char *start_label,
144144
%tokenK_ALIAS
145145
%tokenK_ASSIGN
146146
%tokenK_BEGIN
147+
%tokenK_BY
147148
%tokenK_CLOSE
148149
%tokenK_CONSTANT
149150
%tokenK_CONTINUE
@@ -935,14 +936,42 @@ for_control:
935936
{
936937
/* Saw "..", so it must be an integer loop*/
937938
PLpgSQL_expr*expr2;
939+
PLpgSQL_expr*expr_by;
938940
PLpgSQL_var*fvar;
939941
PLpgSQL_stmt_fori*new;
940942
char*varname;
941943

942944
/* First expression is well-formed*/
943945
check_sql_expr(expr1->query);
944946

945-
expr2 = plpgsql_read_expression(K_LOOP,"LOOP");
947+
948+
expr2 = read_sql_construct(K_BY,
949+
K_LOOP,
950+
"LOOP",
951+
"SELECT",
952+
true,
953+
false,
954+
&tok);
955+
956+
if (tok == K_BY)
957+
expr_by = plpgsql_read_expression(K_LOOP,"LOOP");
958+
else
959+
{
960+
/*
961+
* If there is no BY clause we will assume 1
962+
*/
963+
char buf[1024];
964+
PLpgSQL_dstringds;
965+
966+
plpgsql_dstring_init(&ds);
967+
968+
expr_by = palloc0(sizeof(PLpgSQL_expr));
969+
expr_by->dtype = PLPGSQL_DTYPE_EXPR;
970+
strcpy(buf,"SELECT 1");
971+
plpgsql_dstring_append(&ds, buf);
972+
expr_by->query = pstrdup(plpgsql_dstring_get(&ds));
973+
expr_by->plan=NULL;
974+
}
946975

947976
/* should have had a single variable name*/
948977
plpgsql_error_lineno =$2.lineno;
@@ -970,6 +999,7 @@ for_control:
970999
new->reverse = reverse;
9711000
new->lower = expr1;
9721001
new->upper = expr2;
1002+
new->by = expr_by;
9731003

9741004
$$ = (PLpgSQL_stmt *)new;
9751005
}

‎src/pl/plpgsql/src/pl_exec.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.169 2006/05/30 13:40:55 momjian Exp $
11+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.170 2006/06/12 16:45:30 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1361,7 +1361,8 @@ exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
13611361

13621362
/* ----------
13631363
* exec_stmt_foriIterate an integer variable
1364-
*from a lower to an upper value.
1364+
*from a lower to an upper value
1365+
*incrementing or decrementing in BY value
13651366
*Loop can be left with exit.
13661367
* ----------
13671368
*/
@@ -1370,6 +1371,7 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
13701371
{
13711372
PLpgSQL_var*var;
13721373
Datumvalue;
1374+
Datumby_value;
13731375
Oidvaltype;
13741376
boolisnull;
13751377
boolfound= false;
@@ -1407,6 +1409,21 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
14071409
errmsg("upper bound of FOR loop cannot be NULL")));
14081410
exec_eval_cleanup(estate);
14091411

1412+
/*
1413+
* Get the by value
1414+
*/
1415+
by_value=exec_eval_expr(estate,stmt->by,&isnull,&valtype);
1416+
by_value=exec_cast_value(by_value,valtype,var->datatype->typoid,
1417+
&(var->datatype->typinput),
1418+
var->datatype->typioparam,
1419+
var->datatype->atttypmod,isnull);
1420+
1421+
if (isnull)
1422+
ereport(ERROR,
1423+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1424+
errmsg("by value of FOR loop cannot be NULL")));
1425+
exec_eval_cleanup(estate);
1426+
14101427
/*
14111428
* Now do the loop
14121429
*/
@@ -1483,9 +1500,9 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
14831500
* Increase/decrease loop var
14841501
*/
14851502
if (stmt->reverse)
1486-
var->value--;
1503+
var->value-=by_value;
14871504
else
1488-
var->value++;
1505+
var->value+=by_value;
14891506
}
14901507

14911508
/*

‎src/pl/plpgsql/src/pl_funcs.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.52 2006/05/30 13:40:55 momjian Exp $
11+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.53 2006/06/12 16:45:30 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -705,6 +705,10 @@ dump_fori(PLpgSQL_stmt_fori *stmt)
705705
printf(" upper = ");
706706
dump_expr(stmt->upper);
707707
printf("\n");
708+
dump_ind();
709+
printf(" by = ");
710+
dump_expr(stmt->by);
711+
printf("\n");
708712
dump_indent-=2;
709713

710714
dump_stmts(stmt->body);

‎src/pl/plpgsql/src/plpgsql.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.74 2006/05/30 13:40:55 momjian Exp $
11+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.75 2006/06/12 16:45:30 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -398,6 +398,7 @@ typedef struct
398398
PLpgSQL_var*var;
399399
PLpgSQL_expr*lower;
400400
PLpgSQL_expr*upper;
401+
PLpgSQL_expr*by;
401402
intreverse;
402403
List*body;/* List of statements */
403404
}PLpgSQL_stmt_fori;

‎src/pl/plpgsql/src/scan.l

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.49 2006/05/30 13:40:55 momjian Exp $
12+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.50 2006/06/12 16:45:30 momjian Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -116,6 +116,7 @@ dolqinside[^$]+
116116
\.\.{return K_DOTDOT;}
117117
alias{return K_ALIAS;}
118118
begin{return K_BEGIN;}
119+
by{return K_BY; }
119120
close{return K_CLOSE;}
120121
constant{return K_CONSTANT;}
121122
continue{return K_CONTINUE;}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp