diff --git a/docs/en_US/images/type_range.png b/docs/en_US/images/type_range.png index 43eeac562..f063cbff8 100644 Binary files a/docs/en_US/images/type_range.png and b/docs/en_US/images/type_range.png differ diff --git a/docs/en_US/release_notes.rst b/docs/en_US/release_notes.rst index 79e899148..7db716697 100644 --- a/docs/en_US/release_notes.rst +++ b/docs/en_US/release_notes.rst @@ -12,6 +12,7 @@ notes for it. :maxdepth: 1 + release_notes_9_9 release_notes_9_8 release_notes_9_7 release_notes_9_6 diff --git a/docs/en_US/release_notes_9_9.rst b/docs/en_US/release_notes_9_9.rst new file mode 100644 index 000000000..1236a37a3 --- /dev/null +++ b/docs/en_US/release_notes_9_9.rst @@ -0,0 +1,33 @@ +*********** +Version 9.9 +*********** + +Release date: 2025-10-16 + +This release contains a number of bug fixes and new features since the release of pgAdmin 4 v9.8. + +Supported Database Servers +************************** +**PostgreSQL**: 13, 14, 15, 16 and 17 + +**EDB Advanced Server**: 13, 14, 15, 16 and 17 + +Bundled PostgreSQL Utilities +**************************** +**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 17.5 + + +New features +************ + + | `Issue #6394 `_ - Added "MULTIRANGE_TYPE_NAME" option while creating a Range Type. + | `Issue #6395 `_ - Added "SUBSCRIPT" option while creating a External Type. + + +Housekeeping +************ + + +Bug fixes +********* + diff --git a/docs/en_US/type_dialog.rst b/docs/en_US/type_dialog.rst index 9cc9567ba..db3e29340 100644 --- a/docs/en_US/type_dialog.rst +++ b/docs/en_US/type_dialog.rst @@ -109,17 +109,17 @@ On the *Optional-1* tab: to select a type_modifier_output_function. It is allowed to omit the type_modifier_output_function, in which case the default display format is the stored typmod integer value enclosed in parentheses. +* Use the drop-down listbox next to the optional *Analyze function* field to + select a function for performing type-specific statistics collection for + columns of the data type. +* Use the drop-down listbox next to the optional *Subscript function* field to + select a function for allows the data type to be subscripted in SQL commands. * Use the optional *Internal length* to specify a value for internal representation. -* Move the *Variable?* switch to specify the internal representation is of - variable length (VARIABLE). The default is a fixed length positive integer. * Specify a default value in the optional *Default* field in cases where a column of the data type defaults to something other than the null value. Specify the default with the DEFAULT key word. (A default can be overridden by an explicit DEFAULT clause attached to a particular column.) -* Use the drop-down listbox next to the optional *Analyze function* field to - select a function for performing type-specific statistics collection for - columns of the data type. * Use the drop-down listbox next to the optional *Category type* field to help control which implicit cast will be applied in ambiguous situations. * Move the *Preferred?* switch to *Yes* to specify the selected category type is @@ -162,6 +162,9 @@ disabled. values to a canonical form. * Use the drop-down listbox next to *Sub-type diff function* to select a user-defined subtype_diff function. +* Specify the optional *Multirange type name* parameter to specifies the + name of the corresponding multirange type. If not specified, this name is + chosen automatically. If you select *Shell* in the *Type* field, the *Definition* tab displays the *Shell* panel: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py index a757b825e..758a150d8 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py @@ -249,6 +249,15 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): return wrap + def has_dependent_type(self, data): + """ + This function is used to check the type has dependent + on another type. + """ + return ('rngmultirangetype' in data and + data['rngmultirangetype'] is not None and + data['rngmultirangetype'] != '') + @check_precondition def list(self, gid, sid, did, scid): """ @@ -317,7 +326,8 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): rset['rows'][0]['oid'], scid, rset['rows'][0]['name'], - icon=self.icon_str % self.node_type + icon=self.icon_str % self.node_type, + has_dependent=self.has_dependent_type(rset['rows'][0]) ) return make_json_response( @@ -359,7 +369,8 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): scid, row['name'], icon=self.icon_str % self.node_type, - description=row['description'] + description=row['description'], + has_dependent=self.has_dependent_type(row) )) return make_json_response( @@ -536,7 +547,8 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): enum_list = [] for row in rset['rows']: properties_list.append(row['enumlabel']) - enum_list.append({'label': row['enumlabel']}) + enum_list.append({'label': row['enumlabel'], + 'old_label': row['enumlabel']}) # Adding both results in ouput res['enum_list'] = ', '.join(properties_list) @@ -1063,7 +1075,8 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): tid, scid, data['name'], - icon="icon-type" + icon="icon-type", + has_dependent=self.has_dependent_type(data) ) ) except Exception as e: @@ -1086,7 +1099,7 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): request.data ) try: - SQL, name = self.get_sql(gid, sid, data, scid, tid) + SQL, name, has_dependent = self.get_sql(gid, sid, data, scid, tid) # Most probably this is due to error if not isinstance(SQL, str): return SQL @@ -1114,6 +1127,7 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): scid, name, icon=self.icon_str % self.node_type, + has_dependent=has_dependent, **other_node_info ) ) @@ -1226,11 +1240,15 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): for key, val in req.items(): if key in ['composite', 'enum', 'seclabels', 'typacl']: data[key] = json.loads(val) + elif key in ['typreceive', 'typsend', 'typmodin', 'typmodout', + 'typanalyze', 'typsubscript','typstorage'] and \ + val == 'null': + data[key] = json.loads(val) else: data[key] = val try: - sql, _ = self.get_sql(gid, sid, data, scid, tid) + sql, _, _ = self.get_sql(gid, sid, data, scid, tid) # Most probably this is due to error if not isinstance(sql, str): return sql @@ -1330,7 +1348,7 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): self._CREATE_SQL]), data=data, conn=self.conn, is_sql=is_sql) - return SQL, data['name'] + return SQL, data['name'], False def get_sql(self, gid, sid, data, scid, tid=None, is_sql=False): """ @@ -1339,6 +1357,8 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): if tid is None: return self._get_new_sql(data, is_sql) + data = self._convert_for_sql(data) + for key in ['added', 'changed', 'deleted']: if key in data.get('typacl', []): data['typacl'][key] = parse_priv_to_db( @@ -1411,7 +1431,8 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): data=data, o_data=old_data, conn=self.conn ) - return SQL, old_data['name'] + return (SQL, data['name'] if 'name' in data else old_data['name'], + self.has_dependent_type(old_data)) @check_precondition def sql(self, gid, sid, did, scid, tid, **kwargs): @@ -1478,7 +1499,7 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): if data[k] == '-': data[k] = None - SQL, _ = self.get_sql(gid, sid, data, scid, tid=None, is_sql=True) + SQL, _, _ = self.get_sql(gid, sid, data, scid, tid=None, is_sql=True) # Most probably this is due to error if not isinstance(SQL, str): return SQL @@ -1588,8 +1609,8 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): if data: if target_schema: data['schema'] = target_schema - sql, _ = self.get_sql(gid=gid, sid=sid, scid=scid, data=data, - tid=oid) + sql, _, _ = self.get_sql(gid=gid, sid=sid, scid=scid, data=data, + tid=oid) else: if drop_sql: sql = self.delete(gid=gid, sid=sid, did=did, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js index d1027da26..eedebd680 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js @@ -42,6 +42,9 @@ define('pgadmin.node.type', [ hasSQL: true, hasDepends: true, width: pgBrowser.stdW.md + 'px', + refreshParent: function(node) { + return node?._metadata?.data?.has_dependent; + }, Init: function() { /* Avoid multiple registration of menus */ if (this.initialized) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js index 57cfa78f3..94611ab04 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js @@ -192,7 +192,6 @@ function isVisible(state, type) { } class EnumerationSchema extends BaseUISchema { - constructor() { super({ oid: undefined, @@ -201,18 +200,14 @@ class EnumerationSchema extends BaseUISchema { } get idAttribute() { - return 'oid'; + return 'old_label'; } get baseFields() { - let obj = this; return [ { id: 'label', label: gettext('Label'), type: 'text', cell: 'text', minWidth: 620, - editable: (state) => { - return _.isUndefined(obj.isNew) ? true : obj.isNew(state); - } } ]; } @@ -395,6 +390,15 @@ class RangeSchema extends BaseUISchema { } }; }, + }, { + id: 'rngmultirangetype', label: gettext('Multirange type name'), + cell: 'string', group: gettext('Range Type'), + type: 'text', mode: ['properties', 'create', 'edit'], + disabled: () => obj.inCatalog(), + readonly: function (state) { + return !obj.isNew(state); + }, + min_version: 140000, } ]; } @@ -562,9 +566,6 @@ class ExternalSchema extends BaseUISchema { group: gettext('Optional-1'), mode: ['properties', 'create', 'edit'], disabled: () => obj.inCatalog(), - readonly: function (state) { - return !obj.isNew(state); - }, controlProps: { allowClear: true, placeholder: '', width: '100%' }, },{ id: 'typsend', label: gettext('Send function'), @@ -586,9 +587,6 @@ class ExternalSchema extends BaseUISchema { }, mode: ['properties', 'create', 'edit'], disabled: () => obj.inCatalog(), - readonly: function (state) { - return !obj.isNew(state); - }, controlProps: { allowClear: true, placeholder: '', width: '100%' }, },{ id: 'typmodin', label: gettext('Typmod in function'), @@ -623,9 +621,6 @@ class ExternalSchema extends BaseUISchema { }, mode: ['properties', 'create', 'edit'], group: gettext('Optional-1'), disabled: () => obj.inCatalog(), - readonly: function (state) { - return !obj.isNew(state); - }, controlProps: { allowClear: true, placeholder: '', width: '100%' }, },{ id: 'typmodout', label: gettext('Typmod out function'), @@ -661,9 +656,24 @@ class ExternalSchema extends BaseUISchema { }, mode: ['properties', 'create', 'edit'], disabled: () => obj.inCatalog(), - readonly: function (state) { - return !obj.isNew(state); + },{ + id: 'typanalyze', label: gettext('Analyze function'), + group: gettext('Optional-1'), + type: (state) => { + return obj.getFunctionType(state); }, + mode: ['properties', 'create','edit'], + disabled: () => obj.inCatalog(), + controlProps: { allowClear: true, placeholder: '', width: '100%' }, + },{ + id: 'typsubscript', label: gettext('Subscript function'), + group: gettext('Optional-1'), min_version: 140000, + type: (state) => { + return obj.getFunctionType(state); + }, + mode: ['properties', 'create','edit'], + disabled: () => obj.inCatalog(), + controlProps: { allowClear: true, placeholder: '', width: '100%' }, },{ id: 'typlen', label: gettext('Internal length'), cell: 'integer', group: gettext('Optional-1'), @@ -672,14 +682,6 @@ class ExternalSchema extends BaseUISchema { readonly: function (state) { return !obj.isNew(state); }, - },{ - id: 'variable', label: gettext('Variable?'), cell: 'switch', - group: gettext('Optional-1'), type: 'switch', - mode: ['create','edit'], - disabled: () => obj.inCatalog(), - readonly: function (state) { - return !obj.isNew(state); - }, },{ id: 'typdefault', label: gettext('Default?'), cell: 'string', group: gettext('Optional-1'), @@ -688,18 +690,6 @@ class ExternalSchema extends BaseUISchema { readonly: function (state) { return !obj.isNew(state); }, - },{ - id: 'typanalyze', label: gettext('Analyze function'), - group: gettext('Optional-1'), - type: (state) => { - return obj.getFunctionType(state); - }, - mode: ['properties', 'create','edit'], - disabled: () => obj.inCatalog(), - readonly: function (state) { - return !obj.isNew(state); - }, - controlProps: { allowClear: true, placeholder: '', width: '100%' }, },{ id: 'typcategory', label: gettext('Category type'), cell: 'string', @@ -792,9 +782,6 @@ class ExternalSchema extends BaseUISchema { type: 'select', mode: ['properties', 'create', 'edit'], group: gettext('Optional-2'), cell: 'string', disabled: () => obj.inCatalog(), - readonly: function (state) { - return !obj.isNew(state); - }, controlProps: { allowClear: true, placeholder: '', width: '100%' }, options: obj.fieldOptions.typStorageOptions, },{ @@ -1258,14 +1245,13 @@ export default class TypeSchema extends BaseUISchema { }, { id: 'typtype', label: gettext('Type'), - mode: ['create','edit'], group: gettext('Definition'), - type: 'select', + mode: ['create','edit', 'properties'], group: gettext('Definition'), disabled: () => obj.inCatalog(), readonly: function (state) { return !obj.isNew(state); }, controlProps: { allowClear: false }, - options: function() { + type: (state)=>{ let typetype = [ {label: gettext('Composite'), value: 'c'}, {label: gettext('Enumeration'), value: 'e'}, @@ -1273,6 +1259,13 @@ export default class TypeSchema extends BaseUISchema { {label: gettext('Range'), value: 'r'}, {label: gettext('Shell'), value: 'p'}, ]; + + if (!obj.isNew(state)) { + typetype.push( + {label: gettext('Multirange'), value: 'm'} + ); + } + if (obj.fieldOptions.server_info.server_type === 'ppas' && obj.fieldOptions.server_info.version >= 90500){ typetype.push( @@ -1280,7 +1273,12 @@ export default class TypeSchema extends BaseUISchema { {label: gettext('Varying Array'), value: 'V'} ); } - return typetype; + + return { + type: 'select', + options: typetype, + optionsReloadBasis: state.typtype, + }; }, }, { @@ -1305,6 +1303,7 @@ export default class TypeSchema extends BaseUISchema { schema: new EnumerationSchema(), type: 'collection', group: gettext('Definition'), mode: ['edit', 'create'], + uniqueCol: ['label'], canAddRow: function(state) { return !obj.isInvalidColumnAdded(state); }, @@ -1389,6 +1388,12 @@ export default class TypeSchema extends BaseUISchema { disabled: () => obj.inCatalog(), visible: (state) => isVisible(state, 'r'), }, + { + id: 'rngmultirangetype', label: gettext('Multirange type name'), cell: 'string', + type: 'text', mode: ['properties'], group: gettext('Definition'), + disabled: () => obj.inCatalog(), + visible: (state) => isVisible(state, 'r'), + }, { id: 'typinput', label: gettext('Input function'), cell: 'string', type: 'text', mode: ['properties'], group: gettext('Definition'), diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/additional_properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/additional_properties.sql new file mode 100644 index 000000000..0f5ae3994 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/additional_properties.sql @@ -0,0 +1,45 @@ +{# The SQL given below will fetch composite type#} +{% if typtype == 'c' %} +SELECT attnum, attname, pg_catalog.format_type(t.oid,NULL) AS typname, attndims, atttypmod, nsp.nspname, + (SELECT COUNT(1) from pg_catalog.pg_type t2 WHERE t2.typname=t.typname) > 1 AS isdup, + collname, nspc.nspname as collnspname, att.attrelid, + pg_catalog.format_type(t.oid, att.atttypmod) AS fulltype, + CASE WHEN t.typelem > 0 THEN t.typelem ELSE t.oid END as elemoid +FROM pg_catalog.pg_attribute att + JOIN pg_catalog.pg_type t ON t.oid=atttypid + JOIN pg_catalog.pg_namespace nsp ON t.typnamespace=nsp.oid + LEFT OUTER JOIN pg_catalog.pg_type b ON t.typelem=b.oid + LEFT OUTER JOIN pg_catalog.pg_collation c ON att.attcollation=c.oid + LEFT OUTER JOIN pg_catalog.pg_namespace nspc ON c.collnamespace=nspc.oid + WHERE att.attrelid = {{typrelid}}::oid + ORDER by attnum; +{% endif %} + +{# The SQL given below will fetch enum type#} +{% if typtype == 'e' %} +SELECT enumlabel +FROM pg_catalog.pg_enum + WHERE enumtypid={{tid}}::oid + ORDER by enumsortorder +{% endif %} + +{# The SQL given below will fetch range type#} +{% if typtype == 'r' %} +SELECT rngsubtype, st.typname, + rngcollation, mt.typname as rngmultirangetype, + CASE WHEN n.nspname IS NOT NULL THEN pg_catalog.concat(pg_catalog.quote_ident(n.nspname), '.', pg_catalog.quote_ident(col.collname)) ELSE col.collname END AS collname, + rngsubopc, opc.opcname, + rngcanonical, rngsubdiff as rngsubdiff_proc, + CASE WHEN length(ns.nspname::text) > 0 AND length(pgpr.proname::text) > 0 THEN + pg_catalog.concat(quote_ident(ns.nspname), '.', pg_catalog.quote_ident(pgpr.proname)) + ELSE '' END AS rngsubdiff +FROM pg_catalog.pg_range + LEFT JOIN pg_catalog.pg_type st ON st.oid=rngsubtype + LEFT JOIN pg_catalog.pg_type mt ON mt.oid=rngmultitypid + LEFT JOIN pg_catalog.pg_collation col ON col.oid=rngcollation + LEFT JOIN pg_catalog.pg_namespace n ON col.collnamespace=n.oid + LEFT JOIN pg_catalog.pg_opclass opc ON opc.oid=rngsubopc + LEFT JOIN pg_catalog.pg_proc pgpr ON pgpr.oid = rngsubdiff + LEFT JOIN pg_catalog.pg_namespace ns ON ns.oid=pgpr.pronamespace + WHERE rngtypid={{tid}}::oid; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/create.sql new file mode 100644 index 000000000..924eaa483 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/create.sql @@ -0,0 +1,86 @@ +{% import 'macros/schemas/security.macros' as SECLABEL %} +{% import 'macros/schemas/privilege.macros' as PRIVILEGE %} +{% import 'types/macros/get_full_type_sql_format.macros' as GET_TYPE %} +{## If user selected shell type then just create type template ##} +{% if data and data.typtype == 'p' %} +CREATE TYPE {{ conn|qtIdent(data.schema, data.name) }}; +{% endif %} +{### Composite Type ###} +{% if data and data.typtype == 'c' %} +CREATE TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} AS +({{"\n\t"}}{% if data.composite %}{% for d in data.composite %}{% if loop.index != 1 %},{{"\n\t"}}{% endif %}{{ conn|qtIdent(d.member_name) }} {% if is_sql %}{{ d.fulltype }}{% else %}{{ GET_TYPE.CREATE_TYPE_SQL(conn, d.cltype, d.tlength, d.precision, d.hasSqrBracket) }}{% endif %}{% if d.collation %} COLLATE {{d.collation}}{% endif %}{% endfor %}{% endif %}{{"\n"}}); +{% endif %} +{### Enum Type ###} +{% if data and data.typtype == 'e' %} +CREATE TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} AS ENUM + ({% for e in data.enum %}{% if loop.index != 1 %}, {% endif %}{{ e.label|qtLiteral(conn) }}{% endfor %}); +{% endif %} +{### Range Type ###} +{% if data and data.typtype == 'r' %} +CREATE TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} AS RANGE +( + {% if data.typname %}SUBTYPE={{ conn|qtTypeIdent(data.typname) }}{% endif %}{% if data.collname %}, + COLLATION = {{ data.collname }}{% endif %}{% if data.opcname %}, + SUBTYPE_OPCLASS = {{ data.opcname }}{% endif %}{% if data.rngcanonical %}, + CANONICAL = {{ data.rngcanonical }}{% endif %}{% if data.rngsubdiff %}, + SUBTYPE_DIFF = {{ data.rngsubdiff }}{% endif %}{% if data.rngmultirangetype %}, + MULTIRANGE_TYPE_NAME = {{ data.rngmultirangetype }}{% endif %} + +); +{% endif %} +{### External Type ###} +{% if data and data.typtype == 'b' %} +CREATE TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} + +( + {% if data.typinput %}INPUT = {{data.typinput}}{% endif %}{% if data.typoutput %}, + OUTPUT = {{ data.typoutput }}{% endif %}{% if data.typreceive %}, + RECEIVE = {{data.typreceive}}{% endif %}{% if data.typsend %}, + SEND = {{data.typsend}}{% endif %}{% if data.typmodin %}, + TYPMOD_IN = {{data.typmodin}}{% endif %}{% if data.typmodout %}, + TYPMOD_OUT = {{data.typmodout}}{% endif %}{% if data.typanalyze %}, + ANALYZE = {{data.typanalyze}}{% endif %}{% if data.typsubscript %}, + SUBSCRIPT = {{data.typsubscript}}{% endif %}{% if data.typlen %}, + INTERNALLENGTH = {{data.typlen}}{% endif %}{% if data.typbyval %}, + PASSEDBYVALUE{% endif %}{% if data.typalign %}, + ALIGNMENT = {{data.typalign}}{% endif %}{% if data.typstorage %}, + STORAGE = {{data.typstorage}}{% endif %}{% if data.typcategory %}, + CATEGORY = {{data.typcategory|qtLiteral(conn)}}{% endif %}{% if data.typispreferred %}, + PREFERRED = {{data.typispreferred}}{% endif %}{% if data.typdefault %}, + DEFAULT = {{data.typdefault|qtLiteral(conn)}}{% endif %}{% if data.element %}, + ELEMENT = {{data.element}}{% endif %}{% if data.typdelim %}, + DELIMITER = {{data.typdelim|qtLiteral(conn)}}{% endif %}{% if data.is_collatable %}, + COLLATABLE = {{data.is_collatable}}{% endif %} + +); +{% endif %} +{### Type Owner ###} +{% if data and data.typeowner %} + +ALTER TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} + + OWNER TO {{ conn|qtIdent(data.typeowner) }}; +{% endif %} +{### Type Comments ###} +{% if data and data.description %} + +COMMENT ON TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} + + IS {{data.description|qtLiteral(conn)}}; +{% endif %} +{### ACL ###} +{% if data.typacl %} + +{% for priv in data.typacl %} +{{ PRIVILEGE.SET(conn, 'TYPE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }} +{% endfor %} +{% endif %} +{### Security Lables ###} +{% if data.seclabels %} + +{% for r in data.seclabels %} +{% if r.provider and r.label %} +{{ SECLABEL.SET(conn, 'TYPE', data.name, r.provider, r.label, data.schema) }} +{% endif %} +{% endfor %} +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/nodes.sql new file mode 100644 index 000000000..9469379f5 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/nodes.sql @@ -0,0 +1,19 @@ +SELECT t.oid, t.typname AS name, des.description, ra.rngmultitypid as rngmultirangetype +FROM pg_catalog.pg_type t + LEFT OUTER JOIN pg_catalog.pg_type e ON e.oid=t.typelem + LEFT OUTER JOIN pg_catalog.pg_range ra ON ra.rngtypid=t.oid + LEFT OUTER JOIN pg_catalog.pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c' + LEFT OUTER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = t.typnamespace + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=t.oid AND des.classoid='pg_type'::regclass) +WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%' AND t.typnamespace = {{scid}}::oid +{% if tid %} + AND t.oid = {{tid}}::oid +{% endif %} +{% if not show_system_objects %} + AND ct.oid is NULL +{% endif %} +{% if schema_diff %} + AND CASE WHEN (SELECT COUNT(*) FROM pg_catalog.pg_depend + WHERE objid = t.oid AND deptype = 'e') > 0 THEN FALSE ELSE TRUE END +{% endif %} +ORDER BY t.typname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/properties.sql new file mode 100644 index 000000000..66d66e56c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/properties.sql @@ -0,0 +1,45 @@ +SELECT t.oid, t.typname AS name, + (CASE WHEN CAST(coalesce(t.typcollation, '0') AS integer) = 100 THEN true ElSE false END) AS is_collatable, + t.typacl AS type_acl, + t.typnamespace, t.typowner, t.typlen, t.typbyval, t.typtype, + t.typcategory, t.typispreferred, t.typisdefined, t.typdelim, + t.typrelid, t.typelem, t.typarray, t.typalign, t.typstorage, + t.typnotnull, t.typbasetype, t.typtypmod, t.typndims, + t.typcollation, t.typdefaultbin, t.typdefault, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typinput::oid) AS typinput, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typoutput::oid) AS typoutput, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typreceive::oid) AS typreceive, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typsend::oid) AS typsend, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typmodin::oid) AS typmodin, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typmodout::oid) AS typmodout, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typanalyze::oid) AS typanalyze, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typsubscript::oid) AS typsubscript, + pg_catalog.format_type(t.oid, null) AS alias, + pg_catalog.pg_get_userbyid(t.typowner) as typeowner, e.typname as element, + description, ct.oid AS taboid, + nsp.nspname AS schema, + --MinimumVersion 9.1 START + (SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_seclabel sl1 WHERE sl1.objoid=t.oid) AS seclabels, + -- END + (CASE WHEN (t.oid <= {{ datlastsysoid}}::oid OR ct.oid != 0) THEN true ElSE false END) AS is_sys_type +FROM pg_catalog.pg_type t + LEFT OUTER JOIN pg_catalog.pg_type e ON e.oid=t.typelem + LEFT OUTER JOIN pg_catalog.pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c' + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=t.oid AND des.classoid='pg_type'::regclass) + LEFT OUTER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = t.typnamespace +WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%' AND t.typnamespace = {{scid}}::oid +{% if tid %} + AND t.oid = {{tid}}::oid +{% endif %} +{% if not show_system_objects %} + AND ct.oid is NULL +{% endif %} +ORDER BY t.typname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/update.sql new file mode 100644 index 000000000..008b3e8e1 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/14_plus/update.sql @@ -0,0 +1,183 @@ +{% import 'macros/schemas/security.macros' as SECLABEL %} +{% import 'macros/schemas/privilege.macros' as PRIVILEGE %} +{% import 'types/macros/get_full_type_sql_format.macros' as GET_TYPE %} +{#======================================#} +{# Below will change object owner #} +{% if data.typeowner and data.typeowner != o_data.typeowner %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + OWNER TO {{ conn|qtIdent(data.typeowner) }}; + +{% endif %} +{#======================================#} +{# Below will change objects comment #} +{% if data.description is defined and data.description != o_data.description %} +COMMENT ON TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + IS {{ data.description|qtLiteral(conn) }}; + +{% endif %} +{#======================================#} +{### The sql given below will update composite type ###} +{% if data.composite and data.composite|length > 0 %} +{% set composite = data.composite %} +{% if 'deleted' in composite and composite.deleted|length > 0 %} +{% for r in composite.deleted %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + DROP ATTRIBUTE {{conn|qtIdent(r.member_name)}}; +{% endfor %} +{% endif %} +{% if 'added' in composite and composite.added|length > 0 %} +{% for r in composite.added %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + ADD ATTRIBUTE {{conn|qtIdent(r.member_name)}} {{ GET_TYPE.CREATE_TYPE_SQL(conn, r.cltype, r.tlength, r.precision, r.hasSqrBracket) }}{% if r.collation %} + COLLATE {{r.collation}}{% endif %}; +{% endfor %} +{% endif %} +{% if 'changed' in composite and composite.changed|length > 0 %} +{% for r in composite.changed %} +{% for o in o_data.composite %} +{##### Variables for the loop #####} +{% set member_name = o.member_name %} +{% set cltype = o.cltype %} +{% set tlength = o.tlength %} +{% set precision = o.precision %} +{% set hasSqrBracket = o.hasSqrBracket %} +{##### If member name changed #####} +{% if o.attnum == r.attnum %} +{% if r.member_name and o.member_name != r.member_name %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + RENAME ATTRIBUTE {{o.member_name}} TO {{r.member_name}}; +{% set member_name = r.member_name %} +{% endif %} +{##### If type changed #####} +{% if r.cltype and cltype != r.cltype %} +{% set cltype = r.cltype %} +{% set hasSqrBracket = r.hasSqrBracket %} +{##### If length is not allowed on type #####} +{% if not r.is_tlength %} +{% set tlength = 0 %} +{% set precision = 0 %} +{% endif %} +{% endif %} +{##### If length changed #####} +{% if r.tlength and tlength != r.tlength %} +{% set tlength = r.tlength %} +{% endif %} +{##### If precision changed #####} +{% if tlength and r.precision and precision != r.precision %} +{% set precision = r.precision %} +{% endif %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + ALTER ATTRIBUTE {{conn|qtIdent(member_name)}} SET DATA TYPE {{ GET_TYPE.CREATE_TYPE_SQL(conn, cltype, tlength, precision, hasSqrBracket) }}{% if r.collation %} + COLLATE {{r.collation}}{% endif %}; +{% endif%} +{% endfor %} +{% endfor %} +{% endif %} +{% endif %} +{#======================================#} +{### The sql given below will update enum type ###} +{% if data.enum and data.enum|length > 0 %} +{% set enum = data.enum %} +{% set o_enum_len = o_data.enum|length %} +{# We need actual list index from length #} +{% set o_enum_len = o_enum_len - 1 %} +{% if 'added' in enum and enum.added|length > 0 %} +{% for r in enum.added %} +{% set c_idx = loop.index %} +{% if c_idx == 1 %} +{# if first new element then add it after old data enum list#} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + ADD VALUE {{r.label|qtLiteral(conn)}} {% if o_enum_len > 0 %}AFTER {{o_data.enum[o_enum_len].label|qtLiteral(conn) }}{% endif %}; +{% else %} +{# if first new element then add it after new data enum list#} +{% set p_idx = loop.index - 2 %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + ADD VALUE {{r.label|qtLiteral(conn)}} AFTER {{enum.added[p_idx].label|qtLiteral(conn)}}; +{% endif %} +{% endfor %} +{% endif %} + +{% if 'changed' in enum and enum.changed|length > 0 %} +{% for r in enum.changed %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + RENAME VALUE {{r.old_label|qtLiteral(conn)}} TO {{r.label|qtLiteral(conn)}}; +{% endfor %} +{% endif %} + +{% endif %} +{#======================================#} +{### The sql given below will update External type ###} +{% if (data.typreceive is defined and data.typreceive != o_data.typreceive) or (data.typsend is defined and data.typsend != o_data.typsend) or (data.typmodin is defined and data.typmodin != o_data.typmodin) or (data.typmodout is defined and data.typmodout != o_data.typmodout) or (data.typanalyze is defined and data.typanalyze != o_data.typanalyze) or (data.typsubscript is defined and data.typsubscript != o_data.typsubscript) or (data.typstorage is defined and data.typstorage != o_data.typstorage)%} +{% set ns = namespace(add_comma=false) %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} SET ( + {% if data.typreceive is defined %}RECEIVE = {{data.typreceive}}{% set ns.add_comma = true%}{% endif %}{% if data.typsend is defined %}{% if ns.add_comma %}, + {% endif %}SEND = {{data.typsend}}{% set ns.add_comma = true%}{% endif %}{% if data.typmodin is defined %}{% if ns.add_comma %}, + {% endif %}TYPMOD_IN = {{data.typmodin}}{% set ns.add_comma = true%}{% endif %}{% if data.typmodout is defined %}{% if ns.add_comma %}, + {% endif %}TYPMOD_OUT = {{data.typmodout}}{% set ns.add_comma = true%}{% endif %}{% if data.typanalyze is defined %}{% if ns.add_comma %}, + {% endif %}ANALYZE = {{data.typanalyze}}{% set ns.add_comma = true%}{% endif %}{% if data.typsubscript is defined %}{% if ns.add_comma %}, + {% endif %}SUBSCRIPT = {{data.typsubscript}}{% set ns.add_comma = true%}{% endif %}{% if data.typstorage is defined %}{% if ns.add_comma %}, + {% endif %}STORAGE = {{data.typstorage}}{% endif %} + +); +{% endif %} +{#======================================#} +{# The SQL generated below will change Security Label #} +{% if data.seclabels and data.seclabels|length > 0 %} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} +{{ SECLABEL.UNSET(conn, 'TYPE', o_data.name, r.provider, o_data.schema) }} +{% endfor %} +{% endif %} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} +{{ SECLABEL.SET(conn, 'TYPE', o_data.name, r.provider, r.label, o_data.schema) }} +{% endfor %} +{% endif %} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} +{{ SECLABEL.SET(conn, 'TYPE', o_data.name, r.provider, r.label, o_data.schema) }} +{% endfor %} +{% endif %} + +{% endif %} +{#======================================#} +{# Change the privileges #} +{% if data.typacl and data.typacl|length > 0 %} +{% if 'deleted' in data.typacl %} +{% for priv in data.typacl.deleted %} +{{ PRIVILEGE.UNSETALL(conn, 'TYPE', priv.grantee, o_data.name, o_data.schema) }} +{% endfor %} +{% endif %} +{% if 'changed' in data.typacl %} +{% for priv in data.typacl.changed %} +{% if priv.grantee != priv.old_grantee %} +{{ PRIVILEGE.UNSETALL(conn, 'TYPE', priv.old_grantee, o_data.name, o_data.schema) }} +{% else %} +{{ PRIVILEGE.UNSETALL(conn, 'TYPE', priv.grantee, o_data.name, o_data.schema) }} +{% endif %} +{{ PRIVILEGE.SET(conn, 'TYPE', priv.grantee, o_data.name, priv.without_grant, priv.with_grant, o_data.schema) }} +{% endfor %} +{% endif %} +{% if 'added' in data.typacl %} +{% for priv in data.typacl.added %} +{{ PRIVILEGE.SET(conn, 'TYPE', priv.grantee, o_data.name, priv.without_grant, priv.with_grant, o_data.schema) }} +{% endfor %} +{% endif %} +{% endif %} +{#======================================#} +{# Below will change object name #} +{% if data.name and data.name != o_data.name %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + RENAME TO {{ conn|qtIdent(data.name) }}; + +{% endif %} +{#======================================#} +{# Below will change the schema for object #} +{# with extra if condition we will also make sure that object has correct name #} +{% if data.schema and data.schema != o_data.schema %} +ALTER TYPE {% if data.name and data.name != o_data.name %}{{ conn|qtIdent(o_data.schema, data.name) }} +{% else %}{{ conn|qtIdent(o_data.schema, o_data.name) }} +{% endif %} + SET SCHEMA {{ conn|qtIdent(data.schema) }}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/count.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/count.sql index 20d3b8b25..670982a2e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/count.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/count.sql @@ -1,6 +1,6 @@ SELECT COUNT(*) FROM pg_catalog.pg_type t -LEFT OUTER JOIN pg_catalog.pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c' + LEFT OUTER JOIN pg_catalog.pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c' WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%' AND t.typnamespace = {{scid}}::oid {% if not showsysobj %} AND ct.oid is NULL diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/get_external_functions.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/get_external_functions.sql index 425df8845..003bf0487 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/get_external_functions.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/get_external_functions.sql @@ -1,7 +1,7 @@ {### Input/Output/Send/Receive/Analyze function list also append into TypModeIN/TypModOUT ###} {% if extfunc %} SELECT proname, nspname, - CASE WHEN (length(nspname::text) > 0 AND nspname != 'public') and length(proname::text) > 0 THEN + CASE WHEN length(nspname::text) > 0 and length(proname::text) > 0 THEN pg_catalog.concat(pg_catalog.quote_ident(nspname), '.', pg_catalog.quote_ident(proname)) WHEN length(proname::text) > 0 THEN pg_catalog.quote_ident(proname) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/properties.sql index 09728bf20..a52fbaeb8 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/properties.sql @@ -1,7 +1,26 @@ SELECT t.oid, t.typname AS name, (CASE WHEN CAST(coalesce(t.typcollation, '0') AS integer) = 100 THEN true ElSE false END) AS is_collatable, t.typacl AS type_acl, - t.*, pg_catalog.format_type(t.oid, null) AS alias, + t.typnamespace, t.typowner, t.typlen, t.typbyval, t.typtype, + t.typcategory, t.typispreferred, t.typisdefined, t.typdelim, + t.typrelid, t.typelem, t.typarray, t.typalign, t.typstorage, + t.typnotnull, t.typbasetype, t.typtypmod, t.typndims, + t.typcollation, t.typdefaultbin, t.typdefault, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typinput::oid) AS typinput, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typoutput::oid) AS typoutput, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typreceive::oid) AS typreceive, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typsend::oid) AS typsend, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typmodin::oid) AS typmodin, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typmodout::oid) AS typmodout, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typanalyze::oid) AS typanalyze, + pg_catalog.format_type(t.oid, null) AS alias, pg_catalog.pg_get_userbyid(t.typowner) as typeowner, e.typname as element, description, ct.oid AS taboid, nsp.nspname AS schema, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/update.sql index fd40a44a0..20200cc76 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/update.sql @@ -97,6 +97,27 @@ ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} {% endfor %} {% endif %} +{% if 'changed' in enum and enum.changed|length > 0 %} +{% for r in enum.changed %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + RENAME VALUE {{r.old_label|qtLiteral(conn)}} TO {{r.label|qtLiteral(conn)}}; +{% endfor %} +{% endif %} + +{% endif %} +{#======================================#} +{### The sql given below will update External type ###} +{% if (data.typreceive is defined and data.typreceive != o_data.typreceive) or (data.typsend is defined and data.typsend != o_data.typsend) or (data.typmodin is defined and data.typmodin != o_data.typmodin) or (data.typmodout is defined and data.typmodout != o_data.typmodout) or (data.typanalyze is defined and data.typanalyze != o_data.typanalyze) or (data.typstorage is defined and data.typstorage != o_data.typstorage)%} +{% set ns = namespace(add_comma=false) %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} SET ( + {% if data.typreceive is defined %}RECEIVE = {{data.typreceive}}{% set ns.add_comma = true%}{% endif %}{% if data.typsend is defined %}{% if ns.add_comma %}, + {% endif %}SEND = {{data.typsend}}{% set ns.add_comma = true%}{% endif %}{% if data.typmodin is defined %}{% if ns.add_comma %}, + {% endif %}TYPMOD_IN = {{data.typmodin}}{% set ns.add_comma = true%}{% endif %}{% if data.typmodout is defined %}{% if ns.add_comma %}, + {% endif %}TYPMOD_OUT = {{data.typmodout}}{% set ns.add_comma = true%}{% endif %}{% if data.typanalyze is defined %}{% if ns.add_comma %}, + {% endif %}ANALYZE = {{data.typanalyze}}{% set ns.add_comma = true%}{% endif %}{% if data.typstorage is defined %}{% if ns.add_comma %}, + {% endif %}STORAGE = {{data.typstorage}}{% endif %} + +); {% endif %} {#======================================#} {# The SQL generated below will change Security Label #} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/additional_properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/additional_properties.sql new file mode 100644 index 000000000..b186b762f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/additional_properties.sql @@ -0,0 +1,64 @@ +{# The SQL given below will fetch composite type#} +{% if typtype == 'c' %} +SELECT attnum, attname, pg_catalog.format_type(t.oid,NULL) AS typname, attndims, atttypmod, nsp.nspname, + (SELECT COUNT(1) from pg_catalog.pg_type t2 WHERE t2.typname=t.typname) > 1 AS isdup, + collname, nspc.nspname as collnspname, att.attrelid, + pg_catalog.format_type(t.oid, att.atttypmod) AS fulltype, + CASE WHEN t.typelem > 0 THEN t.typelem ELSE t.oid END as elemoid +FROM pg_catalog.pg_attribute att + JOIN pg_catalog.pg_type t ON t.oid=atttypid + JOIN pg_catalog.pg_namespace nsp ON t.typnamespace=nsp.oid + LEFT OUTER JOIN pg_catalog.pg_type b ON t.typelem=b.oid + LEFT OUTER JOIN pg_catalog.pg_collation c ON att.attcollation=c.oid + LEFT OUTER JOIN pg_catalog.pg_namespace nspc ON c.collnamespace=nspc.oid + WHERE att.attrelid = {{typrelid}}::oid + ORDER by attnum; +{% endif %} + +{# The SQL given below will fetch enum type#} +{% if typtype == 'e' %} +SELECT enumlabel +FROM pg_catalog.pg_enum + WHERE enumtypid={{tid}}::oid + ORDER by enumsortorder +{% endif %} + +{# The SQL given below will fetch range type#} +{% if typtype == 'r' %} +SELECT rngsubtype, st.typname, + rngcollation, mt.typname as rngmultirangetype, + CASE WHEN n.nspname IS NOT NULL THEN pg_catalog.concat(pg_catalog.quote_ident(n.nspname), '.', pg_catalog.quote_ident(col.collname)) ELSE col.collname END AS collname, + rngsubopc, opc.opcname, + rngcanonical, rngsubdiff as rngsubdiff_proc, + CASE WHEN length(ns.nspname::text) > 0 AND length(pgpr.proname::text) > 0 THEN + pg_catalog.concat(quote_ident(ns.nspname), '.', pg_catalog.quote_ident(pgpr.proname)) + ELSE '' END AS rngsubdiff +FROM pg_catalog.pg_range + LEFT JOIN pg_catalog.pg_type st ON st.oid=rngsubtype + LEFT JOIN pg_catalog.pg_type mt ON mt.oid=rngmultitypid + LEFT JOIN pg_catalog.pg_collation col ON col.oid=rngcollation + LEFT JOIN pg_catalog.pg_namespace n ON col.collnamespace=n.oid + LEFT JOIN pg_catalog.pg_opclass opc ON opc.oid=rngsubopc + LEFT JOIN pg_catalog.pg_proc pgpr ON pgpr.oid = rngsubdiff + LEFT JOIN pg_catalog.pg_namespace ns ON ns.oid=pgpr.pronamespace + WHERE rngtypid={{tid}}::oid; +{% endif %} + +{# The SQL given below will fetch enum type#} +{% if typtype == 'N' or typtype == 'V' %} +SELECT t.typname AS typname, + CASE WHEN t.typelem > 0 THEN t.typelem ELSE t.oid END AS elemoid, + t.typtypmod, + t.typtype, + t.typndims, + pg_catalog.format_type(e.oid,NULL) AS type, + pg_catalog.format_type(e.oid, t.typtypmod) AS fulltype, + nsp.nspname as typnspname, + e.typname as type, + (SELECT COUNT(1) FROM pg_catalog.pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup, + CASE WHEN t.typcollation != 0 THEN TRUE ELSE FALSE END AS is_collatable +FROM pg_catalog.pg_type t + LEFT OUTER JOIN pg_catalog.pg_namespace nsp ON typnamespace=nsp.oid + LEFT OUTER JOIN pg_catalog.pg_type e ON e.oid=t.typelem +WHERE t.oid={{tid}}::oid; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/create.sql new file mode 100644 index 000000000..17c46f6eb --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/create.sql @@ -0,0 +1,96 @@ +{% import 'macros/schemas/security.macros' as SECLABEL %} +{% import 'macros/schemas/privilege.macros' as PRIVILEGE %} +{% import 'types/macros/get_full_type_sql_format.macros' as GET_TYPE %} +{## If user selected shell type then just create type template ##} +{% if data and data.typtype == 'p' %} +CREATE TYPE {{ conn|qtIdent(data.schema, data.name) }}; +{% endif %} +{### Composite Type ###} +{% if data and data.typtype == 'c' %} +CREATE TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} AS +({{"\n\t"}}{% if data.composite %}{% for d in data.composite %}{% if loop.index != 1 %},{{"\n\t"}}{% endif %}{{ conn|qtIdent(d.member_name) }} {% if is_sql %}{{ d.fulltype }}{% else %}{{ GET_TYPE.CREATE_TYPE_SQL(conn, d.cltype, d.tlength, d.precision, d.hasSqrBracket) }}{% endif %}{% if d.collation %} COLLATE {{d.collation}}{% endif %}{% endfor %}{% endif %}{{"\n"}}); +{% endif %} +{### Enum Type ###} +{% if data and data.typtype == 'e' %} +CREATE TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} AS ENUM + ({% for e in data.enum %}{% if loop.index != 1 %}, {% endif %}{{ e.label|qtLiteral(conn) }}{% endfor %}); +{% endif %} +{### Range Type ###} +{% if data and data.typtype == 'r' %} +CREATE TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} AS RANGE +( + {% if data.typname %}SUBTYPE={{ conn|qtTypeIdent(data.typname) }}{% endif %}{% if data.collname %}, + COLLATION = {{ data.collname }}{% endif %}{% if data.opcname %}, + SUBTYPE_OPCLASS = {{ data.opcname }}{% endif %}{% if data.rngcanonical %}, + CANONICAL = {{ data.rngcanonical }}{% endif %}{% if data.rngsubdiff %}, + SUBTYPE_DIFF = {{ data.rngsubdiff }}{% endif %}{% if data.rngmultirangetype %}, + MULTIRANGE_TYPE_NAME = {{ data.rngmultirangetype }}{% endif %} + +); +{% endif %} +{### External Type ###} +{% if data and data.typtype == 'b' %} +CREATE TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} + +( + {% if data.typinput %}INPUT = {{data.typinput}}{% endif %}{% if data.typoutput %}, + OUTPUT = {{ data.typoutput }}{% endif %}{% if data.typreceive %}, + RECEIVE = {{data.typreceive}}{% endif %}{% if data.typsend %}, + SEND = {{data.typsend}}{% endif %}{% if data.typmodin %}, + TYPMOD_IN = {{data.typmodin}}{% endif %}{% if data.typmodout %}, + TYPMOD_OUT = {{data.typmodout}}{% endif %}{% if data.typanalyze %}, + ANALYZE = {{data.typanalyze}}{% endif %}{% if data.typsubscript %}, + SUBSCRIPT = {{data.typsubscript}}{% endif %}{% if data.typlen %}, + INTERNALLENGTH = {{data.typlen}}{% endif %}{% if data.typbyval %}, + PASSEDBYVALUE{% endif %}{% if data.typalign %}, + ALIGNMENT = {{data.typalign}}{% endif %}{% if data.typstorage %}, + STORAGE = {{data.typstorage}}{% endif %}{% if data.typcategory %}, + CATEGORY = {{data.typcategory|qtLiteral(conn)}}{% endif %}{% if data.typispreferred %}, + PREFERRED = {{data.typispreferred}}{% endif %}{% if data.typdefault %}, + DEFAULT = {{data.typdefault|qtLiteral(conn)}}{% endif %}{% if data.element %}, + ELEMENT = {{data.element}}{% endif %}{% if data.typdelim %}, + DELIMITER = {{data.typdelim|qtLiteral(conn)}}{% endif %}{% if data.is_collatable %}, + COLLATABLE = {{data.is_collatable}}{% endif %} + +); +{% endif %} +{### Nested-table Type ###} +{% if data and data.typtype == 'N' %} +CREATE TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} AS TABLE OF + {% if is_sql %}{{ data.fulltype }}{% else %}{{ GET_TYPE.CREATE_TYPE_SQL(conn, data.cltype, data.tlength, data.precision, data.hasSqrBracket) }}{% endif %}; +{% endif %} +{### VARRAY Type ###} +{% if data and data.typtype == 'V' %} +CREATE TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} AS VARRAY({{data.maxsize}}) OF + {% if is_sql %}{{ data.fulltype }}{% else %}{{ GET_TYPE.CREATE_TYPE_SQL(conn, data.cltype, data.tlength, data.precision, data.hasSqrBracket) }}{% endif %}; +{% endif %} + +{### Type Owner ###} +{% if data and data.typeowner %} +ALTER TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} + + OWNER TO {{ conn|qtIdent(data.typeowner) }}; +{% endif %} +{### Type Comments ###} +{% if data and data.description %} + +COMMENT ON TYPE {% if data.schema %}{{ conn|qtIdent(data.schema, data.name) }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} + + IS {{data.description|qtLiteral(conn)}}; +{% endif %} +{### ACL ###} +{% if data.typacl %} + +{% for priv in data.typacl %} +{{ PRIVILEGE.SET(conn, 'TYPE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }} +{% endfor %} +{% endif %} +{### Security Lables ###} +{% if data.seclabels %} + +{% for r in data.seclabels %} +{% if r.provider and r.label %} +{{ SECLABEL.SET(conn, 'TYPE', data.name, r.provider, r.label, data.schema) }} +{% endif %} +{% endfor %} +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/nodes.sql new file mode 100644 index 000000000..9469379f5 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/nodes.sql @@ -0,0 +1,19 @@ +SELECT t.oid, t.typname AS name, des.description, ra.rngmultitypid as rngmultirangetype +FROM pg_catalog.pg_type t + LEFT OUTER JOIN pg_catalog.pg_type e ON e.oid=t.typelem + LEFT OUTER JOIN pg_catalog.pg_range ra ON ra.rngtypid=t.oid + LEFT OUTER JOIN pg_catalog.pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c' + LEFT OUTER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = t.typnamespace + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=t.oid AND des.classoid='pg_type'::regclass) +WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%' AND t.typnamespace = {{scid}}::oid +{% if tid %} + AND t.oid = {{tid}}::oid +{% endif %} +{% if not show_system_objects %} + AND ct.oid is NULL +{% endif %} +{% if schema_diff %} + AND CASE WHEN (SELECT COUNT(*) FROM pg_catalog.pg_depend + WHERE objid = t.oid AND deptype = 'e') > 0 THEN FALSE ELSE TRUE END +{% endif %} +ORDER BY t.typname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/properties.sql new file mode 100644 index 000000000..d50619e61 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/properties.sql @@ -0,0 +1,45 @@ +SELECT t.oid, t.typname AS name, + (CASE WHEN CAST(coalesce(t.typcollation, '0') AS integer) = 100 THEN true ElSE false END) AS is_collatable, + t.typacl AS type_acl, + t.typnamespace, t.typowner, t.typlen, t.typbyval, t.typtype, + t.typcategory, t.typispreferred, t.typisdefined, t.typdelim, + t.typrelid, t.typelem, t.typarray, t.typalign, t.typstorage, + t.typnotnull, t.typbasetype, t.typtypmod, t.typndims, + t.typcollation, t.typdefaultbin, t.typdefault, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typinput::oid) AS typinput, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typoutput::oid) AS typoutput, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typreceive::oid) AS typreceive, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typsend::oid) AS typsend, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typmodin::oid) AS typmodin, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typmodout::oid) AS typmodout, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typanalyze::oid) AS typanalyze, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typsubscript::oid) AS typsubscript, + pg_catalog.format_type(t.oid, null) AS alias, + pg_catalog.pg_get_userbyid(t.typowner) as typeowner, e.typname as element, + description, ct.oid AS taboid, + nsp.nspname AS schema, + --MinimumVersion 9.1 START + (SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_seclabel sl1 WHERE sl1.objoid=t.oid) AS seclabels, + -- END + (CASE WHEN (t.oid <= {{ datlastsysoid}}::oid OR ct.oid != 0) THEN true ElSE false END) AS is_sys_type +FROM pg_catalog.pg_type t + LEFT OUTER JOIN pg_catalog.pg_type e ON e.oid=t.typelem + LEFT OUTER JOIN pg_catalog.pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c' + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=t.oid AND des.classoid='pg_type'::regclass) + LEFT OUTER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = t.typnamespace +WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%' AND t.typnamespace = {{scid}}::oid +{% if tid %} + AND t.oid = {{tid}}::oid +{% endif %} +{% if not show_system_objects %} + AND ct.oid is NULL +{% endif %} +ORDER BY t.typname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/update.sql new file mode 100644 index 000000000..008b3e8e1 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/14_plus/update.sql @@ -0,0 +1,183 @@ +{% import 'macros/schemas/security.macros' as SECLABEL %} +{% import 'macros/schemas/privilege.macros' as PRIVILEGE %} +{% import 'types/macros/get_full_type_sql_format.macros' as GET_TYPE %} +{#======================================#} +{# Below will change object owner #} +{% if data.typeowner and data.typeowner != o_data.typeowner %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + OWNER TO {{ conn|qtIdent(data.typeowner) }}; + +{% endif %} +{#======================================#} +{# Below will change objects comment #} +{% if data.description is defined and data.description != o_data.description %} +COMMENT ON TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + IS {{ data.description|qtLiteral(conn) }}; + +{% endif %} +{#======================================#} +{### The sql given below will update composite type ###} +{% if data.composite and data.composite|length > 0 %} +{% set composite = data.composite %} +{% if 'deleted' in composite and composite.deleted|length > 0 %} +{% for r in composite.deleted %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + DROP ATTRIBUTE {{conn|qtIdent(r.member_name)}}; +{% endfor %} +{% endif %} +{% if 'added' in composite and composite.added|length > 0 %} +{% for r in composite.added %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + ADD ATTRIBUTE {{conn|qtIdent(r.member_name)}} {{ GET_TYPE.CREATE_TYPE_SQL(conn, r.cltype, r.tlength, r.precision, r.hasSqrBracket) }}{% if r.collation %} + COLLATE {{r.collation}}{% endif %}; +{% endfor %} +{% endif %} +{% if 'changed' in composite and composite.changed|length > 0 %} +{% for r in composite.changed %} +{% for o in o_data.composite %} +{##### Variables for the loop #####} +{% set member_name = o.member_name %} +{% set cltype = o.cltype %} +{% set tlength = o.tlength %} +{% set precision = o.precision %} +{% set hasSqrBracket = o.hasSqrBracket %} +{##### If member name changed #####} +{% if o.attnum == r.attnum %} +{% if r.member_name and o.member_name != r.member_name %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + RENAME ATTRIBUTE {{o.member_name}} TO {{r.member_name}}; +{% set member_name = r.member_name %} +{% endif %} +{##### If type changed #####} +{% if r.cltype and cltype != r.cltype %} +{% set cltype = r.cltype %} +{% set hasSqrBracket = r.hasSqrBracket %} +{##### If length is not allowed on type #####} +{% if not r.is_tlength %} +{% set tlength = 0 %} +{% set precision = 0 %} +{% endif %} +{% endif %} +{##### If length changed #####} +{% if r.tlength and tlength != r.tlength %} +{% set tlength = r.tlength %} +{% endif %} +{##### If precision changed #####} +{% if tlength and r.precision and precision != r.precision %} +{% set precision = r.precision %} +{% endif %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + ALTER ATTRIBUTE {{conn|qtIdent(member_name)}} SET DATA TYPE {{ GET_TYPE.CREATE_TYPE_SQL(conn, cltype, tlength, precision, hasSqrBracket) }}{% if r.collation %} + COLLATE {{r.collation}}{% endif %}; +{% endif%} +{% endfor %} +{% endfor %} +{% endif %} +{% endif %} +{#======================================#} +{### The sql given below will update enum type ###} +{% if data.enum and data.enum|length > 0 %} +{% set enum = data.enum %} +{% set o_enum_len = o_data.enum|length %} +{# We need actual list index from length #} +{% set o_enum_len = o_enum_len - 1 %} +{% if 'added' in enum and enum.added|length > 0 %} +{% for r in enum.added %} +{% set c_idx = loop.index %} +{% if c_idx == 1 %} +{# if first new element then add it after old data enum list#} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + ADD VALUE {{r.label|qtLiteral(conn)}} {% if o_enum_len > 0 %}AFTER {{o_data.enum[o_enum_len].label|qtLiteral(conn) }}{% endif %}; +{% else %} +{# if first new element then add it after new data enum list#} +{% set p_idx = loop.index - 2 %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + ADD VALUE {{r.label|qtLiteral(conn)}} AFTER {{enum.added[p_idx].label|qtLiteral(conn)}}; +{% endif %} +{% endfor %} +{% endif %} + +{% if 'changed' in enum and enum.changed|length > 0 %} +{% for r in enum.changed %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + RENAME VALUE {{r.old_label|qtLiteral(conn)}} TO {{r.label|qtLiteral(conn)}}; +{% endfor %} +{% endif %} + +{% endif %} +{#======================================#} +{### The sql given below will update External type ###} +{% if (data.typreceive is defined and data.typreceive != o_data.typreceive) or (data.typsend is defined and data.typsend != o_data.typsend) or (data.typmodin is defined and data.typmodin != o_data.typmodin) or (data.typmodout is defined and data.typmodout != o_data.typmodout) or (data.typanalyze is defined and data.typanalyze != o_data.typanalyze) or (data.typsubscript is defined and data.typsubscript != o_data.typsubscript) or (data.typstorage is defined and data.typstorage != o_data.typstorage)%} +{% set ns = namespace(add_comma=false) %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} SET ( + {% if data.typreceive is defined %}RECEIVE = {{data.typreceive}}{% set ns.add_comma = true%}{% endif %}{% if data.typsend is defined %}{% if ns.add_comma %}, + {% endif %}SEND = {{data.typsend}}{% set ns.add_comma = true%}{% endif %}{% if data.typmodin is defined %}{% if ns.add_comma %}, + {% endif %}TYPMOD_IN = {{data.typmodin}}{% set ns.add_comma = true%}{% endif %}{% if data.typmodout is defined %}{% if ns.add_comma %}, + {% endif %}TYPMOD_OUT = {{data.typmodout}}{% set ns.add_comma = true%}{% endif %}{% if data.typanalyze is defined %}{% if ns.add_comma %}, + {% endif %}ANALYZE = {{data.typanalyze}}{% set ns.add_comma = true%}{% endif %}{% if data.typsubscript is defined %}{% if ns.add_comma %}, + {% endif %}SUBSCRIPT = {{data.typsubscript}}{% set ns.add_comma = true%}{% endif %}{% if data.typstorage is defined %}{% if ns.add_comma %}, + {% endif %}STORAGE = {{data.typstorage}}{% endif %} + +); +{% endif %} +{#======================================#} +{# The SQL generated below will change Security Label #} +{% if data.seclabels and data.seclabels|length > 0 %} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} +{{ SECLABEL.UNSET(conn, 'TYPE', o_data.name, r.provider, o_data.schema) }} +{% endfor %} +{% endif %} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} +{{ SECLABEL.SET(conn, 'TYPE', o_data.name, r.provider, r.label, o_data.schema) }} +{% endfor %} +{% endif %} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} +{{ SECLABEL.SET(conn, 'TYPE', o_data.name, r.provider, r.label, o_data.schema) }} +{% endfor %} +{% endif %} + +{% endif %} +{#======================================#} +{# Change the privileges #} +{% if data.typacl and data.typacl|length > 0 %} +{% if 'deleted' in data.typacl %} +{% for priv in data.typacl.deleted %} +{{ PRIVILEGE.UNSETALL(conn, 'TYPE', priv.grantee, o_data.name, o_data.schema) }} +{% endfor %} +{% endif %} +{% if 'changed' in data.typacl %} +{% for priv in data.typacl.changed %} +{% if priv.grantee != priv.old_grantee %} +{{ PRIVILEGE.UNSETALL(conn, 'TYPE', priv.old_grantee, o_data.name, o_data.schema) }} +{% else %} +{{ PRIVILEGE.UNSETALL(conn, 'TYPE', priv.grantee, o_data.name, o_data.schema) }} +{% endif %} +{{ PRIVILEGE.SET(conn, 'TYPE', priv.grantee, o_data.name, priv.without_grant, priv.with_grant, o_data.schema) }} +{% endfor %} +{% endif %} +{% if 'added' in data.typacl %} +{% for priv in data.typacl.added %} +{{ PRIVILEGE.SET(conn, 'TYPE', priv.grantee, o_data.name, priv.without_grant, priv.with_grant, o_data.schema) }} +{% endfor %} +{% endif %} +{% endif %} +{#======================================#} +{# Below will change object name #} +{% if data.name and data.name != o_data.name %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + RENAME TO {{ conn|qtIdent(data.name) }}; + +{% endif %} +{#======================================#} +{# Below will change the schema for object #} +{# with extra if condition we will also make sure that object has correct name #} +{% if data.schema and data.schema != o_data.schema %} +ALTER TYPE {% if data.name and data.name != o_data.name %}{{ conn|qtIdent(o_data.schema, data.name) }} +{% else %}{{ conn|qtIdent(o_data.schema, o_data.name) }} +{% endif %} + SET SCHEMA {{ conn|qtIdent(data.schema) }}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/additional_properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/additional_properties.sql index 8379a23e8..683cca92a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/additional_properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/additional_properties.sql @@ -29,12 +29,17 @@ SELECT rngsubtype, st.typname, rngcollation, CASE WHEN n.nspname IS NOT NULL THEN pg_catalog.concat(pg_catalog.quote_ident(n.nspname), '.', pg_catalog.quote_ident(col.collname)) ELSE col.collname END AS collname, rngsubopc, opc.opcname, - rngcanonical, rngsubdiff + rngcanonical, rngsubdiff as rngsubdiff_proc, + CASE WHEN length(ns.nspname::text) > 0 AND length(pgpr.proname::text) > 0 THEN + pg_catalog.concat(quote_ident(ns.nspname), '.', pg_catalog.quote_ident(pgpr.proname)) + ELSE '' END AS rngsubdiff FROM pg_catalog.pg_range LEFT JOIN pg_catalog.pg_type st ON st.oid=rngsubtype LEFT JOIN pg_catalog.pg_collation col ON col.oid=rngcollation LEFT JOIN pg_catalog.pg_namespace n ON col.collnamespace=n.oid LEFT JOIN pg_catalog.pg_opclass opc ON opc.oid=rngsubopc + LEFT JOIN pg_catalog.pg_proc pgpr ON pgpr.oid = rngsubdiff + LEFT JOIN pg_catalog.pg_namespace ns ON ns.oid=pgpr.pronamespace WHERE rngtypid={{tid}}::oid; {% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/get_external_functions.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/get_external_functions.sql index 425df8845..003bf0487 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/get_external_functions.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/get_external_functions.sql @@ -1,7 +1,7 @@ {### Input/Output/Send/Receive/Analyze function list also append into TypModeIN/TypModOUT ###} {% if extfunc %} SELECT proname, nspname, - CASE WHEN (length(nspname::text) > 0 AND nspname != 'public') and length(proname::text) > 0 THEN + CASE WHEN length(nspname::text) > 0 and length(proname::text) > 0 THEN pg_catalog.concat(pg_catalog.quote_ident(nspname), '.', pg_catalog.quote_ident(proname)) WHEN length(proname::text) > 0 THEN pg_catalog.quote_ident(proname) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/properties.sql index 09728bf20..a52fbaeb8 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/properties.sql @@ -1,7 +1,26 @@ SELECT t.oid, t.typname AS name, (CASE WHEN CAST(coalesce(t.typcollation, '0') AS integer) = 100 THEN true ElSE false END) AS is_collatable, t.typacl AS type_acl, - t.*, pg_catalog.format_type(t.oid, null) AS alias, + t.typnamespace, t.typowner, t.typlen, t.typbyval, t.typtype, + t.typcategory, t.typispreferred, t.typisdefined, t.typdelim, + t.typrelid, t.typelem, t.typarray, t.typalign, t.typstorage, + t.typnotnull, t.typbasetype, t.typtypmod, t.typndims, + t.typcollation, t.typdefaultbin, t.typdefault, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typinput::oid) AS typinput, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typoutput::oid) AS typoutput, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typreceive::oid) AS typreceive, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typsend::oid) AS typsend, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typmodin::oid) AS typmodin, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typmodout::oid) AS typmodout, + (SELECT pg_catalog.concat(nspname, '.', proname,'') FROM pg_proc pr JOIN pg_namespace nsp ON pr.pronamespace = nsp.oid + WHERE pr.oid = t.typanalyze::oid) AS typanalyze, + pg_catalog.format_type(t.oid, null) AS alias, pg_catalog.pg_get_userbyid(t.typowner) as typeowner, e.typname as element, description, ct.oid AS taboid, nsp.nspname AS schema, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/update.sql index fd40a44a0..20200cc76 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/update.sql @@ -97,6 +97,27 @@ ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} {% endfor %} {% endif %} +{% if 'changed' in enum and enum.changed|length > 0 %} +{% for r in enum.changed %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} + RENAME VALUE {{r.old_label|qtLiteral(conn)}} TO {{r.label|qtLiteral(conn)}}; +{% endfor %} +{% endif %} + +{% endif %} +{#======================================#} +{### The sql given below will update External type ###} +{% if (data.typreceive is defined and data.typreceive != o_data.typreceive) or (data.typsend is defined and data.typsend != o_data.typsend) or (data.typmodin is defined and data.typmodin != o_data.typmodin) or (data.typmodout is defined and data.typmodout != o_data.typmodout) or (data.typanalyze is defined and data.typanalyze != o_data.typanalyze) or (data.typstorage is defined and data.typstorage != o_data.typstorage)%} +{% set ns = namespace(add_comma=false) %} +ALTER TYPE {{ conn|qtIdent(o_data.schema, o_data.name) }} SET ( + {% if data.typreceive is defined %}RECEIVE = {{data.typreceive}}{% set ns.add_comma = true%}{% endif %}{% if data.typsend is defined %}{% if ns.add_comma %}, + {% endif %}SEND = {{data.typsend}}{% set ns.add_comma = true%}{% endif %}{% if data.typmodin is defined %}{% if ns.add_comma %}, + {% endif %}TYPMOD_IN = {{data.typmodin}}{% set ns.add_comma = true%}{% endif %}{% if data.typmodout is defined %}{% if ns.add_comma %}, + {% endif %}TYPMOD_OUT = {{data.typmodout}}{% set ns.add_comma = true%}{% endif %}{% if data.typanalyze is defined %}{% if ns.add_comma %}, + {% endif %}ANALYZE = {{data.typanalyze}}{% set ns.add_comma = true%}{% endif %}{% if data.typstorage is defined %}{% if ns.add_comma %}, + {% endif %}STORAGE = {{data.typstorage}}{% endif %} + +); {% endif %} {#======================================#} {# The SQL generated below will change Security Label #} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/alter_acl_grantee_change.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/alter_acl_grantee_change.sql new file mode 100644 index 000000000..91520ae0d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/alter_acl_grantee_change.sql @@ -0,0 +1,18 @@ +-- Type: range_type_$%{}[]()&*^!@"'`\/# + +-- DROP TYPE IF EXISTS public."range_type_$%{}[]()&*^!@""'`\/#"; + +CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE +( + SUBTYPE=bool, + SUBTYPE_OPCLASS = bool_ops, + MULTIRANGE_TYPE_NAME = multirange_type_$%{}[]()&*^!@"'`\/# +); + +ALTER TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + OWNER TO ; + +COMMENT ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + IS 'this is test'; + +GRANT USAGE ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" TO PUBLIC; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/alter_range_type_acl_description.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/alter_range_type_acl_description.sql new file mode 100644 index 000000000..094785d2f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/alter_range_type_acl_description.sql @@ -0,0 +1,20 @@ +-- Type: range_type_$%{}[]()&*^!@"'`\/# + +-- DROP TYPE IF EXISTS public."range_type_$%{}[]()&*^!@""'`\/#"; + +CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE +( + SUBTYPE=bool, + SUBTYPE_OPCLASS = bool_ops, + MULTIRANGE_TYPE_NAME = multirange_type_$%{}[]()&*^!@"'`\/# +); + +ALTER TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + OWNER TO ; + +COMMENT ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + IS 'this is test'; + +GRANT USAGE ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" TO PUBLIC; + +GRANT USAGE ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" TO ; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/create_multi_range_type.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/create_multi_range_type.msql new file mode 100644 index 000000000..6584c082a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/create_multi_range_type.msql @@ -0,0 +1,5 @@ +CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE +( + SUBTYPE=bool, + MULTIRANGE_TYPE_NAME = multirange_type +); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/create_multi_range_type.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/create_multi_range_type.sql new file mode 100644 index 000000000..718440994 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/create_multi_range_type.sql @@ -0,0 +1,13 @@ +-- Type: range_type_$%{}[]()&*^!@"'`\/# + +-- DROP TYPE IF EXISTS public."range_type_$%{}[]()&*^!@""'`\/#"; + +CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE +( + SUBTYPE=bool, + SUBTYPE_OPCLASS = bool_ops, + MULTIRANGE_TYPE_NAME = multirange_type +); + +ALTER TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + OWNER TO ; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/create_range_type.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/create_range_type.sql new file mode 100644 index 000000000..ac57c8cbb --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/create_range_type.sql @@ -0,0 +1,13 @@ +-- Type: range_type_$%{}[]()&*^!@"'`\/# + +-- DROP TYPE IF EXISTS public."range_type_$%{}[]()&*^!@""'`\/#"; + +CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE +( + SUBTYPE=bool, + SUBTYPE_OPCLASS = bool_ops, + MULTIRANGE_TYPE_NAME = multirange_type_$%{}[]()&*^!@"'`\/# +); + +ALTER TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + OWNER TO ; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/tests.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/tests.json new file mode 100644 index 000000000..3c7527248 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/14_plus/tests.json @@ -0,0 +1,324 @@ +{ + "scenarios": [ + { + "type": "create", + "name": "Create ENUM type", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql", + "data": { + "name": "enum_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"e", + "schema":"public", + "composite":[], + "enum":[{"label":"a"},{"label":"b"},{"label":"c"}], + "typacl":[], + "seclabels":[], + "description":"" + }, + "expected_sql_file": "create_enum_type.sql", + "expected_msql_file": "create_enum_type.msql" + }, + { + "type": "alter", + "name": "alter ENUM type and add new label", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "enum": {"added": [{"label": "d"}]} + }, + "expected_sql_file": "alter_enum_type_label.sql", + "expected_msql_file": "alter_enum_type_label.msql" + }, + { + "type": "alter", + "name": "alter ENUM type and add ACL, description", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "description":"this is test", + "typacl": {"added": [{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"U","privilege":true,"with_grant":false}]}]} + }, + "expected_sql_file": "alter_enum_type_acl_description.sql", + "expected_msql_file": "alter_enum_type_acl_description.msql" + }, + { + "type": "alter", + "name": "alter ENUM type and rename ENUM", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "enum": {"changed": [{"label": "a_new", "old_label": "a"}, {"label": "d_new", "old_label": "d"}]} + }, + "expected_sql_file": "alter_enum_type_rename_enum.sql", + "expected_msql_file": "alter_enum_type_rename_enum.msql" + }, + { + "type": "delete", + "name": "Drop ENUM type", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + }, + + + { + "type": "create", + "name": "Create Composite type", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql", + "data": { + "name": "composite_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"c", + "schema":"public", + "composite":[ + {"member_name":"mname1","type":"bigint","is_tlength":false,"is_precision":false}, + {"member_name":"mname2","type":"character varying","tlength":50,"is_tlength":true,"is_precision":false,"collation":"pg_catalog.\"C\"","min_val":1,"max_val":2147483647,"collspcname":""}, + {"member_name":"mname3","type":"text[]","is_tlength":false,"is_precision":false,"collation":"pg_catalog.\"C\"","collspcname":""} + ], + "typacl":[], + "seclabels":[], + "description":"" + }, + "expected_sql_file": "create_composite_type.sql", + "expected_msql_file": "create_composite_type.msql" + }, + { + "type": "alter", + "name": "alter Composite type and add new label", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "composite": {"added": [{"member_name":"mname4","type":"bigint","is_tlength":false,"is_precision":false}]} + }, + "expected_sql_file": "alter_composite_type_add_member.sql", + "expected_msql_file": "alter_composite_type_add_member.msql" + }, + { + "type": "alter", + "name": "alter Composite type and delete label", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "composite": {"deleted":[{"attnum":1,"member_name":"mname1","type":"bigint","tlength":null,"is_tlength":false,"precision":null,"is_precision":false,"collation":"","cltype":"bigint","hasSqrBracket":false,"fulltype":"bigint"}]} + }, + "expected_sql_file": "alter_composite_type_remove_member.sql", + "expected_msql_file": "alter_composite_type_remove_member.msql" + }, + { + "type": "alter", + "name": "alter Composite type and add ACL, description", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "description":"this is test", + "typacl": {"added": [{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"U","privilege":true,"with_grant":false}]}]} + }, + "expected_sql_file": "alter_composite_type_acl_description.sql", + "expected_msql_file": "alter_composite_type_acl_description.msql" + }, + { + "type": "delete", + "name": "Drop Composite type", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + }, + + { + "type": "create", + "name": "Create Composite type - one field", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "data": { + "name": "composite_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"c", + "schema":"public", + "composite":[ + {"member_name":"mname1","type":"bigint","is_tlength":false,"is_precision":false} + ], + "typacl":[], + "seclabels":[], + "description":"" + }, + "expected_sql_file": "create_composite_type_one_field.sql" + }, + { + "type": "delete", + "name": "Drop Composite type - one field", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + }, + + { + "type": "create", + "name": "Create SHELL type", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql", + "data": { + "name": "shell_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"p", + "schema":"public", + "composite":[], + "enum":[], + "typacl":[], + "seclabels":[] + }, + "expected_sql_file": "create_shell_type.sql", + "expected_msql_file": "create_shell_type.msql" + }, + { + "type": "alter", + "name": "alter SHELL type and add description", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "description":"this is test" + }, + "expected_sql_file": "alter_shell_type_acl_description.sql", + "expected_msql_file": "alter_shell_type_acl_description.msql" + }, + { + "type": "delete", + "name": "Drop SHELL type", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + }, + + + { + "type": "create", + "name": "Create RANGE type", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql", + "data": { + "name": "range_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"r", + "schema":"public", + "composite":[], + "enum":[], + "typacl":[], + "seclabels":[], + "typname":"bool" + }, + "expected_sql_file": "create_range_type.sql", + "expected_msql_file": "create_range_type.msql" + }, + { + "type": "alter", + "name": "alter RANGE type and add ACL, description", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "description":"this is test", + "typacl": {"added": [{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"U","privilege":true,"with_grant":false}]}]} + }, + "expected_sql_file": "alter_range_type_acl_description.sql", + "expected_msql_file": "alter_range_type_acl_description.msql" + }, + { + "type": "alter", + "name": "alter ACL (Remove privilege)", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "typacl": { + "deleted": [ + { + "grantee": "PUBLIC", + "grantor": "postgres", + "privileges": [ + { + "privilege_type": "U", + "privilege": true, + "with_grant": false + } + ] + } + ] + } + } + }, + { + "type": "alter", + "name": "alter ACL (change grantee)", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "typacl": { + "changed": [ + { + "grantee": "PUBLIC", + "grantor": "postgres", + "old_grantee": "postgres", + "privileges": [ + { + "privilege_type": "U", + "privilege": true, + "with_grant": false + } + ] + } + ] + } + }, + "expected_sql_file": "alter_acl_grantee_change.sql", + "expected_msql_file": "alter_acl_grantee_change_msql.sql" + }, + { + "type": "delete", + "name": "Drop RANGE type", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + }, + { + "type": "create", + "name": "Create Multi RANGE type", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql", + "data": { + "name": "range_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"r", + "schema":"public", + "composite":[], + "enum":[], + "typacl":[], + "seclabels":[], + "typname":"bool", + "rngmultirangetype": "multirange_type" + }, + "expected_sql_file": "create_multi_range_type.sql", + "expected_msql_file": "create_multi_range_type.msql" + }, + { + "type": "delete", + "name": "Drop RANGE type", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + } + ] +} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/default/alter_enum_type_rename_enum.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/default/alter_enum_type_rename_enum.msql new file mode 100644 index 000000000..9ca45582c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/default/alter_enum_type_rename_enum.msql @@ -0,0 +1,4 @@ +ALTER TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" + RENAME VALUE 'a' TO 'a_new'; +ALTER TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" + RENAME VALUE 'd' TO 'd_new'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/default/alter_enum_type_rename_enum.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/default/alter_enum_type_rename_enum.sql new file mode 100644 index 000000000..02f31566c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/default/alter_enum_type_rename_enum.sql @@ -0,0 +1,16 @@ +-- Type: enum_type_$%{}[]()&*^!@"'`\/# + +-- DROP TYPE IF EXISTS public."enum_type_$%{}[]()&*^!@""'`\/#"; + +CREATE TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" AS ENUM + ('a_new', 'b', 'c', 'd_new'); + +ALTER TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" + OWNER TO ; + +COMMENT ON TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" + IS 'this is test'; + +GRANT USAGE ON TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" TO PUBLIC; + +GRANT USAGE ON TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" TO ; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/default/tests.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/default/tests.json index f44f970d3..31bd5dde5 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/default/tests.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/pg/default/tests.json @@ -45,6 +45,18 @@ "expected_sql_file": "alter_enum_type_acl_description.sql", "expected_msql_file": "alter_enum_type_acl_description.msql" }, + { + "type": "alter", + "name": "alter ENUM type and rename ENUM", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "enum": {"changed": [{"label": "a_new", "old_label": "a"}, {"label": "d_new", "old_label": "d"}]} + }, + "expected_sql_file": "alter_enum_type_rename_enum.sql", + "expected_msql_file": "alter_enum_type_rename_enum.msql" + }, { "type": "delete", "name": "Drop ENUM type", diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/alter_acl_grantee_change.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/alter_acl_grantee_change.sql new file mode 100644 index 000000000..91520ae0d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/alter_acl_grantee_change.sql @@ -0,0 +1,18 @@ +-- Type: range_type_$%{}[]()&*^!@"'`\/# + +-- DROP TYPE IF EXISTS public."range_type_$%{}[]()&*^!@""'`\/#"; + +CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE +( + SUBTYPE=bool, + SUBTYPE_OPCLASS = bool_ops, + MULTIRANGE_TYPE_NAME = multirange_type_$%{}[]()&*^!@"'`\/# +); + +ALTER TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + OWNER TO ; + +COMMENT ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + IS 'this is test'; + +GRANT USAGE ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" TO PUBLIC; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/alter_range_type_acl_description.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/alter_range_type_acl_description.sql new file mode 100644 index 000000000..094785d2f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/alter_range_type_acl_description.sql @@ -0,0 +1,20 @@ +-- Type: range_type_$%{}[]()&*^!@"'`\/# + +-- DROP TYPE IF EXISTS public."range_type_$%{}[]()&*^!@""'`\/#"; + +CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE +( + SUBTYPE=bool, + SUBTYPE_OPCLASS = bool_ops, + MULTIRANGE_TYPE_NAME = multirange_type_$%{}[]()&*^!@"'`\/# +); + +ALTER TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + OWNER TO ; + +COMMENT ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + IS 'this is test'; + +GRANT USAGE ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" TO PUBLIC; + +GRANT USAGE ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" TO ; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/create_multi_range_type.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/create_multi_range_type.msql new file mode 100644 index 000000000..6584c082a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/create_multi_range_type.msql @@ -0,0 +1,5 @@ +CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE +( + SUBTYPE=bool, + MULTIRANGE_TYPE_NAME = multirange_type +); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/create_multi_range_type.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/create_multi_range_type.sql new file mode 100644 index 000000000..718440994 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/create_multi_range_type.sql @@ -0,0 +1,13 @@ +-- Type: range_type_$%{}[]()&*^!@"'`\/# + +-- DROP TYPE IF EXISTS public."range_type_$%{}[]()&*^!@""'`\/#"; + +CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE +( + SUBTYPE=bool, + SUBTYPE_OPCLASS = bool_ops, + MULTIRANGE_TYPE_NAME = multirange_type +); + +ALTER TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + OWNER TO ; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/create_range_type.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/create_range_type.sql new file mode 100644 index 000000000..ac57c8cbb --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/create_range_type.sql @@ -0,0 +1,13 @@ +-- Type: range_type_$%{}[]()&*^!@"'`\/# + +-- DROP TYPE IF EXISTS public."range_type_$%{}[]()&*^!@""'`\/#"; + +CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE +( + SUBTYPE=bool, + SUBTYPE_OPCLASS = bool_ops, + MULTIRANGE_TYPE_NAME = multirange_type_$%{}[]()&*^!@"'`\/# +); + +ALTER TYPE public."range_type_$%{}[]()&*^!@""'`\/#" + OWNER TO ; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/tests.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/tests.json new file mode 100644 index 000000000..3fb712c93 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/14_plus/tests.json @@ -0,0 +1,324 @@ +{ + "scenarios": [ + { + "type": "create", + "name": "Create ENUM type", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql", + "data": { + "name": "enum_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"e", + "schema":"public", + "composite":[], + "enum":[{"label":"a"},{"label":"b"},{"label":"c"}], + "typacl":[], + "seclabels":[], + "description":"" + }, + "expected_sql_file": "create_enum_type.sql", + "expected_msql_file": "create_enum_type.msql" + }, + { + "type": "alter", + "name": "alter ENUM type and add new label", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "enum": {"added": [{"label": "d"}]} + }, + "expected_sql_file": "alter_enum_type_label.sql", + "expected_msql_file": "alter_enum_type_label.msql" + }, + { + "type": "alter", + "name": "alter ENUM type and add ACL, description", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "description":"this is test", + "typacl": {"added": [{"grantee":"PUBLIC","grantor":"enterprisedb","privileges":[{"privilege_type":"U","privilege":true,"with_grant":false}]}]} + }, + "expected_sql_file": "alter_enum_type_acl_description.sql", + "expected_msql_file": "alter_enum_type_acl_description.msql" + }, + { + "type": "alter", + "name": "alter ENUM type and rename ENUM", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "enum": {"changed": [{"label": "a_new", "old_label": "a"}, {"label": "d_new", "old_label": "d"}]} + }, + "expected_sql_file": "alter_enum_type_rename_enum.sql", + "expected_msql_file": "alter_enum_type_rename_enum.msql" + }, + { + "type": "delete", + "name": "Drop ENUM type", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + }, + + + { + "type": "create", + "name": "Create Composite type", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql", + "data": { + "name": "composite_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"c", + "schema":"public", + "composite":[ + {"member_name":"mname1","type":"bigint","is_tlength":false,"is_precision":false}, + {"member_name":"mname2","type":"character varying","tlength":50,"is_tlength":true,"is_precision":false,"collation":"pg_catalog.\"C\"","min_val":1,"max_val":2147483647,"collspcname":""}, + {"member_name":"mname3","type":"text[]","is_tlength":false,"is_precision":false,"collation":"pg_catalog.\"C\"","collspcname":""} + ], + "typacl":[], + "seclabels":[], + "description":"" + }, + "expected_sql_file": "create_composite_type.sql", + "expected_msql_file": "create_composite_type.msql" + }, + { + "type": "alter", + "name": "alter Composite type and add new label", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "composite": {"added": [{"member_name":"mname4","type":"bigint","is_tlength":false,"is_precision":false}]} + }, + "expected_sql_file": "alter_composite_type_add_member.sql", + "expected_msql_file": "alter_composite_type_add_member.msql" + }, + { + "type": "alter", + "name": "alter Composite type and delete label", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "composite": {"deleted":[{"attnum":1,"member_name":"mname1","type":"bigint","tlength":null,"is_tlength":false,"precision":null,"is_precision":false,"collation":"","cltype":"bigint","hasSqrBracket":false,"fulltype":"bigint"}]} + }, + "expected_sql_file": "alter_composite_type_remove_member.sql", + "expected_msql_file": "alter_composite_type_remove_member.msql" + }, + { + "type": "alter", + "name": "alter Composite type and add ACL, description", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "description":"this is test", + "typacl": {"added": [{"grantee":"PUBLIC","grantor":"enterprisedb","privileges":[{"privilege_type":"U","privilege":true,"with_grant":false}]}]} + }, + "expected_sql_file": "alter_composite_type_acl_description.sql", + "expected_msql_file": "alter_composite_type_acl_description.msql" + }, + { + "type": "delete", + "name": "Drop Composite type", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + }, + + { + "type": "create", + "name": "Create Composite type - one field", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "data": { + "name": "composite_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"c", + "schema":"public", + "composite":[ + {"member_name":"mname1","type":"bigint","is_tlength":false,"is_precision":false} + ], + "typacl":[], + "seclabels":[], + "description":"" + }, + "expected_sql_file": "create_composite_type_one_field.sql" + }, + { + "type": "delete", + "name": "Drop Composite type - one field", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + }, + + { + "type": "create", + "name": "Create SHELL type", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql", + "data": { + "name": "shell_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"p", + "schema":"public", + "composite":[], + "enum":[], + "typacl":[], + "seclabels":[] + }, + "expected_sql_file": "create_shell_type.sql", + "expected_msql_file": "create_shell_type.msql" + }, + { + "type": "alter", + "name": "alter SHELL type and add description", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "description":"this is test" + }, + "expected_sql_file": "alter_shell_type_acl_description.sql", + "expected_msql_file": "alter_shell_type_acl_description.msql" + }, + { + "type": "delete", + "name": "Drop SHELL type", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + }, + + + { + "type": "create", + "name": "Create RANGE type", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql", + "data": { + "name": "range_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"r", + "schema":"public", + "composite":[], + "enum":[], + "typacl":[], + "seclabels":[], + "typname":"bool" + }, + "expected_sql_file": "create_range_type.sql", + "expected_msql_file": "create_range_type.msql" + }, + { + "type": "alter", + "name": "alter RANGE type and add ACL, description", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "description":"this is test", + "typacl": {"added": [{"grantee":"PUBLIC","grantor":"enterprisedb","privileges":[{"privilege_type":"U","privilege":true,"with_grant":false}]}]} + }, + "expected_sql_file": "alter_range_type_acl_description.sql", + "expected_msql_file": "alter_range_type_acl_description.msql" + }, + { + "type": "alter", + "name": "alter ACL (Remove privilege)", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "typacl": { + "deleted": [ + { + "grantee": "PUBLIC", + "grantor": "enterprisedb", + "privileges": [ + { + "privilege_type": "U", + "privilege": true, + "with_grant": false + } + ] + } + ] + } + } + }, + { + "type": "alter", + "name": "alter ACL (change grantee)", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "typacl": { + "changed": [ + { + "grantee": "PUBLIC", + "grantor": "enterprisedb", + "old_grantee": "enterprisedb", + "privileges": [ + { + "privilege_type": "U", + "privilege": true, + "with_grant": false + } + ] + } + ] + } + }, + "expected_sql_file": "alter_acl_grantee_change.sql", + "expected_msql_file": "alter_acl_grantee_change_msql.sql" + }, + { + "type": "delete", + "name": "Drop RANGE type", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + }, + { + "type": "create", + "name": "Create Multi RANGE type", + "endpoint": "NODE-type.obj", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql", + "data": { + "name": "range_type_$%{}[]()&*^!@\"'`\\/#", + "is_sys_type":false, + "typtype":"r", + "schema":"public", + "composite":[], + "enum":[], + "typacl":[], + "seclabels":[], + "typname":"bool", + "rngmultirangetype": "multirange_type" + }, + "expected_sql_file": "create_multi_range_type.sql", + "expected_msql_file": "create_multi_range_type.msql" + }, + { + "type": "delete", + "name": "Drop RANGE type", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "data": {} + } + ] +} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/default/alter_enum_type_rename_enum.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/default/alter_enum_type_rename_enum.msql new file mode 100644 index 000000000..9ca45582c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/default/alter_enum_type_rename_enum.msql @@ -0,0 +1,4 @@ +ALTER TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" + RENAME VALUE 'a' TO 'a_new'; +ALTER TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" + RENAME VALUE 'd' TO 'd_new'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/default/alter_enum_type_rename_enum.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/default/alter_enum_type_rename_enum.sql new file mode 100644 index 000000000..02f31566c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/default/alter_enum_type_rename_enum.sql @@ -0,0 +1,16 @@ +-- Type: enum_type_$%{}[]()&*^!@"'`\/# + +-- DROP TYPE IF EXISTS public."enum_type_$%{}[]()&*^!@""'`\/#"; + +CREATE TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" AS ENUM + ('a_new', 'b', 'c', 'd_new'); + +ALTER TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" + OWNER TO ; + +COMMENT ON TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" + IS 'this is test'; + +GRANT USAGE ON TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" TO PUBLIC; + +GRANT USAGE ON TYPE public."enum_type_$%{}[]()&*^!@""'`\/#" TO ; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/default/tests.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/default/tests.json index 94018e027..2aa4cbd34 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/default/tests.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/tests/ppas/default/tests.json @@ -45,6 +45,18 @@ "expected_sql_file": "alter_enum_type_acl_description.sql", "expected_msql_file": "alter_enum_type_acl_description.msql" }, + { + "type": "alter", + "name": "alter ENUM type and rename ENUM", + "endpoint": "NODE-type.obj_id", + "sql_endpoint": "NODE-type.sql_id", + "msql_endpoint": "NODE-type.msql_id", + "data": { + "enum": {"changed": [{"label": "a_new", "old_label": "a"}, {"label": "d_new", "old_label": "d"}]} + }, + "expected_sql_file": "alter_enum_type_rename_enum.sql", + "expected_msql_file": "alter_enum_type_rename_enum.msql" + }, { "type": "delete", "name": "Drop ENUM type", diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js index 3a6af0d9f..a574e768e 100644 --- a/web/pgadmin/browser/static/js/node.js +++ b/web/pgadmin/browser/static/js/node.js @@ -113,7 +113,7 @@ define('pgadmin.browser.node', [ if (self.node_initialized) return; self.node_initialized = true; - + pgAdmin.Browser.add_menus([{ name: 'refresh', node: self.type, @@ -122,7 +122,7 @@ define('pgadmin.browser.node', [ callback: 'refresh', priority: 2, label: gettext('Refresh...'), - shortcut_preference: ['browser', 'sub_menu_refresh'], + shortcut_preference: ['browser', 'sub_menu_refresh'], enable: true, }]); @@ -208,7 +208,7 @@ define('pgadmin.browser.node', [ label: gettext('Query Tool'), enable: enable, permission: AllPermissionTypes.TOOLS_QUERY_TOOL, - shortcut_preference: ['browser', 'sub_menu_query_tool'], + shortcut_preference: ['browser', 'sub_menu_query_tool'], }]); // show search objects same as query tool @@ -587,6 +587,11 @@ define('pgadmin.browser.node', [ }, 10); selectNextNode = false; } + if (obj.refreshParent?.(i)) { + obj.callbacks.refresh('refresh', t.parent(i)); + return; + } + pgBrowser.removeTreeNode(i, selectNextNode); } return true; diff --git a/web/pgadmin/static/js/tree/tree.js b/web/pgadmin/static/js/tree/tree.js index becb5093d..e848a7509 100644 --- a/web/pgadmin/static/js/tree/tree.js +++ b/web/pgadmin/static/js/tree/tree.js @@ -84,7 +84,7 @@ export class Tree { this.rootNode = manageTree.tempTree; this.Nodes = pgBrowser ? pgBrowser.Nodes : pgAdmin.Browser.Nodes; - // Flag to suppress added and opened tree event being called during object search operations, + // Flag to suppress added and opened tree event being called during object search operations, // tree.select of search object clashes with other tree.select. this.suppressEventsForPath = null; this.draggableTypes = {}; @@ -479,7 +479,13 @@ export class Tree { let node_cnt = 0; let result = {}; if (!identifier) return; - let item = TreeNode.prototype.isPrototypeOf(identifier) ? identifier : this.findNode(identifier.path); + let item; + try { + item = TreeNode.prototype.isPrototypeOf(identifier) ? identifier : this.findNode(identifier.path); + } catch { + // It is possible that the requested path is not present in the tree anymore + item = null; + } if (!item) return; do { const currentNodeData = item.getData();