From b23a1a0aaffdaf13725055f15d24b67abe14f63c Mon Sep 17 00:00:00 2001 From: zhangwenchao <656540940@qq.com> Date: Mon, 20 May 2024 19:05:58 +0800 Subject: [PATCH 1/2] Implementation of tag. We implement tag in this commit. Tag can be attached to target database object, which maybe database, user, schema, table etc. Tag has allowed values, when we attach one tag to target object, we should specify this tag's value which must be in allowed values array, otherwise will error out. To use it, we will illustrate some example as following: CREATE TAG tag_example allowed_values '123', 'abc'; CREATE USER tag_user; ALTER USER tag_user TAG (tag_example = '123'); ALTER TAG tag_example ADD ALLOWED_VALUES 'def'; ALTER TAG tag_example DROP ALLOWED_VALUES 'abc'; Authored-by: Zhang Wenchao zwcpostgres@gmail.com --- src/backend/catalog/Makefile | 4 +- src/backend/catalog/aclchk.c | 34 + src/backend/catalog/catalog.c | 14 +- src/backend/catalog/dependency.c | 36 + src/backend/catalog/objectaddress.c | 146 ++ src/backend/catalog/oid_dispatch.c | 35 + src/backend/catalog/pg_shdepend.c | 30 + src/backend/catalog/system_views.sql | 61 + src/backend/commands/Makefile | 3 +- src/backend/commands/alter.c | 7 + src/backend/commands/comment.c | 1 + src/backend/commands/dbcommands.c | 55 +- src/backend/commands/event_trigger.c | 5 + src/backend/commands/exttablecmds.c | 1 + src/backend/commands/indexcmds.c | 13 + src/backend/commands/schemacmds.c | 78 + src/backend/commands/seclabel.c | 1 + src/backend/commands/sequence.c | 10 + src/backend/commands/tablecmds.c | 71 + src/backend/commands/tablespace.c | 39 + src/backend/commands/tag.c | 1086 +++++++++++++ src/backend/commands/user.c | 41 +- src/backend/commands/view.c | 12 + src/backend/nodes/copyfuncs.c | 94 ++ src/backend/nodes/equalfuncs.c | 84 + src/backend/nodes/outfast.c | 21 + src/backend/nodes/outfuncs.c | 32 + src/backend/nodes/outfuncs_common.c | 62 + src/backend/nodes/readfast.c | 47 + src/backend/nodes/readfuncs.c | 8 + src/backend/nodes/readfuncs_common.c | 60 + src/backend/parser/gram.y | 400 ++++- src/backend/postmaster/loginmonitor.c | 3 +- src/backend/tcop/utility.c | 104 ++ src/backend/utils/cache/syscache.c | 35 + src/bin/pg_dump/pg_dumpall.c | 63 + src/bin/psql/tab-complete.c | 28 +- src/include/catalog/dependency.h | 5 + src/include/catalog/oid_dispatch.h | 4 + src/include/catalog/pg_tag.h | 55 + src/include/catalog/pg_tag_description.h | 56 + src/include/commands/schemacmds.h | 1 + src/include/commands/tag.h | 29 + src/include/nodes/nodes.h | 5 + src/include/nodes/parsenodes.h | 70 +- src/include/parser/kwlist.h | 2 + src/include/tcop/cmdtaglist.h | 3 + src/include/utils/acl.h | 1 + src/include/utils/syscache.h | 3 + .../test_ddl_deparse/test_ddl_deparse.c | 6 + src/test/regress/expected/misc_sanity.out | 4 +- src/test/regress/expected/oidjoins.out | 4 + src/test/regress/expected/sanity_check.out | 2 + src/test/regress/input/tag.source | 626 ++++++++ .../regress/output/directory_table.source | 20 +- .../output/directory_table_optimizer.source | 20 +- src/test/regress/output/tag.source | 1424 +++++++++++++++++ src/test/regress/parallel_schedule | 3 + .../expected/misc_sanity.out | 4 +- .../singlenode_regress/expected/oidjoins.out | 4 + .../expected/sanity_check.out | 2 + src/test/singlenode_regress/input/tag.source | 626 ++++++++ src/test/singlenode_regress/output/tag.source | 1424 +++++++++++++++++ src/test/singlenode_regress/parallel_schedule | 3 + src/tools/pgindent/typedefs.list | 6 + 65 files changed, 7166 insertions(+), 70 deletions(-) create mode 100644 src/backend/commands/tag.c create mode 100644 src/include/catalog/pg_tag.h create mode 100644 src/include/catalog/pg_tag_description.h create mode 100644 src/include/commands/tag.h create mode 100644 src/test/regress/input/tag.source create mode 100644 src/test/regress/output/tag.source create mode 100644 src/test/singlenode_regress/input/tag.source create mode 100644 src/test/singlenode_regress/output/tag.source diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile index 4670b33372c..c2e4d421696 100644 --- a/src/backend/catalog/Makefile +++ b/src/backend/catalog/Makefile @@ -95,9 +95,9 @@ CATALOG_HEADERS := \ pg_sequence.h pg_publication.h pg_publication_rel.h pg_subscription.h \ pg_subscription_rel.h gp_partition_template.h pg_task.h pg_task_run_history.h \ pg_profile.h pg_password_history.h pg_directory_table.h gp_storage_server.h \ + gp_storage_user_mapping.h pg_tag.h pg_tag_description.h \ gp_matview_aux.h \ - gp_matview_tables.h \ - gp_storage_user_mapping.h + gp_matview_tables.h USE_INTERNAL_FTS_FOUND := $(if $(findstring USE_INTERNAL_FTS,$(CFLAGS)),true,false) diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index c579dbffc52..d6a496aaf82 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -58,6 +58,7 @@ #include "catalog/pg_statistic_ext.h" #include "catalog/pg_subscription.h" #include "catalog/pg_tablespace.h" +#include "catalog/pg_tag.h" #include "catalog/pg_transform.h" #include "catalog/pg_ts_config.h" #include "catalog/pg_ts_dict.h" @@ -3791,6 +3792,9 @@ aclcheck_error(AclResult aclerr, ObjectType objtype, case OBJECT_EXTPROTOCOL: msg = gettext_noop("permission denied for external protocol %s"); break; + case OBJECT_TAG: + msg = gettext_noop("permission denied for tag %s"); + break; /* these currently aren't used */ case OBJECT_ACCESS_METHOD: case OBJECT_AMOP: @@ -3902,6 +3906,9 @@ aclcheck_error(AclResult aclerr, ObjectType objtype, case OBJECT_TABLE: msg = gettext_noop("must be owner of table %s"); break; + case OBJECT_TAG: + msg = gettext_noop("must be owner of tag %s"); + break; case OBJECT_TYPE: msg = gettext_noop("must be owner of type %s"); break; @@ -5647,6 +5654,33 @@ pg_opfamily_ownercheck(Oid opf_oid, Oid roleid) return has_privs_of_role(roleid, ownerId); } +/* + * Ownership check for a tag (specified by OID). + */ +bool +pg_tag_ownercheck(Oid tag_oid, Oid roleid) +{ + HeapTuple tuple; + Oid ownerId; + + /* Superusers bypass all permission checking. */ + if (superuser_arg(roleid)) + return true; + + tuple = SearchSysCache1(TAGOID, ObjectIdGetDatum(tag_oid)); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tag with OID %u does not exist", + tag_oid))); + + ownerId = ((Form_pg_tag) GETSTRUCT(tuple))->tagowner; + + ReleaseSysCache(tuple); + + return has_privs_of_role(roleid, ownerId); +} + /* * Ownership check for a text search dictionary (specified by OID). */ diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index 53a246fc3e2..51d097d3d54 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -44,6 +44,8 @@ #include "catalog/pg_shseclabel.h" #include "catalog/pg_subscription.h" #include "catalog/pg_tablespace.h" +#include "catalog/pg_tag.h" +#include "catalog/pg_tag_description.h" #include "catalog/pg_task.h" #include "catalog/pg_task_run_history.h" #include "catalog/pg_type.h" @@ -447,7 +449,10 @@ IsSharedRelation(Oid relationId) relationId == StorageServerRelationId || relationId == ProfileRelationId || - relationId == PasswordHistoryRelationId) + relationId == PasswordHistoryRelationId || + + relationId == TagRelationId || + relationId == TagDescriptionRelationId) return true; /* These are their indexes */ @@ -501,7 +506,12 @@ IsSharedRelation(Oid relationId) relationId == ProfileOidIndexId || relationId == ProfileVerifyFunctionIndexId || relationId == PasswordHistoryRolePasswordIndexId || - relationId == PasswordHistoryRolePasswordsetatIndexId) + relationId == PasswordHistoryRolePasswordsetatIndexId || + relationId == TagNameIndexId || + relationId == TagOidIndexId || + relationId == TagDescriptionIndexId || + relationId == TagDescriptionTagidvalueIndexId || + relationId == TagDescriptionOidIndexId) { return true; } diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index ceb5d51ad62..3463ceef98e 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -58,6 +58,8 @@ #include "catalog/pg_statistic_ext.h" #include "catalog/pg_subscription.h" #include "catalog/pg_tablespace.h" +#include "catalog/pg_tag.h" +#include "catalog/pg_tag_description.h" #include "catalog/pg_task.h" #include "catalog/pg_transform.h" #include "catalog/pg_trigger.h" @@ -78,6 +80,7 @@ #include "commands/schemacmds.h" #include "commands/seclabel.h" #include "commands/sequence.h" +#include "commands/tag.h" #include "commands/taskcmds.h" #include "commands/trigger.h" #include "commands/typecmds.h" @@ -209,6 +212,8 @@ static const Oid object_classes[] = { DirectoryTableRelationId, /* OCLASS_DIRECTORY_TABLE */ StorageServerRelationId, /* OCLASS_STORAGE_SERVER */ StorageUserMappingRelationId, /* OCLASS_STORAGE_USER_MAPPING */ + TagRelationId, /* OCLASS_TAG */ + TagDescriptionRelationId, /* OCLASS_TAG_DESCRIPTION */ ExtprotocolRelationId, /* OCLASS_EXTPROTOCOL */ GpMatviewAuxId, /* OCLASS_MATVIEW_AUX */ TaskRelationId, /* OCLASS_TASK */ @@ -1474,6 +1479,13 @@ doDeletion(const ObjectAddress *object, int flags) Assert(object->objectSubId == 0); index_drop(object->objectId, concurrent, concurrent_lock_mode); + + /* + * Delete tag description. + */ + DeleteTagDescriptions(MyDatabaseId, + object->classId, + object->objectId); } else { @@ -1481,7 +1493,17 @@ doDeletion(const ObjectAddress *object, int flags) RemoveAttributeById(object->objectId, object->objectSubId); else + { heap_drop_with_catalog(object->objectId); + + /* + * Delete tag description. + */ + DeleteTagDescriptions(MyDatabaseId, + object->classId, + object->objectId); + } + } /* @@ -1551,6 +1573,12 @@ doDeletion(const ObjectAddress *object, int flags) case OCLASS_SCHEMA: RemoveSchemaById(object->objectId); + /* + * Delete tag description. + */ + DeleteTagDescriptions(MyDatabaseId, + object->classId, + object->objectId); break; case OCLASS_TASK: RemoveTaskById(object->objectId); @@ -1593,6 +1621,8 @@ doDeletion(const ObjectAddress *object, int flags) case OCLASS_PASSWORDHISTORY: case OCLASS_STORAGE_SERVER: case OCLASS_STORAGE_USER_MAPPING: + case OCLASS_TAG: + case OCLASS_TAG_DESCRIPTION: elog(ERROR, "global objects cannot be deleted by doDeletion"); break; @@ -2996,6 +3026,12 @@ getObjectClass(const ObjectAddress *object) case StorageUserMappingRelationId: return OCLASS_STORAGE_USER_MAPPING; + case TagRelationId: + return OCLASS_TAG; + + case TagDescriptionRelationId: + return OCLASS_TAG_DESCRIPTION; + default: { struct CustomObjectClass *coc; diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 0989cecc72a..8f0ba5ebf90 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -61,6 +61,8 @@ #include "catalog/pg_statistic_ext.h" #include "catalog/pg_subscription.h" #include "catalog/pg_tablespace.h" +#include "catalog/pg_tag.h" +#include "catalog/pg_tag_description.h" #include "catalog/pg_task.h" #include "catalog/pg_transform.h" #include "catalog/pg_trigger.h" @@ -80,6 +82,7 @@ #include "commands/resgroupcmds.h" #include "commands/storagecmds.h" #include "commands/tablespace.h" +#include "commands/tag.h" #include "commands/trigger.h" #include "foreign/foreign.h" #include "funcapi.h" @@ -701,6 +704,21 @@ static const ObjectPropertyType ObjectProperty[] = Anum_pg_extprotocol_ptcacl, OBJECT_EXTPROTOCOL, true + }, + + { + "tag", + TagRelationId, + TagOidIndexId, + TAGOID, + TAGNAME, + Anum_pg_tag_oid, + Anum_pg_tag_tagname, + InvalidAttrNumber, + Anum_pg_tag_tagowner, + InvalidAttrNumber, + OBJECT_TAG, + true } }; @@ -942,6 +960,10 @@ static const struct object_type_map /* OCLASS_STORAGE_USER_MAPPING */ { "storage user mapping", OBJECT_STORAGE_USER_MAPPING + }, + /* OCLASS_TAG */ + { + "tag", OBJECT_TAG } }; @@ -1104,6 +1126,7 @@ get_object_address(ObjectType objtype, Node *object, case OBJECT_DATABASE: case OBJECT_EXTENSION: case OBJECT_TABLESPACE: + case OBJECT_TAG: case OBJECT_ROLE: case OBJECT_SCHEMA: case OBJECT_LANGUAGE: @@ -1383,6 +1406,11 @@ get_object_address_unqualified(ObjectType objtype, address.objectId = get_tablespace_oid(name, missing_ok); address.objectSubId = 0; break; + case OBJECT_TAG: + address.classId = TagRelationId; + address.objectId = get_tag_oid(name, missing_ok); + address.objectSubId = 0; + break; case OBJECT_ROLE: address.classId = AuthIdRelationId; address.objectId = get_role_oid(name, missing_ok); @@ -2425,6 +2453,7 @@ pg_get_object_address(PG_FUNCTION_ARGS) case OBJECT_SCHEMA: case OBJECT_SUBSCRIPTION: case OBJECT_TABLESPACE: + case OBJECT_TAG: case OBJECT_EXTPROTOCOL: case OBJECT_RESGROUP: case OBJECT_RESQUEUE: @@ -2686,6 +2715,11 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, aclcheck_error(ACLCHECK_NOT_OWNER, objtype, strVal((Value *) object)); break; + case OBJECT_TAG: + if (!pg_tag_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, objtype, + strVal((Value *) object)); + break; case OBJECT_TSDICTIONARY: if (!pg_ts_dict_ownercheck(address.objectId, roleid)) aclcheck_error(ACLCHECK_NOT_OWNER, objtype, @@ -4197,6 +4231,55 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) break; } + case OCLASS_TAG: + { + char *tagname = TagGetNameByOid(object->objectId, missing_ok); + + if (tagname) + appendStringInfo(&buffer, _("tag %s"), tagname); + break; + } + + case OCLASS_TAG_DESCRIPTION: + { + Relation tag_desc_rel; + ScanKeyData skey; + SysScanDesc tag_desc_scan; + HeapTuple tag_tuple; + HeapTuple tag_desc_tuple; + Form_pg_tag form_tag; + Form_pg_tag_description form_tag_desc; + char *tagname; + + ScanKeyInit(&skey, Anum_pg_tag_description_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); + + tag_desc_rel = table_open(TagDescriptionRelationId, AccessShareLock); + tag_desc_scan = systable_beginscan(tag_desc_rel, TagDescriptionOidIndexId, true, + NULL, 1, &skey); + + tag_desc_tuple = systable_getnext(tag_desc_scan); + if (!HeapTupleIsValid(tag_desc_tuple)) + elog(ERROR, "lookup failed for tag description %u", object->objectId); + + form_tag_desc = (Form_pg_tag_description) GETSTRUCT(tag_desc_tuple); + + tag_tuple = SearchSysCache1(TAGOID, ObjectIdGetDatum(form_tag_desc->tagid)); + if (!HeapTupleIsValid(tag_tuple)) + elog(ERROR, "cache lookup failed for tag %u", form_tag_desc->tagid); + + form_tag = (Form_pg_tag) GETSTRUCT(tag_tuple); + tagname = pstrdup(form_tag->tagname.data); + + appendStringInfo(&buffer, _("tag description with tag %s"), tagname); + + ReleaseSysCache(tag_tuple); + systable_endscan(tag_desc_scan); + table_close(tag_desc_rel, AccessShareLock); + break; + } + default: { struct CustomObjectClass *coc; @@ -4796,6 +4879,14 @@ getObjectTypeDescription(const ObjectAddress *object, bool missing_ok) appendStringInfoString(&buffer, "storage user mapping"); break; + case OCLASS_TAG: + appendStringInfoString(&buffer, "tag"); + break; + + case OCLASS_TAG_DESCRIPTION: + appendStringInfoString(&buffer, "tag description"); + break; + default: { struct CustomObjectClass *coc; @@ -6207,6 +6298,61 @@ getObjectIdentityParts(const ObjectAddress *object, case OCLASS_MATVIEW_AUX: break; + case OCLASS_TAG: + { + char *tagname; + + tagname = TagGetNameByOid(object->objectId, missing_ok); + if (!tagname) + break; + if (objname) + *objname = list_make1(tagname); + appendStringInfoString(&buffer, + quote_identifier(tagname)); + break; + } + + case OCLASS_TAG_DESCRIPTION: + { + Relation tag_desc_rel; + ScanKeyData skey; + SysScanDesc tag_desc_scan; + HeapTuple tag_tuple; + HeapTuple tag_desc_tuple; + Form_pg_tag form_tag; + Form_pg_tag_description form_tag_desc; + char *tagname; + + ScanKeyInit(&skey, Anum_pg_tag_description_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); + + tag_desc_rel = table_open(TagDescriptionRelationId, AccessShareLock); + tag_desc_scan = systable_beginscan(tag_desc_rel, TagDescriptionOidIndexId, true, + NULL, 1, &skey); + + tag_desc_tuple = systable_getnext(tag_desc_scan); + if (!HeapTupleIsValid(tag_desc_tuple)) + elog(ERROR, "lookup failed for tag description %u", object->objectId); + + form_tag_desc = (Form_pg_tag_description) GETSTRUCT(tag_desc_tuple); + + tag_tuple = SearchSysCache1(TAGOID, ObjectIdGetDatum(form_tag_desc->tagid)); + if (!HeapTupleIsValid(tag_tuple)) + elog(ERROR, "cache lookup failed for tag %u", form_tag_desc->tagid); + + form_tag = (Form_pg_tag) GETSTRUCT(tag_tuple); + tagname = pstrdup(form_tag->tagname.data); + + appendStringInfo(&buffer, _("tag description with tag %s"), + quote_identifier(tagname)); + + ReleaseSysCache(tag_tuple); + systable_endscan(tag_desc_scan); + table_close(tag_desc_rel, AccessShareLock); + break; + } + default: { struct CustomObjectClass *coc; diff --git a/src/backend/catalog/oid_dispatch.c b/src/backend/catalog/oid_dispatch.c index 01c95a4644a..51a2b83bfe1 100644 --- a/src/backend/catalog/oid_dispatch.c +++ b/src/backend/catalog/oid_dispatch.c @@ -119,6 +119,8 @@ #include "catalog/pg_statistic_ext.h" #include "catalog/pg_subscription.h" #include "catalog/pg_tablespace.h" +#include "catalog/pg_tag.h" +#include "catalog/pg_tag_description.h" #include "catalog/pg_transform.h" #include "catalog/pg_trigger.h" #include "catalog/pg_ts_config.h" @@ -957,6 +959,39 @@ GetNewOidForResQueue(Relation relation, Oid indexId, AttrNumber oidcolumn, return GetNewOrPreassignedOid(relation, indexId, oidcolumn, &key); } +Oid +GetNewOidForTag(Relation relation, Oid indexId, AttrNumber oidcolumn, + char *tagname) +{ + OidAssignment key; + + Assert(RelationGetRelid(relation) == TagRelationId); + Assert(indexId == TagOidIndexId); + Assert(oidcolumn == Anum_pg_tag_oid); + + memset(&key, 0, sizeof(OidAssignment)); + key.type = T_OidAssignment; + key.objname = tagname; + return GetNewOrPreassignedOid(relation, indexId, oidcolumn, &key); +} + +Oid +GetNewOidForTagDescription(Relation relation, Oid indexId, AttrNumber oidcolumn, + char *objectname, Oid tagId) +{ + OidAssignment key; + + Assert(RelationGetRelid(relation) == TagDescriptionRelationId); + Assert(indexId == TagDescriptionOidIndexId); + Assert(oidcolumn == Anum_pg_tag_description_oid); + + memset(&key, 0, sizeof(OidAssignment)); + key.type = T_OidAssignment; + key.objname = objectname; + key.keyOid1 = tagId; + return GetNewOrPreassignedOid(relation, indexId, oidcolumn, &key); +} + Oid GetNewOidForRewrite(Relation relation, Oid indexId, AttrNumber oidcolumn, Oid ev_class, char *rulename) diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c index 9c101a9fdb0..46f1fc8898a 100644 --- a/src/backend/catalog/pg_shdepend.c +++ b/src/backend/catalog/pg_shdepend.c @@ -46,6 +46,7 @@ #include "catalog/pg_statistic_ext.h" #include "catalog/pg_subscription.h" #include "catalog/pg_tablespace.h" +#include "catalog/pg_tag.h" #include "catalog/pg_ts_config.h" #include "catalog/pg_ts_dict.h" #include "catalog/pg_type.h" @@ -1243,6 +1244,15 @@ shdepLockAndCheckObject(Oid classId, Oid objectId) break; } + case TagRelationId: + { + if (!SearchSysCacheExists1(TAGOID, ObjectIdGetDatum(objectId))) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tag %u was concurrently dropped", + objectId))); + break; + } default: elog(ERROR, "unrecognized shared classId: %u", classId); @@ -1299,6 +1309,8 @@ storeObjectDescription(StringInfo descs, appendStringInfo(descs, _("profile of %s"), objdesc); else if (deptype == SHARED_DEPENDENCY_STORAGE_SERVER) appendStringInfo(descs, _("storage server of %s"), objdesc); + else if (deptype == SHARED_DEPENDENCY_TAG) + appendStringInfo(descs, _("tag of %s"), objdesc); else elog(ERROR, "unrecognized dependency type: %d", (int) deptype); @@ -1785,4 +1797,22 @@ recordStorageServerDependency(Oid classId, Oid objectId, Oid srvId) ObjectAddressSet(referenced, StorageServerRelationId, srvId); recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_STORAGE_SERVER); +} + +/* + * recordTagDependency + * + * A convenient wrapper of recoredSharedDependencyOn -- register the specified + * tag description of attached to tag. + */ +void +recordTagDependency(Oid classId, Oid objectId, Oid tagId) +{ + ObjectAddress myself, + referenced; + + ObjectAddressSet(myself, classId, objectId); + ObjectAddressSet(referenced, TagRelationId, tagId); + + recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_TAG); } \ No newline at end of file diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 37c72f6101f..c330eb0ffd7 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -1763,3 +1763,64 @@ CREATE VIEW gp_suboverflowed_backend(segid, pids) AS SELECT -1, gp_get_suboverflowed_backends() UNION ALL SELECT gp_segment_id, gp_get_suboverflowed_backends() FROM gp_dist_random('gp_id') order by 1; + +CREATE VIEW database_tag_descriptions AS + SELECT + tddatabaseid, + datname, + tagname, + tagvalue + FROM pg_tag_description AS td, + pg_database AS d, + pg_tag AS t + WHERE td.tagid = t.oid and td.tdobjid = d.oid; + +CREATE VIEW user_tag_descriptions AS + SELECT + tddatabaseid, + rolname, + tagname, + tagvalue + FROM pg_tag_description AS td, + pg_authid AS a, + pg_tag AS t + WHERE td.tagid = t.oid and td.tdobjid = a.oid; + +CREATE VIEW tablespace_tag_descriptions AS + SELECT + tddatabaseid, + spcname, + tagname, + tagvalue + FROM pg_tag_description AS td, + pg_tablespace AS ts, + pg_tag AS t + WHERE td.tagid = t.oid and td.tdobjid = ts.oid; + +CREATE VIEW schema_tag_descriptions AS + SELECT + datname, + nspname, + tagname, + tagvalue + FROM pg_tag_description AS td, + pg_namespace AS ns, + pg_database AS d, + pg_tag AS t + WHERE td.tagid = t.oid AND td.tdobjid = ns.oid AND td.tddatabaseid = d.oid; + +CREATE VIEW relation_tag_descriptions AS + SELECT + datname, + relname, + ns.nspname AS relnamespace, + relkind, + tagname, + tagvalue + FROM pg_tag_description AS td, + pg_class AS c, + pg_database AS d, + pg_tag AS t, + pg_namespace AS ns + WHERE td.tagid = t.oid AND td.tdobjid = c.oid + AND td.tddatabaseid = d.oid AND ns.oid = c.relnamespace; diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile index 2fe51b415ba..4ae28e323d4 100644 --- a/src/backend/commands/Makefile +++ b/src/backend/commands/Makefile @@ -66,7 +66,8 @@ OBJS = \ variable.o \ view.o \ pg_profile.o \ - storagecmds.o + storagecmds.o \ + tag.o OBJS += analyzefuncs.o analyzeutils.o extprotocolcmds.o exttablecmds.o queue.o OBJS += resgroupcmds.o tablecmds_gp.o vacuum_ao.o taskcmds.o diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index ea774dbe8a1..d5d08869e65 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -58,6 +58,7 @@ #include "commands/subscriptioncmds.h" #include "commands/tablecmds.h" #include "commands/tablespace.h" +#include "commands/tag.h" #include "commands/trigger.h" #include "commands/typecmds.h" #include "commands/user.h" @@ -359,6 +360,9 @@ ExecRenameStmt_internal(RenameStmt *stmt) case OBJECT_TABLESPACE: return RenameTableSpace(stmt->subname, stmt->newname); + case OBJECT_TAG: + return RenameTag(stmt->subname, stmt->newname); + case OBJECT_TABLE: case OBJECT_SEQUENCE: case OBJECT_VIEW: @@ -737,6 +741,8 @@ AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid, case OCLASS_MATVIEW_AUX: case OCLASS_STORAGE_SERVER: case OCLASS_STORAGE_USER_MAPPING: + case OCLASS_TAG: + case OCLASS_TAG_DESCRIPTION: /* ignore object types that don't have schema-qualified names */ break; @@ -965,6 +971,7 @@ ExecAlterOwnerStmt_internal(AlterOwnerStmt *stmt) case OBJECT_ROUTINE: case OBJECT_STATISTIC_EXT: case OBJECT_TABLESPACE: + case OBJECT_TAG: case OBJECT_TSDICTIONARY: case OBJECT_TSCONFIGURATION: { diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 906405718e2..d654a6cf25a 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -133,6 +133,7 @@ CommentObject(CommentStmt *stmt) case OBJECT_RESQUEUE: case OBJECT_RESGROUP: case OBJECT_PROFILE: + case OBJECT_TAG: CreateSharedComments(address.objectId, address.classId, stmt->comment); break; default: diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 52cef311ba3..d1146d3d4ec 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -54,6 +54,7 @@ #include "commands/defrem.h" #include "commands/seclabel.h" #include "commands/tablespace.h" +#include "commands/tag.h" #include "mb/pg_wchar.h" #include "miscadmin.h" #include "pgstat.h" @@ -620,6 +621,20 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) new_record, new_record_nulls); CatalogTupleInsert(pg_database_rel, tuple); + + CommandCounterIncrement(); + + /* + * Create tag description. + */ + if (stmt->tags) + { + AddTagDescriptions(stmt->tags, + InvalidOid, + DatabaseRelationId, + dboid, + dbname); + } if (shouldDispatch) { @@ -1067,6 +1082,13 @@ dropdb(const char *dbname, bool missing_ok, bool force) */ DeleteSharedComments(db_id, DatabaseRelationId); DeleteSharedSecurityLabel(db_id, DatabaseRelationId); + + /* + * Delete any tag description and associated dependencies. + */ + DeleteTagDescriptions(InvalidOid, + DatabaseRelationId, + db_id); /* * Remove settings associated with this database @@ -1808,7 +1830,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), new_record, new_record_nulls, new_record_repl); CatalogTupleUpdate(rel, &tuple->t_self, newtuple); - + InvokeObjectPostAlterHook(DatabaseRelationId, dboid, 0); systable_endscan(scan); @@ -1823,6 +1845,37 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) /* Close pg_database, but keep lock till commit */ table_close(rel, NoLock); + if (stmt->tags) + { + if (!stmt->unsettag) + { + AlterTagDescriptions(stmt->tags, + InvalidOid, + DatabaseRelationId, + dboid, + stmt->dbname); + } + + if (stmt->unsettag) + { + UnsetTagDescriptions(stmt->tags, + InvalidOid, + DatabaseRelationId, + dboid, + stmt->dbname); + } + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_CANCEL_ON_ERROR| + DF_WITH_SNAPSHOT| + DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + } + if (Gp_role == GP_ROLE_DISPATCH) { char *cmd; diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index e821e00bab0..a8062b2e587 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -1003,6 +1003,7 @@ EventTriggerSupportsObjectType(ObjectType obtype) return true; case OBJECT_RESQUEUE: case OBJECT_RESGROUP: + case OBJECT_TAG: return false; /* @@ -1031,6 +1032,8 @@ EventTriggerSupportsObjectClass(ObjectClass objclass) case OCLASS_MATVIEW_AUX: case OCLASS_STORAGE_SERVER: case OCLASS_STORAGE_USER_MAPPING: + case OCLASS_TAG: + case OCLASS_TAG_DESCRIPTION: /* no support for global objects */ return false; case OCLASS_EVENT_TRIGGER: @@ -2168,6 +2171,7 @@ stringify_grant_objtype(ObjectType objtype) case OBJECT_STATISTIC_EXT: case OBJECT_SUBSCRIPTION: case OBJECT_TABCONSTRAINT: + case OBJECT_TAG: case OBJECT_TRANSFORM: case OBJECT_TRIGGER: case OBJECT_TSCONFIGURATION: @@ -2258,6 +2262,7 @@ stringify_adefprivs_objtype(ObjectType objtype) case OBJECT_STATISTIC_EXT: case OBJECT_SUBSCRIPTION: case OBJECT_TABCONSTRAINT: + case OBJECT_TAG: case OBJECT_TRANSFORM: case OBJECT_TRIGGER: case OBJECT_TSCONFIGURATION: diff --git a/src/backend/commands/exttablecmds.c b/src/backend/commands/exttablecmds.c index af3a20db3a9..4acfc778fc8 100644 --- a/src/backend/commands/exttablecmds.c +++ b/src/backend/commands/exttablecmds.c @@ -118,6 +118,7 @@ DefineExternalRelation(CreateExternalStmt *createExtStmt) createStmt->tablespacename = NULL; createStmt->distributedBy = createExtStmt->distributedBy; /* policy was set in transform */ createStmt->ownerid = userid; + createStmt->tags = createExtStmt->tags; switch (exttypeDesc->exttabletype) { diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 48140959209..6cdbc4888b3 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -45,6 +45,7 @@ #include "commands/progress.h" #include "commands/tablecmds.h" #include "commands/tablespace.h" +#include "commands/tag.h" #include "mb/pg_wchar.h" #include "miscadmin.h" #include "nodes/makefuncs.h" @@ -1571,6 +1572,18 @@ DefineIndex(Oid relationId, return address; } + /* + * Create tag description. + */ + if (stmt->tags) + { + AddTagDescriptions(stmt->tags, + MyDatabaseId, + address.classId, + address.objectId, + stmt->idxname); + } + /* * In the QD, remember the chosen index name and stash it with the * chosen OIDs, so that it's dispatched to the QE later. diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 17a10fca906..a179bac9520 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -28,9 +28,11 @@ #include "catalog/oid_dispatch.h" #include "catalog/pg_authid.h" #include "catalog/pg_namespace.h" +#include "catalog/pg_tag.h" #include "commands/dbcommands.h" #include "commands/event_trigger.h" #include "commands/schemacmds.h" +#include "commands/tag.h" #include "miscadmin.h" #include "parser/parse_utilcmd.h" #include "tcop/utility.h" @@ -170,6 +172,18 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString, { namespaceId = NamespaceCreate(schemaName, owner_uid, false); + /* + * Create tag description. + */ + if (stmt->tags) + { + AddTagDescriptions(stmt->tags, + MyDatabaseId, + NamespaceRelationId, + namespaceId, + stmt->schemaname); + } + if (shouldDispatch) { elog(DEBUG5, "shouldDispatch = true, namespaceOid = %d", namespaceId); @@ -198,6 +212,18 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString, else { namespaceId = NamespaceCreate(schemaName, owner_uid, false); + + /* + * Create tag description. + */ + if (stmt->tags) + { + AddTagDescriptions(stmt->tags, + MyDatabaseId, + NamespaceRelationId, + namespaceId, + stmt->schemaname); + } } /* @@ -307,6 +333,58 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString, return namespaceId; } +/* + * Alter Schema tag + * + * Alter a schema to change it's tag. + */ +void +AlterSchemaCommand(AlterSchemaStmt *stmt) +{ + Oid namespaceId; + HeapTuple tuple; + Form_pg_namespace namespaceform; + + tuple = SearchSysCache1(NAMESPACENAME, CStringGetDatum(stmt->schemaname)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for namespace %s", stmt->schemaname); + + namespaceform = (Form_pg_namespace) GETSTRUCT(tuple); + namespaceId = namespaceform->oid; + + if (stmt->tags) + { + if (!stmt->unsettag) + { + AlterTagDescriptions(stmt->tags, + MyDatabaseId, + NamespaceRelationId, + namespaceId, + stmt->schemaname); + } + + if (stmt->unsettag) + { + UnsetTagDescriptions(stmt->tags, + MyDatabaseId, + NamespaceRelationId, + namespaceId, + stmt->schemaname); + } + } + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_CANCEL_ON_ERROR | + DF_WITH_SNAPSHOT | + DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + ReleaseSysCache(tuple); +} + /* * Guts of schema deletion. */ diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c index a0dd92b2e04..df2727d5df0 100644 --- a/src/backend/commands/seclabel.c +++ b/src/backend/commands/seclabel.c @@ -85,6 +85,7 @@ SecLabelSupportsObjectType(ObjectType objtype) case OBJECT_RULE: case OBJECT_STATISTIC_EXT: case OBJECT_TABCONSTRAINT: + case OBJECT_TAG: case OBJECT_TRANSFORM: case OBJECT_TRIGGER: case OBJECT_TSCONFIGURATION: diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 7033d6da4d5..825988bdb8b 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -37,6 +37,7 @@ #include "commands/defrem.h" #include "commands/sequence.h" #include "commands/tablecmds.h" +#include "commands/tag.h" #include "funcapi.h" #include "libpq/libpq.h" #include "libpq/pqformat.h" @@ -265,6 +266,15 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq) /* now initialize the sequence's data */ tuple = heap_form_tuple(tupDesc, value, null); fill_seq_with_data(rel, tuple); + + if (seq->tags) + { + AddTagDescriptions(seq->tags, + MyDatabaseId, + address.classId, + address.objectId, + seq->sequence->relname); + } /* Dispatch to segments */ if (shouldDispatch) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 19414729f1d..39df631e9c8 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -73,6 +73,7 @@ #include "commands/sequence.h" #include "commands/tablecmds.h" #include "commands/tablespace.h" +#include "commands/tag.h" #include "commands/trigger.h" #include "commands/typecmds.h" #include "commands/user.h" @@ -268,6 +269,7 @@ struct DropRelationCallbackState #define ATT_FOREIGN_TABLE 0x0020 #define ATT_PARTITIONED_INDEX 0x0040 #define ATT_DIRECTORY_TABLE 0x0080 +#define ATT_SEQUENCE 0x0100 /* * ForeignTruncateInfo @@ -570,6 +572,8 @@ static List *GetParentedForeignKeyRefs(Relation partition); static void ATDetachCheckNoForeignKeyRefs(Relation partition); static char GetAttributeCompression(Oid atttypid, char *compression); +static void ATSetTags(Relation rel, List *tags, bool unset); + static RangeVar *make_temp_table_name(Relation rel, BackendId id); static bool prebuild_temp_table(Relation rel, RangeVar *tmpname, DistributedBy *distro, char *amname, List *opts, @@ -1163,6 +1167,20 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, typaddress, valid_opts); + /* + * Create tag description. + */ + if (stmt->tags && + stmt->relation->relpersistence != RELPERSISTENCE_TEMP) + { + + AddTagDescriptions(stmt->tags, + MyDatabaseId, + RelationRelationId, + relationId, + relname); + } + /* * We must bump the command counter to make the newly-created relation * tuple visible for opening. @@ -5001,6 +5019,11 @@ AlterTableGetLockLevel(List *cmds) cmd_lockmode = AccessExclusiveLock; break; + case AT_SetTags: + case AT_UnsetTags: + cmd_lockmode = ShareUpdateExclusiveLock; + break; + default: /* oops */ elog(ERROR, "unrecognized alter table type: %d", (int) cmd->subtype); @@ -5670,6 +5693,12 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, /* No command-specific prep needed */ pass = AT_PASS_MISC; break; + case AT_SetTags: + case AT_UnsetTags: + ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE | ATT_INDEX | ATT_SEQUENCE | ATT_VIEW | ATT_MATVIEW); + /* No command-specific prep needed */ + pass = AT_PASS_MISC; + break; default: /* oops */ elog(ERROR, "unrecognized alter table type: %d", (int) cmd->subtype); @@ -6114,6 +6143,12 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, case AT_DetachPartitionFinalize: ATExecDetachPartitionFinalize(rel, ((PartitionCmd *) cmd->def)->name); break; + case AT_SetTags: + ATSetTags(rel, cmd->tags, cmd->unsettag); + break; + case AT_UnsetTags: + ATSetTags(rel, cmd->tags, cmd->unsettag); + break; default: /* oops */ elog(ERROR, "unrecognized alter table type: %d", (int) cmd->subtype); @@ -7506,6 +7541,9 @@ ATSimplePermissions(Relation rel, int allowed_targets) case RELKIND_DIRECTORY_TABLE: actual_target = ATT_DIRECTORY_TABLE; break; + case RELKIND_SEQUENCE: + actual_target = ATT_SEQUENCE; + break; case RELKIND_AOSEGMENTS: case RELKIND_AOBLOCKDIR: @@ -7608,6 +7646,9 @@ ATWrongRelkindError(Relation rel, int allowed_targets) case ATT_DIRECTORY_TABLE: msg = _("\"%s\" is not a directory table"); break; + case ATT_TABLE | ATT_FOREIGN_TABLE | ATT_INDEX | ATT_SEQUENCE | ATT_VIEW | ATT_MATVIEW: + msg = _("\"%s\" is not a table, foreign table, index, sequence, view or materialized view"); + break; default: /* shouldn't get here, add all necessary cases above */ msg = _("\"%s\" is of the wrong type"); @@ -14156,6 +14197,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, case OCLASS_MATVIEW_AUX: case OCLASS_STORAGE_SERVER: case OCLASS_STORAGE_USER_MAPPING: + case OCLASS_TAG: + case OCLASS_TAG_DESCRIPTION: /* * We don't expect any of these sorts of objects to depend on @@ -22705,3 +22748,31 @@ GetAttributeCompression(Oid atttypid, char *compression) return cmethod; } + +static void +ATSetTags(Relation rel, List *tags, bool unset) +{ + Oid relid; + + relid = RelationGetRelid(rel); + + if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP) + return; + + if (!unset) + { + AlterTagDescriptions(tags, + MyDatabaseId, + RelationRelationId, + relid, + RelationGetRelationName(rel)); + } + else + { + UnsetTagDescriptions(tags, + MyDatabaseId, + RelationRelationId, + relid, + RelationGetRelationName(rel)); + } +} diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index e5c53e7180b..e9d26b0511b 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -81,6 +81,7 @@ #include "commands/seclabel.h" #include "commands/tablecmds.h" #include "commands/tablespace.h" +#include "commands/tag.h" #include "common/file_perm.h" #include "miscadmin.h" #include "parser/parse_func.h" @@ -461,6 +462,16 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) heap_freetuple(tuple); + /* + * Create tag description. + */ + if (stmt->tags) + AddTagDescriptions(stmt->tags, + InvalidOid, + TableSpaceRelationId, + tablespaceoid, + stmt->tablespacename); + /* Record dependency on owner */ recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId); @@ -715,6 +726,13 @@ DropTableSpace(DropTableSpaceStmt *stmt) table_endscan(scandesc); + /* + * Delete any tag description and associated dependencies. + */ + DeleteTagDescriptions(InvalidOid, + TableSpaceRelationId, + tablespaceoid); + /* * Remove any comments or security labels on this tablespace. */ @@ -1512,6 +1530,27 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) table_endscan(scandesc); table_close(rel, NoLock); + if (stmt->tags) + { + if (!stmt->unsettag) + { + AlterTagDescriptions(stmt->tags, + InvalidOid, + TableSpaceRelationId, + tablespaceoid, + stmt->tablespacename); + } + + if (stmt->unsettag) + { + UnsetTagDescriptions(stmt->tags, + InvalidOid, + TableSpaceRelationId, + tablespaceoid, + stmt->tablespacename); + } + } + if (Gp_role == GP_ROLE_DISPATCH && ENABLE_DISPATCH()) { CdbDispatchUtilityStatement((Node *) stmt, diff --git a/src/backend/commands/tag.c b/src/backend/commands/tag.c new file mode 100644 index 00000000000..5e46984b5d4 --- /dev/null +++ b/src/backend/commands/tag.c @@ -0,0 +1,1086 @@ +/*------------------------------------------------------------------------- + * + * tag.c + * Commands to manipulate tag + * + * Tags in Cloudberry database are designed to make tag for a given database + * object. + * + * + * Portions Copyright (c) 2024 Hashdata Inc + * + * + * IDENTIFICATION + * src/backend/commands/tag.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/genam.h" +#include "access/relscan.h" +#include "access/skey.h" +#include "access/table.h" +#include "access/xact.h" +#include "catalog/catalog.h" +#include "catalog/dependency.h" +#include "catalog/heap.h" +#include "catalog/indexing.h" +#include "catalog/objectaccess.h" +#include "catalog/oid_dispatch.h" +#include "catalog/pg_tag.h" +#include "catalog/pg_tag_description.h" +#include "catalog/pg_type.h" +#include "cdb/cdbdisp_query.h" +#include "cdb/cdbvars.h" +#include "commands/defrem.h" +#include "commands/tag.h" +#include "storage/lmgr.h" +#include "utils/acl.h" +#include "utils/array.h" +#include "utils/builtins.h" +#include "utils/rel.h" +#include "utils/relcache.h" +#include "utils/syscache.h" + +#define TAG_VALUES_ACTION_ADD 1 +#define TAG_VALUES_ACTION_DROP -1 + +#define MAX_TAG_NUMBER 50 + +static Datum transformTagValues(int action, Oid tagId, Datum oldvalues, List *allowed_values, bool unset); +static List *untransformTagValues(Datum allowed_values); +static Datum valueListToArray(List *allowed_values); +static void checkDropTagValue(Oid tagId, char *tagvalue); + +/* + * get_tag_oid - given a tag name, look up the OID + * + * If missing_ok is false, throw an error if tag name not found. If + * true, just return InvalidOid. + */ +Oid +get_tag_oid(const char *tagname, bool missing_ok) +{ + Oid oid; + + /* + * Search pg_tag syscache with name to get oid. + */ + oid = GetSysCacheOid1(TAGNAME, Anum_pg_tag_oid, CStringGetDatum(tagname)); + if (!OidIsValid(oid) && !missing_ok) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tag \"%s\" does not exist", tagname))); + + return oid; +} + +/* + * Create a tag + * + * We will record the create user as tag's owner, which is allowed to + * alter or drop this tag. + */ +Oid +CreateTag(CreateTagStmt *stmt) +{ + Relation rel; + Datum values[Natts_pg_tag]; + bool nulls[Natts_pg_tag]; + HeapTuple tuple; + Oid tagId; + Oid ownerId; + Datum tag_values; + + rel = table_open(TagRelationId, RowExclusiveLock); + + /* For now the owner cannot be specified on create. Use effective user ID. */ + ownerId = GetUserId(); + + tuple = SearchSysCache1(TAGNAME, CStringGetDatum(stmt->tag_name)); + if (HeapTupleIsValid(tuple)) + { + if (stmt->missing_ok) + { + ereport(NOTICE, + errmsg("tag \"%s\" already exists, skipping", + stmt->tag_name)); + ReleaseSysCache(tuple); + table_close(rel, RowExclusiveLock); + + return InvalidOid; + } + else + { + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("tag \"%s\" already exists", stmt->tag_name))); + } + } + + /* + * Insert tuple into pg_tag. + */ + memset(values, 0, sizeof(values)); + memset(nulls, false, sizeof(nulls)); + + tagId = GetNewOidForTag(rel, TagOidIndexId, + Anum_pg_tag_oid, + stmt->tag_name); + values[Anum_pg_tag_oid - 1] = ObjectIdGetDatum(tagId); + values[Anum_pg_tag_tagname - 1] = + DirectFunctionCall1(namein, CStringGetDatum(stmt->tag_name)); + values[Anum_pg_tag_tagowner - 1] = + ObjectIdGetDatum(ownerId); + + tag_values = transformTagValues(TAG_VALUES_ACTION_ADD, + tagId, + PointerGetDatum(NULL), + stmt->allowed_values, + false); + + if (PointerIsValid(DatumGetPointer(tag_values))) + values[Anum_pg_tag_allowed_values - 1] = tag_values; + else + nulls[Anum_pg_tag_allowed_values - 1] = true; + + tuple = heap_form_tuple(rel->rd_att, values, nulls); + + CatalogTupleInsert(rel, tuple); + + heap_freetuple(tuple); + + /* Post creation hook for new tag */ + InvokeObjectPostCreateHook(TagRelationId, tagId, 0); + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_WITH_SNAPSHOT | DF_CANCEL_ON_ERROR | DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + + table_close(rel, RowExclusiveLock); + + return tagId; +} + +/* + * Alter a tag + * + * We can alter a tag to add, drop or unset allowed_values. + */ +ObjectAddress +AlterTag(AlterTagStmt *stmt) +{ + Relation rel; + HeapTuple tuple; + Datum repl_val[Natts_pg_tag]; + bool repl_null[Natts_pg_tag]; + bool repl_repl[Natts_pg_tag]; + Oid tagId; + Datum datum = 0; + bool isnull; + Form_pg_tag tagform; + ObjectAddress address = {0}; + + rel = table_open(TagRelationId, RowExclusiveLock); + + tuple = SearchSysCacheCopy1(TAGNAME, CStringGetDatum(stmt->tag_name)); + if (!HeapTupleIsValid(tuple)) + { + if (stmt->missing_ok) + { + ereport(NOTICE, + errmsg("tag \"%s\" does not exist, skipping", + stmt->tag_name)); + table_close(rel, RowExclusiveLock); + + return InvalidObjectAddress; + } + else + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tag \"%s\" does not exist", + stmt->tag_name))); + } + } + + tagform = (Form_pg_tag) GETSTRUCT(tuple); + tagId = tagform->oid; + + /* + * Only owner or a superuser can ALTER a TAG. + */ + if (!pg_tag_ownercheck(tagId, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TAG, + stmt->tag_name); + + memset(repl_val, 0, sizeof(repl_val)); + memset(repl_null, false, sizeof(repl_null)); + memset(repl_repl, false, sizeof(repl_repl)); + + if (stmt->tag_values) + { + /* Extract the current allowed_values */ + datum = SysCacheGetAttr(TAGOID, + tuple, + Anum_pg_tag_allowed_values, + &isnull); + + if (isnull) + datum = PointerGetDatum(NULL); + + /* Prepare the values array */ + datum = transformTagValues(stmt->action, + tagId, + datum, + stmt->tag_values, + stmt->unset); + } + + if (PointerIsValid(DatumGetPointer(datum))) + repl_val[Anum_pg_tag_allowed_values - 1] = datum; + else + repl_null[Anum_pg_tag_allowed_values - 1] = true; + + repl_repl[Anum_pg_tag_allowed_values - 1] = true; + + /* Everything looks good - update the tuple */ + tuple = heap_modify_tuple(tuple, RelationGetDescr(rel), + repl_val, repl_null, repl_repl); + + CatalogTupleUpdate(rel, &tuple->t_self, tuple); + + InvokeObjectPostAlterHook(TagRelationId, tagId, 0); + + ObjectAddressSet(address, TagRelationId, tagId); + + heap_freetuple(tuple); + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_WITH_SNAPSHOT | DF_CANCEL_ON_ERROR | DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + + table_close(rel, RowExclusiveLock); + + return address; +} + +/* + * Drop a tag + */ +void +DropTag(DropTagStmt *stmt) +{ + Relation rel; + Oid curserid; + ListCell *cell; + + curserid = GetUserId(); + + rel = table_open(TagRelationId, RowExclusiveLock); + + foreach(cell, stmt->tags) + { + HeapTuple tuple; + Form_pg_tag tagform; + char *detail; + char *detail_log; + Oid tagId; + char *tagname; + + /* + * Check that if the tag exists. Do nothing if IF NOT + * EXISTS was enforced. + */ + tagname = strVal(lfirst(cell)); + tuple = SearchSysCache1(TAGNAME, PointerGetDatum(tagname)); + if (!HeapTupleIsValid(tuple)) + { + if (!stmt->missing_ok) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tag \"%s\" does not exist", tagname))); + } + if (Gp_role != GP_ROLE_EXECUTE) + { + ereport(NOTICE, + (errmsg("tag \"%s\" does not exist, skipping", tagname))); + } + + continue; + } + + tagform = (Form_pg_tag) GETSTRUCT(tuple); + tagId = tagform->oid; + + /* check permission on tag */ + if (!pg_tag_ownercheck(tagId, GetUserId())) + aclcheck_error_type(ACLCHECK_NOT_OWNER, tagId); + + /* DROP hook for the tag being removed */ + InvokeObjectDropHook(TagRelationId, tagId, 0); + + /* + * Lock the tag, so nobody can add dependencies to it while we drop + * it. We keep the lock until the end of transaction. + */ + LockSharedObject(TagRelationId, tagId, 0, AccessExclusiveLock); + + /* Check for pg_shdepend entries depending on this tag */ + if (checkSharedDependencies(TagRelationId, tagId, + &detail, &detail_log)) + ereport(ERROR, + (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), + errmsg("tag \"%s\" cannot be dropped because some objects depend on it", + tagname), + errdetail_internal("%s", detail), + errdetail_log("%s", detail_log))); + + /* + * Delete the tag from the pg_tag table + */ + CatalogTupleDelete(rel, &tuple->t_self); + + ReleaseSysCache(tuple); + + /* metadata track */ + if (Gp_role == GP_ROLE_DISPATCH) + MetaTrackDropObject(TagRelationId, tagId); + } + + /* + * Now we can clean up; but keep locks until commit. + */ + table_close(rel, NoLock); + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_CANCEL_ON_ERROR| + DF_WITH_SNAPSHOT| + DF_NEED_TWO_PHASE, + NIL, + NULL); + } +} + +/* + * Execute ALTER TAG RENAME + */ +ObjectAddress +RenameTag(const char *oldname, const char *newname) +{ + Oid tagId; + Relation rel; + HeapTuple tuple; + HeapTuple newtuple; + Form_pg_tag tagform; + ObjectAddress address; + + /* + * Look up the target tag's OID, and get exclusive lock on it. We + * need this for this same reasons as DROP TAG. + */ + rel = table_open(TagRelationId, RowExclusiveLock); + + newtuple = SearchSysCacheCopy1(TAGNAME, CStringGetDatum(oldname)); + if (!HeapTupleIsValid(newtuple)) + elog(ERROR, "cache lookup failed for tag %s", oldname); + + tagform = (Form_pg_tag) GETSTRUCT(newtuple); + tagId = tagform->oid; + + /* check permission on tag */ + if (!pg_tag_ownercheck(tagId, GetUserId())) + aclcheck_error_type(ACLCHECK_NOT_OWNER, tagId); + + tuple = SearchSysCache1(TAGNAME, CStringGetDatum(newname)); + if (HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("tag \"%s\" already exists", + newname))); + + /* OK, update the entry */ + namestrcpy(&(tagform->tagname), newname); + + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + + /* MPP-6929: metadata tracking */ + if (Gp_role == GP_ROLE_DISPATCH) + MetaTrackUpdObject(TagRelationId, + tagId, + GetUserId(), + "ALTER", "RENAME"); + + InvokeObjectPostAlterHook(TagRelationId, tagId, 0); + + ObjectAddressSet(address, TagRelationId, tagId); + + heap_freetuple(newtuple); + table_close(rel, RowExclusiveLock); + + return address; +} + +/* + * Add tag for object + * + * Add tag for database object such as database, warehouse, table etc. + */ +void +AddTagDescriptions(List *tags, + Oid databaseid, + Oid classid, + Oid objid, + char *objname) +{ + Relation tag_rel; + Relation tag_desc_rel; + ListCell *cell; + ScanKeyData skey[3]; + SysScanDesc scan; + HeapTuple tuple_to_count; + int tags_counter = 0; + + tag_rel = table_open(TagRelationId, RowExclusiveLock); + tag_desc_rel = table_open(TagDescriptionRelationId, RowExclusiveLock); + + foreach(cell, tags) + { + Oid tag_desc_oid; + DefElem *def; + HeapTuple tuple; + HeapTuple desc_tuple; + HeapTuple new_tuple; + Form_pg_tag tagform; + Oid tagId; + char *tagname; + char *tagvalue; + Datum datum; + bool isnull; + List *allowed_values; + ListCell *value_cell; + + def = lfirst(cell); + tagname = def->defname; + tagvalue = defGetString(def); + + tuple = SearchSysCache1(TAGNAME, CStringGetDatum(tagname)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for tag %s", tagname); + + tagform = (Form_pg_tag) GETSTRUCT(tuple); + tagId = tagform->oid; + + /* Extract the current tag's allowed_values */ + datum = SysCacheGetAttr(TAGNAME, + tuple, + Anum_pg_tag_allowed_values, + &isnull); + + if (isnull) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tag value \"%s\" does not exist in tag \"%s\"", + tagvalue, tagname))); + + allowed_values = untransformTagValues(datum); + + foreach(value_cell, allowed_values) + { + char *allowed_value = strVal(lfirst(value_cell)); + + if (strcmp(tagvalue, allowed_value) == 0) + { + break; + } + } + + if (value_cell) + { + desc_tuple = SearchSysCache4(TAGDESCRIPTION, + ObjectIdGetDatum(databaseid), + ObjectIdGetDatum(classid), + ObjectIdGetDatum(objid), + ObjectIdGetDatum(tagId)); + + if (!HeapTupleIsValid(desc_tuple)) + { + Datum tag_desc_values[Natts_pg_tag_description]; + bool tag_desc_nulls[Natts_pg_tag_description]; + + /* + * Insert tuple into pg_tag_description and record dependency. + */ + memset(tag_desc_values, 0, sizeof(tag_desc_values)); + memset(tag_desc_nulls, false, sizeof(tag_desc_nulls)); + + tag_desc_oid = GetNewOidForTagDescription(tag_desc_rel, + TagDescriptionOidIndexId, + Anum_pg_tag_description_oid, + objname, + tagId); + tag_desc_values[Anum_pg_tag_description_oid - 1] = ObjectIdGetDatum(tag_desc_oid); + tag_desc_values[Anum_pg_tag_description_tddatabaseid - 1] = ObjectIdGetDatum(databaseid); + tag_desc_values[Anum_pg_tag_description_tdclassid - 1] = ObjectIdGetDatum(classid); + tag_desc_values[Anum_pg_tag_description_tdobjid - 1] = ObjectIdGetDatum(objid); + tag_desc_values[Anum_pg_tag_description_tagid - 1] = ObjectIdGetDatum(tagId); + + datum = CStringGetTextDatum(tagvalue); + tag_desc_values[Anum_pg_tag_description_tagvalue - 1] = datum; + + new_tuple = heap_form_tuple(tag_desc_rel->rd_att, tag_desc_values, tag_desc_nulls); + + CatalogTupleInsert(tag_desc_rel, new_tuple); + + heap_freetuple(new_tuple); + + /* Record tag dependency */ + recordTagDependency(TagDescriptionRelationId, tag_desc_oid, tagId); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("tag \"%s\" value has been added for object \"%s\".", + tagname, objname))); + } + } + else + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tag value \"%s\" is not in tag \"%s\" allowed values", + tagvalue, tagname))); + } + + ReleaseSysCache(tuple); + + CommandCounterIncrement(); + } + + /* + * Scan the pg_tag_description to check whether the object has been added 50 tags. + */ + ScanKeyInit(&skey[0], + Anum_pg_tag_description_tddatabaseid, + BTEqualStrategyNumber, F_OIDEQ, + Int32GetDatum(databaseid)); + ScanKeyInit(&skey[1], + Anum_pg_tag_description_tdclassid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(classid)); + ScanKeyInit(&skey[2], + Anum_pg_tag_description_tdobjid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(objid)); + + scan = systable_beginscan(tag_desc_rel, TagDescriptionIndexId, true, + NULL, 3, skey); + + while ((tuple_to_count = systable_getnext(scan)) != NULL) + tags_counter += 1; + + if (tags_counter > MAX_TAG_NUMBER) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("Object \"%s\" added tags have exceeded the max number %d", + objname, MAX_TAG_NUMBER))); + + systable_endscan(scan); + + table_close(tag_desc_rel, RowExclusiveLock); + table_close(tag_rel, NoLock); + + return; +} + +/* + * Alter tag for object + * + * Alter tag for database object such as database, warehouse, table etc. + */ +void +AlterTagDescriptions(List *tags, + Oid databaseid, + Oid classid, + Oid objid, + char *objname) +{ + Relation tag_rel; + Relation tag_desc_rel; + ListCell *cell; + + tag_rel = table_open(TagRelationId, RowExclusiveLock); + tag_desc_rel = table_open(TagDescriptionRelationId, RowExclusiveLock); + + foreach(cell, tags) + { + HeapTuple tuple; + HeapTuple desc_tuple; + HeapTuple new_tuple; + Form_pg_tag tagform; + Oid tagId; + char *tagname = NULL; + char *tagvalue = NULL; + Datum datum; + bool isnull; + List *allowed_values; + ListCell *value_cell; + + DefElem *def = lfirst(cell); + tagname = def->defname; + tagvalue = defGetString(def); + + tuple = SearchSysCache1(TAGNAME, CStringGetDatum(tagname)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for tag %s", tagname); + + /* Extract the current tag's allowed_values */ + datum = SysCacheGetAttr(TAGNAME, + tuple, + Anum_pg_tag_allowed_values, + &isnull); + + if (isnull) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tag value \"%s\" does not exist in tag \"%s\"", + tagvalue, tagname))); + + allowed_values = untransformTagValues(datum); + + foreach(value_cell, allowed_values) + { + char *allowed_value = strVal(lfirst(value_cell)); + + if (strcmp(tagvalue, allowed_value) == 0) + { + break; + } + } + + if (!value_cell) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tag value \"%s\" is not in tag \"%s\" allowed values", + tagvalue, tagname))); + } + + tagform = (Form_pg_tag) GETSTRUCT(tuple); + tagId = tagform->oid; + + desc_tuple = SearchSysCache4(TAGDESCRIPTION, + ObjectIdGetDatum(databaseid), + ObjectIdGetDatum(classid), + ObjectIdGetDatum(objid), + ObjectIdGetDatum(tagId)); + + if (!HeapTupleIsValid(desc_tuple)) + { + if (Gp_role == GP_ROLE_DISPATCH || IS_SINGLENODE()) + ereport(WARNING, + errmsg("object \"%s\" does not have tag \"%s\", creating", + objname, tagname)); + + AddTagDescriptions(list_make1(def), + databaseid, classid, + objid, objname); + } + else + { + Datum tag_desc_repl_val[Natts_pg_tag_description]; + bool tag_desc_repl_null[Natts_pg_tag_description]; + bool tag_desc_repl_repl[Natts_pg_tag_description]; + + /* + * Update existing tuple in pg_tag_description + */ + memset(tag_desc_repl_val, 0, sizeof(tag_desc_repl_val)); + memset(tag_desc_repl_null, false, sizeof(tag_desc_repl_null)); + memset(tag_desc_repl_repl, false, sizeof(tag_desc_repl_repl)); + + datum = CStringGetTextDatum(tagvalue); + tag_desc_repl_val[Anum_pg_tag_description_tagvalue - 1] = datum; + + tag_desc_repl_repl[Anum_pg_tag_description_tagvalue - 1] = true; + + /* Everything looks good - update the tuple */ + new_tuple = heap_modify_tuple(desc_tuple, RelationGetDescr(tag_desc_rel), + tag_desc_repl_val, tag_desc_repl_null, tag_desc_repl_repl); + + CatalogTupleUpdate(tag_desc_rel, &new_tuple->t_self, new_tuple); + + heap_freetuple(new_tuple); + + ReleaseSysCache(desc_tuple); + } + + ReleaseSysCache(tuple); + + CommandCounterIncrement(); + } + + table_close(tag_desc_rel, RowExclusiveLock); + table_close(tag_rel, NoLock); + + return; +} + + +/* + * Unset tags for object + * + * Unset tag description value for object. + */ +void +UnsetTagDescriptions(List *tags, + Oid databaseid, + Oid classid, + Oid objid, + char *objname) +{ + Relation tag_rel; + Relation tag_desc_rel; + ListCell *cell; + + tag_rel = table_open(TagRelationId, RowExclusiveLock); + tag_desc_rel = table_open(TagDescriptionRelationId, RowExclusiveLock); + + foreach(cell, tags) + { + HeapTuple tuple; + HeapTuple desc_tuple; + HeapTuple new_tuple; + Form_pg_tag tagform; + Oid tagId; + char *tagname = NULL; + Datum tag_desc_repl_val[Natts_pg_tag_description]; + bool tag_desc_repl_null[Natts_pg_tag_description]; + bool tag_desc_repl_repl[Natts_pg_tag_description]; + + tagname = strVal(lfirst(cell)); + + tuple = SearchSysCache1(TAGNAME, CStringGetDatum(tagname)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for tag %s", tagname); + + tagform = (Form_pg_tag) GETSTRUCT(tuple); + tagId = tagform->oid; + + desc_tuple = SearchSysCache4(TAGDESCRIPTION, + ObjectIdGetDatum(databaseid), + ObjectIdGetDatum(classid), + ObjectIdGetDatum(objid), + ObjectIdGetDatum(tagId)); + + if (!HeapTupleIsValid(desc_tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("object \"%s\" does not have tag \"%s\"", + objname, tagname))); + + /* + * Unset existing tag value in pg_tag_description + */ + memset(tag_desc_repl_val, 0, sizeof(tag_desc_repl_val)); + memset(tag_desc_repl_null, false, sizeof(tag_desc_repl_null)); + memset(tag_desc_repl_repl, false, sizeof(tag_desc_repl_repl)); + + tag_desc_repl_null[Anum_pg_tag_description_tagvalue - 1] = true; + tag_desc_repl_repl[Anum_pg_tag_description_tagvalue - 1] = true; + + /* Everything looks good - update the tuple */ + new_tuple = heap_modify_tuple(desc_tuple, RelationGetDescr(tag_desc_rel), + tag_desc_repl_val, tag_desc_repl_null, tag_desc_repl_repl); + + CatalogTupleUpdate(tag_desc_rel, &new_tuple->t_self, new_tuple); + + heap_freetuple(new_tuple); + + ReleaseSysCache(desc_tuple); + ReleaseSysCache(tuple); + + CommandCounterIncrement(); + } + + table_close(tag_desc_rel, RowExclusiveLock); + table_close(tag_rel, NoLock); + + return; +} + +/* + * Remove tag for object + * + * Remove tag for database object such as database, warehouse, table etc. + */ +void +DeleteTagDescriptions(Oid databaseid, + Oid classid, + Oid objid) +{ + Oid tagdescId; + HeapTuple desc_tuple; + Relation rel; + ScanKeyData skey[3]; + SysScanDesc scan; + Form_pg_tag tagform; + + ScanKeyInit(&skey[0], + Anum_pg_tag_description_tddatabaseid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(databaseid)); + ScanKeyInit(&skey[1], + Anum_pg_tag_description_tdclassid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(classid)); + ScanKeyInit(&skey[2], + Anum_pg_tag_description_tdobjid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(objid)); + + rel = table_open(TagDescriptionRelationId, RowExclusiveLock); + + scan = systable_beginscan(rel, TagDescriptionIndexId, true, + NULL, 3, skey); + + while ((desc_tuple = systable_getnext(scan)) != NULL) + { + tagform = (Form_pg_tag) GETSTRUCT(desc_tuple); + tagdescId = tagform->oid; + + CatalogTupleDelete(rel, &desc_tuple->t_self); + + /* + * Delete shared dependency references related to this tag description object. + */ + deleteSharedDependencyRecordsFor(TagDescriptionRelationId, tagdescId, 0); + } + + systable_endscan(scan); + + /* Hold lock until transaction commit */ + table_close(rel, NoLock); +} + + +/* + * Transform tag values to datum. + */ +static Datum +transformTagValues(int action, Oid tagId, Datum oldvalues, + List *allowed_values, bool unset) +{ + List *resultValues = untransformTagValues(oldvalues); + ListCell *value_cell; + Datum result; + + Assert(!(resultValues && unset)); + + foreach(value_cell, allowed_values) + { + char *value = strVal(lfirst(value_cell)); + ListCell *cell; + + foreach(cell, resultValues) + { + char *oldvalue = strVal(lfirst(cell)); + + if (strcmp(value, oldvalue) == 0 || unset) + break; + } + + if (action > 0) + { + if (cell) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("allowed value \"%s\" has been added", + strVal(lfirst(value_cell))))); + + /* Max allowed value length is 256. */ + if (strlen(value) > 256) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("added allowed value \"%s\" has exceeded max 256 length", + strVal(lfirst(value_cell))))); + + resultValues = lappend(resultValues, lfirst(value_cell)); + } + else + { + if (!cell) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("allowed value \"%s\" not found", + strVal(lfirst(value_cell))))); + + checkDropTagValue(tagId, strVal(lfirst(cell))); + + resultValues = list_delete_cell(resultValues, cell); + } + } + + /* Max allowed_values number is 300. */ + if (list_length(resultValues) > 300) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("Allowed_values only allow 300 values."))); + + result = valueListToArray(resultValues); + + return result; +} + +/* + * Untranform tag values from datum to list. + */ +static List * +untransformTagValues(Datum allowed_values) +{ + List *result = NIL; + ArrayType *array; + Datum *valuedatums; + int nvalues; + int i; + + /* Nothing to do if no allowed_values */ + if (!PointerIsValid(DatumGetPointer(allowed_values))) + return result; + + array = DatumGetArrayTypeP(allowed_values); + + deconstruct_array(array, TEXTOID, -1, false, TYPALIGN_INT, + &valuedatums, NULL, &nvalues); + + for (i = 0; i < nvalues; i ++) + { + char *s; + Node *val = NULL; + + s = TextDatumGetCString(valuedatums[i]); + val = (Node *) makeString(pstrdup(s)); + + result = lappend(result, val); + } + + return result; +} + +/* + * Get array datum from allowed_values list. + */ +static Datum +valueListToArray(List *allowed_values) +{ + ArrayBuildState *astate = NULL; + ListCell *cell; + + foreach(cell, allowed_values) + { + char *value = strVal(lfirst(cell)); + Size len; + text *t; + + len = VARHDRSZ + strlen(value); + t = palloc(len + 1); + SET_VARSIZE(t, len); + sprintf(VARDATA(t), "%s", value); + + astate = accumArrayResult(astate, PointerGetDatum(t), + false, TEXTOID, + CurrentMemoryContext); + } + + if (astate) + return makeArrayResult(astate, CurrentMemoryContext); + + return PointerGetDatum(NULL); +} + +/* + * Check whether the tag value has been used on object. + * + * When we alter tag to drop allowed_values, only when the tag + * value has not been used on object we can do it. Otherwise, + * we will report error. Here, we do this check. + */ +static +void checkDropTagValue(Oid tagId, char *tagvalue) +{ + Relation tag_desc_rel; + ScanKeyData skey[2]; + SysScanDesc scan; + HeapTuple tuple; + char *tagname; + + ScanKeyInit(&skey[0], Anum_pg_tag_description_tagid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(tagId)); + ScanKeyInit(&skey[1], Anum_pg_tag_description_tagvalue, + BTEqualStrategyNumber, F_TEXTEQ, + CStringGetTextDatum(tagvalue)); + + tag_desc_rel = table_open(TagDescriptionRelationId, AccessShareLock); + + scan = systable_beginscan(tag_desc_rel, TagDescriptionTagidvalueIndexId, true, + NULL, 2, skey); + + tuple = systable_getnext(scan); + if (HeapTupleIsValid(tuple)) + { + tagname = TagGetNameByOid(tagId, false); + + ereport(ERROR, + (errcode(ERRCODE_CHECK_VIOLATION), + errmsg("Can't drop tag \"%s\" value \"%s\", which is using.", + tagname, tagvalue))); + } + + systable_endscan(scan); + table_close(tag_desc_rel, AccessShareLock); +} + +/* + * TagGetNameByOid + * + * Get tag name by tag oid. + */ +char * +TagGetNameByOid(Oid tagid, bool missing_ok) +{ + char *tagname; + HeapTuple tuple; + Form_pg_tag tagform; + + tuple = SearchSysCache1(TAGOID, ObjectIdGetDatum(tagid)); + if (!HeapTupleIsValid(tuple)) + { + if (!missing_ok) + elog(ERROR, "tag %u could not be found", tagid); + + tagname = NULL; + } + else + { + tagform = (Form_pg_tag) GETSTRUCT(tuple); + + tagname = pstrdup(tagform->tagname.data); + } + ReleaseSysCache(tuple); + + return tagname; +} diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 93ffef3c1d2..a3e50250767 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -34,6 +34,7 @@ #include "commands/comment.h" #include "commands/dbcommands.h" #include "commands/seclabel.h" +#include "commands/tag.h" #include "commands/user.h" #include "libpq/crypt.h" #include "miscadmin.h" @@ -857,6 +858,16 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) AddRoleDenials(stmt->role, roleid, addintervals); } + /* + * Create tag description. + */ + if (stmt->tags) + AddTagDescriptions(stmt->tags, + InvalidOid, + AuthIdRelationId, + roleid, + stmt->role); + /* * Close pg_authid, but keep lock till commit. */ @@ -1781,6 +1792,27 @@ AlterRole(AlterRoleStmt *stmt) ReleaseSysCache(tuple); heap_freetuple(new_tuple); + if (stmt->tags) + { + if (!stmt->unsettag) + { + AlterTagDescriptions(stmt->tags, + InvalidOid, + AuthIdRelationId, + roleid, + rolename); + } + + if (stmt->unsettag) + { + UnsetTagDescriptions(stmt->tags, + InvalidOid, + AuthIdRelationId, + roleid, + rolename); + } + } + /* * Advance command counter so we can see new record; else tests in * AddRoleMems may fail. @@ -1866,7 +1898,7 @@ AlterRole(AlterRoleStmt *stmt) DF_CANCEL_ON_ERROR| DF_WITH_SNAPSHOT| DF_NEED_TWO_PHASE, - NIL, + GetAssignedOidsForDispatch(), NULL); } @@ -2138,6 +2170,13 @@ DropRole(DropRoleStmt *stmt) */ DeleteSharedComments(roleid, AuthIdRelationId); DeleteSharedSecurityLabel(roleid, AuthIdRelationId); + + /* + * Delete any tag description and associated dependencies. + */ + DeleteTagDescriptions(InvalidOid, + AuthIdRelationId, + roleid); /* MPP-6929: metadata tracking */ if (Gp_role == GP_ROLE_DISPATCH) diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 52edda2ed02..0b070e3c69d 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -23,6 +23,7 @@ #include "catalog/pg_depend.h" #include "commands/defrem.h" #include "commands/tablecmds.h" +#include "commands/tag.h" #include "commands/view.h" #include "miscadmin.h" #include "nodes/makefuncs.h" @@ -587,6 +588,17 @@ DefineView(ViewStmt *stmt, const char *queryString, address = DefineVirtualRelation(view, viewParse->targetList, stmt->replace, stmt->options, viewParse); + /* + * Create tag description. + */ + if (stmt->tags) + AddTagDescriptions(stmt->tags, + MyDatabaseId, + address.classId, + address.objectId, + stmt->view->relname); + + if (Gp_role == GP_ROLE_DISPATCH) { ViewStmt *dispatchStmt = (ViewStmt *) copyObject(stmt); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 7fe3e7d0836..b0e2fc50f27 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3923,6 +3923,8 @@ _copyAlterTableCmd(const AlterTableCmd *from) COPY_NODE_FIELD(def); COPY_SCALAR_FIELD(behavior); COPY_SCALAR_FIELD(missing_ok); + COPY_NODE_FIELD(tags); + COPY_SCALAR_FIELD(unsettag); return newnode; } @@ -4130,6 +4132,7 @@ CopyCreateStmtFields(const CreateStmt *from, CreateStmt *newnode) COPY_NODE_FIELD(part_idx_oids); COPY_NODE_FIELD(part_idx_names); + COPY_NODE_FIELD(tags); } static CreateStmt * @@ -4183,6 +4186,7 @@ _copyCreateExternalStmt(const CreateExternalStmt *from) COPY_NODE_FIELD(extOptions); COPY_NODE_FIELD(encoding); COPY_NODE_FIELD(distributedBy); + COPY_NODE_FIELD(tags); return newnode; } @@ -4310,6 +4314,7 @@ _copyIndexStmt(const IndexStmt *from) COPY_SCALAR_FIELD(reset_default_tblspc); COPY_SCALAR_FIELD(concurrentlyPhase); COPY_SCALAR_FIELD(indexRelationOid); + COPY_NODE_FIELD(tags); return newnode; } @@ -4594,6 +4599,7 @@ _copyViewStmt(const ViewStmt *from) COPY_SCALAR_FIELD(replace); COPY_NODE_FIELD(options); COPY_SCALAR_FIELD(withCheckOption); + COPY_NODE_FIELD(tags); return newnode; } @@ -4682,6 +4688,7 @@ _copyCreatedbStmt(const CreatedbStmt *from) COPY_STRING_FIELD(dbname); COPY_NODE_FIELD(options); + COPY_NODE_FIELD(tags); return newnode; } @@ -4693,6 +4700,8 @@ _copyAlterDatabaseStmt(const AlterDatabaseStmt *from) COPY_STRING_FIELD(dbname); COPY_NODE_FIELD(options); + COPY_NODE_FIELD(tags); + COPY_SCALAR_FIELD(unsettag); return newnode; } @@ -4812,6 +4821,7 @@ _copyCreateSeqStmt(const CreateSeqStmt *from) COPY_SCALAR_FIELD(ownerId); COPY_SCALAR_FIELD(for_identity); COPY_SCALAR_FIELD(if_not_exists); + COPY_NODE_FIELD(tags); return newnode; } @@ -4872,6 +4882,7 @@ _copyCreateTableSpaceStmt(const CreateTableSpaceStmt *from) COPY_STRING_FIELD(location); COPY_NODE_FIELD(options); COPY_STRING_FIELD(filehandler); + COPY_NODE_FIELD(tags); return newnode; } @@ -4895,6 +4906,8 @@ _copyAlterTableSpaceOptionsStmt(const AlterTableSpaceOptionsStmt *from) COPY_STRING_FIELD(tablespacename); COPY_NODE_FIELD(options); COPY_SCALAR_FIELD(isReset); + COPY_NODE_FIELD(tags); + COPY_SCALAR_FIELD(unsettag); return newnode; } @@ -5238,6 +5251,7 @@ _copyCreateRoleStmt(const CreateRoleStmt *from) COPY_SCALAR_FIELD(stmt_type); COPY_STRING_FIELD(role); COPY_NODE_FIELD(options); + COPY_NODE_FIELD(tags); return newnode; } @@ -5283,6 +5297,8 @@ _copyAlterRoleStmt(const AlterRoleStmt *from) COPY_NODE_FIELD(role); COPY_NODE_FIELD(options); COPY_SCALAR_FIELD(action); + COPY_NODE_FIELD(tags); + COPY_SCALAR_FIELD(unsettag); return newnode; } @@ -5398,10 +5414,60 @@ _copyCreateSchemaStmt(const CreateSchemaStmt *from) COPY_SCALAR_FIELD(if_not_exists); COPY_SCALAR_FIELD(istemp); COPY_SCALAR_FIELD(pop_search_path); + COPY_NODE_FIELD(tags); return newnode; } +static AlterSchemaStmt * +_copyAlterSchemaStmt(const AlterSchemaStmt *from) +{ + AlterSchemaStmt *newnode = makeNode(AlterSchemaStmt); + + COPY_STRING_FIELD(schemaname); + COPY_NODE_FIELD(tags); + COPY_SCALAR_FIELD(unsettag); + + return newnode; +} + +static CreateTagStmt * +_copyCreateTagStmt(const CreateTagStmt *from) +{ + CreateTagStmt *newnode = makeNode(CreateTagStmt); + + COPY_STRING_FIELD(tag_name); + COPY_SCALAR_FIELD(missing_ok); + COPY_NODE_FIELD(allowed_values); + + return newnode; +} + +static AlterTagStmt * +_copyAlterTagStmt(const AlterTagStmt *from) +{ + AlterTagStmt *newnode = makeNode(AlterTagStmt); + + COPY_STRING_FIELD(tag_name); + COPY_SCALAR_FIELD(action); + COPY_NODE_FIELD(tag_values); + COPY_SCALAR_FIELD(missing_ok); + COPY_SCALAR_FIELD(unset); + + return newnode; +} + +static DropTagStmt * +_copyDropTagStmt(const DropTagStmt *from) +{ + DropTagStmt *newnode = makeNode(DropTagStmt); + + COPY_NODE_FIELD(tags); + COPY_SCALAR_FIELD(missing_ok); + + return newnode; +} + static CreateConversionStmt * _copyCreateConversionStmt(const CreateConversionStmt *from) { @@ -6112,6 +6178,18 @@ _copyCreateDirectoryTableStmt(const CreateDirectoryTableStmt *from) return newnode; } +static AlterDirectoryTableStmt * +_copyAlterDirectoryTableStmt(const AlterDirectoryTableStmt *from) +{ + AlterDirectoryTableStmt *newnode = makeNode(AlterDirectoryTableStmt); + + COPY_NODE_FIELD(relation); + COPY_NODE_FIELD(tags); + COPY_SCALAR_FIELD(unsettag); + + return newnode; +} + static EphemeralNamedRelationInfo* _copyEphemeralNamedRelationInfo(const EphemeralNamedRelationInfo *from) { @@ -6946,6 +7024,18 @@ copyObjectImpl(const void *from) case T_CreateSchemaStmt: retval = _copyCreateSchemaStmt(from); break; + case T_AlterSchemaStmt: + retval = _copyAlterSchemaStmt(from); + break; + case T_CreateTagStmt: + retval = _copyCreateTagStmt(from); + break; + case T_AlterTagStmt: + retval = _copyAlterTagStmt(from); + break; + case T_DropTagStmt: + retval = _copyDropTagStmt(from); + break; case T_CreateConversionStmt: retval = _copyCreateConversionStmt(from); break; @@ -7257,6 +7347,10 @@ copyObjectImpl(const void *from) retval = _copyCreateDirectoryTableStmt(from); break; + case T_AlterDirectoryTableStmt: + retval = _copyAlterDirectoryTableStmt(from); + break; + case T_EphemeralNamedRelationInfo: retval = _copyEphemeralNamedRelationInfo(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 283a5c5d552..b222609948f 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1219,6 +1219,8 @@ _equalAlterTableCmd(const AlterTableCmd *a, const AlterTableCmd *b) COMPARE_NODE_FIELD(def); COMPARE_SCALAR_FIELD(behavior); COMPARE_SCALAR_FIELD(missing_ok); + COMPARE_NODE_FIELD(tags); + COMPARE_SCALAR_FIELD(unsettag); return true; } @@ -1389,6 +1391,7 @@ _equalCreateStmt(const CreateStmt *a, const CreateStmt *b) COMPARE_SCALAR_FIELD(buildAoBlkdir); COMPARE_NODE_FIELD(attr_encodings); COMPARE_SCALAR_FIELD(isCtas); + COMPARE_NODE_FIELD(tags); return true; } @@ -1439,6 +1442,7 @@ _equalCreateExternalStmt(const CreateExternalStmt *a, const CreateExternalStmt * COMPARE_NODE_FIELD(extOptions); COMPARE_NODE_FIELD(encoding); COMPARE_NODE_FIELD(distributedBy); + COMPARE_NODE_FIELD(tags); return true; } @@ -1560,6 +1564,7 @@ _equalIndexStmt(const IndexStmt *a, const IndexStmt *b) COMPARE_SCALAR_FIELD(reset_default_tblspc); COMPARE_SCALAR_FIELD(concurrentlyPhase); COMPARE_SCALAR_FIELD(indexRelationOid); + COMPARE_NODE_FIELD(tags); return true; } @@ -1800,6 +1805,7 @@ _equalViewStmt(const ViewStmt *a, const ViewStmt *b) COMPARE_SCALAR_FIELD(replace); COMPARE_NODE_FIELD(options); COMPARE_SCALAR_FIELD(withCheckOption); + COMPARE_NODE_FIELD(tags); return true; } @@ -1874,6 +1880,7 @@ _equalCreatedbStmt(const CreatedbStmt *a, const CreatedbStmt *b) { COMPARE_STRING_FIELD(dbname); COMPARE_NODE_FIELD(options); + COMPARE_NODE_FIELD(tags); return true; } @@ -1882,6 +1889,8 @@ _equalAlterDatabaseStmt(const AlterDatabaseStmt *a, const AlterDatabaseStmt *b) { COMPARE_STRING_FIELD(dbname); COMPARE_NODE_FIELD(options); + COMPARE_NODE_FIELD(tags); + COMPARE_SCALAR_FIELD(unsettag); return true; } @@ -1983,6 +1992,7 @@ _equalCreateSeqStmt(const CreateSeqStmt *a, const CreateSeqStmt *b) COMPARE_SCALAR_FIELD(ownerId); COMPARE_SCALAR_FIELD(for_identity); COMPARE_SCALAR_FIELD(if_not_exists); + COMPARE_NODE_FIELD(tags); return true; } @@ -2033,6 +2043,7 @@ _equalCreateTableSpaceStmt(const CreateTableSpaceStmt *a, const CreateTableSpace COMPARE_STRING_FIELD(location); COMPARE_NODE_FIELD(options); COMPARE_STRING_FIELD(filehandler); + COMPARE_NODE_FIELD(tags); return true; } @@ -2053,6 +2064,8 @@ _equalAlterTableSpaceOptionsStmt(const AlterTableSpaceOptionsStmt *a, COMPARE_STRING_FIELD(tablespacename); COMPARE_NODE_FIELD(options); COMPARE_SCALAR_FIELD(isReset); + COMPARE_NODE_FIELD(tags); + COMPARE_SCALAR_FIELD(unsettag); return true; } @@ -2346,6 +2359,7 @@ _equalCreateRoleStmt(const CreateRoleStmt *a, const CreateRoleStmt *b) COMPARE_SCALAR_FIELD(stmt_type); COMPARE_STRING_FIELD(role); COMPARE_NODE_FIELD(options); + COMPARE_NODE_FIELD(tags); return true; } @@ -2383,6 +2397,8 @@ _equalAlterRoleStmt(const AlterRoleStmt *a, const AlterRoleStmt *b) COMPARE_NODE_FIELD(role); COMPARE_NODE_FIELD(options); COMPARE_SCALAR_FIELD(action); + COMPARE_NODE_FIELD(tags); + COMPARE_SCALAR_FIELD(unsettag); return true; } @@ -2480,10 +2496,52 @@ _equalCreateSchemaStmt(const CreateSchemaStmt *a, const CreateSchemaStmt *b) COMPARE_SCALAR_FIELD(if_not_exists); COMPARE_SCALAR_FIELD(istemp); COMPARE_SCALAR_FIELD(pop_search_path); + COMPARE_NODE_FIELD(tags); return true; } +static bool +_equalAlterSchemaStmt(const AlterSchemaStmt *a, const AlterSchemaStmt *b) +{ + COMPARE_STRING_FIELD(schemaname); + COMPARE_NODE_FIELD(tags); + COMPARE_SCALAR_FIELD(unsettag); + + return true; +} + +static bool +_equalCreateTagStmt(const CreateTagStmt *a, const CreateTagStmt *b) +{ + COMPARE_STRING_FIELD(tag_name); + COMPARE_SCALAR_FIELD(missing_ok); + COMPARE_NODE_FIELD(allowed_values); + + return true; +} + +static bool +_equalAlterTagStmt(const AlterTagStmt *a, const AlterTagStmt *b) +{ + COMPARE_STRING_FIELD(tag_name); + COMPARE_SCALAR_FIELD(action); + COMPARE_NODE_FIELD(tag_values); + COMPARE_SCALAR_FIELD(missing_ok); + COMPARE_SCALAR_FIELD(unset); + + return true; +} + +static bool +_equalDropTagStmt(const DropTagStmt *a, const DropTagStmt *b) +{ + COMPARE_NODE_FIELD(tags); + COMPARE_SCALAR_FIELD(missing_ok); + + return true; +} + static bool _equalCreateConversionStmt(const CreateConversionStmt *a, const CreateConversionStmt *b) { @@ -3406,6 +3464,16 @@ _equalCreateDirectoryTableStmt(const CreateDirectoryTableStmt *a, const CreateDi return true; } +static bool +_equalAlterDirectoryTableStmt(const AlterDirectoryTableStmt *a, const AlterDirectoryTableStmt *b) +{ + COMPARE_NODE_FIELD(relation); + COMPARE_NODE_FIELD(tags); + COMPARE_SCALAR_FIELD(unsettag); + + return true; +} + /* * Stuff from pg_list.h */ @@ -4096,6 +4164,18 @@ equal(const void *a, const void *b) case T_CreateSchemaStmt: retval = _equalCreateSchemaStmt(a, b); break; + case T_AlterSchemaStmt: + retval = _equalAlterSchemaStmt(a, b); + break; + case T_CreateTagStmt: + retval = _equalCreateTagStmt(a, b); + break; + case T_AlterTagStmt: + retval = _equalAlterTagStmt(a, b); + break; + case T_DropTagStmt: + retval = _equalDropTagStmt(a, b); + break; case T_CreateConversionStmt: retval = _equalCreateConversionStmt(a, b); break; @@ -4343,6 +4423,10 @@ equal(const void *a, const void *b) retval = _equalCreateDirectoryTableStmt(a, b); break; + case T_AlterDirectoryTableStmt: + retval = _equalAlterDirectoryTableStmt(a, b); + break; + default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(a)); diff --git a/src/backend/nodes/outfast.c b/src/backend/nodes/outfast.c index 043a2b8af6c..d2ef98d93ed 100644 --- a/src/backend/nodes/outfast.c +++ b/src/backend/nodes/outfast.c @@ -806,6 +806,8 @@ _outAlterTableSpaceOptionsStmt(StringInfo str, AlterTableSpaceOptionsStmt *node) WRITE_STRING_FIELD(tablespacename); WRITE_NODE_FIELD(options); WRITE_BOOL_FIELD(isReset); + WRITE_NODE_FIELD(tags); + WRITE_BOOL_FIELD(unsettag); } static void @@ -1624,6 +1626,19 @@ _outNode(StringInfo str, void *obj) case T_CreateSchemaStmt: _outCreateSchemaStmt(str, obj); break; + case T_AlterSchemaStmt: + _outAlterSchemaStmt(str, obj); + break; + + case T_CreateTagStmt: + _outCreateTagStmt(str, obj); + break; + case T_AlterTagStmt: + _outAlterTagStmt(str, obj); + break; + case T_DropTagStmt: + _outDropTagStmt(str, obj); + break; case T_CreatePLangStmt: _outCreatePLangStmt(str, obj); break; @@ -1863,9 +1878,15 @@ _outNode(StringInfo str, void *obj) case T_CreateDirectoryTableStmt: _outCreateDirectoryTableStmt(str, obj); break; + case T_AlterDirectoryTableStmt: + _outAlterDirectoryTableStmt(str, obj); + break; case T_EphemeralNamedRelationInfo: _outEphemeralNamedRelationInfo(str, obj); break; + case T_AlterDatabaseStmt: + _outAlterDatabaseStmt(str, obj); + break; default: elog(ERROR, "could not serialize unrecognized node type: %d", (int) nodeTag(obj)); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index d562b9c0397..35214101608 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -2902,6 +2902,7 @@ _outCreateStmtInfo(StringInfo str, const CreateStmt *node) WRITE_NODE_FIELD(part_idx_oids); WRITE_NODE_FIELD(part_idx_names); + WRITE_NODE_FIELD(tags); /* * Some extra checks to make sure we didn't get lost @@ -2975,6 +2976,7 @@ _outIndexStmt(StringInfo str, const IndexStmt *node) WRITE_BOOL_FIELD(reset_default_tblspc); WRITE_ENUM_FIELD(concurrentlyPhase, IndexConcurrentlyPhase); WRITE_OID_FIELD(indexRelationOid); + WRITE_NODE_FIELD(tags); } static void @@ -3286,6 +3288,7 @@ _outQuery(StringInfo str, const Query *node) case T_DropProfileStmt: case T_CreateSchemaStmt: + case T_AlterSchemaStmt: case T_CreatePLangStmt: case T_AlterOwnerStmt: case T_AlterObjectSchemaStmt: @@ -4032,6 +4035,16 @@ _outCreateDirectoryTableStmt(StringInfo str, const CreateDirectoryTableStmt *nod WRITE_STRING_FIELD(tablespacename); } +static void +_outAlterDirectoryTableStmt(StringInfo str, const AlterDirectoryTableStmt *node) +{ + WRITE_NODE_TYPE("ALTERDIRECTORYTABLESTMT"); + + WRITE_NODE_FIELD(relation); + WRITE_NODE_FIELD(tags); + WRITE_BOOL_FIELD(unsettag); +} + #include "outfuncs_common.c" #ifndef COMPILING_BINARY_FUNCS /* @@ -5032,6 +5045,19 @@ outNode(StringInfo str, const void *obj) case T_CreateSchemaStmt: _outCreateSchemaStmt(str, obj); break; + case T_AlterSchemaStmt: + _outAlterSchemaStmt(str, obj); + break; + + case T_CreateTagStmt: + _outCreateTagStmt(str, obj); + break; + case T_AlterTagStmt: + _outAlterTagStmt(str, obj); + break; + case T_DropTagStmt: + _outDropTagStmt(str, obj); + break; case T_CreatePLangStmt: _outCreatePLangStmt(str, obj); break; @@ -5167,9 +5193,15 @@ outNode(StringInfo str, const void *obj) case T_EphemeralNamedRelationInfo: _outEphemeralNamedRelationInfo(str, obj); break; + case T_AlterDatabaseStmt: + _outAlterDatabaseStmt(str, obj); + break; case T_CreateDirectoryTableStmt: _outCreateDirectoryTableStmt(str, obj); break; + case T_AlterDirectoryTableStmt: + _outAlterDirectoryTableStmt(str, obj); + break; default: /* diff --git a/src/backend/nodes/outfuncs_common.c b/src/backend/nodes/outfuncs_common.c index 76e766e55d2..4cf0c1b8287 100644 --- a/src/backend/nodes/outfuncs_common.c +++ b/src/backend/nodes/outfuncs_common.c @@ -568,6 +568,7 @@ _outCreateExternalStmt(StringInfo str, const CreateExternalStmt *node) WRITE_NODE_FIELD(extOptions); WRITE_NODE_FIELD(encoding); WRITE_NODE_FIELD(distributedBy); + WRITE_NODE_FIELD(tags); } static void @@ -619,6 +620,7 @@ _outViewStmt(StringInfo str, const ViewStmt *node) WRITE_NODE_FIELD(query); WRITE_BOOL_FIELD(replace); WRITE_NODE_FIELD(options); + WRITE_NODE_FIELD(tags); } static void @@ -712,6 +714,8 @@ _outAlterTableCmd(StringInfo str, const AlterTableCmd *node) WRITE_INT_FIELD(backendId); WRITE_NODE_FIELD(policy); + WRITE_NODE_FIELD(tags); + WRITE_BOOL_FIELD(unsettag); } static void @@ -840,6 +844,7 @@ _outCreateRoleStmt(StringInfo str, const CreateRoleStmt *node) WRITE_ENUM_FIELD(stmt_type, RoleStmtType); WRITE_STRING_FIELD(role); WRITE_NODE_FIELD(options); + WRITE_NODE_FIELD(tags); } static void @@ -927,6 +932,8 @@ _outAlterRoleStmt(StringInfo str, const AlterRoleStmt *node) WRITE_NODE_FIELD(role); WRITE_NODE_FIELD(options); WRITE_INT_FIELD(action); + WRITE_NODE_FIELD(tags); + WRITE_BOOL_FIELD(unsettag); } static void @@ -973,6 +980,7 @@ _outCreateSeqStmt(StringInfo str, const CreateSeqStmt *node) WRITE_OID_FIELD(ownerId); WRITE_BOOL_FIELD(for_identity); WRITE_BOOL_FIELD(if_not_exists); + WRITE_NODE_FIELD(tags); } static void @@ -1000,6 +1008,7 @@ _outCreatedbStmt(StringInfo str, const CreatedbStmt *node) WRITE_NODE_TYPE("CREATEDBSTMT"); WRITE_STRING_FIELD(dbname); WRITE_NODE_FIELD(options); + WRITE_NODE_FIELD(tags); } static void @@ -1366,6 +1375,48 @@ _outCreateSchemaStmt(StringInfo str, const CreateSchemaStmt *node) WRITE_NODE_FIELD(authrole); WRITE_BOOL_FIELD(istemp); WRITE_BOOL_FIELD(pop_search_path); + WRITE_NODE_FIELD(tags); +} + +static void +_outAlterSchemaStmt(StringInfo str, const AlterSchemaStmt *node) +{ + WRITE_NODE_TYPE("ALTERSCHEMASTMT"); + + WRITE_STRING_FIELD(schemaname); + WRITE_NODE_FIELD(tags); + WRITE_BOOL_FIELD(unsettag); +} + +static void +_outCreateTagStmt(StringInfo str, const CreateTagStmt *node) +{ + WRITE_NODE_TYPE("CREATETAGSTMT"); + + WRITE_STRING_FIELD(tag_name); + WRITE_BOOL_FIELD(missing_ok); + WRITE_NODE_FIELD(allowed_values); +} + +static void +_outAlterTagStmt(StringInfo str, const AlterTagStmt *node) +{ + WRITE_NODE_TYPE("ALTERTAGSTMT"); + + WRITE_STRING_FIELD(tag_name); + WRITE_INT_FIELD(action); + WRITE_NODE_FIELD(tag_values); + WRITE_BOOL_FIELD(missing_ok); + WRITE_BOOL_FIELD(unset); +} + +static void +_outDropTagStmt(StringInfo str, const DropTagStmt *node) +{ + WRITE_NODE_TYPE("DROPTAGSTMT"); + + WRITE_NODE_FIELD(tags); + WRITE_BOOL_FIELD(missing_ok); } static void @@ -1485,6 +1536,7 @@ _outCreateTableSpaceStmt(StringInfo str, const CreateTableSpaceStmt *node) WRITE_STRING_FIELD(location); WRITE_NODE_FIELD(options); WRITE_STRING_FIELD(filehandler); + WRITE_NODE_FIELD(tags); } static void @@ -1714,3 +1766,13 @@ _outEphemeralNamedRelationInfo(StringInfo str, const EphemeralNamedRelationInfo WRITE_ENUM_FIELD(enrtype, EphemeralNameRelationType); WRITE_FLOAT_FIELD(enrtuples, "%.0f"); } + +static void +_outAlterDatabaseStmt(StringInfo str, const AlterDatabaseStmt *node) +{ + WRITE_NODE_TYPE("AlterDatabaseStmt"); + WRITE_STRING_FIELD(dbname); + WRITE_NODE_FIELD(options); + WRITE_NODE_FIELD(tags); + WRITE_BOOL_FIELD(unsettag); +} \ No newline at end of file diff --git a/src/backend/nodes/readfast.c b/src/backend/nodes/readfast.c index 96e42bff0cd..351c8eae1d5 100644 --- a/src/backend/nodes/readfast.c +++ b/src/backend/nodes/readfast.c @@ -744,6 +744,7 @@ _readCreateStmt_common(CreateStmt *local_node) READ_NODE_FIELD(part_idx_oids); READ_NODE_FIELD(part_idx_names); + READ_NODE_FIELD(tags); /* * Some extra checks to make sure we didn't get lost @@ -1132,6 +1133,7 @@ _readCreateTableSpaceStmt(void) READ_STRING_FIELD(location); READ_NODE_FIELD(options); READ_STRING_FIELD(filehandler); + READ_NODE_FIELD(tags); READ_DONE(); } @@ -1170,6 +1172,8 @@ _readAlterTableSpaceOptionsStmt(void) READ_STRING_FIELD(tablespacename); READ_NODE_FIELD(options); READ_BOOL_FIELD(isReset); + READ_NODE_FIELD(tags); + READ_BOOL_FIELD(unsettag); READ_DONE(); } @@ -1726,6 +1730,18 @@ _readCreateDirectoryTableStmt(void) READ_DONE(); } +static AlterDirectoryTableStmt * +_readAlterDirectoryTableStmt(void) +{ + READ_LOCALS(AlterDirectoryTableStmt); + + READ_NODE_FIELD(relation); + READ_NODE_FIELD(tags); + READ_BOOL_FIELD(unsettag); + + READ_DONE(); +} + static EphemeralNamedRelationInfo * _readEphemeralNamedRelationInfo(void) { @@ -1758,6 +1774,19 @@ _readEphemeralNamedRelationInfo(void) READ_DONE(); } +static void * +_readAlterDatabaseStmt(void) +{ + READ_LOCALS(AlterDatabaseStmt); + + READ_STRING_FIELD(dbname); + READ_NODE_FIELD(options); + READ_NODE_FIELD(tags); + READ_BOOL_FIELD(unsettag); + + READ_DONE(); +} + static void * readNodeBinary(void) { @@ -2548,6 +2577,18 @@ readNodeBinary(void) case T_CreateSchemaStmt: return_value = _readCreateSchemaStmt(); break; + case T_AlterSchemaStmt: + return_value = _readAlterSchemaStmt(); + break; + case T_CreateTagStmt: + return_value = _readCreateTagStmt(); + break; + case T_AlterTagStmt: + return_value = _readAlterTagStmt(); + break; + case T_DropTagStmt: + return_value = _readDropTagStmt(); + break; case T_CreatePLangStmt: return_value = _readCreatePLangStmt(); break; @@ -2773,9 +2814,15 @@ readNodeBinary(void) case T_EphemeralNamedRelationInfo: return_value = _readEphemeralNamedRelationInfo(); break; + case T_AlterDatabaseStmt: + return_value = _readAlterDatabaseStmt(); + break; case T_CreateDirectoryTableStmt: return_value = _readCreateDirectoryTableStmt(); break; + case T_AlterDirectoryTableStmt: + return_value = _readAlterDirectoryTableStmt(); + break; default: return_value = NULL; /* keep the compiler silent */ elog(ERROR, "could not deserialize unrecognized node type: %d", diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 7c73b544df1..6a3eaec5f46 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -3204,6 +3204,14 @@ parseNodeString(void) return_value = _readCreateProfileStmt(); else if (MATCHX("CREATESCHEMASTMT")) return_value = _readCreateSchemaStmt(); + else if (MATCHX("ALTERSCHEMASTMT")) + return_value = _readAlterSchemaStmt(); + else if (MATCHX("CREATETAGSTMT")) + return_value = _readCreateTagStmt(); + else if (MATCHX("ALTERTAGSTMT")) + return_value = _readAlterTagStmt(); + else if (MATCHX("DROPTAGSTMT")) + return_value = _readDropTagStmt(); else if (MATCHX("CREATESEQSTMT")) return_value = _readCreateSeqStmt(); else if (MATCHX("CREATETRANSFORMSTMT")) diff --git a/src/backend/nodes/readfuncs_common.c b/src/backend/nodes/readfuncs_common.c index f23687143e3..96b8c9f8690 100644 --- a/src/backend/nodes/readfuncs_common.c +++ b/src/backend/nodes/readfuncs_common.c @@ -385,6 +385,8 @@ _readAlterRoleStmt(void) READ_NODE_FIELD(role); READ_NODE_FIELD(options); READ_INT_FIELD(action); + READ_NODE_FIELD(tags); + READ_BOOL_FIELD(unsettag); READ_DONE(); } @@ -453,6 +455,8 @@ _readAlterTableCmd(void) READ_INT_FIELD(backendId); READ_NODE_FIELD(policy); + READ_NODE_FIELD(tags); + READ_BOOL_FIELD(unsettag); READ_DONE(); } @@ -765,6 +769,7 @@ _readCreateExternalStmt(void) READ_NODE_FIELD(extOptions); READ_NODE_FIELD(encoding); READ_NODE_FIELD(distributedBy); + READ_NODE_FIELD(tags); READ_DONE(); } @@ -877,6 +882,7 @@ _readCreateRoleStmt(void) READ_ENUM_FIELD(stmt_type, RoleStmtType); READ_STRING_FIELD(role); READ_NODE_FIELD(options); + READ_NODE_FIELD(tags); READ_DONE(); } @@ -902,10 +908,60 @@ _readCreateSchemaStmt(void) local_node->schemaElts = 0; READ_BOOL_FIELD(istemp); READ_BOOL_FIELD(pop_search_path); + READ_NODE_FIELD(tags); READ_DONE(); } +static AlterSchemaStmt * +_readAlterSchemaStmt(void) +{ + READ_LOCALS(AlterSchemaStmt); + + READ_STRING_FIELD(schemaname); + READ_NODE_FIELD(tags); + READ_BOOL_FIELD(unsettag); + + READ_DONE(); +} + +static CreateTagStmt * +_readCreateTagStmt(void) +{ + READ_LOCALS(CreateTagStmt); + + READ_STRING_FIELD(tag_name); + READ_BOOL_FIELD(missing_ok); + READ_NODE_FIELD(allowed_values); + + READ_DONE(); +} + +static AlterTagStmt * +_readAlterTagStmt(void) +{ + READ_LOCALS(AlterTagStmt); + + READ_STRING_FIELD(tag_name); + READ_INT_FIELD(action); + READ_NODE_FIELD(tag_values); + READ_BOOL_FIELD(missing_ok); + READ_BOOL_FIELD(unset); + + READ_DONE(); +} + +static DropTagStmt * +_readDropTagStmt(void) +{ + READ_LOCALS(DropTagStmt); + + READ_NODE_FIELD(tags); + READ_BOOL_FIELD(missing_ok); + + READ_DONE(); +} + static CreateSeqStmt * _readCreateSeqStmt(void) { @@ -915,6 +971,7 @@ _readCreateSeqStmt(void) READ_OID_FIELD(ownerId); READ_BOOL_FIELD(for_identity); READ_BOOL_FIELD(if_not_exists); + READ_NODE_FIELD(tags); READ_DONE(); } @@ -961,6 +1018,7 @@ _readCreatedbStmt(void) READ_STRING_FIELD(dbname); READ_NODE_FIELD(options); + READ_NODE_FIELD(tags); READ_DONE(); } @@ -1266,6 +1324,7 @@ _readIndexStmt(void) READ_BOOL_FIELD(reset_default_tblspc); READ_ENUM_FIELD(concurrentlyPhase,IndexConcurrentlyPhase); READ_OID_FIELD(indexRelationOid); + READ_NODE_FIELD(tags); READ_DONE(); } @@ -1713,6 +1772,7 @@ _readViewStmt(void) READ_NODE_FIELD(query); READ_BOOL_FIELD(replace); READ_NODE_FIELD(options); + READ_NODE_FIELD(tags); READ_DONE(); } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 5b99cc679a7..eecfeea40dd 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -280,7 +280,7 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ %type stmt toplevel_stmt schema_stmt routine_body_stmt AlterEventTrigStmt AlterCollationStmt - AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt + AlterDatabaseStmt AlterDatabaseSetStmt AlterDirectoryTableStmt AlterDomainStmt AlterEnumStmt AlterFdwStmt AlterForeignServerStmt AlterGroupStmt AlterObjectDependsStmt AlterObjectSchemaStmt AlterOwnerStmt AlterOperatorStmt AlterTypeStmt AlterSeqStmt AlterStorageServerStmt AlterSystemStmt AlterTableStmt @@ -321,10 +321,10 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ RetrieveStmt CreateTaskStmt AlterTaskStmt DropTaskStmt /* GPDB-specific commands */ -%type AlterProfileStmt AlterQueueStmt AlterResourceGroupStmt +%type AlterProfileStmt AlterQueueStmt AlterResourceGroupStmt AlterSchemaStmt AlterTagStmt CreateExternalStmt - CreateProfileStmt CreateQueueStmt CreateResourceGroupStmt - DropProfileStmt DropQueueStmt DropResourceGroupStmt + CreateProfileStmt CreateQueueStmt CreateResourceGroupStmt CreateTagStmt + DropProfileStmt DropQueueStmt DropResourceGroupStmt DropTagStmt ExtTypedesc OptSingleRowErrorHandling ExtSingleRowErrorHandling %type deny_login_role deny_interval deny_point deny_day_specifier @@ -377,6 +377,8 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ %type OptRoleList AlterOptRoleList %type OptProfileList +%type OptTagValuesList OptTagOptList TagOptList +%type TagOptElem %type CreateOptRoleElem AlterOptRoleElem %type AlterOnlyOptRoleElem %type OptProfileElem @@ -840,7 +842,7 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ /* GPDB-added keywords, in alphabetical order */ %token - ACCOUNT ACTIVE + ACCOUNT ACTIVE ALLOWED_VALUES CONTAINS COORDINATOR CPUSET CPU_HARD_QUOTA_LIMIT CPU_SOFT_PRIORITY @@ -884,6 +886,8 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ THRESHOLD UNLOCK_P + + UNSET_P VALIDATION @@ -1189,6 +1193,7 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ %nonassoc SYSTEM_P %nonassoc STRICT_P %nonassoc TABLESPACE + %nonassoc TAG %nonassoc TASK %nonassoc TEMP %nonassoc TEMPLATE @@ -1384,6 +1389,7 @@ stmt: | AlterDatabaseStmt | AlterDatabaseSetStmt | AlterDefaultPrivilegesStmt + | AlterDirectoryTableStmt | AlterDomainStmt | AlterEnumStmt | AlterExtensionStmt @@ -1402,10 +1408,12 @@ stmt: | AlterProfileStmt | AlterQueueStmt | AlterResourceGroupStmt + | AlterSchemaStmt | AlterSeqStmt | AlterStorageServerStmt | AlterSystemStmt | AlterTableStmt + | AlterTagStmt | AlterTblSpcStmt | AlterCompositeTypeStmt | AlterPublicationStmt @@ -1458,6 +1466,7 @@ stmt: | CreateStorageServerStmt | CreateStorageUserMappingStmt | CreateTableSpaceStmt + | CreateTagStmt | CreateTaskStmt | CreateTransformStmt | CreateTrigStmt @@ -1482,6 +1491,7 @@ stmt: | DropStmt | DropSubscriptionStmt | DropTableSpaceStmt + | DropTagStmt | DropTaskStmt | DropTransformStmt | DropRoleStmt @@ -2019,12 +2029,13 @@ keyvalue_pair: *****************************************************************************/ CreateUserStmt: - CREATE USER RoleId opt_with OptRoleList + CREATE USER RoleId opt_with OptRoleList OptTagOptList { CreateRoleStmt *n = makeNode(CreateRoleStmt); n->stmt_type = ROLESTMT_USER; n->role = $3; n->options = $5; + n->tags = $6; $$ = (Node *)n; } ; @@ -2053,6 +2064,21 @@ AlterRoleStmt: n->options = $5; $$ = (Node *)n; } + | ALTER USER RoleSpec TAG '(' TagOptList ')' + { + AlterRoleStmt *n = makeNode(AlterRoleStmt); + n->role = $3; + n->tags = $6; + $$ = (Node *)n; + } + | ALTER USER RoleSpec UNSET_P TAG '(' name_list ')' + { + AlterRoleStmt *n = makeNode(AlterRoleStmt); + n->role = $3; + n->tags = $7; + n->unsettag = true; + $$ = (Node *)n; + } ; opt_in_database: @@ -2342,8 +2368,40 @@ CreateSchemaStmt: n->if_not_exists = true; $$ = (Node *)n; } + | CREATE SCHEMA ColId WITH TAG '(' TagOptList ')' + { + CreateSchemaStmt *n = makeNode(CreateSchemaStmt); + n->schemaname = $3; + n->if_not_exists = false; + n->tags = $7; + $$ = (Node *)n; + } ; +/***************************************************************************** + * + * Alter a schema to add a tag + * + *****************************************************************************/ + +AlterSchemaStmt: + ALTER SCHEMA name TAG '(' TagOptList ')' + { + AlterSchemaStmt *n = makeNode(AlterSchemaStmt); + n->schemaname = $3; + n->tags = $6; + $$ = (Node *)n; + } + | ALTER SCHEMA name UNSET_P TAG '(' name_list ')' + { + AlterSchemaStmt *n = makeNode(AlterSchemaStmt); + n->schemaname = $3; + n->tags = $7; + n->unsettag = true; + $$ = (Node *)n; + } + ; + OptSchemaName: ColId { $$ = $1; } | /* EMPTY */ { $$ = NULL; } @@ -2374,6 +2432,136 @@ schema_stmt: ; +/***************************************************************************** + * + * Create a new Postgres DBMS Tag + * + *****************************************************************************/ + +CreateTagStmt: + CREATE TAG name + { + CreateTagStmt *n = makeNode(CreateTagStmt); + n->tag_name = $3; + n->missing_ok = false; + n->allowed_values = NIL; + $$ = (Node *)n; + } + | CREATE TAG IF_P NOT EXISTS name + { + CreateTagStmt *n = makeNode(CreateTagStmt); + n->tag_name = $6; + n->missing_ok = true; + n->allowed_values = NIL; + $$ = (Node *)n; + } + | CREATE TAG name ALLOWED_VALUES OptTagValuesList + { + CreateTagStmt *n = makeNode(CreateTagStmt); + n->tag_name = $3; + n->missing_ok = false; + n->allowed_values = $5; + $$ = (Node *)n; + } + | CREATE TAG IF_P NOT EXISTS name ALLOWED_VALUES OptTagValuesList + { + CreateTagStmt *n = makeNode(CreateTagStmt); + n->tag_name = $6; + n->missing_ok = true; + n->allowed_values = $8; + $$ = (Node *)n; + } + ; + + +/***************************************************************************** + * + * Alter a postgresql DBMS Tag + * + *****************************************************************************/ + +AlterTagStmt: + ALTER TAG name add_drop ALLOWED_VALUES OptTagValuesList + { + AlterTagStmt *n = makeNode(AlterTagStmt); + n->missing_ok = false; + n->tag_name = $3; + n->action = $4; + n->tag_values = $6; + n->unset = false; + $$ = (Node *)n; + } + | ALTER TAG IF_P EXISTS name add_drop ALLOWED_VALUES OptTagValuesList + { + AlterTagStmt *n = makeNode(AlterTagStmt); + n->missing_ok = true; + n->tag_name = $5; + n->action = $6; + n->tag_values = $8; + n->unset = false; + $$ = (Node *)n; + } + | ALTER TAG name UNSET_P ALLOWED_VALUES + { + AlterTagStmt *n = makeNode(AlterTagStmt); + n->tag_name = $3; + n->unset = true; + $$ = (Node *)n; + } + ; + + +/***************************************************************************** + * + * Drop a postgresql DBMS Tag + * + * XXX Ideally this would have CASCADE/RESTRICT options, but a profile + * might be attached by users in multiple databases, using CASCADE will drop + * users meanwhile which is unreasonable. So we always behave as RESTRICT. + *****************************************************************************/ + +DropTagStmt: + DROP TAG name_list + { + DropTagStmt *n = makeNode(DropTagStmt); + n->tags = $3; + n->missing_ok = false; + $$ = (Node *)n; + } + | DROP TAG IF_P EXISTS name_list + { + DropTagStmt *n = makeNode(DropTagStmt); + n->tags = $5; + n->missing_ok = true; + $$ = (Node *)n; + } + ; + +/* + * List of allowed values for Tag. + */ +OptTagValuesList: + OptTagValuesList ',' Sconst { $$ = lappend($1, makeString($3)); } + | Sconst { $$ = list_make1(makeString($1)); } + ; + +OptTagOptList: + TAG '(' TagOptList ')' { $$ = $3; } + | /*EMPTY*/ { $$ = NIL; } + ; + +TagOptList: + TagOptElem { $$ = list_make1($1); } + | TagOptList ',' TagOptElem { $$ = lappend($1, $3); } + ; + +TagOptElem: + ColLabel '=' Sconst + { + $$ = makeDefElem($1, (Node *) makeString($3), @1); + } + ; + /***************************************************************************** * * Set PG internal variable @@ -3657,6 +3845,21 @@ alter_table_cmd: n->def = (Node *)$1; $$ = (Node *) n; } + | TAG '(' TagOptList ')' + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SetTags; + n->tags = $3; + $$ = (Node *) n; + } + | UNSET_P TAG '(' name_list ')' + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_UnsetTags; + n->tags = $4; + n->unsettag = true; + $$ = (Node *) n; + } ; alter_column_default: @@ -4783,7 +4986,7 @@ copy_generic_opt_arg_list_item: CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' OptInherit OptFirstPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace - OptDistributedBy OptSecondPartitionSpec + OptDistributedBy OptSecondPartitionSpec OptTagOptList { CreateStmt *n = makeNode(CreateStmt); $4->relpersistence = $2; @@ -4804,6 +5007,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $13; n->if_not_exists = false; n->distributedBy = (DistributedBy *) $14; + n->tags = $16; n->relKind = RELKIND_RELATION; n->accessMethod = greenplumLegacyAOoptions(n->accessMethod, &n->options); @@ -4813,7 +5017,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name '(' OptTableElementList ')' OptInherit OptFirstPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace - OptDistributedBy OptSecondPartitionSpec + OptDistributedBy OptSecondPartitionSpec OptTagOptList { CreateStmt *n = makeNode(CreateStmt); $7->relpersistence = $2; @@ -4834,6 +5038,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $16; n->if_not_exists = true; n->distributedBy = (DistributedBy *) $17; + n->tags = $19; n->relKind = RELKIND_RELATION; n->accessMethod = greenplumLegacyAOoptions(n->accessMethod, &n->options); @@ -4843,7 +5048,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' | CREATE OptTemp TABLE qualified_name OF any_name OptTypedTableElementList OptFirstPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace - OptDistributedBy OptSecondPartitionSpec + OptDistributedBy OptSecondPartitionSpec OptTagOptList { CreateStmt *n = makeNode(CreateStmt); $4->relpersistence = $2; @@ -4865,6 +5070,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $12; n->if_not_exists = false; n->distributedBy = (DistributedBy *) $13; + n->tags = $15; n->relKind = RELKIND_RELATION; n->accessMethod = greenplumLegacyAOoptions(n->accessMethod, &n->options); @@ -4874,7 +5080,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name OF any_name OptTypedTableElementList OptFirstPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace - OptDistributedBy OptSecondPartitionSpec + OptDistributedBy OptSecondPartitionSpec OptTagOptList { CreateStmt *n = makeNode(CreateStmt); $7->relpersistence = $2; @@ -4896,6 +5102,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $15; n->if_not_exists = true; n->distributedBy = (DistributedBy *) $16; + n->tags = $18; n->relKind = RELKIND_RELATION; n->accessMethod = greenplumLegacyAOoptions(n->accessMethod, &n->options); @@ -4905,7 +5112,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' | CREATE OptTemp TABLE qualified_name PARTITION OF qualified_name OptTypedTableElementList PartitionBoundSpec OptFirstPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace - OptSecondPartitionSpec + OptSecondPartitionSpec OptTagOptList { CreateStmt *n = makeNode(CreateStmt); $4->relpersistence = $2; @@ -4927,6 +5134,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $14; n->if_not_exists = false; n->distributedBy = NULL; + n->tags = $16; n->relKind = RELKIND_RELATION; n->accessMethod = greenplumLegacyAOoptions(n->accessMethod, &n->options); @@ -4936,7 +5144,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name PARTITION OF qualified_name OptTypedTableElementList PartitionBoundSpec OptFirstPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace - OptSecondPartitionSpec + OptSecondPartitionSpec OptTagOptList { CreateStmt *n = makeNode(CreateStmt); $7->relpersistence = $2; @@ -4958,6 +5166,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $17; n->if_not_exists = true; n->distributedBy = NULL; + n->tags = $19; n->relKind = RELKIND_RELATION; n->accessMethod = greenplumLegacyAOoptions(n->accessMethod, &n->options); @@ -6503,7 +6712,7 @@ opt_with_data: *****************************************************************************/ CreateExternalStmt: CREATE OptWritable EXTERNAL OptWeb OptTemp TABLE qualified_name '(' OptExtTableElementList ')' - ExtTypedesc FORMAT Sconst format_opt ext_options_opt ext_opt_encoding_list ExtSingleRowErrorHandling OptDistributedBy + ExtTypedesc FORMAT Sconst format_opt ext_options_opt ext_opt_encoding_list ExtSingleRowErrorHandling OptDistributedBy OptTagOptList { CreateExternalStmt *n = makeNode(CreateExternalStmt); n->iswritable = $2; @@ -6518,6 +6727,7 @@ CreateExternalStmt: CREATE OptWritable EXTERNAL OptWeb OptTemp TABLE qualified_n n->encoding = $16; n->sreh = $17; n->distributedBy = (DistributedBy *) $18; + n->tags = $19; /* various syntax checks for EXECUTE external table */ if(((ExtTableTypeDesc *) n->exttypedesc)->exttabletype == EXTTBL_TYPE_EXECUTE) @@ -6974,7 +7184,7 @@ RefreshMatViewStmt: *****************************************************************************/ CreateSeqStmt: - CREATE OptTemp SEQUENCE qualified_name OptSeqOptList + CREATE OptTemp SEQUENCE qualified_name OptSeqOptList OptTagOptList { CreateSeqStmt *n = makeNode(CreateSeqStmt); $4->relpersistence = $2; @@ -6982,9 +7192,10 @@ CreateSeqStmt: n->options = $5; n->ownerId = InvalidOid; n->if_not_exists = false; + n->tags = $6; $$ = (Node *)n; } - | CREATE OptTemp SEQUENCE IF_P NOT EXISTS qualified_name OptSeqOptList + | CREATE OptTemp SEQUENCE IF_P NOT EXISTS qualified_name OptSeqOptList OptTagOptList { CreateSeqStmt *n = makeNode(CreateSeqStmt); $7->relpersistence = $2; @@ -6992,6 +7203,7 @@ CreateSeqStmt: n->options = $8; n->ownerId = InvalidOid; n->if_not_exists = true; + n->tags = $9; $$ = (Node *)n; } ; @@ -7185,7 +7397,7 @@ opt_procedural: * *****************************************************************************/ -CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst opt_reloptions OptServer OptFileHandler +CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst opt_reloptions OptServer OptFileHandler OptTagOptList { CreateTableSpaceStmt *n = makeNode(CreateTableSpaceStmt); List *fileHandler_list; @@ -7216,6 +7428,7 @@ CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst errmsg("invalid list syntax for \"handler\""), parser_errposition(@9))); } + n->tags = $10; $$ = (Node *) n; } @@ -7902,7 +8115,7 @@ DropStorageServerStmt: CreateForeignTableStmt: CREATE FOREIGN TABLE qualified_name '(' OptTableElementList ')' - OptInherit SERVER name create_generic_options OptDistributedBy + OptInherit SERVER name create_generic_options OptDistributedBy OptTagOptList { CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); $4->relpersistence = RELPERSISTENCE_PERMANENT; @@ -7919,6 +8132,7 @@ CreateForeignTableStmt: n->servername = $10; n->options = $11; n->distributedBy = (DistributedBy *) $12; + n->base.tags = $13; if (strcmp(n->servername, GP_EXTTABLE_SERVER_NAME) != 0 && n->distributedBy) { ereport(ERROR, @@ -7929,7 +8143,7 @@ CreateForeignTableStmt: } | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name '(' OptTableElementList ')' - OptInherit SERVER name create_generic_options + OptInherit SERVER name create_generic_options OptTagOptList { CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); $7->relpersistence = RELPERSISTENCE_PERMANENT; @@ -7945,11 +8159,12 @@ CreateForeignTableStmt: /* FDW-specific data */ n->servername = $13; n->options = $14; + n->base.tags = $15; $$ = (Node *) n; } | CREATE FOREIGN TABLE qualified_name PARTITION OF qualified_name OptTypedTableElementList PartitionBoundSpec - SERVER name create_generic_options + SERVER name create_generic_options OptTagOptList { CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); $4->relpersistence = RELPERSISTENCE_PERMANENT; @@ -7966,11 +8181,12 @@ CreateForeignTableStmt: /* FDW-specific data */ n->servername = $11; n->options = $12; + n->base.tags = $13; $$ = (Node *) n; } | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name PARTITION OF qualified_name OptTypedTableElementList PartitionBoundSpec - SERVER name create_generic_options + SERVER name create_generic_options OptTagOptList { CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); $7->relpersistence = RELPERSISTENCE_PERMANENT; @@ -7987,6 +8203,7 @@ CreateForeignTableStmt: /* FDW-specific data */ n->servername = $14; n->options = $15; + n->base.tags = $16; $$ = (Node *) n; } ; @@ -8197,7 +8414,7 @@ AlterStorageUserMappingStmt: CreateDirectoryTableStmt: CREATE DIRECTORY TABLE qualified_name - table_access_method_clause OptTableSpace OptDistributedBy + table_access_method_clause OptTableSpace OptDistributedBy OptTagOptList { CreateDirectoryTableStmt *n = makeNode(CreateDirectoryTableStmt); $4->relpersistence = RELPERSISTENCE_PERMANENT; @@ -8217,12 +8434,13 @@ CreateDirectoryTableStmt: errmsg("Create directory table is not allowed to set distributed by."), parser_errposition(@7))); n->base.relKind = RELKIND_DIRECTORY_TABLE; + n->base.tags = $8; n->tablespacename = $6; $$ = (Node *) n; } | CREATE DIRECTORY TABLE IF_P NOT EXISTS qualified_name - table_access_method_clause OptTableSpace OptDistributedBy + table_access_method_clause OptTableSpace OptDistributedBy OptTagOptList { CreateDirectoryTableStmt *n = makeNode(CreateDirectoryTableStmt); $7->relpersistence = RELPERSISTENCE_PERMANENT; @@ -8242,12 +8460,42 @@ CreateDirectoryTableStmt: errmsg("Create directory table is not allowed to set distributed by."), parser_errposition(@10))); n->base.relKind = RELKIND_DIRECTORY_TABLE; + n->base.tags = $11; n->tablespacename = $9; $$ = (Node *) n; } ; +/***************************************************************************** + * + * QUERY: + * ALTER DIRECTORY TABLE relname TAG (tagname = tagvalue, ...) + * ALTER DIRECTORY TABLE relname UNSET TAG (tagname_list) + * + *****************************************************************************/ + +AlterDirectoryTableStmt: + ALTER DIRECTORY TABLE qualified_name TAG '(' TagOptList ')' + { + AlterDirectoryTableStmt *n = makeNode(AlterDirectoryTableStmt); + n->relation = $4; + n->tags = $7; + + $$ = (Node *)n; + } + | ALTER DIRECTORY TABLE qualified_name UNSET_P TAG '(' name_list ')' + { + AlterDirectoryTableStmt *n = makeNode(AlterDirectoryTableStmt); + n->relation = $4; + n->tags = $8; + n->unsettag = true; + + $$ = (Node *)n; + } + ; + + /***************************************************************************** * * QUERIES: @@ -9626,6 +9874,14 @@ CommentStmt: n->comment = $10; $$ = (Node *) n; } + | COMMENT ON TAG name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_TAG; + n->object = (Node *) makeString($4); + n->comment = $6; + $$ = (Node *) n; + } ; comment_text: @@ -10381,7 +10637,7 @@ defacl_privilege_target: IndexStmt: CREATE opt_unique INDEX opt_concurrently opt_index_name ON relation_expr access_method_clause '(' index_params ')' - opt_include opt_reloptions OptTableSpace where_clause + opt_include opt_reloptions OptTableSpace where_clause OptTagOptList { IndexStmt *n = makeNode(IndexStmt); n->unique = $2; @@ -10407,12 +10663,13 @@ IndexStmt: CREATE opt_unique INDEX opt_concurrently opt_index_name n->transformed = false; n->if_not_exists = false; n->reset_default_tblspc = false; + n->tags = $16; $$ = (Node *)n; } | CREATE opt_unique INDEX opt_concurrently IF_P NOT EXISTS name ON relation_expr access_method_clause '(' index_params ')' - opt_include opt_reloptions OptTableSpace where_clause + opt_include opt_reloptions OptTableSpace where_clause OptTagOptList { IndexStmt *n = makeNode(IndexStmt); n->unique = $2; @@ -10438,6 +10695,7 @@ IndexStmt: CREATE opt_unique INDEX opt_concurrently opt_index_name n->transformed = false; n->if_not_exists = true; n->reset_default_tblspc = false; + n->tags = $19; $$ = (Node *)n; } @@ -11582,6 +11840,21 @@ AlterTblSpcStmt: n->isReset = true; $$ = (Node *)n; } + | ALTER TABLESPACE name TAG '(' TagOptList ')' + { + AlterTableSpaceOptionsStmt *n = makeNode(AlterTableSpaceOptionsStmt); + n->tablespacename = $3; + n->tags = $6; + $$ = (Node *)n; + } + | ALTER TABLESPACE name UNSET_P TAG '(' name_list ')' + { + AlterTableSpaceOptionsStmt *n = makeNode(AlterTableSpaceOptionsStmt); + n->tablespacename = $3; + n->tags = $7; + n->unsettag = true; + $$ = (Node *)n; + } ; /***************************************************************************** @@ -12139,6 +12412,24 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name n->missing_ok = false; $$ = (Node *)n; } + | ALTER TAG name RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_TAG; + n->subname = $3; + n->newname = $6; + n->missing_ok = false; + $$ = (Node *)n; + } + | ALTER TAG IF_P EXISTS name RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_TAG; + n->subname = $5; + n->newname = $8; + n->missing_ok = true; + $$ = (Node *)n; + } ; opt_column: COLUMN @@ -12737,6 +13028,14 @@ AlterOwnerStmt: ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec n->newowner = $6; $$ = (Node *)n; } + | ALTER TAG name OWNER TO RoleSpec + { + AlterOwnerStmt *n = makeNode(AlterOwnerStmt); + n->objectType = OBJECT_TAG; + n->object = (Node *) makeString($3); + n->newowner = $6; + $$ = (Node *)n; + } ; @@ -12790,11 +13089,12 @@ publication_for_tables: * *****************************************************************************/ -CreateWarehouseStmt: CREATE WAREHOUSE name OptWarehouseOptList +CreateWarehouseStmt: CREATE WAREHOUSE name OptWarehouseOptList OptTagOptList { CreateWarehouseStmt *n = makeNode(CreateWarehouseStmt); n->whname = $3; n->options = $4; + n->tags = $5; $$ = (Node *) n; } ; @@ -13286,43 +13586,46 @@ opt_transaction_chain: * *****************************************************************************/ -ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list opt_reloptions +ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list opt_reloptions OptTagOptList AS SelectStmt opt_check_option { ViewStmt *n = makeNode(ViewStmt); n->view = $4; n->view->relpersistence = $2; n->aliases = $5; - n->query = $8; + n->query = $9; n->replace = false; n->options = $6; - n->withCheckOption = $9; + n->withCheckOption = $10; + n->tags = $7; $$ = (Node *) n; } - | CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list opt_reloptions + | CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list opt_reloptions OptTagOptList AS SelectStmt opt_check_option { ViewStmt *n = makeNode(ViewStmt); n->view = $6; n->view->relpersistence = $4; n->aliases = $7; - n->query = $10; + n->query = $11; n->replace = true; n->options = $8; - n->withCheckOption = $11; + n->withCheckOption = $12; + n->tags = $9; $$ = (Node *) n; } - | CREATE OptTemp RECURSIVE VIEW qualified_name '(' columnList ')' opt_reloptions + | CREATE OptTemp RECURSIVE VIEW qualified_name '(' columnList ')' opt_reloptions OptTagOptList AS SelectStmt opt_check_option { ViewStmt *n = makeNode(ViewStmt); n->view = $5; n->view->relpersistence = $2; n->aliases = $7; - n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, $11); + n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, $12); n->replace = false; n->options = $9; - n->withCheckOption = $12; + n->withCheckOption = $13; + n->tags = $10; if (n->withCheckOption != NO_CHECK_OPTION) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -13330,17 +13633,18 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list opt_reloptions parser_errposition(@12))); $$ = (Node *) n; } - | CREATE OR REPLACE OptTemp RECURSIVE VIEW qualified_name '(' columnList ')' opt_reloptions + | CREATE OR REPLACE OptTemp RECURSIVE VIEW qualified_name '(' columnList ')' opt_reloptions OptTagOptList AS SelectStmt opt_check_option { ViewStmt *n = makeNode(ViewStmt); n->view = $7; n->view->relpersistence = $4; n->aliases = $9; - n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, $13); + n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, $14); n->replace = true; n->options = $11; - n->withCheckOption = $14; + n->withCheckOption = $15; + n->tags = $12; if (n->withCheckOption != NO_CHECK_OPTION) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -13380,11 +13684,12 @@ LoadStmt: LOAD file_name *****************************************************************************/ CreatedbStmt: - CREATE DATABASE name opt_with createdb_opt_list + CREATE DATABASE name opt_with createdb_opt_list OptTagOptList { CreatedbStmt *n = makeNode(CreatedbStmt); n->dbname = $3; n->options = $5; + n->tags = $6; $$ = (Node *)n; } ; @@ -13473,6 +13778,21 @@ AlterDatabaseStmt: (Node *)makeString($6), @6)); $$ = (Node *)n; } + | ALTER DATABASE name TAG '(' TagOptList ')' + { + AlterDatabaseStmt *n = makeNode(AlterDatabaseStmt); + n->dbname = $3; + n->tags = $6; + $$ = (Node *)n; + } + | ALTER DATABASE name UNSET_P TAG '(' name_list ')' + { + AlterDatabaseStmt *n = makeNode(AlterDatabaseStmt); + n->dbname = $3; + n->tags = $7; + n->unsettag = true; + $$ = (Node *)n; + } ; AlterDatabaseSetStmt: @@ -18961,6 +19281,7 @@ unreserved_keyword: | ADMIN | AFTER | AGGREGATE + | ALLOWED_VALUES | ALSO | ALTER | ALWAYS @@ -19293,6 +19614,7 @@ unreserved_keyword: | UNLISTEN | UNLOCK_P | UNLOGGED + | UNSET_P | UNTIL | UPDATE | VACUUM @@ -19848,6 +20170,7 @@ bare_label_keyword: | AFTER | AGGREGATE | ALL + | ALLOWED_VALUES | ALSO | ALTER | ALWAYS @@ -20288,6 +20611,7 @@ bare_label_keyword: | UNLISTEN | UNLOCK_P | UNLOGGED + | UNSET_P | UNTIL | UPDATE | USER diff --git a/src/backend/postmaster/loginmonitor.c b/src/backend/postmaster/loginmonitor.c index 466be82e9e7..d5299ff5e29 100644 --- a/src/backend/postmaster/loginmonitor.c +++ b/src/backend/postmaster/loginmonitor.c @@ -572,7 +572,8 @@ LoginMonitorWorkerMain(int argc, char *argv[]) { SetConfigOption("synchronous_commit", "local", PGC_SUSET, PGC_S_OVERRIDE); - if (LoginMonitorShmem->curr_user_name[0] != '\0') { + if (LoginMonitorShmem->curr_user_name[0] != '\0') + { InitPostgres(DB_FOR_COMMON_ACCESS, InvalidOid, NULL, InvalidOid, NULL, false); SetProcessingMode(NormalProcessing); set_ps_display(LoginMonitorShmem->curr_user_name); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 55105efebd0..0fcb3624846 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -59,6 +59,7 @@ #include "commands/subscriptioncmds.h" #include "commands/tablecmds.h" #include "commands/tablespace.h" +#include "commands/tag.h" #include "commands/taskcmds.h" #include "commands/trigger.h" #include "commands/typecmds.h" @@ -173,6 +174,7 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree) case T_AlterPublicationStmt: case T_AlterRoleSetStmt: case T_AlterRoleStmt: + case T_AlterSchemaStmt: case T_AlterSeqStmt: case T_AlterStatsStmt: case T_AlterSubscriptionStmt: @@ -244,16 +246,20 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree) case T_AlterProfileStmt: case T_AlterQueueStmt: case T_AlterResourceGroupStmt: + case T_AlterTagStmt: case T_CreateDirectoryTableStmt: + case T_AlterDirectoryTableStmt: case T_CreateProfileStmt: case T_CreateQueueStmt: case T_CreateResourceGroupStmt: case T_CreateTaskStmt: + case T_CreateTagStmt: case T_AlterTaskStmt: case T_DropTaskStmt: case T_DropProfileStmt: case T_DropQueueStmt: case T_DropResourceGroupStmt: + case T_DropTagStmt: case T_DropWarehouseStmt: case T_CreateExternalStmt: case T_RetrieveStmt: @@ -1010,10 +1016,23 @@ standard_ProcessUtility(PlannedStmt *pstmt, } break; + case T_CreateTagStmt: + CreateTag((CreateTagStmt *) parsetree); + break; + + case T_AlterTagStmt: + AlterTag((AlterTagStmt *) parsetree); + break; + + case T_DropTagStmt: + DropTag((DropTagStmt *) parsetree); + break; + case T_ExplainStmt: ExplainQuery(pstate, (ExplainStmt *) parsetree, params, dest); break; + case T_AlterSystemStmt: PreventInTransactionBlock(isTopLevel, "ALTER SYSTEM"); AlterSystemSetConfigFile((AlterSystemStmt *) parsetree); @@ -1365,6 +1384,15 @@ ProcessUtilitySlow(ParseState *pstate, commandCollected = true; break; + case T_AlterSchemaStmt: + AlterSchemaCommand((AlterSchemaStmt *) parsetree); + /* + * EventTriggerCollectSimpleCommand called by + * CreateSchemaCommand + */ + commandCollected = true; + break; + case T_CreateStmt: case T_CreateForeignTableStmt: case T_CreateDirectoryTableStmt: @@ -1699,6 +1727,54 @@ ProcessUtilitySlow(ParseState *pstate, commandCollected = true; break; + case T_AlterDirectoryTableStmt: + { + AlterDirectoryTableStmt *stmt = (AlterDirectoryTableStmt *) parsetree; + Oid relid; + + /* + * Get relid of the directory table. + */ + relid = RangeVarGetRelidExtended(stmt->relation, + ShareUpdateExclusiveLock, + 0, + NULL, + NULL); + + if (stmt->tags) + { + if (!stmt->unsettag) + { + AlterTagDescriptions(stmt->tags, + MyDatabaseId, + RelationRelationId, + relid, + stmt->relation->relname); + } + + if (stmt->unsettag) + { + UnsetTagDescriptions(stmt->tags, + MyDatabaseId, + RelationRelationId, + relid, + stmt->relation->relname); + } + + } + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_CANCEL_ON_ERROR | + DF_WITH_SNAPSHOT | + DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + } + break; + case T_AlterDomainStmt: { AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree; @@ -2859,6 +2935,9 @@ AlterObjectTypeCommandTag(ObjectType objtype) case OBJECT_TABLESPACE: tag = CMDTAG_ALTER_TABLESPACE; break; + case OBJECT_TAG: + tag = CMDTAG_ALTER_TAG; + break; case OBJECT_TRIGGER: tag = CMDTAG_ALTER_TRIGGER; break; @@ -3037,6 +3116,10 @@ CreateCommandTag(Node *parsetree) tag = CMDTAG_CREATE_SCHEMA; break; + case T_AlterSchemaStmt: + tag = CMDTAG_ALTER_SCHEMA; + break; + case T_CreateStmt: tag = CMDTAG_CREATE_TABLE; break; @@ -3057,6 +3140,18 @@ CreateCommandTag(Node *parsetree) tag = CMDTAG_ALTER_TABLESPACE; break; + case T_CreateTagStmt: + tag = CMDTAG_CREATE_TAG; + break; + + case T_AlterTagStmt: + tag = CMDTAG_ALTER_TAG; + break; + + case T_DropTagStmt: + tag = CMDTAG_DROP_TAG; + break; + case T_CreateExtensionStmt: tag = CMDTAG_CREATE_EXTENSION; break; @@ -3133,6 +3228,10 @@ CreateCommandTag(Node *parsetree) tag = CMDTAG_CREATE_DIRECTORY_TABLE; break; + case T_AlterDirectoryTableStmt: + tag = CMDTAG_ALTER_DIRECTORY_TABLE; + break; + case T_DropStmt: switch (((DropStmt *) parsetree)->removeType) { @@ -3169,6 +3268,9 @@ CreateCommandTag(Node *parsetree) case OBJECT_TABLESPACE: tag = CMDTAG_DROP_TABLESPACE; break; + case OBJECT_TAG: + tag = CMDTAG_DROP_TAG; + break; case OBJECT_EXTPROTOCOL: tag = CMDTAG_DROP_PROTOCOL; break; @@ -3956,6 +4058,7 @@ GetCommandLogLevel(Node *parsetree) break; case T_CreateSchemaStmt: + case T_AlterSchemaStmt: lev = LOGSTMT_DDL; break; @@ -3995,6 +4098,7 @@ GetCommandLogLevel(Node *parsetree) case T_DropStorageUserMappingStmt: case T_ImportForeignSchemaStmt: case T_CreateDirectoryTableStmt: + case T_AlterDirectoryTableStmt: lev = LOGSTMT_DDL; break; diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 547231c2747..0db5f5d433b 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -71,6 +71,8 @@ #include "catalog/pg_subscription.h" #include "catalog/pg_subscription_rel.h" #include "catalog/pg_tablespace.h" +#include "catalog/pg_tag.h" +#include "catalog/pg_tag_description.h" #include "catalog/pg_transform.h" #include "catalog/pg_ts_config.h" #include "catalog/pg_ts_config_map.h" @@ -955,6 +957,39 @@ static const struct cachedesc cacheinfo[] = { }, 4 }, + {TagRelationId, /* TAGNAME */ + TagNameIndexId, + 1, + { + Anum_pg_tag_tagname, + 0, + 0, + 0, + }, + 16 + }, + {TagRelationId, /* TAGOID */ + TagOidIndexId, + 1, + { + Anum_pg_tag_oid, + 0, + 0, + 0, + }, + 16 + }, + {TagDescriptionRelationId, /* TAGDESCRIPTION */ + TagDescriptionIndexId, + 4, + { + Anum_pg_tag_description_tddatabaseid, + Anum_pg_tag_description_tdclassid, + Anum_pg_tag_description_tdobjid, + Anum_pg_tag_description_tagid, + }, + 16 + }, {TransformRelationId, /* TRFOID */ TransformOidIndexId, 1, diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 911374e2796..a36845a6539 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -47,6 +47,7 @@ static void dumpProfiles(PGconn *conn); static void dumpPasswordHistory(PGconn *conn); static void dropTablespaces(PGconn *conn); static void dumpTablespaces(PGconn *conn); +static void dumpTags(PGconn *conn); static void dropDBs(PGconn *conn); static void dumpUserConfig(PGconn *conn, const char *username); static void dumpDatabases(PGconn *conn); @@ -664,6 +665,9 @@ main(int argc, char *argv[]) /* Dump role profile */ dumpProfiles(conn); + /* Dump tags */ + dumpTags(conn); + /* Dump roles (users) */ dumpRoles(conn); @@ -1876,6 +1880,65 @@ dumpTablespaces(PGconn *conn) fprintf(OPF, "\n\n"); } +/* + * Dump tags. + */ +static void +dumpTags(PGconn *conn) +{ + PGresult *res; + int i; + + if (server_version < 140000) + return; + + res = executeQuery(conn, "SELECT oid, tagname, " + "pg_catalog.pg_get_userbyid(tagowner) AS tagowner, " + "array_to_string(allowed_values, ', '), " + "pg_catalog.shobj_description(oid, 'pg_tag') " + "FROM pg_catalog.pg_tag " + "ORDER BY 1"); + + if (PQntuples(res) > 0) + fprintf(OPF, "--\n-- Tags\n--\n\n"); + + for (i = 0; i < PQntuples(res); i++) + { + PQExpBuffer buf = createPQExpBuffer(); + Oid tagid = atooid(PQgetvalue(res, i, 0)); + char *tagname = PQgetvalue(res, i, 1); + char *tagowner = PQgetvalue(res, i, 2); + char *allowed_values = PQgetvalue(res, i, 3); + char *tagcomment = PQgetvalue(res, i, 4); + + appendPQExpBuffer(buf, "CREATE TAG %s", tagname); + + if (allowed_values && allowed_values[0] != '\0') + appendPQExpBuffer(buf, " ALLOWED_VALUES %s;\n ", allowed_values); + + appendPQExpBuffer(buf, "ALTER TAG %s OWNER TO %s;\n", + tagname, tagowner); + + if (!no_comments && tagcomment && tagcomment[0] != '\0') + { + appendPQExpBuffer(buf, "COMMENT ON TAG %s IS ", tagname); + appendStringLiteralConn(buf, tagcomment, conn); + appendPQExpBufferStr(buf, ";\n"); + } + + if (!no_security_labels && server_version >= 140000) + buildShSecLabels(conn, "pg_tag", tagid, + "TAG", tagname, + buf); + + fprintf(OPF, "%s", buf->data); + + destroyPQExpBuffer(buf); + } + + PQclear(res); + fprintf(OPF, "\n\n"); +} /* * Dump commands to drop each database. diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 9a015481166..64929caf223 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -761,6 +761,10 @@ static const SchemaQuery Query_for_list_of_collations = { "SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\ " WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'" +#define Query_for_list_of_tags \ +"SELECT pg_catalog.quote_ident(tagname) FROM pg_catalog.pg_tag " \ +" WHERE substring(pg_catalog.quote_ident(tagname),1,%d)='%s'" + #define Query_for_list_of_encodings \ " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\ " FROM pg_catalog.pg_conversion "\ @@ -1150,6 +1154,7 @@ static const pgsql_thing_t words_after_create[] = { {"SYSTEM", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP}, {"TABLE", NULL, NULL, &Query_for_list_of_tables}, {"TABLESPACE", Query_for_list_of_tablespaces}, + {"TAG", Query_for_list_of_tags}, {"TASK", Query_for_list_of_tasks}, {"TEMP", NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMP TABLE * ... */ @@ -1709,6 +1714,19 @@ psql_completion(const char *text, int start, int end) else COMPLETE_WITH_FUNCTION_ARG(prev2_wd); } + /* ALTER TAG (...) */ + else if (Matches("ALTER", "TAG")) + { + COMPLETE_WITH("IF EXISTS"); + } + else if (Matches("ALTER", "TAG", "IF EXISTS", MatchAny)) + { + COMPLETE_WITH("OWNER TO", "RENAME TO", "UNSET ALLOWED_VALUES", "ADD ALLOWED_VLAUES", "DROP ALLOWED_VLAUES"); + } + else if (Matches("ALTER", "TAG", MatchAny)) + { + COMPLETE_WITH("OWNER TO", "RENAME TO", "UNSET ALLOWED_VALUES", "ADD ALLOWED_VLAUES", "DROP ALLOWED_VLAUES"); + } /* ALTER FUNCTION,PROCEDURE,ROUTINE (...) */ else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny)) { @@ -2457,7 +2475,7 @@ psql_completion(const char *text, int start, int end) "COLUMN", "AGGREGATE", "FUNCTION", "STORAGE SERVER", "PROCEDURE", "PROFILE", "ROUTINE", "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", - "LARGE OBJECT", "TABLESPACE", "TEXT SEARCH", "ROLE"); + "LARGE OBJECT", "TABLESPACE", "TAG", "TEXT SEARCH", "ROLE"); else if (Matches("COMMENT", "ON", "ACCESS", "METHOD")) COMPLETE_WITH_QUERY(Query_for_list_of_access_methods); else if (Matches("COMMENT", "ON", "FOREIGN")) @@ -2866,6 +2884,14 @@ psql_completion(const char *text, int start, int end) else if (Matches("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny)) COMPLETE_WITH("LOCATION"); +/* CREATE TAG */ + else if (Matches("CREATE", "TAG")) + COMPLETE_WITH("IF NOT EXISTS"); + else if (Matches("CREATE", "TAG", MatchAny)) + COMPLETE_WITH("ALLOWED_VALUES"); + else if (Matches("CREATE", "TAG", "IF NOT EXISTS", MatchAny)) + COMPLETE_WITH("ALLOWED_VALUES"); + /* CREATE TEXT SEARCH */ else if (Matches("CREATE", "TEXT", "SEARCH")) COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE"); diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index cd34fee0ad3..3b57044e512 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -94,6 +94,7 @@ typedef enum SharedDependencyType SHARED_DEPENDENCY_TABLESPACE = 't', SHARED_DEPENDENCY_PROFILE = 'f', SHARED_DEPENDENCY_STORAGE_SERVER = 's', + SHARED_DEPENDENCY_TAG = 'g', SHARED_DEPENDENCY_INVALID = 0 } SharedDependencyType; @@ -151,6 +152,8 @@ typedef enum ObjectClass OCLASS_DIRTABLE, /* pg_directory_table */ OCLASS_STORAGE_SERVER, /* gp_storage_server */ OCLASS_STORAGE_USER_MAPPING, /* gp_storage_user_mapping */ + OCLASS_TAG, /* pg_tag */ + OCLASS_TAG_DESCRIPTION, /* pg_tag_description */ OCLASS_EXTPROTOCOL, /* pg_extprotocol */ OCLASS_MATVIEW_AUX, /* gp_matview_aux */ OCLASS_TASK, /* pg_task */ @@ -301,6 +304,8 @@ extern void changeProfileDependency(Oid roleId, Oid profileId); extern void recordStorageServerDependency(Oid classId, Oid objectId, Oid srvId); +extern void recordTagDependency(Oid classId, Oid objectId, Oid tagId); + /* Custom object class */ struct StringInfoData; struct CustomObjectClass { diff --git a/src/include/catalog/oid_dispatch.h b/src/include/catalog/oid_dispatch.h index 90cc813c6a5..0dbb8532511 100644 --- a/src/include/catalog/oid_dispatch.h +++ b/src/include/catalog/oid_dispatch.h @@ -83,6 +83,10 @@ extern Oid GetNewOidForRelation(Relation relation, Oid indexId, AttrNumber oidco char *relname, Oid relnamespace); extern Oid GetNewOidForResQueue(Relation relation, Oid indexId, AttrNumber oidcolumn, char *rsqname); +extern Oid GetNewOidForTag(Relation relation, Oid indexId, AttrNumber oidcolumn, + char *tagname); +extern Oid GetNewOidForTagDescription(Relation relation, Oid indexId, AttrNumber oidcolumn, + char *objectname, Oid tagId); extern Oid GetNewOidForRewrite(Relation relation, Oid indexId, AttrNumber oidcolumn, Oid ev_class, char *rulename); extern Oid GetNewOidForStatisticExt(Relation relation, Oid indexId, AttrNumber oidcolumn, diff --git a/src/include/catalog/pg_tag.h b/src/include/catalog/pg_tag.h new file mode 100644 index 00000000000..7009b6e5ac7 --- /dev/null +++ b/src/include/catalog/pg_tag.h @@ -0,0 +1,55 @@ +/*------------------------------------------------------------------------- + * + * pg_tag.h + * definition of the "tag" system catalog (pg_tag) + * + * + * Portions Copyright (c) 2024, Hashdata Inc. + * + * src/include/catalog/pg_tag.h + * + * NOTES + * The Catalog.pm module reads this file and derives schema + * information. + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_TAG_H +#define PG_TAG_H + +#include "catalog/genbki.h" +#include "catalog/pg_tag_d.h" +#include "parser/parse_node.h" + +/* ---------------- + * pg_tag definition. cpp turns this into + * typedef struct FormData_pg_tag + * + * If you change the following, make sure you change the structs for + * system attributes in catalog/heap.c also. + * You may need to change catalog/genbki.pl as well. + */ +CATALOG(pg_tag,6461,TagRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(6462,TagRelation_Rowtype_Id) BKI_SCHEMA_MACRO +{ + Oid oid BKI_FORCE_NOT_NULL; /* oid */ + NameData tagname BKI_FORCE_NOT_NULL; /* name of tag */ + Oid tagowner BKI_DEFAULT(POSTGRES) BKI_LOOKUP(pg_authid); /* owner of tag */ +#ifdef CATALOG_VARLEN /* variable-length fields start here */ + text allowed_values[1]; /* per tag allowed values */ +#endif +} FormData_pg_tag; + +/* ---------------- + * Form_pg_tag corresponds to a pointer to a tuple with + * the format of pg_tag relation. + * ---------------- + */ +typedef FormData_pg_tag *Form_pg_tag; + +DECLARE_UNIQUE_INDEX_PKEY(pg_tag_tagname_index, 6463, on pg_tag using btree(tagname name_ops)); +#define TagNameIndexId 6463 +DECLARE_UNIQUE_INDEX(pg_tag_oid_index, 6465, on pg_tag using btree(oid oid_ops)); +#define TagOidIndexId 6465 + +#endif /* PG_TAG_H */ \ No newline at end of file diff --git a/src/include/catalog/pg_tag_description.h b/src/include/catalog/pg_tag_description.h new file mode 100644 index 00000000000..cd957db2d4c --- /dev/null +++ b/src/include/catalog/pg_tag_description.h @@ -0,0 +1,56 @@ +/*------------------------------------------------------------------------- + * + * pg_tag_description.h + * definition of the "tag description" system catalog (pg_tag_description) + * + * + * Portions Copyright (c) 2024, Hashdata Inc. + * + * src/include/catalog/pg_tag_description.h + * + * NOTES + * The Catalog.pm module reads this file and derives schema + * information. + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_TAG_DESCRIPTION_H +#define PG_TAG_DESCRIPTION_H + +#include "catalog/genbki.h" +#include "catalog/pg_tag_description_d.h" +#include "parser/parse_node.h" + +/* ---------------- + * pg_tag_description definition. cpp turns this into + * typedef struct FormData_pg_tag_description + * ---------------- + */ +CATALOG(pg_tag_description,6485,TagDescriptionRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(6486,TagDescriptionRelation_Rowtype_Id) BKI_SCHEMA_MACRO +{ + Oid oid BKI_FORCE_NOT_NULL; /* OID of this tag description */ + Oid tddatabaseid BKI_LOOKUP_OPT(pg_database); /* OID of database containing object */ + Oid tdclassid BKI_LOOKUP_OPT(pg_class); /* OID of table containing object */ + Oid tdobjid; /* OID of object itself */ + Oid tagid BKI_LOOKUP_OPT(pg_tag); /* Oid of tag */ +#ifdef CATALOG_VARLEN /* variable-length fields start here */ + text tagvalue; /* tag value for this object */ +#endif +} FormData_pg_tag_description; + +/* ---------------- + * Form_pg_tag_description corresponds to a pointer to a tuple with + * the format of pg_tag_description relation. + * ---------------- + */ +typedef FormData_pg_tag_description *Form_pg_tag_description; + +DECLARE_UNIQUE_INDEX_PKEY(pg_tag_description_d_c_o_t_index, 6487, on pg_tag_description using btree(tddatabaseid oid_ops, tdclassid oid_ops, tdobjid oid_ops, tagid oid_ops)); +#define TagDescriptionIndexId 6487 +DECLARE_UNIQUE_INDEX(pg_tag_description_oid_index, 6488, on pg_tag_description using btree(oid oid_ops)); +#define TagDescriptionOidIndexId 6488 +DECLARE_INDEX(pg_tag_description_tagidvalue_index, 6489, on pg_tag_description using btree(tagid oid_ops, tagvalue text_ops)); +#define TagDescriptionTagidvalueIndexId 6489 + +#endif /* PG_TAG_DESCRIPTION_H */ \ No newline at end of file diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h index 90aea55605b..297f8431203 100644 --- a/src/include/commands/schemacmds.h +++ b/src/include/commands/schemacmds.h @@ -21,6 +21,7 @@ extern Oid CreateSchemaCommand(CreateSchemaStmt *parsetree, const char *queryString, int stmt_location, int stmt_len); +extern void AlterSchemaCommand(AlterSchemaStmt *stmt); extern void RemoveSchemaById(Oid schemaOid); diff --git a/src/include/commands/tag.h b/src/include/commands/tag.h new file mode 100644 index 00000000000..2e6022d228a --- /dev/null +++ b/src/include/commands/tag.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * + * tag.h + * Tag management commands (create/drop/alter tag). + * + * + * Portions Copyright (c) 2024 Hashdata Inc + * + * src/include/commands/tag.h + * + *------------------------------------------------------------------------- + */ + +#ifndef TAG_H +#define TAG_H +#include "catalog/objectaddress.h" + +extern Oid CreateTag(CreateTagStmt *stmt); +extern ObjectAddress AlterTag(AlterTagStmt *stmt); +extern void DropTag(DropTagStmt *stmt); +extern void AddTagDescriptions(List *tags, Oid databaseid, Oid classid, Oid objid, char *objname); +extern void AlterTagDescriptions(List *tags, Oid databaseid, Oid classid, Oid objid, char *objname); +extern void UnsetTagDescriptions(List *tags, Oid databaseid, Oid classid, Oid objid, char *objname); +extern void DeleteTagDescriptions(Oid databaseid, Oid classid, Oid objid); +extern Oid get_tag_oid(const char *tagname, bool missing_ok); +extern ObjectAddress RenameTag(const char *oldname, const char *newname); +extern char *TagGetNameByOid(Oid tagid, bool missing_ok); + +#endif /* TAG_H */ \ No newline at end of file diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 8496472faa8..65af47ad2af 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -459,6 +459,10 @@ typedef enum NodeTag T_ReindexStmt, T_CheckPointStmt, T_CreateSchemaStmt, + T_AlterSchemaStmt, + T_CreateTagStmt, + T_AlterTagStmt, + T_DropTagStmt, T_AlterDatabaseStmt, T_AlterDatabaseSetStmt, T_AlterRoleSetStmt, @@ -534,6 +538,7 @@ typedef enum NodeTag T_PartitionRangeItem, T_PartitionValuesSpec, T_CreateDirectoryTableStmt, + T_AlterDirectoryTableStmt, T_CreateFileSpaceStmt, T_FileSpaceEntry, T_DropFileSpaceStmt, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 29a2782a662..51229924c67 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1947,6 +1947,7 @@ typedef enum ObjectType OBJECT_TABLE, OBJECT_EXTPROTOCOL, OBJECT_TABLESPACE, + OBJECT_TAG, OBJECT_TRANSFORM, OBJECT_TRIGGER, OBJECT_TSCONFIGURATION, @@ -1993,8 +1994,31 @@ typedef struct CreateSchemaStmt */ bool istemp; /* true for temp schemas (internal only) */ bool pop_search_path; /* true for pop search path only (internal only) */ + List *tags; /* List of tags DefElem nodes */ } CreateSchemaStmt; +typedef struct AlterSchemaStmt +{ + NodeTag type; + char *schemaname; /* the name of the schema to create */ + List *tags; /* List of tags, DelElem or String nodes */ + bool unsettag; /* Whether unset tag */ +} AlterSchemaStmt; + +/* ---------------------- + * Create Tag Statement + * + * NOTE: the allowed_values list contains all the allowed values for this tag. + * ---------------------- + */ +typedef struct CreateTagStmt +{ + NodeTag type; + char *tag_name; /* the name of the tag to create */ + bool missing_ok; /* skip error if table missing */ + List *allowed_values; /* allowed values list for this tag */ +} CreateTagStmt; + typedef enum DropBehavior { DROP_RESTRICT, /* drop fails if any dependent objects */ @@ -2032,6 +2056,16 @@ typedef struct AlterTableStmt bool is_internal; /* GPDB: set for internal generated alter table stmt */ } AlterTableStmt; +typedef struct AlterTagStmt +{ + NodeTag type; + char *tag_name; + int action; + List *tag_values; + bool missing_ok; + bool unset; +} AlterTagStmt; + typedef enum AlterTableType { AT_AddColumn, /* add column */ @@ -2110,6 +2144,8 @@ typedef enum AlterTableType AT_ExpandTable, /* EXPAND DISTRIBUTED */ AT_ExpandPartitionTablePrepare, /* EXPAND PARTITION PREPARE */ AT_ShrinkTable, /* SHRINK DISTRIBUTED */ + AT_SetTags, /* Set tags */ + AT_UnsetTags, /* Unset tags */ /* GPDB: Legacy commands to manipulate partitions */ AT_PartAdd, /* Add */ @@ -2154,6 +2190,9 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */ const char *queryString; GpPolicy *policy; + + List *tags; /* List of tags, DefElem or String nodes */ + bool unsettag; /* Whether unset tag */ } AlterTableCmd; @@ -2474,6 +2513,7 @@ typedef struct CreateStmt /* names chosen for partition indexes */ List *part_idx_oids; List *part_idx_names; + List *tags; /* List of tags DefElem nodes */ } CreateStmt; /* ---------------------- @@ -2510,7 +2550,7 @@ typedef struct CreateExternalStmt List *encoding; /* List (size 1 max) of DefElem nodes for data encoding */ DistributedBy *distributedBy; /* what columns we distribute the data by */ - + List *tags; /* List of tags DefElem nodes */ } CreateExternalStmt; /* ---------------------- @@ -2718,6 +2758,7 @@ typedef struct CreateTableSpaceStmt char *location; List *options; char *filehandler; + List *tags; /* List of tags DefElem nodes */ } CreateTableSpaceStmt; typedef struct DropTableSpaceStmt @@ -2733,6 +2774,8 @@ typedef struct AlterTableSpaceOptionsStmt char *tablespacename; List *options; bool isReset; + List *tags; /* List of tags, DefElem or String nodes */ + bool unsettag; /* Whether unset tag */ } AlterTableSpaceOptionsStmt; typedef struct AlterTableMoveAllStmt @@ -2745,6 +2788,13 @@ typedef struct AlterTableMoveAllStmt bool nowait; } AlterTableMoveAllStmt; +typedef struct DropTagStmt +{ + NodeTag type; + List *tags; + bool missing_ok; +} DropTagStmt; + /* ---------------------- * Create/Alter/Drop Task Statements * ---------------------- @@ -3170,6 +3220,7 @@ typedef struct CreateRoleStmt RoleStmtType stmt_type; /* ROLE/USER/GROUP */ char *role; /* role name */ List *options; /* List of DefElem nodes */ + List *tags; /* List of DefElem tag nodes */ } CreateRoleStmt; typedef struct AlterRoleStmt @@ -3178,6 +3229,8 @@ typedef struct AlterRoleStmt RoleSpec *role; /* role */ List *options; /* List of DefElem nodes */ int action; /* +1 = add members, -1 = drop members */ + List *tags; /* List of DefElem tag nodes */ + bool unsettag; } AlterRoleStmt; typedef struct AlterRoleSetStmt @@ -3244,6 +3297,7 @@ typedef struct CreateSeqStmt Oid ownerId; /* ID of owner, or InvalidOid for default */ bool for_identity; bool if_not_exists; /* just do nothing if it already exists? */ + List *tags; /* List of tags DefElem nodes */ } CreateSeqStmt; typedef struct AlterSeqStmt @@ -3352,6 +3406,14 @@ typedef struct CreateDirectoryTableStmt char *tablespacename; } CreateDirectoryTableStmt; +typedef struct AlterDirectoryTableStmt +{ + NodeTag type; + RangeVar *relation; /* directory table to alter */ + List *tags; /* List of tags, DefElem or String nodes */ + bool unsettag; /* Whether unset tag */ +} AlterDirectoryTableStmt; + /* ---------------------- * DROP Statement, applies to: @@ -3532,6 +3594,7 @@ typedef struct IndexStmt * concurrently build */ Oid indexRelationOid; /* relationOid of index, dispatch to QEs when * concurrently build */ + List *tags; /* List of tags DefElem nodes */ } IndexStmt; /* ---------------------- @@ -3892,6 +3955,7 @@ typedef struct ViewStmt bool replace; /* replace an existing view? */ List *options; /* options from WITH clause */ ViewCheckOption withCheckOption; /* WITH CHECK OPTION */ + List *tags; /* List of tags DefElem nodes */ } ViewStmt; /* ---------------------- @@ -3913,6 +3977,7 @@ typedef struct CreatedbStmt NodeTag type; char *dbname; /* name of database to create */ List *options; /* List of DefElem nodes */ + List *tags; /* List of tags DefElem nodes */ } CreatedbStmt; /* ---------------------- @@ -3924,6 +3989,8 @@ typedef struct AlterDatabaseStmt NodeTag type; char *dbname; /* name of database to alter */ List *options; /* List of DefElem nodes */ + List *tags; /* List of tags, DefElem or String nodes */ + bool unsettag; /* Whether unset tag */ } AlterDatabaseStmt; typedef struct AlterDatabaseSetStmt @@ -4364,6 +4431,7 @@ typedef struct CreateWarehouseStmt NodeTag type; char *whname; List *options; /* List of DefElem nodes */ + List *tags; /* List of tag DefElem nodes */ } CreateWarehouseStmt; typedef struct DropWarehouseStmt diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index ed3551490ee..a0c33bec4c0 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -37,6 +37,7 @@ PG_KEYWORD("admin", ADMIN, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("after", AFTER, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("aggregate", AGGREGATE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("all", ALL, RESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("allowed_values", ALLOWED_VALUES, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("also", ALSO, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("alter", ALTER, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("always", ALWAYS, UNRESERVED_KEYWORD, BARE_LABEL) @@ -510,6 +511,7 @@ PG_KEYWORD("unknown", UNKNOWN, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("unlisten", UNLISTEN, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("unlock", UNLOCK_P, UNRESERVED_KEYWORD, BARE_LABEL) /* GPDB */ PG_KEYWORD("unlogged", UNLOGGED, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("unset", UNSET_P, UNRESERVED_KEYWORD, BARE_LABEL) /* GPDB */ PG_KEYWORD("until", UNTIL, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("update", UPDATE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("user", USER, RESERVED_KEYWORD, BARE_LABEL) diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h index c97011262df..dd63c7659e4 100644 --- a/src/include/tcop/cmdtaglist.h +++ b/src/include/tcop/cmdtaglist.h @@ -68,6 +68,7 @@ PG_CMDTAG(CMDTAG_ALTER_SUBSCRIPTION, "ALTER SUBSCRIPTION", true, false, false) PG_CMDTAG(CMDTAG_ALTER_SYSTEM, "ALTER SYSTEM", false, false, false) PG_CMDTAG(CMDTAG_ALTER_TABLE, "ALTER TABLE", true, true, false) PG_CMDTAG(CMDTAG_ALTER_TABLESPACE, "ALTER TABLESPACE", false, false, false) +PG_CMDTAG(CMDTAG_ALTER_TAG, "ALTER TAG", true, false, false) PG_CMDTAG(CMDTAG_ALTER_TASK, "ALTER TASK", true, false, false) PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION, "ALTER TEXT SEARCH CONFIGURATION", true, false, false) PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY, "ALTER TEXT SEARCH DICTIONARY", true, false, false) @@ -133,6 +134,7 @@ PG_CMDTAG(CMDTAG_CREATE_SUBSCRIPTION, "CREATE SUBSCRIPTION", true, false, false) PG_CMDTAG(CMDTAG_CREATE_TABLE, "CREATE TABLE", true, false, false) PG_CMDTAG(CMDTAG_CREATE_TABLE_AS, "CREATE TABLE AS", true, false, false) PG_CMDTAG(CMDTAG_CREATE_TABLESPACE, "CREATE TABLESPACE", false, false, false) +PG_CMDTAG(CMDTAG_CREATE_TAG, "CREATE TAG", true, false, false) PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_CONFIGURATION, "CREATE TEXT SEARCH CONFIGURATION", true, false, false) PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_DICTIONARY, "CREATE TEXT SEARCH DICTIONARY", true, false, false) PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_PARSER, "CREATE TEXT SEARCH PARSER", true, false, false) @@ -204,6 +206,7 @@ PG_CMDTAG(CMDTAG_DROP_STORAGE_USER_MAPPING, "DROP STORAGE USER MAPPING", true, f PG_CMDTAG(CMDTAG_DROP_SUBSCRIPTION, "DROP SUBSCRIPTION", true, false, false) PG_CMDTAG(CMDTAG_DROP_TABLE, "DROP TABLE", true, false, false) PG_CMDTAG(CMDTAG_DROP_TABLESPACE, "DROP TABLESPACE", false, false, false) +PG_CMDTAG(CMDTAG_DROP_TAG, "DROP TAG", true, false, false) PG_CMDTAG(CMDTAG_DROP_TASK, "DROP TASK", true, false, false) PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_CONFIGURATION, "DROP TEXT SEARCH CONFIGURATION", true, false, false) PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_DICTIONARY, "DROP TEXT SEARCH DICTIONARY", true, false, false) diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index bf47cd0a592..223175099bd 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -318,6 +318,7 @@ extern bool pg_opfamily_ownercheck(Oid opf_oid, Oid roleid); extern bool pg_database_ownercheck(Oid db_oid, Oid roleid); extern bool pg_collation_ownercheck(Oid coll_oid, Oid roleid); extern bool pg_conversion_ownercheck(Oid conv_oid, Oid roleid); +extern bool pg_tag_ownercheck(Oid tag_oid, Oid roleid); extern bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid); extern bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid); extern bool pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid); diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index d1653761f43..0a7f66bd4e4 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -106,6 +106,9 @@ enum SysCacheIdentifier SUBSCRIPTIONOID, SUBSCRIPTIONRELMAP, TABLESPACEOID, + TAGNAME, + TAGOID, + TAGDESCRIPTION, TRFOID, TRFTYPELANG, TSCONFIGMAP, diff --git a/src/test/modules/test_ddl_deparse/test_ddl_deparse.c b/src/test/modules/test_ddl_deparse/test_ddl_deparse.c index 1bae1e54380..849bf7898b5 100644 --- a/src/test/modules/test_ddl_deparse/test_ddl_deparse.c +++ b/src/test/modules/test_ddl_deparse/test_ddl_deparse.c @@ -279,6 +279,12 @@ get_altertable_subcmdtypes(PG_FUNCTION_ARGS) case AT_GenericOptions: strtype = "SET OPTIONS"; break; + case AT_SetTags: + strtype = "SET TAGS"; + break; + case AT_UnsetTags: + strtype = "UNSET TAGS"; + break; default: strtype = "unrecognized"; break; diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out index 8bd8db7e70b..a05cf9aba47 100644 --- a/src/test/regress/expected/misc_sanity.out +++ b/src/test/regress/expected/misc_sanity.out @@ -123,6 +123,8 @@ ORDER BY 1, 2; pg_resqueuecapability | ressetting | text pg_stat_last_operation | stasubtype | text pg_stat_last_shoperation | stasubtype | text + pg_tag | allowed_values | text[] + pg_tag_description | tagvalue | text pg_task | command | text pg_task | database | text pg_task | jobname | text @@ -134,7 +136,7 @@ ORDER BY 1, 2; pg_task_run_history | return_message | text pg_task_run_history | status | text pg_task_run_history | username | text -(31 rows) +(33 rows) -- system catalogs without primary keys -- diff --git a/src/test/regress/expected/oidjoins.out b/src/test/regress/expected/oidjoins.out index 4d6ad39fbb8..0ae8a90e731 100644 --- a/src/test/regress/expected/oidjoins.out +++ b/src/test/regress/expected/oidjoins.out @@ -202,6 +202,10 @@ NOTICE: checking pg_tablespace {spcowner} => pg_authid {oid} NOTICE: checking pg_auth_members {roleid} => pg_authid {oid} NOTICE: checking pg_auth_members {member} => pg_authid {oid} NOTICE: checking pg_auth_members {grantor} => pg_authid {oid} +NOTICE: checking pg_tag {tagowner} => pg_authid {oid} +NOTICE: checking pg_tag_description {tdclassid} => pg_class {oid} +NOTICE: checking pg_tag_description {tddatabaseid} => pg_database {oid} +NOTICE: checking pg_tag_description {tagid} => pg_tag {oid} NOTICE: checking pg_shdepend {dbid} => pg_database {oid} NOTICE: checking pg_shdepend {classid} => pg_class {oid} NOTICE: checking pg_shdepend {refclassid} => pg_class {oid} diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out index ca4b1db5320..2c8d696a0b1 100644 --- a/src/test/regress/expected/sanity_check.out +++ b/src/test/regress/expected/sanity_check.out @@ -174,6 +174,8 @@ pg_statistic_ext_data|t pg_subscription|t pg_subscription_rel|t pg_tablespace|t +pg_tag|t +pg_tag_description|t pg_task|t pg_task_run_history|t pg_transform|t diff --git a/src/test/regress/input/tag.source b/src/test/regress/input/tag.source new file mode 100644 index 00000000000..5a295703ae9 --- /dev/null +++ b/src/test/regress/input/tag.source @@ -0,0 +1,626 @@ +-- Test tag manipulation +\d+ pg_tag; +\d+ pg_tag_description; +SELECT * FROM pg_tag; +SELECT * FROM pg_tag_description; +CREATE DATABASE other_db; + +-- Test create tag +CREATE TAG tag1; +CREATE TAG IF NOT EXISTS tag1; +CREATE TAG IF NOT EXISTS tag2; +CREATE TAG tag2; -- error +CREATE TAG tag3 ALLOWED_VALUES '123'; +CREATE TAG tag3; -- error +CREATE TAG tag4 ALLOWED_VALUES '123', '456', ' '; +CREATE TAG IF NOT EXISTS tag5 ALLOWED_VALUES '123', 'val1'; +CREATE TAG tag6 ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +CREATE TAG tag7 ALLOWED_VALUES 'val1', '123', 'val1'; -- error +CREATE TAG tag8 ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +CREATE TAG tag9 ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300', '301'; + +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- Test Drop tag +DROP TAG tag5; +DROP TAG IF EXISTS tag5; +DROP TAG IF EXISTS tag8; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- Test Alter tag +-- Rename +ALTER TAG tag3 RENAME TO tag3_new; +ALTER TAG IF EXISTS tag4 RENAME TO tag4_new; +ALTER TAG tag3_new RENAME TO tag3; +ALTER TAG tag4_new RENAME TO tag4; + +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- OWNER TO +CREATE USER tag_user; +ALTER TAG tag1 OWNER TO tag_user; +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; +ALTER TAG tag1 OWNER TO gpadmin; +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; +\c other_db +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; +\c postgres + +-- Unset allowed_values +ALTER TAG tag1 UNSET ALLOWED_VALUES; +ALTER TAG tag2 UNSET ALLOWED_VALUES; +ALTER TAG tag3 UNSET ALLOWED_VALUES; + +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- ADD allowed_values +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1'; +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1'; -- error +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val1'; -- error +ALTER TAG tag1 ADD ALLOWED_VALUES 'val2', 'val2'; -- error +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val2', 'val2'; -- error +ALTER TAG tag1 ADD ALLOWED_VALUES 'val2', 'val3'; +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val4', 'val5'; +ALTER TAG tag1 ADD ALLOWED_VALUES '', ''; -- error +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES '', ''; --error +ALTER TAG tag1 ADD ALLOWED_VALUES ' ', ' '; -- error +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES ' '; + +ALTER TAG tag1 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +ALTER TAG tag2 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ALTER TAG IF EXISTS tag2 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; + +ALTER TAG tag3 ADD ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +ALTER TAG IF EXISTS tag3 ADD ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +ALTER TAG tag3 ADD ALLOWED_VALUES 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'; + +ALTER TAG tag4 ADD ALLOWED_VALUES ' '; -- error +ALTER TAG IF EXISTS tag4 ADD ALLOWED_VALUES ' '; -- error +ALTER TAG tag4 ADD ALLOWED_VALUES ''; +ALTER TAG tag4 ADD ALLOWED_VALUES ''; -- error + +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- DROP allowed_values +ALTER TAG tag1 DROP ALLOWED_VALUES 'unknown'; -- error; +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES 'unknown'; -- error; +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ALTER TAG tag1 DROP ALLOWED_VALUES '1'; -- error +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES '1'; -- error +ALTER TAG tag1 DROP ALLOWED_VALUES ''; -- error +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES ''; -- error +ALTER TAG tag1 UNSET ALLOWED_VALUES; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1', 'val2', 'val3'; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- Cleanup +DROP USER tag_user; + +-- Test database with tag +-- Create database +CREATE DATABASE tag_db1 TAG (tag1 = 'novalue'); -- error +CREATE DATABASE tag_db1 TAG (tag1 = 'val1'); +CREATE DATABASE tag_db2 TAG; -- error +CREATE DATABASE tag_db2 TAG (); -- error +CREATE DATABASE tag_db2 TAG (tag1 = ''); -- error +CREATE DATABASE tag_db2 TAG (tag1 = 'val1', tag2 = '10'); +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag2 = '1'); +CREATE DATABASE tag_db4 TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE DATABASE tag_db5 TAG (tag2 = '300', tag4 = ' '); +CREATE DATABASE tag_db6 TAG (tag4 = '', tag4 = ' '); -- error +CREATE DATABASE tag_db6 TAG (tag4 = '', tag4 = ''); -- error +CREATE DATABASE tag_db6 TAG (tag4 = ' ', tag4 = ' '); -- error +CREATE DATABASE tag_db6 TAG (tag4 = ''); +CREATE DATABASE tag_db7 TAG (tag4 = ' '); +CREATE DATABASE tag_db8 TAG (tag3 = ''); -- error +CREATE DATABASE tag_db8 WITH TEMPLATE = template0 TAG (tag1 = 'novalue'); -- error +CREATE DATABASE tag_db8 WITH TEMPLATE = template0 TAG (tag1 = 'val1'); +CREATE DATABASE tag_db9 WITH TEMPLATE = template0; +CREATE DATABASE tag_db10 WITH TEMPLATE = template0 TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); + +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + +DROP TAG tag1; -- error +DROP TAG tag2; -- error +DROP TAG tag3; -- error +DROP TAG tag4; -- error +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +-- Alter Database +ALTER DATABASE tag_db1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER DATABASE tag_db2 TAG (tag2 = '10'); +ALTER DATABASE tag_db3 TAG (tag3 = ''); -- error +ALTER DATABASE tag_db4 UNSET TAG (tag1, tag2); +ALTER DATABASE tag_db4 TAG (tag1 = 'val3', tag4 = ''); +ALTER DATABASE tag_db5 TAG (tag4 = '', tag4 = ' '); +ALTER DATABASE tag_db6 TAG (tag4 = ' '); +ALTER DATABASE tag_db7 TAG (tag1 = 'val2', tag2 = '3'); +ALTER DATABASE tag_db7 UNSET TAG (tag1); +ALTER DATABASE tag_db8 TAG (tag4 = '123', tag4 = '123'); +ALTER DATABASE tag_db9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +ALTER DATABASE tag_db9 TAG (tag4 = '123'); + +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + +-- Drop Database +DROP DATABASE tag_db1; +DROP DATABASE tag_db2; +DROP DATABASE tag_db3; +DROP DATABASE tag_db4; +DROP DATABASE tag_db5; +DROP DATABASE tag_db6; +DROP DATABASE tag_db7; +DROP DATABASE tag_db8; +DROP DATABASE tag_db9; +DROP DATABASE tag_db10; + +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + + +-- Test user with tag +-- Create User +CREATE USER tag_user1 TAG (tag1 = 'novalue'); -- error +CREATE USER tag_user1 TAG (tag1 = 'val1'); +CREATE USER tag_user2 TAG; -- error +CREATE USER tag_user2 TAG (); -- error +CREATE USER tag_user2 TAG (tag1 = ''); -- error +CREATE USER tag_user2 TAG (tag1 = 'val1', tag2 = '10'); +CREATE USER tag_user3 TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +CREATE USER tag_user3 TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +CREATE USER tag_user3 TAG (tag1 = 'val1', tag2 = '1'); +CREATE USER tag_user4 TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE USER tag_user5 TAG (tag2 = '300', tag4 = ' '); +CREATE USER tag_user6 TAG (tag4 = '', tag4 = ''); -- error +CREATE USER tag_user6 TAG (tag4 = ' ', tag4 = ' '); -- error +CREATE USER tag_user6 TAG (tag4 = ''); +CREATE USER tag_user7 CONNECTION LIMIT 10 TAG (tag4 = ' '); +CREATE USER tag_user8 TAG (tag3 = ''); -- error +CREATE USER tag_user8 superuser TAG (tag1 = 'novalue'); -- error +CREATE USER tag_user8 superuser TAG (tag1 = 'val1'); +CREATE USER tag_user9 superuser; +CREATE USER tag_user10 superuser TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); + +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + +DROP TAG tag1; -- error +DROP TAG tag2; -- error +DROP TAG tag3; -- error +DROP TAG tag4; -- error +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +-- Alter User +ALTER USER tag_user1 CONNECTION LIMIT 3 TAG (tag1 = 'val1', tag1 = 'val1'); -- error +ALTER USER tag_user1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER USER tag_user2 TAG (tag2 = '10'); +ALTER USER tag_user3 TAG (tag3 = ''); -- error +ALTER USER tag_user4 UNSET TAG (tag1, tag2); +ALTER USER tag_user4 TAG (tag1 = 'val3', tag4 = ''); +ALTER USER tag_user5 TAG (tag4 = '', tag4 = ' '); +ALTER USER tag_user6 TAG (tag4 = ' '); +ALTER USER tag_user7 TAG (tag1 = 'val2', tag2 = '3'); +ALTER USER tag_user7 UNSET TAG (tag1); +ALTER USER tag_user8 TAG (tag4 = '123', tag4 = '123'); +ALTER USER tag_user9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +ALTER USER tag_user9 TAG (tag4 = '123'); + +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + +-- Drop User +DROP USER tag_user1; +DROP USER tag_user2; +DROP USER tag_user3; +DROP USER tag_user4; +DROP USER tag_user5; +DROP USER tag_user6; +DROP USER tag_user7; +DROP USER tag_user8; +DROP USER tag_user9; +DROP USER tag_user10; + +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + + +-- Test tablespace with tag +-- Create tablespace +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'test'); -- error +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'val1', tag2 = '301'); -- error +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'val1', tag2 = '2'); + +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + +-- Alter tablespace +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag2 = '10'); -- error +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag3 = ''); -- error +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag4 = '', tag1 = 'val1'); -- error +ALTER TABLESPACE tag_tablespace TAG (tag4 = '', tag1 = 'val1'); +ALTER TABLESPACE tag_tablespace UNSET TAG (tag1, tag2); +ALTER TABLESPACE tag_tablespace UNSET TAG (tag2); +ALTER TABLESPACE tag_tablespace TAG (tag1 = 'val2', tag1 = 'val3'); + +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + +DROP TAG tag1; -- error +DROP TAG tag2; -- error +DROP TAG tag4; -- error +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +-- Drop tablespace +DROP TABLESPACE tag_tablespace; + +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + + +-- Test Schema with Tag +-- Create Schema +CREATE SCHEMA tag_schema1 TAG (tag1 = 'val1'); -- error +CREATE SCHEMA tag_schema1 WITH TAG (tag1 = 'novalue'); -- error +CREATE SCHEMA tag_schema1 WITH TAG (tag1 = 'val1'); +CREATE SCHEMA tag_schema2 WITH TAG; -- error +CREATE SCHEMA tag_schema2 WITH TAG (); -- error +CREATE SCHEMA tag_schema2 WITH TAG (tag1 = ''); -- error +CREATE SCHEMA tag_schema2 WITH TAG (tag1 = 'val1', tag2 = '10'); +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag2 = '1'); +CREATE SCHEMA tag_schema4 WITH TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE SCHEMA tag_schema5 WITH TAG (tag2 = '300', tag4 = ' '); +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = '', tag4 = ''); -- error +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = ' ', tag4 = ' '); -- error +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = ''); +CREATE SCHEMA tag_schema7 WITH TAG (tag4 = ' '); +CREATE SCHEMA tag_schema8 WITH TAG (tag3 = ''); -- error +CREATE SCHEMA tag_schema8 WITH TAG (tag1 = 'novalue'); -- error +CREATE SCHEMA tag_schema8 WITH TAG (tag1 = 'val1'); +CREATE SCHEMA tag_schema9; +CREATE SCHEMA tag_schema10 WITH TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); + +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + +DROP TAG tag1; -- error +DROP TAG tag2; -- error +DROP TAG tag3; -- error +DROP TAG tag4; -- error +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +-- Alter Schema +ALTER SCHEMA tag_schema1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER SCHEMA tag_schema2 TAG (tag2 = '10'); +ALTER SCHEMA tag_schema3 TAG (tag3 = ''); -- error +ALTER SCHEMA tag_schema4 UNSET TAG (tag1, tag2); +ALTER SCHEMA tag_schema4 TAG (tag1 = 'val3', tag4 = ''); +ALTER SCHEMA tag_schema5 TAG (tag4 = '', tag4 = ' '); +ALTER SCHEMA tag_schema6 TAG (tag4 = ' '); +ALTER SCHEMA tag_schema7 TAG (tag1 = 'val2', tag2 = '3'); +ALTER SCHEMA tag_schema7 UNSET TAG (tag1); +ALTER SCHEMA tag_schema8 TAG (tag4 = '123', tag4 = '123'); +ALTER SCHEMA tag_schema9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +ALTER SCHEMA tag_schema9 TAG (tag4 = '123'); + +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + +-- Drop Schema +DROP SCHEMA tag_schema1; +DROP SCHEMA tag_schema2; +DROP SCHEMA tag_schema3; +DROP SCHEMA tag_schema4; +DROP SCHEMA tag_schema5; +DROP SCHEMA tag_schema6; +DROP SCHEMA tag_schema7; +DROP SCHEMA tag_schema8; +DROP SCHEMA tag_schema9; +DROP SCHEMA tag_schema10; + +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + + +-- Test Table with Tag +-- Create Table +CREATE TABLE tag_table1(a int, b varchar) TAG (tag1 = 'novalue'); -- error +CREATE TEMP TABLE tag_table1(a int, b varchar) TAG (tag1 = 'val1'); +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG; -- error +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG (); -- error +CREATE TABLE tag_table2(a int, b varchar) TAG (tag1 = ''); -- error +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG (tag1 = 'val1', tag2 = '10'); +CREATE TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +CREATE TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +CREATE TEMP TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag2 = '1'); +CREATE TABLE tag_table4(a int, b varchar) TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE TABLE tag_table5(a int, b varchar) TAG (tag2 = '300', tag4 = ' '); +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = '', tag4 = ''); -- error +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = ' ', tag4 = ' '); -- error +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = ''); +CREATE TABLE tag_table7(a int, b varchar) TAG (tag4 = ' '); +CREATE TABLE tag_table8(a int, b varchar) TAG (tag3 = ''); -- error +CREATE TABLE tag_table8(a int, b varchar) TAG (tag1 = 'novalue'); -- error +CREATE TABLE tag_table8(a int, b varchar) TAG (tag1 = 'val1'); +CREATE TABLE tag_table9(a int, b varchar); +CREATE TABLE tag_table10(a int, b varchar) TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); + +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + +DROP TAG tag1; -- error +DROP TAG tag2; -- error +DROP TAG tag3; -- error +DROP TAG tag4; -- error +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +-- Alter Table +ALTER TABLE tag_table1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER TABLE tag_table2 TAG (tag2 = '10'); +ALTER TABLE tag_table3 TAG (tag3 = ''); +ALTER TABLE tag_table4 UNSET TAG (tag1, tag2); +ALTER TABLE tag_table4 TAG (tag1 = 'val3', tag4 = ''); +ALTER TABLE tag_table5 TAG (tag4 = '', tag4 = ' '); +ALTER TABLE tag_table6 TAG (tag4 = ' '); +ALTER TABLE tag_table7 TAG (tag1 = 'val2', tag2 = '3'); +ALTER TABLE tag_table7 UNSET TAG (tag1); +ALTER TABLE tag_table8 TAG (tag4 = '123', tag4 = '123'); +ALTER TABLE tag_table9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +ALTER TABLE tag_table9 TAG (tag4 = '123'); + +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + +-- Drop Table +DROP TABLE tag_table1; +DROP TABLE tag_table2; +DROP TABLE tag_table3; +DROP TABLE tag_table4; +DROP TABLE tag_table5; +DROP TABLE tag_table6; +DROP TABLE tag_table7; +DROP TABLE tag_table8; +DROP TABLE tag_table9; +DROP TABLE tag_table10; + +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + + +-- Cleanup +DROP TAG tag1; +DROP TAG tag2; +DROP TAG tag3; +DROP TAG tag4; +DROP DATABASE other_db; diff --git a/src/test/regress/output/directory_table.source b/src/test/regress/output/directory_table.source index d407c797710..2ec788753c5 100644 --- a/src/test/regress/output/directory_table.source +++ b/src/test/regress/output/directory_table.source @@ -1379,35 +1379,35 @@ SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; ALTER TABLE dir_table1 ADD COLUMN a int; -- fail ERROR: "dir_table1" is not a table, composite type, or foreign table ALTER DIRECTORY TABLE dir_table1 ADD COLUMN a int; -- fail -ERROR: syntax error at or near "DIRECTORY" +ERROR: syntax error at or near "ADD" LINE 1: ALTER DIRECTORY TABLE dir_table1 ADD COLUMN a int; - ^ + ^ ALTER TABLE dir_table2 DROP COLUMN relative_path; -- fail ERROR: "dir_table2" is not a table, composite type, or foreign table ALTER DIRECTORY TABLE dir_table2 DROP COLUMN relative_path; -- fail -ERROR: syntax error at or near "DIRECTORY" +ERROR: syntax error at or near "DROP" LINE 1: ALTER DIRECTORY TABLE dir_table2 DROP COLUMN relative_path; - ^ + ^ ALTER TABLE dir_table1 RENAME TO dir_table_new; -- fail ERROR: Rename directory table is not allowed. ALTER DIRECTORY TABLE dir_table1 RENAME TO dir_table_new; -- fail -ERROR: syntax error at or near "DIRECTORY" +ERROR: syntax error at or near "RENAME" LINE 1: ALTER DIRECTORY TABLE dir_table1 RENAME TO dir_table_new; - ^ + ^ ALTER TABLE dir_table2 ADD CONSTRAINT dirtable_constraint UNIQUE (tag); -- fail ERROR: "dir_table2" is not a table or foreign table ALTER DIRECTORY TABLE dir_table2 ADD CONSTRAINT dirtable_constraint UNIQUE (tag); -- fail -ERROR: syntax error at or near "DIRECTORY" +ERROR: syntax error at or near "ADD" LINE 1: ALTER DIRECTORY TABLE dir_table2 ADD CONSTRAINT dirtable_con... - ^ + ^ ALTER TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_pkey; -- fail ERROR: syntax error at or near "CONSTRAINT" LINE 1: ALTER TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_... ^ ALTER DIRECTORY TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_pkey; -- fail -ERROR: syntax error at or near "DIRECTORY" +ERROR: syntax error at or near "DROP" LINE 1: ALTER DIRECTORY TABLE dir_table1 DROP CONSTRAINT DROP CONSTR... - ^ + ^ -- Test remove_table SELECT remove_file('dir_table1', 'nation5'); -- fail remove_file diff --git a/src/test/regress/output/directory_table_optimizer.source b/src/test/regress/output/directory_table_optimizer.source index 96f06814616..21b7db6ee23 100644 --- a/src/test/regress/output/directory_table_optimizer.source +++ b/src/test/regress/output/directory_table_optimizer.source @@ -1375,35 +1375,35 @@ SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; ALTER TABLE dir_table1 ADD COLUMN a int; -- fail ERROR: "dir_table1" is not a table, composite type, or foreign table ALTER DIRECTORY TABLE dir_table1 ADD COLUMN a int; -- fail -ERROR: syntax error at or near "DIRECTORY" +ERROR: syntax error at or near "ADD" LINE 1: ALTER DIRECTORY TABLE dir_table1 ADD COLUMN a int; - ^ + ^ ALTER TABLE dir_table2 DROP COLUMN relative_path; -- fail ERROR: "dir_table2" is not a table, composite type, or foreign table ALTER DIRECTORY TABLE dir_table2 DROP COLUMN relative_path; -- fail -ERROR: syntax error at or near "DIRECTORY" +ERROR: syntax error at or near "DROP" LINE 1: ALTER DIRECTORY TABLE dir_table2 DROP COLUMN relative_path; - ^ + ^ ALTER TABLE dir_table1 RENAME TO dir_table_new; -- fail ERROR: Rename directory table is not allowed. ALTER DIRECTORY TABLE dir_table1 RENAME TO dir_table_new; -- fail -ERROR: syntax error at or near "DIRECTORY" +ERROR: syntax error at or near "RENAME" LINE 1: ALTER DIRECTORY TABLE dir_table1 RENAME TO dir_table_new; - ^ + ^ ALTER TABLE dir_table2 ADD CONSTRAINT dirtable_constraint UNIQUE (tag); -- fail ERROR: "dir_table2" is not a table or foreign table ALTER DIRECTORY TABLE dir_table2 ADD CONSTRAINT dirtable_constraint UNIQUE (tag); -- fail -ERROR: syntax error at or near "DIRECTORY" +ERROR: syntax error at or near "ADD" LINE 1: ALTER DIRECTORY TABLE dir_table2 ADD CONSTRAINT dirtable_con... - ^ + ^ ALTER TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_pkey; -- fail ERROR: syntax error at or near "CONSTRAINT" LINE 1: ALTER TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_... ^ ALTER DIRECTORY TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_pkey; -- fail -ERROR: syntax error at or near "DIRECTORY" +ERROR: syntax error at or near "DROP" LINE 1: ALTER DIRECTORY TABLE dir_table1 DROP CONSTRAINT DROP CONSTR... - ^ + ^ -- Test remove_table SELECT remove_file('dir_table1', 'nation5'); -- fail remove_file diff --git a/src/test/regress/output/tag.source b/src/test/regress/output/tag.source new file mode 100644 index 00000000000..714dd91753d --- /dev/null +++ b/src/test/regress/output/tag.source @@ -0,0 +1,1424 @@ +-- Test tag manipulation +\d+ pg_tag; + Table "pg_catalog.pg_tag" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +----------------+--------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + tagname | name | | not null | | plain | | + tagowner | oid | | not null | | plain | | + allowed_values | text[] | C | | | extended | | +Indexes: + "pg_tag_tagname_index" PRIMARY KEY, btree (tagname), tablespace "pg_global" + "pg_tag_oid_index" UNIQUE CONSTRAINT, btree (oid), tablespace "pg_global" +Tablespace: "pg_global" + +\d+ pg_tag_description; + Table "pg_catalog.pg_tag_description" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------+------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + tddatabaseid | oid | | not null | | plain | | + tdclassid | oid | | not null | | plain | | + tdobjid | oid | | not null | | plain | | + tagid | oid | | not null | | plain | | + tagvalue | text | C | | | extended | | +Indexes: + "pg_tag_description_d_c_o_t_index" PRIMARY KEY, btree (tddatabaseid, tdclassid, tdobjid, tagid), tablespace "pg_global" + "pg_tag_description_oid_index" UNIQUE CONSTRAINT, btree (oid), tablespace "pg_global" + "pg_tag_description_tagidvalue_index" btree (tagid, tagvalue), tablespace "pg_global" +Tablespace: "pg_global" + +SELECT * FROM pg_tag; + oid | tagname | tagowner | allowed_values +-----+---------+----------+---------------- +(0 rows) + +SELECT * FROM pg_tag_description; + oid | tddatabaseid | tdclassid | tdobjid | tagid | tagvalue +-----+--------------+-----------+---------+-------+---------- +(0 rows) + +CREATE DATABASE other_db; +-- Test create tag +CREATE TAG tag1; +CREATE TAG IF NOT EXISTS tag1; +NOTICE: tag "tag1" already exists, skipping +CREATE TAG IF NOT EXISTS tag2; +CREATE TAG tag2; -- error +ERROR: tag "tag2" already exists +CREATE TAG tag3 ALLOWED_VALUES '123'; +CREATE TAG tag3; -- error +ERROR: tag "tag3" already exists +CREATE TAG tag4 ALLOWED_VALUES '123', '456', ' '; +CREATE TAG IF NOT EXISTS tag5 ALLOWED_VALUES '123', 'val1'; +CREATE TAG tag6 ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +ERROR: added allowed value "nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqweffjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwefqifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdasiqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho" has exceeded max 256 length +CREATE TAG tag7 ALLOWED_VALUES 'val1', '123', 'val1'; -- error +ERROR: allowed value "val1" has been added +CREATE TAG tag8 ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +CREATE TAG tag9 ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300', '301'; +ERROR: Allowed_values only allow 300 values. +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} + tag5 | 10 | {123,val1} + tag8 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} +(6 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} + tag5 | 10 | {123,val1} + tag8 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} +(6 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- Test Drop tag +DROP TAG tag5; +DROP TAG IF EXISTS tag5; +NOTICE: tag "tag5" does not exist, skipping +DROP TAG IF EXISTS tag8; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- Test Alter tag +-- Rename +ALTER TAG tag3 RENAME TO tag3_new; +ALTER TAG IF EXISTS tag4 RENAME TO tag4_new; +ALTER TAG tag3_new RENAME TO tag3; +ALTER TAG tag4_new RENAME TO tag4; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- OWNER TO +CREATE USER tag_user; +NOTICE: resource queue required -- using default resource queue "pg_default" +ALTER TAG tag1 OWNER TO tag_user; +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | tag_user | + tag2 | gpadmin | + tag3 | gpadmin | {123} + tag4 | gpadmin | {123,456," "} +(4 rows) + +ALTER TAG tag1 OWNER TO gpadmin; +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | gpadmin | + tag2 | gpadmin | + tag3 | gpadmin | {123} + tag4 | gpadmin | {123,456," "} +(4 rows) + +\c other_db +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | gpadmin | + tag2 | gpadmin | + tag3 | gpadmin | {123} + tag4 | gpadmin | {123,456," "} +(4 rows) + +\c postgres +-- Unset allowed_values +ALTER TAG tag1 UNSET ALLOWED_VALUES; +ALTER TAG tag2 UNSET ALLOWED_VALUES; +ALTER TAG tag3 UNSET ALLOWED_VALUES; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- ADD allowed_values +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1'; +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1'; -- error +ERROR: allowed value "val1" has been added +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val1'; -- error +ERROR: allowed value "val1" has been added +ALTER TAG tag1 ADD ALLOWED_VALUES 'val2', 'val2'; -- error +ERROR: allowed value "val2" has been added +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val2', 'val2'; -- error +ERROR: allowed value "val2" has been added +ALTER TAG tag1 ADD ALLOWED_VALUES 'val2', 'val3'; +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val4', 'val5'; +ALTER TAG tag1 ADD ALLOWED_VALUES '', ''; -- error +ERROR: allowed value "" has been added +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES '', ''; --error +ERROR: allowed value "" has been added +ALTER TAG tag1 ADD ALLOWED_VALUES ' ', ' '; -- error +ERROR: allowed value " " has been added +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES ' '; +ALTER TAG tag1 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ERROR: Allowed_values only allow 300 values. +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ERROR: Allowed_values only allow 300 values. +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+-------------------------------- + tag1 | 10 | {val1,val2,val3,val4,val5," "} + tag2 | 10 | + tag3 | 10 | + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+-------------------------------- + tag1 | 10 | {val1,val2,val3,val4,val5," "} + tag2 | 10 | + tag3 | 10 | + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +ALTER TAG tag2 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ALTER TAG IF EXISTS tag2 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ERROR: allowed value "1" has been added +ALTER TAG tag3 ADD ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +ERROR: added allowed value "nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqweffjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwefqifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdasiqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho" has exceeded max 256 length +ALTER TAG IF EXISTS tag3 ADD ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +ERROR: added allowed value "nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqweffjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwefqifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdasiqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho" has exceeded max 256 length +ALTER TAG tag3 ADD ALLOWED_VALUES 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'; +ALTER TAG tag4 ADD ALLOWED_VALUES ' '; -- error +ERROR: allowed value " " has been added +ALTER TAG IF EXISTS tag4 ADD ALLOWED_VALUES ' '; -- error +ERROR: allowed value " " has been added +ALTER TAG tag4 ADD ALLOWED_VALUES ''; +ALTER TAG tag4 ADD ALLOWED_VALUES ''; -- error +ERROR: allowed value "" has been added +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3,val4,val5," "} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3,val4,val5," "} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- DROP allowed_values +ALTER TAG tag1 DROP ALLOWED_VALUES 'unknown'; -- error; +ERROR: allowed value "unknown" not found +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES 'unknown'; -- error; +ERROR: allowed value "unknown" not found +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ERROR: allowed value "1" not found +ALTER TAG tag1 DROP ALLOWED_VALUES '1'; -- error +ERROR: allowed value "1" not found +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES '1'; -- error +ERROR: allowed value "1" not found +ALTER TAG tag1 DROP ALLOWED_VALUES ''; -- error +ERROR: allowed value "" not found +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES ''; -- error +ERROR: allowed value "" not found +ALTER TAG tag1 UNSET ALLOWED_VALUES; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1', 'val2', 'val3'; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- Cleanup +DROP USER tag_user; +-- Test database with tag +-- Create database +CREATE DATABASE tag_db1 TAG (tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE DATABASE tag_db1 TAG (tag1 = 'val1'); +CREATE DATABASE tag_db2 TAG; -- error +ERROR: syntax error at or near ";" +LINE 1: CREATE DATABASE tag_db2 TAG; + ^ +CREATE DATABASE tag_db2 TAG (); -- error +ERROR: syntax error at or near ")" +LINE 1: CREATE DATABASE tag_db2 TAG (); + ^ +CREATE DATABASE tag_db2 TAG (tag1 = ''); -- error +ERROR: tag value "" is not in tag "tag1" allowed values +CREATE DATABASE tag_db2 TAG (tag1 = 'val1', tag2 = '10'); +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +ERROR: tag "tag1" value has been added for object "tag_db3". +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag2 = '1'); +CREATE DATABASE tag_db4 TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE DATABASE tag_db5 TAG (tag2 = '300', tag4 = ' '); +CREATE DATABASE tag_db6 TAG (tag4 = '', tag4 = ' '); -- error +ERROR: tag "tag4" value has been added for object "tag_db6". +CREATE DATABASE tag_db6 TAG (tag4 = '', tag4 = ''); -- error +ERROR: tag "tag4" value has been added for object "tag_db6". +CREATE DATABASE tag_db6 TAG (tag4 = ' ', tag4 = ' '); -- error +ERROR: tag "tag4" value has been added for object "tag_db6". +CREATE DATABASE tag_db6 TAG (tag4 = ''); +CREATE DATABASE tag_db7 TAG (tag4 = ' '); +CREATE DATABASE tag_db8 TAG (tag3 = ''); -- error +ERROR: tag value "" is not in tag "tag3" allowed values +CREATE DATABASE tag_db8 WITH TEMPLATE = template0 TAG (tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE DATABASE tag_db8 WITH TEMPLATE = template0 TAG (tag1 = 'val1'); +CREATE DATABASE tag_db9 WITH TEMPLATE = template0; +CREATE DATABASE tag_db10 WITH TEMPLATE = template0 TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | datname | tagname | tagvalue +--------------+----------+---------+----------------------------------------------------------------------------------- + 0 | tag_db1 | tag1 | val1 + 0 | tag_db10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + 0 | tag_db2 | tag1 | val1 + 0 | tag_db2 | tag2 | 10 + 0 | tag_db3 | tag1 | val1 + 0 | tag_db3 | tag2 | 1 + 0 | tag_db4 | tag1 | val1 + 0 | tag_db4 | tag2 | 3 + 0 | tag_db4 | tag4 | + 0 | tag_db5 | tag2 | 300 + 0 | tag_db5 | tag4 | + 0 | tag_db6 | tag4 | + 0 | tag_db7 | tag4 | + 0 | tag_db8 | tag1 | val1 +(14 rows) + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + datname | datdba | encoding | datistemplate | datallowconn | datconnlimit +----------+--------+----------+---------------+--------------+-------------- + tag_db1 | 10 | 6 | f | t | -1 + tag_db10 | 10 | 6 | f | t | -1 + tag_db2 | 10 | 6 | f | t | -1 + tag_db3 | 10 | 6 | f | t | -1 + tag_db4 | 10 | 6 | f | t | -1 + tag_db5 | 10 | 6 | f | t | -1 + tag_db6 | 10 | 6 | f | t | -1 + tag_db7 | 10 | 6 | f | t | -1 + tag_db8 | 10 | 6 | f | t | -1 + tag_db9 | 10 | 6 | f | t | -1 +(10 rows) + +DROP TAG tag1; -- error +ERROR: tag "tag1" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +DROP TAG tag2; -- error +ERROR: tag "tag2" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +DROP TAG tag3; -- error +ERROR: tag "tag3" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag3 +DROP TAG tag4; -- error +ERROR: tag "tag4" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +-- Alter Database +ALTER DATABASE tag_db1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER DATABASE tag_db2 TAG (tag2 = '10'); +ALTER DATABASE tag_db3 TAG (tag3 = ''); -- error +ERROR: tag value "" is not in tag "tag3" allowed values +ALTER DATABASE tag_db4 UNSET TAG (tag1, tag2); +ALTER DATABASE tag_db4 TAG (tag1 = 'val3', tag4 = ''); +ALTER DATABASE tag_db5 TAG (tag4 = '', tag4 = ' '); +ALTER DATABASE tag_db6 TAG (tag4 = ' '); +ALTER DATABASE tag_db7 TAG (tag1 = 'val2', tag2 = '3'); +WARNING: object "tag_db7" does not have tag "tag1", creating +WARNING: object "tag_db7" does not have tag "tag2", creating +ALTER DATABASE tag_db7 UNSET TAG (tag1); +ALTER DATABASE tag_db8 TAG (tag4 = '123', tag4 = '123'); +WARNING: object "tag_db8" does not have tag "tag4", creating +ALTER DATABASE tag_db9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +WARNING: object "tag_db9" does not have tag "tag4", creating +ALTER DATABASE tag_db9 TAG (tag4 = '123'); +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | datname | tagname | tagvalue +--------------+----------+---------+----------------------------------------------------------------------------------- + 0 | tag_db1 | tag1 | val1 + 0 | tag_db10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + 0 | tag_db2 | tag1 | val1 + 0 | tag_db2 | tag2 | 10 + 0 | tag_db3 | tag1 | val1 + 0 | tag_db3 | tag2 | 1 + 0 | tag_db4 | tag1 | val3 + 0 | tag_db4 | tag2 | + 0 | tag_db4 | tag4 | + 0 | tag_db5 | tag2 | 300 + 0 | tag_db5 | tag4 | + 0 | tag_db6 | tag4 | + 0 | tag_db7 | tag1 | + 0 | tag_db7 | tag2 | 3 + 0 | tag_db7 | tag4 | + 0 | tag_db8 | tag1 | val1 + 0 | tag_db8 | tag4 | 123 + 0 | tag_db9 | tag4 | 123 +(18 rows) + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + datname | datdba | encoding | datistemplate | datallowconn | datconnlimit +----------+--------+----------+---------------+--------------+-------------- + tag_db1 | 10 | 6 | f | t | -1 + tag_db10 | 10 | 6 | f | t | -1 + tag_db2 | 10 | 6 | f | t | -1 + tag_db3 | 10 | 6 | f | t | -1 + tag_db4 | 10 | 6 | f | t | -1 + tag_db5 | 10 | 6 | f | t | -1 + tag_db6 | 10 | 6 | f | t | -1 + tag_db7 | 10 | 6 | f | t | -1 + tag_db8 | 10 | 6 | f | t | -1 + tag_db9 | 10 | 6 | f | t | -1 +(10 rows) + +-- Drop Database +DROP DATABASE tag_db1; +DROP DATABASE tag_db2; +DROP DATABASE tag_db3; +DROP DATABASE tag_db4; +DROP DATABASE tag_db5; +DROP DATABASE tag_db6; +DROP DATABASE tag_db7; +DROP DATABASE tag_db8; +DROP DATABASE tag_db9; +DROP DATABASE tag_db10; +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | datname | tagname | tagvalue +--------------+---------+---------+---------- +(0 rows) + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + datname | datdba | encoding | datistemplate | datallowconn | datconnlimit +---------+--------+----------+---------------+--------------+-------------- +(0 rows) + +-- Test user with tag +-- Create User +CREATE USER tag_user1 TAG (tag1 = 'novalue'); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE USER tag_user1 TAG (tag1 = 'val1'); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user2 TAG; -- error +ERROR: syntax error at or near ";" +LINE 1: CREATE USER tag_user2 TAG; + ^ +CREATE USER tag_user2 TAG (); -- error +ERROR: syntax error at or near ")" +LINE 1: CREATE USER tag_user2 TAG (); + ^ +CREATE USER tag_user2 TAG (tag1 = ''); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag value "" is not in tag "tag1" allowed values +CREATE USER tag_user2 TAG (tag1 = 'val1', tag2 = '10'); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user3 TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag "tag1" value has been added for object "tag_user3". +CREATE USER tag_user3 TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE USER tag_user3 TAG (tag1 = 'val1', tag2 = '1'); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user4 TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user5 TAG (tag2 = '300', tag4 = ' '); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user6 TAG (tag4 = '', tag4 = ''); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag "tag4" value has been added for object "tag_user6". +CREATE USER tag_user6 TAG (tag4 = ' ', tag4 = ' '); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag "tag4" value has been added for object "tag_user6". +CREATE USER tag_user6 TAG (tag4 = ''); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user7 CONNECTION LIMIT 10 TAG (tag4 = ' '); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user8 TAG (tag3 = ''); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag value "" is not in tag "tag3" allowed values +CREATE USER tag_user8 superuser TAG (tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE USER tag_user8 superuser TAG (tag1 = 'val1'); +CREATE USER tag_user9 superuser; +CREATE USER tag_user10 superuser TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + tddatabaseid | rolname | tagname | tagvalue +--------------+------------+---------+----------------------------------------------------------------------------------- + 0 | tag_user1 | tag1 | val1 + 0 | tag_user10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + 0 | tag_user2 | tag1 | val1 + 0 | tag_user2 | tag2 | 10 + 0 | tag_user3 | tag1 | val1 + 0 | tag_user3 | tag2 | 1 + 0 | tag_user4 | tag1 | val1 + 0 | tag_user4 | tag2 | 3 + 0 | tag_user4 | tag4 | + 0 | tag_user5 | tag2 | 300 + 0 | tag_user5 | tag4 | + 0 | tag_user6 | tag4 | + 0 | tag_user7 | tag4 | + 0 | tag_user8 | tag1 | val1 +(14 rows) + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + rolname | rolsuper | rolconnlimit +------------+----------+-------------- + tag_user1 | f | -1 + tag_user10 | t | -1 + tag_user2 | f | -1 + tag_user3 | f | -1 + tag_user4 | f | -1 + tag_user5 | f | -1 + tag_user6 | f | -1 + tag_user7 | f | 10 + tag_user8 | t | -1 + tag_user9 | t | -1 +(10 rows) + +DROP TAG tag1; -- error +ERROR: tag "tag1" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +DROP TAG tag2; -- error +ERROR: tag "tag2" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +DROP TAG tag3; -- error +ERROR: tag "tag3" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag3 +DROP TAG tag4; -- error +ERROR: tag "tag4" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +-- Alter User +ALTER USER tag_user1 CONNECTION LIMIT 3 TAG (tag1 = 'val1', tag1 = 'val1'); -- error +ERROR: syntax error at or near "TAG" +LINE 1: ALTER USER tag_user1 CONNECTION LIMIT 3 TAG (tag1 = 'val1', ... + ^ +ALTER USER tag_user1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER USER tag_user2 TAG (tag2 = '10'); +ALTER USER tag_user3 TAG (tag3 = ''); -- error +ERROR: tag value "" is not in tag "tag3" allowed values +ALTER USER tag_user4 UNSET TAG (tag1, tag2); +ALTER USER tag_user4 TAG (tag1 = 'val3', tag4 = ''); +ALTER USER tag_user5 TAG (tag4 = '', tag4 = ' '); +ALTER USER tag_user6 TAG (tag4 = ' '); +ALTER USER tag_user7 TAG (tag1 = 'val2', tag2 = '3'); +WARNING: object "tag_user7" does not have tag "tag1", creating +WARNING: object "tag_user7" does not have tag "tag2", creating +ALTER USER tag_user7 UNSET TAG (tag1); +ALTER USER tag_user8 TAG (tag4 = '123', tag4 = '123'); +WARNING: object "tag_user8" does not have tag "tag4", creating +ALTER USER tag_user9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +WARNING: object "tag_user9" does not have tag "tag4", creating +ALTER USER tag_user9 TAG (tag4 = '123'); +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + tddatabaseid | rolname | tagname | tagvalue +--------------+------------+---------+----------------------------------------------------------------------------------- + 0 | tag_user1 | tag1 | val1 + 0 | tag_user10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + 0 | tag_user2 | tag1 | val1 + 0 | tag_user2 | tag2 | 10 + 0 | tag_user3 | tag1 | val1 + 0 | tag_user3 | tag2 | 1 + 0 | tag_user4 | tag1 | val3 + 0 | tag_user4 | tag2 | + 0 | tag_user4 | tag4 | + 0 | tag_user5 | tag2 | 300 + 0 | tag_user5 | tag4 | + 0 | tag_user6 | tag4 | + 0 | tag_user7 | tag1 | + 0 | tag_user7 | tag2 | 3 + 0 | tag_user7 | tag4 | + 0 | tag_user8 | tag1 | val1 + 0 | tag_user8 | tag4 | 123 + 0 | tag_user9 | tag4 | 123 +(18 rows) + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + rolname | rolsuper | rolconnlimit +------------+----------+-------------- + tag_user1 | f | -1 + tag_user10 | t | -1 + tag_user2 | f | -1 + tag_user3 | f | -1 + tag_user4 | f | -1 + tag_user5 | f | -1 + tag_user6 | f | -1 + tag_user7 | f | 10 + tag_user8 | t | -1 + tag_user9 | t | -1 +(10 rows) + +-- Drop User +DROP USER tag_user1; +DROP USER tag_user2; +DROP USER tag_user3; +DROP USER tag_user4; +DROP USER tag_user5; +DROP USER tag_user6; +DROP USER tag_user7; +DROP USER tag_user8; +DROP USER tag_user9; +DROP USER tag_user10; +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + tddatabaseid | rolname | tagname | tagvalue +--------------+---------+---------+---------- +(0 rows) + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + rolname | rolsuper | rolconnlimit +---------+----------+-------------- +(0 rows) + +-- Test tablespace with tag +-- Create tablespace +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'test'); -- error +ERROR: tag value "test" is not in tag "tag1" allowed values +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'val1', tag2 = '301'); -- error +ERROR: tag value "301" is not in tag "tag2" allowed values +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'val1', tag2 = '2'); +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | spcname | tagname | tagvalue +--------------+----------------+---------+---------- + 0 | tag_tablespace | tag1 | val1 + 0 | tag_tablespace | tag2 | 2 +(2 rows) + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + spcname +---------------- + pg_default + pg_global + tag_tablespace +(3 rows) + +-- Alter tablespace +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag2 = '10'); -- error +ERROR: syntax error at or near "TAG" +LINE 1: ...SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag2 ... + ^ +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag3 = ''); -- error +ERROR: syntax error at or near "TAG" +LINE 1: ...SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag3 ... + ^ +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag4 = '', tag1 = 'val1'); -- error +ERROR: syntax error at or near "TAG" +LINE 1: ...SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag4 ... + ^ +ALTER TABLESPACE tag_tablespace TAG (tag4 = '', tag1 = 'val1'); +WARNING: object "tag_tablespace" does not have tag "tag4", creating +ALTER TABLESPACE tag_tablespace UNSET TAG (tag1, tag2); +ALTER TABLESPACE tag_tablespace UNSET TAG (tag2); +ALTER TABLESPACE tag_tablespace TAG (tag1 = 'val2', tag1 = 'val3'); +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | spcname | tagname | tagvalue +--------------+----------------+---------+---------- + 0 | tag_tablespace | tag1 | val3 + 0 | tag_tablespace | tag2 | + 0 | tag_tablespace | tag4 | +(3 rows) + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + spcname +---------------- + pg_default + pg_global + tag_tablespace +(3 rows) + +DROP TAG tag1; -- error +ERROR: tag "tag1" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag1 +DROP TAG tag2; -- error +ERROR: tag "tag2" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag2 +DROP TAG tag4; -- error +ERROR: tag "tag4" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag4 +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +-- Drop tablespace +DROP TABLESPACE tag_tablespace; +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | spcname | tagname | tagvalue +--------------+---------+---------+---------- +(0 rows) + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + spcname +------------ + pg_default + pg_global +(2 rows) + +-- Test Schema with Tag +-- Create Schema +CREATE SCHEMA tag_schema1 TAG (tag1 = 'val1'); -- error +ERROR: syntax error at or near "TAG" +LINE 1: CREATE SCHEMA tag_schema1 TAG (tag1 = 'val1'); + ^ +CREATE SCHEMA tag_schema1 WITH TAG (tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE SCHEMA tag_schema1 WITH TAG (tag1 = 'val1'); +CREATE SCHEMA tag_schema2 WITH TAG; -- error +ERROR: syntax error at or near ";" +LINE 1: CREATE SCHEMA tag_schema2 WITH TAG; + ^ +CREATE SCHEMA tag_schema2 WITH TAG (); -- error +ERROR: syntax error at or near ")" +LINE 1: CREATE SCHEMA tag_schema2 WITH TAG (); + ^ +CREATE SCHEMA tag_schema2 WITH TAG (tag1 = ''); -- error +ERROR: tag value "" is not in tag "tag1" allowed values +CREATE SCHEMA tag_schema2 WITH TAG (tag1 = 'val1', tag2 = '10'); +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +ERROR: tag "tag1" value has been added for object "tag_schema3". +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag2 = '1'); +CREATE SCHEMA tag_schema4 WITH TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE SCHEMA tag_schema5 WITH TAG (tag2 = '300', tag4 = ' '); +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = '', tag4 = ''); -- error +ERROR: tag "tag4" value has been added for object "tag_schema6". +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = ' ', tag4 = ' '); -- error +ERROR: tag "tag4" value has been added for object "tag_schema6". +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = ''); +CREATE SCHEMA tag_schema7 WITH TAG (tag4 = ' '); +CREATE SCHEMA tag_schema8 WITH TAG (tag3 = ''); -- error +ERROR: tag value "" is not in tag "tag3" allowed values +CREATE SCHEMA tag_schema8 WITH TAG (tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE SCHEMA tag_schema8 WITH TAG (tag1 = 'val1'); +CREATE SCHEMA tag_schema9; +CREATE SCHEMA tag_schema10 WITH TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + datname | nspname | tagname | tagvalue +----------+--------------+---------+----------------------------------------------------------------------------------- + postgres | tag_schema1 | tag1 | val1 + postgres | tag_schema10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + postgres | tag_schema2 | tag1 | val1 + postgres | tag_schema2 | tag2 | 10 + postgres | tag_schema3 | tag1 | val1 + postgres | tag_schema3 | tag2 | 1 + postgres | tag_schema4 | tag1 | val1 + postgres | tag_schema4 | tag2 | 3 + postgres | tag_schema4 | tag4 | + postgres | tag_schema5 | tag2 | 300 + postgres | tag_schema5 | tag4 | + postgres | tag_schema6 | tag4 | + postgres | tag_schema7 | tag4 | + postgres | tag_schema8 | tag1 | val1 +(14 rows) + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + nspname | nspowner +--------------+---------- + tag_schema1 | 10 + tag_schema10 | 10 + tag_schema2 | 10 + tag_schema3 | 10 + tag_schema4 | 10 + tag_schema5 | 10 + tag_schema6 | 10 + tag_schema7 | 10 + tag_schema8 | 10 + tag_schema9 | 10 +(10 rows) + +DROP TAG tag1; -- error +ERROR: tag "tag1" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +DROP TAG tag2; -- error +ERROR: tag "tag2" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +DROP TAG tag3; -- error +ERROR: tag "tag3" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag3 +DROP TAG tag4; -- error +ERROR: tag "tag4" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +-- Alter Schema +ALTER SCHEMA tag_schema1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER SCHEMA tag_schema2 TAG (tag2 = '10'); +ALTER SCHEMA tag_schema3 TAG (tag3 = ''); -- error +ERROR: tag value "" is not in tag "tag3" allowed values +ALTER SCHEMA tag_schema4 UNSET TAG (tag1, tag2); +ALTER SCHEMA tag_schema4 TAG (tag1 = 'val3', tag4 = ''); +ALTER SCHEMA tag_schema5 TAG (tag4 = '', tag4 = ' '); +ALTER SCHEMA tag_schema6 TAG (tag4 = ' '); +ALTER SCHEMA tag_schema7 TAG (tag1 = 'val2', tag2 = '3'); +WARNING: object "tag_schema7" does not have tag "tag1", creating +WARNING: object "tag_schema7" does not have tag "tag2", creating +ALTER SCHEMA tag_schema7 UNSET TAG (tag1); +ALTER SCHEMA tag_schema8 TAG (tag4 = '123', tag4 = '123'); +WARNING: object "tag_schema8" does not have tag "tag4", creating +ALTER SCHEMA tag_schema9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +WARNING: object "tag_schema9" does not have tag "tag4", creating +ALTER SCHEMA tag_schema9 TAG (tag4 = '123'); +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + datname | nspname | tagname | tagvalue +----------+--------------+---------+----------------------------------------------------------------------------------- + postgres | tag_schema1 | tag1 | val1 + postgres | tag_schema10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + postgres | tag_schema2 | tag1 | val1 + postgres | tag_schema2 | tag2 | 10 + postgres | tag_schema3 | tag1 | val1 + postgres | tag_schema3 | tag2 | 1 + postgres | tag_schema4 | tag1 | val3 + postgres | tag_schema4 | tag2 | + postgres | tag_schema4 | tag4 | + postgres | tag_schema5 | tag2 | 300 + postgres | tag_schema5 | tag4 | + postgres | tag_schema6 | tag4 | + postgres | tag_schema7 | tag1 | + postgres | tag_schema7 | tag2 | 3 + postgres | tag_schema7 | tag4 | + postgres | tag_schema8 | tag1 | val1 + postgres | tag_schema8 | tag4 | 123 + postgres | tag_schema9 | tag4 | 123 +(18 rows) + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + nspname | nspowner +--------------+---------- + tag_schema1 | 10 + tag_schema10 | 10 + tag_schema2 | 10 + tag_schema3 | 10 + tag_schema4 | 10 + tag_schema5 | 10 + tag_schema6 | 10 + tag_schema7 | 10 + tag_schema8 | 10 + tag_schema9 | 10 +(10 rows) + +-- Drop Schema +DROP SCHEMA tag_schema1; +DROP SCHEMA tag_schema2; +DROP SCHEMA tag_schema3; +DROP SCHEMA tag_schema4; +DROP SCHEMA tag_schema5; +DROP SCHEMA tag_schema6; +DROP SCHEMA tag_schema7; +DROP SCHEMA tag_schema8; +DROP SCHEMA tag_schema9; +DROP SCHEMA tag_schema10; +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + datname | nspname | tagname | tagvalue +---------+---------+---------+---------- +(0 rows) + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + nspname | nspowner +---------+---------- +(0 rows) + +-- Test Table with Tag +-- Create Table +CREATE TABLE tag_table1(a int, b varchar) TAG (tag1 = 'novalue'); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE TEMP TABLE tag_table1(a int, b varchar) TAG (tag1 = 'val1'); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG; -- error +ERROR: syntax error at or near ";" +LINE 1: CREATE TEMP TABLE tag_table2(a int, b varchar) TAG; + ^ +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG (); -- error +ERROR: syntax error at or near ")" +LINE 1: CREATE TEMP TABLE tag_table2(a int, b varchar) TAG (); + ^ +CREATE TABLE tag_table2(a int, b varchar) TAG (tag1 = ''); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag value "" is not in tag "tag1" allowed values +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG (tag1 = 'val1', tag2 = '10'); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag "tag1" value has been added for object "tag_table3". +CREATE TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE TEMP TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag2 = '1'); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table4(a int, b varchar) TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table5(a int, b varchar) TAG (tag2 = '300', tag4 = ' '); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = '', tag4 = ''); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag "tag4" value has been added for object "tag_table6". +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = ' ', tag4 = ' '); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag "tag4" value has been added for object "tag_table6". +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = ''); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table7(a int, b varchar) TAG (tag4 = ' '); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table8(a int, b varchar) TAG (tag3 = ''); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag value "" is not in tag "tag3" allowed values +CREATE TABLE tag_table8(a int, b varchar) TAG (tag1 = 'novalue'); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE TABLE tag_table8(a int, b varchar) TAG (tag1 = 'val1'); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table9(a int, b varchar); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table10(a int, b varchar) TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + datname | relname | relnamespace | relkind | tagname | tagvalue +----------+-------------+--------------+---------+---------+----------------------------------------------------------------------------------- + postgres | tag_table10 | public | r | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + postgres | tag_table4 | public | r | tag1 | val1 + postgres | tag_table4 | public | r | tag2 | 3 + postgres | tag_table4 | public | r | tag4 | + postgres | tag_table5 | public | r | tag2 | 300 + postgres | tag_table5 | public | r | tag4 | + postgres | tag_table6 | public | r | tag4 | + postgres | tag_table7 | public | r | tag4 | + postgres | tag_table8 | public | r | tag1 | val1 +(9 rows) + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + relname | relpersistence +-------------+---------------- + tag_table1 | t + tag_table10 | p + tag_table2 | t + tag_table3 | t + tag_table4 | p + tag_table5 | p + tag_table6 | p + tag_table7 | p + tag_table8 | p + tag_table9 | p +(10 rows) + +DROP TAG tag1; -- error +ERROR: tag "tag1" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag1 +tag of tag description with tag tag1 +DROP TAG tag2; -- error +ERROR: tag "tag2" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag2 +tag of tag description with tag tag2 +DROP TAG tag3; -- error +ERROR: tag "tag3" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag3 +DROP TAG tag4; -- error +ERROR: tag "tag4" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +-- Alter Table +ALTER TABLE tag_table1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER TABLE tag_table2 TAG (tag2 = '10'); +ALTER TABLE tag_table3 TAG (tag3 = ''); +ALTER TABLE tag_table4 UNSET TAG (tag1, tag2); +ALTER TABLE tag_table4 TAG (tag1 = 'val3', tag4 = ''); +ALTER TABLE tag_table5 TAG (tag4 = '', tag4 = ' '); +ALTER TABLE tag_table6 TAG (tag4 = ' '); +ALTER TABLE tag_table7 TAG (tag1 = 'val2', tag2 = '3'); +WARNING: object "tag_table7" does not have tag "tag1", creating +WARNING: object "tag_table7" does not have tag "tag2", creating +ALTER TABLE tag_table7 UNSET TAG (tag1); +ALTER TABLE tag_table8 TAG (tag4 = '123', tag4 = '123'); +WARNING: object "tag_table8" does not have tag "tag4", creating +ALTER TABLE tag_table9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +WARNING: object "tag_table9" does not have tag "tag4", creating +ALTER TABLE tag_table9 TAG (tag4 = '123'); +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + datname | relname | relnamespace | relkind | tagname | tagvalue +----------+-------------+--------------+---------+---------+----------------------------------------------------------------------------------- + postgres | tag_table10 | public | r | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + postgres | tag_table4 | public | r | tag1 | val3 + postgres | tag_table4 | public | r | tag2 | + postgres | tag_table4 | public | r | tag4 | + postgres | tag_table5 | public | r | tag2 | 300 + postgres | tag_table5 | public | r | tag4 | + postgres | tag_table6 | public | r | tag4 | + postgres | tag_table7 | public | r | tag1 | + postgres | tag_table7 | public | r | tag2 | 3 + postgres | tag_table7 | public | r | tag4 | + postgres | tag_table8 | public | r | tag1 | val1 + postgres | tag_table8 | public | r | tag4 | 123 + postgres | tag_table9 | public | r | tag4 | 123 +(13 rows) + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + relname | relpersistence +-------------+---------------- + tag_table1 | t + tag_table10 | p + tag_table2 | t + tag_table3 | t + tag_table4 | p + tag_table5 | p + tag_table6 | p + tag_table7 | p + tag_table8 | p + tag_table9 | p +(10 rows) + +-- Drop Table +DROP TABLE tag_table1; +DROP TABLE tag_table2; +DROP TABLE tag_table3; +DROP TABLE tag_table4; +DROP TABLE tag_table5; +DROP TABLE tag_table6; +DROP TABLE tag_table7; +DROP TABLE tag_table8; +DROP TABLE tag_table9; +DROP TABLE tag_table10; +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + datname | relname | relnamespace | relkind | tagname | tagvalue +---------+---------+--------------+---------+---------+---------- +(0 rows) + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + relname | relpersistence +---------+---------------- +(0 rows) + +-- Cleanup +DROP TAG tag1; +DROP TAG tag2; +DROP TAG tag3; +DROP TAG tag4; +DROP DATABASE other_db; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 792c667348f..34f917041d8 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -176,3 +176,6 @@ test: fast_default # run stats by itself because its delay may be insufficient under heavy load test: stats + +# test of tag +test: tag diff --git a/src/test/singlenode_regress/expected/misc_sanity.out b/src/test/singlenode_regress/expected/misc_sanity.out index 8bd8db7e70b..a05cf9aba47 100644 --- a/src/test/singlenode_regress/expected/misc_sanity.out +++ b/src/test/singlenode_regress/expected/misc_sanity.out @@ -123,6 +123,8 @@ ORDER BY 1, 2; pg_resqueuecapability | ressetting | text pg_stat_last_operation | stasubtype | text pg_stat_last_shoperation | stasubtype | text + pg_tag | allowed_values | text[] + pg_tag_description | tagvalue | text pg_task | command | text pg_task | database | text pg_task | jobname | text @@ -134,7 +136,7 @@ ORDER BY 1, 2; pg_task_run_history | return_message | text pg_task_run_history | status | text pg_task_run_history | username | text -(31 rows) +(33 rows) -- system catalogs without primary keys -- diff --git a/src/test/singlenode_regress/expected/oidjoins.out b/src/test/singlenode_regress/expected/oidjoins.out index 4d6ad39fbb8..87502771aae 100644 --- a/src/test/singlenode_regress/expected/oidjoins.out +++ b/src/test/singlenode_regress/expected/oidjoins.out @@ -199,6 +199,10 @@ NOTICE: checking pg_database {dattablespace} => pg_tablespace {oid} NOTICE: checking pg_db_role_setting {setdatabase} => pg_database {oid} NOTICE: checking pg_db_role_setting {setrole} => pg_authid {oid} NOTICE: checking pg_tablespace {spcowner} => pg_authid {oid} +NOTICE: checking pg_tag {tagowner} => pg_authid {oid} +NOTICE: checking pg_tag_description {tdclassid} => pg_class {oid} +NOTICE: checking pg_tag_description {tddatabaseid} => pg_database {oid} +NOTICE: checking pg_tag_description {tagid} => pg_tag {oid} NOTICE: checking pg_auth_members {roleid} => pg_authid {oid} NOTICE: checking pg_auth_members {member} => pg_authid {oid} NOTICE: checking pg_auth_members {grantor} => pg_authid {oid} diff --git a/src/test/singlenode_regress/expected/sanity_check.out b/src/test/singlenode_regress/expected/sanity_check.out index b47c31bc7e6..484b3ea50d6 100644 --- a/src/test/singlenode_regress/expected/sanity_check.out +++ b/src/test/singlenode_regress/expected/sanity_check.out @@ -174,6 +174,8 @@ pg_statistic_ext_data|t pg_subscription|t pg_subscription_rel|t pg_tablespace|t +pg_tag|t +pg_tag_description|t pg_task|t pg_task_run_history|t pg_transform|t diff --git a/src/test/singlenode_regress/input/tag.source b/src/test/singlenode_regress/input/tag.source new file mode 100644 index 00000000000..5a295703ae9 --- /dev/null +++ b/src/test/singlenode_regress/input/tag.source @@ -0,0 +1,626 @@ +-- Test tag manipulation +\d+ pg_tag; +\d+ pg_tag_description; +SELECT * FROM pg_tag; +SELECT * FROM pg_tag_description; +CREATE DATABASE other_db; + +-- Test create tag +CREATE TAG tag1; +CREATE TAG IF NOT EXISTS tag1; +CREATE TAG IF NOT EXISTS tag2; +CREATE TAG tag2; -- error +CREATE TAG tag3 ALLOWED_VALUES '123'; +CREATE TAG tag3; -- error +CREATE TAG tag4 ALLOWED_VALUES '123', '456', ' '; +CREATE TAG IF NOT EXISTS tag5 ALLOWED_VALUES '123', 'val1'; +CREATE TAG tag6 ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +CREATE TAG tag7 ALLOWED_VALUES 'val1', '123', 'val1'; -- error +CREATE TAG tag8 ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +CREATE TAG tag9 ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300', '301'; + +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- Test Drop tag +DROP TAG tag5; +DROP TAG IF EXISTS tag5; +DROP TAG IF EXISTS tag8; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- Test Alter tag +-- Rename +ALTER TAG tag3 RENAME TO tag3_new; +ALTER TAG IF EXISTS tag4 RENAME TO tag4_new; +ALTER TAG tag3_new RENAME TO tag3; +ALTER TAG tag4_new RENAME TO tag4; + +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- OWNER TO +CREATE USER tag_user; +ALTER TAG tag1 OWNER TO tag_user; +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; +ALTER TAG tag1 OWNER TO gpadmin; +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; +\c other_db +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; +\c postgres + +-- Unset allowed_values +ALTER TAG tag1 UNSET ALLOWED_VALUES; +ALTER TAG tag2 UNSET ALLOWED_VALUES; +ALTER TAG tag3 UNSET ALLOWED_VALUES; + +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- ADD allowed_values +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1'; +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1'; -- error +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val1'; -- error +ALTER TAG tag1 ADD ALLOWED_VALUES 'val2', 'val2'; -- error +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val2', 'val2'; -- error +ALTER TAG tag1 ADD ALLOWED_VALUES 'val2', 'val3'; +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val4', 'val5'; +ALTER TAG tag1 ADD ALLOWED_VALUES '', ''; -- error +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES '', ''; --error +ALTER TAG tag1 ADD ALLOWED_VALUES ' ', ' '; -- error +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES ' '; + +ALTER TAG tag1 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +ALTER TAG tag2 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ALTER TAG IF EXISTS tag2 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; + +ALTER TAG tag3 ADD ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +ALTER TAG IF EXISTS tag3 ADD ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +ALTER TAG tag3 ADD ALLOWED_VALUES 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'; + +ALTER TAG tag4 ADD ALLOWED_VALUES ' '; -- error +ALTER TAG IF EXISTS tag4 ADD ALLOWED_VALUES ' '; -- error +ALTER TAG tag4 ADD ALLOWED_VALUES ''; +ALTER TAG tag4 ADD ALLOWED_VALUES ''; -- error + +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- DROP allowed_values +ALTER TAG tag1 DROP ALLOWED_VALUES 'unknown'; -- error; +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES 'unknown'; -- error; +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ALTER TAG tag1 DROP ALLOWED_VALUES '1'; -- error +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES '1'; -- error +ALTER TAG tag1 DROP ALLOWED_VALUES ''; -- error +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES ''; -- error +ALTER TAG tag1 UNSET ALLOWED_VALUES; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1', 'val2', 'val3'; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; +SELECT count(*) FROM pg_tag_description; +\c postgres + +-- Cleanup +DROP USER tag_user; + +-- Test database with tag +-- Create database +CREATE DATABASE tag_db1 TAG (tag1 = 'novalue'); -- error +CREATE DATABASE tag_db1 TAG (tag1 = 'val1'); +CREATE DATABASE tag_db2 TAG; -- error +CREATE DATABASE tag_db2 TAG (); -- error +CREATE DATABASE tag_db2 TAG (tag1 = ''); -- error +CREATE DATABASE tag_db2 TAG (tag1 = 'val1', tag2 = '10'); +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag2 = '1'); +CREATE DATABASE tag_db4 TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE DATABASE tag_db5 TAG (tag2 = '300', tag4 = ' '); +CREATE DATABASE tag_db6 TAG (tag4 = '', tag4 = ' '); -- error +CREATE DATABASE tag_db6 TAG (tag4 = '', tag4 = ''); -- error +CREATE DATABASE tag_db6 TAG (tag4 = ' ', tag4 = ' '); -- error +CREATE DATABASE tag_db6 TAG (tag4 = ''); +CREATE DATABASE tag_db7 TAG (tag4 = ' '); +CREATE DATABASE tag_db8 TAG (tag3 = ''); -- error +CREATE DATABASE tag_db8 WITH TEMPLATE = template0 TAG (tag1 = 'novalue'); -- error +CREATE DATABASE tag_db8 WITH TEMPLATE = template0 TAG (tag1 = 'val1'); +CREATE DATABASE tag_db9 WITH TEMPLATE = template0; +CREATE DATABASE tag_db10 WITH TEMPLATE = template0 TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); + +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + +DROP TAG tag1; -- error +DROP TAG tag2; -- error +DROP TAG tag3; -- error +DROP TAG tag4; -- error +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +-- Alter Database +ALTER DATABASE tag_db1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER DATABASE tag_db2 TAG (tag2 = '10'); +ALTER DATABASE tag_db3 TAG (tag3 = ''); -- error +ALTER DATABASE tag_db4 UNSET TAG (tag1, tag2); +ALTER DATABASE tag_db4 TAG (tag1 = 'val3', tag4 = ''); +ALTER DATABASE tag_db5 TAG (tag4 = '', tag4 = ' '); +ALTER DATABASE tag_db6 TAG (tag4 = ' '); +ALTER DATABASE tag_db7 TAG (tag1 = 'val2', tag2 = '3'); +ALTER DATABASE tag_db7 UNSET TAG (tag1); +ALTER DATABASE tag_db8 TAG (tag4 = '123', tag4 = '123'); +ALTER DATABASE tag_db9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +ALTER DATABASE tag_db9 TAG (tag4 = '123'); + +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + +-- Drop Database +DROP DATABASE tag_db1; +DROP DATABASE tag_db2; +DROP DATABASE tag_db3; +DROP DATABASE tag_db4; +DROP DATABASE tag_db5; +DROP DATABASE tag_db6; +DROP DATABASE tag_db7; +DROP DATABASE tag_db8; +DROP DATABASE tag_db9; +DROP DATABASE tag_db10; + +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + + +-- Test user with tag +-- Create User +CREATE USER tag_user1 TAG (tag1 = 'novalue'); -- error +CREATE USER tag_user1 TAG (tag1 = 'val1'); +CREATE USER tag_user2 TAG; -- error +CREATE USER tag_user2 TAG (); -- error +CREATE USER tag_user2 TAG (tag1 = ''); -- error +CREATE USER tag_user2 TAG (tag1 = 'val1', tag2 = '10'); +CREATE USER tag_user3 TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +CREATE USER tag_user3 TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +CREATE USER tag_user3 TAG (tag1 = 'val1', tag2 = '1'); +CREATE USER tag_user4 TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE USER tag_user5 TAG (tag2 = '300', tag4 = ' '); +CREATE USER tag_user6 TAG (tag4 = '', tag4 = ''); -- error +CREATE USER tag_user6 TAG (tag4 = ' ', tag4 = ' '); -- error +CREATE USER tag_user6 TAG (tag4 = ''); +CREATE USER tag_user7 CONNECTION LIMIT 10 TAG (tag4 = ' '); +CREATE USER tag_user8 TAG (tag3 = ''); -- error +CREATE USER tag_user8 superuser TAG (tag1 = 'novalue'); -- error +CREATE USER tag_user8 superuser TAG (tag1 = 'val1'); +CREATE USER tag_user9 superuser; +CREATE USER tag_user10 superuser TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); + +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + +DROP TAG tag1; -- error +DROP TAG tag2; -- error +DROP TAG tag3; -- error +DROP TAG tag4; -- error +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +-- Alter User +ALTER USER tag_user1 CONNECTION LIMIT 3 TAG (tag1 = 'val1', tag1 = 'val1'); -- error +ALTER USER tag_user1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER USER tag_user2 TAG (tag2 = '10'); +ALTER USER tag_user3 TAG (tag3 = ''); -- error +ALTER USER tag_user4 UNSET TAG (tag1, tag2); +ALTER USER tag_user4 TAG (tag1 = 'val3', tag4 = ''); +ALTER USER tag_user5 TAG (tag4 = '', tag4 = ' '); +ALTER USER tag_user6 TAG (tag4 = ' '); +ALTER USER tag_user7 TAG (tag1 = 'val2', tag2 = '3'); +ALTER USER tag_user7 UNSET TAG (tag1); +ALTER USER tag_user8 TAG (tag4 = '123', tag4 = '123'); +ALTER USER tag_user9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +ALTER USER tag_user9 TAG (tag4 = '123'); + +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + +-- Drop User +DROP USER tag_user1; +DROP USER tag_user2; +DROP USER tag_user3; +DROP USER tag_user4; +DROP USER tag_user5; +DROP USER tag_user6; +DROP USER tag_user7; +DROP USER tag_user8; +DROP USER tag_user9; +DROP USER tag_user10; + +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + + +-- Test tablespace with tag +-- Create tablespace +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'test'); -- error +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'val1', tag2 = '301'); -- error +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'val1', tag2 = '2'); + +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + +-- Alter tablespace +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag2 = '10'); -- error +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag3 = ''); -- error +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag4 = '', tag1 = 'val1'); -- error +ALTER TABLESPACE tag_tablespace TAG (tag4 = '', tag1 = 'val1'); +ALTER TABLESPACE tag_tablespace UNSET TAG (tag1, tag2); +ALTER TABLESPACE tag_tablespace UNSET TAG (tag2); +ALTER TABLESPACE tag_tablespace TAG (tag1 = 'val2', tag1 = 'val3'); + +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + +DROP TAG tag1; -- error +DROP TAG tag2; -- error +DROP TAG tag4; -- error +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +-- Drop tablespace +DROP TABLESPACE tag_tablespace; + +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + + +-- Test Schema with Tag +-- Create Schema +CREATE SCHEMA tag_schema1 TAG (tag1 = 'val1'); -- error +CREATE SCHEMA tag_schema1 WITH TAG (tag1 = 'novalue'); -- error +CREATE SCHEMA tag_schema1 WITH TAG (tag1 = 'val1'); +CREATE SCHEMA tag_schema2 WITH TAG; -- error +CREATE SCHEMA tag_schema2 WITH TAG (); -- error +CREATE SCHEMA tag_schema2 WITH TAG (tag1 = ''); -- error +CREATE SCHEMA tag_schema2 WITH TAG (tag1 = 'val1', tag2 = '10'); +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag2 = '1'); +CREATE SCHEMA tag_schema4 WITH TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE SCHEMA tag_schema5 WITH TAG (tag2 = '300', tag4 = ' '); +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = '', tag4 = ''); -- error +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = ' ', tag4 = ' '); -- error +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = ''); +CREATE SCHEMA tag_schema7 WITH TAG (tag4 = ' '); +CREATE SCHEMA tag_schema8 WITH TAG (tag3 = ''); -- error +CREATE SCHEMA tag_schema8 WITH TAG (tag1 = 'novalue'); -- error +CREATE SCHEMA tag_schema8 WITH TAG (tag1 = 'val1'); +CREATE SCHEMA tag_schema9; +CREATE SCHEMA tag_schema10 WITH TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); + +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + +DROP TAG tag1; -- error +DROP TAG tag2; -- error +DROP TAG tag3; -- error +DROP TAG tag4; -- error +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +-- Alter Schema +ALTER SCHEMA tag_schema1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER SCHEMA tag_schema2 TAG (tag2 = '10'); +ALTER SCHEMA tag_schema3 TAG (tag3 = ''); -- error +ALTER SCHEMA tag_schema4 UNSET TAG (tag1, tag2); +ALTER SCHEMA tag_schema4 TAG (tag1 = 'val3', tag4 = ''); +ALTER SCHEMA tag_schema5 TAG (tag4 = '', tag4 = ' '); +ALTER SCHEMA tag_schema6 TAG (tag4 = ' '); +ALTER SCHEMA tag_schema7 TAG (tag1 = 'val2', tag2 = '3'); +ALTER SCHEMA tag_schema7 UNSET TAG (tag1); +ALTER SCHEMA tag_schema8 TAG (tag4 = '123', tag4 = '123'); +ALTER SCHEMA tag_schema9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +ALTER SCHEMA tag_schema9 TAG (tag4 = '123'); + +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + +-- Drop Schema +DROP SCHEMA tag_schema1; +DROP SCHEMA tag_schema2; +DROP SCHEMA tag_schema3; +DROP SCHEMA tag_schema4; +DROP SCHEMA tag_schema5; +DROP SCHEMA tag_schema6; +DROP SCHEMA tag_schema7; +DROP SCHEMA tag_schema8; +DROP SCHEMA tag_schema9; +DROP SCHEMA tag_schema10; + +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + + +-- Test Table with Tag +-- Create Table +CREATE TABLE tag_table1(a int, b varchar) TAG (tag1 = 'novalue'); -- error +CREATE TEMP TABLE tag_table1(a int, b varchar) TAG (tag1 = 'val1'); +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG; -- error +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG (); -- error +CREATE TABLE tag_table2(a int, b varchar) TAG (tag1 = ''); -- error +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG (tag1 = 'val1', tag2 = '10'); +CREATE TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +CREATE TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +CREATE TEMP TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag2 = '1'); +CREATE TABLE tag_table4(a int, b varchar) TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE TABLE tag_table5(a int, b varchar) TAG (tag2 = '300', tag4 = ' '); +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = '', tag4 = ''); -- error +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = ' ', tag4 = ' '); -- error +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = ''); +CREATE TABLE tag_table7(a int, b varchar) TAG (tag4 = ' '); +CREATE TABLE tag_table8(a int, b varchar) TAG (tag3 = ''); -- error +CREATE TABLE tag_table8(a int, b varchar) TAG (tag1 = 'novalue'); -- error +CREATE TABLE tag_table8(a int, b varchar) TAG (tag1 = 'val1'); +CREATE TABLE tag_table9(a int, b varchar); +CREATE TABLE tag_table10(a int, b varchar) TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); + +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + +DROP TAG tag1; -- error +DROP TAG tag2; -- error +DROP TAG tag3; -- error +DROP TAG tag4; -- error +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + +-- Alter Table +ALTER TABLE tag_table1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER TABLE tag_table2 TAG (tag2 = '10'); +ALTER TABLE tag_table3 TAG (tag3 = ''); +ALTER TABLE tag_table4 UNSET TAG (tag1, tag2); +ALTER TABLE tag_table4 TAG (tag1 = 'val3', tag4 = ''); +ALTER TABLE tag_table5 TAG (tag4 = '', tag4 = ' '); +ALTER TABLE tag_table6 TAG (tag4 = ' '); +ALTER TABLE tag_table7 TAG (tag1 = 'val2', tag2 = '3'); +ALTER TABLE tag_table7 UNSET TAG (tag1); +ALTER TABLE tag_table8 TAG (tag4 = '123', tag4 = '123'); +ALTER TABLE tag_table9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +ALTER TABLE tag_table9 TAG (tag4 = '123'); + +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + +-- Drop Table +DROP TABLE tag_table1; +DROP TABLE tag_table2; +DROP TABLE tag_table3; +DROP TABLE tag_table4; +DROP TABLE tag_table5; +DROP TABLE tag_table6; +DROP TABLE tag_table7; +DROP TABLE tag_table8; +DROP TABLE tag_table9; +DROP TABLE tag_table10; + +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + + +-- Cleanup +DROP TAG tag1; +DROP TAG tag2; +DROP TAG tag3; +DROP TAG tag4; +DROP DATABASE other_db; diff --git a/src/test/singlenode_regress/output/tag.source b/src/test/singlenode_regress/output/tag.source new file mode 100644 index 00000000000..714dd91753d --- /dev/null +++ b/src/test/singlenode_regress/output/tag.source @@ -0,0 +1,1424 @@ +-- Test tag manipulation +\d+ pg_tag; + Table "pg_catalog.pg_tag" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +----------------+--------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + tagname | name | | not null | | plain | | + tagowner | oid | | not null | | plain | | + allowed_values | text[] | C | | | extended | | +Indexes: + "pg_tag_tagname_index" PRIMARY KEY, btree (tagname), tablespace "pg_global" + "pg_tag_oid_index" UNIQUE CONSTRAINT, btree (oid), tablespace "pg_global" +Tablespace: "pg_global" + +\d+ pg_tag_description; + Table "pg_catalog.pg_tag_description" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------+------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + tddatabaseid | oid | | not null | | plain | | + tdclassid | oid | | not null | | plain | | + tdobjid | oid | | not null | | plain | | + tagid | oid | | not null | | plain | | + tagvalue | text | C | | | extended | | +Indexes: + "pg_tag_description_d_c_o_t_index" PRIMARY KEY, btree (tddatabaseid, tdclassid, tdobjid, tagid), tablespace "pg_global" + "pg_tag_description_oid_index" UNIQUE CONSTRAINT, btree (oid), tablespace "pg_global" + "pg_tag_description_tagidvalue_index" btree (tagid, tagvalue), tablespace "pg_global" +Tablespace: "pg_global" + +SELECT * FROM pg_tag; + oid | tagname | tagowner | allowed_values +-----+---------+----------+---------------- +(0 rows) + +SELECT * FROM pg_tag_description; + oid | tddatabaseid | tdclassid | tdobjid | tagid | tagvalue +-----+--------------+-----------+---------+-------+---------- +(0 rows) + +CREATE DATABASE other_db; +-- Test create tag +CREATE TAG tag1; +CREATE TAG IF NOT EXISTS tag1; +NOTICE: tag "tag1" already exists, skipping +CREATE TAG IF NOT EXISTS tag2; +CREATE TAG tag2; -- error +ERROR: tag "tag2" already exists +CREATE TAG tag3 ALLOWED_VALUES '123'; +CREATE TAG tag3; -- error +ERROR: tag "tag3" already exists +CREATE TAG tag4 ALLOWED_VALUES '123', '456', ' '; +CREATE TAG IF NOT EXISTS tag5 ALLOWED_VALUES '123', 'val1'; +CREATE TAG tag6 ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +ERROR: added allowed value "nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqweffjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwefqifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdasiqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho" has exceeded max 256 length +CREATE TAG tag7 ALLOWED_VALUES 'val1', '123', 'val1'; -- error +ERROR: allowed value "val1" has been added +CREATE TAG tag8 ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +CREATE TAG tag9 ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300', '301'; +ERROR: Allowed_values only allow 300 values. +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} + tag5 | 10 | {123,val1} + tag8 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} +(6 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} + tag5 | 10 | {123,val1} + tag8 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} +(6 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- Test Drop tag +DROP TAG tag5; +DROP TAG IF EXISTS tag5; +NOTICE: tag "tag5" does not exist, skipping +DROP TAG IF EXISTS tag8; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- Test Alter tag +-- Rename +ALTER TAG tag3 RENAME TO tag3_new; +ALTER TAG IF EXISTS tag4 RENAME TO tag4_new; +ALTER TAG tag3_new RENAME TO tag3; +ALTER TAG tag4_new RENAME TO tag4; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | {123} + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- OWNER TO +CREATE USER tag_user; +NOTICE: resource queue required -- using default resource queue "pg_default" +ALTER TAG tag1 OWNER TO tag_user; +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | tag_user | + tag2 | gpadmin | + tag3 | gpadmin | {123} + tag4 | gpadmin | {123,456," "} +(4 rows) + +ALTER TAG tag1 OWNER TO gpadmin; +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | gpadmin | + tag2 | gpadmin | + tag3 | gpadmin | {123} + tag4 | gpadmin | {123,456," "} +(4 rows) + +\c other_db +SELECT tagname, rolname AS tagowner, allowed_values FROM pg_tag, pg_authid +WHERE pg_tag.tagowner = pg_authid.oid +ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | gpadmin | + tag2 | gpadmin | + tag3 | gpadmin | {123} + tag4 | gpadmin | {123,456," "} +(4 rows) + +\c postgres +-- Unset allowed_values +ALTER TAG tag1 UNSET ALLOWED_VALUES; +ALTER TAG tag2 UNSET ALLOWED_VALUES; +ALTER TAG tag3 UNSET ALLOWED_VALUES; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+---------------- + tag1 | 10 | + tag2 | 10 | + tag3 | 10 | + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- ADD allowed_values +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1'; +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1'; -- error +ERROR: allowed value "val1" has been added +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val1'; -- error +ERROR: allowed value "val1" has been added +ALTER TAG tag1 ADD ALLOWED_VALUES 'val2', 'val2'; -- error +ERROR: allowed value "val2" has been added +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val2', 'val2'; -- error +ERROR: allowed value "val2" has been added +ALTER TAG tag1 ADD ALLOWED_VALUES 'val2', 'val3'; +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES 'val4', 'val5'; +ALTER TAG tag1 ADD ALLOWED_VALUES '', ''; -- error +ERROR: allowed value "" has been added +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES '', ''; --error +ERROR: allowed value "" has been added +ALTER TAG tag1 ADD ALLOWED_VALUES ' ', ' '; -- error +ERROR: allowed value " " has been added +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES ' '; +ALTER TAG tag1 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ERROR: Allowed_values only allow 300 values. +ALTER TAG IF EXISTS tag1 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ERROR: Allowed_values only allow 300 values. +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+-------------------------------- + tag1 | 10 | {val1,val2,val3,val4,val5," "} + tag2 | 10 | + tag3 | 10 | + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+-------------------------------- + tag1 | 10 | {val1,val2,val3,val4,val5," "} + tag2 | 10 | + tag3 | 10 | + tag4 | 10 | {123,456," "} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +ALTER TAG tag2 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ALTER TAG IF EXISTS tag2 ADD ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ERROR: allowed value "1" has been added +ALTER TAG tag3 ADD ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +ERROR: added allowed value "nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqweffjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwefqifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdasiqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho" has exceeded max 256 length +ALTER TAG IF EXISTS tag3 ADD ALLOWED_VALUES 'nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqwef' +'fjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwef' +'qifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdas' +'iqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho'; -- error +ERROR: added allowed value "nqwenfqpjenpjqnpufnqwpiuenfuiasqwefqfsafqwefnfiunl;jfa;lskdfjqpwefjqpewe234dfqweffjhsudfiueqihfsakdljfqeqfhqoufhoaisuehfqoiuwehfqoifhqoiuwehfoqihfosfqwfeqwfqwefqwefqwfefqefqfqewfqwefweqfsdfqwefqifquhowifhoiuqhfuosdfqjfqkepfqjfpishdfuiqh2139u108wefoiuqwhefoiuqwehfoiuqwhfoiuweqfheiasuohfioquwehfqwoeiufhdasiqeqwejfpqwifjipqwfjqwiefjpiqwehfpiquwehfqwiufhqwpiuefhqwui0fhpiiohfoqiuwehfoquwefoiweqfewoqifqwoiufhho" has exceeded max 256 length +ALTER TAG tag3 ADD ALLOWED_VALUES 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'; +ALTER TAG tag4 ADD ALLOWED_VALUES ' '; -- error +ERROR: allowed value " " has been added +ALTER TAG IF EXISTS tag4 ADD ALLOWED_VALUES ' '; -- error +ERROR: allowed value " " has been added +ALTER TAG tag4 ADD ALLOWED_VALUES ''; +ALTER TAG tag4 ADD ALLOWED_VALUES ''; -- error +ERROR: allowed value "" has been added +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3,val4,val5," "} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3,val4,val5," "} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- DROP allowed_values +ALTER TAG tag1 DROP ALLOWED_VALUES 'unknown'; -- error; +ERROR: allowed value "unknown" not found +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES 'unknown'; -- error; +ERROR: allowed value "unknown" not found +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', -- error + '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', + '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', + '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', + '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', + '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', +'117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', +'137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', +'157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', +'177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', +'197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', +'217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', +'237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256', +'257', '258', '259', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '270', '271', '272', '273', '274', '275', '276', +'277', '278', '279', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', +'297', '298', '299', '300'; +ERROR: allowed value "1" not found +ALTER TAG tag1 DROP ALLOWED_VALUES '1'; -- error +ERROR: allowed value "1" not found +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES '1'; -- error +ERROR: allowed value "1" not found +ALTER TAG tag1 DROP ALLOWED_VALUES ''; -- error +ERROR: allowed value "" not found +ALTER TAG IF EXISTS tag1 DROP ALLOWED_VALUES ''; -- error +ERROR: allowed value "" not found +ALTER TAG tag1 UNSET ALLOWED_VALUES; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +ALTER TAG tag1 ADD ALLOWED_VALUES 'val1', 'val2', 'val3'; +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c other_db +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +SELECT count(*) FROM pg_tag_description; + count +------- + 0 +(1 row) + +\c postgres +-- Cleanup +DROP USER tag_user; +-- Test database with tag +-- Create database +CREATE DATABASE tag_db1 TAG (tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE DATABASE tag_db1 TAG (tag1 = 'val1'); +CREATE DATABASE tag_db2 TAG; -- error +ERROR: syntax error at or near ";" +LINE 1: CREATE DATABASE tag_db2 TAG; + ^ +CREATE DATABASE tag_db2 TAG (); -- error +ERROR: syntax error at or near ")" +LINE 1: CREATE DATABASE tag_db2 TAG (); + ^ +CREATE DATABASE tag_db2 TAG (tag1 = ''); -- error +ERROR: tag value "" is not in tag "tag1" allowed values +CREATE DATABASE tag_db2 TAG (tag1 = 'val1', tag2 = '10'); +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +ERROR: tag "tag1" value has been added for object "tag_db3". +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE DATABASE tag_db3 TAG (tag1 = 'val1', tag2 = '1'); +CREATE DATABASE tag_db4 TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE DATABASE tag_db5 TAG (tag2 = '300', tag4 = ' '); +CREATE DATABASE tag_db6 TAG (tag4 = '', tag4 = ' '); -- error +ERROR: tag "tag4" value has been added for object "tag_db6". +CREATE DATABASE tag_db6 TAG (tag4 = '', tag4 = ''); -- error +ERROR: tag "tag4" value has been added for object "tag_db6". +CREATE DATABASE tag_db6 TAG (tag4 = ' ', tag4 = ' '); -- error +ERROR: tag "tag4" value has been added for object "tag_db6". +CREATE DATABASE tag_db6 TAG (tag4 = ''); +CREATE DATABASE tag_db7 TAG (tag4 = ' '); +CREATE DATABASE tag_db8 TAG (tag3 = ''); -- error +ERROR: tag value "" is not in tag "tag3" allowed values +CREATE DATABASE tag_db8 WITH TEMPLATE = template0 TAG (tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE DATABASE tag_db8 WITH TEMPLATE = template0 TAG (tag1 = 'val1'); +CREATE DATABASE tag_db9 WITH TEMPLATE = template0; +CREATE DATABASE tag_db10 WITH TEMPLATE = template0 TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | datname | tagname | tagvalue +--------------+----------+---------+----------------------------------------------------------------------------------- + 0 | tag_db1 | tag1 | val1 + 0 | tag_db10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + 0 | tag_db2 | tag1 | val1 + 0 | tag_db2 | tag2 | 10 + 0 | tag_db3 | tag1 | val1 + 0 | tag_db3 | tag2 | 1 + 0 | tag_db4 | tag1 | val1 + 0 | tag_db4 | tag2 | 3 + 0 | tag_db4 | tag4 | + 0 | tag_db5 | tag2 | 300 + 0 | tag_db5 | tag4 | + 0 | tag_db6 | tag4 | + 0 | tag_db7 | tag4 | + 0 | tag_db8 | tag1 | val1 +(14 rows) + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + datname | datdba | encoding | datistemplate | datallowconn | datconnlimit +----------+--------+----------+---------------+--------------+-------------- + tag_db1 | 10 | 6 | f | t | -1 + tag_db10 | 10 | 6 | f | t | -1 + tag_db2 | 10 | 6 | f | t | -1 + tag_db3 | 10 | 6 | f | t | -1 + tag_db4 | 10 | 6 | f | t | -1 + tag_db5 | 10 | 6 | f | t | -1 + tag_db6 | 10 | 6 | f | t | -1 + tag_db7 | 10 | 6 | f | t | -1 + tag_db8 | 10 | 6 | f | t | -1 + tag_db9 | 10 | 6 | f | t | -1 +(10 rows) + +DROP TAG tag1; -- error +ERROR: tag "tag1" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +DROP TAG tag2; -- error +ERROR: tag "tag2" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +DROP TAG tag3; -- error +ERROR: tag "tag3" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag3 +DROP TAG tag4; -- error +ERROR: tag "tag4" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +-- Alter Database +ALTER DATABASE tag_db1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER DATABASE tag_db2 TAG (tag2 = '10'); +ALTER DATABASE tag_db3 TAG (tag3 = ''); -- error +ERROR: tag value "" is not in tag "tag3" allowed values +ALTER DATABASE tag_db4 UNSET TAG (tag1, tag2); +ALTER DATABASE tag_db4 TAG (tag1 = 'val3', tag4 = ''); +ALTER DATABASE tag_db5 TAG (tag4 = '', tag4 = ' '); +ALTER DATABASE tag_db6 TAG (tag4 = ' '); +ALTER DATABASE tag_db7 TAG (tag1 = 'val2', tag2 = '3'); +WARNING: object "tag_db7" does not have tag "tag1", creating +WARNING: object "tag_db7" does not have tag "tag2", creating +ALTER DATABASE tag_db7 UNSET TAG (tag1); +ALTER DATABASE tag_db8 TAG (tag4 = '123', tag4 = '123'); +WARNING: object "tag_db8" does not have tag "tag4", creating +ALTER DATABASE tag_db9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +WARNING: object "tag_db9" does not have tag "tag4", creating +ALTER DATABASE tag_db9 TAG (tag4 = '123'); +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | datname | tagname | tagvalue +--------------+----------+---------+----------------------------------------------------------------------------------- + 0 | tag_db1 | tag1 | val1 + 0 | tag_db10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + 0 | tag_db2 | tag1 | val1 + 0 | tag_db2 | tag2 | 10 + 0 | tag_db3 | tag1 | val1 + 0 | tag_db3 | tag2 | 1 + 0 | tag_db4 | tag1 | val3 + 0 | tag_db4 | tag2 | + 0 | tag_db4 | tag4 | + 0 | tag_db5 | tag2 | 300 + 0 | tag_db5 | tag4 | + 0 | tag_db6 | tag4 | + 0 | tag_db7 | tag1 | + 0 | tag_db7 | tag2 | 3 + 0 | tag_db7 | tag4 | + 0 | tag_db8 | tag1 | val1 + 0 | tag_db8 | tag4 | 123 + 0 | tag_db9 | tag4 | 123 +(18 rows) + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + datname | datdba | encoding | datistemplate | datallowconn | datconnlimit +----------+--------+----------+---------------+--------------+-------------- + tag_db1 | 10 | 6 | f | t | -1 + tag_db10 | 10 | 6 | f | t | -1 + tag_db2 | 10 | 6 | f | t | -1 + tag_db3 | 10 | 6 | f | t | -1 + tag_db4 | 10 | 6 | f | t | -1 + tag_db5 | 10 | 6 | f | t | -1 + tag_db6 | 10 | 6 | f | t | -1 + tag_db7 | 10 | 6 | f | t | -1 + tag_db8 | 10 | 6 | f | t | -1 + tag_db9 | 10 | 6 | f | t | -1 +(10 rows) + +-- Drop Database +DROP DATABASE tag_db1; +DROP DATABASE tag_db2; +DROP DATABASE tag_db3; +DROP DATABASE tag_db4; +DROP DATABASE tag_db5; +DROP DATABASE tag_db6; +DROP DATABASE tag_db7; +DROP DATABASE tag_db8; +DROP DATABASE tag_db9; +DROP DATABASE tag_db10; +SELECT * FROM database_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | datname | tagname | tagvalue +--------------+---------+---------+---------- +(0 rows) + +SELECT datname, datdba, encoding, datistemplate, datallowconn, datconnlimit +FROM pg_database +WHERE datname like '%tag%' ORDER BY 1; + datname | datdba | encoding | datistemplate | datallowconn | datconnlimit +---------+--------+----------+---------------+--------------+-------------- +(0 rows) + +-- Test user with tag +-- Create User +CREATE USER tag_user1 TAG (tag1 = 'novalue'); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE USER tag_user1 TAG (tag1 = 'val1'); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user2 TAG; -- error +ERROR: syntax error at or near ";" +LINE 1: CREATE USER tag_user2 TAG; + ^ +CREATE USER tag_user2 TAG (); -- error +ERROR: syntax error at or near ")" +LINE 1: CREATE USER tag_user2 TAG (); + ^ +CREATE USER tag_user2 TAG (tag1 = ''); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag value "" is not in tag "tag1" allowed values +CREATE USER tag_user2 TAG (tag1 = 'val1', tag2 = '10'); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user3 TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag "tag1" value has been added for object "tag_user3". +CREATE USER tag_user3 TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE USER tag_user3 TAG (tag1 = 'val1', tag2 = '1'); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user4 TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user5 TAG (tag2 = '300', tag4 = ' '); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user6 TAG (tag4 = '', tag4 = ''); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag "tag4" value has been added for object "tag_user6". +CREATE USER tag_user6 TAG (tag4 = ' ', tag4 = ' '); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag "tag4" value has been added for object "tag_user6". +CREATE USER tag_user6 TAG (tag4 = ''); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user7 CONNECTION LIMIT 10 TAG (tag4 = ' '); +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER tag_user8 TAG (tag3 = ''); -- error +NOTICE: resource queue required -- using default resource queue "pg_default" +ERROR: tag value "" is not in tag "tag3" allowed values +CREATE USER tag_user8 superuser TAG (tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE USER tag_user8 superuser TAG (tag1 = 'val1'); +CREATE USER tag_user9 superuser; +CREATE USER tag_user10 superuser TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + tddatabaseid | rolname | tagname | tagvalue +--------------+------------+---------+----------------------------------------------------------------------------------- + 0 | tag_user1 | tag1 | val1 + 0 | tag_user10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + 0 | tag_user2 | tag1 | val1 + 0 | tag_user2 | tag2 | 10 + 0 | tag_user3 | tag1 | val1 + 0 | tag_user3 | tag2 | 1 + 0 | tag_user4 | tag1 | val1 + 0 | tag_user4 | tag2 | 3 + 0 | tag_user4 | tag4 | + 0 | tag_user5 | tag2 | 300 + 0 | tag_user5 | tag4 | + 0 | tag_user6 | tag4 | + 0 | tag_user7 | tag4 | + 0 | tag_user8 | tag1 | val1 +(14 rows) + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + rolname | rolsuper | rolconnlimit +------------+----------+-------------- + tag_user1 | f | -1 + tag_user10 | t | -1 + tag_user2 | f | -1 + tag_user3 | f | -1 + tag_user4 | f | -1 + tag_user5 | f | -1 + tag_user6 | f | -1 + tag_user7 | f | 10 + tag_user8 | t | -1 + tag_user9 | t | -1 +(10 rows) + +DROP TAG tag1; -- error +ERROR: tag "tag1" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +DROP TAG tag2; -- error +ERROR: tag "tag2" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +DROP TAG tag3; -- error +ERROR: tag "tag3" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag3 +DROP TAG tag4; -- error +ERROR: tag "tag4" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +-- Alter User +ALTER USER tag_user1 CONNECTION LIMIT 3 TAG (tag1 = 'val1', tag1 = 'val1'); -- error +ERROR: syntax error at or near "TAG" +LINE 1: ALTER USER tag_user1 CONNECTION LIMIT 3 TAG (tag1 = 'val1', ... + ^ +ALTER USER tag_user1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER USER tag_user2 TAG (tag2 = '10'); +ALTER USER tag_user3 TAG (tag3 = ''); -- error +ERROR: tag value "" is not in tag "tag3" allowed values +ALTER USER tag_user4 UNSET TAG (tag1, tag2); +ALTER USER tag_user4 TAG (tag1 = 'val3', tag4 = ''); +ALTER USER tag_user5 TAG (tag4 = '', tag4 = ' '); +ALTER USER tag_user6 TAG (tag4 = ' '); +ALTER USER tag_user7 TAG (tag1 = 'val2', tag2 = '3'); +WARNING: object "tag_user7" does not have tag "tag1", creating +WARNING: object "tag_user7" does not have tag "tag2", creating +ALTER USER tag_user7 UNSET TAG (tag1); +ALTER USER tag_user8 TAG (tag4 = '123', tag4 = '123'); +WARNING: object "tag_user8" does not have tag "tag4", creating +ALTER USER tag_user9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +WARNING: object "tag_user9" does not have tag "tag4", creating +ALTER USER tag_user9 TAG (tag4 = '123'); +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + tddatabaseid | rolname | tagname | tagvalue +--------------+------------+---------+----------------------------------------------------------------------------------- + 0 | tag_user1 | tag1 | val1 + 0 | tag_user10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + 0 | tag_user2 | tag1 | val1 + 0 | tag_user2 | tag2 | 10 + 0 | tag_user3 | tag1 | val1 + 0 | tag_user3 | tag2 | 1 + 0 | tag_user4 | tag1 | val3 + 0 | tag_user4 | tag2 | + 0 | tag_user4 | tag4 | + 0 | tag_user5 | tag2 | 300 + 0 | tag_user5 | tag4 | + 0 | tag_user6 | tag4 | + 0 | tag_user7 | tag1 | + 0 | tag_user7 | tag2 | 3 + 0 | tag_user7 | tag4 | + 0 | tag_user8 | tag1 | val1 + 0 | tag_user8 | tag4 | 123 + 0 | tag_user9 | tag4 | 123 +(18 rows) + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + rolname | rolsuper | rolconnlimit +------------+----------+-------------- + tag_user1 | f | -1 + tag_user10 | t | -1 + tag_user2 | f | -1 + tag_user3 | f | -1 + tag_user4 | f | -1 + tag_user5 | f | -1 + tag_user6 | f | -1 + tag_user7 | f | 10 + tag_user8 | t | -1 + tag_user9 | t | -1 +(10 rows) + +-- Drop User +DROP USER tag_user1; +DROP USER tag_user2; +DROP USER tag_user3; +DROP USER tag_user4; +DROP USER tag_user5; +DROP USER tag_user6; +DROP USER tag_user7; +DROP USER tag_user8; +DROP USER tag_user9; +DROP USER tag_user10; +SELECT * FROM user_tag_descriptions +WHERE rolname like '%tag_user%' +ORDER BY 1, 2, 3, 4; + tddatabaseid | rolname | tagname | tagvalue +--------------+---------+---------+---------- +(0 rows) + +SELECT rolname, rolsuper, rolconnlimit FROM pg_authid +WHERE rolname like '%tag_user%' +ORDER BY 1; + rolname | rolsuper | rolconnlimit +---------+----------+-------------- +(0 rows) + +-- Test tablespace with tag +-- Create tablespace +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'test'); -- error +ERROR: tag value "test" is not in tag "tag1" allowed values +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'val1', tag2 = '301'); -- error +ERROR: tag value "301" is not in tag "tag2" allowed values +CREATE TABLESPACE tag_tablespace LOCATION '@testtablespace@' WITH (random_page_cost = 3.0) TAG (tag1 = 'val1', tag2 = '2'); +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | spcname | tagname | tagvalue +--------------+----------------+---------+---------- + 0 | tag_tablespace | tag1 | val1 + 0 | tag_tablespace | tag2 | 2 +(2 rows) + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + spcname +---------------- + pg_default + pg_global + tag_tablespace +(3 rows) + +-- Alter tablespace +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag2 = '10'); -- error +ERROR: syntax error at or near "TAG" +LINE 1: ...SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag2 ... + ^ +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag3 = ''); -- error +ERROR: syntax error at or near "TAG" +LINE 1: ...SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag3 ... + ^ +ALTER TABLESPACE tag_tablespace SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag4 = '', tag1 = 'val1'); -- error +ERROR: syntax error at or near "TAG" +LINE 1: ...SET (random_page_cost = 1.0, seq_page_cost = 1.1) TAG (tag4 ... + ^ +ALTER TABLESPACE tag_tablespace TAG (tag4 = '', tag1 = 'val1'); +WARNING: object "tag_tablespace" does not have tag "tag4", creating +ALTER TABLESPACE tag_tablespace UNSET TAG (tag1, tag2); +ALTER TABLESPACE tag_tablespace UNSET TAG (tag2); +ALTER TABLESPACE tag_tablespace TAG (tag1 = 'val2', tag1 = 'val3'); +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | spcname | tagname | tagvalue +--------------+----------------+---------+---------- + 0 | tag_tablespace | tag1 | val3 + 0 | tag_tablespace | tag2 | + 0 | tag_tablespace | tag4 | +(3 rows) + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + spcname +---------------- + pg_default + pg_global + tag_tablespace +(3 rows) + +DROP TAG tag1; -- error +ERROR: tag "tag1" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag1 +DROP TAG tag2; -- error +ERROR: tag "tag2" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag2 +DROP TAG tag4; -- error +ERROR: tag "tag4" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag4 +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +-- Drop tablespace +DROP TABLESPACE tag_tablespace; +SELECT * FROM tablespace_tag_descriptions +ORDER BY 1, 2, 3, 4; + tddatabaseid | spcname | tagname | tagvalue +--------------+---------+---------+---------- +(0 rows) + +SELECT spcname FROM pg_tablespace +ORDER BY 1; + spcname +------------ + pg_default + pg_global +(2 rows) + +-- Test Schema with Tag +-- Create Schema +CREATE SCHEMA tag_schema1 TAG (tag1 = 'val1'); -- error +ERROR: syntax error at or near "TAG" +LINE 1: CREATE SCHEMA tag_schema1 TAG (tag1 = 'val1'); + ^ +CREATE SCHEMA tag_schema1 WITH TAG (tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE SCHEMA tag_schema1 WITH TAG (tag1 = 'val1'); +CREATE SCHEMA tag_schema2 WITH TAG; -- error +ERROR: syntax error at or near ";" +LINE 1: CREATE SCHEMA tag_schema2 WITH TAG; + ^ +CREATE SCHEMA tag_schema2 WITH TAG (); -- error +ERROR: syntax error at or near ")" +LINE 1: CREATE SCHEMA tag_schema2 WITH TAG (); + ^ +CREATE SCHEMA tag_schema2 WITH TAG (tag1 = ''); -- error +ERROR: tag value "" is not in tag "tag1" allowed values +CREATE SCHEMA tag_schema2 WITH TAG (tag1 = 'val1', tag2 = '10'); +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +ERROR: tag "tag1" value has been added for object "tag_schema3". +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE SCHEMA tag_schema3 WITH TAG (tag1 = 'val1', tag2 = '1'); +CREATE SCHEMA tag_schema4 WITH TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +CREATE SCHEMA tag_schema5 WITH TAG (tag2 = '300', tag4 = ' '); +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = '', tag4 = ''); -- error +ERROR: tag "tag4" value has been added for object "tag_schema6". +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = ' ', tag4 = ' '); -- error +ERROR: tag "tag4" value has been added for object "tag_schema6". +CREATE SCHEMA tag_schema6 WITH TAG (tag4 = ''); +CREATE SCHEMA tag_schema7 WITH TAG (tag4 = ' '); +CREATE SCHEMA tag_schema8 WITH TAG (tag3 = ''); -- error +ERROR: tag value "" is not in tag "tag3" allowed values +CREATE SCHEMA tag_schema8 WITH TAG (tag1 = 'novalue'); -- error +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE SCHEMA tag_schema8 WITH TAG (tag1 = 'val1'); +CREATE SCHEMA tag_schema9; +CREATE SCHEMA tag_schema10 WITH TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + datname | nspname | tagname | tagvalue +----------+--------------+---------+----------------------------------------------------------------------------------- + postgres | tag_schema1 | tag1 | val1 + postgres | tag_schema10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + postgres | tag_schema2 | tag1 | val1 + postgres | tag_schema2 | tag2 | 10 + postgres | tag_schema3 | tag1 | val1 + postgres | tag_schema3 | tag2 | 1 + postgres | tag_schema4 | tag1 | val1 + postgres | tag_schema4 | tag2 | 3 + postgres | tag_schema4 | tag4 | + postgres | tag_schema5 | tag2 | 300 + postgres | tag_schema5 | tag4 | + postgres | tag_schema6 | tag4 | + postgres | tag_schema7 | tag4 | + postgres | tag_schema8 | tag1 | val1 +(14 rows) + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + nspname | nspowner +--------------+---------- + tag_schema1 | 10 + tag_schema10 | 10 + tag_schema2 | 10 + tag_schema3 | 10 + tag_schema4 | 10 + tag_schema5 | 10 + tag_schema6 | 10 + tag_schema7 | 10 + tag_schema8 | 10 + tag_schema9 | 10 +(10 rows) + +DROP TAG tag1; -- error +ERROR: tag "tag1" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +tag of tag description with tag tag1 +DROP TAG tag2; -- error +ERROR: tag "tag2" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +tag of tag description with tag tag2 +DROP TAG tag3; -- error +ERROR: tag "tag3" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag3 +DROP TAG tag4; -- error +ERROR: tag "tag4" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +-- Alter Schema +ALTER SCHEMA tag_schema1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER SCHEMA tag_schema2 TAG (tag2 = '10'); +ALTER SCHEMA tag_schema3 TAG (tag3 = ''); -- error +ERROR: tag value "" is not in tag "tag3" allowed values +ALTER SCHEMA tag_schema4 UNSET TAG (tag1, tag2); +ALTER SCHEMA tag_schema4 TAG (tag1 = 'val3', tag4 = ''); +ALTER SCHEMA tag_schema5 TAG (tag4 = '', tag4 = ' '); +ALTER SCHEMA tag_schema6 TAG (tag4 = ' '); +ALTER SCHEMA tag_schema7 TAG (tag1 = 'val2', tag2 = '3'); +WARNING: object "tag_schema7" does not have tag "tag1", creating +WARNING: object "tag_schema7" does not have tag "tag2", creating +ALTER SCHEMA tag_schema7 UNSET TAG (tag1); +ALTER SCHEMA tag_schema8 TAG (tag4 = '123', tag4 = '123'); +WARNING: object "tag_schema8" does not have tag "tag4", creating +ALTER SCHEMA tag_schema9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +WARNING: object "tag_schema9" does not have tag "tag4", creating +ALTER SCHEMA tag_schema9 TAG (tag4 = '123'); +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + datname | nspname | tagname | tagvalue +----------+--------------+---------+----------------------------------------------------------------------------------- + postgres | tag_schema1 | tag1 | val1 + postgres | tag_schema10 | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + postgres | tag_schema2 | tag1 | val1 + postgres | tag_schema2 | tag2 | 10 + postgres | tag_schema3 | tag1 | val1 + postgres | tag_schema3 | tag2 | 1 + postgres | tag_schema4 | tag1 | val3 + postgres | tag_schema4 | tag2 | + postgres | tag_schema4 | tag4 | + postgres | tag_schema5 | tag2 | 300 + postgres | tag_schema5 | tag4 | + postgres | tag_schema6 | tag4 | + postgres | tag_schema7 | tag1 | + postgres | tag_schema7 | tag2 | 3 + postgres | tag_schema7 | tag4 | + postgres | tag_schema8 | tag1 | val1 + postgres | tag_schema8 | tag4 | 123 + postgres | tag_schema9 | tag4 | 123 +(18 rows) + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + nspname | nspowner +--------------+---------- + tag_schema1 | 10 + tag_schema10 | 10 + tag_schema2 | 10 + tag_schema3 | 10 + tag_schema4 | 10 + tag_schema5 | 10 + tag_schema6 | 10 + tag_schema7 | 10 + tag_schema8 | 10 + tag_schema9 | 10 +(10 rows) + +-- Drop Schema +DROP SCHEMA tag_schema1; +DROP SCHEMA tag_schema2; +DROP SCHEMA tag_schema3; +DROP SCHEMA tag_schema4; +DROP SCHEMA tag_schema5; +DROP SCHEMA tag_schema6; +DROP SCHEMA tag_schema7; +DROP SCHEMA tag_schema8; +DROP SCHEMA tag_schema9; +DROP SCHEMA tag_schema10; +SELECT * FROM schema_tag_descriptions +WHERE nspname like '%tag_schema%' +ORDER BY 1, 2, 3, 4; + datname | nspname | tagname | tagvalue +---------+---------+---------+---------- +(0 rows) + +SELECT nspname, nspowner FROM pg_namespace +WHERE nspname like '%tag_schema%' +ORDER BY 1; + nspname | nspowner +---------+---------- +(0 rows) + +-- Test Table with Tag +-- Create Table +CREATE TABLE tag_table1(a int, b varchar) TAG (tag1 = 'novalue'); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE TEMP TABLE tag_table1(a int, b varchar) TAG (tag1 = 'val1'); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG; -- error +ERROR: syntax error at or near ";" +LINE 1: CREATE TEMP TABLE tag_table2(a int, b varchar) TAG; + ^ +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG (); -- error +ERROR: syntax error at or near ")" +LINE 1: CREATE TEMP TABLE tag_table2(a int, b varchar) TAG (); + ^ +CREATE TABLE tag_table2(a int, b varchar) TAG (tag1 = ''); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag value "" is not in tag "tag1" allowed values +CREATE TEMP TABLE tag_table2(a int, b varchar) TAG (tag1 = 'val1', tag2 = '10'); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag1 = 'val2', tag1 = 'val1'); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag "tag1" value has been added for object "tag_table3". +CREATE TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag1 = 'novalue'); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE TEMP TABLE tag_table3(a int, b varchar) TAG (tag1 = 'val1', tag2 = '1'); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table4(a int, b varchar) TAG (tag1 = 'val1', tag2 = '3', tag4 = ''); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table5(a int, b varchar) TAG (tag2 = '300', tag4 = ' '); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = '', tag4 = ''); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag "tag4" value has been added for object "tag_table6". +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = ' ', tag4 = ' '); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag "tag4" value has been added for object "tag_table6". +CREATE TABLE tag_table6(a int, b varchar) TAG (tag4 = ''); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table7(a int, b varchar) TAG (tag4 = ' '); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table8(a int, b varchar) TAG (tag3 = ''); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag value "" is not in tag "tag3" allowed values +CREATE TABLE tag_table8(a int, b varchar) TAG (tag1 = 'novalue'); -- error +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +ERROR: tag value "novalue" is not in tag "tag1" allowed values +CREATE TABLE tag_table8(a int, b varchar) TAG (tag1 = 'val1'); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table9(a int, b varchar); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +CREATE TABLE tag_table10(a int, b varchar) TAG (tag3 = 'dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef'); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + datname | relname | relnamespace | relkind | tagname | tagvalue +----------+-------------+--------------+---------+---------+----------------------------------------------------------------------------------- + postgres | tag_table10 | public | r | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + postgres | tag_table4 | public | r | tag1 | val1 + postgres | tag_table4 | public | r | tag2 | 3 + postgres | tag_table4 | public | r | tag4 | + postgres | tag_table5 | public | r | tag2 | 300 + postgres | tag_table5 | public | r | tag4 | + postgres | tag_table6 | public | r | tag4 | + postgres | tag_table7 | public | r | tag4 | + postgres | tag_table8 | public | r | tag1 | val1 +(9 rows) + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + relname | relpersistence +-------------+---------------- + tag_table1 | t + tag_table10 | p + tag_table2 | t + tag_table3 | t + tag_table4 | p + tag_table5 | p + tag_table6 | p + tag_table7 | p + tag_table8 | p + tag_table9 | p +(10 rows) + +DROP TAG tag1; -- error +ERROR: tag "tag1" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag1 +tag of tag description with tag tag1 +DROP TAG tag2; -- error +ERROR: tag "tag2" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag2 +tag of tag description with tag tag2 +DROP TAG tag3; -- error +ERROR: tag "tag3" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag3 +DROP TAG tag4; -- error +ERROR: tag "tag4" cannot be dropped because some objects depend on it +DETAIL: tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +tag of tag description with tag tag4 +SELECT tagname, tagowner, allowed_values FROM pg_tag ORDER BY 1; + tagname | tagowner | allowed_values +---------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + tag1 | 10 | {val1,val2,val3} + tag2 | 10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300} + tag3 | 10 | {dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef} + tag4 | 10 | {123,456," ",""} +(4 rows) + +-- Alter Table +ALTER TABLE tag_table1 TAG (tag1 = 'val1', tag1 = 'val1'); +ALTER TABLE tag_table2 TAG (tag2 = '10'); +ALTER TABLE tag_table3 TAG (tag3 = ''); +ALTER TABLE tag_table4 UNSET TAG (tag1, tag2); +ALTER TABLE tag_table4 TAG (tag1 = 'val3', tag4 = ''); +ALTER TABLE tag_table5 TAG (tag4 = '', tag4 = ' '); +ALTER TABLE tag_table6 TAG (tag4 = ' '); +ALTER TABLE tag_table7 TAG (tag1 = 'val2', tag2 = '3'); +WARNING: object "tag_table7" does not have tag "tag1", creating +WARNING: object "tag_table7" does not have tag "tag2", creating +ALTER TABLE tag_table7 UNSET TAG (tag1); +ALTER TABLE tag_table8 TAG (tag4 = '123', tag4 = '123'); +WARNING: object "tag_table8" does not have tag "tag4", creating +ALTER TABLE tag_table9 TAG (tag4 = '', tag4 = '123', tag4 = '456'); +WARNING: object "tag_table9" does not have tag "tag4", creating +ALTER TABLE tag_table9 TAG (tag4 = '123'); +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + datname | relname | relnamespace | relkind | tagname | tagvalue +----------+-------------+--------------+---------+---------+----------------------------------------------------------------------------------- + postgres | tag_table10 | public | r | tag3 | dadkqjefpqfqfqe4l123j9i1snkqenp3412n4jnflqjenfaddpiqepj21304i12;kfnqpqnepfqefqwef + postgres | tag_table4 | public | r | tag1 | val3 + postgres | tag_table4 | public | r | tag2 | + postgres | tag_table4 | public | r | tag4 | + postgres | tag_table5 | public | r | tag2 | 300 + postgres | tag_table5 | public | r | tag4 | + postgres | tag_table6 | public | r | tag4 | + postgres | tag_table7 | public | r | tag1 | + postgres | tag_table7 | public | r | tag2 | 3 + postgres | tag_table7 | public | r | tag4 | + postgres | tag_table8 | public | r | tag1 | val1 + postgres | tag_table8 | public | r | tag4 | 123 + postgres | tag_table9 | public | r | tag4 | 123 +(13 rows) + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + relname | relpersistence +-------------+---------------- + tag_table1 | t + tag_table10 | p + tag_table2 | t + tag_table3 | t + tag_table4 | p + tag_table5 | p + tag_table6 | p + tag_table7 | p + tag_table8 | p + tag_table9 | p +(10 rows) + +-- Drop Table +DROP TABLE tag_table1; +DROP TABLE tag_table2; +DROP TABLE tag_table3; +DROP TABLE tag_table4; +DROP TABLE tag_table5; +DROP TABLE tag_table6; +DROP TABLE tag_table7; +DROP TABLE tag_table8; +DROP TABLE tag_table9; +DROP TABLE tag_table10; +SELECT * FROM relation_tag_descriptions +WHERE relname like '%tag_table%' +ORDER BY 1, 2, 3, 4, 5, 6; + datname | relname | relnamespace | relkind | tagname | tagvalue +---------+---------+--------------+---------+---------+---------- +(0 rows) + +SELECT relname, relpersistence FROM pg_class +WHERE relname like '%tag_table%' +ORDER BY 1; + relname | relpersistence +---------+---------------- +(0 rows) + +-- Cleanup +DROP TAG tag1; +DROP TAG tag2; +DROP TAG tag3; +DROP TAG tag4; +DROP DATABASE other_db; diff --git a/src/test/singlenode_regress/parallel_schedule b/src/test/singlenode_regress/parallel_schedule index 54ccd53cfe0..de48b399543 100644 --- a/src/test/singlenode_regress/parallel_schedule +++ b/src/test/singlenode_regress/parallel_schedule @@ -166,3 +166,6 @@ test: fast_default # run stats by itself because its delay may be insufficient under heavy load test: stats + +# test of tag +test: tag diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 9cecc124ce3..c496a76a87a 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -66,6 +66,7 @@ AlterCollationStmt AlterDatabaseSetStmt AlterDatabaseStmt AlterDefaultPrivilegesStmt +AlterDirectoryTableStmt AlterDomainStmt AlterEnumStmt AlterEventTrigStmt @@ -84,6 +85,7 @@ AlterProfileStmt AlterPublicationStmt AlterRoleSetStmt AlterRoleStmt +AlterSchemaStmt AlterSeqStmt AlterStatsStmt AlterStorageServer @@ -91,6 +93,7 @@ AlterStorageUserMappingStmt AlterSubscriptionStmt AlterSubscriptionType AlterSystemStmt +AlterTagStmt AlterTSConfigType AlterTSConfigurationStmt AlterTSDictionaryStmt @@ -462,6 +465,7 @@ CoverPos CreateAmStmt CreateCastStmt CreateConversionStmt +CreateDirectoryTableStmt CreateDomainStmt CreateEnumStmt CreateEventTrigStmt @@ -491,6 +495,7 @@ CreateStorageUserMappingStmt CreateSubscriptionStmt CreateTableAsStmt CreateTableSpaceStmt +CreateTagStmt CreateTransformStmt CreateTrigStmt CreateUserMappingStmt @@ -580,6 +585,7 @@ DropStorageServer DropStorageUserMappingStmt DropSubscriptionStmt DropTableSpaceStmt +DropTagStmt DropUserMappingStmt DropdbStmt DumpComponents From 5ddad9467439dd768fee2db85870c51347a136e8 Mon Sep 17 00:00:00 2001 From: zhangwenchao <656540940@qq.com> Date: Mon, 8 Jul 2024 10:44:59 +0800 Subject: [PATCH 2/2] Fix singlenode mode isolation2 expected results not stable. As there are three ao/aocs tables in the prevent_ao_wal isolation2 test, the expected results of wal are not stable after VACUUM. We fix this by truncate unrelated table in lockmodes test. Authored-by: Zhang Wenchao zwcpostgres@gmail.com --- src/test/regress/expected/misc_sanity_external_fts.out | 4 +++- src/test/singlenode_isolation2/expected/lockmodes.out | 3 +++ src/test/singlenode_isolation2/expected/prevent_ao_wal.out | 2 -- src/test/singlenode_isolation2/sql/lockmodes.sql | 2 ++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/test/regress/expected/misc_sanity_external_fts.out b/src/test/regress/expected/misc_sanity_external_fts.out index 1c0ac1b7ccb..ca783a4aa70 100644 --- a/src/test/regress/expected/misc_sanity_external_fts.out +++ b/src/test/regress/expected/misc_sanity_external_fts.out @@ -122,6 +122,8 @@ ORDER BY 1, 2; pg_resqueuecapability | ressetting | text pg_stat_last_operation | stasubtype | text pg_stat_last_shoperation | stasubtype | text + pg_tag | allowed_values | text[] + pg_tag_description | tagvalue | text pg_task | command | text pg_task | database | text pg_task | jobname | text @@ -133,7 +135,7 @@ ORDER BY 1, 2; pg_task_run_history | return_message | text pg_task_run_history | status | text pg_task_run_history | username | text -(31 rows) +(33 rows) -- system catalogs without primary keys -- diff --git a/src/test/singlenode_isolation2/expected/lockmodes.out b/src/test/singlenode_isolation2/expected/lockmodes.out index 8ec759ee242..89046e72b69 100644 --- a/src/test/singlenode_isolation2/expected/lockmodes.out +++ b/src/test/singlenode_isolation2/expected/lockmodes.out @@ -1089,3 +1089,6 @@ UPDATE 1 1: ROLLBACK; ROLLBACK 1q: ... + +TRUNCATE t_lockmods_ao; +TRUNCATE diff --git a/src/test/singlenode_isolation2/expected/prevent_ao_wal.out b/src/test/singlenode_isolation2/expected/prevent_ao_wal.out index 9b6c36805e4..789053d3e32 100644 --- a/src/test/singlenode_isolation2/expected/prevent_ao_wal.out +++ b/src/test/singlenode_isolation2/expected/prevent_ao_wal.out @@ -75,7 +75,6 @@ rmgr: Appendonly len (rec/tot): 146/ 146, tx: 12664, lsn: 0/F8000B38, rmgr: Appendonly len (rec/tot): 58/ 58, tx: 12665, lsn: 0/F8000C98, prev 0/F8000C68, desc: APPENDONLY_TRUNCATE truncate: rel 1663/221728/180472 seg/offset:0/0 rmgr: Appendonly len (rec/tot): 58/ 58, tx: 0, lsn: 0/F80412F8, prev 0/F80412C8, desc: APPENDONLY_TRUNCATE truncate: rel 1663/221728/180476 seg/offset:0/80 rmgr: Appendonly len (rec/tot): 58/ 58, tx: 0, lsn: 0/F8041338, prev 0/F80412F8, desc: APPENDONLY_TRUNCATE truncate: rel 1663/221728/180476 seg/offset:128/80 -rmgr: Appendonly len (rec/tot): 58/ 58, tx: 0, lsn: 0/F80D2020, prev 0/F80D1FF0, desc: APPENDONLY_TRUNCATE truncate: rel 1663/221728/180445 seg/offset:0/112 rmgr: Appendonly len (rec/tot): 58/ 58, tx: 0, lsn: 0/F8307118, prev 0/F83070E8, desc: APPENDONLY_TRUNCATE truncate: rel 1663/221728/180472 seg/offset:1/88 rmgr: Appendonly len (rec/tot): 58/ 58, tx: 0, lsn: 0/F8307158, prev 0/F8307118, desc: APPENDONLY_TRUNCATE truncate: rel 1663/221728/180472 seg/offset:0/0 rmgr: Appendonly len (rec/tot): 58/ 58, tx: 0, lsn: 0/F8307208, prev 0/F83071D8, desc: APPENDONLY_TRUNCATE truncate: rel 1663/221728/180476 seg/offset:0/80 @@ -86,7 +85,6 @@ rmgr: Appendonly len (rec/tot): 122/ 122, tx: 12673, lsn: 0/F83075A0, rmgr: Appendonly len (rec/tot): 122/ 122, tx: 12673, lsn: 0/F8307620, prev 0/F83075A0, desc: APPENDONLY_INSERT insert: rel 1663/221728/180476 seg/offset:129/0 len:64 rmgr: Appendonly len (rec/tot): 58/ 58, tx: 12674, lsn: 0/F8307780, prev 0/F8307750, desc: APPENDONLY_TRUNCATE truncate: rel 1663/221728/180476 seg/offset:0/0 rmgr: Appendonly len (rec/tot): 58/ 58, tx: 12674, lsn: 0/F83077C0, prev 0/F8307780, desc: APPENDONLY_TRUNCATE truncate: rel 1663/221728/180476 seg/offset:128/0 -rmgr: Appendonly len (rec/tot): 58/ 58, tx: 0, lsn: 0/F8327BF0, prev 0/F8327BC0, desc: APPENDONLY_TRUNCATE truncate: rel 1663/221728/180445 seg/offset:0/112 -- *********** Set wal_level=minimal ************** diff --git a/src/test/singlenode_isolation2/sql/lockmodes.sql b/src/test/singlenode_isolation2/sql/lockmodes.sql index 25f071769c0..d2513f82658 100644 --- a/src/test/singlenode_isolation2/sql/lockmodes.sql +++ b/src/test/singlenode_isolation2/sql/lockmodes.sql @@ -381,3 +381,5 @@ create table t_lockmods_ao1 (c int) with (appendonly=true); 1: select * from show_locks_lockmodes; 1: ROLLBACK; 1q: + +TRUNCATE t_lockmods_ao;