Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4be2018

Browse files
committed
Fix some problems in new plpgsql cursor operations, found while trying
to reverse-engineer documentation for them.
1 parent d4337f6 commit 4be2018

File tree

4 files changed

+98
-155
lines changed

4 files changed

+98
-155
lines changed

src/pl/plpgsql/src/gram.y

+26-20
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* procedural language
55
*
66
* IDENTIFICATION
7-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.27 2001/10/09 15:59:56 tgl Exp $
7+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.28 2001/11/15 23:31:09 tgl Exp $
88
*
99
* This software is copyrighted by Jan Wieck - Hamburg.
1010
*
@@ -351,14 +351,17 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
351351
{
352352
plpgsql_ns_rename($2, $4);
353353
}
354-
| decl_varname K_CURSOR decl_cursor_args decl_is_from K_SELECT decl_cursor_query
354+
| decl_varname K_CURSOR
355+
{ plpgsql_ns_push(NULL); }
356+
decl_cursor_args decl_is_from K_SELECT decl_cursor_query
355357
{
356358
PLpgSQL_var *new;
357359
PLpgSQL_expr *curname_def;
358360
char buf[1024];
359361
char *cp1;
360362
char *cp2;
361363

364+
/* pop local namespace for cursor args */
362365
plpgsql_ns_pop();
363366

364367
new = malloc(sizeof(PLpgSQL_var));
@@ -381,22 +384,21 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
381384
*cp2++ = '\\';
382385
*cp2++ = *cp1++;
383386
}
384-
*cp2++ = '\'';
385-
*cp2 = '\0';
387+
strcpy(cp2, "'::refcursor");
386388
curname_def->query = strdup(buf);
387389
new->default_val = curname_def;
388390

389391
new->datatype = plpgsql_parse_datatype("refcursor");
390392

391-
new->cursor_explicit_expr = $6;
392-
if ($3 == NULL)
393+
new->cursor_explicit_expr = $7;
394+
if ($4 == NULL)
393395
new->cursor_explicit_argrow = -1;
394396
else
395-
new->cursor_explicit_argrow = $3->rowno;
397+
new->cursor_explicit_argrow = $4->rowno;
396398

397399
plpgsql_adddatum((PLpgSQL_datum *)new);
398400
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
399-
$1.name);
401+
$1.name);
400402
}
401403
;
402404

@@ -416,15 +418,17 @@ decl_cursor_args :
416418
{
417419
$$ = NULL;
418420
}
419-
| decl_cursor_openparen decl_cursor_arglist ')'
421+
| '(' decl_cursor_arglist ')'
420422
{
423+
/* Copy the temp arrays to malloc'd storage */
424+
int nfields = $2->nfields;
421425
char **ftmp;
422426
int *vtmp;
423427

424-
ftmp = malloc($2->nfields * sizeof(char *));
425-
vtmp = malloc($2->nfields * sizeof(int));
426-
memcpy(ftmp, $2->fieldnames, $2->nfields * sizeof(char *));
427-
memcpy(vtmp, $2->varnos, $2->nfields * sizeof(int));
428+
ftmp = malloc(nfields * sizeof(char *));
429+
vtmp = malloc(nfields * sizeof(int));
430+
memcpy(ftmp, $2->fieldnames, nfields * sizeof(char *));
431+
memcpy(vtmp, $2->varnos, nfields * sizeof(int));
428432

429433
pfree((char *)($2->fieldnames));
430434
pfree((char *)($2->varnos));
@@ -449,6 +453,12 @@ decl_cursor_arglist : decl_cursor_arg
449453
new->refname = strdup("*internal*");
450454
new->lineno = yylineno;
451455
new->rowtypeclass = InvalidOid;
456+
/*
457+
* We make temporary fieldnames/varnos arrays that
458+
* are much bigger than necessary. We will resize
459+
* them to just the needed size in the
460+
* decl_cursor_args production.
461+
*/
452462
new->fieldnames = palloc(1024 * sizeof(char *));
453463
new->varnos = palloc(1024 * sizeof(int));
454464
new->nfields = 1;
@@ -464,6 +474,8 @@ decl_cursor_arglist : decl_cursor_arg
464474

465475
$1->fieldnames[i] = $3->refname;
466476
$1->varnos[i] = $3->varno;
477+
478+
$$ = $1;
467479
}
468480
;
469481

@@ -484,18 +496,12 @@ decl_cursor_arg : decl_varname decl_datatype
484496

485497
plpgsql_adddatum((PLpgSQL_datum *)new);
486498
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
487-
$1.name);
499+
$1.name);
488500

489501
$$ = new;
490502
}
491503
;
492504

493-
decl_cursor_openparen : '('
494-
{
495-
plpgsql_ns_push(NULL);
496-
}
497-
;
498-
499505
decl_is_from : K_IS | /* Oracle */
500506
K_FOR; /* ANSI */
501507

src/pl/plpgsql/src/pl_exec.c

+21-132
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.51 2001/11/13 02:05:27 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.52 2001/11/15 23:31:09 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -192,76 +192,12 @@ plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo)
192192
elog(NOTICE, "Error occurred while executing PL/pgSQL function %s",
193193
error_info_func->fn_name);
194194
if (error_info_stmt != NULL)
195-
{
196-
char *stmttype;
197-
198-
switch (error_info_stmt->cmd_type)
199-
{
200-
case PLPGSQL_STMT_BLOCK:
201-
stmttype = "blocks variable initialization";
202-
break;
203-
case PLPGSQL_STMT_ASSIGN:
204-
stmttype = "assignment";
205-
break;
206-
case PLPGSQL_STMT_GETDIAG:
207-
stmttype = "get diagnostics";
208-
break;
209-
case PLPGSQL_STMT_IF:
210-
stmttype = "if";
211-
break;
212-
case PLPGSQL_STMT_LOOP:
213-
stmttype = "loop";
214-
break;
215-
case PLPGSQL_STMT_WHILE:
216-
stmttype = "while";
217-
break;
218-
case PLPGSQL_STMT_FORI:
219-
stmttype = "for with integer loopvar";
220-
break;
221-
case PLPGSQL_STMT_FORS:
222-
stmttype = "for over select rows";
223-
break;
224-
case PLPGSQL_STMT_SELECT:
225-
stmttype = "select into variables";
226-
break;
227-
case PLPGSQL_STMT_EXIT:
228-
stmttype = "exit";
229-
break;
230-
case PLPGSQL_STMT_RETURN:
231-
stmttype = "return";
232-
break;
233-
case PLPGSQL_STMT_RAISE:
234-
stmttype = "raise";
235-
break;
236-
case PLPGSQL_STMT_EXECSQL:
237-
stmttype = "SQL statement";
238-
break;
239-
case PLPGSQL_STMT_DYNEXECUTE:
240-
stmttype = "execute statement";
241-
break;
242-
case PLPGSQL_STMT_DYNFORS:
243-
stmttype = "for over execute statement";
244-
break;
245-
case PLPGSQL_STMT_FETCH:
246-
stmttype = "fetch";
247-
break;
248-
case PLPGSQL_STMT_CLOSE:
249-
stmttype = "close";
250-
break;
251-
default:
252-
stmttype = "unknown";
253-
break;
254-
}
255195
elog(NOTICE, "line %d at %s", error_info_stmt->lineno,
256-
stmttype);
257-
}
196+
plpgsql_stmt_typename(error_info_stmt));
197+
else if (error_info_text != NULL)
198+
elog(NOTICE, "%s", error_info_text);
258199
else
259-
{
260-
if (error_info_text != NULL)
261-
elog(NOTICE, "%s", error_info_text);
262-
else
263-
elog(NOTICE, "no more error information available");
264-
}
200+
elog(NOTICE, "no more error information available");
265201

266202
error_info_func = NULL;
267203
error_info_stmt = NULL;
@@ -504,70 +440,12 @@ plpgsql_exec_trigger(PLpgSQL_function * func,
504440
elog(NOTICE, "Error occurred while executing PL/pgSQL function %s",
505441
error_info_func->fn_name);
506442
if (error_info_stmt != NULL)
507-
{
508-
char *stmttype;
509-
510-
switch (error_info_stmt->cmd_type)
511-
{
512-
case PLPGSQL_STMT_BLOCK:
513-
stmttype = "blocks variable initialization";
514-
break;
515-
case PLPGSQL_STMT_ASSIGN:
516-
stmttype = "assignment";
517-
break;
518-
case PLPGSQL_STMT_GETDIAG:
519-
stmttype = "get diagnostics";
520-
break;
521-
case PLPGSQL_STMT_IF:
522-
stmttype = "if";
523-
break;
524-
case PLPGSQL_STMT_LOOP:
525-
stmttype = "loop";
526-
break;
527-
case PLPGSQL_STMT_WHILE:
528-
stmttype = "while";
529-
break;
530-
case PLPGSQL_STMT_FORI:
531-
stmttype = "for with integer loopvar";
532-
break;
533-
case PLPGSQL_STMT_FORS:
534-
stmttype = "for over select rows";
535-
break;
536-
case PLPGSQL_STMT_SELECT:
537-
stmttype = "select into variables";
538-
break;
539-
case PLPGSQL_STMT_EXIT:
540-
stmttype = "exit";
541-
break;
542-
case PLPGSQL_STMT_RETURN:
543-
stmttype = "return";
544-
break;
545-
case PLPGSQL_STMT_RAISE:
546-
stmttype = "raise";
547-
break;
548-
case PLPGSQL_STMT_EXECSQL:
549-
stmttype = "SQL statement";
550-
break;
551-
case PLPGSQL_STMT_DYNEXECUTE:
552-
stmttype = "execute statement";
553-
break;
554-
case PLPGSQL_STMT_DYNFORS:
555-
stmttype = "for over execute statement";
556-
break;
557-
default:
558-
stmttype = "unknown";
559-
break;
560-
}
561443
elog(NOTICE, "line %d at %s", error_info_stmt->lineno,
562-
stmttype);
563-
}
444+
plpgsql_stmt_typename(error_info_stmt));
445+
else if (error_info_text != NULL)
446+
elog(NOTICE, "%s", error_info_text);
564447
else
565-
{
566-
if (error_info_text != NULL)
567-
elog(NOTICE, "%s", error_info_text);
568-
else
569-
elog(NOTICE, "no more error information available");
570-
}
448+
elog(NOTICE, "no more error information available");
571449

572450
error_info_func = NULL;
573451
error_info_stmt = NULL;
@@ -2412,7 +2290,7 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
24122290
HeapTuple typetup;
24132291
Form_pg_type typeStruct;
24142292
FmgrInfo finfo_output;
2415-
void *curplan = NULL;
2293+
void *curplan;
24162294

24172295
/* ----------
24182296
* We evaluate the string expression after the
@@ -2471,6 +2349,9 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
24712349
{
24722350
/* ----------
24732351
* This is an OPEN cursor
2352+
*
2353+
* Note: parser should already have checked that statement supplies
2354+
* args iff cursor needs them, but we check again to be safe.
24742355
* ----------
24752356
*/
24762357
if (stmt->argquery != NULL)
@@ -2483,6 +2364,9 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
24832364
*/
24842365
PLpgSQL_stmt_select set_args;
24852366

2367+
if (curvar->cursor_explicit_argrow < 0)
2368+
elog(ERROR, "arguments given for cursor without arguments");
2369+
24862370
memset(&set_args, 0, sizeof(set_args));
24872371
set_args.cmd_type = PLPGSQL_STMT_SELECT;
24882372
set_args.lineno = stmt->lineno;
@@ -2493,6 +2377,11 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
24932377
if (exec_stmt_select(estate, &set_args) != PLPGSQL_RC_OK)
24942378
elog(ERROR, "open cursor failed during argument processing");
24952379
}
2380+
else
2381+
{
2382+
if (curvar->cursor_explicit_argrow >= 0)
2383+
elog(ERROR, "arguments required for cursor");
2384+
}
24962385

24972386
query = curvar->cursor_explicit_expr;
24982387
if (query->plan == NULL)

src/pl/plpgsql/src/pl_funcs.c

+48-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.16 2001/10/09 15:59:56 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.17 2001/11/15 23:31:09 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -360,7 +360,54 @@ plpgsql_tolower(char *s)
360360
}
361361

362362

363+
/*
364+
* Statement type as a string, for use in error messages etc.
365+
*/
366+
const char *
367+
plpgsql_stmt_typename(PLpgSQL_stmt * stmt)
368+
{
369+
switch (stmt->cmd_type)
370+
{
371+
case PLPGSQL_STMT_BLOCK:
372+
return "block variables initialization";
373+
case PLPGSQL_STMT_ASSIGN:
374+
return "assignment";
375+
case PLPGSQL_STMT_IF:
376+
return "if";
377+
case PLPGSQL_STMT_LOOP:
378+
return "loop";
379+
case PLPGSQL_STMT_WHILE:
380+
return "while";
381+
case PLPGSQL_STMT_FORI:
382+
return "for with integer loopvar";
383+
case PLPGSQL_STMT_FORS:
384+
return "for over select rows";
385+
case PLPGSQL_STMT_SELECT:
386+
return "select into variables";
387+
case PLPGSQL_STMT_EXIT:
388+
return "exit";
389+
case PLPGSQL_STMT_RETURN:
390+
return "return";
391+
case PLPGSQL_STMT_RAISE:
392+
return "raise";
393+
case PLPGSQL_STMT_EXECSQL:
394+
return "SQL statement";
395+
case PLPGSQL_STMT_DYNEXECUTE:
396+
return "execute statement";
397+
case PLPGSQL_STMT_DYNFORS:
398+
return "for over execute statement";
399+
case PLPGSQL_STMT_GETDIAG:
400+
return "get diagnostics";
401+
case PLPGSQL_STMT_OPEN:
402+
return "open";
403+
case PLPGSQL_STMT_FETCH:
404+
return "fetch";
405+
case PLPGSQL_STMT_CLOSE:
406+
return "close";
407+
}
363408

409+
return "unknown";
410+
}
364411

365412

366413
/**********************************************************************

0 commit comments

Comments
 (0)