Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified docs/en_US/images/type_range.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/en_US/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ notes for it.
:maxdepth: 1


release_notes_9_9
release_notes_9_8
release_notes_9_7
release_notes_9_6
Expand Down
33 changes: 33 additions & 0 deletions docs/en_US/release_notes_9_9.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
***********
Version 9.9
***********

Release date: 2025-10-16

This release contains a number of bug fixes and new features since the release of pgAdmin 4 v9.8.

Supported Database Servers
**************************
**PostgreSQL**: 13, 14, 15, 16 and 17

**EDB Advanced Server**: 13, 14, 15, 16 and 17

Bundled PostgreSQL Utilities
****************************
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 17.5


New features
************

| `Issue #6394 <https://github.com/pgadmin-org/pgadmin4/issues/6394>`_ - Added "MULTIRANGE_TYPE_NAME" option while creating a Range Type.
| `Issue #6395 <https://github.com/pgadmin-org/pgadmin4/issues/6395>`_ - Added "SUBSCRIPT" option while creating a External Type.


Housekeeping
************


Bug fixes
*********

13 changes: 8 additions & 5 deletions docs/en_US/type_dialog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,17 @@ On the *Optional-1* tab:
to select a type_modifier_output_function. It is allowed to omit the
type_modifier_output_function, in which case the default display format is the
stored typmod integer value enclosed in parentheses.
* Use the drop-down listbox next to the optional *Analyze function* field to
select a function for performing type-specific statistics collection for
columns of the data type.
* Use the drop-down listbox next to the optional *Subscript function* field to
select a function for allows the data type to be subscripted in SQL commands.
* Use the optional *Internal length* to specify a value for internal
representation.
* Move the *Variable?* switch to specify the internal representation is of
variable length (VARIABLE). The default is a fixed length positive integer.
* Specify a default value in the optional *Default* field in cases where a
column of the data type defaults to something other than the null value.
Specify the default with the DEFAULT key word. (A default can be overridden
by an explicit DEFAULT clause attached to a particular column.)
* Use the drop-down listbox next to the optional *Analyze function* field to
select a function for performing type-specific statistics collection for
columns of the data type.
* Use the drop-down listbox next to the optional *Category type* field to help
control which implicit cast will be applied in ambiguous situations.
* Move the *Preferred?* switch to *Yes* to specify the selected category type is
Expand Down Expand Up @@ -162,6 +162,9 @@ disabled.
values to a canonical form.
* Use the drop-down listbox next to *Sub-type diff function* to select a
user-defined subtype_diff function.
* Specify the optional *Multirange type name* parameter to specifies the
name of the corresponding multirange type. If not specified, this name is
chosen automatically.

If you select *Shell* in the *Type* field, the *Definition* tab displays the
*Shell* panel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,8 @@ def additional_properties(self, copy_dict, tid):
enum_list = []
for row in rset['rows']:
properties_list.append(row['enumlabel'])
enum_list.append({'label': row['enumlabel']})
enum_list.append({'label': row['enumlabel'],
'old_label': row['enumlabel']})

# Adding both results in ouput
res['enum_list'] = ', '.join(properties_list)
Expand Down Expand Up @@ -1226,6 +1227,10 @@ def msql(self, gid, sid, did, scid, tid=None):
for key, val in req.items():
if key in ['composite', 'enum', 'seclabels', 'typacl']:
data[key] = json.loads(val)
elif key in ['typreceive', 'typsend', 'typmodin', 'typmodout',
'typanalyze', 'typsubscript','typstorage'] and \
val == 'null':
data[key] = json.loads(val)
else:
data[key] = val

Expand Down Expand Up @@ -1339,6 +1344,8 @@ def get_sql(self, gid, sid, data, scid, tid=None, is_sql=False):
if tid is None:
return self._get_new_sql(data, is_sql)

data = self._convert_for_sql(data)

for key in ['added', 'changed', 'deleted']:
if key in data.get('typacl', []):
data['typacl'][key] = parse_priv_to_db(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ function isVisible(state, type) {
}

class EnumerationSchema extends BaseUISchema {

constructor() {
super({
oid: undefined,
Expand All @@ -201,18 +200,14 @@ class EnumerationSchema extends BaseUISchema {
}

get idAttribute() {
return 'oid';
return 'old_label';
}

get baseFields() {
let obj = this;
return [
{
id: 'label', label: gettext('Label'),
type: 'text', cell: 'text', minWidth: 620,
editable: (state) => {
return _.isUndefined(obj.isNew) ? true : obj.isNew(state);
}
}
];
}
Expand Down Expand Up @@ -395,6 +390,15 @@ class RangeSchema extends BaseUISchema {
}
};
},
}, {
id: 'rngmultirangetype', label: gettext('Multirange type name'),
cell: 'string', group: gettext('Range Type'),
type: 'text', mode: ['properties', 'create', 'edit'],
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
min_version: 140000,
}
];
}
Expand Down Expand Up @@ -562,9 +566,6 @@ class ExternalSchema extends BaseUISchema {
group: gettext('Optional-1'),
mode: ['properties', 'create', 'edit'],
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
controlProps: { allowClear: true, placeholder: '', width: '100%' },
},{
id: 'typsend', label: gettext('Send function'),
Expand All @@ -586,9 +587,6 @@ class ExternalSchema extends BaseUISchema {
},
mode: ['properties', 'create', 'edit'],
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
controlProps: { allowClear: true, placeholder: '', width: '100%' },
},{
id: 'typmodin', label: gettext('Typmod in function'),
Expand Down Expand Up @@ -623,9 +621,6 @@ class ExternalSchema extends BaseUISchema {
},
mode: ['properties', 'create', 'edit'], group: gettext('Optional-1'),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
controlProps: { allowClear: true, placeholder: '', width: '100%' },
},{
id: 'typmodout', label: gettext('Typmod out function'),
Expand Down Expand Up @@ -661,9 +656,24 @@ class ExternalSchema extends BaseUISchema {
},
mode: ['properties', 'create', 'edit'],
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},{
id: 'typanalyze', label: gettext('Analyze function'),
group: gettext('Optional-1'),
type: (state) => {
return obj.getFunctionType(state);
},
mode: ['properties', 'create','edit'],
disabled: () => obj.inCatalog(),
controlProps: { allowClear: true, placeholder: '', width: '100%' },
},{
id: 'typsubscript', label: gettext('Subscript function'),
group: gettext('Optional-1'), min_version: 140000,
type: (state) => {
return obj.getFunctionType(state);
},
mode: ['properties', 'create','edit'],
disabled: () => obj.inCatalog(),
controlProps: { allowClear: true, placeholder: '', width: '100%' },
},{
id: 'typlen', label: gettext('Internal length'),
cell: 'integer', group: gettext('Optional-1'),
Expand All @@ -672,14 +682,6 @@ class ExternalSchema extends BaseUISchema {
readonly: function (state) {
return !obj.isNew(state);
},
},{
id: 'variable', label: gettext('Variable?'), cell: 'switch',
group: gettext('Optional-1'), type: 'switch',
mode: ['create','edit'],
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
},{
id: 'typdefault', label: gettext('Default?'),
cell: 'string', group: gettext('Optional-1'),
Expand All @@ -688,18 +690,6 @@ class ExternalSchema extends BaseUISchema {
readonly: function (state) {
return !obj.isNew(state);
},
},{
id: 'typanalyze', label: gettext('Analyze function'),
group: gettext('Optional-1'),
type: (state) => {
return obj.getFunctionType(state);
},
mode: ['properties', 'create','edit'],
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
controlProps: { allowClear: true, placeholder: '', width: '100%' },
},{
id: 'typcategory', label: gettext('Category type'),
cell: 'string',
Expand Down Expand Up @@ -792,9 +782,6 @@ class ExternalSchema extends BaseUISchema {
type: 'select', mode: ['properties', 'create', 'edit'],
group: gettext('Optional-2'), cell: 'string',
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
controlProps: { allowClear: true, placeholder: '', width: '100%' },
options: obj.fieldOptions.typStorageOptions,
},{
Expand Down Expand Up @@ -1258,29 +1245,40 @@ export default class TypeSchema extends BaseUISchema {
},
{
id: 'typtype', label: gettext('Type'),
mode: ['create','edit'], group: gettext('Definition'),
type: 'select',
mode: ['create','edit', 'properties'], group: gettext('Definition'),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
controlProps: { allowClear: false },
options: function() {
type: (state)=>{
let typetype = [
{label: gettext('Composite'), value: 'c'},
{label: gettext('Enumeration'), value: 'e'},
{label: gettext('External'), value: 'b'},
{label: gettext('Range'), value: 'r'},
{label: gettext('Shell'), value: 'p'},
];

if (!obj.isNew(state)) {
typetype.push(
{label: gettext('Multirange'), value: 'm'}
);
}

if (obj.fieldOptions.server_info.server_type === 'ppas' &&
obj.fieldOptions.server_info.version >= 90500){
typetype.push(
{label: gettext('Nested Table'), value: 'N'},
{label: gettext('Varying Array'), value: 'V'}
);
}
return typetype;

return {
type: 'select',
options: typetype,
optionsReloadBasis: state.typtype,
};
},
},
{
Expand All @@ -1305,6 +1303,7 @@ export default class TypeSchema extends BaseUISchema {
schema: new EnumerationSchema(),
type: 'collection',
group: gettext('Definition'), mode: ['edit', 'create'],
uniqueCol: ['label'],
canAddRow: function(state) {
return !obj.isInvalidColumnAdded(state);
},
Expand Down Expand Up @@ -1389,6 +1388,12 @@ export default class TypeSchema extends BaseUISchema {
disabled: () => obj.inCatalog(),
visible: (state) => isVisible(state, 'r'),
},
{
id: 'rngmultirangetype', label: gettext('Multirange type name'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
disabled: () => obj.inCatalog(),
visible: (state) => isVisible(state, 'r'),
},
{
id: 'typinput', label: gettext('Input function'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{# The SQL given below will fetch composite type#}
{% if typtype == 'c' %}
SELECT attnum, attname, pg_catalog.format_type(t.oid,NULL) AS typname, attndims, atttypmod, nsp.nspname,
(SELECT COUNT(1) from pg_catalog.pg_type t2 WHERE t2.typname=t.typname) > 1 AS isdup,
collname, nspc.nspname as collnspname, att.attrelid,
pg_catalog.format_type(t.oid, att.atttypmod) AS fulltype,
CASE WHEN t.typelem > 0 THEN t.typelem ELSE t.oid END as elemoid
FROM pg_catalog.pg_attribute att
JOIN pg_catalog.pg_type t ON t.oid=atttypid
JOIN pg_catalog.pg_namespace nsp ON t.typnamespace=nsp.oid
LEFT OUTER JOIN pg_catalog.pg_type b ON t.typelem=b.oid
LEFT OUTER JOIN pg_catalog.pg_collation c ON att.attcollation=c.oid
LEFT OUTER JOIN pg_catalog.pg_namespace nspc ON c.collnamespace=nspc.oid
WHERE att.attrelid = {{typrelid}}::oid
ORDER by attnum;
{% endif %}

{# The SQL given below will fetch enum type#}
{% if typtype == 'e' %}
SELECT enumlabel
FROM pg_catalog.pg_enum
WHERE enumtypid={{tid}}::oid
ORDER by enumsortorder
{% endif %}

{# The SQL given below will fetch range type#}
{% if typtype == 'r' %}
SELECT rngsubtype, st.typname,
rngcollation, mt.typname as rngmultirangetype,
CASE WHEN n.nspname IS NOT NULL THEN pg_catalog.concat(pg_catalog.quote_ident(n.nspname), '.', pg_catalog.quote_ident(col.collname)) ELSE col.collname END AS collname,
rngsubopc, opc.opcname,
rngcanonical, rngsubdiff as rngsubdiff_proc,
CASE WHEN length(ns.nspname::text) > 0 AND length(pgpr.proname::text) > 0 THEN
pg_catalog.concat(quote_ident(ns.nspname), '.', pg_catalog.quote_ident(pgpr.proname))
ELSE '' END AS rngsubdiff
FROM pg_catalog.pg_range
LEFT JOIN pg_catalog.pg_type st ON st.oid=rngsubtype
LEFT JOIN pg_catalog.pg_type mt ON mt.oid=rngmultitypid
LEFT JOIN pg_catalog.pg_collation col ON col.oid=rngcollation
LEFT JOIN pg_catalog.pg_namespace n ON col.collnamespace=n.oid
LEFT JOIN pg_catalog.pg_opclass opc ON opc.oid=rngsubopc
LEFT JOIN pg_catalog.pg_proc pgpr ON pgpr.oid = rngsubdiff
LEFT JOIN pg_catalog.pg_namespace ns ON ns.oid=pgpr.pronamespace
WHERE rngtypid={{tid}}::oid;
{% endif %}
Loading
Loading