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

Reply via email to