mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-01-24 15:26:46 -06:00
Added support for the creation of Nested Table and Varying Array Type for Advanced Server. Fixes #6407
This commit is contained in:
parent
c32ff3a7ee
commit
b0df4d3604
@ -27,6 +27,7 @@ Bug fixes
|
||||
| `Issue #6355 <https://redmine.postgresql.org/issues/6355>`_ - Ensure that pgAdmin should not allow opening external files that are dragged into it.
|
||||
| `Issue #6377 <https://redmine.postgresql.org/issues/6377>`_ - Fixed an issue where schema diff does not create DROP DEFAULT statement for columns.
|
||||
| `Issue #6385 <https://redmine.postgresql.org/issues/6385>`_ - Ensure that Backup and Restore should work on shared servers.
|
||||
| `Issue #6407 <https://redmine.postgresql.org/issues/6407>`_ - Added support for the creation of Nested Table and Varying Array Type for Advanced Server.
|
||||
| `Issue #6408 <https://redmine.postgresql.org/issues/6408>`_ - Fixed ModuleNotFoundError when running setup.py from outside of the root.
|
||||
| `Issue #6409 <https://redmine.postgresql.org/issues/6409>`_ - Fixed an issue where the current debug line is not visible in the 'Dark' theme.
|
||||
| `Issue #6413 <https://redmine.postgresql.org/issues/6413>`_ - Fixed an issue where duplicate columns are visible in the browser tree, which is owned by two sequences.
|
||||
|
@ -246,14 +246,12 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
||||
# Declare allows acl on type
|
||||
self.acl = ['U']
|
||||
|
||||
ver = self.manager.version
|
||||
server_type = self.manager.server_type
|
||||
# Set the template path for the SQL scripts
|
||||
self.template_path = 'types/sql/' + (
|
||||
'#{0}#{1}#'.format(server_type, ver)
|
||||
if server_type == 'gpdb' else
|
||||
'#{0}#'.format(ver)
|
||||
)
|
||||
self.template_path = "/".join([
|
||||
'types',
|
||||
self.manager.server_type,
|
||||
'sql',
|
||||
'#{0}#'
|
||||
]).format(self.manager.version)
|
||||
|
||||
return f(*args, **kwargs)
|
||||
|
||||
@ -472,6 +470,31 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
||||
|
||||
return res
|
||||
|
||||
def _additional_properties_advanced_server_type(self, data):
|
||||
"""
|
||||
Used by additional_properties internally for advanced server types.
|
||||
:param rows: list of data
|
||||
:return: formatted response
|
||||
"""
|
||||
is_tlength, is_precision, typeval = \
|
||||
self.get_length_precision(data.get('elemoid', None))
|
||||
|
||||
# Split length, precision from type name for grid
|
||||
t_len, t_prec = DataTypeReader.parse_length_precision(
|
||||
data['fulltype'], is_tlength, is_precision)
|
||||
|
||||
data = self.convert_length_precision_to_string(data)
|
||||
data['type'] = self._cltype_formatter(data['type'])
|
||||
data['cltype'] = self._cltype_formatter(data['type'])
|
||||
data['hasSqrBracket'] = self.hasSqrBracket
|
||||
data['tlength'] = t_len,
|
||||
data['precision'] = t_prec
|
||||
data['is_tlength'] = is_tlength,
|
||||
data['is_precision'] = is_precision,
|
||||
data['maxsize'] = data['typndims']
|
||||
|
||||
return data
|
||||
|
||||
def additional_properties(self, copy_dict, tid):
|
||||
"""
|
||||
We will use this function to add additional properties according to
|
||||
@ -485,13 +508,13 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
||||
of_type = copy_dict['typtype']
|
||||
res = dict()
|
||||
|
||||
render_args = {'type': of_type}
|
||||
render_args = {'typtype': of_type}
|
||||
if of_type == 'c':
|
||||
render_args['typrelid'] = copy_dict['typrelid']
|
||||
else:
|
||||
render_args['tid'] = tid
|
||||
|
||||
if of_type in ('c', 'e', 'r'):
|
||||
if of_type in ('c', 'e', 'r', 'N', 'V', 'A'):
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
'additional_properties.sql']),
|
||||
**render_args)
|
||||
@ -505,6 +528,11 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
||||
# To display in properties
|
||||
res = self._additional_properties_composite(rset['rows'])
|
||||
|
||||
if of_type in ('N', 'V'):
|
||||
# To display in properties
|
||||
res = self._additional_properties_advanced_server_type(
|
||||
rset['rows'][0])
|
||||
|
||||
# If type is of ENUM then we need to add labels in our output
|
||||
if of_type == 'e':
|
||||
# To display in properties
|
||||
@ -1003,6 +1031,12 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
||||
each_type['type'])
|
||||
each_type['hasSqrBracket'] = self.hasSqrBracket
|
||||
|
||||
of_type = data.get('typtype', None)
|
||||
if of_type in ('N', 'V'):
|
||||
data = self.convert_length_precision_to_string(data)
|
||||
data['cltype'] = self._cltype_formatter(data['type'])
|
||||
data['hasSqrBracket'] = self.hasSqrBracket
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._CREATE_SQL]),
|
||||
data=data, conn=self.conn)
|
||||
@ -1281,6 +1315,14 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
||||
each_type['type'])
|
||||
each_type['hasSqrBracket'] = self.hasSqrBracket
|
||||
|
||||
of_type = data.get('typtype', None)
|
||||
if of_type in ('N', 'V', 'A'):
|
||||
data = self.convert_length_precision_to_string(data)
|
||||
data['cltype'] = self._cltype_formatter(data['type'])
|
||||
data['hasSqrBracket'] = self.hasSqrBracket
|
||||
if of_type == 'V':
|
||||
data['typndims'] = data['maxsize']
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._CREATE_SQL]),
|
||||
data=data, conn=self.conn, is_sql=is_sql)
|
||||
@ -1307,6 +1349,15 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
||||
each_type['type'])
|
||||
each_type['hasSqrBracket'] = self.hasSqrBracket
|
||||
|
||||
of_type = data.get('typtype', None)
|
||||
if of_type in ('N', 'V', 'A'):
|
||||
data = self.convert_length_precision_to_string(data)
|
||||
data['cltype'] = self._cltype_formatter(data['type'])
|
||||
data['hasSqrBracket'] = self.hasSqrBracket
|
||||
|
||||
if of_type == 'V':
|
||||
data['typndims'] = data['maxsize']
|
||||
|
||||
SQL = render_template(
|
||||
"/".join([self.template_path,
|
||||
self._PROPERTIES_SQL]),
|
||||
|
@ -343,13 +343,21 @@ define('pgadmin.node.type', [
|
||||
group: gettext('Definition'),
|
||||
select2: { allowClear: false },
|
||||
options: function() {
|
||||
return [
|
||||
var typetype = [
|
||||
{label: gettext('Composite'), value: 'c'},
|
||||
{label: gettext('Enumeration'), value: 'e'},
|
||||
{label: gettext('External'), value: 'b'},
|
||||
{label: gettext('Range'), value: 'r'},
|
||||
{label: gettext('Shell'), value: 'p'},
|
||||
];
|
||||
if (this.node_info.server.server_type === 'ppas' &&
|
||||
this.node_info.server.version >= 90500){
|
||||
typetype.push(
|
||||
{label: gettext('Nested Table'), value: 'N'},
|
||||
{label: gettext('Varying Array'), value: 'V'}
|
||||
);
|
||||
}
|
||||
return typetype;
|
||||
},
|
||||
// If create mode then by default open composite type
|
||||
control: Backform.Select2Control.extend({
|
||||
@ -385,6 +393,171 @@ define('pgadmin.node.type', [
|
||||
visible: function(m) {
|
||||
return m.get('typtype') === 'e';
|
||||
},
|
||||
},{
|
||||
type: 'nested',
|
||||
group: gettext('Definition'),
|
||||
label: '',
|
||||
control: 'plain-fieldset',
|
||||
deps: ['typtype'],
|
||||
mode: ['edit', 'create', 'properties'],
|
||||
visible: function (m) {
|
||||
return m.get('typtype') === 'N' || m.get('typtype') === 'V';
|
||||
},
|
||||
schema: [{
|
||||
id: 'type',
|
||||
type: 'text',
|
||||
label: gettext('Data Type'),
|
||||
group: gettext('Definition'),
|
||||
control: 'node-ajax-options',
|
||||
mode: ['edit', 'create','properties'],
|
||||
readonly: 'inEditMode',
|
||||
url: 'get_types',
|
||||
disabled: false,
|
||||
node: 'type',
|
||||
cache_node: 'domain',
|
||||
editable: true,
|
||||
deps: ['typtype'],
|
||||
cell: 'node-ajax-options',
|
||||
select2: { allowClear: false },
|
||||
transform: function (d, control) {
|
||||
var data_types = [];
|
||||
_.each(d, function (o) {
|
||||
if (!(o.value.includes('[]'))) {
|
||||
data_types.push(o);
|
||||
}
|
||||
});
|
||||
control.model.type_options = data_types;
|
||||
return data_types;
|
||||
},
|
||||
},{
|
||||
id: 'maxsize',
|
||||
group: gettext('Definition'),
|
||||
label: gettext('Size'),
|
||||
type: 'int',
|
||||
deps: ['typtype'],
|
||||
cell: IntegerDepCell,
|
||||
mode: ['create', 'edit','properties'],
|
||||
readonly: 'inEditMode',
|
||||
visible: function (m) {
|
||||
return m.get('typtype') === 'V';
|
||||
}
|
||||
},{
|
||||
// Note: There are ambiguities in the PG catalogs and docs between
|
||||
// precision and scale. In the UI, we try to follow the docs as
|
||||
// closely as possible, therefore we use Length/Precision and Scale
|
||||
id: 'tlength',
|
||||
group: gettext('Data Type'),
|
||||
label: gettext('Length/Precision'),
|
||||
mode: ['edit', 'create','properties'],
|
||||
deps: ['type'],
|
||||
type: 'text',
|
||||
readonly: 'inEditMode',
|
||||
cell: IntegerDepCell,
|
||||
visible: function (m) {
|
||||
return m.get('typtype') === 'N';
|
||||
},
|
||||
disabled: function (m) {
|
||||
var of_type = m.get('type'),
|
||||
flag = true;
|
||||
_.each(m.type_options, function (o) {
|
||||
if (of_type == o.value) {
|
||||
if (o.length) {
|
||||
m.set('min_val_attlen', o.min_val, { silent: true });
|
||||
m.set('max_val_attlen', o.max_val, { silent: true });
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
flag && setTimeout(function () {
|
||||
if (m.get('attlen')) {
|
||||
m.set('attlen', null);
|
||||
}
|
||||
}, 10);
|
||||
return flag;
|
||||
},
|
||||
editable: function (m) {
|
||||
// We will store type from selected from combobox
|
||||
var of_type = m.get('type');
|
||||
if (m.type_options) {
|
||||
// iterating over all the types
|
||||
_.each(m.type_options, function (o) {
|
||||
// if type from selected from combobox matches in options
|
||||
if (of_type == o.value) {
|
||||
// if length is allowed for selected type
|
||||
if (o.length) {
|
||||
// set the values in model
|
||||
m.set('is_tlength', true, { silent: true });
|
||||
m.set('min_val', o.min_val, { silent: true });
|
||||
m.set('max_val', o.max_val, { silent: true });
|
||||
} else {
|
||||
// set the values in model
|
||||
m.set('is_tlength', false, { silent: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return m.get('is_tlength');
|
||||
}
|
||||
},{
|
||||
// Note: There are ambiguities in the PG catalogs and docs between
|
||||
// precision and scale. In the UI, we try to follow the docs as
|
||||
// closely as possible, therefore we use Length/Precision and Scale
|
||||
id: 'precision',
|
||||
group: gettext('Data Type'),
|
||||
label: gettext('Scale'),
|
||||
mode: ['edit', 'create','properties'],
|
||||
deps: ['type'],
|
||||
type: 'text',
|
||||
readonly: 'inEditMode',
|
||||
cell: IntegerDepCell,
|
||||
visible: function (m) {
|
||||
return m.get('typtype') === 'N';
|
||||
},
|
||||
disabled: function(m) {
|
||||
var of_type = m.get('type'),
|
||||
flag = true;
|
||||
_.each(m.type_options, function(o) {
|
||||
if ( of_type == o.value ) {
|
||||
if(o.precision) {
|
||||
m.set('min_val_attprecision', 0, {silent: true});
|
||||
m.set('max_val_attprecision', o.max_val, {silent: true});
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
flag && setTimeout(function() {
|
||||
if(m.get('attprecision')) {
|
||||
m.set('attprecision', null);
|
||||
}
|
||||
},10);
|
||||
return flag;
|
||||
},
|
||||
editable: function(m) {
|
||||
// We will store type from selected from combobox
|
||||
var of_type = m.get('type');
|
||||
if(m.type_options) {
|
||||
// iterating over all the types
|
||||
_.each(m.type_options, function(o) {
|
||||
// if type from selected from combobox matches in options
|
||||
if ( of_type == o.value ) {
|
||||
// if precession is allowed for selected type
|
||||
if(o.precision)
|
||||
{
|
||||
// set the values in model
|
||||
m.set('is_precision', true, {silent: true});
|
||||
m.set('min_val', o.min_val, {silent: true});
|
||||
m.set('max_val', o.max_val, {silent: true});
|
||||
} else {
|
||||
// set the values in model
|
||||
m.set('is_precision', false, {silent: true});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return m.get('is_precision');
|
||||
},
|
||||
}]
|
||||
},{
|
||||
// We will disable range type control in edit mode
|
||||
type: 'nested', control: 'plain-fieldset', group: gettext('Definition'),
|
||||
|
@ -1,5 +1,5 @@
|
||||
{# The SQL given below will fetch composite type#}
|
||||
{% if type == 'c' %}
|
||||
{% 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,
|
||||
@ -16,7 +16,7 @@ FROM pg_catalog.pg_attribute att
|
||||
{% endif %}
|
||||
|
||||
{# The SQL given below will fetch enum type#}
|
||||
{% if type == 'e' %}
|
||||
{% if typtype == 'e' %}
|
||||
SELECT enumlabel
|
||||
FROM pg_catalog.pg_enum
|
||||
WHERE enumtypid={{tid}}::oid
|
||||
@ -24,7 +24,7 @@ FROM pg_catalog.pg_enum
|
||||
{% endif %}
|
||||
|
||||
{# The SQL given below will fetch range type#}
|
||||
{% if type == 'r' %}
|
||||
{% if typtype == 'r' %}
|
||||
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,
|
@ -0,0 +1,27 @@
|
||||
SELECT 'typacl' as deftype, COALESCE(gt.rolname, 'PUBLIC') grantee, g.rolname grantor, pg_catalog.array_agg(privilege_type) as privileges, pg_catalog.array_agg(is_grantable) as grantable
|
||||
FROM
|
||||
(SELECT
|
||||
d.grantee, d.grantor, d.is_grantable,
|
||||
CASE d.privilege_type
|
||||
WHEN 'USAGE' THEN 'U'
|
||||
ELSE 'UNKNOWN'
|
||||
END AS privilege_type
|
||||
FROM
|
||||
(SELECT t.typacl
|
||||
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)
|
||||
WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%' AND t.typnamespace = {{scid}}::oid
|
||||
{% if tid %}
|
||||
AND t.oid = {{tid}}::oid
|
||||
{% endif %}
|
||||
) acl,
|
||||
(SELECT (d).grantee AS grantee, (d).grantor AS grantor, (d).is_grantable
|
||||
AS is_grantable, (d).privilege_type AS privilege_type FROM (SELECT
|
||||
pg_catalog.aclexplode(t.typacl) as d FROM pg_catalog.pg_type t WHERE t.oid = {{tid}}::oid) a ORDER BY privilege_type) d
|
||||
) d
|
||||
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
|
||||
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
|
||||
GROUP BY g.rolname, gt.rolname
|
||||
ORDER BY grantee
|
@ -0,0 +1,58 @@
|
||||
{# 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,
|
||||
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
|
||||
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
|
||||
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 %}
|
@ -0,0 +1,94 @@
|
||||
{% 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 }}{% 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 %}
|
||||
|
||||
);
|
||||
{% 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.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}}{% endif %}{% if data.typispreferred %},
|
||||
PREFERRED = {{data.typispreferred}}{% endif %}{% if data.typdefault %},
|
||||
DEFAULT = {{data.typdefault|qtLiteral}}{% endif %}{% if data.element %},
|
||||
ELEMENT = {{data.element}}{% endif %}{% if data.typdelim %},
|
||||
DELIMITER = {{data.typdelim|qtLiteral}}{% 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}};
|
||||
{% 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 %}
|
@ -0,0 +1 @@
|
||||
DROP TYPE {{ conn|qtIdent(data.schema, data.name) }}{% if cascade%} CASCADE{% endif %};
|
@ -0,0 +1,7 @@
|
||||
SELECT --nspname, collname,
|
||||
CASE WHEN length(nspname::text) > 0 AND length(collname::text) > 0 THEN
|
||||
pg_catalog.concat(pg_catalog.quote_ident(nspname), '.', pg_catalog.quote_ident(collname))
|
||||
ELSE '' END AS collation
|
||||
FROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n
|
||||
WHERE c.collnamespace=n.oid
|
||||
ORDER BY nspname, collname;
|
@ -0,0 +1,42 @@
|
||||
{### 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
|
||||
pg_catalog.concat(pg_catalog.quote_ident(nspname), '.', pg_catalog.quote_ident(proname))
|
||||
WHEN length(proname::text) > 0 THEN
|
||||
pg_catalog.quote_ident(proname)
|
||||
ELSE '' END AS func
|
||||
FROM (
|
||||
SELECT proname, nspname, max(proargtypes[0]) AS arg0, max(proargtypes[1]) AS arg1
|
||||
FROM pg_catalog.pg_proc p
|
||||
JOIN pg_catalog.pg_namespace n ON n.oid=pronamespace
|
||||
GROUP BY proname, nspname
|
||||
HAVING count(proname) = 1) AS uniquefunc
|
||||
WHERE arg0 <> 0 AND (arg1 IS NULL OR arg1 <> 0);
|
||||
{% endif %}
|
||||
{### TypmodIN list ###}
|
||||
{% if typemodin %}
|
||||
SELECT proname, nspname,
|
||||
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))
|
||||
ELSE '' END AS func
|
||||
FROM pg_catalog.pg_proc p
|
||||
JOIN pg_catalog.pg_namespace n ON n.oid=pronamespace
|
||||
WHERE prorettype=(SELECT oid FROM pg_catalog.pg_type WHERE typname='int4')
|
||||
AND proargtypes[0]=(SELECT oid FROM pg_catalog.pg_type WHERE typname='_cstring')
|
||||
AND proargtypes[1] IS NULL
|
||||
ORDER BY nspname, proname;
|
||||
{% endif %}
|
||||
{### TypmodOUT list ###}
|
||||
{% if typemodout %}
|
||||
SELECT proname, nspname,
|
||||
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))
|
||||
ELSE '' END AS func
|
||||
FROM pg_catalog.pg_proc p
|
||||
JOIN pg_catalog.pg_namespace n ON n.oid=pronamespace
|
||||
WHERE prorettype=(SELECT oid FROM pg_catalog.pg_type WHERE typname='cstring')
|
||||
AND proargtypes[0]=(SELECT oid FROM pg_catalog.pg_type WHERE typname='int4')
|
||||
AND proargtypes[1] IS NULL
|
||||
ORDER BY nspname, proname;
|
||||
{% endif %}
|
@ -0,0 +1,11 @@
|
||||
{# Below will provide oid for newly created type #}
|
||||
SELECT t.oid
|
||||
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)
|
||||
WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%' AND t.typnamespace = {{scid}}::oid
|
||||
{% if data %}
|
||||
AND t.typname = {{data.name|qtLiteral}}
|
||||
{% endif %}
|
||||
ORDER BY t.typname;
|
@ -0,0 +1,15 @@
|
||||
{% if tid %}
|
||||
SELECT
|
||||
t.typnamespace as scid
|
||||
FROM
|
||||
pg_catalog.pg_type t
|
||||
WHERE
|
||||
t.oid = {{tid}}::oid;
|
||||
{% else %}
|
||||
SELECT
|
||||
ns.oid as scid
|
||||
FROM
|
||||
pg_catalog.pg_namespace ns
|
||||
WHERE
|
||||
ns.nspname = {{schema|qtLiteral}}::text;
|
||||
{% endif %}
|
@ -0,0 +1,56 @@
|
||||
{### To fill subtype combobox ###}
|
||||
{% if subtype %}
|
||||
SELECT DISTINCT typ.typname AS stype,
|
||||
(CASE WHEN typ.typcollation > 0 THEN true ELSE false END) AS is_collate
|
||||
FROM pg_catalog.pg_opclass opc
|
||||
JOIN pg_catalog.pg_type typ ON opc.opcintype = typ.oid
|
||||
WHERE opc.opcmethod = 403
|
||||
ORDER BY 1
|
||||
{% endif %}
|
||||
{### To fill subtype opclass combobox ###}
|
||||
{% if subtype_opclass and data and data.typname %}
|
||||
SELECT opc.opcname
|
||||
FROM pg_catalog.pg_opclass opc
|
||||
JOIN pg_catalog.pg_type typ ON opc.opcintype=typ.oid
|
||||
AND typ.typname = {{ data.typname|qtLiteral }}
|
||||
WHERE opc.opcmethod = 403
|
||||
ORDER BY opcname;
|
||||
{% endif %}
|
||||
{### To fetch opcinttype from subtype opclass ###}
|
||||
{% if get_opcintype and data and data.typname and data.opcname %}
|
||||
SELECT opc.opcintype
|
||||
FROM pg_catalog.pg_opclass opc
|
||||
JOIN pg_catalog.pg_type typ ON opc.opcintype=typ.oid
|
||||
AND typ.typname = {{ data.typname|qtLiteral }}
|
||||
WHERE opc.opcmethod = 403
|
||||
AND opc.opcname = {{ data.opcname|qtLiteral }}
|
||||
ORDER BY opcname;
|
||||
{% endif %}
|
||||
{### To fill subtype diff function combobox ###}
|
||||
{% if opcintype %}
|
||||
SELECT proname, nspname,
|
||||
CASE WHEN length(nspname::text) > 0 AND length(proname::text) > 0 THEN
|
||||
pg_catalog.concat(quote_ident(nspname), '.', pg_catalog.quote_ident(proname))
|
||||
ELSE '' END AS stypdiff
|
||||
FROM pg_catalog.pg_proc
|
||||
JOIN pg_catalog.pg_namespace n ON n.oid=pronamespace
|
||||
WHERE prorettype = 701
|
||||
AND proargtypes = '{{opcintype}} {{opcintype}}'
|
||||
ORDER BY proname;
|
||||
{% endif %}
|
||||
{### To fill canonical combobox ###}
|
||||
{% if getoid %}
|
||||
SELECT oid FROM pg_catalog.pg_type
|
||||
WHERE typname = {{ data.name|qtLiteral }}
|
||||
{% endif %}
|
||||
{% if canonical and oid %}
|
||||
SELECT proname, nspname,
|
||||
CASE WHEN length(nspname::text) > 0 AND length(proname::text) > 0 THEN
|
||||
pg_catalog.concat(quote_ident(nspname), '.', pg_catalog.quote_ident(proname))
|
||||
ELSE '' END AS canonical
|
||||
FROM pg_catalog.pg_proc
|
||||
JOIN pg_catalog.pg_namespace n ON n.oid=pronamespace
|
||||
WHERE prorettype= {{ oid }}
|
||||
AND proargtypes = '{{ oid }}'
|
||||
ORDER BY proname;
|
||||
{% endif %}
|
@ -0,0 +1,11 @@
|
||||
SELECT * FROM
|
||||
(SELECT pg_catalog.format_type(t.oid,NULL) AS typname,
|
||||
CASE WHEN typelem > 0 THEN typelem ELSE t.oid END AS elemoid,
|
||||
typlen, typtype, t.oid, nspname,
|
||||
(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
|
||||
JOIN pg_catalog.pg_namespace nsp ON typnamespace=nsp.oid
|
||||
WHERE (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) AND typisdefined AND typtype IN ('b', 'c', 'd', 'e', 'r') AND NOT EXISTS (select 1 from pg_catalog.pg_class where relnamespace=typnamespace and relname = typname and relkind != 'c') AND (typname not like '_%' OR NOT EXISTS (select 1 from pg_catalog.pg_class where relnamespace=typnamespace and relname = substring(typname from 2)::name and relkind != 'c')) AND nsp.nspname != 'information_schema'
|
||||
) AS dummy
|
||||
ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1
|
@ -0,0 +1,13 @@
|
||||
SELECT t.oid, t.typname AS name
|
||||
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_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;
|
@ -0,0 +1,24 @@
|
||||
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,
|
||||
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;
|
@ -0,0 +1,161 @@
|
||||
{% 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 }};
|
||||
|
||||
{% 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}} {% if o_enum_len > 0 %}AFTER {{o_data.enum[o_enum_len].label|qtLiteral }}{% 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}} AFTER {{enum.added[p_idx].label|qtLiteral}};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% 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 %}
|
@ -1,53 +0,0 @@
|
||||
"""
|
||||
Here is the list of Postgres inbuilt types & their OID's
|
||||
We will use these types to check for validations
|
||||
|
||||
## PGOID_TYPE_SERIAL -42L
|
||||
## PGOID_TYPE_SERIAL8 -43L
|
||||
## PGOID_TYPE_SERIAL2 -44L
|
||||
## PGOID_TYPE_BOOL 16L
|
||||
## PGOID_TYPE_BYTEA 17L
|
||||
## PGOID_TYPE_CHAR 18L
|
||||
## PGOID_TYPE_NAME 19L
|
||||
## PGOID_TYPE_INT8 20L
|
||||
## PGOID_TYPE_INT2 21L
|
||||
## PGOID_TYPE_INT4 23L
|
||||
## PGOID_TYPE_TEXT 25L
|
||||
## PGOID_TYPE_OID 26L
|
||||
## PGOID_TYPE_TID 27L
|
||||
## PGOID_TYPE_XID 28L
|
||||
## PGOID_TYPE_CID 29L
|
||||
## PGOID_TYPE_FLOAT4 700L
|
||||
## PGOID_TYPE_FLOAT8 701L
|
||||
## PGOID_TYPE_MONEY 790L
|
||||
## PGOID_TYPE_CHAR_ARRAY 1002L
|
||||
## PGOID_TYPE_TEXT_ARRAY 1009L
|
||||
## PGOID_TYPE_BPCHAR_ARRAY 1014L
|
||||
## PGOID_TYPE_VARCHAR_ARRAY 1015L
|
||||
## PGOID_TYPE_BPCHAR 1042L
|
||||
## PGOID_TYPE_VARCHAR 1043L
|
||||
## PGOID_TYPE_DATE 1082L
|
||||
## PGOID_TYPE_TIME 1083L
|
||||
## PGOID_TYPE_TIMESTAMP 1114L
|
||||
## PGOID_TYPE_TIMESTAMP_ARRAY 1115L
|
||||
## PGOID_TYPE_TIME_ARRAY 1183L
|
||||
## PGOID_TYPE_TIMESTAMPTZ 1184L
|
||||
## PGOID_TYPE_TIMESTAMPTZ_ARRAY 1185L
|
||||
## PGOID_TYPE_INTERVAL 1186L
|
||||
## PGOID_TYPE_INTERVAL_ARRAY 1187L
|
||||
## PGOID_TYPE_NUMERIC_ARRAY 1231L
|
||||
## PGOID_TYPE_TIMETZ 1266L
|
||||
## PGOID_TYPE_TIMETZ_ARRAY 1270L
|
||||
## PGOID_TYPE_BIT 1560L
|
||||
## PGOID_TYPE_BIT_ARRAY 1561L
|
||||
## PGOID_TYPE_VARBIT 1562L
|
||||
## PGOID_TYPE_VARBIT_ARRAY 1563L
|
||||
## PGOID_TYPE_NUMERIC 1700L
|
||||
## PGOID_TYPE_CSTRING 2275L
|
||||
## PGOID_TYPE_ANY 2276L
|
||||
## PGOID_TYPE_VOID 2278L
|
||||
## PGOID_TYPE_TRIGGER 2279L
|
||||
## PGOID_TYPE_LANGUAGE_HANDLER 2280L
|
||||
## PGOID_TYPE_INTERNAL 2281L
|
||||
## PGOID_TYPE_HANDLER 3115L
|
||||
"""
|
@ -0,0 +1,9 @@
|
||||
-- Type: nested_table_type_$%{}[]()&*^!@"'`\/#
|
||||
|
||||
-- DROP TYPE public."nested_table_type_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE TYPE public."nested_table_type_$%{}[]()&*^!@""'`\/#" AS TABLE OF
|
||||
numeric(2,1);
|
||||
|
||||
ALTER TYPE public."nested_table_type_$%{}[]()&*^!@""'`\/#"
|
||||
OWNER TO enterprisedb;
|
@ -0,0 +1,9 @@
|
||||
-- Type: varray_type_$%{}[]()&*^!@"'`\/#
|
||||
|
||||
-- DROP TYPE public."varray_type_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE TYPE public."varray_type_$%{}[]()&*^!@""'`\/#" AS VARRAY(10) OF
|
||||
integer;
|
||||
|
||||
ALTER TYPE public."varray_type_$%{}[]()&*^!@""'`\/#"
|
||||
OWNER TO enterprisedb;
|
@ -53,7 +53,45 @@
|
||||
"data": {}
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"type": "create",
|
||||
"name": "Create Nested Table type",
|
||||
"endpoint": "NODE-type.obj",
|
||||
"sql_endpoint": "NODE-type.sql_id",
|
||||
"msql_endpoint": "NODE-type.msql",
|
||||
"data": {
|
||||
"name": "nested_table_type_$%{}[]()&*^!@\"'`\\/#",
|
||||
"is_sys_type":false,
|
||||
"typtype":"N",
|
||||
"schema":"public",
|
||||
"type": "numeric",
|
||||
"tlength": 2,
|
||||
"precision": 1,
|
||||
"typacl":[],
|
||||
"seclabels":[],
|
||||
"description":""
|
||||
},
|
||||
"expected_sql_file": "create_nested_table_type.sql"
|
||||
},
|
||||
{
|
||||
"type": "create",
|
||||
"name": "Create Varray type",
|
||||
"endpoint": "NODE-type.obj",
|
||||
"sql_endpoint": "NODE-type.sql_id",
|
||||
"msql_endpoint": "NODE-type.msql",
|
||||
"data": {
|
||||
"name": "varray_type_$%{}[]()&*^!@\"'`\\/#",
|
||||
"is_sys_type":false,
|
||||
"typtype":"V",
|
||||
"schema":"public",
|
||||
"type": "integer",
|
||||
"maxsize": 10,
|
||||
"typacl":[],
|
||||
"seclabels":[],
|
||||
"description":""
|
||||
},
|
||||
"expected_sql_file": "create_varray_type.sql"
|
||||
},
|
||||
{
|
||||
"type": "create",
|
||||
"name": "Create Composite type",
|
||||
|
@ -19,6 +19,7 @@ from regression import parent_node_dict
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as types_utils
|
||||
from unittest.mock import patch
|
||||
from pgadmin.utils import server_utils as server_utils
|
||||
|
||||
|
||||
class TypesAddTestCase(BaseTestGenerator):
|
||||
@ -27,10 +28,23 @@ class TypesAddTestCase(BaseTestGenerator):
|
||||
types_utils.test_cases)
|
||||
|
||||
def setUp(self):
|
||||
self.data = self.test_data
|
||||
self.db_name = parent_node_dict["database"][-1]["db_name"]
|
||||
schema_info = parent_node_dict["schema"][-1]
|
||||
self.server_id = schema_info["server_id"]
|
||||
self.db_id = schema_info["db_id"]
|
||||
|
||||
# Check DB version
|
||||
if "server_min_version" in self.data:
|
||||
server_con = server_utils.connect_server(self, self.server_id)
|
||||
if not server_con["info"] == "Server connected.":
|
||||
raise Exception("Could not connect to server to add "
|
||||
"a table.")
|
||||
if (server_con["data"]["type"] == 'pg' or
|
||||
server_con["data"]["version"] <=
|
||||
self.data["server_min_version"]):
|
||||
self.skipTest(self.data["skip_msg"])
|
||||
|
||||
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
||||
self.server_id, self.db_id)
|
||||
if not db_con['data']["connected"]:
|
||||
@ -57,15 +71,17 @@ class TypesAddTestCase(BaseTestGenerator):
|
||||
|
||||
def runTest(self):
|
||||
""" This function will add type under schema node. """
|
||||
if "name" in self.data:
|
||||
self.data["name"] = self.data["name"] + (str(uuid.uuid4())[1:8])
|
||||
|
||||
db_user = self.server["username"]
|
||||
self.type_name = "test_type_add_%s" % (str(uuid.uuid4())[1:8])
|
||||
self.data = types_utils.get_types_data(self.type_name,
|
||||
self.schema_name, db_user)
|
||||
self.data["typeowner"] = db_user
|
||||
self.data["schema"] = self.schema_name
|
||||
|
||||
if self.is_positive_test:
|
||||
response = self.create_types()
|
||||
else:
|
||||
if hasattr(self, "missing_parameter"):
|
||||
del self.data['name']
|
||||
response = self.create_types()
|
||||
|
||||
if hasattr(self, "internal_server_error"):
|
||||
|
@ -3,8 +3,68 @@
|
||||
{
|
||||
"name": "Create types: With valid data.",
|
||||
"url": "/browser/type/obj/",
|
||||
"server_min_version": "10000",
|
||||
"skip_msg": "Nested Table types are supported for PPAS & version > 9.6",
|
||||
"is_positive_test": true,
|
||||
"test_data": {},
|
||||
"test_data": {
|
||||
"name": "type_name_add",
|
||||
"is_sys_type": false,
|
||||
"typtype": "c",
|
||||
"typeowner": "db_user",
|
||||
"schema": "schema_name",
|
||||
"composite": [{"member_name": "one", "type": "bigint",
|
||||
"is_tlength": false, "is_precision": false},
|
||||
{"member_name": "two", "type": "\"char\"[]",
|
||||
"is_tlength": false, "is_precision": false}],
|
||||
"enum": [], "typacl": [], "seclabels": []
|
||||
},
|
||||
"mocking_required": false,
|
||||
"mock_data": {},
|
||||
"expected_data": {
|
||||
"status_code": 200
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Create Nested types: With valid data for Advanced Server.",
|
||||
"url": "/browser/type/obj/",
|
||||
"is_positive_test": true,
|
||||
"test_data": {
|
||||
"name": "type_name_add",
|
||||
"is_sys_type": false,
|
||||
"typeowner": "db_user",
|
||||
"schema": "schema_name",
|
||||
"typtype":"N",
|
||||
"type": "numeric",
|
||||
"tlength": 2,
|
||||
"precision": 1,
|
||||
"typacl":[],
|
||||
"seclabels":[],
|
||||
"server_min_version": 10000,
|
||||
"skip_msg": "Nested Table types are supported for PPAS & version > 9.6"
|
||||
},
|
||||
"mocking_required": false,
|
||||
"mock_data": {},
|
||||
"expected_data": {
|
||||
"status_code": 200
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Create Varray types: With valid data for Advanced Server.",
|
||||
"url": "/browser/type/obj/",
|
||||
"is_positive_test": true,
|
||||
"test_data": {
|
||||
"name": "type_name_add",
|
||||
"is_sys_type": false,
|
||||
"typeowner": "db_user",
|
||||
"schema": "schema_name",
|
||||
"typtype":"V",
|
||||
"type": "integer",
|
||||
"maxsize": 10,
|
||||
"typacl":[],
|
||||
"seclabels":[],
|
||||
"server_min_version": 10000,
|
||||
"skip_msg": "Varray types are supported for PPAS & version > 9.6"
|
||||
},
|
||||
"mocking_required": false,
|
||||
"mock_data": {},
|
||||
"expected_data": {
|
||||
@ -16,7 +76,17 @@
|
||||
"url": "/browser/type/obj/",
|
||||
"is_positive_test": false,
|
||||
"missing_parameter": true,
|
||||
"test_data": {},
|
||||
"test_data": {
|
||||
"is_sys_type": false,
|
||||
"typtype": "c",
|
||||
"typeowner": "db_user",
|
||||
"schema": "schema_name",
|
||||
"composite": [{"member_name": "one", "type": "bigint",
|
||||
"is_tlength": false, "is_precision": false},
|
||||
{"member_name": "two", "type": "\"char\"[]",
|
||||
"is_tlength": false, "is_precision": false}],
|
||||
"enum": [], "typacl": [], "seclabels": []
|
||||
},
|
||||
"mocking_required": false,
|
||||
"mock_data": {},
|
||||
"expected_data": {
|
||||
@ -28,7 +98,18 @@
|
||||
"url": "/browser/type/obj/",
|
||||
"is_positive_test": false,
|
||||
"internal_server_error": true,
|
||||
"test_data": {},
|
||||
"test_data": {
|
||||
"name": "type_name_add",
|
||||
"is_sys_type": false,
|
||||
"typtype": "c",
|
||||
"typeowner": "db_user",
|
||||
"schema": "schema_name",
|
||||
"composite": [{"member_name": "one", "type": "bigint",
|
||||
"is_tlength": false, "is_precision": false},
|
||||
{"member_name": "two", "type": "\"char\"[]",
|
||||
"is_tlength": false, "is_precision": false}],
|
||||
"enum": [], "typacl": [], "seclabels": []
|
||||
},
|
||||
"mocking_required": true,
|
||||
"mock_data": {
|
||||
"function_name": "pgadmin.utils.driver.psycopg2.connection.Connection.execute_dict",
|
||||
@ -43,7 +124,18 @@
|
||||
"url": "/browser/type/obj/",
|
||||
"is_positive_test": false,
|
||||
"error_in_db": true,
|
||||
"test_data": {},
|
||||
"test_data": {
|
||||
"name": "type_name_add",
|
||||
"is_sys_type": false,
|
||||
"typtype": "c",
|
||||
"typeowner": "db_user",
|
||||
"schema": "schema_name",
|
||||
"composite": [{"member_name": "one", "type": "bigint",
|
||||
"is_tlength": false, "is_precision": false},
|
||||
{"member_name": "two", "type": "\"char\"[]",
|
||||
"is_tlength": false, "is_precision": false}],
|
||||
"enum": [], "typacl": [], "seclabels": []
|
||||
},
|
||||
"mocking_required": true,
|
||||
"mock_data": {
|
||||
"function_name": "pgadmin.utils.driver.psycopg2.connection.Connection.execute_scalar",
|
||||
|
Loading…
Reference in New Issue
Block a user