mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Fix exclusion constraint support on 9.6. Fixes #1875
This commit is contained in:
committed by
Dave Page
parent
23a0fc2f22
commit
2952faab5e
@@ -290,7 +290,11 @@ class TableView(PGChildNodeView, DataTypeReader, VacuumSettings):
|
|||||||
self.template_path = 'table/sql/9.1_plus'
|
self.template_path = 'table/sql/9.1_plus'
|
||||||
|
|
||||||
# Template for Column ,check constraint and exclusion constraint node
|
# Template for Column ,check constraint and exclusion constraint node
|
||||||
if ver >= 90200:
|
if ver >= 90600:
|
||||||
|
self.column_template_path = 'column/sql/9.2_plus'
|
||||||
|
self.check_constraint_template_path = 'check_constraint/sql/9.2_plus'
|
||||||
|
self.exclusion_constraint_template_path = 'exclusion_constraint/sql/9.6_plus'
|
||||||
|
elif ver >= 90200:
|
||||||
self.column_template_path = 'column/sql/9.2_plus'
|
self.column_template_path = 'column/sql/9.2_plus'
|
||||||
self.check_constraint_template_path = 'check_constraint/sql/9.2_plus'
|
self.check_constraint_template_path = 'check_constraint/sql/9.2_plus'
|
||||||
self.exclusion_constraint_template_path = 'exclusion_constraint/sql/9.2_plus'
|
self.exclusion_constraint_template_path = 'exclusion_constraint/sql/9.2_plus'
|
||||||
|
|||||||
@@ -217,7 +217,9 @@ class ExclusionConstraintView(PGChildNodeView):
|
|||||||
self.conn = self.manager.connection(did=kwargs['did'])
|
self.conn = self.manager.connection(did=kwargs['did'])
|
||||||
|
|
||||||
ver = self.manager.version
|
ver = self.manager.version
|
||||||
if ver >= 90200:
|
if ver >= 90600:
|
||||||
|
self.template_path = 'exclusion_constraint/sql/9.6_plus'
|
||||||
|
elif ver >= 90200:
|
||||||
self.template_path = 'exclusion_constraint/sql/9.2_plus'
|
self.template_path = 'exclusion_constraint/sql/9.2_plus'
|
||||||
elif ver >= 90100:
|
elif ver >= 90100:
|
||||||
self.template_path = 'exclusion_constraint/sql/9.1_plus'
|
self.template_path = 'exclusion_constraint/sql/9.1_plus'
|
||||||
|
|||||||
@@ -700,8 +700,14 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
|
|||||||
if (column_collection.length > 0 && current_am != previous_am) {
|
if (column_collection.length > 0 && current_am != previous_am) {
|
||||||
var msg = '{{ _('Changing access method will clear columns collection') }}';
|
var msg = '{{ _('Changing access method will clear columns collection') }}';
|
||||||
Alertify.confirm(msg, function (e) {
|
Alertify.confirm(msg, function (e) {
|
||||||
// User clicks Ok, lets clear collection
|
// User clicks Ok, lets clear collection.
|
||||||
column_collection.reset();
|
column_collection.each(function(m) {
|
||||||
|
/*
|
||||||
|
* Our datamodel do not support collection reset method.
|
||||||
|
* So remove model one by one.
|
||||||
|
*/
|
||||||
|
column_collection.remove(m);
|
||||||
|
});
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
column_collection.trigger('pgadmin:columns:updated', column_collection);
|
column_collection.trigger('pgadmin:columns:updated', column_collection);
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ SELECT ct.oid,
|
|||||||
ct.conname as name,
|
ct.conname as name,
|
||||||
NOT convalidated as convalidated
|
NOT convalidated as convalidated
|
||||||
FROM pg_constraint ct
|
FROM pg_constraint ct
|
||||||
WHERE contype='f' AND
|
WHERE contype='x' AND
|
||||||
conrelid = {{tid}}::oid LIMIT 1;
|
conrelid = {{tid}}::oid LIMIT 1;
|
||||||
@@ -2,5 +2,5 @@ SELECT ct.oid,
|
|||||||
ct.conname as name,
|
ct.conname as name,
|
||||||
NOT convalidated as convalidated
|
NOT convalidated as convalidated
|
||||||
FROM pg_constraint ct
|
FROM pg_constraint ct
|
||||||
WHERE contype='f' AND
|
WHERE contype='x' AND
|
||||||
conrelid = {{tid}}::oid LIMIT 1;
|
conrelid = {{tid}}::oid LIMIT 1;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
BEGIN;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
|
||||||
|
ADD{% if data.name %} CONSTRAINT {{ conn|qtIdent(data.name) }}{% endif%} EXCLUDE {% if data.amname and data.amname != '' %}USING {{data.amname}}{% endif %} (
|
||||||
|
{% for col in data.columns %}{% if loop.index != 1 %},
|
||||||
|
{% endif %}{{ conn|qtIdent(col.column)}} {% if col.oper_class and col.oper_class != '' %}{{col.oper_class}} {% endif%}{% if col.order %}ASC{% else %}DESC{% endif %} NULLS {% if col.nulls_order %}FIRST{% else %}LAST{% endif %} WITH {{col.operator}}{% endfor %}){% if data.fillfactor %}
|
||||||
|
WITH (FILLFACTOR={{data.fillfactor}}){% endif %}{% if data.spcname and data.spcname != "pg_default" %}
|
||||||
|
|
||||||
|
USING INDEX TABLESPACE {{ conn|qtIdent(data.spcname) }}{% endif %}
|
||||||
|
{% if data.condeferrable %}
|
||||||
|
|
||||||
|
DEFERRABLE{% if data.condeferred %}
|
||||||
|
INITIALLY DEFERRED{% endif%}
|
||||||
|
{% endif%}{% if data.constraint %} WHERE ({{data.constraint}}){% endif%};
|
||||||
|
{% if data.comment and data.name %}
|
||||||
|
|
||||||
|
COMMENT ON CONSTRAINT {{ conn|qtIdent(data.name) }} ON {{ conn|qtIdent(data.schema, data.table) }}
|
||||||
|
IS {{ data.comment|qtLiteral }};
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{% if data %}
|
||||||
|
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }} DROP CONSTRAINT {{ conn|qtIdent(data.name) }}{% if cascade%} CASCADE{% endif %};
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
END;
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
SELECT amname
|
||||||
|
FROM pg_am
|
||||||
|
WHERE EXISTS (SELECT 1
|
||||||
|
FROM pg_proc
|
||||||
|
WHERE oid=amhandler)
|
||||||
|
ORDER BY amname;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{% for n in range(colcnt|int) %}
|
||||||
|
{% if loop.index != 1 %}
|
||||||
|
UNION
|
||||||
|
{% endif %}
|
||||||
|
SELECT
|
||||||
|
i.indoption[{{loop.index -1}}] AS options,
|
||||||
|
pg_get_indexdef(i.indexrelid, {{loop.index}}, true) AS coldef,
|
||||||
|
op.oprname,
|
||||||
|
CASE WHEN (o.opcdefault = FALSE) THEN o.opcname ELSE null END AS opcname
|
||||||
|
,
|
||||||
|
coll.collname,
|
||||||
|
nspc.nspname as collnspname,
|
||||||
|
format_type(ty.oid,NULL) AS datatype
|
||||||
|
FROM pg_index i
|
||||||
|
JOIN pg_attribute a ON (a.attrelid = i.indexrelid AND attnum = {{loop.index}})
|
||||||
|
JOIN pg_type ty ON ty.oid=a.atttypid
|
||||||
|
LEFT OUTER JOIN pg_opclass o ON (o.oid = i.indclass[{{loop.index -1}}])
|
||||||
|
LEFT OUTER JOIN pg_constraint c ON (c.conindid = i.indexrelid) LEFT OUTER JOIN pg_operator op ON (op.oid = c.conexclop[{{loop.index}}])
|
||||||
|
LEFT OUTER JOIN pg_collation coll ON a.attcollation=coll.oid
|
||||||
|
LEFT OUTER JOIN pg_namespace nspc ON coll.collnamespace=nspc.oid
|
||||||
|
WHERE i.indexrelid = {{cid}}::oid
|
||||||
|
{% endfor %}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
SELECT conname as name
|
||||||
|
FROM pg_constraint ct
|
||||||
|
WHERE ct.conindid = {{cid}}::oid
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
SELECT ct.oid
|
||||||
|
FROM pg_constraint ct
|
||||||
|
WHERE contype='x' AND
|
||||||
|
ct.conname = {{ name|qtLiteral }};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
SELECT ct.oid,
|
||||||
|
ct.conname as name,
|
||||||
|
NOT convalidated as convalidated
|
||||||
|
FROM pg_constraint ct
|
||||||
|
WHERE contype='x' AND
|
||||||
|
conrelid = {{tid}}::oid LIMIT 1;
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
SELECT opcname
|
||||||
|
FROM pg_opclass opc,
|
||||||
|
pg_am am
|
||||||
|
WHERE opcmethod=am.oid AND
|
||||||
|
am.amname ={{indextype|qtLiteral}} AND
|
||||||
|
NOT opcdefault
|
||||||
|
ORDER BY 1
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
SELECT DISTINCT op.oprname as oprname
|
||||||
|
FROM pg_operator op,
|
||||||
|
( SELECT oid
|
||||||
|
FROM (SELECT format_type(t.oid,NULL) AS typname,
|
||||||
|
t.oid as oid
|
||||||
|
FROM pg_type t
|
||||||
|
JOIN 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_class
|
||||||
|
WHERE relnamespace=typnamespace AND
|
||||||
|
relname = typname AND
|
||||||
|
relkind != 'c') AND
|
||||||
|
(typname NOT LIKE '_%' OR
|
||||||
|
NOT EXISTS (SELECT 1
|
||||||
|
FROM pg_class
|
||||||
|
WHERE relnamespace=typnamespace AND
|
||||||
|
relname = SUBSTRING(typname FROM 2)::name AND
|
||||||
|
relkind != 'c'))
|
||||||
|
{% if not show_sysobj %}
|
||||||
|
AND nsp.nspname != 'information_schema'
|
||||||
|
{% endif %}
|
||||||
|
UNION SELECT 'smallserial', 0
|
||||||
|
UNION SELECT 'bigserial', 0
|
||||||
|
UNION SELECT 'serial', 0) t1
|
||||||
|
WHERE typname = {{type|qtLiteral}}) AS types
|
||||||
|
WHERE oprcom > 0 AND
|
||||||
|
(op.oprleft=types.oid OR op.oprright=types.oid)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
SELECT nsp.nspname AS schema,
|
||||||
|
rel.relname AS table
|
||||||
|
FROM
|
||||||
|
pg_class rel
|
||||||
|
JOIN pg_namespace nsp
|
||||||
|
ON rel.relnamespace = nsp.oid::int
|
||||||
|
WHERE rel.oid = {{tid}}::int
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
SELECT conindid as oid,
|
||||||
|
conname as name,
|
||||||
|
NOT convalidated as convalidated
|
||||||
|
FROM pg_constraint ct
|
||||||
|
WHERE contype='x' AND
|
||||||
|
conrelid = {{tid}}::oid
|
||||||
|
ORDER BY conname
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
SELECT cls.oid,
|
||||||
|
cls.relname as name,
|
||||||
|
indnatts,
|
||||||
|
amname,
|
||||||
|
COALESCE(spcname, 'pg_default') as spcname,
|
||||||
|
CASE contype
|
||||||
|
WHEN 'p' THEN desp.description
|
||||||
|
WHEN 'u' THEN desp.description
|
||||||
|
WHEN 'x' THEN desp.description
|
||||||
|
ELSE des.description
|
||||||
|
END AS comment,
|
||||||
|
condeferrable,
|
||||||
|
condeferred,
|
||||||
|
substring(array_to_string(cls.reloptions, ',') from 'fillfactor=([0-9]*)') AS fillfactor
|
||||||
|
FROM pg_index idx
|
||||||
|
JOIN pg_class cls ON cls.oid=indexrelid
|
||||||
|
JOIN pg_class tab ON tab.oid=indrelid
|
||||||
|
LEFT OUTER JOIN pg_tablespace ta on ta.oid=cls.reltablespace
|
||||||
|
JOIN pg_namespace n ON n.oid=tab.relnamespace
|
||||||
|
JOIN pg_am am ON am.oid=cls.relam
|
||||||
|
LEFT JOIN pg_depend dep ON (dep.classid = cls.tableoid AND dep.objid = cls.oid AND dep.refobjsubid = '0' AND dep.refclassid=(SELECT oid FROM pg_class WHERE relname='pg_constraint') AND dep.deptype='i')
|
||||||
|
LEFT OUTER JOIN pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid)
|
||||||
|
LEFT OUTER JOIN pg_description des ON (des.objoid=cls.oid AND des.classoid='pg_class'::regclass)
|
||||||
|
LEFT OUTER JOIN pg_description desp ON (desp.objoid=con.oid AND desp.objsubid = 0 AND desp.classoid='pg_constraint'::regclass)
|
||||||
|
WHERE indrelid = {{tid}}::oid
|
||||||
|
{% if cid %}
|
||||||
|
AND cls.oid = {{cid}}::oid
|
||||||
|
{% endif %}
|
||||||
|
AND contype='x'
|
||||||
|
ORDER BY cls.relname
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
SELECT
|
||||||
|
idx_scan AS {{ conn|qtIdent(_('Index scans')) }},
|
||||||
|
idx_tup_read AS {{ conn|qtIdent(_('Index tuples read')) }},
|
||||||
|
idx_tup_fetch AS {{ conn|qtIdent(_('Index tuples fetched')) }},
|
||||||
|
idx_blks_read AS {{ conn|qtIdent(_('Index blocks read')) }},
|
||||||
|
idx_blks_hit AS {{ conn|qtIdent(_('Index blocks hit')) }},
|
||||||
|
pg_size_pretty(pg_relation_size({{ exid }}::OID)) AS {{ conn|qtIdent(_('Index size')) }}
|
||||||
|
{#=== Extended stats ===#}
|
||||||
|
{% if is_pgstattuple %}
|
||||||
|
,version AS {{ conn|qtIdent(_('Version')) }},
|
||||||
|
tree_level AS {{ conn|qtIdent(_('Tree level')) }},
|
||||||
|
pg_size_pretty(index_size) AS {{ conn|qtIdent(_('Index size')) }},
|
||||||
|
root_block_no AS {{ conn|qtIdent(_('Root block no')) }},
|
||||||
|
internal_pages AS {{ conn|qtIdent(_('Internal pages')) }},
|
||||||
|
leaf_pages AS {{ conn|qtIdent(_('Leaf pages')) }},
|
||||||
|
empty_pages AS {{ conn|qtIdent(_('Empty pages')) }},
|
||||||
|
deleted_pages AS {{ conn|qtIdent(_('Deleted pages')) }},
|
||||||
|
avg_leaf_density AS {{ conn|qtIdent(_('Average leaf density')) }},
|
||||||
|
leaf_fragmentation AS {{ conn|qtIdent(_('Leaf fragmentation')) }}
|
||||||
|
FROM
|
||||||
|
pgstatindex('{{conn|qtIdent(schema)}}.{{conn|qtIdent(name)}}'), pg_stat_all_indexes stat
|
||||||
|
{% else %}
|
||||||
|
FROM
|
||||||
|
pg_stat_all_indexes stat
|
||||||
|
{% endif %}
|
||||||
|
JOIN pg_statio_all_indexes statio ON stat.indexrelid = statio.indexrelid
|
||||||
|
JOIN pg_class cl ON cl.oid=stat.indexrelid
|
||||||
|
WHERE stat.indexrelid = {{ exid }}::OID
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{### SQL to update exclusion constraint object ###}
|
||||||
|
{% if data %}
|
||||||
|
{# ==== To update exclusion constraint name ==== #}
|
||||||
|
{% if data.name != o_data.name %}
|
||||||
|
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
|
||||||
|
RENAME CONSTRAINT {{ conn|qtIdent(o_data.name) }} TO {{ conn|qtIdent(data.name) }};
|
||||||
|
{% endif %}
|
||||||
|
{# ==== To update exclusion constraint tablespace ==== #}
|
||||||
|
{% if data.spcname and data.spcname != o_data.spcname %}
|
||||||
|
ALTER INDEX {{ conn|qtIdent(data.schema, data.name) }}
|
||||||
|
SET TABLESPACE {{ conn|qtIdent(data.spcname) }};
|
||||||
|
{% endif %}
|
||||||
|
{% if data.fillfactor and data.fillfactor != o_data.fillfactor %}
|
||||||
|
ALTER INDEX {{ conn|qtIdent(data.schema, data.name) }}
|
||||||
|
SET (FILLFACTOR={{ data.fillfactor }});
|
||||||
|
{% endif %}
|
||||||
|
{# ==== To update exclusion constraint comments ==== #}
|
||||||
|
{% if data.comment is defined and data.comment != o_data.comment %}
|
||||||
|
COMMENT ON CONSTRAINT {{ conn|qtIdent(data.name) }} ON {{ conn|qtIdent(data.schema, data.table) }}
|
||||||
|
IS {{ data.comment|qtLiteral }};
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
Reference in New Issue
Block a user