Hello This patch remove redundant rows from PL/pgSQL executor (-89 lines). Doesn't change a functionality.
Regards Pavel Stehule
*** ./src/pl/plpgsql/src/pl_exec.c.orig 2010-12-16 10:25:37.000000000 +0100 --- ./src/pl/plpgsql/src/pl_exec.c 2010-12-17 10:50:31.793623763 +0100 *************** *** 204,209 **** --- 204,211 ---- PLpgSQL_expr *dynquery, List *params, const char *portalname, int cursorOptions); + static bool can_leave_loop(PLpgSQL_execstate *estate, + PLpgSQL_any_loop *stmt, int *rc); /* ---------- * plpgsql_exec_function Called by the call handler for *************** *** 1566,1571 **** --- 1568,1637 ---- return exec_stmts(estate, stmt->else_stmts); } + /* + * function returns true, when outer cycle should be leaved + */ + static bool + can_leave_loop(PLpgSQL_execstate *estate, PLpgSQL_any_loop *stmt, int *rc) + { + switch (*rc) + { + case PLPGSQL_RC_OK: + return false; + + case PLPGSQL_RC_RETURN: + return true; + + case PLPGSQL_RC_EXIT: + if (estate->exitlabel == NULL) + { + /* unlabelled exit, finish the current loop */ + *rc = PLPGSQL_RC_OK; + } + if (stmt->label != NULL && strcmp(stmt->label, estate->exitlabel) == 0) + { + /* labelled exit, matches the current stmt's label */ + estate->exitlabel = NULL; + *rc = PLPGSQL_RC_OK; + } + + /* + * otherwise, this is a labelled exit that does not match the + * current statement's label, if any: return RC_EXIT so that the + * EXIT continues to propagate up the stack. + */ + return true; + + case PLPGSQL_RC_CONTINUE: + if (estate->exitlabel == NULL) + { + /* anonymous continue, so re-run the loop */ + *rc = PLPGSQL_RC_OK; + } + else if (stmt->label != NULL && + strcmp(stmt->label, estate->exitlabel) == 0) + { + /* label matches named continue, so re-run loop */ + estate->exitlabel = NULL; + *rc = PLPGSQL_RC_OK; + } + else + { + /* + * otherwise, this is a named continue that does not match the + * current statement's label, if any: return RC_CONTINUE so + * that the CONTINUE will propagate up the stack. + */ + return true; + } + + return false; + + default: + elog(ERROR, "unrecognized rc: %d", *rc); + return false; /* be compiler quiet */ + } + } /* ---------- * exec_stmt_loop Loop over statements until *************** *** 1575,1621 **** static int exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt) { for (;;) { ! int rc = exec_stmts(estate, stmt->body); ! ! switch (rc) ! { ! case PLPGSQL_RC_OK: ! break; ! ! case PLPGSQL_RC_EXIT: ! if (estate->exitlabel == NULL) ! return PLPGSQL_RC_OK; ! if (stmt->label == NULL) ! return PLPGSQL_RC_EXIT; ! if (strcmp(stmt->label, estate->exitlabel) != 0) ! return PLPGSQL_RC_EXIT; ! estate->exitlabel = NULL; ! return PLPGSQL_RC_OK; ! ! case PLPGSQL_RC_CONTINUE: ! if (estate->exitlabel == NULL) ! /* anonymous continue, so re-run the loop */ ! break; ! else if (stmt->label != NULL && ! strcmp(stmt->label, estate->exitlabel) == 0) ! /* label matches named continue, so re-run loop */ ! estate->exitlabel = NULL; ! else ! /* label doesn't match named continue, so propagate upward */ ! return PLPGSQL_RC_CONTINUE; ! break; ! ! case PLPGSQL_RC_RETURN: ! return rc; ! default: ! elog(ERROR, "unrecognized rc: %d", rc); ! } } ! return PLPGSQL_RC_OK; } --- 1641,1657 ---- static int exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt) { + int rc; + for (;;) { ! rc = exec_stmts(estate, stmt->body); ! if (can_leave_loop(estate, (PLpgSQL_any_loop *) stmt, &rc)) ! break; } ! return rc; } *************** *** 1628,1636 **** static int exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt) { for (;;) { - int rc; bool value; bool isnull; --- 1664,1673 ---- static int exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt) { + int rc; + for (;;) { bool value; bool isnull; *************** *** 1642,1684 **** rc = exec_stmts(estate, stmt->body); ! switch (rc) ! { ! case PLPGSQL_RC_OK: ! break; ! ! case PLPGSQL_RC_EXIT: ! if (estate->exitlabel == NULL) ! return PLPGSQL_RC_OK; ! if (stmt->label == NULL) ! return PLPGSQL_RC_EXIT; ! if (strcmp(stmt->label, estate->exitlabel) != 0) ! return PLPGSQL_RC_EXIT; ! estate->exitlabel = NULL; ! return PLPGSQL_RC_OK; ! ! case PLPGSQL_RC_CONTINUE: ! if (estate->exitlabel == NULL) ! /* anonymous continue, so re-run loop */ ! break; ! else if (stmt->label != NULL && ! strcmp(stmt->label, estate->exitlabel) == 0) ! /* label matches named continue, so re-run loop */ ! estate->exitlabel = NULL; ! else ! /* label doesn't match named continue, propagate upward */ ! return PLPGSQL_RC_CONTINUE; ! break; ! ! case PLPGSQL_RC_RETURN: ! return rc; ! ! default: ! elog(ERROR, "unrecognized rc: %d", rc); ! } } ! return PLPGSQL_RC_OK; } --- 1679,1689 ---- rc = exec_stmts(estate, stmt->body); ! if (can_leave_loop(estate, (PLpgSQL_any_loop *) stmt, &rc)) ! break; } ! return rc; } *************** *** 1789,1838 **** */ rc = exec_stmts(estate, stmt->body); ! if (rc == PLPGSQL_RC_RETURN) ! break; /* break out of the loop */ ! else if (rc == PLPGSQL_RC_EXIT) ! { ! if (estate->exitlabel == NULL) ! /* unlabelled exit, finish the current loop */ ! rc = PLPGSQL_RC_OK; ! else if (stmt->label != NULL && ! strcmp(stmt->label, estate->exitlabel) == 0) ! { ! /* labelled exit, matches the current stmt's label */ ! estate->exitlabel = NULL; ! rc = PLPGSQL_RC_OK; ! } ! ! /* ! * otherwise, this is a labelled exit that does not match the ! * current statement's label, if any: return RC_EXIT so that the ! * EXIT continues to propagate up the stack. ! */ break; - } - else if (rc == PLPGSQL_RC_CONTINUE) - { - if (estate->exitlabel == NULL) - /* unlabelled continue, so re-run the current loop */ - rc = PLPGSQL_RC_OK; - else if (stmt->label != NULL && - strcmp(stmt->label, estate->exitlabel) == 0) - { - /* label matches named continue, so re-run loop */ - estate->exitlabel = NULL; - rc = PLPGSQL_RC_OK; - } - else - { - /* - * otherwise, this is a named continue that does not match the - * current statement's label, if any: return RC_CONTINUE so - * that the CONTINUE will propagate up the stack. - */ - break; - } - } /* * Increase/decrease loop value, unless it would overflow, in which --- 1794,1801 ---- */ rc = exec_stmts(estate, stmt->body); ! if (can_leave_loop(estate, (PLpgSQL_any_loop *) stmt, &rc)) break; /* * Increase/decrease loop value, unless it would overflow, in which *************** *** 4410,4469 **** */ rc = exec_stmts(estate, stmt->body); ! if (rc != PLPGSQL_RC_OK) ! { ! if (rc == PLPGSQL_RC_EXIT) ! { ! if (estate->exitlabel == NULL) ! { ! /* unlabelled exit, so exit the current loop */ ! rc = PLPGSQL_RC_OK; ! } ! else if (stmt->label != NULL && ! strcmp(stmt->label, estate->exitlabel) == 0) ! { ! /* label matches this loop, so exit loop */ ! estate->exitlabel = NULL; ! rc = PLPGSQL_RC_OK; ! } ! ! /* ! * otherwise, we processed a labelled exit that does not ! * match the current statement's label, if any; return ! * RC_EXIT so that the EXIT continues to recurse upward. ! */ ! } ! else if (rc == PLPGSQL_RC_CONTINUE) ! { ! if (estate->exitlabel == NULL) ! { ! /* unlabelled continue, so re-run the current loop */ ! rc = PLPGSQL_RC_OK; ! continue; ! } ! else if (stmt->label != NULL && ! strcmp(stmt->label, estate->exitlabel) == 0) ! { ! /* label matches this loop, so re-run loop */ ! estate->exitlabel = NULL; ! rc = PLPGSQL_RC_OK; ! continue; ! } ! ! /* ! * otherwise, we process a labelled continue that does not ! * match the current statement's label, if any; return ! * RC_CONTINUE so that the CONTINUE will propagate up the ! * stack. ! */ ! } ! ! /* ! * We're aborting the loop. Need a goto to get out of two ! * levels of loop... ! */ goto loop_exit; - } } SPI_freetuptable(tuptab); --- 4373,4380 ---- */ rc = exec_stmts(estate, stmt->body); ! if (can_leave_loop(estate, (PLpgSQL_any_loop *) stmt, &rc)) goto loop_exit; } SPI_freetuptable(tuptab); *** ./src/pl/plpgsql/src/plpgsql.h.orig 2010-12-16 09:14:42.000000000 +0100 --- ./src/pl/plpgsql/src/plpgsql.h 2010-12-17 09:54:39.726801715 +0100 *************** *** 407,412 **** --- 407,420 ---- } PLpgSQL_case_when; + typedef struct /* Ancestor of loops */ + { + int cmd_type; + int lineno; + char *label; + } PLpgSQL_any_loop; + + typedef struct { /* Unconditional LOOP statement */ int cmd_type;
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers