1) Added "MULTIRANGE_TYPE_NAME" option while creating a Range Type. #6394

2) Added "SUBSCRIPT" option while creating an External Type. #6395
pull/9162/head
Akshay Joshi 2025-09-11 14:27:27 +05:30 committed by GitHub
parent 2fd2a144f1
commit 3e66b6f7be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 1868 additions and 71 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -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

View File

@ -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 <https://github.com/pgadmin-org/pgadmin4/issues/6394>`_ - Added "MULTIRANGE_TYPE_NAME" option while creating a Range Type.
| `Issue #6395 <https://github.com/pgadmin-org/pgadmin4/issues/6395>`_ - Added "SUBSCRIPT" option while creating a External Type.
Housekeeping
************
Bug fixes
*********

View File

@ -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:

View File

@ -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,

View File

@ -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)

View File

@ -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'),

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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;

View File

@ -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;

View File

@ -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 %}

View File

@ -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

View File

@ -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)

View File

@ -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,

View File

@ -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 #}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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;

View File

@ -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;

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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)

View File

@ -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,

View File

@ -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 #}

View File

@ -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 <OWNER>;
COMMENT ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#"
IS 'this is test';
GRANT USAGE ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" TO PUBLIC;

View File

@ -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 <OWNER>;
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 <OWNER>;

View File

@ -0,0 +1,5 @@
CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE
(
SUBTYPE=bool,
MULTIRANGE_TYPE_NAME = multirange_type
);

View File

@ -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 <OWNER>;

View File

@ -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 <OWNER>;

View File

@ -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": {}
}
]
}

View File

@ -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';

View File

@ -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 <OWNER>;
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 <OWNER>;

View File

@ -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",

View File

@ -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 <OWNER>;
COMMENT ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#"
IS 'this is test';
GRANT USAGE ON TYPE public."range_type_$%{}[]()&*^!@""'`\/#" TO PUBLIC;

View File

@ -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 <OWNER>;
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 <OWNER>;

View File

@ -0,0 +1,5 @@
CREATE TYPE public."range_type_$%{}[]()&*^!@""'`\/#" AS RANGE
(
SUBTYPE=bool,
MULTIRANGE_TYPE_NAME = multirange_type
);

View File

@ -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 <OWNER>;

View File

@ -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 <OWNER>;

View File

@ -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": {}
}
]
}

View File

@ -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';

View File

@ -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 <OWNER>;
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 <OWNER>;

View File

@ -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",

View File

@ -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;

View File

@ -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();