diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 3432bb921d..ac961df791 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -4563,6 +4563,7 @@ _copyPartitionSpec(const PartitionSpec *from) COPY_STRING_FIELD(strategy); COPY_NODE_FIELD(partParams); + COPY_NODE_FIELD(partdefs); COPY_LOCATION_FIELD(location); return newnode; @@ -4608,6 +4609,23 @@ _copyPartitionCmd(const PartitionCmd *from) return newnode; } +static SubPartition * +_copySubPartition(const SubPartition *from) +{ + SubPartition *newnode = makeNode(SubPartition); + /* + * TODO (Next Version) + * It supports the necessary options in our current version + * We should add something here for options support. + */ + COPY_NODE_FIELD(name); + COPY_NODE_FIELD(bound); + COPY_STRING_FIELD(tablespacename); + COPY_NODE_FIELD(partspec); + + return newnode; +} + static CreatePublicationStmt * _copyCreatePublicationStmt(const CreatePublicationStmt *from) { @@ -5634,6 +5652,9 @@ copyObjectImpl(const void *from) case T_PartitionCmd: retval = _copyPartitionCmd(from); break; + case T_SubPartition: + retval = _copySubPartition(from); + break; /* * MISCELLANEOUS NODES diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 18cb014373..cc966d38a4 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -2872,6 +2872,7 @@ _equalPartitionSpec(const PartitionSpec *a, const PartitionSpec *b) { COMPARE_STRING_FIELD(strategy); COMPARE_NODE_FIELD(partParams); + COMPARE_NODE_FIELD(partdefs); COMPARE_LOCATION_FIELD(location); return true; @@ -2911,6 +2912,21 @@ _equalPartitionCmd(const PartitionCmd *a, const PartitionCmd *b) return true; } +static bool +_equalSubPartition(const SubPartition *a, const SubPartition *b) +{ + /* + * TODO + * It just supports the necessary options currently for POC + */ + COMPARE_NODE_FIELD(name); + COMPARE_NODE_FIELD(bound); + COMPARE_STRING_FIELD(tablespacename); + COMPARE_NODE_FIELD(partspec); + + return true; +} + /* * Stuff from pg_list.h */ @@ -3730,6 +3746,9 @@ equal(const void *a, const void *b) case T_PartitionCmd: retval = _equalPartitionCmd(a, b); break; + case T_SubPartition: + retval = _equalSubPartition(a, b); + break; default: elog(ERROR, "unrecognized node type: %d", diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 3f67aaf30e..9273bb6ea8 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -588,6 +588,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type part_params %type PartitionBoundSpec %type hash_partbound +%type table_partitions_list +%type table_partition %type hash_partbound_elem /* @@ -3870,6 +3872,18 @@ PartitionSpec: PARTITION BY part_strategy '(' part_params ')' $$ = n; } + + | PARTITION BY part_strategy '(' part_params ')' '(' table_partitions_list ')' + { + PartitionSpec *n = makeNode(PartitionSpec); + + n->strategy = $3; + n->partParams = $5; + n->partdefs = $8; + n->location = @1; + + $$ = n; + } ; part_strategy: IDENT { $$ = $1; } @@ -3915,6 +3929,35 @@ part_elem: ColId opt_collate opt_class } ; +/* + * table_partitions_list returns the list of PartitionCmd + * for now, Latter we may want to use more specific data structure + * when we will introduce the shard server specification syntax. + */ +table_partitions_list: + table_partitions_list ',' table_partition + { + $$ = lappend($1, $3); + } + + | table_partition + { + $$ = list_make1($1); + } + ; + +table_partition: PARTITION qualified_name PartitionBoundSpec OptTableSpace OptPartitionSpec + { + SubPartition *n = makeNode(SubPartition); + + n->name = $2; + n->bound = $3; + n->tablespacename = $4; + n->partspec = $5; + $$ = n; + } + ; + table_access_method_clause: USING access_method { $$ = $2; } | /*EMPTY*/ { $$ = NULL; } diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 6e5768c66c..7fe7d38c7b 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -121,6 +121,10 @@ static void transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause); static void transformOfType(CreateStmtContext *cxt, TypeName *ofTypename); +static void transformSubPartitionDefinition(CreateStmtContext *cxt, + SubPartition *partition, RangeVar *parentrelation); +static void transformSubPartitionList(CreateStmtContext *cxt, List *partlist, RangeVar *parentrelation); + static CreateStatsStmt *generateClonedExtStatsStmt(RangeVar *heapRel, Oid heapRelid, Oid source_statsid); static List *get_collation(Oid collation, Oid actual_datatype); @@ -261,6 +265,14 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("cannot create partitioned table as inheritance child"))); + /* + * For handle the new syntax for create subpartition + * during create parent partition table. + */ + if(stmt->partspec->partdefs) + { + transformSubPartitionList(&cxt, stmt->partspec->partdefs, cxt.relation); + } } /* @@ -492,6 +504,66 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column, *sname_p = sname; } +/* + * transformSubPartitionList - + * Handle the subpartition list, and the function body is in transformCreateStmt + * function at first, and it comes to a independent function because of to + * implement recursion subpartition. + */ +static void +transformSubPartitionList(CreateStmtContext *cxt, List *partlist, RangeVar *parentrelation) +{ + ListCell *partielems = NULL; + + //partlist = stmt->partspec->partdefs; + foreach(partielems, partlist) + { + Node *element = lfirst(partielems); + /* + * Set the subpartition create, into cxt.alist. + */ + transformSubPartitionDefinition(cxt, (SubPartition *) element, parentrelation); + } +} + +/* + * transformSubPartitionDefinition - + * transform a partition create within CREATE TABLE + */ +static void +transformSubPartitionDefinition(CreateStmtContext *cxt, SubPartition *partition, RangeVar *relation) +{ + CreateStmt *stmt = NULL; + + stmt = makeNode(CreateStmt); + stmt->relation = partition->name; + stmt->relation->relpersistence = RELPERSISTENCE_PERMANENT; + stmt->tableElts = NULL; + stmt->inhRelations = list_make1(relation); + stmt->partbound = partition->bound; + stmt->partspec = partition->partspec; + stmt->ofTypename = NULL; + stmt->constraints = NIL; + /* + * TODO + * For table_access_method_clause + */ + stmt->accessMethod = NULL; + /* + * TODO + * For OptWith + */ + stmt->options = NULL; + stmt->oncommit = ONCOMMIT_NOOP; + stmt->tablespacename = partition->tablespacename; + cxt->alist = lappend(cxt->alist, stmt); + + if(partition->partspec) + { + transformSubPartitionList(cxt, partition->partspec->partdefs, partition->name); + } +} + /* * transformColumnDefinition - * transform a single ColumnDef within CREATE TABLE diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index bce2d59b0d..582b6d0ae0 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -476,6 +476,7 @@ typedef enum NodeTag T_PartitionBoundSpec, T_PartitionRangeDatum, T_PartitionCmd, + T_SubPartition, T_VacuumRelation, /* diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index d93a79a554..455224a4a9 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -791,6 +791,9 @@ typedef struct PartitionSpec char *strategy; /* partitioning strategy ('hash', 'list' or * 'range') */ List *partParams; /* List of PartitionElems */ + List *partdefs; /* List of partition definations + * provided in the CREATE TABLE + */ int location; /* token location, or -1 if unknown */ } PartitionSpec; @@ -859,6 +862,23 @@ typedef struct PartitionCmd PartitionBoundSpec *bound; /* FOR VALUES, if attaching */ } PartitionCmd; +/* + * Partition - info for subpartition which created during create parent table. + */ +typedef struct SubPartition +{ + /* + * TODO + * It supports the necessary options in our current version + * We should add something here for options support. + */ + NodeTag type; + RangeVar *name; /* name of partition to attach/detach/create */ + char *tablespacename; /* table space to use, or NULL */ + PartitionBoundSpec *bound; /* FOR VALUES of creating subpartition*/ + PartitionSpec *partspec; /* PARTITION BY clause */ +}SubPartition; + /**************************************************************************** * Nodes for a Query tree ****************************************************************************/ diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index fb65265175..ceb65528fb 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -1698,6 +1698,7 @@ PartitionBoundInfo PartitionBoundInfoData PartitionBoundSpec PartitionCmd +SubPartition PartitionDesc PartitionDescData PartitionDirectory