Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions src/pg_query_parse_plpgsql.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,10 @@ static PLpgSQL_function *compile_do_stmt(DoStmt* stmt)
}
}

assert(proc_source != NULL);
if (proc_source == NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("no inline code specified")));

if(strcmp(language, "plpgsql") != 0) {
return (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
Expand Down Expand Up @@ -431,11 +434,25 @@ compile_create_function_stmt_via_callback(CreateFunctionStmt *stmt)
}
}

assert(proc_source != NULL);

if (strcmp(language, "plpgsql") != 0)
return (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));

/* Mirrors the checks in upstream interpret_AS_clause */
if (stmt->sql_body == NULL && proc_source == NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("no function body specified")));

if (stmt->sql_body != NULL && proc_source != NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("duplicate function body specified")));

if (stmt->sql_body != NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("inline SQL function body only valid for language SQL")));

wrapper = pg_query_create_function(stmt, language, proc_source,
&is_dml_trigger, &is_event_trigger);

Expand Down Expand Up @@ -624,6 +641,7 @@ PgQueryPlpgsqlParseResult pg_query_parse_plpgsql(const char* input)

if (statements.stmts_count == 0) {
result.plpgsql_funcs = strdup("[]");
free(parse_result.stderr_buffer);
pg_query_exit_memory_context(ctx);
return result;
}
Expand All @@ -639,6 +657,7 @@ PgQueryPlpgsqlParseResult pg_query_parse_plpgsql(const char* input)
result.error = func_and_error.error;

if (result.error != NULL) {
free(parse_result.stderr_buffer);
pg_query_exit_memory_context(ctx);
return result;
}
Expand Down
59 changes: 59 additions & 0 deletions test/parse_plpgsql.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,40 @@
#include <fcntl.h>
#include <assert.h>

static bool
expect_error(const char *input, const char *expected_message)
{
PgQueryPlpgsqlParseResult result = pg_query_parse_plpgsql(input);
bool success = result.error != NULL &&
strcmp(result.error->message, expected_message) == 0;

if (!success)
{
printf("Expected error: %s\n", expected_message);
printf("Actual error: %s\n",
result.error == NULL ? "(none)" : result.error->message);
}

pg_query_free_plpgsql_parse_result(result);
return success;
}

static bool
expect_no_error(const char *input)
{
PgQueryPlpgsqlParseResult result = pg_query_parse_plpgsql(input);
bool success = result.error == NULL;

if (!success)
{
printf("Expected no error for: %s\n", input);
printf("Actual error: %s\n", result.error->message);
}

pg_query_free_plpgsql_parse_result(result);
return success;
}

int main() {
bool ret_code = EXIT_SUCCESS;
char *sample_buffer;
Expand Down Expand Up @@ -56,6 +90,31 @@ int main() {

pg_query_free_plpgsql_parse_result(result);

if (!expect_error("CREATE FUNCTION f() RETURNS void LANGUAGE plpgsql;",
"no function body specified"))
ret_code = EXIT_FAILURE;

if (!expect_error("DO LANGUAGE plpgsql;",
"no inline code specified"))
ret_code = EXIT_FAILURE;

if (!expect_error("CREATE FUNCTION f() RETURNS int LANGUAGE plpgsql RETURN 1;",
"inline SQL function body only valid for language SQL"))
ret_code = EXIT_FAILURE;

if (!expect_error("CREATE FUNCTION f() RETURNS int AS $$ BEGIN RETURN 1; END; $$ LANGUAGE plpgsql RETURN 1;",
"duplicate function body specified"))
ret_code = EXIT_FAILURE;

if (!expect_no_error("CREATE FUNCTION f() RETURNS int LANGUAGE sql RETURN 1;"))
ret_code = EXIT_FAILURE;

if (!expect_no_error("CREATE FUNCTION f() RETURNS int LANGUAGE sql BEGIN ATOMIC SELECT 1; END;"))
ret_code = EXIT_FAILURE;

if (!expect_no_error("SELECT 1;"))
ret_code = EXIT_FAILURE;

pg_query_exit();

return ret_code;
Expand Down
Loading