%type <str> any_identifier opt_block_label opt_label
-%type <list> proc_sect proc_stmts stmt_else
+%type <list> proc_sect proc_stmts stmt_elsifs stmt_else
%type <loop_body> loop_body
%type <stmt> proc_stmt pl_block
%type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
}
;
-stmt_if : K_IF expr_until_then proc_sect stmt_else K_END K_IF ';'
+stmt_if : K_IF expr_until_then proc_sect stmt_elsifs stmt_else K_END K_IF ';'
{
PLpgSQL_stmt_if *new;
new->cmd_type = PLPGSQL_STMT_IF;
new->lineno = plpgsql_location_to_lineno(@1);
new->cond = $2;
- new->true_body = $3;
- new->false_body = $4;
+ new->then_body = $3;
+ new->elsif_list = $4;
+ new->else_body = $5;
$$ = (PLpgSQL_stmt *)new;
}
;
-stmt_else :
+stmt_elsifs :
{
$$ = NIL;
}
- | K_ELSIF expr_until_then proc_sect stmt_else
- {
- /*----------
- * Translate the structure: into:
- *
- * IF c1 THEN IF c1 THEN
- * ... ...
- * ELSIF c2 THEN ELSE
- * IF c2 THEN
- * ... ...
- * ELSE ELSE
- * ... ...
- * END IF END IF
- * END IF
- *----------
- */
- PLpgSQL_stmt_if *new_if;
+ | stmt_elsifs K_ELSIF expr_until_then proc_sect
+ {
+ PLpgSQL_if_elsif *new;
- /* first create a new if-statement */
- new_if = palloc0(sizeof(PLpgSQL_stmt_if));
- new_if->cmd_type = PLPGSQL_STMT_IF;
- new_if->lineno = plpgsql_location_to_lineno(@1);
- new_if->cond = $2;
- new_if->true_body = $3;
- new_if->false_body = $4;
+ new = palloc0(sizeof(PLpgSQL_if_elsif));
+ new->lineno = plpgsql_location_to_lineno(@2);
+ new->cond = $3;
+ new->stmts = $4;
- /* wrap the if-statement in a "container" list */
- $$ = list_make1(new_if);
+ $$ = lappend($1, new);
}
+ ;
+stmt_else :
+ {
+ $$ = NIL;
+ }
| K_ELSE proc_sect
{
$$ = $2;
{
bool value;
bool isnull;
+ ListCell *lc;
value = exec_eval_boolean(estate, stmt->cond, &isnull);
exec_eval_cleanup(estate);
-
if (!isnull && value)
+ return exec_stmts(estate, stmt->then_body);
+
+ foreach(lc, stmt->elsif_list)
{
- if (stmt->true_body != NIL)
- return exec_stmts(estate, stmt->true_body);
- }
- else
- {
- if (stmt->false_body != NIL)
- return exec_stmts(estate, stmt->false_body);
+ PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(lc);
+
+ value = exec_eval_boolean(estate, elif->cond, &isnull);
+ exec_eval_cleanup(estate);
+ if (!isnull && value)
+ return exec_stmts(estate, elif->stmts);
}
- return PLPGSQL_RC_OK;
+ return exec_stmts(estate, stmt->else_body);
}
static void
free_if(PLpgSQL_stmt_if *stmt)
{
+ ListCell *l;
+
free_expr(stmt->cond);
- free_stmts(stmt->true_body);
- free_stmts(stmt->false_body);
+ free_stmts(stmt->then_body);
+ foreach(l, stmt->elsif_list)
+ {
+ PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(l);
+
+ free_expr(elif->cond);
+ free_stmts(elif->stmts);
+ }
+ free_stmts(stmt->else_body);
}
static void
static void
dump_if(PLpgSQL_stmt_if *stmt)
{
+ ListCell *l;
+
dump_ind();
printf("IF ");
dump_expr(stmt->cond);
printf(" THEN\n");
+ dump_stmts(stmt->then_body);
+ foreach(l, stmt->elsif_list)
+ {
+ PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(l);
- dump_stmts(stmt->true_body);
-
- if (stmt->false_body != NIL)
+ dump_ind();
+ printf(" ELSIF ");
+ dump_expr(elif->cond);
+ printf(" THEN\n");
+ dump_stmts(elif->stmts);
+ }
+ if (stmt->else_body != NIL)
{
dump_ind();
printf(" ELSE\n");
- dump_stmts(stmt->false_body);
+ dump_stmts(stmt->else_body);
}
-
dump_ind();
printf(" ENDIF\n");
}
{ /* IF statement */
int cmd_type;
int lineno;
- PLpgSQL_expr *cond;
- List *true_body; /* List of statements */
- List *false_body; /* List of statements */
+ PLpgSQL_expr *cond; /* boolean expression for THEN */
+ List *then_body; /* List of statements */
+ List *elsif_list; /* List of PLpgSQL_if_elsif structs */
+ List *else_body; /* List of statements */
} PLpgSQL_stmt_if;
+typedef struct /* one ELSIF arm of IF statement */
+{
+ int lineno;
+ PLpgSQL_expr *cond; /* boolean expression for this case */
+ List *stmts; /* List of statements */
+} PLpgSQL_if_elsif;
+
typedef struct /* CASE statement */
{