From f9f5eb3cf6370e48e771507305edba0a792dddf9 Mon Sep 17 00:00:00 2001 From: wuyuechuan Date: Wed, 3 Aug 2022 17:29:49 +0800 Subject: [PATCH] create table/index/function/procedure/funciton support --- src/common/backend/catalog/heap.cpp | 20 ++- src/common/backend/nodes/copyfuncs.cpp | 2 +- src/common/backend/nodes/equalfuncs.cpp | 1 + src/common/backend/nodes/outfuncs.cpp | 3 + src/common/backend/nodes/readfuncs.cpp | 6 +- src/common/backend/parser/gram.y | 144 +++++++++++++----- src/common/backend/parser/parse_utilcmd.cpp | 32 +++- .../optimizer/commands/functioncmds.cpp | 58 ++++++- .../optimizer/commands/indexcmds.cpp | 12 ++ .../optimizer/commands/tablecmds.cpp | 33 +++- src/gausskernel/process/tcop/postgres.cpp | 4 +- src/gausskernel/process/tcop/utility.cpp | 44 ------ src/include/knl/knl_session.h | 2 + src/include/nodes/parsenodes_common.h | 4 +- src/test/regress/expected/b_comments.out | 73 ++++++++- src/test/regress/sql/b_comments.sql | 32 +++- 16 files changed, 366 insertions(+), 104 deletions(-) diff --git a/src/common/backend/catalog/heap.cpp b/src/common/backend/catalog/heap.cpp index e7b193b76..97dc81fe7 100644 --- a/src/common/backend/catalog/heap.cpp +++ b/src/common/backend/catalog/heap.cpp @@ -119,6 +119,7 @@ #include "catalog/pgxc_class.h" #include "catalog/pgxc_node.h" #include "catalog/pgxc_slice.h" +#include "commands/comment.h" #include "pgxc/locator.h" #include "pgxc/groupmgr.h" #include "pgxc/nodemgr.h" @@ -156,7 +157,7 @@ static void heapDropPartitionTable(Relation relation); static Oid AddNewRelationType(const char* typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, Oid ownerid, Oid new_row_type, Oid new_array_type); static void RelationRemoveInheritance(Oid relid); -static void StoreRelCheck( +static Oid StoreRelCheck( Relation rel, const char* ccname, Node* expr, bool is_validated, bool is_local, int inhcount, bool is_no_inherit); static void StoreConstraints(Relation rel, List* cooked_constraints); static bool MergeWithExistingConstraint( @@ -3739,7 +3740,7 @@ void StoreAttrDefault(Relation rel, AttrNumber attnum, Node* expr, char generate * Caller is responsible for updating the count of constraints * in the pg_class entry for the relation. */ -static void StoreRelCheck( +static Oid StoreRelCheck( Relation rel, const char* ccname, Node* expr, bool is_validated, bool is_local, int inhcount, bool is_no_inherit) { char* ccbin = NULL; @@ -3791,7 +3792,7 @@ static void StoreRelCheck( /* * Create the Check Constraint */ - (void)CreateConstraintEntry(ccname, /* Constraint Name */ + Oid oid = CreateConstraintEntry(ccname, /* Constraint Name */ RelationGetNamespace(rel), /* namespace */ CONSTRAINT_CHECK, /* Constraint Type */ false, /* Is Deferrable */ @@ -3823,6 +3824,7 @@ static void StoreRelCheck( pfree(ccbin); pfree(ccsrc); + return oid; } /* @@ -4066,8 +4068,16 @@ List* AddRelationNewConstraints( /* * OK, store it. */ - StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local, is_local ? 0 : 1, cdef->is_no_inherit); - + Oid oid = StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local, is_local ? 0 : 1, cdef->is_no_inherit); + ListCell *cell = NULL; + foreach (cell, cdef->constraintOptions) { + void *pointer = lfirst(cell); + if (IsA(pointer, CommentStmt)) { + CommentStmt *commentStmt = (CommentStmt *)pointer; + CreateComments(oid, ConstraintRelationId, 0, commentStmt->comment); + break; + } + } numchecks++; cooked = (CookedConstraint*)palloc(sizeof(CookedConstraint)); diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index bed60cf45..dcf3e2b6a 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -4148,7 +4148,7 @@ static Constraint* _copyConstraint(const Constraint* from) COPY_SCALAR_FIELD(skip_validation); COPY_SCALAR_FIELD(initially_valid); COPY_NODE_FIELD(inforConstraint); - + COPY_NODE_FIELD(constraintOptions); return newnode; } diff --git a/src/common/backend/nodes/equalfuncs.cpp b/src/common/backend/nodes/equalfuncs.cpp index 8fe38309f..1dbd799c1 100644 --- a/src/common/backend/nodes/equalfuncs.cpp +++ b/src/common/backend/nodes/equalfuncs.cpp @@ -2603,6 +2603,7 @@ static bool _equalConstraint(const Constraint* a, const Constraint* b) COMPARE_SCALAR_FIELD(old_pktable_oid); COMPARE_SCALAR_FIELD(skip_validation); COMPARE_SCALAR_FIELD(initially_valid); + COMPARE_NODE_FIELD(constraintOptions); return true; } diff --git a/src/common/backend/nodes/outfuncs.cpp b/src/common/backend/nodes/outfuncs.cpp index d69e4ea5a..14bde1160 100755 --- a/src/common/backend/nodes/outfuncs.cpp +++ b/src/common/backend/nodes/outfuncs.cpp @@ -5085,6 +5085,9 @@ static void _outConstraint(StringInfo str, Constraint* node) appendStringInfo(str, "", (int)node->contype); break; } + if (t_thrd.proc->workingVersionNum >= COMMENT_SUPPORT_VERSION_NUM) { + WRITE_NODE_FIELD(constraintOptions); + } } static void _outDistFdwDataNodeTask(StringInfo str, DistFdwDataNodeTask* node) diff --git a/src/common/backend/nodes/readfuncs.cpp b/src/common/backend/nodes/readfuncs.cpp index 60f50d46e..9469c0fd6 100755 --- a/src/common/backend/nodes/readfuncs.cpp +++ b/src/common/backend/nodes/readfuncs.cpp @@ -5386,7 +5386,7 @@ static IndexStmt* _readIndexStmt() READ_OID_FIELD(indexOid); READ_OID_FIELD(oldNode); READ_NODE_FIELD(partClause); - IF_EXIST(columnOptions) { + IF_EXIST(indexOptions) { READ_NODE_FIELD(indexOptions); } READ_BOOL_FIELD(isPartitioned); @@ -5489,7 +5489,9 @@ static Constraint* _readConstraint() ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("_readConstraint(): badly contype \"%s\"...", token))); } - + IF_EXIST(constraintOptions) { + READ_NODE_FIELD(constraintOptions); + } READ_DONE(); } diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index a943fc8a3..ca9910f7c 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -493,6 +493,10 @@ static int errstate; /* b compatibility: comment start */ %type opt_index_options index_options opt_table_options table_options opt_column_options column_options %type index_option table_option column_option + +%type opt_part_options +%type part_options +%type part_option /* b compatibility: comment end */ %type group_by_list @@ -2840,6 +2844,31 @@ modify_column_cmd: cons->location = @2; $$ = (Node *)n; } + /* modify column comments start */ + | COLUMN ColId opt_column_options + { + AlterTableCmd *n = makeNode(AlterTableCmd); + ColumnDef *def = makeNode(ColumnDef); + def->columnOptions = $3; + def->colname = $2; + n->subtype = AT_COMMENTS; + n->def = (Node *) def; + n->name = NULL; + $$ = (Node *)n; + } + ; + | ColId opt_column_options + { + AlterTableCmd *n = makeNode(AlterTableCmd); + ColumnDef *def = makeNode(ColumnDef); + def->columnOptions = $2; + def->colname = $1; + n->subtype = AT_COMMENTS; + n->def = (Node *) def; + n->name = NULL; + $$ = (Node *)n; + } + /* modify column comments end */ ; opt_enable: ENABLE_P {} | /* empty */ {} @@ -2916,7 +2945,7 @@ alter_partition_cmd: } /* ALTER TABLE ADD PARTITION: use less/than */ | ADD_PARTITION name VALUES LESS THAN - '(' maxValueList ')' OptTableSpace + '(' maxValueList ')' opt_part_options { RangePartitionDefState *p = makeNode(RangePartitionDefState); AlterTableCmd *n = makeNode(AlterTableCmd); @@ -2931,7 +2960,7 @@ alter_partition_cmd: $$ = (Node *)n; } /* ALTER TABLE ADD PARTITION: use START/END */ - | ADD_PARTITION name START '(' maxValueList ')' END_P '(' maxValueList ')' opt_range_every_list OptTableSpace + | ADD_PARTITION name START '(' maxValueList ')' END_P '(' maxValueList ')' opt_range_every_list opt_part_options { RangePartitionStartEndDefState *p = makeNode(RangePartitionStartEndDefState); AlterTableCmd *n = makeNode(AlterTableCmd); @@ -2947,7 +2976,7 @@ alter_partition_cmd: n->def = (Node*)s; $$ = (Node *)n; } - | ADD_PARTITION name END_P '(' maxValueList ')' OptTableSpace + | ADD_PARTITION name END_P '(' maxValueList ')' opt_part_options { RangePartitionStartEndDefState *p = makeNode(RangePartitionStartEndDefState); AlterTableCmd *n = makeNode(AlterTableCmd); @@ -2963,7 +2992,7 @@ alter_partition_cmd: n->def = (Node*)s; $$ = (Node *)n; } - | ADD_PARTITION name START '(' maxValueList ')' OptTableSpace + | ADD_PARTITION name START '(' maxValueList ')' opt_part_options { RangePartitionStartEndDefState *p = makeNode(RangePartitionStartEndDefState); AlterTableCmd *n = makeNode(AlterTableCmd); @@ -2979,7 +3008,7 @@ alter_partition_cmd: n->def = (Node*)s; $$ = (Node *)n; } - | ADD_PARTITION name VALUES '(' expr_list ')' OptTableSpace + | ADD_PARTITION name VALUES '(' expr_list ')' opt_part_options { ListPartitionDefState *p = makeNode(ListPartitionDefState); AlterTableCmd *n = makeNode(AlterTableCmd); @@ -2993,7 +3022,7 @@ alter_partition_cmd: n->def = (Node*)s; $$ = (Node *)n; } - | ADD_PARTITION name VALUES '(' DEFAULT ')' OptTableSpace + | ADD_PARTITION name VALUES '(' DEFAULT ')' opt_part_options { ListPartitionDefState *p = makeNode(ListPartitionDefState); AlterTableCmd *n = makeNode(AlterTableCmd); @@ -3011,7 +3040,7 @@ alter_partition_cmd: $$ = (Node *)n; } | ADD_PARTITION name VALUES LESS THAN - '(' maxValueList ')' OptTableSpace '(' subpartition_definition_list ')' + '(' maxValueList ')' opt_part_options '(' subpartition_definition_list ')' { RangePartitionDefState *p = makeNode(RangePartitionDefState); AlterTableCmd *n = makeNode(AlterTableCmd); @@ -3037,7 +3066,7 @@ alter_partition_cmd: n->def = (Node*)s; $$ = (Node *)n; } - | ADD_PARTITION name VALUES '(' expr_list ')' OptTableSpace '(' subpartition_definition_list ')' + | ADD_PARTITION name VALUES '(' expr_list ')' opt_part_options '(' subpartition_definition_list ')' { ListPartitionDefState *p = makeNode(ListPartitionDefState); AlterTableCmd *n = makeNode(AlterTableCmd); @@ -4008,6 +4037,16 @@ alter_table_cmd: $$ = (Node *)n; } /* PGXC_END */ +/* table comments start */ + | COMMENT opt_equal Sconst + { + BCompatibilityOptionSupportCheck(); + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_COMMENTS; + n->name = $3; + $$ = (Node *)n; + } +/* table comments end */ ; alter_column_default: @@ -4164,6 +4203,30 @@ column_option: } ; +opt_part_options: + OptTableSpace part_options { $$ = $1; } + | OptTableSpace { $$ = $1; } + ; +/* set null return for grammer comparitibility */ +part_options: + part_option + { + BCompatibilityOptionSupportCheck(); + $$ = NULL; + } + | part_options part_option + { + $$ = NULL; + } + ; +part_option: + COMMENT opt_equal Sconst + { + u_sess->parser_cxt.hasPartitionComment = true; + $$ = (Node*)NULL; + } + ; + reloption_list: reloption_elem { $$ = list_make1($1); } | reloption_list ',' reloption_elem { $$ = lappend($1, $3); } @@ -5423,7 +5486,7 @@ subpartition_definition_list: ; subpartition_item: - SUBPARTITION name VALUES '(' expr_list ')' OptTableSpace + SUBPARTITION name VALUES '(' expr_list ')' opt_part_options { ListPartitionDefState *n = makeNode(ListPartitionDefState); n->partitionName = $2; @@ -5432,7 +5495,7 @@ subpartition_item: $$ = (Node *)n; } - | SUBPARTITION name VALUES '(' DEFAULT ')' OptTableSpace + | SUBPARTITION name VALUES '(' DEFAULT ')' opt_part_options { ListPartitionDefState *n = makeNode(ListPartitionDefState); n->partitionName = $2; @@ -5443,7 +5506,7 @@ subpartition_item: n->tablespacename = $7; $$ = (Node *)n; } - | SUBPARTITION name OptTableSpace + | SUBPARTITION name opt_part_options { HashPartitionDefState *n = makeNode(HashPartitionDefState); n->partitionName = $2; @@ -5452,7 +5515,7 @@ subpartition_item: $$ = (Node*)n; } | SUBPARTITION name VALUES LESS THAN - '(' maxValueList ')' OptTableSpace + '(' maxValueList ')' opt_part_options { RangePartitionDefState *n = makeNode(RangePartitionDefState); n->partitionName = $2; @@ -5566,7 +5629,7 @@ range_less_than_list: ; list_partition_item: - PARTITION name VALUES '(' expr_list ')' OptTableSpace + PARTITION name VALUES '(' expr_list ')' opt_part_options { ListPartitionDefState *n = makeNode(ListPartitionDefState); n->partitionName = $2; @@ -5575,7 +5638,7 @@ list_partition_item: $$ = (Node *)n; } - | PARTITION name VALUES '(' DEFAULT ')' OptTableSpace + | PARTITION name VALUES '(' DEFAULT ')' opt_part_options { ListPartitionDefState *n = makeNode(ListPartitionDefState); n->partitionName = $2; @@ -5586,7 +5649,7 @@ list_partition_item: n->tablespacename = $7; $$ = (Node *)n; } - | PARTITION name VALUES '(' expr_list ')' OptTableSpace '(' subpartition_definition_list ')' + | PARTITION name VALUES '(' expr_list ')' opt_part_options '(' subpartition_definition_list ')' { ListPartitionDefState *n = makeNode(ListPartitionDefState); n->partitionName = $2; @@ -5606,7 +5669,7 @@ list_partition_item: } $$ = (Node *)n; } - | PARTITION name VALUES '(' DEFAULT ')' OptTableSpace '(' subpartition_definition_list ')' + | PARTITION name VALUES '(' DEFAULT ')' opt_part_options '(' subpartition_definition_list ')' { ListPartitionDefState *n = makeNode(ListPartitionDefState); n->partitionName = $2; @@ -5632,7 +5695,7 @@ list_partition_item: ; hash_partition_item: - PARTITION name OptTableSpace + PARTITION name opt_part_options { HashPartitionDefState *n = makeNode(HashPartitionDefState); n->partitionName = $2; @@ -5640,7 +5703,7 @@ hash_partition_item: $$ = (Node*)n; } - | PARTITION name OptTableSpace '(' subpartition_definition_list ')' + | PARTITION name opt_part_options '(' subpartition_definition_list ')' { HashPartitionDefState *n = makeNode(HashPartitionDefState); n->partitionName = $2; @@ -5663,7 +5726,7 @@ hash_partition_item: range_less_than_item: PARTITION name VALUES LESS THAN - '(' maxValueList ')' OptTableSpace + '(' maxValueList ')' opt_part_options { RangePartitionDefState *n = makeNode(RangePartitionDefState); n->partitionName = $2; @@ -5673,7 +5736,7 @@ range_less_than_item: $$ = (Node *)n; } | PARTITION name VALUES LESS THAN - '(' maxValueList ')' OptTableSpace '(' subpartition_definition_list ')' + '(' maxValueList ')' opt_part_options '(' subpartition_definition_list ')' { RangePartitionDefState *n = makeNode(RangePartitionDefState); n->partitionName = $2; @@ -5708,7 +5771,7 @@ range_start_end_list: ; range_start_end_item: - PARTITION name START '(' maxValueList ')' END_P '(' maxValueList ')' opt_range_every_list OptTableSpace + PARTITION name START '(' maxValueList ')' END_P '(' maxValueList ')' opt_range_every_list opt_part_options { RangePartitionStartEndDefState *n = makeNode(RangePartitionStartEndDefState); n->partitionName = $2; @@ -5719,7 +5782,7 @@ range_start_end_item: $$ = (Node *)n; } - | PARTITION name END_P '(' maxValueList ')' OptTableSpace + | PARTITION name END_P '(' maxValueList ')' opt_part_options { RangePartitionStartEndDefState *n = makeNode(RangePartitionStartEndDefState); n->partitionName = $2; @@ -5730,7 +5793,7 @@ range_start_end_item: $$ = (Node *)n; } - | PARTITION name START '(' maxValueList ')' OptTableSpace + | PARTITION name START '(' maxValueList ')' opt_part_options { RangePartitionStartEndDefState *n = makeNode(RangePartitionStartEndDefState); n->partitionName = $2; @@ -6520,15 +6583,21 @@ internal_data_body: { * - thomas 1997-12-03 */ TableConstraint: - CONSTRAINT name ConstraintElem + CONSTRAINT name ConstraintElem opt_index_options { Constraint *n = (Constraint *) $3; Assert(IsA(n, Constraint)); n->conname = $2; n->location = @1; + n->constraintOptions = $4; $$ = (Node *) n; } - | ConstraintElem { $$ = $1; } + | ConstraintElem opt_index_options + { + Constraint *n = (Constraint *) $1; + n->constraintOptions = $2; + $$ = (Node *) n; + } ; ConstraintElem: @@ -6813,7 +6882,7 @@ OnCommitOption: ON COMMIT DROP { $$ = ONCOMMIT_DROP; } | /*EMPTY*/ { $$ = ONCOMMIT_NOOP; } ; -OptTableSpace: TABLESPACE name { $$ = $2; } +OptTableSpace: TABLESPACE opt_equal name { $$ = $3; } | /*EMPTY*/ { $$ = NULL; } ; OptGPI: UPDATE GLOBAL INDEX { $$ = TRUE; } @@ -12045,15 +12114,15 @@ range_partition_index_list: range_partition_index_item: - PARTITION index_name OptTableSpace - { - RangePartitionindexDefState* def = makeNode(RangePartitionindexDefState); - def->name = $2; - def->tablespace = $3; - $$ = (Node*)def; + PARTITION index_name opt_part_options + { + RangePartitionindexDefState* def = makeNode(RangePartitionindexDefState); + def->name = $2; + def->tablespace = $3; + $$ = (Node*)def; - } - | PARTITION index_name OptTableSpace opt_subpartition_index_def + } + | PARTITION index_name opt_part_options opt_subpartition_index_def { RangePartitionindexDefState* def = makeNode(RangePartitionindexDefState); def->name = $2; @@ -12082,7 +12151,7 @@ range_subpartition_index_list: ; range_subpartition_index_item: - SUBPARTITION index_name OptTableSpace + SUBPARTITION index_name opt_part_options { RangePartitionindexDefState* def = makeNode(RangePartitionindexDefState); def->name = $2; @@ -13058,6 +13127,11 @@ common_func_opt_item: { $$ = makeDefElem("package", (Node *)makeInteger(true)); } + | COMMENT Sconst + { + BCompatibilityOptionSupportCheck(); + $$ = makeDefElem("comment", (Node *)makeString($2)); + } ; createfunc_opt_item: diff --git a/src/common/backend/parser/parse_utilcmd.cpp b/src/common/backend/parser/parse_utilcmd.cpp index e9f3c562c..f9753e14c 100644 --- a/src/common/backend/parser/parse_utilcmd.cpp +++ b/src/common/backend/parser/parse_utilcmd.cpp @@ -407,6 +407,20 @@ Oid *namespaceid, bool isFirstNode) if (stmt->ofTypename) transformOfType(&cxt, stmt->ofTypename); + ListCell *cell = NULL; + foreach (cell, stmt->tableOptions) { + void *pointer = lfirst(cell); + if (IsA(pointer, CommentStmt)) { + CommentStmt *commentStmt = (CommentStmt *)pointer; + commentStmt->objtype = OBJECT_TABLE; + commentStmt->objname = list_make1(makeString(cxt.relation->relname)); + if (cxt.relation->schemaname) { + commentStmt->objname = lcons(makeString(cxt.relation->schemaname), commentStmt->objname); + } + cxt.alist = lappend(cxt.alist, commentStmt); + break; + } + } /* * Run through each primary element in the table creation clause. Separate * column defs from constraints, and do preliminary analysis. @@ -1109,6 +1123,21 @@ static void transformColumnDefinition(CreateStmtContext* cxt, ColumnDef* column, cxt->alist = lappend(cxt->alist, stmt); } + + ListCell *columnOption = NULL; + foreach (columnOption, column->columnOptions) { + void *pointer = lfirst(columnOption); + if (IsA(pointer, CommentStmt)) { + CommentStmt *commentStmt = (CommentStmt *)pointer; + commentStmt->objtype = OBJECT_COLUMN; + commentStmt->objname = list_make2(makeString(cxt->relation->relname), makeString(column->colname)); + if (cxt->relation->schemaname) { + commentStmt->objname = lcons(makeString(cxt->relation->schemaname) , commentStmt->objname); + } + cxt->alist = lappend(cxt->alist, commentStmt); + break; + } + } } /* @@ -3362,7 +3391,8 @@ static IndexStmt* transformIndexConstraint(Constraint* constraint, CreateStmtCon index->indexParams = lappend(index->indexParams, iparam); } } - + /* unique/primary key constraint is considered an index */ + index->indexOptions = constraint->constraintOptions; /* Add included columns to index definition */ foreach (lc, constraint->including) { char* key = strVal(lfirst(lc)); diff --git a/src/gausskernel/optimizer/commands/functioncmds.cpp b/src/gausskernel/optimizer/commands/functioncmds.cpp index bfc4f6e7d..9dc0225a6 100644 --- a/src/gausskernel/optimizer/commands/functioncmds.cpp +++ b/src/gausskernel/optimizer/commands/functioncmds.cpp @@ -86,6 +86,8 @@ #include "storage/lmgr.h" #include "tcop/utility.h" #include "tsearch/ts_type.h" +#include "commands/comment.h" + typedef struct PendingLibraryDelete { char* filename; /* library file name. */ @@ -96,6 +98,23 @@ static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup, Oid newOwne static void checkAllowAlter(HeapTuple tup); static int2vector* GetDefaultArgPos(List* defargpos); +static void CreateFunctionComment(Oid funcOid, List* options, bool lock = false) +{ + ListCell *cell = NULL; + foreach (cell, options) { + DefElem* defElem = (DefElem*)lfirst(cell); + if (strcmp(defElem->defname, "comment") == 0) { + /* lock until transaction commit or rollback */ + if (lock) { + LockDatabaseObject(funcOid, ProcedureRelationId, 0, ShareUpdateExclusiveLock); + } + CreateComments(funcOid, ProcedureRelationId, 0, defGetString(defElem)); + break; + } + } + +} + /* * Examine the RETURNS clause of the CREATE FUNCTION statement * and return information about it as *prorettype_p and *returnsSet. @@ -630,11 +649,19 @@ static ArrayType* update_proconfig_value(ArrayType* a, const List* set_items) return a; } +static bool compute_b_attribute(DefElem* defel) +{ + if (strcmp(defel->defname, "comment") == 0) { + return true; + } + return false; +} + /* * Dissect the list of options assembled in gram.y into function * attributes. */ -static void compute_attributes_sql_style(const List* options, List** as, char** language, bool* windowfunc_p, +static List* compute_attributes_sql_style(const List* options, List** as, char** language, bool* windowfunc_p, char* volatility_p, bool* strict_p, bool* security_definer, bool* leakproof_p, ArrayType** proconfig, float4* procost, float4* prorows, bool* fenced, bool* shippable, bool* package) { @@ -652,7 +679,7 @@ static void compute_attributes_sql_style(const List* options, List** as, char** DefElem* fencedItem = NULL; DefElem* shippable_item = NULL; DefElem* package_item = NULL; - + List* bCompatibilities = NIL; foreach (option, options) { DefElem* defel = (DefElem*)lfirst(option); @@ -681,6 +708,9 @@ static void compute_attributes_sql_style(const List* options, List** as, char** &package_item)) { /* recognized common option */ continue; + } else if (compute_b_attribute(defel)) { + /* recognized b compatibility options */ + bCompatibilities = lcons(defel, bCompatibilities); } else ereport(ERROR, (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION), errmsg("option \"%s\" not recognized", defel->defname))); @@ -747,6 +777,7 @@ static void compute_attributes_sql_style(const List* options, List** as, char** *package = intVal(package_item->arg); } list_free(set_items); + return bCompatibilities; } /* ------------- @@ -1021,8 +1052,9 @@ void CreateFunction(CreateFunctionStmt* stmt, const char* queryString, Oid pkg_o shippable = false; /* override attributes from explicit list */ - compute_attributes_sql_style((const List*)stmt->options, &as_clause, &language, &isWindowFunc, &volatility, - &isStrict, &security, &isLeakProof, &proconfig, &procost, &prorows, &fenced, &shippable, &package); + List *functionOptions = compute_attributes_sql_style((const List *)stmt->options, &as_clause, &language, + &isWindowFunc, &volatility, &isStrict, &security, &isLeakProof, + &proconfig, &procost, &prorows, &fenced, &shippable, &package); /* Look up the language and validate permissions */ languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language)); @@ -1156,7 +1188,7 @@ void CreateFunction(CreateFunctionStmt* stmt, const char* queryString, Oid pkg_o * And now that we have all the parameters, and know we're permitted to do * so, go ahead and create the function. */ - ProcedureCreate(funcname, namespaceId, pkg_oid, stmt->isOraStyle, stmt->replace, + Oid procedureOid = ProcedureCreate(funcname, namespaceId, pkg_oid, stmt->isOraStyle, stmt->replace, returnsSet, prorettype, proowner, languageOid, languageValidator, prosrc_str, /* converted to text later */ probin_str, /* converted to text later */ @@ -1175,6 +1207,9 @@ void CreateFunction(CreateFunctionStmt* stmt, const char* queryString, Oid pkg_o proIsProcedure, stmt->inputHeaderSrc, stmt->isPrivate); + + CreateFunctionComment(procedureOid, functionOptions); + u_sess->plsql_cxt.procedure_start_line = 0; u_sess->plsql_cxt.procedure_first_line = 0; if (u_sess->plsql_cxt.debug_query_string != NULL && !OidIsValid(pkg_oid)) { @@ -1920,7 +1955,8 @@ void AlterFunction(AlterFunctionStmt* stmt) if (procForm->pronamespace == u_sess->catalog_cxt.myTempNamespace) ExecSetTempObjectIncluded(); - /* Examine requested actions. */ + /* Examine requested actions and add b compatibility options to alterOptions. */ + List* alterOptions = NIL; foreach (l, stmt->actions) { DefElem* defel = (DefElem*)lfirst(l); @@ -1934,9 +1970,15 @@ void AlterFunction(AlterFunctionStmt* stmt) &rows_item, &fencedItem, &shippable_item, - &package_item) == false) + &package_item)) { + continue; + } else if (compute_b_attribute(defel)) { + /* recognized b compatibility options */ + alterOptions = lcons(defel, alterOptions); + } else { ereport(ERROR, (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION), errmsg("option \"%s\" not recognized", defel->defname))); + } } if (volatility_item != NULL) @@ -2032,6 +2074,8 @@ void AlterFunction(AlterFunctionStmt* stmt) simple_heap_update(rel, &tup->t_self, tup); CatalogUpdateIndexes(rel, tup); + CreateFunctionComment(funcOid, alterOptions, true); + /* Recode time of alter funciton. */ if (OidIsValid(funcOid)) { UpdatePgObjectMtime(funcOid, OBJECT_TYPE_PROC); diff --git a/src/gausskernel/optimizer/commands/indexcmds.cpp b/src/gausskernel/optimizer/commands/indexcmds.cpp index 9b31df565..4305613eb 100755 --- a/src/gausskernel/optimizer/commands/indexcmds.cpp +++ b/src/gausskernel/optimizer/commands/indexcmds.cpp @@ -1438,6 +1438,18 @@ Oid DefineIndex(Oid relationId, IndexStmt* stmt, Oid indexRelationId, bool is_al &extra, false, indexsplitMethod); + + /* index options */ + List *indexOptions = stmt->indexOptions; + foreach (cell, indexOptions) { + void *pointer = lfirst(cell); + if (IsA(pointer, CommentStmt)) { + CommentStmt *commentStmt = (CommentStmt *)pointer; + CreateComments(indexRelationId, RelationRelationId, 0, commentStmt->comment); + break; + } + } + /* Add any requested comment */ if (stmt->idxcomment != NULL) CreateComments(indexRelationId, RelationRelationId, 0, stmt->idxcomment); diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index 4f2fc844c..ba1607bd6 100644 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -259,7 +259,8 @@ static const char* ORCSupportOption[] = {"orientation", "compression", "version" #define AT_PASS_MISC 9 /* other stuff */ #ifdef PGXC #define AT_PASS_DISTRIB 10 /* Redistribution pass */ -#define AT_NUM_PASSES 11 +#define AT_COMMENT 11 +#define AT_NUM_PASSES 12 #else #define AT_NUM_PASSES 10 #endif @@ -7617,6 +7618,9 @@ static void ATPrepCmd(List** wqueue, Relation rel, AlterTableCmd* cmd, bool recu /* No command-specific prep needed */ pass = AT_PASS_DISTRIB; break; + case AT_COMMENTS: + pass = AT_COMMENT; + break; #endif default: /* oops */ ereport(ERROR, @@ -7755,6 +7759,21 @@ static void ATRewriteCatalogs(List** wqueue, LOCKMODE lockmode) } } +static void ATCreateColumComments(Oid relOid, ColumnDef* columnDef) +{ + List *columnOptions = columnDef->columnOptions; + ListCell *ColumnOption = NULL; + foreach (ColumnOption, columnOptions) { + void *pointer = lfirst(ColumnOption); + if (IsA(pointer, CommentStmt)) { + CommentStmt *commentStmt = (CommentStmt *)pointer; + CreateComments(relOid, RelationRelationId, get_attnum(relOid, columnDef->colname), + commentStmt->comment); + break; + } + } +} + /* * ATExecCmd: dispatch a subcommand to appropriate execution routine */ @@ -8018,6 +8037,14 @@ static void ATExecCmd(List** wqueue, AlteredTableInfo* tab, Relation rel, AlterT AtExecUpdateSliceLike(rel, cmd->exchange_with_rel); break; #endif + case AT_COMMENTS: + /* Modify Column comment or table comment */ + if (cmd->def != NULL && IsA(cmd->def, ColumnDef)) { + ATCreateColumComments(rel->rd_id, (ColumnDef*)cmd->def); + } else { + CreateComments(rel->rd_id, RelationRelationId, 0, cmd->name); + } + break; default: /* oops */ ereport(ERROR, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), @@ -9749,6 +9776,10 @@ static void ATExecAddColumn(List** wqueue, AlteredTableInfo* tab, Relation rel, colDef->is_local = false; } + + /* column Options */ + ATCreateColumComments(myrelid, colDef); + foreach (child, children) { Oid childrelid = lfirst_oid(child); Relation childrel; diff --git a/src/gausskernel/process/tcop/postgres.cpp b/src/gausskernel/process/tcop/postgres.cpp index e20ad7589..22bbd0a3f 100755 --- a/src/gausskernel/process/tcop/postgres.cpp +++ b/src/gausskernel/process/tcop/postgres.cpp @@ -898,7 +898,9 @@ List* pg_parse_query(const char* query_string, List** query_string_locationlist, #endif } raw_parsetree_list = parser_hook(query_string, query_string_locationlist); - + if (u_sess->parser_cxt.hasPartitionComment) { + ereport(WARNING, (errmsg("comment is not allowed in partition/subpartition."))); + } PGSTAT_END_TIME_RECORD(PARSE_TIME); if (u_sess->attr.attr_common.log_parser_stats) diff --git a/src/gausskernel/process/tcop/utility.cpp b/src/gausskernel/process/tcop/utility.cpp index 5bc116a5f..fd8a545fb 100755 --- a/src/gausskernel/process/tcop/utility.cpp +++ b/src/gausskernel/process/tcop/utility.cpp @@ -196,8 +196,6 @@ static bool IsAllTempObjectsInVacuumStmt(Node* parsetree); static int64 getCopySequenceMaxval(const char *nspname, const char *relname, const char *colname); static int64 getCopySequenceCountval(const char *nspname, const char *relname); -void BCompatibilityCreateTableOptions(CreateStmt* stmt, Oid relOid); -static inline void RelOrIndexOrColumnCreateComment(List* list, Oid oid, char *columnName = NULL); /* the hash value of extension script */ #define POSTGIS_VERSION_NUM 2 @@ -2162,9 +2160,6 @@ void CreateCommand(CreateStmt *parse_tree, const char *query_string, ParamListIn AlterCStoreCreateTables(rel_oid, toast_options, (CreateStmt*)stmt); AlterDfsCreateTables(rel_oid, toast_options, (CreateStmt*)stmt); AlterCreateChainTables(rel_oid, toast_options, (CreateStmt *)stmt); - - BCompatibilityCreateTableOptions((CreateStmt*)stmt, rel_oid); - #ifdef ENABLE_MULTIPLE_NODES Datum reloptions = transformRelOptions( (Datum)0, ((CreateStmt*)stmt)->options, NULL, validnsps, true, false); @@ -4912,8 +4907,6 @@ void standard_ProcessUtility(Node* parse_tree, const char* query_string, ParamLi DefineDeltaUniqueIndex(rel_id, stmt, indexRelOid); } #endif - /* index options */ - RelOrIndexOrColumnCreateComment(((IndexStmt *)stmt)->indexOptions, indexRelOid); pgstat_report_waitstatus(oldStatus); #ifdef PGXC @@ -13419,41 +13412,4 @@ static int64 getCopySequenceMaxval(const char *nspname, const char *relname, con } SPI_finish(); return DatumGetInt64(attval); -} - - /** - * b stmt create index. Only the last one of comments takes effect. - * @param list table or index or column option - * @param oid oid of table or index - */ - static inline void RelOrIndexOrColumnCreateComment(List* list, Oid oid, char *columnName) -{ - ListCell *cell = NULL; - foreach (cell, list) { - void *pointer = lfirst(cell); - if (IsA(pointer, CommentStmt)) { - CommentStmt *commentStmt = (CommentStmt *)pointer; - CreateComments(oid, RelationRelationId, columnName == NULL ? 0 : get_attnum(oid, columnName), - commentStmt->comment); - return; - } - } -} - -/** - * B Compatibility Create Table Options - * @params: stmt createStmt - * @params: relOid oid of table created - */ -void BCompatibilityCreateTableOptions(CreateStmt *stmt, Oid relOid) -{ - /* table Options */ - RelOrIndexOrColumnCreateComment(stmt->tableOptions, relOid); - - /* column Options */ - ListCell *cell = NULL; - foreach (cell, stmt->tableElts) { - ColumnDef *columnDef = (ColumnDef *)lfirst(cell); - RelOrIndexOrColumnCreateComment(columnDef->columnOptions, relOid, columnDef->colname); - } } \ No newline at end of file diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index cde82ff7a..09ac2f532 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -419,6 +419,8 @@ typedef struct knl_u_parser_context { bool isCreateFuncOrProc; bool isTimeCapsule; + + bool hasPartitionComment; } knl_u_parser_context; typedef struct knl_u_trigger_context { diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index dcc246d18..4769705cf 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -824,7 +824,8 @@ typedef enum AlterTableType { AT_SplitSubPartition, /* this will be in a more natural position in 9.3: */ AT_ReAddConstraint, /* internal to commands/tablecmds.c */ - AT_AddIntoCBI + AT_AddIntoCBI, + AT_COMMENTS, } AlterTableType; typedef enum AlterTableStatProperty { /* Additional Property for AlterTableCmd */ @@ -1318,6 +1319,7 @@ typedef struct Constraint { bool skip_validation; /* skip validation of existing rows? */ bool initially_valid; /* mark the new constraint as valid? */ + List* constraintOptions; /* opt_index_options from gram.y */ /* * @hdfs * Field used for soft constraint, which works on HDFS foreign table. diff --git a/src/test/regress/expected/b_comments.out b/src/test/regress/expected/b_comments.out index d42dd65e2..9bf42b396 100644 --- a/src/test/regress/expected/b_comments.out +++ b/src/test/regress/expected/b_comments.out @@ -1,4 +1,4 @@ -/* unsupport */ +/* unsupported */ create schema b_comments; set search_path to 'b_comments'; create table test_row(a int not null comment 'test_row.a'); @@ -21,7 +21,36 @@ create index partition_test_index on partition_test (logdate) local partition sip3_index_local tablespace PG_DEFAULT ) comment 'partition_test_index'; ERROR: Comment is supported only in B compatible database. +create table test( id int comment 'test.id', uid int comment 'test.uid', checkid int comment 'test.checkid', primary key ( id ) comment 'pkey.id', unique ( uid ) comment 'ukey.uid', check(checkid > 0) comment 'check.checkid') comment 'test'; +ERROR: Comment is supported only in B compatible database. +create index test_id_index on test(id) comment 'test_id_index'; +ERROR: Comment is supported only in B compatible database. +create function test_function(a int) returns void as $$ begin end; $$ language plpgsql comment 'test_function'; +ERROR: Comment is supported only in B compatible database. +create procedure test_procedure(int,int) comment 'test_procedure' as begin select $1 + $2;end; +/ +ERROR: Comment is supported only in B compatible database. +create table test_alter(id int); +alter table test_alter comment 'test_alter'; +ERROR: Comment is supported only in B compatible database. +alter table test_alter add column id2 int comment 'test_alter.id2'; +ERROR: Comment is supported only in B compatible database. +alter table test_alter add constraint test_alter_id_check check (id > 0) comment 'test_alter.constraint'; +ERROR: Comment is supported only in B compatible database. +alter table test_alter add constraint primary_key unique(id) comment 'test_alter.primary_key'; +ERROR: Comment is supported only in B compatible database. +create function test_alter_function(a int) returns void as $$ begin end; $$ language plpgsql; +alter function test_alter_function(a int) comment 'test_alter_function'; +ERROR: Comment is supported only in B compatible database. +create procedure test_alter_procedure(int,int) as begin select $1 + $2;end; +/ +alter procedure test_alter_procedure(int,int) comment 'test_alter_procedure'; +ERROR: Comment is supported only in B compatible database. drop schema b_comments cascade; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table test_alter +drop cascades to function test_alter_function(integer) +drop cascades to function test_alter_procedure(integer,integer) create database b_comments dbcompatibility 'B'; \c b_comments create schema b_comments; @@ -48,6 +77,24 @@ create index partition_test_index on partition_test (logdate) local partition sip2_index_local tablespace PG_DEFAULT, partition sip3_index_local tablespace PG_DEFAULT ) comment 'partition_test_index'; +create table test_new( id int comment 'test_new.id', uid int comment 'test_new.uid', checkid int comment 'test_new.checkid', primary key ( id ) comment 'pkey.id', unique ( uid ) comment 'ukey.uid', check(checkid > 0) comment 'check.checkid') comment 'test_new'; +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_new_pkey" for table "test_new" +NOTICE: CREATE TABLE / UNIQUE will create implicit index "test_new_uid_key" for table "test_new" +create index test_id_index on test_new(id) comment 'test_new_id_index'; +create function test_function(a int) returns void as $$ begin end; $$ language plpgsql comment 'test_function'; +create procedure test_procedure(int,int) comment 'test_procedure' as begin select $1 + $2;end; +/ +create table test_alter(id int); +alter table test_alter comment 'test_alter'; +alter table test_alter add column id2 int comment 'test_alter.id2'; +alter table test_alter add constraint test_alter_id_check check (id > 0) comment 'test_alter.constraint'; +alter table test_alter add constraint primary_key unique(id) comment 'test_alter.primary_key'; +NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "primary_key" for table "test_alter" +create function test_alter_function(a int) returns void as $$ begin end; $$ language plpgsql; +alter function test_alter_function(a int) comment 'test_alter_function'; +create procedure test_alter_procedure(int,int) as begin select $1 + $2;end; +/ +alter procedure test_alter_procedure(int,int) comment 'test_alter_procedure'; /* result */ select description from pg_description @@ -55,27 +102,43 @@ where objoid in (select relfilenode from pg_class where relnamespace in (select oid from pg_catalog.pg_namespace where nspname = 'b_comments')) order by description; - description ----------------------- + description +------------------------ partition_test partition_test_index + pkey.id test + test_alter + test_alter.id2 + test_alter.primary_key test_column test_column.a test_column.b test_index + test_new + test_new.checkid + test_new.id + test_new_id_index + test_new.uid test_row test_row.a test_row.b test_row_index -(11 rows) + ukey.uid +(21 rows) drop schema b_comments cascade; -NOTICE: drop cascades to 4 other objects +NOTICE: drop cascades to 10 other objects DETAIL: drop cascades to table test_row drop cascades to table test_column drop cascades to table test drop cascades to table partition_test +drop cascades to table test_new +drop cascades to function test_function(integer) +drop cascades to function test_procedure(integer,integer) +drop cascades to table test_alter +drop cascades to function test_alter_function(integer) +drop cascades to function test_alter_procedure(integer,integer) reset search_path; \c postgres drop database b_comments; diff --git a/src/test/regress/sql/b_comments.sql b/src/test/regress/sql/b_comments.sql index 6323ff0d9..6634baa7c 100644 --- a/src/test/regress/sql/b_comments.sql +++ b/src/test/regress/sql/b_comments.sql @@ -1,4 +1,4 @@ -/* unsupport */ +/* unsupported */ create schema b_comments; set search_path to 'b_comments'; create table test_row(a int not null comment 'test_row.a'); @@ -16,6 +16,21 @@ create index partition_test_index on partition_test (logdate) local partition sip2_index_local tablespace PG_DEFAULT, partition sip3_index_local tablespace PG_DEFAULT ) comment 'partition_test_index'; +create table test( id int comment 'test.id', uid int comment 'test.uid', checkid int comment 'test.checkid', primary key ( id ) comment 'pkey.id', unique ( uid ) comment 'ukey.uid', check(checkid > 0) comment 'check.checkid') comment 'test'; +create index test_id_index on test(id) comment 'test_id_index'; +create function test_function(a int) returns void as $$ begin end; $$ language plpgsql comment 'test_function'; +create procedure test_procedure(int,int) comment 'test_procedure' as begin select $1 + $2;end; +/ +create table test_alter(id int); +alter table test_alter comment 'test_alter'; +alter table test_alter add column id2 int comment 'test_alter.id2'; +alter table test_alter add constraint test_alter_id_check check (id > 0) comment 'test_alter.constraint'; +alter table test_alter add constraint primary_key unique(id) comment 'test_alter.primary_key'; +create function test_alter_function(a int) returns void as $$ begin end; $$ language plpgsql; +alter function test_alter_function(a int) comment 'test_alter_function'; +create procedure test_alter_procedure(int,int) as begin select $1 + $2;end; +/ +alter procedure test_alter_procedure(int,int) comment 'test_alter_procedure'; drop schema b_comments cascade; @@ -48,7 +63,22 @@ create index partition_test_index on partition_test (logdate) local partition sip2_index_local tablespace PG_DEFAULT, partition sip3_index_local tablespace PG_DEFAULT ) comment 'partition_test_index'; +create table test_new( id int comment 'test_new.id', uid int comment 'test_new.uid', checkid int comment 'test_new.checkid', primary key ( id ) comment 'pkey.id', unique ( uid ) comment 'ukey.uid', check(checkid > 0) comment 'check.checkid') comment 'test_new'; +create index test_id_index on test_new(id) comment 'test_new_id_index'; +create function test_function(a int) returns void as $$ begin end; $$ language plpgsql comment 'test_function'; +create procedure test_procedure(int,int) comment 'test_procedure' as begin select $1 + $2;end; +/ +create table test_alter(id int); +alter table test_alter comment 'test_alter'; +alter table test_alter add column id2 int comment 'test_alter.id2'; +alter table test_alter add constraint test_alter_id_check check (id > 0) comment 'test_alter.constraint'; +alter table test_alter add constraint primary_key unique(id) comment 'test_alter.primary_key'; +create function test_alter_function(a int) returns void as $$ begin end; $$ language plpgsql; +alter function test_alter_function(a int) comment 'test_alter_function'; +create procedure test_alter_procedure(int,int) as begin select $1 + $2;end; +/ +alter procedure test_alter_procedure(int,int) comment 'test_alter_procedure'; /* result */ select description from pg_description