[PATCH v1 5/5] POC: Add naive grammar to specify the column logical order in CREATE TABLE
Julien Rouhaud <julien.rouhaud@free.fr>
From: Julien Rouhaud <julien.rouhaud@free.fr>
To:
Date: 2022-06-07T10:46:06Z
Lists: pgsql-hackers
e.g.:
CREATE TABLE ab (b integer, a integer) ORDER (a, b).
Author: Julien Rouhaud
Reviewed-by: FIXME
Discussion: FIXME
---
src/backend/commands/tablecmds.c | 39 +++++++++++++++++++++++++++++-
src/backend/nodes/copyfuncs.c | 1 +
src/backend/nodes/equalfuncs.c | 1 +
src/backend/nodes/outfuncs.c | 1 +
src/backend/parser/gram.y | 41 +++++++++++++++++++++++++++-----
src/include/nodes/parsenodes.h | 1 +
6 files changed, 77 insertions(+), 7 deletions(-)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 06b9733717..660a18c638 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -945,12 +945,49 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
colDef->compression);
}
+ /* Change rels logical attributes position if needed */
+ if (stmt->orderElts != NIL)
+ {
+ if (list_length(stmt->orderElts) != descriptor->natts)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("Invalid number of elements in ORDER clause"),
+ errdetail("expected %d, found %d", descriptor->natts,
+ list_length(stmt->orderElts))));
+
+ for (int i = 0; i < descriptor->natts; i++)
+ {
+ Form_pg_attribute att = TupleDescAttr(descriptor, i);
+ ListCell *lc;
+ AttrNumber attnum = 1;
+ bool found = false;
+
+ foreach(lc, stmt->orderElts)
+ {
+ char *colname = strVal(lfirst(lc));
+
+ if (strcmp(colname, NameStr(att->attname)) == 0)
+ {
+ found = true;
+ att->attnum = attnum;
+ break;
+ }
+ attnum++;
+ }
+
+ if (!found)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("order attribute \"%s\" not found in \"%s\" attributes",
+ NameStr(att->attname), relname)));
+ }
+ }
/*
* FIXME
* testing mode: inverse all attribute positions. This has to be done
* after that defaults have been computed.
*/
- if (relkind == RELKIND_RELATION && inheritOids == NIL
+ else if (relkind == RELKIND_RELATION && inheritOids == NIL
&& descriptor->natts > 1
/* lame attempt to discard CTAS */
&& queryString != NULL)
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 68c6fb7c93..07dc422101 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -4065,6 +4065,7 @@ CopyCreateStmtFields(const CreateStmt *from, CreateStmt *newnode)
{
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(tableElts);
+ COPY_NODE_FIELD(orderElts);
COPY_NODE_FIELD(inhRelations);
COPY_NODE_FIELD(partspec);
COPY_NODE_FIELD(partbound);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index d9ca25606b..bab8abfb02 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1647,6 +1647,7 @@ _equalCreateStmt(const CreateStmt *a, const CreateStmt *b)
{
COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(tableElts);
+ COMPARE_NODE_FIELD(orderElts);
COMPARE_NODE_FIELD(inhRelations);
COMPARE_NODE_FIELD(partbound);
COMPARE_NODE_FIELD(partspec);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index d80d18cfca..65dbe6ea20 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -2870,6 +2870,7 @@ _outCreateStmtInfo(StringInfo str, const CreateStmt *node)
{
WRITE_NODE_FIELD(relation);
WRITE_NODE_FIELD(tableElts);
+ WRITE_NODE_FIELD(orderElts);
WRITE_NODE_FIELD(inhRelations);
WRITE_NODE_FIELD(partspec);
WRITE_NODE_FIELD(partbound);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 969c9c158f..c24adf59de 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -425,6 +425,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> parse_toplevel stmtmulti routine_body_stmt_list
OptTableElementList TableElementList OptInherit definition
+ OptOrderElementList OrderElementList
OptTypedTableElementList TypedTableElementList
reloptions opt_reloptions
OptWith opt_definition func_args func_args_list
@@ -524,6 +525,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
SetResetClause FunctionSetResetClause
%type <node> TableElement TypedTableElement ConstraintElem TableFuncElement
+ OrderElement
%type <node> columnDef columnOptions
%type <defelt> def_elem reloption_elem old_aggr_elem operator_def_elem
%type <node> def_arg columnElem where_clause where_or_current_clause
@@ -3577,6 +3579,7 @@ copy_generic_opt_arg_list_item:
*****************************************************************************/
CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
+ OptOrderElementList
OptInherit OptPartitionSpec table_access_method_clause OptWith
OnCommitOption OptTableSpace
{
@@ -3585,14 +3588,15 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
$4->relpersistence = $2;
n->relation = $4;
n->tableElts = $6;
- n->inhRelations = $8;
- n->partspec = $9;
+ n->orderElts = $8;
+ n->inhRelations = $9;
+ n->partspec = $10;
n->ofTypename = NULL;
n->constraints = NIL;
- n->accessMethod = $10;
- n->options = $11;
- n->oncommit = $12;
- n->tablespacename = $13;
+ n->accessMethod = $11;
+ n->options = $12;
+ n->oncommit = $13;
+ n->tablespacename = $14;
n->if_not_exists = false;
$$ = (Node *) n;
}
@@ -3605,6 +3609,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
$7->relpersistence = $2;
n->relation = $7;
n->tableElts = $9;
+ n->orderElts = NIL;
n->inhRelations = $11;
n->partspec = $12;
n->ofTypename = NULL;
@@ -3625,6 +3630,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
$4->relpersistence = $2;
n->relation = $4;
n->tableElts = $7;
+ n->orderElts = NIL;
n->inhRelations = NIL;
n->partspec = $8;
n->ofTypename = makeTypeNameFromNameList($6);
@@ -3646,6 +3652,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
$7->relpersistence = $2;
n->relation = $7;
n->tableElts = $10;
+ n->orderElts = NIL;
n->inhRelations = NIL;
n->partspec = $11;
n->ofTypename = makeTypeNameFromNameList($9);
@@ -3667,6 +3674,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
$4->relpersistence = $2;
n->relation = $4;
n->tableElts = $8;
+ n->orderElts = NIL;
n->inhRelations = list_make1($7);
n->partbound = $9;
n->partspec = $10;
@@ -3688,6 +3696,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
$7->relpersistence = $2;
n->relation = $7;
n->tableElts = $11;
+ n->orderElts = NIL;
n->inhRelations = list_make1($10);
n->partbound = $12;
n->partspec = $13;
@@ -3735,6 +3744,26 @@ OptTemp: TEMPORARY { $$ = RELPERSISTENCE_TEMP; }
| /*EMPTY*/ { $$ = RELPERSISTENCE_PERMANENT; }
;
+OptOrderElementList:
+ ORDER '(' OrderElementList ')' { $$ = $3; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
+OrderElementList:
+ OrderElement
+ {
+ $$ = list_make1($1);
+ }
+ | OrderElementList ',' OrderElement
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
+OrderElement:
+ columnElem { $$ = $1; }
+ ;
+
OptTableElementList:
TableElementList { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 73f635b455..0f39d72f6f 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2530,6 +2530,7 @@ typedef struct CreateStmt
NodeTag type;
RangeVar *relation; /* relation to create */
List *tableElts; /* column definitions (list of ColumnDef) */
+ List *orderElts; /* column logical order (list of String) */
List *inhRelations; /* relations to inherit from (list of
* RangeVar) */
PartitionBoundSpec *partbound; /* FOR VALUES clause */
--
2.33.1
--niuvl3z5xzutv25e--