diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index f8e956b2a423de75fe7dcef58d4901e184438303..fb3a54646f08c02a771f22ac94ad88fb47e3c1a2 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -186,7 +186,7 @@ static	List			*read_raise_options(void);
 
 %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
@@ -1007,7 +1007,7 @@ assign_var		: T_DATUM
 					}
 				;
 
-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;
 
@@ -1015,47 +1015,35 @@ stmt_if			: K_IF expr_until_then proc_sect stmt_else K_END K_IF ';'
 						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;
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index b1ed3c3167c6120bd6d0d30998c6f006077e9791..387362a59a2de3b77e51301439e00b5e294600cb 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -1510,22 +1510,24 @@ exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
 {
 	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);
 }
 
 
diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c
index 030ed07ac55f999af6160bbac9294a4a2f360a42..18ca885e806dabe274eb798777760f9e92f3c7a2 100644
--- a/src/pl/plpgsql/src/pl_funcs.c
+++ b/src/pl/plpgsql/src/pl_funcs.c
@@ -446,9 +446,18 @@ free_assign(PLpgSQL_stmt_assign *stmt)
 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
@@ -877,20 +886,29 @@ dump_assign(PLpgSQL_stmt_assign *stmt)
 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");
 }
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 61503f10a786b18765893185721e12ff2587e8b8..c638f4323f442dbfd6ec86a7b4367dabe2649e77 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -396,11 +396,19 @@ typedef struct
 {								/* 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 */
 {