Add support for foreign server
parent
fcc3d112e2
commit
d1e2b902dc
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 492 B |
Binary file not shown.
After Width: | Height: | Size: 563 B |
|
@ -0,0 +1,751 @@
|
|||
/* Create and Register Foreign Table Collection and Node. */
|
||||
define(
|
||||
['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'],
|
||||
function($, _, S, pgAdmin, pgBrowser, alertify) {
|
||||
|
||||
if (!pgBrowser.Nodes['coll-foreign-table']) {
|
||||
var foreigntable = pgAdmin.Browser.Nodes['coll-foreign-table'] =
|
||||
pgAdmin.Browser.Collection.extend({
|
||||
node: 'foreign-table',
|
||||
label: '{{ _('Foreign Tables') }}',
|
||||
type: 'coll-foreign-table',
|
||||
columns: ['name', 'owner', 'description']
|
||||
});
|
||||
};
|
||||
|
||||
// Security Model
|
||||
var SecurityModel = Backform.SecurityModel = pgAdmin.Browser.Node.Model.extend({
|
||||
defaults: {
|
||||
provider: null,
|
||||
label: null
|
||||
},
|
||||
schema: [{
|
||||
id: 'provider', label: '{{ _('Provider') }}',
|
||||
type: 'text', editable: true, cellHeaderClasses:'width_percent_50'
|
||||
},{
|
||||
id: 'security_label', label: '{{ _('Security Label') }}',
|
||||
type: 'text', editable: true, cellHeaderClasses:'width_percent_50'
|
||||
}],
|
||||
validate: function() {
|
||||
var err = {},
|
||||
errmsg = null,
|
||||
data = this.toJSON();
|
||||
|
||||
if (_.isUndefined(data.security_label) ||
|
||||
_.isNull(data.security_label) ||
|
||||
String(data.security_label).replace(/^\s+|\s+$/g, '') == '') {
|
||||
return _("Please specify the value for all the security providers.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Integer Cell for Columns Length and Precision
|
||||
var IntegerDepCell = Backgrid.IntegerCell.extend({
|
||||
initialize: function() {
|
||||
Backgrid.NumberCell.prototype.initialize.apply(this, arguments);
|
||||
Backgrid.Extension.DependentCell.prototype.initialize.apply(this, arguments);
|
||||
},
|
||||
dependentChanged: function () {
|
||||
this.$el.empty();
|
||||
var model = this.model;
|
||||
var column = this.column;
|
||||
editable = this.column.get("editable");
|
||||
|
||||
is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
|
||||
if (is_editable){ this.$el.addClass("editable"); }
|
||||
else { this.$el.removeClass("editable"); }
|
||||
|
||||
this.delegateEvents();
|
||||
return this;
|
||||
},
|
||||
remove: Backgrid.Extension.DependentCell.prototype.remove
|
||||
});
|
||||
|
||||
|
||||
// Columns Model
|
||||
var ColumnsModel = pgAdmin.Browser.Node.Model.extend({
|
||||
idAttribute: 'attnum',
|
||||
defaults: {
|
||||
attname: undefined,
|
||||
datatype: undefined,
|
||||
typlen: undefined,
|
||||
precision: undefined,
|
||||
typdefault: undefined,
|
||||
attnotnull: undefined,
|
||||
collname: undefined,
|
||||
attnum: undefined,
|
||||
inheritedfrom: undefined,
|
||||
inheritedid: undefined,
|
||||
attstattarget: undefined
|
||||
},
|
||||
type_options: undefined,
|
||||
schema: [{
|
||||
id: 'attname', label:'{{ _('Name') }}', cell: 'string', type: 'text',
|
||||
editable: 'is_editable_column', cellHeaderClasses: 'width_percent_20'
|
||||
},{
|
||||
id: 'datatype', label:'{{ _('Data Type') }}', cell: 'node-ajax-options',
|
||||
control: 'node-ajax-options', type: 'text', url: 'get_types',
|
||||
editable: 'is_editable_column', cellHeaderClasses: 'width_percent_20',
|
||||
transform: function(d, self){
|
||||
self.model.type_options = d;
|
||||
return d;
|
||||
}
|
||||
},{
|
||||
id: 'typlen', label:'{{ _('Length') }}',
|
||||
cell: IntegerDepCell,
|
||||
type: 'text', deps: ['datatype'],
|
||||
editable: function(m) {
|
||||
// We will store type from selected from combobox
|
||||
if(!(_.isUndefined(m.get('inheritedid'))
|
||||
|| _.isNull(m.get('inheritedid'))
|
||||
|| _.isUndefined(m.get('inheritedfrom'))
|
||||
|| _.isNull(m.get('inheritedfrom')))) { return false; }
|
||||
|
||||
var of_type = m.get('datatype');
|
||||
if(m.type_options) {
|
||||
m.set('is_tlength', false, {silent: true});
|
||||
|
||||
// iterating over all the types
|
||||
_.each(m.type_options, function(o) {
|
||||
// if type from selected from combobox matches in options
|
||||
if ( of_type == o.value ) {
|
||||
m.set('typlen', undefined);
|
||||
// if length is allowed for selected type
|
||||
if(o.length)
|
||||
{
|
||||
// set the values in model
|
||||
m.set('is_tlength', true, {silent: true});
|
||||
m.set('min_val', o.min_val, {silent: true});
|
||||
m.set('max_val', o.max_val, {silent: true});
|
||||
}
|
||||
}
|
||||
});
|
||||
return m.get('is_tlength');
|
||||
}
|
||||
return true;
|
||||
},
|
||||
cellHeaderClasses: 'width_percent_10'
|
||||
},{
|
||||
id: 'precision', label:'{{ _('Precision') }}',
|
||||
type: 'text', deps: ['datatype'],
|
||||
cell: IntegerDepCell,
|
||||
editable: function(m) {
|
||||
if(!(_.isUndefined(m.get('inheritedid'))
|
||||
|| _.isNull(m.get('inheritedid'))
|
||||
|| _.isUndefined(m.get('inheritedfrom'))
|
||||
|| _.isNull(m.get('inheritedfrom')))) { return false; }
|
||||
|
||||
var of_type = m.get('datatype');
|
||||
if(m.type_options) {
|
||||
m.set('is_precision', false, {silent: true});
|
||||
// iterating over all the types
|
||||
_.each(m.type_options, function(o) {
|
||||
// if type from selected from combobox matches in options
|
||||
if ( of_type == o.value ) {
|
||||
m.set('precision', undefined);
|
||||
// if precession is allowed for selected type
|
||||
if(o.precision)
|
||||
{
|
||||
// set the values in model
|
||||
m.set('is_precision', true, {silent: true});
|
||||
m.set('min_val', o.min_val, {silent: true});
|
||||
m.set('max_val', o.max_val, {silent: true});
|
||||
}
|
||||
}
|
||||
});
|
||||
return m.get('is_precision');
|
||||
}
|
||||
return true;
|
||||
}, cellHeaderClasses: 'width_percent_10'
|
||||
},{
|
||||
id: 'typdefault', label:'{{ _('Default') }}', type: 'text',
|
||||
cell: 'string', min_version: 90300,
|
||||
placeholder: "Enter an expression or a value.",
|
||||
cellHeaderClasses: 'width_percent_10',
|
||||
editable: function(m) {
|
||||
if(!(_.isUndefined(m.get('inheritedid'))
|
||||
|| _.isNull(m.get('inheritedid'))
|
||||
|| _.isUndefined(m.get('inheritedfrom'))
|
||||
|| _.isNull(m.get('inheritedfrom')))) { return false; }
|
||||
if (this.get('node_info').server.version < 90300){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},{
|
||||
id: 'attnotnull', label:'{{ _('Not Null') }}',
|
||||
cell: 'boolean',type: 'switch', editable: 'is_editable_column',
|
||||
cellHeaderClasses: 'width_percent_10'
|
||||
},{
|
||||
id: 'attstattarget', label:'{{ _('Statistics') }}', min_version: 90200,
|
||||
cell: 'integer', type: 'int', editable: function(m) {
|
||||
if (_.isUndefined(m.isNew) || m.isNew()) { return false; }
|
||||
if (this.get('node_info').server.version < 90200){
|
||||
return false;
|
||||
}
|
||||
return (_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid'))
|
||||
|| _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false
|
||||
}, cellHeaderClasses: 'width_percent_10'
|
||||
},{
|
||||
id: 'collname', label:'{{ _('Collation') }}', cell: 'node-ajax-options',
|
||||
control: 'node-ajax-options', type: 'text', url: 'get_collations',
|
||||
min_version: 90300, editable: function(m) {
|
||||
if (!(_.isUndefined(m.isNew)) && !m.isNew()) { return false; }
|
||||
return (_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid'))
|
||||
|| _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false
|
||||
},
|
||||
cellHeaderClasses: 'width_percent_20'
|
||||
},{
|
||||
id: 'attnum', cell: 'string',type: 'text', visible: false
|
||||
},{
|
||||
id: 'inheritedfrom', label:'{{ _('Inherited From') }}', cell: 'string',
|
||||
type: 'text', visible: false, mode: ['properties', 'edit'],
|
||||
cellHeaderClasses: 'width_percent_10'
|
||||
}],
|
||||
validate: function() {
|
||||
var err = {},
|
||||
errmsg;
|
||||
|
||||
if (_.isUndefined(this.get('attname')) || String(this.get('attname')).replace(/^\s+|\s+$/g, '') == '') {
|
||||
err['name'] = '{{ _('Column Name can not be empty!') }}';
|
||||
errmsg = errmsg || err['attname'];
|
||||
}
|
||||
|
||||
if (_.isUndefined(this.get('datatype')) || String(this.get('datatype'))
|
||||
.replace(/^\s+|\s+$/g, '') == '') {
|
||||
err['basensp'] = '{{ _('Column Datatype can not be empty!') }}';
|
||||
errmsg = errmsg || err['datatype'];
|
||||
}
|
||||
|
||||
this.errorModel.clear().set(err);
|
||||
|
||||
return errmsg;
|
||||
},
|
||||
is_editable_column: function(m) {
|
||||
return (_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid'))
|
||||
|| _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false
|
||||
},
|
||||
toJSON: Backbone.Model.prototype.toJSON
|
||||
});
|
||||
|
||||
var formatNode = function(opt) {
|
||||
if (!opt.id) {
|
||||
return opt.text;
|
||||
}
|
||||
|
||||
var optimage = $(opt.element).data('image');
|
||||
|
||||
if(!optimage){
|
||||
return opt.text;
|
||||
} else {
|
||||
return $(
|
||||
'<span><span class="wcTabIcon ' + optimage + '"/>' + opt.text + '</span>'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* NodeAjaxOptionsMultipleControl is for multiple selection of Combobox.
|
||||
* This control is used to select Multiple Parent Tables to be inherited.
|
||||
* It also populates/vacates Columns on selection/deselection of the option (i.e. table name).
|
||||
* To populates the column, it calls the server and fetch the columns data
|
||||
* for the selected table.
|
||||
*/
|
||||
|
||||
var NodeAjaxOptionsMultipleControl = Backform.NodeAjaxOptionsMultipleControl = Backform.NodeAjaxOptionsControl.extend({
|
||||
template: _.template([
|
||||
'<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
|
||||
'<div class="<%=Backform.controlsClassName%> <%=extraClasses.join(\' \')%>">',
|
||||
' <select class="pgadmin-node-select form-control" name="<%=name%>" style="width:100%;" value=<%-value%> <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> >',
|
||||
' </select>',
|
||||
'</div>'].join("\n")),
|
||||
defaults: _.extend(
|
||||
{}, Backform.NodeAjaxOptionsControl.prototype.defaults,
|
||||
{
|
||||
select2: {
|
||||
allowClear: true,
|
||||
placeholder: 'Select from the list',
|
||||
width: 'style',
|
||||
templateResult: formatNode,
|
||||
templateSelection: formatNode
|
||||
}
|
||||
}),
|
||||
render: function() {
|
||||
var field = _.defaults(this.field.toJSON(), this.defaults),
|
||||
attributes = this.model.toJSON(),
|
||||
attrArr = field.name.split('.'),
|
||||
name = attrArr.shift(),
|
||||
path = attrArr.join('.'),
|
||||
rawValue = this.keyPathAccessor(attributes[name], path),
|
||||
data = _.extend(field, {
|
||||
rawValue: rawValue,
|
||||
value: this.formatter.fromRaw(rawValue, this.model),
|
||||
attributes: attributes,
|
||||
formatter: this.formatter
|
||||
}),
|
||||
evalF = function(f, d, m) {
|
||||
return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
|
||||
};
|
||||
|
||||
// Evaluate the disabled, visible, and required option
|
||||
_.extend(data, {
|
||||
disabled: evalF(data.disabled, data, this.model),
|
||||
visible: evalF(data.visible, data, this.model),
|
||||
required: evalF(data.required, data, this.model)
|
||||
});
|
||||
|
||||
if (field.node_info.server.version < field.min_version) {
|
||||
field.version_compatible = false
|
||||
return this;
|
||||
}
|
||||
else {
|
||||
// Evaluation the options
|
||||
if (_.isFunction(data.options)) {
|
||||
try {
|
||||
data.options = data.options.apply(this)
|
||||
} catch(e) {
|
||||
// Do nothing
|
||||
data.options = []
|
||||
this.model.trigger('pgadmin-view:transform:error', self.model, self.field, e);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up first
|
||||
this.$el.removeClass(Backform.hiddenClassname);
|
||||
this.$el.html(this.template(data)).addClass(field.name);
|
||||
|
||||
if (!data.visible) {
|
||||
this.$el.addClass(Backform.hiddenClassname);
|
||||
} else {
|
||||
var opts = _.extend(
|
||||
{}, this.defaults.select2, data.select2,
|
||||
{
|
||||
'data': data.options
|
||||
});
|
||||
this.$el.find("select").select2(opts).val(data.rawValue).trigger("change");
|
||||
this.updateInvalid();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
onChange: function(e) {
|
||||
var model = this.model,
|
||||
$el = $(e.target),
|
||||
attrArr = this.field.get("name").split('.'),
|
||||
name = attrArr.shift(),
|
||||
path = attrArr.join('.'),
|
||||
value = this.getValueFromDOM(),
|
||||
changes = {},
|
||||
columns = model.get('columns'),
|
||||
inherits = model.get(name);
|
||||
|
||||
if (this.model.errorModel instanceof Backbone.Model) {
|
||||
if (_.isEmpty(path)) {
|
||||
this.model.errorModel.unset(name);
|
||||
} else {
|
||||
var nestedError = this.model.errorModel.get(name);
|
||||
if (nestedError) {
|
||||
this.keyPathSetter(nestedError, path, null);
|
||||
this.model.errorModel.set(name, nestedError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
if (typeof(inherits) == "string"){ inherits = JSON.parse(inherits); }
|
||||
|
||||
// Remove Columns if inherit option is deselected from the combobox
|
||||
if(_.size(JSON.parse(value)) < _.size(inherits)) {
|
||||
var dif = _.difference(inherits, JSON.parse(value));
|
||||
var rmv_columns = columns.where({inheritedid: parseInt(dif[0])});
|
||||
columns.remove(rmv_columns);
|
||||
}
|
||||
else
|
||||
{
|
||||
_.each(JSON.parse(value), function(i) {
|
||||
// Fetch Columns from server
|
||||
var fnd_columns = columns.where({inheritedid: parseInt(i)});
|
||||
if (fnd_columns && fnd_columns.length <= 0) {
|
||||
inhted_columns = self.fetchColumns(i);
|
||||
columns.add(inhted_columns);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
changes[name] = _.isEmpty(path) ? value : _.clone(model.get(name)) || {};
|
||||
this.stopListening(this.model, "change:" + name, this.render);
|
||||
model.set(changes);
|
||||
this.listenTo(this.model, "change:" + name, this.render);
|
||||
},
|
||||
fetchColumns: function(table_id){
|
||||
var self = this,
|
||||
url = 'get_columns',
|
||||
m = self.model.top || self.model;
|
||||
|
||||
if (url) {
|
||||
var node = this.field.get('schema_node'),
|
||||
node_info = this.field.get('node_info'),
|
||||
full_url = node.generate_url.apply(
|
||||
node, [
|
||||
null, url, this.field.get('node_data'),
|
||||
this.field.get('url_with_id') || false, node_info
|
||||
]),
|
||||
cache_level = this.field.get('cache_level') || node.type,
|
||||
cache_node = this.field.get('cache_node');
|
||||
|
||||
cache_node = (cache_node && pgAdmin.Browser.Nodes['cache_node']) || node;
|
||||
|
||||
m.trigger('pgadmin:view:fetching', m, self.field);
|
||||
data = {attrelid: table_id}
|
||||
|
||||
// Fetching Columns data for the selected table.
|
||||
$.ajax({
|
||||
async: false,
|
||||
url: full_url,
|
||||
data: data,
|
||||
success: function(res) {
|
||||
/*
|
||||
* We will cache this data for short period of time for avoiding
|
||||
* same calls.
|
||||
*/
|
||||
data = cache_node.cache(url, node_info, cache_level, res.data);
|
||||
|
||||
},
|
||||
error: function() {
|
||||
m.trigger('pgadmin:view:fetch:error', m, self.field);
|
||||
}
|
||||
});
|
||||
m.trigger('pgadmin:view:fetched', m, self.field);
|
||||
|
||||
// To fetch only options from cache, we do not need time from 'at'
|
||||
// attribute but only options.
|
||||
//
|
||||
// It is feasible that the data may not have been fetched.
|
||||
data = (data && data.data) || [];
|
||||
return data;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// Constraints Model
|
||||
var ConstraintModel = pgAdmin.Browser.Node.Model.extend({
|
||||
idAttribute: 'conoid',
|
||||
initialize: function(attrs, args) {
|
||||
var isNew = (_.size(attrs) === 0);
|
||||
if (!isNew) {
|
||||
this.convalidated_default = this.get('convalidated')
|
||||
}
|
||||
pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
|
||||
},
|
||||
defaults: {
|
||||
conoid: undefined,
|
||||
conname: undefined,
|
||||
consrc: undefined,
|
||||
connoinherit: undefined,
|
||||
convalidated: true,
|
||||
conislocal: undefined
|
||||
},
|
||||
convalidated_default: true,
|
||||
schema: [{
|
||||
id: 'conoid', type: 'text', cell: 'string', visible: false
|
||||
},{
|
||||
id: 'conname', label:'{{ _('Name') }}', type: 'text', cell: 'string',
|
||||
editable: 'is_editable', cellHeaderClasses: 'width_percent_30'
|
||||
},{
|
||||
id: 'consrc', label:'{{ _('Check') }}', type: 'multiline',
|
||||
editable: 'is_editable', cell: Backgrid.Extension.TextareaCell,
|
||||
cellHeaderClasses: 'width_percent_30'
|
||||
},{
|
||||
id: 'connoinherit', label:'{{ _('No Inherit') }}', type: 'switch',
|
||||
cell: 'boolean', editable: 'is_editable',
|
||||
cellHeaderClasses: 'width_percent_20'
|
||||
},{
|
||||
id: 'convalidated', label:'{{ _('Validate?') }}', type: 'switch',
|
||||
cell: 'boolean', cellHeaderClasses: 'width_percent_20',
|
||||
editable: function(m) {
|
||||
var server = this.get('node_info').server;
|
||||
if (_.isUndefined(m.isNew)) { return true; }
|
||||
if (!m.isNew()) {
|
||||
if(m.get('convalidated') && m.convalidated_default) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
],
|
||||
validate: function() {
|
||||
var err = {},
|
||||
errmsg;
|
||||
|
||||
if (_.isUndefined(this.get('conname')) || String(this.get('conname')).replace(/^\s+|\s+$/g, '') == '') {
|
||||
err['conname'] = '{{ _('Constraint Name can not be empty!') }}';
|
||||
errmsg = errmsg || err['conname'];
|
||||
}
|
||||
|
||||
if (_.isUndefined(this.get('consrc')) || String(this.get('consrc'))
|
||||
.replace(/^\s+|\s+$/g, '') == '') {
|
||||
err['consrc'] = '{{ _('Constraint Check can not be empty!') }}';
|
||||
errmsg = errmsg || err['consrc'];
|
||||
}
|
||||
|
||||
this.errorModel.clear().set(err);
|
||||
|
||||
return errmsg;
|
||||
},
|
||||
is_editable: function(m) {
|
||||
return _.isUndefined(m.isNew) ? true : m.isNew();
|
||||
},
|
||||
toJSON: Backbone.Model.prototype.toJSON
|
||||
});
|
||||
|
||||
|
||||
// Options Model
|
||||
var OptionsModel = pgAdmin.Browser.Node.Model.extend({
|
||||
defaults: {
|
||||
option: undefined,
|
||||
value: undefined
|
||||
},
|
||||
schema: [{
|
||||
id: 'option', label:'{{ _('Option') }}', cell: 'string', type: 'text',
|
||||
editable: true, cellHeaderClasses:'width_percent_50'
|
||||
},{
|
||||
id: 'value', label:'{{ _('Value') }}', cell: 'string',type: 'text',
|
||||
editable: true, cellHeaderClasses:'width_percent_50'
|
||||
}
|
||||
],
|
||||
validate: function() {
|
||||
// TODO: Add validation here
|
||||
},
|
||||
toJSON: Backbone.Model.prototype.toJSON
|
||||
});
|
||||
|
||||
|
||||
if (!pgBrowser.Nodes['foreign-table']) {
|
||||
pgAdmin.Browser.Nodes['foreign-table'] = pgBrowser.Node.extend({
|
||||
type: 'foreign-table',
|
||||
sqlAlterHelp: 'sql-alterforeigntable.html',
|
||||
sqlCreateHelp: 'sql-createforeigntable.html',
|
||||
label: '{{ _('Foreign Table') }}',
|
||||
collection_type: 'coll-foreign-table',
|
||||
hasSQL: true,
|
||||
hasDepends: true,
|
||||
parent_type: ['schema'],
|
||||
Init: function() {
|
||||
/* Avoid multiple registration of menus */
|
||||
if (this.initialized)
|
||||
return;
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
pgBrowser.add_menus([{
|
||||
name: 'create_foreign-table_on_coll', node: 'coll-foreign-table', module: this,
|
||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||
category: 'create', priority: 4, label: '{{ _('Foreign Table...') }}',
|
||||
icon: 'wcTabIcon icon-foreign-table', data: {action: 'create', check: true},
|
||||
enable: 'canCreate'
|
||||
},{
|
||||
name: 'create_foreign-table', node: 'foreign-table', module: this,
|
||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||
category: 'create', priority: 4, label: '{{ _('Foreign Table...') }}',
|
||||
icon: 'wcTabIcon icon-foreign-table', data: {action: 'create', check: true},
|
||||
enable: 'canCreate'
|
||||
},{
|
||||
name: 'create_foreign-table', node: 'schema', module: this,
|
||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||
category: 'create', priority: 4, label: '{{ _('Foreign Table...') }}',
|
||||
icon: 'wcTabIcon icon-foreign-table', data: {action: 'create', check: false},
|
||||
enable: 'canCreate'
|
||||
}
|
||||
]);
|
||||
|
||||
},
|
||||
canDrop: pgBrowser.Nodes['schema'].canChildDrop,
|
||||
canDropCascade: pgBrowser.Nodes['schema'].canChildDrop,
|
||||
model: pgAdmin.Browser.Node.Model.extend({
|
||||
initialize: function(attrs, args) {
|
||||
var isNew = (_.size(attrs) === 0);
|
||||
if (isNew) {
|
||||
// Set Selected Schema
|
||||
schema = args.node_info.schema.label
|
||||
this.set({'basensp': schema}, {silent: true});
|
||||
|
||||
// Set Current User
|
||||
var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
|
||||
this.set({'owner': userInfo.name}, {silent: true});
|
||||
}
|
||||
pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
|
||||
},
|
||||
defaults: {
|
||||
name: undefined,
|
||||
oid: undefined,
|
||||
owner: undefined,
|
||||
basensp: undefined,
|
||||
description: undefined,
|
||||
ftsrvname: undefined,
|
||||
strcolumn: undefined,
|
||||
strftoptions: undefined,
|
||||
inherits: [],
|
||||
columns: [],
|
||||
constraints: [],
|
||||
ftoptions: [],
|
||||
relacl: [],
|
||||
stracl: [],
|
||||
seclabels: []
|
||||
},
|
||||
schema: [{
|
||||
id: 'name', label: '{{ _('Name') }}', cell: 'string',
|
||||
type: 'text', mode: ['properties', 'create', 'edit']
|
||||
},{
|
||||
id: 'oid', label:'{{ _('OID') }}', cell: 'string',
|
||||
type: 'text' , mode: ['properties']
|
||||
},{
|
||||
id: 'owner', label:'{{ _('Owner') }}', cell: 'string',
|
||||
control: Backform.NodeListByNameControl,
|
||||
node: 'role', type: 'text', select2: { allowClear: false }
|
||||
},{
|
||||
id: 'basensp', label:'{{ _('Schema') }}', cell: 'node-list-by-name',
|
||||
control: 'node-list-by-name', cache_level: 'database', type: 'text',
|
||||
node: 'schema', mode:['create', 'edit']
|
||||
},{
|
||||
id: 'description', label:'{{ _('Comment') }}', cell: 'string',
|
||||
type: 'multiline'
|
||||
},{
|
||||
id: 'ftsrvname', label:'{{ _('Foreign server') }}', cell: 'string', control: 'node-ajax-options',
|
||||
type: 'text', group: 'Definition', url: 'get_foreign_servers', disabled: function(m) { return !m.isNew(); }
|
||||
},{
|
||||
id: 'inherits', label:'{{ _('Inherits') }}', cell: 'string', group: 'Definition',
|
||||
type: 'list', min_version: 90500, control: 'node-ajax-options-multiple',
|
||||
url: 'get_tables', select2: {multiple: true},
|
||||
'cache_level': 'database',
|
||||
transform: function(d, self){
|
||||
if (this.field.get('mode') == 'edit') {
|
||||
oid = this.model.get('oid');
|
||||
s = _.findWhere(d, {'id': oid});
|
||||
if (s) {
|
||||
d = _.reject(d, s);
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
},{
|
||||
id: 'strcolumn', label:'{{ _('Columns') }}', cell: 'string', group: 'Definition',
|
||||
type: 'text', min_version: 90500, mode: ['properties']
|
||||
},{
|
||||
id: 'columns', label:'{{ _('Columns') }}', cell: 'string',
|
||||
type: 'collection', group: 'Columns', visible: false, mode: ['edit', 'create'],
|
||||
model: ColumnsModel, canAdd: true, canDelete: true, canEdit: false,
|
||||
columns: ['attname', 'datatype', 'typlen', 'precision', 'typdefault', 'attnotnull', 'attstattarget', 'collname', 'inheritedfrom'],
|
||||
canDeleteRow: function(m) {
|
||||
return (_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid'))
|
||||
|| _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'constraints', label:'{{ _('Constraints') }}', cell: 'string',
|
||||
type: 'collection', group: 'Constraints', visible: false, mode: ['edit', 'create'],
|
||||
model: ConstraintModel, canAdd: true, canDelete: true, columns: ['conname','consrc', 'connoinherit', 'convalidated'],
|
||||
canEdit: function(o) {
|
||||
if (o instanceof Backbone.Model) {
|
||||
if (o instanceof ConstraintModel) {
|
||||
return o.isNew();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, min_version: 90500, canDeleteRow: function(m) {
|
||||
return (m.get('conislocal') == true || _.isUndefined(m.get('conislocal'))) ? true : false
|
||||
}
|
||||
},{
|
||||
id: 'strftoptions', label:'{{ _('Options') }}', cell: 'string',
|
||||
type: 'text', group: 'Definition', mode: ['properties']
|
||||
},{
|
||||
id: 'ftoptions', label:'{{ _('Options') }}', cell: 'string',
|
||||
type: 'collection', group: 'Options', mode: ['edit', 'create'],
|
||||
model: OptionsModel, canAdd: true, canDelete: true, canEdit: false,
|
||||
control: 'unique-col-collection', uniqueCol : ['option']
|
||||
},{
|
||||
id: 'relacl', label: '{{ _('Privileges') }}', cell: 'string',
|
||||
type: 'text', group: '{{ _('Security') }}',
|
||||
mode: ['properties'], min_version: 90200
|
||||
},{
|
||||
id: 'acl', label: '{{ _('Privileges') }}', model: pgAdmin
|
||||
.Browser.Node.PrivilegeRoleModel.extend(
|
||||
{privileges: ['a','r','w','x']}), uniqueCol : ['grantee', 'grantor'],
|
||||
editable: false, type: 'collection', group: '{{ _('Security') }}',
|
||||
mode: ['edit', 'create'],
|
||||
canAdd: true, canDelete: true, control: 'unique-col-collection',
|
||||
min_version: 90200
|
||||
},{
|
||||
id: 'seclabels', label: '{{ _('Security Labels') }}',
|
||||
model: SecurityModel, type: 'collection',
|
||||
group: '{{ _('Security') }}', mode: ['edit', 'create'],
|
||||
min_version: 90100, canAdd: true,
|
||||
canEdit: false, canDelete: true,
|
||||
control: 'unique-col-collection', uniqueCol : ['provider']
|
||||
}
|
||||
],
|
||||
validate: function()
|
||||
{
|
||||
var err = {},
|
||||
errmsg,
|
||||
seclabels = this.get('seclabels');
|
||||
|
||||
if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') {
|
||||
err['name'] = '{{ _('Name cannot be empty.') }}';
|
||||
errmsg = errmsg || err['name'];
|
||||
}
|
||||
|
||||
if (_.isUndefined(this.get('basensp')) || String(this.get('basensp'))
|
||||
.replace(/^\s+|\s+$/g, '') == '') {
|
||||
err['basensp'] = '{{ _('Schema cannot be empty.') }}';
|
||||
errmsg = errmsg || err['basensp'];
|
||||
}
|
||||
|
||||
if (_.isUndefined(this.get('ftsrvname')) || String(this.get('ftsrvname')).replace(/^\s+|\s+$/g, '') == '') {
|
||||
err['ftsrvname'] = '{{ _('Foreign server cannot be empty.') }}';
|
||||
errmsg = errmsg || err['ftsrvname'];
|
||||
}
|
||||
|
||||
this.errorModel.clear().set(err);
|
||||
|
||||
return null;
|
||||
}
|
||||
}),
|
||||
canCreate: function(itemData, item, data) {
|
||||
//If check is false then , we will allow create menu
|
||||
if (data && data.check == false)
|
||||
return true;
|
||||
|
||||
var t = pgBrowser.tree, i = item, d = itemData;
|
||||
// To iterate over tree to check parent node
|
||||
while (i) {
|
||||
// If it is schema then allow user to create foreign table
|
||||
if (_.indexOf(['schema'], d._type) > -1)
|
||||
return true;
|
||||
|
||||
if ('coll-foreign-table' == d._type) {
|
||||
//Check if we are not child of catalog
|
||||
prev_i = t.hasParent(i) ? t.parent(i) : null;
|
||||
prev_d = prev_i ? t.itemData(prev_i) : null;
|
||||
if( prev_d._type == 'catalog') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i = t.hasParent(i) ? t.parent(i) : null;
|
||||
d = i ? t.itemData(i) : null;
|
||||
}
|
||||
// by default we do not want to allow create menu
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return pgBrowser.Nodes['foreign-table'];
|
||||
});
|
|
@ -0,0 +1,36 @@
|
|||
{% import 'macros/schemas/security.macros' as SECLABLE %}
|
||||
{% if data %}
|
||||
CREATE FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}(
|
||||
{% if data.columns %}
|
||||
{% for c in data.columns %}
|
||||
{{conn|qtIdent(c.attname)}} {{ conn|qtTypeIdent(c.datatype) }}{% if c.typlen %}({{c.typlen}} {% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}{% if c.attnotnull %}
|
||||
NOT NULL{% else %} NULL{% endif %}
|
||||
{% if not loop.last %},
|
||||
{% endif %}{% endfor -%}{% endif %}
|
||||
|
||||
)
|
||||
SERVER {{ conn|qtIdent(data.ftsrvname) }}{% if data.ftoptions %}
|
||||
|
||||
{% for o in data.ftoptions %}
|
||||
{% if o.option and o.value %}
|
||||
{% if loop.first %} OPTIONS ({% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral}}{% if loop.last %}){% endif %}{% endif %}
|
||||
{% endfor %}{% endif -%};
|
||||
{% if data.owner %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}
|
||||
OWNER TO {{ data.owner }};
|
||||
{% endif -%}
|
||||
{% if data.description %}
|
||||
|
||||
COMMENT ON FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}
|
||||
IS '{{ data.description }}';
|
||||
{% endif -%}
|
||||
{% if data.seclabels %}
|
||||
{% for r in data.seclabels %}
|
||||
{% if r.security_label and r.provider %}
|
||||
|
||||
{{ SECLABLE.SET(conn, 'FOREIGN TABLE', data.name, r.provider, r.security_label, data.basensp) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
|
@ -0,0 +1,15 @@
|
|||
{% if scid and foid %}
|
||||
SELECT
|
||||
c.relname AS name, nspname as basensp
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace nsp ON (nsp.oid=c.relnamespace)
|
||||
WHERE
|
||||
c.relnamespace = {{scid}}::oid
|
||||
AND c.oid = {{foid}}::oid;
|
||||
{% endif %}
|
||||
|
||||
{% if name %}
|
||||
DROP FOREIGN TABLE {{ conn|qtIdent(basensp, name) }}{% if cascade %} CASCADE{% endif %};
|
||||
{% endif %}
|
|
@ -0,0 +1,10 @@
|
|||
SELECT --nspname, collname,
|
||||
CASE WHEN length(nspname) > 0 AND length(collname) > 0 THEN
|
||||
concat(nspname, '."', collname,'"')
|
||||
ELSE '' END AS copy_collation
|
||||
FROM
|
||||
pg_collation c, pg_namespace n
|
||||
WHERE
|
||||
c.collnamespace=n.oid
|
||||
ORDER BY
|
||||
nspname, collname;
|
|
@ -0,0 +1,22 @@
|
|||
SELECT
|
||||
attname, attndims, atttypmod, format_type(t.oid,NULL) AS datatype,
|
||||
format_type(t.oid, att.atttypmod) AS fulltype, attnotnull, attnum,
|
||||
(SELECT COUNT(1) from pg_type t2 WHERE t2.typname=t.typname) > 1 AS isdup,
|
||||
(
|
||||
attname || ' ' || format_type(t.oid, att.atttypmod) || ' ' ||
|
||||
(CASE WHEN attnotnull='true'
|
||||
THEN 'NOT NULL' ELSE 'NULL'
|
||||
END)
|
||||
) as strcolumn
|
||||
FROM
|
||||
pg_attribute att
|
||||
JOIN
|
||||
pg_type t ON t.oid=atttypid
|
||||
JOIN
|
||||
pg_namespace nsp ON t.typnamespace=nsp.oid
|
||||
LEFT OUTER JOIN
|
||||
pg_type b ON t.typelem=b.oid
|
||||
WHERE
|
||||
att.attrelid={{foid}}::oid
|
||||
AND attnum>0
|
||||
ORDER by attnum;
|
|
@ -0,0 +1,7 @@
|
|||
SELECT
|
||||
conname, contype, consrc
|
||||
FROM
|
||||
pg_constraint
|
||||
WHERE
|
||||
conrelid={{foid}}::oid
|
||||
ORDER by conname;
|
|
@ -0,0 +1,5 @@
|
|||
SELECT
|
||||
srvname
|
||||
FROM
|
||||
pg_foreign_server
|
||||
ORDER BY srvname;
|
|
@ -0,0 +1,19 @@
|
|||
{% if basensp %}
|
||||
SELECT
|
||||
c.oid, bn.oid as scid
|
||||
FROM
|
||||
pg_class c
|
||||
JOIN
|
||||
pg_namespace bn ON bn.oid=c.relnamespace
|
||||
WHERE
|
||||
bn.nspname = {{ basensp|qtLiteral }}
|
||||
AND c.relname={{ name|qtLiteral }};
|
||||
|
||||
{% elif foid %}
|
||||
SELECT
|
||||
c.relnamespace as scid
|
||||
FROM
|
||||
pg_class c
|
||||
WHERE
|
||||
c.oid = {{foid}}::oid;
|
||||
{% endif %}
|
|
@ -0,0 +1,14 @@
|
|||
SELECT
|
||||
c.oid, c.relname AS name, pg_get_userbyid(relowner) AS owner,
|
||||
ftoptions, nspname as basensp, description
|
||||
FROM
|
||||
pg_class c
|
||||
JOIN
|
||||
pg_foreign_table ft ON c.oid=ft.ftrelid
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace nsp ON (nsp.oid=c.relnamespace)
|
||||
LEFT OUTER JOIN
|
||||
pg_description des ON (des.objoid=c.oid AND des.classoid='pg_class'::regclass)
|
||||
WHERE
|
||||
c.relnamespace = {{scid}}::oid
|
||||
ORDER BY c.relname;
|
|
@ -0,0 +1,25 @@
|
|||
SELECT
|
||||
c.oid, c.relname AS name, pg_get_userbyid(relowner) AS owner,
|
||||
ftoptions, srvname AS ftsrvname, description, nspname as basensp,
|
||||
(SELECT
|
||||
array_agg(provider || '=' || label)
|
||||
FROM
|
||||
pg_seclabel sl1
|
||||
WHERE
|
||||
sl1.objoid=c.oid) AS seclabels
|
||||
FROM
|
||||
pg_class c
|
||||
JOIN
|
||||
pg_foreign_table ft ON c.oid=ft.ftrelid
|
||||
LEFT OUTER JOIN
|
||||
pg_foreign_server fs ON ft.ftserver=fs.oid
|
||||
LEFT OUTER JOIN
|
||||
pg_description des ON (des.objoid=c.oid AND des.classoid='pg_class'::regclass)
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace nsp ON (nsp.oid=c.relnamespace)
|
||||
WHERE
|
||||
c.relnamespace = {{scid}}::oid
|
||||
{% if foid %}
|
||||
AND c.oid = {{foid}}::oid
|
||||
{% endif %}
|
||||
ORDER BY c.relname;
|
|
@ -0,0 +1,109 @@
|
|||
{% import 'macros/schemas/security.macros' as SECLABLE %}
|
||||
{% if data %}
|
||||
{% set name = o_data.name %}
|
||||
{% if data.name %}
|
||||
{% if data.name != o_data.name %}
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, o_data.name) }}
|
||||
RENAME TO {{ conn|qtIdent(data.name) }};
|
||||
{% set name = data.name %}
|
||||
{% endif %}
|
||||
{% endif -%}
|
||||
|
||||
{% if data.owner %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OWNER TO {{ data.owner }};
|
||||
{% endif -%}
|
||||
|
||||
{% if data.columns %}
|
||||
{% for c in data.columns.deleted %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
DROP COLUMN {{conn|qtIdent(c.attname)}};
|
||||
{% endfor -%}
|
||||
{% for c in data.columns.added %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ADD COLUMN {{conn|qtIdent(c.attname)}} {{ conn|qtTypeIdent(c.datatype) }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}
|
||||
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
||||
{% if c.typdefault %} DEFAULT {{c.typdefault}}{% endif %}
|
||||
{% if c.collname %} COLLATE {{c.collname}}{% endif %};
|
||||
{% endfor -%}
|
||||
{% for c in data.columns.changed %}
|
||||
{% set col_name = o_data['columns'][c.attnum]['attname'] %}
|
||||
{% if c.attname != o_data['columns'][c.attnum]['attname'] %}
|
||||
{% set col_name = c.attname %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
RENAME COLUMN {{conn|qtIdent(o_data['columns'][c.attnum]['attname'])}} TO {{conn|qtIdent(c.attname)}};
|
||||
{% endif %}
|
||||
{% if c.attnotnull != o_data['columns'][c.attnum]['attnotnull'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}}{% if c.attnotnull %} SET{% else %} DROP{% endif %} NOT NULL;
|
||||
{% endif %}
|
||||
{% if c.datatype != o_data['columns'][c.attnum]['datatype'] or c.typlen != o_data['columns'][c.attnum]['typlen'] or
|
||||
c.precision != o_data['columns'][c.attnum]['precision'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}} TYPE {{ conn|qtTypeIdent(c.datatype) }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %};
|
||||
{% endif %}
|
||||
{% if c.typdefault != o_data['columns'][c.attnum]['typdefault'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}}{% if c.typdefault %} SET DEFAULT {{c.typdefault}}{% else %} DROP DEFAULT{% endif %};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if data.ftoptions %}
|
||||
{% for o in data.ftoptions.deleted %}
|
||||
{% if o.option and o.value %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OPTIONS (DROP {{o.option}});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for o in data.ftoptions.added %}
|
||||
{% if o.option and o.value %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OPTIONS (ADD {{o.option}} {{o.value|qtLiteral}});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for o in data.ftoptions.changed %}
|
||||
{% if o.option and o.value %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OPTIONS (SET {{o.option}} {{o.value|qtLiteral}});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% set seclabels = data.seclabels %}
|
||||
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
|
||||
{% for r in seclabels.deleted %}
|
||||
{{ SECLABLE.UNSET(conn, 'FOREIGN TABLE', name, r.provider, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||
{% for r in seclabels.added %}
|
||||
|
||||
{{ SECLABLE.SET(conn, 'FOREIGN TABLE', name, r.provider, r.security_label, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
|
||||
{% for r in seclabels.changed %}
|
||||
|
||||
{{ SECLABLE.SET(conn, 'FOREIGN TABLE', name, r.provider, r.security_label, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if data.description %}
|
||||
|
||||
COMMENT ON FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
{% endif -%}
|
||||
{% if data.basensp %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
SET SCHEMA {{ conn|qtIdent(data.basensp) }};
|
||||
{% endif %}
|
||||
{% endif %}
|
|
@ -0,0 +1,35 @@
|
|||
SELECT
|
||||
COALESCE(gt.rolname, 'public') AS grantee,
|
||||
g.rolname AS grantor, array_agg(privilege_type) AS privileges,
|
||||
array_agg(is_grantable) AS grantable
|
||||
FROM
|
||||
(SELECT
|
||||
d.grantee, d.grantor, d.is_grantable,
|
||||
CASE d.privilege_type
|
||||
WHEN 'CONNECT' THEN 'c'
|
||||
WHEN 'CREATE' THEN 'C'
|
||||
WHEN 'DELETE' THEN 'd'
|
||||
WHEN 'EXECUTE' THEN 'X'
|
||||
WHEN 'INSERT' THEN 'a'
|
||||
WHEN 'REFERENCES' THEN 'x'
|
||||
WHEN 'SELECT' THEN 'r'
|
||||
WHEN 'TEMPORARY' THEN 'T'
|
||||
WHEN 'TRIGGER' THEN 't'
|
||||
WHEN 'TRUNCATE' THEN 'D'
|
||||
WHEN 'UPDATE' THEN 'w'
|
||||
WHEN 'USAGE' THEN 'U'
|
||||
ELSE 'UNKNOWN'
|
||||
END AS privilege_type
|
||||
FROM
|
||||
(SELECT
|
||||
(d).grantee AS grantee, (d).grantor AS grantor,
|
||||
(d).is_grantable AS is_grantable,
|
||||
(d).privilege_type AS privilege_type
|
||||
FROM
|
||||
(SELECT aclexplode(db.relacl) AS d FROM pg_class db
|
||||
WHERE db.oid = {{foid}}::OID) a
|
||||
) d
|
||||
) d
|
||||
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
|
||||
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
|
||||
GROUP BY g.rolname, gt.rolname;
|
|
@ -0,0 +1,44 @@
|
|||
{% import 'macros/schemas/security.macros' as SECLABLE %}
|
||||
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
|
||||
{% if data %}
|
||||
CREATE FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}(
|
||||
{% if data.columns %}
|
||||
{% for c in data.columns %}
|
||||
{{conn|qtIdent(c.attname)}} {{conn|qtTypeIdent(c.datatype) }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}{% if c.attnotnull %}
|
||||
NOT NULL{% else %} NULL{% endif %}{% if c.typdefault %}
|
||||
DEFAULT {{c.typdefault}}{% endif %}{% if c.collname %}
|
||||
COLLATE {{c.collname}}{% endif %}
|
||||
{% if not loop.last %},
|
||||
{% endif %}{% endfor -%}{% endif %}
|
||||
|
||||
)
|
||||
SERVER {{ conn|qtIdent(data.ftsrvname) }}{% if data.ftoptions %}
|
||||
|
||||
{% for o in data.ftoptions %}
|
||||
{% if o.option and o.value %}
|
||||
{% if loop.first %} OPTIONS ({% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral}}{% if loop.last %}){% endif %}{% endif %}
|
||||
{% endfor %}{% endif %};
|
||||
{% if data.owner %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}
|
||||
OWNER TO {{ data.owner }};
|
||||
{% endif -%}
|
||||
{% if data.description %}
|
||||
|
||||
COMMENT ON FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}
|
||||
IS '{{ data.description }}';
|
||||
{% endif -%}
|
||||
{% if data.acl %}
|
||||
|
||||
{% for priv in data.acl %}
|
||||
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.basensp) }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
{% if data.seclabels %}
|
||||
|
||||
{% for r in data.seclabels %}{% if r.security_label and r.provider %}
|
||||
{{ SECLABLE.SET(conn, 'FOREIGN TABLE', data.name, r.provider, r.security_label, data.basensp) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
|
@ -0,0 +1,17 @@
|
|||
{% if scid and foid %}
|
||||
SELECT
|
||||
c.relname AS name, nspname as basensp
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace nsp ON (nsp.oid=c.relnamespace)
|
||||
WHERE
|
||||
c.relnamespace = {{scid}}::oid
|
||||
AND
|
||||
c.oid = {{foid}}::oid;
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if name %}
|
||||
DROP FOREIGN TABLE {{ conn|qtIdent(basensp, name) }}{% if cascade%} CASCADE{% endif %};
|
||||
{% endif %}
|
|
@ -0,0 +1,9 @@
|
|||
SELECT --nspname, collname,
|
||||
CASE WHEN length(nspname) > 0 AND length(collname) > 0 THEN
|
||||
concat(nspname, '."', collname,'"')
|
||||
ELSE '' END AS copy_collation
|
||||
FROM
|
||||
pg_collation c, pg_namespace n
|
||||
WHERE
|
||||
c.collnamespace=n.oid
|
||||
ORDER BY nspname, collname;
|
|
@ -0,0 +1,34 @@
|
|||
SELECT
|
||||
attname, attndims, atttypmod, format_type(t.oid,NULL) AS datatype,
|
||||
attnotnull, attstattarget, attnum, format_type(t.oid, att.atttypmod) AS fulltype,
|
||||
CASE WHEN length(cn.nspname) > 0 AND length(cl.collname) > 0 THEN
|
||||
concat(cn.nspname, '."', cl.collname,'"') ELSE '' END AS collname,
|
||||
(SELECT COUNT(1) from pg_type t2 WHERE t2.typname=t.typname) > 1 AS isdup,
|
||||
pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS typdefault,
|
||||
(
|
||||
attname || ' ' || format_type(t.oid, att.atttypmod) || ' ' ||
|
||||
(CASE WHEN attnotnull='true'
|
||||
THEN 'NOT NULL' ELSE 'NULL'
|
||||
END) || ' ' ||
|
||||
(CASE WHEN pg_catalog.pg_get_expr(def.adbin, def.adrelid)<>''
|
||||
THEN 'DEFAULT ' || pg_catalog.pg_get_expr(def.adbin, def.adrelid)
|
||||
ELSE '' END)
|
||||
) as strcolumn
|
||||
FROM
|
||||
pg_attribute att
|
||||
JOIN
|
||||
pg_type t ON t.oid=atttypid
|
||||
JOIN
|
||||
pg_namespace nsp ON t.typnamespace=nsp.oid
|
||||
LEFT OUTER JOIN
|
||||
pg_attrdef def ON adrelid=att.attrelid AND adnum=att.attnum
|
||||
LEFT OUTER JOIN
|
||||
pg_type b ON t.typelem=b.oid
|
||||
LEFT OUTER JOIN
|
||||
pg_collation cl ON t.typcollation=cl.oid
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace cn ON cl.collnamespace=cn.oid
|
||||
WHERE
|
||||
att.attrelid={{foid}}::oid
|
||||
AND attnum>0
|
||||
ORDER by attnum;
|
|
@ -0,0 +1,7 @@
|
|||
SELECT
|
||||
conname, contype, consrc, conislocal
|
||||
FROM
|
||||
pg_constraint
|
||||
WHERE
|
||||
conrelid={{foid}}::oid
|
||||
ORDER by conname;
|
|
@ -0,0 +1,6 @@
|
|||
SELECT
|
||||
srvname
|
||||
FROM
|
||||
pg_foreign_server
|
||||
ORDER BY
|
||||
srvname;
|
|
@ -0,0 +1,19 @@
|
|||
{% if basensp %}
|
||||
SELECT
|
||||
c.oid, bn.oid as scid
|
||||
FROM
|
||||
pg_class c
|
||||
JOIN
|
||||
pg_namespace bn ON bn.oid=c.relnamespace
|
||||
WHERE
|
||||
bn.nspname = {{ basensp|qtLiteral }}
|
||||
AND c.relname={{ name|qtLiteral }};
|
||||
|
||||
{% elif foid %}
|
||||
SELECT
|
||||
c.relnamespace as scid
|
||||
FROM
|
||||
pg_class c
|
||||
WHERE
|
||||
c.oid = {{foid}}::oid;
|
||||
{% endif %}
|
|
@ -0,0 +1,14 @@
|
|||
SELECT
|
||||
c.oid, c.relname AS name, pg_get_userbyid(relowner) AS owner,
|
||||
ftoptions, nspname as basensp, description
|
||||
FROM
|
||||
pg_class c
|
||||
JOIN
|
||||
pg_foreign_table ft ON c.oid=ft.ftrelid
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace nsp ON (nsp.oid=c.relnamespace)
|
||||
LEFT OUTER JOIN
|
||||
pg_description des ON (des.objoid=c.oid AND des.classoid='pg_class'::regclass)
|
||||
WHERE
|
||||
c.relnamespace = {{scid}}::oid
|
||||
ORDER BY c.relname;
|
|
@ -0,0 +1,27 @@
|
|||
SELECT
|
||||
c.oid, c.relname AS name, c.relacl, pg_get_userbyid(relowner) AS owner,
|
||||
ftoptions, srvname AS ftsrvname, description, nspname as basensp, consrc,
|
||||
(SELECT
|
||||
array_agg(provider || '=' || label)
|
||||
FROM
|
||||
pg_shseclabel sl1
|
||||
WHERE
|
||||
sl1.objoid=c.oid) AS seclabels
|
||||
FROM
|
||||
pg_class c
|
||||
JOIN
|
||||
pg_foreign_table ft ON c.oid=ft.ftrelid
|
||||
LEFT OUTER JOIN
|
||||
pg_foreign_server fs ON ft.ftserver=fs.oid
|
||||
LEFT OUTER JOIN
|
||||
pg_description des ON (des.objoid=c.oid AND des.classoid='pg_class'::regclass)
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace nsp ON (nsp.oid=c.relnamespace)
|
||||
LEFT OUTER JOIN
|
||||
pg_constraint cn ON (cn.conrelid=c.oid)
|
||||
WHERE
|
||||
c.relnamespace = {{scid}}::oid
|
||||
{% if foid %}
|
||||
AND c.oid = {{foid}}::oid
|
||||
{% endif %}
|
||||
ORDER BY c.relname;
|
|
@ -0,0 +1,148 @@
|
|||
{% import 'macros/schemas/security.macros' as SECLABLE %}
|
||||
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
|
||||
{% if data %}
|
||||
{% set name = o_data.name %}
|
||||
{% if data.name %}
|
||||
{% if data.name != o_data.name %}
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, o_data.name) }}
|
||||
RENAME TO {{ conn|qtIdent(data.name) }};
|
||||
{% set name = data.name %}
|
||||
{% endif %}
|
||||
{% endif -%}
|
||||
{% if data.owner %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OWNER TO {{ data.owner }};
|
||||
{% endif -%}
|
||||
{% if data.columns %}
|
||||
{% for c in data.columns.deleted %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
DROP COLUMN {{conn|qtIdent(c.attname)}};
|
||||
{% endfor -%}
|
||||
{% for c in data.columns.added %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ADD COLUMN {{conn|qtIdent(c.attname)}} {{ conn|qtTypeIdent(c.datatype) }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}
|
||||
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
||||
{% if c.typdefault %} DEFAULT {{c.typdefault}}{% endif %}
|
||||
{% if c.collname %} COLLATE {{c.collname}}{% endif %};
|
||||
{% endfor -%}
|
||||
{% for c in data.columns.changed %}
|
||||
{% set col_name = o_data['columns'][c.attnum]['attname'] %}
|
||||
{% if c.attname != o_data['columns'][c.attnum]['attname'] %}
|
||||
{% set col_name = c.attname %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
RENAME COLUMN {{conn|qtIdent(o_data['columns'][c.attnum]['attname'])}} TO {{conn|qtIdent(c.attname)}};
|
||||
{% endif %}
|
||||
{% if c.attnotnull != o_data['columns'][c.attnum]['attnotnull'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}}{% if c.attnotnull %} SET{% else %} DROP{% endif %} NOT NULL;
|
||||
{% endif %}
|
||||
{% if c.datatype != o_data['columns'][c.attnum]['datatype'] or c.typlen != o_data['columns'][c.attnum]['typlen'] or
|
||||
c.precision != o_data['columns'][c.attnum]['precision'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}} TYPE {{ conn|qtTypeIdent(c.datatype) }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %};
|
||||
{% endif %}
|
||||
{% if c.typdefault != o_data['columns'][c.attnum]['typdefault'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}}{% if c.typdefault %} SET DEFAULT {{c.typdefault}}{% else %} DROP DEFAULT{% endif %};
|
||||
{% endif %}
|
||||
{% if c.attstattarget != o_data['columns'][c.attnum]['attstattarget'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}} SET STATISTICS {% if c.attstattarget %}{{c.attstattarget}}{% else %}-1{% endif %};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if data.constraints %}
|
||||
{% for c in data.constraints.deleted %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
DROP CONSTRAINT {{conn|qtIdent(c.conname)}};
|
||||
{% endfor %}
|
||||
{% for c in data.constraints.added %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ADD CONSTRAINT {{conn|qtIdent(c.conname)}} {% if c.consrc %} CHECK ({{c.consrc}}){% endif %} {% if c.connoinherit %} NO INHERIT{% endif %};
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if data.ftoptions %}
|
||||
{% for o in data.ftoptions.deleted %}
|
||||
{% if o.option and o.value %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OPTIONS ( DROP {{o.option}});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for o in data.ftoptions.added %}
|
||||
{% if o.option and o.value %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OPTIONS (ADD {{o.option}} {{o.value|qtLiteral}});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for o in data.ftoptions.changed %}
|
||||
{% if o.option and o.value %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OPTIONS (SET {{o.option}} {{o.value|qtLiteral}});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if data.acl %}
|
||||
{% if 'deleted' in data.acl %}
|
||||
{% for priv in data.acl.deleted %}
|
||||
|
||||
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, name, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if 'changed' in data.acl %}
|
||||
{% for priv in data.acl.changed %}
|
||||
|
||||
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, name, o_data.basensp) }}
|
||||
|
||||
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if 'added' in data.acl %}
|
||||
{% for priv in data.acl.added %}
|
||||
|
||||
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif -%}
|
||||
{% set seclabels = data.seclabels %}
|
||||
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
|
||||
{% for r in seclabels.deleted %}
|
||||
|
||||
{{ SECLABLE.UNSET(conn, 'FOREIGN TABLE', name, r.provider, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||
{% for r in seclabels.added %}
|
||||
|
||||
{{ SECLABLE.SET(conn, 'FOREIGN TABLE', name, r.provider, r.security_label, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
|
||||
{% for r in seclabels.changed %}
|
||||
|
||||
{{ SECLABLE.SET(conn, 'FOREIGN TABLE', name, r.provider, r.security_label, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if data.description %}
|
||||
|
||||
COMMENT ON FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
{% endif -%}
|
||||
{% if data.basensp %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
SET SCHEMA {{ conn|qtIdent(data.basensp) }};
|
||||
{% endif %}
|
||||
{% endif %}
|
|
@ -0,0 +1,35 @@
|
|||
SELECT
|
||||
COALESCE(gt.rolname, 'public') AS grantee,
|
||||
g.rolname AS grantor, array_agg(privilege_type) AS privileges,
|
||||
array_agg(is_grantable) AS grantable
|
||||
FROM
|
||||
(SELECT
|
||||
d.grantee, d.grantor, d.is_grantable,
|
||||
CASE d.privilege_type
|
||||
WHEN 'CONNECT' THEN 'c'
|
||||
WHEN 'CREATE' THEN 'C'
|
||||
WHEN 'DELETE' THEN 'd'
|
||||
WHEN 'EXECUTE' THEN 'X'
|
||||
WHEN 'INSERT' THEN 'a'
|
||||
WHEN 'REFERENCES' THEN 'x'
|
||||
WHEN 'SELECT' THEN 'r'
|
||||
WHEN 'TEMPORARY' THEN 'T'
|
||||
WHEN 'TRIGGER' THEN 't'
|
||||
WHEN 'TRUNCATE' THEN 'D'
|
||||
WHEN 'UPDATE' THEN 'w'
|
||||
WHEN 'USAGE' THEN 'U'
|
||||
ELSE 'UNKNOWN'
|
||||
END AS privilege_type
|
||||
FROM
|
||||
(SELECT
|
||||
(d).grantee AS grantee, (d).grantor AS grantor,
|
||||
(d).is_grantable AS is_grantable,
|
||||
(d).privilege_type AS privilege_type
|
||||
FROM
|
||||
(SELECT aclexplode(db.relacl) AS d FROM pg_class db
|
||||
WHERE db.oid = {{foid}}::OID) a
|
||||
) d
|
||||
) d
|
||||
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
|
||||
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
|
||||
GROUP BY g.rolname, gt.rolname;
|
|
@ -0,0 +1,61 @@
|
|||
{% import 'macros/schemas/security.macros' as SECLABLE %}
|
||||
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
|
||||
{% set is_columns = [] %}
|
||||
{% if data %}
|
||||
CREATE FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}(
|
||||
{% if data.columns %}
|
||||
{% for c in data.columns %}
|
||||
{% if (not c.inheritedfrom or c.inheritedfrom =='' or c.inheritedfrom == None or c.inheritedfrom == 'None' ) %}
|
||||
{% if is_columns.append('1') %}{% endif %}
|
||||
{{conn|qtIdent(c.attname)}} {{conn|qtTypeIdent(c.datatype) }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}
|
||||
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
||||
{% if c.typdefault %} DEFAULT {{c.typdefault}}{% endif %}
|
||||
{% if c.collname %} COLLATE {{c.collname}}{% endif %}
|
||||
{% if not loop.last %},
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
)
|
||||
{% if data.inherits %}
|
||||
INHERITS ({% for i in data.inherits %}{% if i %}{{i}}{% if not loop.last %}, {% endif %}{% endif %}{% endfor %})
|
||||
{% endif %}
|
||||
SERVER {{ conn|qtIdent(data.ftsrvname) }}{% if data.ftoptions %}
|
||||
|
||||
{% for o in data.ftoptions %}
|
||||
{% if o.option and o.value %}
|
||||
{% if loop.first %} OPTIONS ({% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral}}{% if loop.last %}){% endif %}{% endif %}
|
||||
{% endfor %}{% endif %};
|
||||
{% if data.owner %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}
|
||||
OWNER TO {{ data.owner }};
|
||||
{% endif -%}
|
||||
{% if data.constraints %}
|
||||
{% for c in data.constraints %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}
|
||||
ADD CONSTRAINT {{ conn|qtIdent(c.conname) }} CHECK ({{ c.consrc }}){% if not c.convalidated %} NOT VALID{% endif %}{% if c.connoinherit %} NO INHERIT{% endif %};
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.description %}
|
||||
|
||||
COMMENT ON FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}
|
||||
IS '{{ data.description }}';
|
||||
{% endif -%}
|
||||
{% if data.acl %}
|
||||
|
||||
{% for priv in data.acl %}
|
||||
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.basensp) }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
{% if data.seclabels %}
|
||||
{% for r in data.seclabels %}
|
||||
{% if r.security_label and r.provider %}
|
||||
|
||||
{{ SECLABLE.SET(conn, 'FOREIGN TABLE', data.name, r.provider, r.security_label, data.basensp) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
|
@ -0,0 +1,17 @@
|
|||
{% if scid and foid %}
|
||||
SELECT
|
||||
c.relname AS name, nspname as basensp
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace nsp ON (nsp.oid=c.relnamespace)
|
||||
WHERE
|
||||
c.relnamespace = {{scid}}::oid
|
||||
AND
|
||||
c.oid = {{foid}}::oid;
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if name %}
|
||||
DROP FOREIGN TABLE {{ conn|qtIdent(basensp, name) }}{% if cascade%} CASCADE{% endif %};
|
||||
{% endif %}
|
|
@ -0,0 +1,9 @@
|
|||
SELECT --nspname, collname,
|
||||
CASE WHEN length(nspname) > 0 AND length(collname) > 0 THEN
|
||||
concat(nspname, '."', collname,'"')
|
||||
ELSE '' END AS copy_collation
|
||||
FROM
|
||||
pg_collation c, pg_namespace n
|
||||
WHERE
|
||||
c.collnamespace=n.oid
|
||||
ORDER BY nspname, collname;
|
|
@ -0,0 +1,53 @@
|
|||
WITH INH_TABLES AS
|
||||
(SELECT
|
||||
distinct on (at.attname) attname, ph.inhparent AS inheritedid, ph.inhseqno,
|
||||
concat(nmsp_parent.nspname, '.',parent.relname ) AS inheritedfrom
|
||||
FROM
|
||||
pg_attribute at
|
||||
JOIN
|
||||
pg_inherits ph ON ph.inhparent = at.attrelid AND ph.inhrelid = {{foid}}::oid
|
||||
JOIN
|
||||
pg_class parent ON ph.inhparent = parent.oid
|
||||
JOIN
|
||||
pg_namespace nmsp_parent ON nmsp_parent.oid = parent.relnamespace
|
||||
GROUP BY at.attname, ph.inhparent, ph.inhseqno, inheritedfrom
|
||||
ORDER BY at.attname, ph.inhparent, ph.inhseqno, inheritedfrom
|
||||
)
|
||||
SELECT INH.inheritedfrom, INH.inheritedid,
|
||||
att.attname, att.attndims, att.atttypmod, format_type(t.oid,NULL) AS datatype,
|
||||
att.attnotnull, att.attstattarget, att.attnum, format_type(t.oid, att.atttypmod) AS fulltype,
|
||||
CASE WHEN length(cn.nspname) > 0 AND length(cl.collname) > 0 THEN
|
||||
concat(cn.nspname, '."', cl.collname,'"')
|
||||
ELSE '' END AS collname,
|
||||
pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS typdefault,
|
||||
(
|
||||
att.attname || ' ' || format_type(t.oid, att.atttypmod) || ' ' ||
|
||||
(CASE WHEN attnotnull='true'
|
||||
THEN 'NOT NULL' ELSE 'NULL'
|
||||
END) || ' ' ||
|
||||
(CASE WHEN pg_catalog.pg_get_expr(def.adbin, def.adrelid)<>''
|
||||
THEN 'DEFAULT ' || pg_catalog.pg_get_expr(def.adbin, def.adrelid)
|
||||
ELSE '' END)
|
||||
) as strcolumn,
|
||||
|
||||
(SELECT COUNT(1) from pg_type t2 WHERE t2.typname=t.typname) > 1 AS isdup
|
||||
FROM
|
||||
pg_attribute att
|
||||
LEFT JOIN
|
||||
INH_TABLES as INH ON att.attname = INH.attname
|
||||
JOIN
|
||||
pg_type t ON t.oid=atttypid
|
||||
JOIN
|
||||
pg_namespace nsp ON t.typnamespace=nsp.oid
|
||||
LEFT OUTER JOIN
|
||||
pg_attrdef def ON adrelid=att.attrelid AND adnum=att.attnum
|
||||
LEFT OUTER JOIN
|
||||
pg_type b ON t.typelem=b.oid
|
||||
LEFT OUTER JOIN
|
||||
pg_collation cl ON t.typcollation=cl.oid
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace cn ON cl.collnamespace=cn.oid
|
||||
WHERE
|
||||
att.attrelid={{foid}}::oid
|
||||
AND att.attnum>0
|
||||
ORDER BY att.attname;
|
|
@ -0,0 +1,7 @@
|
|||
SELECT
|
||||
oid as conoid, conname, contype, consrc, connoinherit, convalidated, conislocal
|
||||
FROM
|
||||
pg_constraint
|
||||
WHERE
|
||||
conrelid={{foid}}::oid
|
||||
ORDER by conname;
|
|
@ -0,0 +1,6 @@
|
|||
SELECT
|
||||
srvname
|
||||
FROM
|
||||
pg_foreign_server
|
||||
ORDER
|
||||
BY srvname;
|
|
@ -0,0 +1,19 @@
|
|||
{% if basensp %}
|
||||
SELECT
|
||||
c.oid, bn.oid as scid
|
||||
FROM
|
||||
pg_class c
|
||||
JOIN
|
||||
pg_namespace bn ON bn.oid=c.relnamespace
|
||||
WHERE
|
||||
bn.nspname = {{ basensp|qtLiteral }}
|
||||
AND c.relname={{ name|qtLiteral }};
|
||||
|
||||
{% elif foid %}
|
||||
SELECT
|
||||
c.relnamespace as scid
|
||||
FROM
|
||||
pg_class c
|
||||
WHERE
|
||||
c.oid = {{foid}}::oid;
|
||||
{% endif %}
|
|
@ -0,0 +1,14 @@
|
|||
{% if attrelid %}
|
||||
SELECT
|
||||
a.attname, format_type(a.atttypid, NULL) AS datatype,
|
||||
quote_ident(n.nspname)||'.'||quote_ident(c.relname) as inheritedfrom,
|
||||
c.oid as inheritedid
|
||||
FROM
|
||||
pg_class c
|
||||
JOIN
|
||||
pg_namespace n ON c.relnamespace=n.oid
|
||||
JOIN
|
||||
pg_attribute a ON a.attrelid = c.oid AND NOT a.attisdropped AND a.attnum>0
|
||||
WHERE
|
||||
c.oid = {{attrelid}}::OID
|
||||
{% endif %}
|
|
@ -0,0 +1,22 @@
|
|||
{% if attrelid %}
|
||||
SELECT
|
||||
array_agg(quote_ident(n.nspname) || '.' || quote_ident(c.relname)) as inherits
|
||||
FROM
|
||||
pg_class c, pg_namespace n
|
||||
WHERE
|
||||
c.relnamespace=n.oid AND c.relkind IN ('r', 'f')
|
||||
AND c.oid in {{attrelid}};
|
||||
|
||||
{% else %}
|
||||
SELECT
|
||||
c.oid AS id, quote_ident(n.nspname) || '.' || quote_ident(c.relname) as text
|
||||
FROM
|
||||
pg_class c, pg_namespace n
|
||||
WHERE
|
||||
c.relnamespace=n.oid AND c.relkind IN ('r', 'f')
|
||||
{% if foid %}
|
||||
AND c.oid <> {{foid}}::oid
|
||||
{% endif %}
|
||||
ORDER BY
|
||||
n.nspname, c.relname;
|
||||
{% endif %}
|
|
@ -0,0 +1,14 @@
|
|||
SELECT
|
||||
c.oid, c.relname AS name, pg_get_userbyid(relowner) AS owner,
|
||||
ftoptions, nspname as basensp, description
|
||||
FROM
|
||||
pg_class c
|
||||
JOIN
|
||||
pg_foreign_table ft ON c.oid=ft.ftrelid
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace nsp ON (nsp.oid=c.relnamespace)
|
||||
LEFT OUTER JOIN
|
||||
pg_description des ON (des.objoid=c.oid AND des.classoid='pg_class'::regclass)
|
||||
WHERE
|
||||
c.relnamespace = {{scid}}::oid
|
||||
ORDER BY c.relname;
|
|
@ -0,0 +1,31 @@
|
|||
SELECT
|
||||
c.oid, c.relname AS name, c.relacl, pg_get_userbyid(relowner) AS owner,
|
||||
ftoptions, srvname AS ftsrvname, description, nspname AS basensp,
|
||||
(SELECT
|
||||
array_agg(provider || '=' || label)
|
||||
FROM
|
||||
pg_shseclabel sl1
|
||||
WHERE
|
||||
sl1.objoid=c.oid) AS seclabels
|
||||
{% if foid %},
|
||||
(SELECT
|
||||
array_agg(i.inhparent) FROM pg_inherits i
|
||||
WHERE
|
||||
i.inhrelid = {{foid}}::oid GROUP BY i.inhrelid) AS inherits
|
||||
{% endif %}
|
||||
FROM
|
||||
pg_class c
|
||||
JOIN
|
||||
pg_foreign_table ft ON c.oid=ft.ftrelid
|
||||
LEFT OUTER JOIN
|
||||
pg_foreign_server fs ON ft.ftserver=fs.oid
|
||||
LEFT OUTER JOIN
|
||||
pg_description des ON (des.objoid=c.oid AND des.classoid='pg_class'::regclass)
|
||||
LEFT OUTER JOIN
|
||||
pg_namespace nsp ON (nsp.oid=c.relnamespace)
|
||||
WHERE
|
||||
c.relnamespace = {{scid}}::oid
|
||||
{% if foid %}
|
||||
AND c.oid = {{foid}}::oid
|
||||
{% endif %}
|
||||
ORDER BY c.relname;
|
|
@ -0,0 +1,182 @@
|
|||
{% import 'macros/schemas/security.macros' as SECLABLE %}
|
||||
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
|
||||
{% if data %}
|
||||
{% set name = o_data.name %}
|
||||
{% if data.name %}{% if data.name != o_data.name %}
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, o_data.name) }}
|
||||
RENAME TO {{ conn|qtIdent(data.name) }};
|
||||
{% set name = data.name %}
|
||||
{% endif %}{% endif %}
|
||||
{% if data.owner %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OWNER TO {{ data.owner }};
|
||||
{% endif %}
|
||||
{% if data.columns %}
|
||||
{% for c in data.columns.deleted %}
|
||||
{% if (not c.inheritedfrom or c.inheritedfrom =='' or c.inheritedfrom == None or c.inheritedfrom == 'None' ) %}
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
DROP COLUMN {{conn|qtIdent(c.attname)}};
|
||||
{% endif %}
|
||||
{% endfor -%}
|
||||
{% for c in data.columns.added %}
|
||||
{% if (not c.inheritedfrom or c.inheritedfrom =='' or c.inheritedfrom == None or c.inheritedfrom == 'None' ) %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ADD COLUMN {{conn|qtIdent(c.attname)}} {{ conn|qtTypeIdent(c.datatype) }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}
|
||||
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
||||
{% if c.typdefault %} DEFAULT {{c.typdefault}}{% endif %}
|
||||
{% if c.collname %} COLLATE {{c.collname}}{% endif %};
|
||||
{% endif %}
|
||||
{% endfor -%}
|
||||
{% for c in data.columns.changed %}
|
||||
{% set col_name = o_data['columns'][c.attnum]['attname'] %}
|
||||
{% if c.attname != o_data['columns'][c.attnum]['attname'] %}
|
||||
{% set col_name = c.attname %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
RENAME COLUMN {{conn|qtIdent(o_data['columns'][c.attnum]['attname'])}} TO {{conn|qtIdent(c.attname)}};
|
||||
{% endif %}
|
||||
{% if c.attnotnull != o_data['columns'][c.attnum]['attnotnull'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}}{% if c.attnotnull %} SET{% else %} DROP{% endif %} NOT NULL;
|
||||
{% endif %}
|
||||
{% if c.datatype != o_data['columns'][c.attnum]['datatype'] or c.typlen != o_data['columns'][c.attnum]['typlen'] or
|
||||
c.precision != o_data['columns'][c.attnum]['precision'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}} TYPE {{ conn|qtTypeIdent(c.datatype) }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %};
|
||||
{% endif %}
|
||||
{% if c.typdefault != o_data['columns'][c.attnum]['typdefault'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}}{% if c.typdefault %} SET DEFAULT {{c.typdefault}}{% else %} DROP DEFAULT{% endif %};
|
||||
{% endif %}
|
||||
{% if c.attstattarget != o_data['columns'][c.attnum]['attstattarget'] %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}} SET STATISTICS {% if c.attstattarget %}{{c.attstattarget}}{% else %}-1{% endif %};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.inherits and data.inherits|length > 0%}
|
||||
{% if o_data.inherits == None or o_data.inherits == 'None' %}
|
||||
{% set inherits = '' %}
|
||||
{% else %}
|
||||
{% set inherits = o_data.inherits %}
|
||||
{% endif %}
|
||||
{% for i in data.inherits %}
|
||||
{% if i not in inherits %}{% if i %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }} INHERIT {{i}};
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if o_data.inherits and 'inherits' in data %}
|
||||
{% if data.inherits == None or data.inherits == 'None' %}
|
||||
{% set inherits = '' %}
|
||||
{% else %}
|
||||
{% set inherits = data.inherits %}
|
||||
{% endif %}
|
||||
{% for i in o_data.inherits %}{% if i not in inherits %}{% if i %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }} NO INHERIT {{i}};{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.constraints %}
|
||||
{% for c in data.constraints.deleted %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
DROP CONSTRAINT {{conn|qtIdent(c.conname)}};
|
||||
{% endfor -%}
|
||||
{% for c in data.constraints.added %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ADD CONSTRAINT {{ conn|qtIdent(c.conname) }} CHECK ({{ c.consrc }}){% if not c.convalidated %} NOT VALID{% endif %}{% if c.connoinherit %} NO INHERIT{% endif %};
|
||||
{% endfor %}
|
||||
{% for c in data.constraints.changed %}
|
||||
{% if c.convalidated %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
VALIDATE CONSTRAINT {{ conn|qtIdent(c.conname) }};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.ftoptions %}
|
||||
{% for o in data.ftoptions.deleted %}
|
||||
{% if o.option and o.value %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OPTIONS ( DROP {{o.option}});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for o in data.ftoptions.added %}
|
||||
{% if o.option and o.value %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OPTIONS (ADD {{o.option}} {{o.value|qtLiteral}});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for o in data.ftoptions.changed %}
|
||||
{% if o.option and o.value %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OPTIONS (SET {{o.option}} {{o.value|qtLiteral}});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% set seclabels = data.seclabels %}
|
||||
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
|
||||
{% for r in seclabels.deleted %}
|
||||
|
||||
{{ SECLABLE.UNSET(conn, 'FOREIGN TABLE', name, r.provider, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||
{% for r in seclabels.added %}
|
||||
|
||||
{{ SECLABLE.SET(conn, 'FOREIGN TABLE', name, r.provider, r.security_label, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
|
||||
{% for r in seclabels.changed %}
|
||||
|
||||
{{ SECLABLE.SET(conn, 'FOREIGN TABLE', name, r.provider, r.security_label, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if data.description %}
|
||||
|
||||
COMMENT ON FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
{% endif -%}
|
||||
{% if data.acl %}
|
||||
{% if 'deleted' in data.acl %}
|
||||
{% for priv in data.acl.deleted %}
|
||||
|
||||
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, name, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if 'changed' in data.acl %}
|
||||
{% for priv in data.acl.changed %}
|
||||
|
||||
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, name, o_data.basensp) }}
|
||||
|
||||
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if 'added' in data.acl %}
|
||||
{% for priv in data.acl.added %}
|
||||
|
||||
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.basensp) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif -%}
|
||||
{% if data.basensp %}
|
||||
|
||||
ALTER FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
SET SCHEMA {{ conn|qtIdent(data.basensp) }};
|
||||
{% endif %}
|
||||
{% endif %}
|
Loading…
Reference in New Issue