mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Added support for expression in exclusion constraints. Fixes #5571
This commit is contained in:
parent
a92595012f
commit
5448de2d3f
@ -58,13 +58,15 @@ Click the *Columns* tab to continue.
|
|||||||
:alt: Exclusion constraint dialog columns tab
|
:alt: Exclusion constraint dialog columns tab
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
Use the fields in the *Columns* tab to to specify the column(s) to which the
|
Use the fields in the *Columns* tab to specify the column(s) or expression(s)
|
||||||
constraint applies. Use the drop-down listbox next to *Column* to select a
|
to which the constraint applies. Use the *Is expression ?* switch to enable
|
||||||
column and click the *Add* icon (+) to provide details of the action on the
|
expression text input. Use the drop-down listbox next to *Column*
|
||||||
column:
|
to select a column. Once the *Column* is selected or the *Expression* is
|
||||||
|
entered then click the *Add* icon (+) to provide details of the action on the
|
||||||
|
column/expression:
|
||||||
|
|
||||||
* The *Column* field is populated with the selection made in the *Column*
|
* The *Col/Exp* field is populated with the selection made in the *Column*
|
||||||
drop-down listbox.
|
drop-down listbox or the *Expression* entered.
|
||||||
* If applicable, use the drop-down listbox in the *Operator class* to specify
|
* If applicable, use the drop-down listbox in the *Operator class* to specify
|
||||||
the operator class that will be used by the index for the column.
|
the operator class that will be used by the index for the column.
|
||||||
* Move the *DESC* switch to *DESC* to specify a descending sort order. The
|
* Move the *DESC* switch to *DESC* to specify a descending sort order. The
|
||||||
|
BIN
docs/en_US/images/exclusion_constraint_columns.png
Executable file → Normal file
BIN
docs/en_US/images/exclusion_constraint_columns.png
Executable file → Normal file
Binary file not shown.
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 93 KiB |
BIN
docs/en_US/images/exclusion_constraint_sql.png
Executable file → Normal file
BIN
docs/en_US/images/exclusion_constraint_sql.png
Executable file → Normal file
Binary file not shown.
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 74 KiB |
@ -19,6 +19,7 @@ Housekeeping
|
|||||||
Bug fixes
|
Bug fixes
|
||||||
*********
|
*********
|
||||||
|
|
||||||
|
| `Issue #5571 <https://redmine.postgresql.org/issues/5571>`_ - Added support for expression in exclusion constraints.
|
||||||
| `Issue #5875 <https://redmine.postgresql.org/issues/5875>`_ - Ensure that the 'template1' database should not be visible after pg_upgrade.
|
| `Issue #5875 <https://redmine.postgresql.org/issues/5875>`_ - Ensure that the 'template1' database should not be visible after pg_upgrade.
|
||||||
| `Issue #5965 <https://redmine.postgresql.org/issues/5965>`_ - Ensure that the macro query result should be download properly.
|
| `Issue #5965 <https://redmine.postgresql.org/issues/5965>`_ - Ensure that the macro query result should be download properly.
|
||||||
| `Issue #5973 <https://redmine.postgresql.org/issues/5973>`_ - Added appropriate help message and a placeholder for letting users know about the account password expiry for Login/Group Role.
|
| `Issue #5973 <https://redmine.postgresql.org/issues/5973>`_ - Added appropriate help message and a placeholder for letting users know about the account password expiry for Login/Group Role.
|
||||||
|
@ -560,17 +560,16 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings,
|
|||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
data = request.args if request.args else None
|
data = request.args
|
||||||
try:
|
try:
|
||||||
if data and 'col_type' in data:
|
result = exclusion_utils.get_operator(
|
||||||
result = exclusion_utils.get_operator(
|
self.conn, data.get('col_type', None),
|
||||||
self.conn, data['col_type'],
|
self.blueprint.show_system_objects)
|
||||||
self.blueprint.show_system_objects)
|
|
||||||
|
|
||||||
return make_json_response(
|
return make_json_response(
|
||||||
data=result,
|
data=result,
|
||||||
status=200
|
status=200
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return internal_server_error(errormsg=str(e))
|
return internal_server_error(errormsg=str(e))
|
||||||
|
|
||||||
|
@ -778,58 +778,18 @@ class ExclusionConstraintView(PGChildNodeView):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
SQL = render_template(
|
status, rows = exclusion_utils.get_exclusion_constraints(
|
||||||
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
self.conn, did, tid, exid, template_path=self.template_path
|
||||||
did=did, tid=tid, conn=self.conn, cid=exid)
|
)
|
||||||
status, result = self.conn.execute_dict(SQL)
|
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=result)
|
return rows
|
||||||
if len(result['rows']) == 0:
|
if len(rows) == 0:
|
||||||
return gone(_("Could not find the exclusion constraint."))
|
return gone(_("Could not find the exclusion constraint."))
|
||||||
|
|
||||||
data = result['rows'][0]
|
data = rows[0]
|
||||||
data['schema'] = self.schema
|
data['schema'] = self.schema
|
||||||
data['table'] = self.table
|
data['table'] = self.table
|
||||||
|
|
||||||
sql = render_template(
|
|
||||||
"/".join([self.template_path, 'get_constraint_cols.sql']),
|
|
||||||
cid=exid,
|
|
||||||
colcnt=data['col_count'])
|
|
||||||
status, res = self.conn.execute_dict(sql)
|
|
||||||
|
|
||||||
if not status:
|
|
||||||
return internal_server_error(errormsg=res)
|
|
||||||
|
|
||||||
columns = []
|
|
||||||
for row in res['rows']:
|
|
||||||
nulls_order = True if (row['options'] & 2) else False
|
|
||||||
order = False if row['options'] & 1 else True
|
|
||||||
columns.append({"column": row['coldef'].strip('"'),
|
|
||||||
"oper_class": row['opcname'],
|
|
||||||
"order": order,
|
|
||||||
"nulls_order": nulls_order,
|
|
||||||
"operator": row['oprname']
|
|
||||||
})
|
|
||||||
|
|
||||||
data['columns'] = columns
|
|
||||||
|
|
||||||
# Add Include details of the index supported for PG-11+
|
|
||||||
if self.manager.version >= 110000:
|
|
||||||
sql = render_template(
|
|
||||||
"/".join(
|
|
||||||
[self.template_path, 'get_constraint_include.sql']
|
|
||||||
),
|
|
||||||
cid=exid)
|
|
||||||
status, res = self.conn.execute_dict(sql)
|
|
||||||
|
|
||||||
if not status:
|
|
||||||
return internal_server_error(errormsg=res)
|
|
||||||
|
|
||||||
data['include'] = [col['colname'] for col in res['rows']]
|
|
||||||
|
|
||||||
if data.get('amname', '') == "":
|
|
||||||
data['amname'] = 'btree'
|
|
||||||
|
|
||||||
SQL = render_template(
|
SQL = render_template(
|
||||||
"/".join([self.template_path, self._CREATE_SQL]), data=data)
|
"/".join([self.template_path, self._CREATE_SQL]), data=data)
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
var ExclusionConstraintColumnModel = pgBrowser.Node.Model.extend({
|
var ExclusionConstraintColumnModel = pgBrowser.Node.Model.extend({
|
||||||
defaults: {
|
defaults: {
|
||||||
column: undefined,
|
column: undefined,
|
||||||
|
is_exp: false,
|
||||||
oper_class: undefined,
|
oper_class: undefined,
|
||||||
order: false,
|
order: false,
|
||||||
nulls_order: false,
|
nulls_order: false,
|
||||||
@ -32,8 +33,20 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
return d;
|
return d;
|
||||||
},
|
},
|
||||||
schema: [{
|
schema: [{
|
||||||
id: 'column', label: gettext('Column'), type:'text', editable: false,
|
id: 'column', label: gettext('Col/Exp'), type:'text', editable: false,
|
||||||
cell:'string',
|
cell:'string',
|
||||||
|
},{
|
||||||
|
id: 'is_exp', label: '', type:'boolean', editable: false,
|
||||||
|
cell: Backgrid.StringCell.extend({
|
||||||
|
formatter: {
|
||||||
|
fromRaw: function (rawValue) {
|
||||||
|
return rawValue ? 'E' : 'C';
|
||||||
|
},
|
||||||
|
toRaw: function (val) {
|
||||||
|
return val;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}), visible: false,
|
||||||
},{
|
},{
|
||||||
id: 'oper_class', label: gettext('Operator class'), type:'text',
|
id: 'oper_class', label: gettext('Operator class'), type:'text',
|
||||||
node: 'table', url: 'get_oper_class', first_empty: true,
|
node: 'table', url: 'get_oper_class', first_empty: true,
|
||||||
@ -175,7 +188,7 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
|
|
||||||
self.column.set('options', []);
|
self.column.set('options', []);
|
||||||
|
|
||||||
if (url && !_.isUndefined(col_type) && !_.isNull(col_type) && col_type != '') {
|
if (url) {
|
||||||
var node = this.column.get('schema_node'),
|
var node = this.column.get('schema_node'),
|
||||||
eventHandler = m.top || m,
|
eventHandler = m.top || m,
|
||||||
node_info = this.column.get('node_info'),
|
node_info = this.column.get('node_info'),
|
||||||
@ -210,9 +223,11 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
validate: function() {
|
validate: function() {
|
||||||
this.errorModel.clear();
|
this.errorModel.clear();
|
||||||
var operator = this.get('operator'),
|
var operator = this.get('operator'),
|
||||||
column_name = this.get('column');
|
column_name = this.get('column'),
|
||||||
|
is_exp = this.get('is_exp');
|
||||||
if (_.isUndefined(operator) || _.isNull(operator)) {
|
if (_.isUndefined(operator) || _.isNull(operator)) {
|
||||||
var msg = gettext('Please specify operator for column: ') + column_name;
|
var msg = gettext('Please specify operator for column: ') + column_name;
|
||||||
|
if(is_exp) msg = gettext('Please specify operator for expression: ') + column_name;
|
||||||
this.errorModel.set('operator', msg);
|
this.errorModel.set('operator', msg);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
@ -231,8 +246,15 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
var self = this,
|
var self = this,
|
||||||
node = 'exclusion_constraint',
|
node = 'exclusion_constraint',
|
||||||
headerSchema = [{
|
headerSchema = [{
|
||||||
id: 'column', label:'', type:'text',
|
id: 'is_exp', label: gettext('Is expression ?'), type: 'switch',
|
||||||
node: 'column', control: Backform.NodeListByNameControl.extend({
|
control: 'switch', controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12',
|
||||||
|
controlsClassName: 'pgadmin-controls pg-el-sm-6 pg-el-12',
|
||||||
|
},{
|
||||||
|
id: 'column', label: gettext('Column'), type:'text',
|
||||||
|
controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12',
|
||||||
|
controlsClassName: 'pgadmin-controls pg-el-sm-6 pg-el-12',
|
||||||
|
node: 'column', deps: ['is_exp'],
|
||||||
|
control: Backform.NodeListByNameControl.extend({
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
// Here we will decide if we need to call URL
|
// Here we will decide if we need to call URL
|
||||||
// Or fetch the data from parent columns collection
|
// Or fetch the data from parent columns collection
|
||||||
@ -310,7 +332,8 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: _.template([
|
template: _.template([
|
||||||
'<div class="<%=Backform.controlsClassName%> <%=extraClasses.join(\' \')%>">',
|
'<span class="<%=controlLabelClassName%>"><%=label%></span>',
|
||||||
|
'<div class="<%=controlsClassName%> <%=extraClasses.join(\' \')%>">',
|
||||||
' <select class="pgadmin-node-select form-control" name="<%=name%>" style="width:100%;" value="<%-value%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> >',
|
' <select class="pgadmin-node-select form-control" name="<%=name%>" style="width:100%;" value="<%-value%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> >',
|
||||||
' <% for (var i=0; i < options.length; i++) { %>',
|
' <% for (var i=0; i < options.length; i++) { %>',
|
||||||
' <% var option = options[i]; %>',
|
' <% var option = options[i]; %>',
|
||||||
@ -363,10 +386,21 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
readonly: function() {
|
readonly: function() {
|
||||||
return !_.isUndefined(self.model.get('oid'));
|
return !_.isUndefined(self.model.get('oid'));
|
||||||
},
|
},
|
||||||
|
disabled: function(m) {
|
||||||
|
return m.get('is_exp');
|
||||||
|
},
|
||||||
|
},{
|
||||||
|
id: 'exp', label: gettext('Expression'), type: 'text',
|
||||||
|
editable: true, deps: ['is_exp'],
|
||||||
|
controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12',
|
||||||
|
controlsClassName: 'pgadmin-controls pg-el-sm-6 pg-el-12',
|
||||||
|
disabled: function(m) {
|
||||||
|
return !m.get('is_exp');
|
||||||
|
},
|
||||||
}],
|
}],
|
||||||
headerDefaults = {column: null},
|
headerDefaults = {is_exp: false, column: null, exp: null},
|
||||||
|
|
||||||
gridCols = ['column', 'oper_class', 'order', 'nulls_order', 'operator'];
|
gridCols = ['is_exp', 'column', 'oper_class', 'order', 'nulls_order', 'operator'];
|
||||||
|
|
||||||
self.headerData = new (Backbone.Model.extend({
|
self.headerData = new (Backbone.Model.extend({
|
||||||
defaults: headerDefaults,
|
defaults: headerDefaults,
|
||||||
@ -396,22 +430,16 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
},
|
},
|
||||||
|
|
||||||
generateHeader: function(data) {
|
generateHeader: function(data) {
|
||||||
|
var isNew = _.isUndefined(this.model.get('oid'));
|
||||||
var header = [
|
var header = [
|
||||||
'<div class="subnode-header-form">',
|
'<div class="subnode-header-form '+ (isNew ? '' : 'd-none') +'">',
|
||||||
' <div>',
|
' <div>',
|
||||||
' <div class="row">',
|
' <div header="is_exp"></div>',
|
||||||
' <div class="col-4">',
|
' <div header="column"></div>',
|
||||||
' <label class="control-label"><%-column_label%></label>',
|
' <div header="exp"></div>',
|
||||||
' </div>',
|
|
||||||
' <div class="col-4" header="column"></div>',
|
|
||||||
' </div>',
|
|
||||||
' </div>',
|
' </div>',
|
||||||
'</div>'].join('\n');
|
'</div>'].join('\n');
|
||||||
|
|
||||||
_.extend(data, {
|
|
||||||
column_label: gettext('Column'),
|
|
||||||
});
|
|
||||||
|
|
||||||
var self = this,
|
var self = this,
|
||||||
headerTmpl = _.template(header),
|
headerTmpl = _.template(header),
|
||||||
$header = $(headerTmpl(data)),
|
$header = $(headerTmpl(data)),
|
||||||
@ -514,20 +542,24 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (self.control_data.canAdd) {
|
if (self.control_data.canAdd) {
|
||||||
self.collection.each(function(m) {
|
if(data['is_exp']) {
|
||||||
if (!inSelected) {
|
inSelected = false;
|
||||||
_.each(checkVars, function(v) {
|
} else {
|
||||||
if (!inSelected) {
|
self.collection.each(function(m) {
|
||||||
val = m.get(v);
|
if (!inSelected) {
|
||||||
inSelected = ((
|
_.each(checkVars, function(v) {
|
||||||
(_.isUndefined(val) || _.isNull(val)) &&
|
if (!inSelected) {
|
||||||
(_.isUndefined(data[v]) || _.isNull(data[v]))
|
val = m.get(v);
|
||||||
) ||
|
inSelected = ((
|
||||||
(val == data[v]));
|
(_.isUndefined(val) || _.isNull(val)) &&
|
||||||
}
|
(_.isUndefined(data[v]) || _.isNull(data[v]))
|
||||||
});
|
) ||
|
||||||
}
|
(val == data[v]));
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
inSelected = true;
|
inSelected = true;
|
||||||
@ -538,23 +570,28 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
|
|
||||||
addColumns: function(ev) {
|
addColumns: function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
var self = this,
|
var self = this;
|
||||||
column = self.headerData.get('column');
|
let newHeaderData = {
|
||||||
|
is_exp: self.headerData.get('is_exp'),
|
||||||
|
column: self.headerData.get('is_exp') ? self.headerData.get('exp') : self.headerData.get('column'),
|
||||||
|
};
|
||||||
|
|
||||||
if (column && column != '') {
|
if (newHeaderData.column && newHeaderData.column != '') {
|
||||||
var coll = self.model.get(self.field.get('name')),
|
var coll = self.model.get(self.field.get('name')),
|
||||||
m = new (self.field.get('model'))(
|
m = new (self.field.get('model'))(
|
||||||
self.headerData.toJSON(), {
|
newHeaderData, {
|
||||||
silent: true, top: self.model.top,
|
silent: true, top: self.model.top,
|
||||||
collection: coll, handler: coll,
|
collection: coll, handler: coll,
|
||||||
}),
|
}),
|
||||||
col_types =self.field.get('col_types') || [];
|
col_types =self.field.get('col_types') || [];
|
||||||
|
|
||||||
for(var i=0; i < col_types.length; i++) {
|
if(!m.get('is_exp')) {
|
||||||
var col_type = col_types[i];
|
for(var i=0; i < col_types.length; i++) {
|
||||||
if (col_type['name'] == m.get('column')) {
|
var col_type = col_types[i];
|
||||||
m.set({'col_type':col_type['type']});
|
if (col_type['name'] == m.get('column')) {
|
||||||
break;
|
m.set({'col_type':col_type['type']});
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,7 +823,7 @@ define('pgadmin.node.exclusion_constraint', [
|
|||||||
!_.isUndefined(m.get('oid'))) || (_.isFunction(m.isNew) && !m.isNew()));
|
!_.isUndefined(m.get('oid'))) || (_.isFunction(m.isNew) && !m.isNew()));
|
||||||
},
|
},
|
||||||
},{
|
},{
|
||||||
id: 'columns', label: gettext('Columns'),
|
id: 'columns', label: gettext('Columns/Expressions'),
|
||||||
type: 'collection', group: gettext('Columns'),
|
type: 'collection', group: gettext('Columns'),
|
||||||
deps:['amname'], canDelete: true, editable: false,
|
deps:['amname'], canDelete: true, editable: false,
|
||||||
canAdd: function(m) {
|
canAdd: function(m) {
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
-- Constraint: Exclusion_$%{}[]()&*^!@"'`\/#
|
||||||
|
|
||||||
|
-- ALTER TABLE testschema.tableforexclusion DROP CONSTRAINT "Exclusion_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
ALTER TABLE testschema.tableforexclusion
|
||||||
|
ADD CONSTRAINT "Exclusion_$%{}[]()&*^!@""'`\/#" EXCLUDE USING gist (
|
||||||
|
(col1 + col3) WITH <>,
|
||||||
|
col2 WITH <>)
|
||||||
|
WITH (FILLFACTOR=12)
|
||||||
|
WHERE (col1 > 1)
|
||||||
|
DEFERRABLE INITIALLY DEFERRED;
|
||||||
|
|
||||||
|
COMMENT ON CONSTRAINT "Exclusion_$%{}[]()&*^!@""'`\/#" ON testschema.tableforexclusion
|
||||||
|
IS 'Comment for create';
|
@ -14,6 +14,9 @@
|
|||||||
}, {
|
}, {
|
||||||
"name": "col2",
|
"name": "col2",
|
||||||
"cltype": "text"
|
"cltype": "text"
|
||||||
|
}, {
|
||||||
|
"name": "col3",
|
||||||
|
"cltype": "integer",
|
||||||
}],
|
}],
|
||||||
"is_partitioned": false,
|
"is_partitioned": false,
|
||||||
"schema": "testschema",
|
"schema": "testschema",
|
||||||
@ -76,6 +79,43 @@
|
|||||||
"data": {
|
"data": {
|
||||||
"name": "Exclusion_$%{}[]()&*^!@\"'`\\/#a"
|
"name": "Exclusion_$%{}[]()&*^!@\"'`\\/#a"
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create Exclusion Constraint with expressions",
|
||||||
|
"endpoint": "NODE-exclusion_constraint.obj",
|
||||||
|
"sql_endpoint": "NODE-exclusion_constraint.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "Exclusion_$%{}[]()&*^!@\"'`\\/#_1",
|
||||||
|
"comment": "Comment for create",
|
||||||
|
"fillfactor": "12",
|
||||||
|
"amname": "gist",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"column": "col2",
|
||||||
|
"order": false,
|
||||||
|
"nulls_order": false,
|
||||||
|
"operator": "<>",
|
||||||
|
"is_sort_nulls_applicable": false,
|
||||||
|
"is_exp": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"column": "(col1+col3)",
|
||||||
|
"order": false,
|
||||||
|
"nulls_order": false,
|
||||||
|
"operator": "<>",
|
||||||
|
"is_sort_nulls_applicable": false,
|
||||||
|
"is_exp": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expected_sql_file": "create_exclusion_constraint_exp.sql"
|
||||||
|
}, {
|
||||||
|
"type": "delete",
|
||||||
|
"name": "Drop Exclusion Constraint",
|
||||||
|
"endpoint": "NODE-exclusion_constraint.delete_id",
|
||||||
|
"data": {
|
||||||
|
"name": "Exclusion_$%{}[]()&*^!@\"'`\\/#_1a"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
-- Constraint: Exclusion_$%{}[]()&*^!@"'`\/#
|
||||||
|
|
||||||
|
-- ALTER TABLE testschema.tableforexclusion DROP CONSTRAINT "Exclusion_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
ALTER TABLE testschema.tableforexclusion
|
||||||
|
ADD CONSTRAINT "Exclusion_$%{}[]()&*^!@""'`\/#" EXCLUDE USING gist (
|
||||||
|
(col1 + col3) WITH <>,
|
||||||
|
col2 WITH <>)
|
||||||
|
WITH (FILLFACTOR=12)
|
||||||
|
WHERE (col1 > 1)
|
||||||
|
DEFERRABLE INITIALLY DEFERRED;
|
||||||
|
|
||||||
|
COMMENT ON CONSTRAINT "Exclusion_$%{}[]()&*^!@""'`\/#" ON testschema.tableforexclusion
|
||||||
|
IS 'Comment for create';
|
@ -14,6 +14,9 @@
|
|||||||
}, {
|
}, {
|
||||||
"name": "col2",
|
"name": "col2",
|
||||||
"cltype": "text"
|
"cltype": "text"
|
||||||
|
}, {
|
||||||
|
"name": "col3",
|
||||||
|
"cltype": "integer",
|
||||||
}],
|
}],
|
||||||
"is_partitioned": false,
|
"is_partitioned": false,
|
||||||
"schema": "testschema",
|
"schema": "testschema",
|
||||||
@ -49,7 +52,8 @@
|
|||||||
"order": false,
|
"order": false,
|
||||||
"nulls_order": false,
|
"nulls_order": false,
|
||||||
"operator": "<>",
|
"operator": "<>",
|
||||||
"is_sort_nulls_applicable": false
|
"is_sort_nulls_applicable": false,
|
||||||
|
"is_exp": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -90,7 +94,8 @@
|
|||||||
"order": false,
|
"order": false,
|
||||||
"nulls_order": false,
|
"nulls_order": false,
|
||||||
"operator": "<>",
|
"operator": "<>",
|
||||||
"is_sort_nulls_applicable": false
|
"is_sort_nulls_applicable": false,
|
||||||
|
"is_exp": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -115,6 +120,43 @@
|
|||||||
"data": {
|
"data": {
|
||||||
"name": "Exclusion_$%{}[]()&*^!@\"'`\\/#_1a"
|
"name": "Exclusion_$%{}[]()&*^!@\"'`\\/#_1a"
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create Exclusion Constraint with expressions",
|
||||||
|
"endpoint": "NODE-exclusion_constraint.obj",
|
||||||
|
"sql_endpoint": "NODE-exclusion_constraint.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "Exclusion_$%{}[]()&*^!@\"'`\\/#_1",
|
||||||
|
"comment": "Comment for create",
|
||||||
|
"fillfactor": "12",
|
||||||
|
"amname": "gist",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"column": "col2",
|
||||||
|
"order": false,
|
||||||
|
"nulls_order": false,
|
||||||
|
"operator": "<>",
|
||||||
|
"is_sort_nulls_applicable": false,
|
||||||
|
"is_exp": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"column": "(col1+col3)",
|
||||||
|
"order": false,
|
||||||
|
"nulls_order": false,
|
||||||
|
"operator": "<>",
|
||||||
|
"is_sort_nulls_applicable": false,
|
||||||
|
"is_exp": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expected_sql_file": "create_exclusion_constraint_exp.sql"
|
||||||
|
}, {
|
||||||
|
"type": "delete",
|
||||||
|
"name": "Drop Exclusion Constraint",
|
||||||
|
"endpoint": "NODE-exclusion_constraint.delete_id",
|
||||||
|
"data": {
|
||||||
|
"name": "Exclusion_$%{}[]()&*^!@\"'`\\/#_1a"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,8 @@ def _get_columns(res):
|
|||||||
"order": order,
|
"order": order,
|
||||||
"nulls_order": nulls_order,
|
"nulls_order": nulls_order,
|
||||||
"operator": row['oprname'],
|
"operator": row['oprname'],
|
||||||
"col_type": row['datatype']
|
"col_type": row['datatype'],
|
||||||
|
"is_exp": row['is_exp']
|
||||||
})
|
})
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
@ -127,6 +128,9 @@ def get_exclusion_constraints(conn, did, tid, exid=None, template_path=None):
|
|||||||
|
|
||||||
ex['include'] = [col['colname'] for col in res['rows']]
|
ex['include'] = [col['colname'] for col in res['rows']]
|
||||||
|
|
||||||
|
if ex.get('amname', '') == "":
|
||||||
|
ex['amname'] = 'btree'
|
||||||
|
|
||||||
return True, result['rows']
|
return True, result['rows']
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
|
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 %} (
|
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 %},
|
{% 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 is defined and col.is_sort_nulls_applicable %}{% if col.order %} ASC{% else %} DESC{% endif %} NULLS{% endif %} {% if col.nulls_order is defined and col.is_sort_nulls_applicable %}{% if col.nulls_order %}FIRST {% else %}LAST {% endif %}{% endif %}WITH {{col.operator}}{% endfor %}){% if data.include|length > 0 %}
|
{% endif %}{% if col.is_exp %}{{col.column}}{% else %}{{ conn|qtIdent(col.column)}}{% endif %}{% if col.oper_class and col.oper_class != '' %} {{col.oper_class}}{% endif%}{% if col.order is defined and col.is_sort_nulls_applicable %}{% if col.order %} ASC{% else %} DESC{% endif %} NULLS{% endif %} {% if col.nulls_order is defined and col.is_sort_nulls_applicable %}{% if col.nulls_order %}FIRST {% else %}LAST {% endif %}{% endif %}WITH {{col.operator}}{% endfor %}){% if data.include|length > 0 %}
|
||||||
|
|
||||||
INCLUDE ({% for col in data.include %}{% if loop.index != 1 %}, {% endif %}{{conn|qtIdent(col)}}{% endfor %}){% endif %}{% if data.fillfactor %}
|
INCLUDE ({% for col in data.include %}{% if loop.index != 1 %}, {% endif %}{{conn|qtIdent(col)}}{% endfor %}){% endif %}{% if data.fillfactor %}
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@ SELECT
|
|||||||
,
|
,
|
||||||
coll.collname,
|
coll.collname,
|
||||||
nspc.nspname as collnspname,
|
nspc.nspname as collnspname,
|
||||||
format_type(ty.oid,NULL) AS datatype
|
format_type(ty.oid,NULL) AS datatype,
|
||||||
|
CASE WHEN pg_get_indexdef(i.indexrelid, {{loop.index}}, true) = a.attname THEN FALSE ELSE TRUE END AS is_exp
|
||||||
FROM pg_index i
|
FROM pg_index i
|
||||||
JOIN pg_attribute a ON (a.attrelid = i.indexrelid AND attnum = {{loop.index}})
|
JOIN pg_attribute a ON (a.attrelid = i.indexrelid AND attnum = {{loop.index}})
|
||||||
JOIN pg_type ty ON ty.oid=a.atttypid
|
JOIN pg_type ty ON ty.oid=a.atttypid
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
{% if type is not none %}
|
||||||
SELECT DISTINCT op.oprname as oprname
|
SELECT DISTINCT op.oprname as oprname
|
||||||
FROM pg_operator op,
|
FROM pg_operator op,
|
||||||
( SELECT oid
|
( SELECT oid
|
||||||
@ -28,3 +29,8 @@ FROM pg_operator op,
|
|||||||
WHERE typname = {{type|qtLiteral}}) AS types
|
WHERE typname = {{type|qtLiteral}}) AS types
|
||||||
WHERE oprcom > 0 AND
|
WHERE oprcom > 0 AND
|
||||||
(op.oprleft=types.oid OR op.oprright=types.oid)
|
(op.oprleft=types.oid OR op.oprright=types.oid)
|
||||||
|
{% else %}
|
||||||
|
SELECT DISTINCT op.oprname as oprname
|
||||||
|
FROM pg_operator op
|
||||||
|
WHERE oprcom > 0
|
||||||
|
{% endif %}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
|
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 %} (
|
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 %},
|
{% 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 is defined and col.is_sort_nulls_applicable %}{% if col.order %} ASC{% else %} DESC{% endif %} NULLS{% endif %} {% if col.nulls_order is defined and col.is_sort_nulls_applicable %}{% if col.nulls_order %}FIRST {% else %}LAST {% endif %}{% endif %}WITH {{col.operator}}{% endfor %}){% if data.fillfactor %}
|
{% endif %}{% if col.is_exp %}{{col.column}}{% else %}{{ conn|qtIdent(col.column)}}{% endif %}{% if col.oper_class and col.oper_class != '' %} {{col.oper_class}}{% endif%}{% if col.order is defined and col.is_sort_nulls_applicable %}{% if col.order %} ASC{% else %} DESC{% endif %} NULLS{% endif %} {% if col.nulls_order is defined and col.is_sort_nulls_applicable %}{% if col.nulls_order %}FIRST {% else %}LAST {% endif %}{% endif %}WITH {{col.operator}}{% endfor %}){% if data.fillfactor %}
|
||||||
|
|
||||||
WITH (FILLFACTOR={{data.fillfactor}}){% endif %}{% if data.spcname and data.spcname != "pg_default" %}
|
WITH (FILLFACTOR={{data.fillfactor}}){% endif %}{% if data.spcname and data.spcname != "pg_default" %}
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@ SELECT
|
|||||||
,
|
,
|
||||||
coll.collname,
|
coll.collname,
|
||||||
nspc.nspname as collnspname,
|
nspc.nspname as collnspname,
|
||||||
format_type(ty.oid,NULL) AS col_type
|
format_type(ty.oid,NULL) AS datatype,
|
||||||
|
CASE WHEN pg_get_indexdef(i.indexrelid, {{loop.index}}, true) = a.attname THEN FALSE ELSE TRUE END AS is_exp
|
||||||
FROM pg_index i
|
FROM pg_index i
|
||||||
JOIN pg_attribute a ON (a.attrelid = i.indexrelid AND attnum = {{loop.index}})
|
JOIN pg_attribute a ON (a.attrelid = i.indexrelid AND attnum = {{loop.index}})
|
||||||
JOIN pg_type ty ON ty.oid=a.atttypid
|
JOIN pg_type ty ON ty.oid=a.atttypid
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
{% if type is not none %}
|
||||||
SELECT DISTINCT op.oprname as oprname
|
SELECT DISTINCT op.oprname as oprname
|
||||||
FROM pg_operator op,
|
FROM pg_operator op,
|
||||||
( SELECT oid
|
( SELECT oid
|
||||||
@ -27,3 +28,8 @@ FROM pg_operator op,
|
|||||||
WHERE typname = {{type|qtLiteral}}) AS types
|
WHERE typname = {{type|qtLiteral}}) AS types
|
||||||
WHERE oprcom > 0 AND
|
WHERE oprcom > 0 AND
|
||||||
(op.oprleft=types.oid OR op.oprright=types.oid)
|
(op.oprleft=types.oid OR op.oprright=types.oid)
|
||||||
|
{% else %}
|
||||||
|
SELECT DISTINCT op.oprname as oprname
|
||||||
|
FROM pg_operator op
|
||||||
|
WHERE oprcom > 0
|
||||||
|
{% endif %}
|
||||||
|
@ -259,9 +259,13 @@ define([
|
|||||||
*/
|
*/
|
||||||
_.extend(
|
_.extend(
|
||||||
Backform.InputControl.prototype, {
|
Backform.InputControl.prototype, {
|
||||||
|
defaults: _.extend(Backform.InputControl.prototype.defaults, {
|
||||||
|
controlLabelClassName: Backform.controlLabelClassName,
|
||||||
|
controlsClassName: Backform.controlsClassName,
|
||||||
|
}),
|
||||||
template: _.template([
|
template: _.template([
|
||||||
'<label class="<%=Backform.controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
|
'<label class="<%=controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
|
||||||
'<div class="<%=Backform.controlContainerClassName%>">',
|
'<div class="<%=controlsClassName%>">',
|
||||||
' <input type="<%=type%>" id="<%=cId%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" maxlength="<%=maxlength%>" value="<%-value%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%> <%=required ? "required" : ""%> />',
|
' <input type="<%=type%>" id="<%=cId%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" maxlength="<%=maxlength%>" value="<%-value%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%> <%=required ? "required" : ""%> />',
|
||||||
' <% if (helpMessage && helpMessage.length) { %>',
|
' <% if (helpMessage && helpMessage.length) { %>',
|
||||||
' <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
|
' <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
|
||||||
|
Loading…
Reference in New Issue
Block a user