Added all supported index storage parameters while creating an index. #6374

This commit is contained in:
Pravesh Sharma 2023-07-11 18:12:53 +05:30 committed by GitHub
parent ac5be70c60
commit ab0b1dd40c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 742 additions and 33 deletions

View File

@ -51,11 +51,22 @@ Use the fields in the *Definition* tab to define the index:
* Use the *Fill Factor* field to specify a fill factor for the index. The fill
factor specifies how full the selected method will try to fill each index
page.
* Move the *Unique?* switch to the *Yes* position to check for duplicate values
in the table when the index is created and when data is added. The default is
*No*.
* Move the *NULLs not distinct?* switch to the *Yes* position to treat null values as not distinct. The default is
*No*. This option is available only on PostgreSQL 15 and above.
* Use the *Gin pending list limit* field to specify the maximum size of a GIN index's pending list, which is used
when fastupdate is enabled. This value is specified in kilobytes.
* Use the *Pages per range* field to specify the number of table blocks that make up one block range
for each entry of a BRIN index.
* Select *Buffering* to specify whether the buffering build technique is used to build the index. The default is
*Auto*
* Move the switch next to *Deduplicate items?* towards the *right position* to control usage of the B-tree
deduplication technique. The default is *Yes*. This option is available only on PostgreSQL 13 and above.
* Move the switch next to *Fast update?* towards the *right position* to control usage of the fast update technique.
The default is *Yes*.
* Move the switch next to *Autosummarize* towards the *right position* to define whether a summarization run is
queued for the previous page range whenever an insertion is detected on the next one. The default is *No*
* Move the switch next to *Unique?* towards the *right position* to check for duplicate values
in the table when the index is created and when data is added. The default is *No*.
* Move the switch next to *NULLs not distinct?* towards the *right position* to treat null values as not distinct.
The default is*No*. This option is available only on PostgreSQL 15 and above.
* Move the *Clustered?* switch to the *Yes* position to instruct the server to
cluster the table.
* Move the *Concurrent build?* switch to the *Yes* position to build the index

View File

@ -604,6 +604,14 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
# Adding parent into data dict, will be using it while creating sql
data['schema'] = self.schema
data['table'] = self.table
data["storage_parameters"] = {}
storage_params = index_utils.get_storage_params(data['amname'])
for param in storage_params:
if param in data and data[param] != '':
data["storage_parameters"].update({param: data[param]})
if len(data['table']) == 0:
return gone(gettext(self.not_found_error_msg('Table')))
@ -819,6 +827,15 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
data['schema'] = self.schema
data['table'] = self.table
if data.get('amname', None):
data["storage_parameters"] = {}
storage_params = index_utils.get_storage_params(data['amname'])
for param in storage_params:
if param in data and data[param] != '':
data["storage_parameters"].update({param: data[param]})
try:
sql, name = index_utils.get_sql(
self.conn, data=data, did=did, tid=tid, idx=idx,

View File

@ -136,7 +136,8 @@ define('pgadmin.node.index', [
node_info: treeNodeInfo
},
{
amname: 'btree'
amname: 'btree',
deduplicate_items: treeNodeInfo.server.version >= 130000 ? true : undefined,
}
);
}

View File

@ -194,6 +194,109 @@ export class ColumnSchema extends BaseUISchema {
}
}
export class WithSchema extends BaseUISchema {
constructor(node_info) {
super({});
this.node_info = node_info;
}
get baseFields() {
let withSchemaObj = this;
return [
{
id: 'fillfactor', label: gettext('Fill factor'), deps: ['amname'], cell: 'string',
type: 'int', disabled: (state) => {
return !_.includes(['btree', 'hash', 'gist', 'spgist'], state.amname) || inSchema(withSchemaObj.node_info);
},
mode: ['create', 'edit', 'properties'],
min: 10, max:100, group: gettext('Definition'),
depChange: state => {
if (!_.includes(['btree', 'hash', 'gist', 'spgist'], state.amname)) {
return {fillfactor: ''};
}
}
},{
id: 'gin_pending_list_limit', label: gettext('Gin pending list limit'), cell: 'string',
type: 'int', deps: ['amname'], disabled: state => state.amname !== 'gin' || inSchema(withSchemaObj.node_info),
mode: ['create', 'edit', 'properties'],
group: gettext('Definition'), min: 64, max: 2147483647,
depChange: state => {
if (state.amname !== 'gin') {
return {gin_pending_list_limit: ''};
}
}, helpMessage: gettext('This value is specified in kilobytes.')
},{
id: 'pages_per_range', label: gettext('Pages per range'), cell: 'string',
type: 'int', deps: ['amname'], disabled: state => state.amname !== 'brin' || inSchema(withSchemaObj.node_info),
mode: ['create', 'edit', 'properties'],
group: gettext('Definition'), depChange: state => {
if (state.amname !== 'brin') {
return {pages_per_range: ''};
}
}, helpMessage: gettext('Number of table blocks that make up one block range for each entry of a BRIN index.')
},{
id: 'buffering', label: gettext('Buffering'), cell: 'string', group: gettext('Definition'),
type: 'select', deps: ['amname'], mode: ['create', 'edit', 'properties'], options: [
{
label: gettext('Auto'),
value: 'auto',
},
{
label: gettext('On'),
value: 'on',
},
{
label: gettext('Off'),
value: 'off',
}], disabled: state => state.amname !== 'gist' || inSchema(withSchemaObj.node_info),
depChange: (state, source) => {
if (state.amname !== 'gist') {
return {buffering: ''};
} else if (state.amname === 'gist' && source[0] !== 'buffering') {
return {buffering: 'auto'};
}
}
},{
id: 'deduplicate_items', label: gettext('Deduplicate items?'), cell: 'string',
type: 'switch', deps:['amname'], mode: ['create', 'edit', 'properties'], disabled: (state) => {
return state.amname !== 'btree' || inSchema(withSchemaObj.node_info);
},
depChange: (state, source) => {
if (state.amname !== 'btree') {
return {deduplicate_items:undefined};
} else if (state.amname === 'btree' && source[0] !== 'deduplicate_items') {
return {deduplicate_items: true};
}
}, min_version: 130000,
group: gettext('Definition'),
},{
id: 'fastupdate', label: gettext('Fast update?'), cell: 'string',
type: 'switch', deps:['amname'], mode: ['create', 'edit', 'properties'], disabled: (state) => {
return state.amname !== 'gin' || inSchema(withSchemaObj.node_info);
},
depChange: (state, source) => {
if (state.amname !== 'gin') {
return {fastupdate:undefined};
} else if (state.amname === 'gin' && source[0] !== 'fastupdate') {
return {fastupdate: true};
}
},
group: gettext('Definition'),
},{
id: 'autosummarize', label: gettext('Autosummarize?'), cell: 'string',
type: 'switch', deps:['amname'], mode: ['create', 'edit', 'properties'], disabled: state => {
return state.amname !== 'brin' || inSchema(withSchemaObj.node_info);
}, group: gettext('Definition'),
depChange: (state) => {
if (state.amname !== 'brin') {
return {autosummarize:undefined};
}
}
}
];
}
}
function inSchema(node_info) {
return node_info && 'catalog' in node_info;
}
@ -209,6 +312,8 @@ export default class IndexSchema extends BaseUISchema {
tabname: undefined,
spcname: undefined,
amname: undefined,
fastupdate: false,
autosummarize: false,
columns: [],
...initValues
});
@ -222,6 +327,7 @@ export default class IndexSchema extends BaseUISchema {
...nodeData.node_info
};
this.getColumnSchema = columnSchema;
this.withSchema = new WithSchema(this.node_info);
}
get idAttribute() {
@ -353,10 +459,8 @@ export default class IndexSchema extends BaseUISchema {
},
node:'column',
},{
id: 'fillfactor', label: gettext('Fill factor'), cell: 'string',
type: 'int', disabled: () => inSchema(indexSchemaObj.node_info),
mode: ['create', 'edit', 'properties'],
min: 10, max:100, group: gettext('Definition'),
type: 'nested-fieldset', label: gettext('With'), group: gettext('Definition'),
schema: this.withSchema,
},{
id: 'indisunique', label: gettext('Unique?'), cell: 'string',
type: 'switch', deps:['amname'], disabled: (state) => {

View File

@ -0,0 +1,13 @@
-- Index: Idx_$%{}[]()&*^!@"'`\/#
-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#";
CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST)
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -0,0 +1,9 @@
CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST)
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -0,0 +1,13 @@
-- Index: Idx_$%{}[]()&*^!@"'`\/#
-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#";
CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -0,0 +1,9 @@
CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -0,0 +1,13 @@
-- Index: Idx_$%{}[]()&*^!@"'`\/#
-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#";
CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST)
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -0,0 +1,9 @@
CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST)
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -0,0 +1,298 @@
{
"scenarios": [
{
"type": "create",
"name": "Create Table for indexes",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"data": {
"name": "test_table_for_indexes",
"columns": [{
"name": "id",
"cltype": "bigint",
"is_primary_key": true
}, {
"name": "name",
"cltype": "text"
}],
"is_partitioned": false,
"spcname": "pg_default",
"schema": "public"
},
"store_object_id": true
},
{
"type": "create",
"name": "Create btree index with ASC and NULLS LAST -- 15 Plus",
"endpoint": "NODE-index.obj",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql",
"data": {
"name":"Idx_$%{}[]()&*^!@\"'`\\/#",
"spcname":"pg_default",
"amname":"btree",
"columns":[{
"colname":"id",
"collspcname":"",
"op_class":"",
"sort_order":false,
"nulls":false,
"is_sort_nulls_applicable":true
}, {
"colname":"name",
"collspcname":"pg_catalog.\"POSIX\"",
"op_class":"text_pattern_ops",
"sort_order":false,
"nulls":false,
"is_sort_nulls_applicable":true
}],
"description":"Test Comment",
"fillfactor":"10",
"deduplicate_items": false,
"indisunique":true,
"indnullsnotdistinct":true,
"indisclustered":false,
"isconcurrent":false,
"indconstraint":"id < 100"
},
"expected_sql_file": "create_btree_asc_null_last.sql",
"expected_msql_file": "create_btree_asc_null_last_msql.sql"
},
{
"type": "delete",
"name": "Drop index",
"endpoint": "NODE-index.delete_id",
"data": {
"name": "Idx_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create btree index with ASC and NULLS FIRST -- 13 Plus",
"endpoint": "NODE-index.obj",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql",
"data": {
"name":"Idx_$%{}[]()&*^!@\"'`\\/#",
"spcname":"pg_default",
"amname":"btree",
"columns":[{
"colname":"id",
"collspcname":"",
"op_class":"",
"sort_order":false,
"nulls":true,
"is_sort_nulls_applicable":true
}, {
"colname":"name",
"collspcname":"pg_catalog.\"POSIX\"",
"op_class":"text_pattern_ops",
"sort_order":false,
"nulls":true,
"is_sort_nulls_applicable":true
}],
"description":"Test Comment",
"fillfactor":"10",
"deduplicate_items": false,
"indisunique":true,
"indnullsnotdistinct":true,
"indisclustered":false,
"isconcurrent":false,
"indconstraint":"id < 100"
},
"expected_sql_file": "create_btree_asc_null_first.sql",
"expected_msql_file": "create_btree_asc_null_first_msql.sql"
},
{
"type": "delete",
"name": "Drop index -- 15 Plus",
"endpoint": "NODE-index.delete_id",
"data": {
"name": "Idx_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create btree index with DESC and NULLS LAST -- 15 Plus",
"endpoint": "NODE-index.obj",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql",
"data": {
"name":"Idx_$%{}[]()&*^!@\"'`\\/#",
"spcname":"pg_default",
"amname":"btree",
"columns":[{
"colname":"id",
"collspcname":"",
"op_class":"",
"sort_order":true,
"nulls":false,
"is_sort_nulls_applicable":true
}, {
"colname":"name",
"collspcname":"pg_catalog.\"POSIX\"",
"op_class":"text_pattern_ops",
"sort_order":true,
"nulls":false,
"is_sort_nulls_applicable":true
}],
"description":"Test Comment",
"fillfactor":"10",
"deduplicate_items":false,
"indisunique":true,
"indnullsnotdistinct":true,
"indisclustered":false,
"isconcurrent":false,
"indconstraint":"id < 100"
},
"expected_sql_file": "create_btree_desc_null_last.sql",
"expected_msql_file": "create_btree_desc_null_last_msql.sql"
},
{
"type": "delete",
"name": "Drop index -- 15 Plus",
"endpoint": "NODE-index.delete_id",
"data": {
"name": "Idx_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create btree index with DESC and NULLS FIRST -- 15 Plus",
"endpoint": "NODE-index.obj",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql",
"data": {
"name":"Idx_$%{}[]()&*^!@\"'`\\/#",
"spcname":"pg_default",
"amname":"btree",
"columns":[{
"colname":"id",
"collspcname":"",
"op_class":"",
"sort_order":true,
"nulls":true,
"is_sort_nulls_applicable":true
}, {
"colname":"name",
"collspcname":"pg_catalog.\"POSIX\"",
"op_class":"text_pattern_ops",
"sort_order":true,
"nulls":true,
"is_sort_nulls_applicable":true
}],
"indisunique":true,
"indnullsnotdistinct":true,
"indisclustered":false,
"isconcurrent":false
},
"expected_sql_file": "create_btree_desc_null_first.sql",
"expected_msql_file": "create_btree_desc_null_first_msql.sql"
},
{
"type": "alter",
"name": "Alter index name, fill factor, comment and clustered -- 15 Plus",
"endpoint": "NODE-index.obj_id",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql_id",
"data": {
"name": "Idx1_$%{}[]()&*^!@\"'`\\/#",
"description":"Test Comment",
"fillfactor":"10",
"indisclustered":true
},
"expected_sql_file": "alter_name_fillfactor_comment.sql",
"expected_msql_file": "alter_name_fillfactor_comment_msql.sql"
},
{
"type": "alter",
"name": "Alter reset fill factor and cluster -- 15 Plus",
"endpoint": "NODE-index.obj_id",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql_id",
"data": {
"fillfactor": "",
"indisclustered": false
},
"expected_sql_file": "alter_reset_fillfactor_cluster.sql",
"expected_msql_file": "alter_reset_fillfactor_cluster_msql.sql"
},
{
"type": "delete",
"name": "Drop index -- 15 Plus",
"endpoint": "NODE-index.delete_id",
"data": {
"name": "Idx1_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create hash index -- 15 Plus",
"endpoint": "NODE-index.obj",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql",
"data": {
"name": "Idx_$%{}[]()&*^!@\"'`\\/#",
"spcname": "pg_default",
"amname": "hash",
"columns": [{
"colname": "id",
"collspcname": "",
"op_class": "",
"sort_order": false,
"nulls": false,
"is_sort_nulls_applicable": false
}],
"indisunique": false,
"indisclustered": false,
"isconcurrent": false
},
"expected_sql_file": "create_hash_index.sql",
"expected_msql_file": "create_hash_index_msql.sql"
},
{
"type": "delete",
"name": "Drop hash index -- 15 Plus",
"endpoint": "NODE-index.delete_id",
"data": {
"name": "Idx_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "delete",
"name": "Drop Table",
"endpoint": "NODE-table.delete_id",
"data": {
"name": "test_table_for_indexes"
}
},
{
"type": "create",
"name": "Create unnamed hash index -- 15 Plus",
"endpoint": "NODE-index.obj",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql",
"data": {
"spcname": "pg_default",
"amname": "hash",
"columns": [{
"colname": "id",
"collspcname": "",
"op_class": "",
"sort_order": false,
"nulls": false,
"is_sort_nulls_applicable": false
}],
"indisunique": false,
"isconcurrent": false
},
"expected_msql_file": "create_unnamed_hash_index_msql.sql"
},
{
"type": "delete",
"name": "Drop hash index -- 15 Plus",
"endpoint": "NODE-index.delete_id"
}
]
}

View File

@ -6,7 +6,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx1_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id DESC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS FIRST)
NULLS NOT DISTINCT
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.test_table_for_indexes

View File

@ -6,7 +6,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST)
NULLS NOT DISTINCT
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -2,7 +2,7 @@ CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST)
NULLS NOT DISTINCT
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -6,7 +6,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
NULLS NOT DISTINCT
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -2,7 +2,7 @@ CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
NULLS NOT DISTINCT
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -6,7 +6,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST)
NULLS NOT DISTINCT
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -2,7 +2,7 @@ CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST)
NULLS NOT DISTINCT
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -5,7 +5,7 @@
CREATE UNIQUE INDEX IF NOT EXISTS "Idx1_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id DESC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS FIRST)
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.test_table_for_indexes

View File

@ -2,7 +2,8 @@ ALTER INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#"
RENAME TO "Idx1_$%{}[]()&*^!@""'`\/#";
ALTER INDEX IF EXISTS public."Idx1_$%{}[]()&*^!@""'`\/#"
SET (FILLFACTOR=10);
SET (fillfactor=10);
ALTER TABLE IF EXISTS public.test_table_for_indexes
CLUSTER ON "Idx1_$%{}[]()&*^!@""'`\/#";

View File

@ -1,5 +1,6 @@
ALTER INDEX IF EXISTS public."Idx1_$%{}[]()&*^!@""'`\/#"
RESET (FILLFACTOR);
RESET (fillfactor);
ALTER TABLE IF EXISTS public.test_table_for_indexes
SET WITHOUT CLUSTER;

View File

@ -5,7 +5,7 @@
CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST)
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -1,7 +1,7 @@
CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST)
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -5,7 +5,7 @@
CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -1,7 +1,7 @@
CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -5,7 +5,7 @@
CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST)
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -1,7 +1,7 @@
CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST)
WITH (FILLFACTOR=10)
WITH (fillfactor=10)
TABLESPACE pg_default
WHERE id < 100;

View File

@ -253,6 +253,68 @@
"error_msg": null,
"test_result_data": {}
}
},
{
"name": "Create index: Create btree index with storage parameters",
"is_positive_test": true,
"inventory_data": {
"server_min_version": 130000,
"skip_msg": "Storage parameter deduplicate_items is not supported below PG 13.0."
},
"test_data": {
"name": "test_index_add",
"spcname": "pg_default",
"amname": "btree",
"indisunique":true,
"indnullsnotdistinct":true,
"fillfactor":"10",
"columns": [
{
"colname": "id",
"sort_order": false,
"nulls": false
}
],
"include": [
"name"
]
},
"mocking_required": false,
"mock_data": {},
"expected_data": {
"status_code": 200,
"error_msg": null,
"test_result_data": {}
}
},{
"name": "Create index: Create btree index with storage parameters (fillfactor)",
"is_positive_test": true,
"inventory_data": {},
"test_data": {
"name": "test_index_add",
"spcname": "pg_default",
"amname": "btree",
"indisunique":true,
"indnullsnotdistinct":true,
"fillfactor":"10",
"columns": [
{
"colname": "id",
"sort_order": false,
"nulls": false
}
],
"include": [
"name"
]
},
"mocking_required": false,
"mock_data": {},
"expected_data": {
"status_code": 200,
"error_msg": null,
"test_result_data": {}
}
}
],
"index_get": [

View File

@ -306,6 +306,13 @@ def get_reverse_engineered_sql(conn, **kwargs):
# Adding parent into data dict, will be using it while creating sql
data['schema'] = schema
data['table'] = table
data["storage_parameters"] = {}
storage_params = get_storage_params(data['amname'])
for param in storage_params:
if (param in data) and (data[param] is not None):
data["storage_parameters"].update({param: data[param]})
# Add column details for current index
data = get_column_details(conn, idx, data, 'create')
@ -327,3 +334,22 @@ def get_reverse_engineered_sql(conn, **kwargs):
SQL = sql_header + '\n\n' + SQL
return SQL
def get_storage_params(amname):
"""
This function will return storage parameters according to index type.
:param amname: access method name
:return:
"""
storage_parameters = {
"btree": ["fillfactor", "deduplicate_items"],
"hash": ["fillfactor"],
"gist": ["fillfactor", "buffering"],
"gin": ["fastupdate", "gin_pending_list_limit"],
"spgist": ["fillfactor"],
"brin": ["pages_per_range", "autosummarize"],
"heap": []
}
return storage_parameters[amname]

View File

@ -18,8 +18,8 @@ FIRST{% else %}LAST{% endif %}{% endif %}{% endfor %})
INCLUDE({% for col in data.include %}{% if loop.index != 1 %}, {% endif %}{{conn|qtIdent(col)}}{% endfor %})
{% endif %}
{% endif %}
{% if data.fillfactor %}
WITH (FILLFACTOR={{data.fillfactor}})
{% if data.storage_parameters %}
WITH ({% for key, value in data.storage_parameters.items() %}{% if loop.index != 1 %}, {% endif %}{{key}}={{value}}{% endfor %})
{% endif %}{% if data.spcname %}
TABLESPACE {{conn|qtIdent(data.spcname)}}{% endif %}{% if data.indconstraint %}

View File

@ -0,0 +1,33 @@
SELECT DISTINCT ON(cls.relname) cls.oid, cls.relname as name, indrelid, indkey, indisclustered,
indisvalid, indisunique, indisprimary, n.nspname,indnatts,cls.reltablespace AS spcoid,
CASE WHEN (length(spcname::text) > 0 OR cls.relkind = 'I') THEN spcname ELSE
(SELECT sp.spcname FROM pg_catalog.pg_database dtb
JOIN pg_catalog.pg_tablespace sp ON dtb.dattablespace=sp.oid
WHERE dtb.oid = {{ did }}::oid)
END as spcname,
tab.relname as tabname, indclass, con.oid AS conoid,
CASE WHEN contype IN ('p', 'u', 'x') THEN desp.description
ELSE des.description END AS description,
pg_catalog.pg_get_expr(indpred, indrelid, true) as indconstraint, contype, condeferrable, condeferred, amname,
(SELECT (CASE WHEN count(i.inhrelid) > 0 THEN true ELSE false END) FROM pg_inherits i WHERE i.inhrelid = cls.oid) as is_inherited,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'fillfactor=([0-9]*)') AS fillfactor,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'gin_pending_list_limit=([0-9]*)') AS gin_pending_list_limit,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'pages_per_range=([0-9]*)') AS pages_per_range,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'buffering=([a-z]*)') AS buffering,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'fastupdate=([a-z]*)')::boolean AS fastupdate,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'autosummarize=([a-z]*)')::boolean AS autosummarize
{% if datlastsysoid %}, (CASE WHEN cls.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_idx {% endif %}
FROM pg_catalog.pg_index idx
JOIN pg_catalog.pg_class cls ON cls.oid=indexrelid
JOIN pg_catalog.pg_class tab ON tab.oid=indrelid
LEFT OUTER JOIN pg_catalog.pg_tablespace ta on ta.oid=cls.reltablespace
JOIN pg_catalog.pg_namespace n ON n.oid=tab.relnamespace
JOIN pg_catalog.pg_am am ON am.oid=cls.relam
LEFT JOIN pg_catalog.pg_depend dep ON (dep.classid = cls.tableoid AND dep.objid = cls.oid AND dep.refobjsubid = '0' AND dep.refclassid=(SELECT oid FROM pg_catalog.pg_class WHERE relname='pg_constraint') AND dep.deptype='i')
LEFT OUTER JOIN pg_catalog.pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid)
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=cls.oid AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN pg_catalog.pg_description desp ON (desp.objoid=con.oid AND desp.objsubid = 0 AND desp.classoid='pg_constraint'::regclass)
WHERE indrelid = {{tid}}::OID
AND conname is NULL
{% if idx %}AND cls.oid = {{idx}}::OID {% endif %}
ORDER BY cls.relname

View File

@ -0,0 +1,34 @@
SELECT DISTINCT ON(cls.relname) cls.oid, cls.relname as name, indrelid, indkey, indisclustered,
indisvalid, indisunique, indisprimary, n.nspname,indnatts,cls.reltablespace AS spcoid,
CASE WHEN (length(spcname::text) > 0 OR cls.relkind = 'I') THEN spcname ELSE
(SELECT sp.spcname FROM pg_catalog.pg_database dtb
JOIN pg_catalog.pg_tablespace sp ON dtb.dattablespace=sp.oid
WHERE dtb.oid = {{ did }}::oid)
END as spcname,
tab.relname as tabname, indclass, con.oid AS conoid,
CASE WHEN contype IN ('p', 'u', 'x') THEN desp.description
ELSE des.description END AS description,
pg_catalog.pg_get_expr(indpred, indrelid, true) as indconstraint, contype, condeferrable, condeferred, amname,
(SELECT (CASE WHEN count(i.inhrelid) > 0 THEN true ELSE false END) FROM pg_inherits i WHERE i.inhrelid = cls.oid) as is_inherited,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'fillfactor=([0-9]*)') AS fillfactor,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'deduplicate_items=([a-z]*)')::boolean AS deduplicate_items,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'gin_pending_list_limit=([0-9]*)') AS gin_pending_list_limit,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'pages_per_range=([0-9]*)') AS pages_per_range,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'buffering=([a-z]*)') AS buffering,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'fastupdate=([a-z]*)')::boolean AS fastupdate,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'autosummarize=([a-z]*)')::boolean AS autosummarize
{% if datlastsysoid %}, (CASE WHEN cls.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_idx {% endif %}
FROM pg_catalog.pg_index idx
JOIN pg_catalog.pg_class cls ON cls.oid=indexrelid
JOIN pg_catalog.pg_class tab ON tab.oid=indrelid
LEFT OUTER JOIN pg_catalog.pg_tablespace ta on ta.oid=cls.reltablespace
JOIN pg_catalog.pg_namespace n ON n.oid=tab.relnamespace
JOIN pg_catalog.pg_am am ON am.oid=cls.relam
LEFT JOIN pg_catalog.pg_depend dep ON (dep.classid = cls.tableoid AND dep.objid = cls.oid AND dep.refobjsubid = '0' AND dep.refclassid=(SELECT oid FROM pg_catalog.pg_class WHERE relname='pg_constraint') AND dep.deptype='i')
LEFT OUTER JOIN pg_catalog.pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid)
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=cls.oid AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN pg_catalog.pg_description desp ON (desp.objoid=con.oid AND desp.objsubid = 0 AND desp.classoid='pg_constraint'::regclass)
WHERE indrelid = {{tid}}::OID
AND conname is NULL
{% if idx %}AND cls.oid = {{idx}}::OID {% endif %}
ORDER BY cls.relname

View File

@ -24,8 +24,8 @@ FIRST{% else %}LAST{% endif %}{% endif %}{% endfor %})
NULLS NOT DISTINCT
{% endif %}
{% endif %}
{% if data.fillfactor %}
WITH (FILLFACTOR={{data.fillfactor}})
{% if data.storage_parameters %}
WITH ({% for key, value in data.storage_parameters.items() %}{% if loop.index != 1 %}, {% endif %}{{key}}={{value}}{% endfor %})
{% endif %}{% if data.spcname %}
TABLESPACE {{conn|qtIdent(data.spcname)}}{% endif %}{% if data.indconstraint %}

View File

@ -10,7 +10,13 @@ SELECT DISTINCT ON(cls.relname) cls.oid, cls.relname as name, indrelid, indkey,
ELSE des.description END AS description,
pg_catalog.pg_get_expr(indpred, indrelid, true) as indconstraint, contype, condeferrable, condeferred, amname,
(SELECT (CASE WHEN count(i.inhrelid) > 0 THEN true ELSE false END) FROM pg_inherits i WHERE i.inhrelid = cls.oid) as is_inherited,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'fillfactor=([0-9]*)') AS fillfactor
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'fillfactor=([0-9]*)') AS fillfactor,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'deduplicate_items=([a-z]*)')::boolean AS deduplicate_items,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'gin_pending_list_limit=([0-9]*)') AS gin_pending_list_limit,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'pages_per_range=([0-9]*)') AS pages_per_range,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'buffering=([a-z]*)') AS buffering,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'fastupdate=([a-z]*)')::boolean AS fastupdate,
substring(pg_catalog.array_to_string(cls.reloptions, ',') from 'autosummarize=([a-z]*)')::boolean AS autosummarize
{% if datlastsysoid %}, (CASE WHEN cls.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_idx {% endif %}
FROM pg_catalog.pg_index idx
JOIN pg_catalog.pg_class cls ON cls.oid=indexrelid

View File

@ -7,11 +7,60 @@ ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, o_data.name)}}
{## Changes fillfactor ##}
{% if data.fillfactor and o_data.fillfactor != data.fillfactor %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (FILLFACTOR={{data.fillfactor}});
SET (fillfactor={{data.fillfactor}});
{% elif (data.fillfactor == '' or data.fillfactor == None) and o_data.fillfactor|default('', 'true') != data.fillfactor %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (FILLFACTOR);
RESET (fillfactor);
{% endif %}
{## Changes gin_pending_list_limit ##}
{% if data.gin_pending_list_limit and o_data.gin_pending_list_limit != data.gin_pending_list_limit %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (gin_pending_list_limit={{data.gin_pending_list_limit}});
{% elif (data.gin_pending_list_limit == '' or data.gin_pending_list_limit == None) and o_data.gin_pending_list_limit|default('', 'true') != data.gin_pending_list_limit %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (gin_pending_list_limit);
{% endif %}
{## Changes deduplicate_items ##}
{% if data.deduplicate_items in [True, False] and o_data.deduplicate_items != data.deduplicate_items %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (deduplicate_items={{data.deduplicate_items}});
{% endif %}
{## Changes pages_per_range ##}
{% if data.pages_per_range and o_data.pages_per_range != data.pages_per_range %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (pages_per_range={{data.pages_per_range}});
{% elif (data.pages_per_range == '' or data.pages_per_range == None) and o_data.pages_per_range|default('', 'true') != data.pages_per_range %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (pages_per_range);
{% endif %}
{## Changes buffering ##}
{% if data.buffering and o_data.buffering != data.buffering %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (buffering={{data.buffering}});
{% elif (data.buffering == '' or data.buffering == None) and o_data.buffering|default('', 'true') != data.buffering %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (buffering);
{% endif %}
{## Changes fastupdate ##}
{% if data.fastupdate in [True, False] and o_data.fastupdate != data.fastupdate %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (fastupdate={{data.fastupdate}});
{% endif %}
{## Changes autosummarize ##}
{% if data.autosummarize in [True, False] and o_data.autosummarize != data.autosummarize %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (autosummarize={{data.autosummarize}});
{% endif %}
{## Changes tablespace ##}