mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2026-10-26 06:30:06 -05:00
Added support for the creation of Nested Table and Varying Array Type for Advanced Server. Fixes #6407
This commit is contained in:
1 parent
c32ff3a7ee
commit
b0df4d3604
40 files changed
+932
-76
No files matched your search
@@ -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]),
|
||||
|
||||
+174
-1
@@ -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'),
|
||||
|
||||
File renamed without changes.
+3
-3
@@ -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,
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+27
@@ -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
|
||||
+58
@@ -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 %}
|
||||
+94
@@ -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 %}
|
||||
+1
@@ -0,0 +1 @@
|
||||
DROP TYPE {{ conn|qtIdent(data.schema, data.name) }}{% if cascade%} CASCADE{% endif %};
|
||||
+7
@@ -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;
|
||||
+42
@@ -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 %}
|
||||
+11
@@ -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;
|
||||
+15
@@ -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 %}
|
||||
+56
@@ -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 %}
|
||||
+11
@@ -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
|
||||
+13
@@ -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;
|
||||
+24
@@ -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;
|
||||
+161
@@ -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 %}
|
||||
-53
@@ -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
|
||||
"""
|
||||
+9
@@ -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;
|
||||
+9
@@ -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;
|
||||
+39
-1
@@ -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",
|
||||
|
||||
+20
-4
@@ -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"):
|
||||
|
||||
+96
-4
@@ -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",
|
||||
|
||||
Reference in new issue
Block a user