Added support to create the Partitioned table should be created using COLLATE and opclass. Fixes #2546

pull/61/head
Pradip Parkale 2021-09-09 16:26:23 +05:30 committed by Akshay Joshi
parent 02ed2289e6
commit dbf78bf214
28 changed files with 1346 additions and 27 deletions

View File

@ -21,4 +21,5 @@ Housekeeping
Bug fixes Bug fixes
********* *********
| `Issue #2546 <https://redmine.postgresql.org/issues/2546>`_ - Added support to create the Partitioned table should be created using COLLATE and opclass.
| `Issue #6712 <https://redmine.postgresql.org/issues/6712>`_ - Fixed an issue where collapse and expand arrows mismatch in case of nested IF. | `Issue #6712 <https://redmine.postgresql.org/issues/6712>`_ - Fixed an issue where collapse and expand arrows mismatch in case of nested IF.

View File

@ -283,7 +283,8 @@ class TableView(BaseTableView, DataTypeReader, SchemaDiffTableCompare):
'update_sql': [{'get': 'update_sql'}], 'update_sql': [{'get': 'update_sql'}],
'delete_sql': [{'get': 'delete_sql'}], 'delete_sql': [{'get': 'delete_sql'}],
'count_rows': [{'get': 'count_rows'}], 'count_rows': [{'get': 'count_rows'}],
'compare': [{'get': 'compare'}, {'get': 'compare'}] 'compare': [{'get': 'compare'}, {'get': 'compare'}],
'get_op_class': [{'get': 'get_op_class'}, {'get': 'get_op_class'}],
}) })
@BaseTableView.check_precondition @BaseTableView.check_precondition
@ -597,6 +598,38 @@ class TableView(BaseTableView, DataTypeReader, SchemaDiffTableCompare):
gid, sid, did, scid, tid, res=res gid, sid, did, scid, tid, res=res
) )
@BaseTableView.check_precondition
def get_op_class(self, gid, sid, did, scid, tid=None):
"""
This function will return list of op_class method
for each access methods available via AJAX response
"""
res = dict()
try:
# for row in rset['rows']:
# # Fetching all the op_classes for each access method
SQL = render_template(
"/".join([self.table_template_path, 'get_op_class.sql'])
)
status, result = self.conn.execute_2darray(SQL)
if not status:
return internal_server_error(errormsg=res)
op_class_list = [{'label': '', 'value': ''}]
for r in result['rows']:
op_class_list.append({'label': r['opcname'],
'value': r['opcname']})
return make_json_response(
data=op_class_list,
status=200
)
except Exception as e:
return internal_server_error(errormsg=str(e))
@BaseTableView.check_precondition @BaseTableView.check_precondition
def types(self, gid, sid, did, scid, tid=None, clid=None): def types(self, gid, sid, did, scid, tid=None, clid=None):
""" """

View File

@ -4,18 +4,30 @@ import BaseUISchema from 'sources/SchemaView/base_schema.ui';
import { emptyValidator, isEmptyString } from '../../../../../../../../static/js/validators'; import { emptyValidator, isEmptyString } from '../../../../../../../../static/js/validators';
export class PartitionKeysSchema extends BaseUISchema { export class PartitionKeysSchema extends BaseUISchema {
constructor(columns=[]) { constructor(columns=[], getOperatorClass, getCollations) {
super({ super({
key_type: 'column', key_type: 'column',
}); });
this.columns = columns; this.columns = columns;
this.columnsReloadBasis = false; this.columnsReloadBasis = false;
this.getOperatorClass = getOperatorClass;
this.getCollations = getCollations;
this.op_class_types = [];
} }
changeColumnOptions(columns) { changeColumnOptions(columns) {
this.columns = columns; this.columns = columns;
} }
setOpClassTypes(options) {
if(!options || (_.isArray(options) && options.length == 0))
return this.op_class_types;
if(this.op_class_types.length == 0)
this.op_class_types = options;
}
get baseFields() { get baseFields() {
let obj = this; let obj = this;
return [{ return [{
@ -66,6 +78,30 @@ export class PartitionKeysSchema extends BaseUISchema {
} }
return false; return false;
}, },
},{
id: 'collationame', label: gettext('Collation'), cell: 'select',
type: 'select', group: gettext('partition'), deps:['key_type'],
options: obj._top.getCollations(), mode: ['create', 'properties', 'edit'],
editable: function(state) {
if(state.key_type == 'expression') {
return false;
}
return true;
},
disabled: ()=>{return !(obj.isNew()); },
},
{
id: 'op_class', label: gettext('Operator class'), cell: 'select',
type: 'select', group: gettext('partition'), deps:['key_type'],
editable: function(state) {
if(state.key_type == 'expression') {
return false;
}
return true;
},
disabled: ()=>{return !(obj.isNew()); },
options: obj._top.getOperatorClass(), mode: ['create', 'properties', 'edit'],
optionsLoaded: (options)=>{obj.setOpClassTypes(options);},
}]; }];
} }

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
// //234567890
// pgAdmin 4 - PostgreSQL Tools // pgAdmin 4 - PostgreSQL Tools
// //
// Copyright (C) 2013 - 2021, The pgAdmin Development Team // Copyright (C) 2013 - 2021, The pgAdmin Development Team

View File

@ -57,6 +57,8 @@ export function getNodeTableSchema(treeNodeInfo, itemNodeData, pgBrowser) {
(params)=>{ (params)=>{
return getNodeAjaxOptions('get_columns', tableNode, treeNodeInfo, itemNodeData, {urlParams: params, useCache:false}); return getNodeAjaxOptions('get_columns', tableNode, treeNodeInfo, itemNodeData, {urlParams: params, useCache:false});
}, },
()=>getNodeAjaxOptions('get_collations', pgBrowser.Nodes['collation'], treeNodeInfo, itemNodeData),
()=>getNodeAjaxOptions('get_op_class', pgBrowser.Nodes['table'], treeNodeInfo, itemNodeData),
{ {
relowner: pgBrowser.serverInfo[treeNodeInfo.server._id].user.name, relowner: pgBrowser.serverInfo[treeNodeInfo.server._id].user.name,
schema: treeNodeInfo.schema._label, schema: treeNodeInfo.schema._label,
@ -255,7 +257,7 @@ export class LikeSchema extends BaseUISchema {
} }
export default class TableSchema extends BaseUISchema { export default class TableSchema extends BaseUISchema {
constructor(fieldOptions={}, nodeInfo, schemas, getPrivilegeRoleSchema, getColumns, initValues) { constructor(fieldOptions={}, nodeInfo, schemas, getPrivilegeRoleSchema, getColumns, getCollations, getOperatorClass, initValues) {
super({ super({
name: undefined, name: undefined,
oid: undefined, oid: undefined,
@ -298,6 +300,8 @@ export default class TableSchema extends BaseUISchema {
this.getPrivilegeRoleSchema = getPrivilegeRoleSchema; this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
this.nodeInfo = nodeInfo; this.nodeInfo = nodeInfo;
this.getColumns = getColumns; this.getColumns = getColumns;
this.getCollations = getCollations;
this.getOperatorClass = getOperatorClass;
this.partitionKeysObj = new PartitionKeysSchema(); this.partitionKeysObj = new PartitionKeysSchema();
this.partitionsObj = new PartitionsSchema(this.nodeInfo); this.partitionsObj = new PartitionsSchema(this.nodeInfo);

View File

@ -0,0 +1,7 @@
SELECT (PG_CATALOG.CONCAT(PG_CATALOG.QUOTE_IDENT(nspc.nspname),'.',PG_CATALOG.QUOTE_IDENT(PGCOL.COLLNAME))) AS collationame
FROM PG_PARTITIONED_TABLE PARTT
LEFT OUTER JOIN PG_CATALOG.PG_COLLATION PGCOL
ON PGCOL.OID = 950
LEFT OUTER JOIN PG_CATALOG.PG_NAMESPACE NSPC
ON PGCOL.COLLNAMESPACE = NSPC.OID
WHERE PARTRELID = 162140

View File

@ -0,0 +1,3 @@
SELECT opcname, opcmethod
FROM pg_catalog.pg_opclass
ORDER BY 1;

View File

@ -0,0 +1,24 @@
-- Table: public.partition_table_with_collate_$%{}[]()&*^!@"'`\/#
-- DROP TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#";
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text COLLATE pg_catalog."default",
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to postgres;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
-- Partitions SQL
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');
ALTER TABLE IF EXISTS public.cust_arr_small
OWNER to postgres;

View File

@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text,
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to postgres;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');

View File

@ -1790,6 +1790,158 @@
"store_object_id": true, "store_object_id": true,
"expected_sql_file": "create_table_with_range_partition.sql", "expected_sql_file": "create_table_with_range_partition.sql",
"expected_msql_file": "create_table_with_range_partition_msql.sql" "expected_msql_file": "create_table_with_range_partition_msql.sql"
},
{
"type": "create",
"name": "Create Table with range partition with collate and opclass",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"msql_endpoint": "NODE-table.msql",
"data": {
"name": "partition_table_with_collate_$%{}[]()&*^!@\"'`\\/#",
"relowner": "postgres",
"relacl": [],
"description": "partition table",
"coll_inherits": "[]",
"hastoasttable": true,
"toast_autovacuum_enabled": "x",
"autovacuum_enabled": "x",
"primary_key": [],
"partitions": [
{
"is_attach": false,
"partition_name": "cust_arr_small",
"values_from": "'20'",
"values_to": "'25'",
"is_sub_partitioned": false,
"sub_partition_type": "range",
"sub_partition_keys": []
}
],
"partition_type": "range",
"is_partitioned": true,
"schema": "public",
"columns": [
{
"name": "id",
"cltype": "integer",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "status",
"cltype": "text",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "arr",
"cltype": "numeric",
"attacl": [],
"min_val_attlen": 1,
"min_val_attprecision": 0,
"max_val_attlen": 1000,
"max_val_attprecision": 1000,
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
}
],
"foreign_key": [],
"check_constraint": [],
"unique_constraint": [],
"exclude_constraint": [],
"partition_keys": [
{
"key_type": "column",
"pt_column": "status",
"collationame": "\"C\"",
"op_class": "text_pattern_ops"
}
],
"vacuum_table": [
{
"name": "autovacuum_analyze_scale_factor"
},
{
"name": "autovacuum_analyze_threshold"
},
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"vacuum_toast": [
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"seclabels": [],
"forcerlspolicy": false,
"like_default_value": false,
"like_constraints": false,
"like_indexes": false,
"like_storage": false,
"like_comments": false,
"autovacuum_custom": false
},
"store_object_id": true,
"expected_sql_file": "create_partition_table_with_collate.sql",
"expected_msql_file": "create_partition_table_with_collate_msql.sql"
} }
] ]
} }

View File

@ -0,0 +1,24 @@
-- Table: public.partition_table_with_collate_$%{}[]()&*^!@"'`\/#
-- DROP TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#";
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text COLLATE pg_catalog."default",
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to postgres;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
-- Partitions SQL
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');
ALTER TABLE IF EXISTS public.cust_arr_small
OWNER to postgres;

View File

@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text COLLATE pg_catalog."default",
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to postgres;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');

View File

@ -1940,6 +1940,158 @@
"store_object_id": true, "store_object_id": true,
"expected_sql_file": "create_table_with_hash_partition.sql", "expected_sql_file": "create_table_with_hash_partition.sql",
"expected_msql_file": "create_table_with_hash_partition_msql.sql" "expected_msql_file": "create_table_with_hash_partition_msql.sql"
},
{
"type": "create",
"name": "Create Table with range partition with collate and opclass",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"msql_endpoint": "NODE-table.msql",
"data": {
"name": "partition_table_with_collate_$%{}[]()&*^!@\"'`\\/#",
"relowner": "postgres",
"relacl": [],
"description": "partition table",
"coll_inherits": "[]",
"hastoasttable": true,
"toast_autovacuum_enabled": "x",
"autovacuum_enabled": "x",
"primary_key": [],
"partitions": [
{
"is_attach": false,
"partition_name": "cust_arr_small",
"values_from": "'20'",
"values_to": "'25'",
"is_sub_partitioned": false,
"sub_partition_type": "range",
"sub_partition_keys": []
}
],
"partition_type": "range",
"is_partitioned": true,
"schema": "public",
"columns": [
{
"name": "id",
"cltype": "integer",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "status",
"cltype": "text",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "arr",
"cltype": "numeric",
"attacl": [],
"min_val_attlen": 1,
"min_val_attprecision": 0,
"max_val_attlen": 1000,
"max_val_attprecision": 1000,
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
}
],
"foreign_key": [],
"check_constraint": [],
"unique_constraint": [],
"exclude_constraint": [],
"partition_keys": [
{
"key_type": "column",
"pt_column": "status",
"collationame": "\"C\"",
"op_class": "text_pattern_ops"
}
],
"vacuum_table": [
{
"name": "autovacuum_analyze_scale_factor"
},
{
"name": "autovacuum_analyze_threshold"
},
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"vacuum_toast": [
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"seclabels": [],
"forcerlspolicy": false,
"like_default_value": false,
"like_constraints": false,
"like_indexes": false,
"like_storage": false,
"like_comments": false,
"autovacuum_custom": false
},
"store_object_id": true,
"expected_sql_file": "create_partition_table_with_collate.sql",
"expected_msql_file": "create_partition_table_with_collate_msql.sql"
} }
] ]
} }

View File

@ -0,0 +1,24 @@
-- Table: public.partition_table_with_collate_$%{}[]()&*^!@"'`\/#
-- DROP TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#";
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text COLLATE pg_catalog."default",
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to postgres;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
-- Partitions SQL
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');
ALTER TABLE IF EXISTS public.cust_arr_small
OWNER to postgres;

View File

@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text,
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to postgres;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');

View File

@ -1940,6 +1940,158 @@
"store_object_id": true, "store_object_id": true,
"expected_sql_file": "create_table_with_hash_partition.sql", "expected_sql_file": "create_table_with_hash_partition.sql",
"expected_msql_file": "create_table_with_hash_partition_msql.sql" "expected_msql_file": "create_table_with_hash_partition_msql.sql"
},
{
"type": "create",
"name": "Create Table with range partition with collate and opclass",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"msql_endpoint": "NODE-table.msql",
"data": {
"name": "partition_table_with_collate_$%{}[]()&*^!@\"'`\\/#",
"relowner": "enterprisedb",
"relacl": [],
"description": "partition table",
"coll_inherits": "[]",
"hastoasttable": true,
"toast_autovacuum_enabled": "x",
"autovacuum_enabled": "x",
"primary_key": [],
"partitions": [
{
"is_attach": false,
"partition_name": "cust_arr_small",
"values_from": "'20'",
"values_to": "'25'",
"is_sub_partitioned": false,
"sub_partition_type": "range",
"sub_partition_keys": []
}
],
"partition_type": "range",
"is_partitioned": true,
"schema": "public",
"columns": [
{
"name": "id",
"cltype": "integer",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "status",
"cltype": "text",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "arr",
"cltype": "numeric",
"attacl": [],
"min_val_attlen": 1,
"min_val_attprecision": 0,
"max_val_attlen": 1000,
"max_val_attprecision": 1000,
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
}
],
"foreign_key": [],
"check_constraint": [],
"unique_constraint": [],
"exclude_constraint": [],
"partition_keys": [
{
"key_type": "column",
"pt_column": "status",
"collationame": "\"C\"",
"op_class": "text_pattern_ops"
}
],
"vacuum_table": [
{
"name": "autovacuum_analyze_scale_factor"
},
{
"name": "autovacuum_analyze_threshold"
},
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"vacuum_toast": [
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"seclabels": [],
"forcerlspolicy": false,
"like_default_value": false,
"like_constraints": false,
"like_indexes": false,
"like_storage": false,
"like_comments": false,
"autovacuum_custom": false
},
"store_object_id": true,
"expected_sql_file": "create_partition_table_with_collate.sql",
"expected_msql_file": "create_partition_table_with_collate_msql.sql"
} }
] ]
} }

View File

@ -0,0 +1,24 @@
-- Table: public.partition_table_with_collate_$%{}[]()&*^!@"'`\/#
-- DROP TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#";
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text COLLATE pg_catalog."default",
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to enterprisedb;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
-- Partitions SQL
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');
ALTER TABLE IF EXISTS public.cust_arr_small
OWNER to enterprisedb;

View File

@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text,
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to enterprisedb;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');

View File

@ -1790,6 +1790,158 @@
"store_object_id": true, "store_object_id": true,
"expected_sql_file": "create_table_with_range_partition.sql", "expected_sql_file": "create_table_with_range_partition.sql",
"expected_msql_file": "create_table_with_range_partition_msql.sql" "expected_msql_file": "create_table_with_range_partition_msql.sql"
},
{
"type": "create",
"name": "Create Table with range partition with collate and opclass",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"msql_endpoint": "NODE-table.msql",
"data": {
"name": "partition_table_with_collate_$%{}[]()&*^!@\"'`\\/#",
"relowner": "enterprisedb",
"relacl": [],
"description": "partition table",
"coll_inherits": "[]",
"hastoasttable": true,
"toast_autovacuum_enabled": "x",
"autovacuum_enabled": "x",
"primary_key": [],
"partitions": [
{
"is_attach": false,
"partition_name": "cust_arr_small",
"values_from": "'20'",
"values_to": "'25'",
"is_sub_partitioned": false,
"sub_partition_type": "range",
"sub_partition_keys": []
}
],
"partition_type": "range",
"is_partitioned": true,
"schema": "public",
"columns": [
{
"name": "id",
"cltype": "integer",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "status",
"cltype": "text",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "arr",
"cltype": "numeric",
"attacl": [],
"min_val_attlen": 1,
"min_val_attprecision": 0,
"max_val_attlen": 1000,
"max_val_attprecision": 1000,
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
}
],
"foreign_key": [],
"check_constraint": [],
"unique_constraint": [],
"exclude_constraint": [],
"partition_keys": [
{
"key_type": "column",
"pt_column": "status",
"collationame": "\"C\"",
"op_class": "text_pattern_ops"
}
],
"vacuum_table": [
{
"name": "autovacuum_analyze_scale_factor"
},
{
"name": "autovacuum_analyze_threshold"
},
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"vacuum_toast": [
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"seclabels": [],
"forcerlspolicy": false,
"like_default_value": false,
"like_constraints": false,
"like_indexes": false,
"like_storage": false,
"like_comments": false,
"autovacuum_custom": false
},
"store_object_id": true,
"expected_sql_file": "create_partition_table_with_collate.sql",
"expected_msql_file": "create_partition_table_with_collate_msql.sql"
} }
] ]
} }

View File

@ -0,0 +1,24 @@
-- Table: public.partition_table_with_collate_$%{}[]()&*^!@"'`\/#
-- DROP TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#";
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text COLLATE pg_catalog."default",
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to enterprisedb;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
-- Partitions SQL
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');
ALTER TABLE IF EXISTS public.cust_arr_small
OWNER to enterprisedb;

View File

@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text,
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to enterprisedb;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');

View File

@ -1940,6 +1940,158 @@
"store_object_id": true, "store_object_id": true,
"expected_sql_file": "create_table_with_hash_partition.sql", "expected_sql_file": "create_table_with_hash_partition.sql",
"expected_msql_file": "create_table_with_hash_partition_msql.sql" "expected_msql_file": "create_table_with_hash_partition_msql.sql"
},
{
"type": "create",
"name": "Create Table with range partition with collate and opclass",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"msql_endpoint": "NODE-table.msql",
"data": {
"name": "partition_table_with_collate_$%{}[]()&*^!@\"'`\\/#",
"relowner": "enterprisedb",
"relacl": [],
"description": "partition table",
"coll_inherits": "[]",
"hastoasttable": true,
"toast_autovacuum_enabled": "x",
"autovacuum_enabled": "x",
"primary_key": [],
"partitions": [
{
"is_attach": false,
"partition_name": "cust_arr_small",
"values_from": "'20'",
"values_to": "'25'",
"is_sub_partitioned": false,
"sub_partition_type": "range",
"sub_partition_keys": []
}
],
"partition_type": "range",
"is_partitioned": true,
"schema": "public",
"columns": [
{
"name": "id",
"cltype": "integer",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "status",
"cltype": "text",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "arr",
"cltype": "numeric",
"attacl": [],
"min_val_attlen": 1,
"min_val_attprecision": 0,
"max_val_attlen": 1000,
"max_val_attprecision": 1000,
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
}
],
"foreign_key": [],
"check_constraint": [],
"unique_constraint": [],
"exclude_constraint": [],
"partition_keys": [
{
"key_type": "column",
"pt_column": "status",
"collationame": "\"C\"",
"op_class": "text_pattern_ops"
}
],
"vacuum_table": [
{
"name": "autovacuum_analyze_scale_factor"
},
{
"name": "autovacuum_analyze_threshold"
},
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"vacuum_toast": [
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"seclabels": [],
"forcerlspolicy": false,
"like_default_value": false,
"like_constraints": false,
"like_indexes": false,
"like_storage": false,
"like_comments": false,
"autovacuum_custom": false
},
"store_object_id": true,
"expected_sql_file": "create_partition_table_with_collate.sql",
"expected_msql_file": "create_partition_table_with_collate_msql.sql"
} }
] ]
} }

View File

@ -0,0 +1,24 @@
-- Table: public.partition_table_with_collate_$%{}[]()&*^!@"'`\/#
-- DROP TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#";
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text COLLATE pg_catalog."default",
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to enterprisedb;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
-- Partitions SQL
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');
ALTER TABLE IF EXISTS public.cust_arr_small
OWNER to enterprisedb;

View File

@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
(
id integer,
status text,
arr numeric
) PARTITION BY RANGE (status COLLATE "C" text_pattern_ops);
ALTER TABLE IF EXISTS public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
OWNER to enterprisedb;
COMMENT ON TABLE public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
IS 'partition table';
CREATE TABLE IF NOT EXISTS public.cust_arr_small PARTITION OF public."partition_table_with_collate_$%{}[]()&*^!@""'`\/#"
FOR VALUES FROM ('20') TO ('25');

View File

@ -1940,6 +1940,158 @@
"store_object_id": true, "store_object_id": true,
"expected_sql_file": "create_table_with_hash_partition.sql", "expected_sql_file": "create_table_with_hash_partition.sql",
"expected_msql_file": "create_table_with_hash_partition_msql.sql" "expected_msql_file": "create_table_with_hash_partition_msql.sql"
},
{
"type": "create",
"name": "Create Table with range partition with collate and opclass",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"msql_endpoint": "NODE-table.msql",
"data": {
"name": "partition_table_with_collate_$%{}[]()&*^!@\"'`\\/#",
"relowner": "enterprisedb",
"relacl": [],
"description": "partition table",
"coll_inherits": "[]",
"hastoasttable": true,
"toast_autovacuum_enabled": "x",
"autovacuum_enabled": "x",
"primary_key": [],
"partitions": [
{
"is_attach": false,
"partition_name": "cust_arr_small",
"values_from": "'20'",
"values_to": "'25'",
"is_sub_partitioned": false,
"sub_partition_type": "range",
"sub_partition_keys": []
}
],
"partition_type": "range",
"is_partitioned": true,
"schema": "public",
"columns": [
{
"name": "id",
"cltype": "integer",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "status",
"cltype": "text",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
},
{
"name": "arr",
"cltype": "numeric",
"attacl": [],
"min_val_attlen": 1,
"min_val_attprecision": 0,
"max_val_attlen": 1000,
"max_val_attprecision": 1000,
"is_primary_key": false,
"attnotnull": false,
"attlen": null,
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": []
}
],
"foreign_key": [],
"check_constraint": [],
"unique_constraint": [],
"exclude_constraint": [],
"partition_keys": [
{
"key_type": "column",
"pt_column": "status",
"collationame": "\"C\"",
"op_class": "text_pattern_ops"
}
],
"vacuum_table": [
{
"name": "autovacuum_analyze_scale_factor"
},
{
"name": "autovacuum_analyze_threshold"
},
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"vacuum_toast": [
{
"name": "autovacuum_freeze_max_age"
},
{
"name": "autovacuum_vacuum_cost_delay"
},
{
"name": "autovacuum_vacuum_cost_limit"
},
{
"name": "autovacuum_vacuum_scale_factor"
},
{
"name": "autovacuum_vacuum_threshold"
},
{
"name": "autovacuum_freeze_min_age"
},
{
"name": "autovacuum_freeze_table_age"
}
],
"seclabels": [],
"forcerlspolicy": false,
"like_default_value": false,
"like_constraints": false,
"like_indexes": false,
"like_storage": false,
"like_comments": false,
"autovacuum_custom": false
},
"store_object_id": true,
"expected_sql_file": "create_partition_table_with_collate.sql",
"expected_msql_file": "create_partition_table_with_collate_msql.sql"
} }
] ]
} }

View File

@ -378,6 +378,57 @@
"test_result_data": {} "test_result_data": {}
} }
}, },
{
"name": "Create: Add Range partitioned table with collate",
"is_positive_test": true,
"inventory_data": {
"server_min_version": 100000,
"skip_msg": "Partitioned table are not supported by PPAS/PG 10.0 and below."
},
"test_data": {
"is_partitioned": true,
"description": "partition table",
"partition_type": "range",
"multilevel_partition": true,
"partitions": [
{
"values_from": "'2010-01-01'",
"values_to": "'2010-12-31'",
"is_attach": false,
"partition_name": "emp_2010_multi_level",
"is_sub_partitioned": true,
"sub_partition_type": "range",
"sub_partition_keys": [
{
"key_type": "column",
"pt_column": "empno"
}
]
},
{
"values_from": "'20'",
"values_to": "'25'",
"is_attach": false,
"partition_name": "emp_2011_multi_level"
}
],
"partition_keys": [
{
"key_type": "column",
"pt_column": "part_col",
"collationame": "pg_catalog.\"C\"",
"op_class": "text_pattern_ops"
}
]
},
"mocking_required": false,
"mock_data": {},
"expected_data": {
"status_code": 200,
"error_msg": null,
"test_result_data": {}
}
},
{ {
"name": "Create: Add Table with name more than 64 chars.", "name": "Create: Add Table with name more than 64 chars.",
"is_positive_test": true, "is_positive_test": true,
@ -1329,7 +1380,7 @@
"is_positive_test": true, "is_positive_test": true,
"inventory_data": {}, "inventory_data": {},
"test_data": { "test_data": {
"toast_autovacuum":false "toast_autovacuum": false
}, },
"mocking_required": false, "mocking_required": false,
"mock_data": {}, "mock_data": {},
@ -1348,25 +1399,40 @@
}, },
"test_data": { "test_data": {
"columns": { "columns": {
"changed": [{ "changed": [
"attnum": 1, {
"attacl": { "attnum": 1,
"added": [{ "attacl": {
"privileges": [ "added": [
{"privilege_type": "a", "privilege": true, {
"with_grant": true}, "privileges": [
{"privilege_type": "r", "privilege": true, {
"with_grant": true}, "privilege_type": "a",
{"privilege_type": "w", "privilege": true, "privilege": true,
"with_grant": true}, "with_grant": true
{"privilege_type": "x", "privilege": true, },
"with_grant": true {
} "privilege_type": "r",
] "privilege": true,
}] "with_grant": true
} },
}] {
"privilege_type": "w",
"privilege": true,
"with_grant": true
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": true
}
]
}
]
}
} }
]
}
}, },
"mocking_required": false, "mocking_required": false,
"mock_data": {}, "mock_data": {},
@ -1817,7 +1883,7 @@
"inventory_data": {}, "inventory_data": {},
"url_encoded_data": true, "url_encoded_data": true,
"test_data": { "test_data": {
"col_type":"integer" "col_type": "integer"
}, },
"mocking_required": false, "mocking_required": false,
"mock_data": {}, "mock_data": {},
@ -1835,7 +1901,7 @@
"inventory_data": {}, "inventory_data": {},
"url_encoded_data": true, "url_encoded_data": true,
"test_data": { "test_data": {
"indextype":"btree" "indextype": "btree"
}, },
"mocking_required": false, "mocking_required": false,
"mock_data": {}, "mock_data": {},

View File

@ -395,7 +395,16 @@ def get_table_common_data():
"is_primary_key": False, "is_primary_key": False,
"attoptions": [], "attoptions": [],
"seclabels": [] "seclabels": []
}], },
{
"name": "part_col",
"cltype": "text",
"attacl": [],
"is_primary_key": False,
"attoptions": [],
"seclabels": []
}
],
"exclude_constraint": [], "exclude_constraint": [],
"fillfactor": "", "fillfactor": "",
"hastoasttable": True, "hastoasttable": True,

View File

@ -1117,7 +1117,15 @@ class BaseTableView(PGChildNodeView, BasePartitionTable, VacuumSettings):
for row in data[part_keys]: for row in data[part_keys]:
if row['key_type'] == 'column': if row['key_type'] == 'column':
partition_scheme += self.qtIdent( partition_scheme += self.qtIdent(
self.conn, row['pt_column']) + ', ' self.conn, row['pt_column'])
if 'collationame' in row:
partition_scheme += ' COLLATE %s' % row['collationame']
if 'op_class' in row:
partition_scheme += ' %s' % row['op_class']
partition_scheme += ', '
elif row['key_type'] == 'expression': elif row['key_type'] == 'expression':
partition_scheme += row['expression'] + ', ' partition_scheme += row['expression'] + ', '