summaryrefslogtreecommitdiff
path: root/src/pl/plpgsql
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-09-02 15:53:06 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-09-02 15:56:50 +0300
commitc1008f0037ec9c738127c2fa6d7f6c88d885f45f (patch)
tree6832c92a64a63ee5321008d8d3a46cc170f6c7ce /src/pl/plpgsql
parentf8f4227976a2cdb8ac7c611e49da03aa9e65e0d2 (diff)
downloadpostgresql-c1008f0037ec9c738127c2fa6d7f6c88d885f45f.tar.gz
Check number of parameters in RAISE statement at compile time.
The number of % parameter markers in RAISE statement should match the number of parameters given. We used to check that at execution time, but we have all the information needed at compile time, so let's check it at compile time instead. It's generally better to find mistakes earlier. Marko Tiikkaja, reviewed by Fabien Coelho
Diffstat (limited to 'src/pl/plpgsql')
-rw-r--r--src/pl/plpgsql/src/pl_exec.c14
-rw-r--r--src/pl/plpgsql/src/pl_gram.y38
2 files changed, 42 insertions, 10 deletions
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 69d1965253..11cb47b522 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -2939,10 +2939,9 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
continue;
}
+ /* should have been checked at compile time */
if (current_param == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("too few parameters specified for RAISE")));
+ elog(ERROR, "unexpected RAISE parameter list length");
paramvalue = exec_eval_expr(estate,
(PLpgSQL_expr *) lfirst(current_param),
@@ -2963,14 +2962,9 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
appendStringInfoChar(&ds, cp[0]);
}
- /*
- * If more parameters were specified than were required to process the
- * format string, throw an error
- */
+ /* should have been checked at compile time */
if (current_param != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("too many parameters specified for RAISE")));
+ elog(ERROR, "unexpected RAISE parameter list length");
err_message = ds.data;
/* No pfree(ds.data), the pfree(err_message) does it */
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index e3a992cf0f..893f3a486f 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -106,6 +106,7 @@ static void check_labels(const char *start_label,
static PLpgSQL_expr *read_cursor_args(PLpgSQL_var *cursor,
int until, const char *expected);
static List *read_raise_options(void);
+static void check_raise_parameters(PLpgSQL_stmt_raise *stmt);
%}
@@ -1849,6 +1850,8 @@ stmt_raise : K_RAISE
new->options = read_raise_options();
}
+ check_raise_parameters(new);
+
$$ = (PLpgSQL_stmt *)new;
}
;
@@ -3768,6 +3771,41 @@ read_raise_options(void)
}
/*
+ * Check that the number of parameter placeholders in the message matches the
+ * number of parameters passed to it, if a message was given.
+ */
+static void
+check_raise_parameters(PLpgSQL_stmt_raise *stmt)
+{
+ char *cp;
+ int expected_nparams = 0;
+
+ if (stmt->message == NULL)
+ return;
+
+ for (cp = stmt->message; *cp; cp++)
+ {
+ if (cp[0] == '%')
+ {
+ /* ignore literal % characters */
+ if (cp[1] == '%')
+ cp++;
+ else
+ expected_nparams++;
+ }
+ }
+
+ if (expected_nparams < list_length(stmt->params))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("too many parameters specified for RAISE")));
+ if (expected_nparams > list_length(stmt->params))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("too few parameters specified for RAISE")));
+}
+
+/*
* Fix up CASE statement
*/
static PLpgSQL_stmt *