mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-25 10:10:19 -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
|
||||
:align: center
|
||||
|
||||
Use the fields in the *Columns* tab to to specify the column(s) to which the
|
||||
constraint applies. Use the drop-down listbox next to *Column* to select a
|
||||
column and click the *Add* icon (+) to provide details of the action on the
|
||||
column:
|
||||
Use the fields in the *Columns* tab to specify the column(s) or expression(s)
|
||||
to which the constraint applies. Use the *Is expression ?* switch to enable
|
||||
expression text input. Use the drop-down listbox next to *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*
|
||||
drop-down listbox.
|
||||
* The *Col/Exp* field is populated with the selection made in the *Column*
|
||||
drop-down listbox or the *Expression* entered.
|
||||
* 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.
|
||||
* 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
|
||||
*********
|
||||
|
||||
| `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 #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.
|
||||
|
@ -560,17 +560,16 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings,
|
||||
Returns:
|
||||
|
||||
"""
|
||||
data = request.args if request.args else None
|
||||
data = request.args
|
||||
try:
|
||||
if data and 'col_type' in data:
|
||||
result = exclusion_utils.get_operator(
|
||||
self.conn, data['col_type'],
|
||||
self.blueprint.show_system_objects)
|
||||
result = exclusion_utils.get_operator(
|
||||
self.conn, data.get('col_type', None),
|
||||
self.blueprint.show_system_objects)
|
||||
|
||||
return make_json_response(
|
||||
data=result,
|
||||
status=200
|
||||
)
|
||||
return make_json_response(
|
||||
data=result,
|
||||
status=200
|
||||
)
|
||||
except Exception as e:
|
||||
return internal_server_error(errormsg=str(e))
|
||||
|
||||
|
@ -778,58 +778,18 @@ class ExclusionConstraintView(PGChildNodeView):
|
||||
|
||||
"""
|
||||
try:
|
||||
SQL = render_template(
|
||||
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
||||
did=did, tid=tid, conn=self.conn, cid=exid)
|
||||
status, result = self.conn.execute_dict(SQL)
|
||||
status, rows = exclusion_utils.get_exclusion_constraints(
|
||||
self.conn, did, tid, exid, template_path=self.template_path
|
||||
)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=result)
|
||||
if len(result['rows']) == 0:
|
||||
return rows
|
||||
if len(rows) == 0:
|
||||
return gone(_("Could not find the exclusion constraint."))
|
||||
|
||||
data = result['rows'][0]
|
||||
data = rows[0]
|
||||
data['schema'] = self.schema
|
||||
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(
|
||||
"/".join([self.template_path, self._CREATE_SQL]), data=data)
|
||||
|
||||
|
@ -19,6 +19,7 @@ define('pgadmin.node.exclusion_constraint', [
|
||||
var ExclusionConstraintColumnModel = pgBrowser.Node.Model.extend({
|
||||
defaults: {
|
||||
column: undefined,
|
||||
is_exp: false,
|
||||
oper_class: undefined,
|
||||
order: false,
|
||||
nulls_order: false,
|
||||
@ -32,8 +33,20 @@ define('pgadmin.node.exclusion_constraint', [
|
||||
return d;
|
||||
},
|
||||
schema: [{
|
||||
id: 'column', label: gettext('Column'), type:'text', editable: false,
|
||||
id: 'column', label: gettext('Col/Exp'), type:'text', editable: false,
|
||||
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',
|
||||
node: 'table', url: 'get_oper_class', first_empty: true,
|
||||
@ -175,7 +188,7 @@ define('pgadmin.node.exclusion_constraint', [
|
||||
|
||||
self.column.set('options', []);
|
||||
|
||||
if (url && !_.isUndefined(col_type) && !_.isNull(col_type) && col_type != '') {
|
||||
if (url) {
|
||||
var node = this.column.get('schema_node'),
|
||||
eventHandler = m.top || m,
|
||||
node_info = this.column.get('node_info'),
|
||||
@ -210,9 +223,11 @@ define('pgadmin.node.exclusion_constraint', [
|
||||
validate: function() {
|
||||
this.errorModel.clear();
|
||||
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)) {
|
||||
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);
|
||||
return msg;
|
||||
}
|
||||
@ -231,8 +246,15 @@ define('pgadmin.node.exclusion_constraint', [
|
||||
var self = this,
|
||||
node = 'exclusion_constraint',
|
||||
headerSchema = [{
|
||||
id: 'column', label:'', type:'text',
|
||||
node: 'column', control: Backform.NodeListByNameControl.extend({
|
||||
id: 'is_exp', label: gettext('Is expression ?'), type: 'switch',
|
||||
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() {
|
||||
// Here we will decide if we need to call URL
|
||||
// Or fetch the data from parent columns collection
|
||||
@ -310,7 +332,8 @@ define('pgadmin.node.exclusion_constraint', [
|
||||
}
|
||||
},
|
||||
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" : ""%> >',
|
||||
' <% for (var i=0; i < options.length; i++) { %>',
|
||||
' <% var option = options[i]; %>',
|
||||
@ -363,10 +386,21 @@ define('pgadmin.node.exclusion_constraint', [
|
||||
readonly: function() {
|
||||
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({
|
||||
defaults: headerDefaults,
|
||||
@ -396,22 +430,16 @@ define('pgadmin.node.exclusion_constraint', [
|
||||
},
|
||||
|
||||
generateHeader: function(data) {
|
||||
var isNew = _.isUndefined(this.model.get('oid'));
|
||||
var header = [
|
||||
'<div class="subnode-header-form">',
|
||||
'<div class="subnode-header-form '+ (isNew ? '' : 'd-none') +'">',
|
||||
' <div>',
|
||||
' <div class="row">',
|
||||
' <div class="col-4">',
|
||||
' <label class="control-label"><%-column_label%></label>',
|
||||
' </div>',
|
||||
' <div class="col-4" header="column"></div>',
|
||||
' </div>',
|
||||
' <div header="is_exp"></div>',
|
||||
' <div header="column"></div>',
|
||||
' <div header="exp"></div>',
|
||||
' </div>',
|
||||
'</div>'].join('\n');
|
||||
|
||||
_.extend(data, {
|
||||
column_label: gettext('Column'),
|
||||
});
|
||||
|
||||
var self = this,
|
||||
headerTmpl = _.template(header),
|
||||
$header = $(headerTmpl(data)),
|
||||
@ -514,20 +542,24 @@ define('pgadmin.node.exclusion_constraint', [
|
||||
}
|
||||
|
||||
if (self.control_data.canAdd) {
|
||||
self.collection.each(function(m) {
|
||||
if (!inSelected) {
|
||||
_.each(checkVars, function(v) {
|
||||
if (!inSelected) {
|
||||
val = m.get(v);
|
||||
inSelected = ((
|
||||
(_.isUndefined(val) || _.isNull(val)) &&
|
||||
(_.isUndefined(data[v]) || _.isNull(data[v]))
|
||||
) ||
|
||||
(val == data[v]));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if(data['is_exp']) {
|
||||
inSelected = false;
|
||||
} else {
|
||||
self.collection.each(function(m) {
|
||||
if (!inSelected) {
|
||||
_.each(checkVars, function(v) {
|
||||
if (!inSelected) {
|
||||
val = m.get(v);
|
||||
inSelected = ((
|
||||
(_.isUndefined(val) || _.isNull(val)) &&
|
||||
(_.isUndefined(data[v]) || _.isNull(data[v]))
|
||||
) ||
|
||||
(val == data[v]));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
inSelected = true;
|
||||
@ -538,23 +570,28 @@ define('pgadmin.node.exclusion_constraint', [
|
||||
|
||||
addColumns: function(ev) {
|
||||
ev.preventDefault();
|
||||
var self = this,
|
||||
column = self.headerData.get('column');
|
||||
var self = this;
|
||||
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')),
|
||||
m = new (self.field.get('model'))(
|
||||
self.headerData.toJSON(), {
|
||||
newHeaderData, {
|
||||
silent: true, top: self.model.top,
|
||||
collection: coll, handler: coll,
|
||||
}),
|
||||
col_types =self.field.get('col_types') || [];
|
||||
|
||||
for(var i=0; i < col_types.length; i++) {
|
||||
var col_type = col_types[i];
|
||||
if (col_type['name'] == m.get('column')) {
|
||||
m.set({'col_type':col_type['type']});
|
||||
break;
|
||||
if(!m.get('is_exp')) {
|
||||
for(var i=0; i < col_types.length; i++) {
|
||||
var col_type = col_types[i];
|
||||
if (col_type['name'] == m.get('column')) {
|
||||
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()));
|
||||
},
|
||||
},{
|
||||
id: 'columns', label: gettext('Columns'),
|
||||
id: 'columns', label: gettext('Columns/Expressions'),
|
||||
type: 'collection', group: gettext('Columns'),
|
||||
deps:['amname'], canDelete: true, editable: false,
|
||||
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",
|
||||
"cltype": "text"
|
||||
}, {
|
||||
"name": "col3",
|
||||
"cltype": "integer",
|
||||
}],
|
||||
"is_partitioned": false,
|
||||
"schema": "testschema",
|
||||
@ -76,6 +79,43 @@
|
||||
"data": {
|
||||
"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",
|
||||
"cltype": "text"
|
||||
}, {
|
||||
"name": "col3",
|
||||
"cltype": "integer",
|
||||
}],
|
||||
"is_partitioned": false,
|
||||
"schema": "testschema",
|
||||
@ -49,7 +52,8 @@
|
||||
"order": false,
|
||||
"nulls_order": false,
|
||||
"operator": "<>",
|
||||
"is_sort_nulls_applicable": false
|
||||
"is_sort_nulls_applicable": false,
|
||||
"is_exp": false
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -90,7 +94,8 @@
|
||||
"order": false,
|
||||
"nulls_order": false,
|
||||
"operator": "<>",
|
||||
"is_sort_nulls_applicable": false
|
||||
"is_sort_nulls_applicable": false,
|
||||
"is_exp": false
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -115,6 +120,43 @@
|
||||
"data": {
|
||||
"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,
|
||||
"nulls_order": nulls_order,
|
||||
"operator": row['oprname'],
|
||||
"col_type": row['datatype']
|
||||
"col_type": row['datatype'],
|
||||
"is_exp": row['is_exp']
|
||||
})
|
||||
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']]
|
||||
|
||||
if ex.get('amname', '') == "":
|
||||
ex['amname'] = 'btree'
|
||||
|
||||
return True, result['rows']
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
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 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 %}
|
||||
|
||||
|
@ -10,7 +10,8 @@ SELECT
|
||||
,
|
||||
coll.collname,
|
||||
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
|
||||
JOIN pg_attribute a ON (a.attrelid = i.indexrelid AND attnum = {{loop.index}})
|
||||
JOIN pg_type ty ON ty.oid=a.atttypid
|
||||
@ -19,4 +20,4 @@ LEFT OUTER JOIN pg_constraint c ON (c.conindid = i.indexrelid) LEFT OUTER JOIN p
|
||||
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 %}
|
||||
{% endfor %}
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% if type is not none %}
|
||||
SELECT DISTINCT op.oprname as oprname
|
||||
FROM pg_operator op,
|
||||
( SELECT oid
|
||||
@ -27,4 +28,9 @@ FROM pg_operator op,
|
||||
UNION SELECT 'serial', 0) t1
|
||||
WHERE typname = {{type|qtLiteral}}) AS types
|
||||
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) }}
|
||||
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 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" %}
|
||||
|
||||
|
@ -10,7 +10,8 @@ SELECT
|
||||
,
|
||||
coll.collname,
|
||||
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
|
||||
JOIN pg_attribute a ON (a.attrelid = i.indexrelid AND attnum = {{loop.index}})
|
||||
JOIN pg_type ty ON ty.oid=a.atttypid
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% if type is not none %}
|
||||
SELECT DISTINCT op.oprname as oprname
|
||||
FROM pg_operator op,
|
||||
( SELECT oid
|
||||
@ -26,4 +27,9 @@ FROM pg_operator op,
|
||||
UNION SELECT 'serial', 0) t1
|
||||
WHERE typname = {{type|qtLiteral}}) AS types
|
||||
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(
|
||||
Backform.InputControl.prototype, {
|
||||
defaults: _.extend(Backform.InputControl.prototype.defaults, {
|
||||
controlLabelClassName: Backform.controlLabelClassName,
|
||||
controlsClassName: Backform.controlsClassName,
|
||||
}),
|
||||
template: _.template([
|
||||
'<label class="<%=Backform.controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
|
||||
'<div class="<%=Backform.controlContainerClassName%>">',
|
||||
'<label class="<%=controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
|
||||
'<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" : ""%> />',
|
||||
' <% if (helpMessage && helpMessage.length) { %>',
|
||||
' <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
|
||||
|
Loading…
Reference in New Issue
Block a user