|
|
@ -4,7 +4,7 @@ |
|
|
|
* procedural language |
|
|
|
* procedural language |
|
|
|
* |
|
|
|
* |
|
|
|
* IDENTIFICATION |
|
|
|
* IDENTIFICATION |
|
|
|
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.83 2006/02/12 04:59:32 tgl Exp $ |
|
|
|
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.84 2006/02/12 06:03:38 momjian Exp $ |
|
|
|
* |
|
|
|
* |
|
|
|
* This software is copyrighted by Jan Wieck - Hamburg. |
|
|
|
* This software is copyrighted by Jan Wieck - Hamburg. |
|
|
|
* |
|
|
|
* |
|
|
@ -58,7 +58,9 @@ static void check_sql_expr(const char *stmt); |
|
|
|
static void plpgsql_sql_error_callback(void *arg); |
|
|
|
static void plpgsql_sql_error_callback(void *arg); |
|
|
|
static void check_labels(const char *start_label, |
|
|
|
static void check_labels(const char *start_label, |
|
|
|
const char *end_label); |
|
|
|
const char *end_label); |
|
|
|
|
|
|
|
static PLpgSQL_row *make_scalar_list1(const char *name, |
|
|
|
|
|
|
|
PLpgSQL_datum *variable); |
|
|
|
|
|
|
|
|
|
|
|
%} |
|
|
|
%} |
|
|
|
|
|
|
|
|
|
|
|
%union { |
|
|
|
%union { |
|
|
@ -76,6 +78,7 @@ static void check_labels(const char *start_label, |
|
|
|
int lineno; |
|
|
|
int lineno; |
|
|
|
PLpgSQL_rec *rec; |
|
|
|
PLpgSQL_rec *rec; |
|
|
|
PLpgSQL_row *row; |
|
|
|
PLpgSQL_row *row; |
|
|
|
|
|
|
|
PLpgSQL_datum *scalar; |
|
|
|
} forvariable; |
|
|
|
} forvariable; |
|
|
|
struct |
|
|
|
struct |
|
|
|
{ |
|
|
|
{ |
|
|
@ -890,10 +893,15 @@ for_control : |
|
|
|
new->row = $2.row; |
|
|
|
new->row = $2.row; |
|
|
|
check_assignable((PLpgSQL_datum *) new->row); |
|
|
|
check_assignable((PLpgSQL_datum *) new->row); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if ($2.scalar) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
new->row = make_scalar_list1($2.name, $2.scalar); |
|
|
|
|
|
|
|
check_assignable((PLpgSQL_datum *) new->row); |
|
|
|
|
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
plpgsql_error_lineno = $1; |
|
|
|
plpgsql_error_lineno = $1; |
|
|
|
yyerror("loop variable of loop over rows must be a record or row variable"); |
|
|
|
yyerror("loop variable of loop over rows must be a record, row, or scalar variable"); |
|
|
|
} |
|
|
|
} |
|
|
|
new->query = expr; |
|
|
|
new->query = expr; |
|
|
|
|
|
|
|
|
|
|
@ -948,6 +956,15 @@ for_control : |
|
|
|
|
|
|
|
|
|
|
|
expr2 = plpgsql_read_expression(K_LOOP, "LOOP"); |
|
|
|
expr2 = plpgsql_read_expression(K_LOOP, "LOOP"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* T_SCALAR identifier waits for converting */ |
|
|
|
|
|
|
|
if ($2.scalar) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char *name; |
|
|
|
|
|
|
|
plpgsql_convert_ident($2.name, &name, 1); |
|
|
|
|
|
|
|
pfree($2.name); |
|
|
|
|
|
|
|
$2.name = name; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* create loop's private variable */ |
|
|
|
/* create loop's private variable */ |
|
|
|
fvar = (PLpgSQL_var *) |
|
|
|
fvar = (PLpgSQL_var *) |
|
|
|
plpgsql_build_variable($2.name, |
|
|
|
plpgsql_build_variable($2.name, |
|
|
@ -1002,10 +1019,15 @@ for_control : |
|
|
|
new->row = $2.row; |
|
|
|
new->row = $2.row; |
|
|
|
check_assignable((PLpgSQL_datum *) new->row); |
|
|
|
check_assignable((PLpgSQL_datum *) new->row); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if ($2.scalar) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
new->row = make_scalar_list1($2.name, $2.scalar); |
|
|
|
|
|
|
|
check_assignable((PLpgSQL_datum *) new->row); |
|
|
|
|
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
plpgsql_error_lineno = $1; |
|
|
|
plpgsql_error_lineno = $1; |
|
|
|
yyerror("loop variable of loop over rows must be record or row variable"); |
|
|
|
yyerror("loop variable of loop over rows must be record, row, or scalar variable"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
new->query = expr1; |
|
|
|
new->query = expr1; |
|
|
@ -1027,14 +1049,31 @@ for_control : |
|
|
|
* until we know what's what. |
|
|
|
* until we know what's what. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
for_variable : T_SCALAR |
|
|
|
for_variable : T_SCALAR |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
int tok; |
|
|
|
char *name; |
|
|
|
char *name; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
name = pstrdup(yytext); |
|
|
|
|
|
|
|
$$.scalar = yylval.scalar; |
|
|
|
|
|
|
|
$$.lineno = plpgsql_scanner_lineno(); |
|
|
|
|
|
|
|
|
|
|
|
plpgsql_convert_ident(yytext, &name, 1); |
|
|
|
if((tok = yylex()) == ',') |
|
|
|
$$.name = name; |
|
|
|
{ |
|
|
|
$$.lineno = plpgsql_scanner_lineno(); |
|
|
|
plpgsql_push_back_token(tok); |
|
|
|
$$.rec = NULL; |
|
|
|
$$.name = NULL; |
|
|
|
$$.row = NULL; |
|
|
|
$$.row = read_into_scalar_list(name, $$.scalar); |
|
|
|
|
|
|
|
$$.rec = NULL; |
|
|
|
|
|
|
|
$$.scalar = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pfree(name); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
plpgsql_push_back_token(tok); |
|
|
|
|
|
|
|
$$.name = name; |
|
|
|
|
|
|
|
$$.row = NULL; |
|
|
|
|
|
|
|
$$.rec = NULL; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
| T_WORD |
|
|
|
| T_WORD |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1048,20 +1087,14 @@ for_variable : T_SCALAR |
|
|
|
} |
|
|
|
} |
|
|
|
| T_RECORD |
|
|
|
| T_RECORD |
|
|
|
{ |
|
|
|
{ |
|
|
|
char *name; |
|
|
|
$$.name = NULL; |
|
|
|
|
|
|
|
|
|
|
|
plpgsql_convert_ident(yytext, &name, 1); |
|
|
|
|
|
|
|
$$.name = name; |
|
|
|
|
|
|
|
$$.lineno = plpgsql_scanner_lineno(); |
|
|
|
$$.lineno = plpgsql_scanner_lineno(); |
|
|
|
$$.rec = yylval.rec; |
|
|
|
$$.rec = yylval.rec; |
|
|
|
$$.row = NULL; |
|
|
|
$$.row = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
| T_ROW |
|
|
|
| T_ROW |
|
|
|
{ |
|
|
|
{ |
|
|
|
char *name; |
|
|
|
$$.name = NULL; |
|
|
|
|
|
|
|
|
|
|
|
plpgsql_convert_ident(yytext, &name, 1); |
|
|
|
|
|
|
|
$$.name = name; |
|
|
|
|
|
|
|
$$.lineno = plpgsql_scanner_lineno(); |
|
|
|
$$.lineno = plpgsql_scanner_lineno(); |
|
|
|
$$.row = yylval.row; |
|
|
|
$$.row = yylval.row; |
|
|
|
$$.rec = NULL; |
|
|
|
$$.rec = NULL; |
|
|
@ -2088,6 +2121,30 @@ make_fetch_stmt(void) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static PLpgSQL_row * |
|
|
|
|
|
|
|
make_scalar_list1(const char *name, |
|
|
|
|
|
|
|
PLpgSQL_datum *variable) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
PLpgSQL_row *row; |
|
|
|
|
|
|
|
check_assignable(variable); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
row = palloc(sizeof(PLpgSQL_row)); |
|
|
|
|
|
|
|
row->dtype = PLPGSQL_DTYPE_ROW; |
|
|
|
|
|
|
|
row->refname = pstrdup("*internal*"); |
|
|
|
|
|
|
|
row->lineno = plpgsql_scanner_lineno(); |
|
|
|
|
|
|
|
row->rowtupdesc = NULL; |
|
|
|
|
|
|
|
row->nfields = 1; |
|
|
|
|
|
|
|
row->fieldnames = palloc(sizeof(char *) * 1); |
|
|
|
|
|
|
|
row->varnos = palloc(sizeof(int) * 1); |
|
|
|
|
|
|
|
row->fieldnames[0] = pstrdup(name); |
|
|
|
|
|
|
|
row->varnos[0] = variable->dno; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plpgsql_adddatum((PLpgSQL_datum *)row); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return row; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
static void |
|
|
|
check_assignable(PLpgSQL_datum *datum) |
|
|
|
check_assignable(PLpgSQL_datum *datum) |
|
|
|
{ |
|
|
|
{ |
|
|
|