ECPG doesn't compile CREATE AS EXECUTE properly.
Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.
You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:
docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t44492psql -h localhost -U postgresBuilt from patchset v2 (message #2), July 27, 2026 at 04:37 PM.
Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:
git clone --branch t44492_2 https://github.com/hackorum-dev/postgres.gitIn a checkout you already have, add the fork once:
git remote add hackorum https://github.com/hackorum-dev/postgres.gitthen, for this patchset and every later one:
git fetch hackorum t44492_2 && git checkout t44492_2Patchset v2 (message #2) is on t44492_2
Hello.
While I looked a patch, I found that the following ECPG statement
generates uncompilable .c source.
EXEC SQL CREATE TABLE t AS stmt;
ecpgtest.c:
#line 42 "ecpgtest.pgc"
printf("1:dbname=%s\n", dbname);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_execute, create table t as execute "stmt", ECPGt_EOIT, ECPGt_EORT);
This is apparently broken. The cause is that the rule ExecutStmt is
assumed to return a statement name when type is empty (or null), while
it actually returns a full statement for the CREATE TABLE AS EXECUTE
syntax.
Separating "CREATE TABLE AS EXECUTE" from ExecuteStmt would be cleaner
but I avoided to change the syntax tree. Instead the attched make
distinction of $$.type of ExecuteStmt between NULL and "" to use to
notify the returned name is name of a prepared statement or a full
statement.
I'll post the test part later.
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
Attachments:
v1-0001-Fix-ECPG-s-CREATE-TABLE-AS-EXECUTE.patchtext/x-patch; charset=us-asciiDownload+7-2
At Thu, 01 Jul 2021 18:45:25 +0900 (JST), Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote in
I'll post the test part later.
A version incluedes the test part.
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
On Thu, Jul 01, 2021 at 06:45:25PM +0900, Kyotaro Horiguchi wrote:
Separating "CREATE TABLE AS EXECUTE" from ExecuteStmt would be cleaner
but I avoided to change the syntax tree. Instead the attched make
distinction of $$.type of ExecuteStmt between NULL and "" to use to
notify the returned name is name of a prepared statement or a full
statement.
I am not so sure, and using an empty string makes the code a bit
harder to follow. How would that look with the grammar split you have
in mind? Maybe that makes the code more consistent with the PREPARE
block a couple of lines above?
--
Michael
Thanks for the comment.
At Tue, 6 Jul 2021 11:17:47 +0900, Michael Paquier <michael@paquier.xyz> wrote in
On Thu, Jul 01, 2021 at 06:45:25PM +0900, Kyotaro Horiguchi wrote:
Separating "CREATE TABLE AS EXECUTE" from ExecuteStmt would be cleaner
but I avoided to change the syntax tree. Instead the attched make
distinction of $$.type of ExecuteStmt between NULL and "" to use to
notify the returned name is name of a prepared statement or a full
statement.I am not so sure, and using an empty string makes the code a bit
harder to follow. How would that look with the grammar split you have
I agree to that.
in mind? Maybe that makes the code more consistent with the PREPARE
block a couple of lines above?
More accurately, I didn't come up with the way to split out some of
the rule-components in a rule out as another rule using the existing
infrastructure.
preproc.y:
ExecuteStmt:
EXECUTE prepared_name execute_param_clause execute_rest
{}
| CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest
{}
| CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest
{}
;
I can directly edit this as the following:
ExecuteStmt:
EXECUTE prepared_name execute_param_clause execute_rest
{}
;
CreateExecuteStmt:
| CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest
{}
| CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest
{}
;
Then add the following component to the rule "stmt".
| CreateExecuteStmt:
{ output_statement(..., ECPGst_normal); }
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
On Tue, Jul 06, 2021 at 05:47:34PM +0900, Kyotaro Horiguchi wrote:
More accurately, I didn't come up with the way to split out some of
the rule-components in a rule out as another rule using the existing
infrastructure.[...]
Then add the following component to the rule "stmt".
I see. That sounds interesting as solution, and consistent with the
existing cursor queries. The ECPG parser is not that advanced, and we
may not really need to make it more complicated with sub-clause
handling like INEs. So I'd be rather in favor of what you are
describing here.
--
Michael