On Mon, 2005-08-08 at 17:18 -0400, Tom Lane wrote:
> If you think that this should be a global option instead of a
> per-statement one, something like the (undocumented) #option hack might
> be a good way to specify it; that would give it per-function scope,
> which seems reasonable.
>
> create function myfn(...) returns ... as $$
> #option select_into_1_row
> declare ...
> $$ language plpgsql;
Attached is a patch that implements the "#option select_into_1_row"
directive as suggested.
Is it time to document this directive?
Index: src/pl/plpgsql/src/gram.y
===================================================================
RCS file: /var/local/pgcvs/pgsql/src/pl/plpgsql/src/gram.y,v
retrieving revision 1.80
diff -c -r1.80 gram.y
*** src/pl/plpgsql/src/gram.y 2 Jul 2005 17:01:59 -0000 1.80
--- src/pl/plpgsql/src/gram.y 8 Aug 2005 22:53:36 -0000
***************
*** 224,229 ****
--- 224,230 ----
%token O_OPTION
%token O_DUMP
+ %token O_SELECT_INTO_1_ROW
%%
***************
*** 249,254 ****
--- 250,259 ----
{
plpgsql_DumpExecTree = true;
}
+ | O_OPTION O_SELECT_INTO_1_ROW
+ {
+ plpgsql_SelectInto1Row = true;
+ }
;
opt_semi :
Index: src/pl/plpgsql/src/pl_comp.c
===================================================================
RCS file: /var/local/pgcvs/pgsql/src/pl/plpgsql/src/pl_comp.c,v
retrieving revision 1.92
diff -c -r1.92 pl_comp.c
*** src/pl/plpgsql/src/pl_comp.c 6 Jul 2005 16:42:10 -0000 1.92
--- src/pl/plpgsql/src/pl_comp.c 9 Aug 2005 14:32:43 -0000
***************
*** 78,83 ****
--- 78,84 ----
int plpgsql_error_lineno;
char *plpgsql_error_funcname;
bool plpgsql_DumpExecTree = false;
+ bool plpgsql_SelectInto1Row = false;
bool plpgsql_check_syntax = false;
PLpgSQL_function *plpgsql_curr_compile;
***************
*** 309,314 ****
--- 310,316 ----
plpgsql_ns_init();
plpgsql_ns_push(NULL);
plpgsql_DumpExecTree = false;
+ plpgsql_SelectInto1Row = false;
datums_alloc = 128;
plpgsql_nDatums = 0;
Index: src/pl/plpgsql/src/pl_exec.c
===================================================================
RCS file: /var/local/pgcvs/pgsql/src/pl/plpgsql/src/pl_exec.c,v
retrieving revision 1.151
diff -c -r1.151 pl_exec.c
*** src/pl/plpgsql/src/pl_exec.c 28 Jul 2005 07:51:13 -0000 1.151
--- src/pl/plpgsql/src/pl_exec.c 9 Aug 2005 14:49:45 -0000
***************
*** 1649,1665 ****
elog(ERROR, "unsupported target");
/*
! * Run the query
*/
! exec_run_select(estate, stmt->query, 1, NULL);
tuptab = estate->eval_tuptable;
n = estate->eval_processed;
/*
! * If the query didn't return any rows, set the target to NULL and
! * return.
*/
! if (n == 0)
{
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
exec_eval_cleanup(estate);
--- 1649,1672 ----
elog(ERROR, "unsupported target");
/*
! * Run the query, bringing back up to 2 rows if necessary
*/
! exec_run_select(estate, stmt->query, plpgsql_SelectInto1Row ? 2 : 1, NULL);
tuptab = estate->eval_tuptable;
n = estate->eval_processed;
/*
! * If the "#option select_into_1_row" directive was specified, and the query didn't
! * find exactly 1 row, then exit without setting the target. If this directive was
! * not specified then set the target, either to NULL if no rows were found or to
! * the value of the "first" row found.
*/
! if (plpgsql_SelectInto1Row && n != 1)
! {
! exec_eval_cleanup(estate);
! return PLPGSQL_RC_OK;
! }
! else if (n == 0)
{
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
exec_eval_cleanup(estate);
Index: src/pl/plpgsql/src/plpgsql.h
===================================================================
RCS file: /var/local/pgcvs/pgsql/src/pl/plpgsql/src/plpgsql.h,v
retrieving revision 1.64
diff -c -r1.64 plpgsql.h
*** src/pl/plpgsql/src/plpgsql.h 22 Jun 2005 01:35:02 -0000 1.64
--- src/pl/plpgsql/src/plpgsql.h 8 Aug 2005 22:53:36 -0000
***************
*** 644,649 ****
--- 644,650 ----
**********************************************************************/
extern bool plpgsql_DumpExecTree;
+ extern bool plpgsql_SelectInto1Row;
extern bool plpgsql_SpaceScanned;
extern int plpgsql_nDatums;
extern PLpgSQL_datum **plpgsql_Datums;
Index: src/pl/plpgsql/src/scan.l
===================================================================
RCS file: /var/local/pgcvs/pgsql/src/pl/plpgsql/src/scan.l,v
retrieving revision 1.42
diff -c -r1.42 scan.l
*** src/pl/plpgsql/src/scan.l 26 Jun 2005 19:16:07 -0000 1.42
--- src/pl/plpgsql/src/scan.l 8 Aug 2005 22:53:36 -0000
***************
*** 186,191 ****
--- 186,192 ----
^#option { return O_OPTION; }
dump { return O_DUMP; }
+ select_into_1_row { return O_SELECT_INTO_1_ROW; }
/* ----------
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend