Add support for foreign server

pull/3/head
Khushboo Vashi 2016-05-16 01:42:09 +05:30 committed by Ashesh Vashi
parent fcc3d112e2
commit d1e2b902dc
38 changed files with 2964 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

View File

@ -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'];
});

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1,7 @@
SELECT
conname, contype, consrc
FROM
pg_constraint
WHERE
conrelid={{foid}}::oid
ORDER by conname;

View File

@ -0,0 +1,5 @@
SELECT
srvname
FROM
pg_foreign_server
ORDER BY srvname;

View File

@ -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 %}

View File

@ -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;

View File

@ -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;

View File

@ -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 %}

View File

@ -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;

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1,7 @@
SELECT
conname, contype, consrc, conislocal
FROM
pg_constraint
WHERE
conrelid={{foid}}::oid
ORDER by conname;

View File

@ -0,0 +1,6 @@
SELECT
srvname
FROM
pg_foreign_server
ORDER BY
srvname;

View File

@ -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 %}

View File

@ -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;

View File

@ -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;

View File

@ -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 %}

View File

@ -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;

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1,7 @@
SELECT
oid as conoid, conname, contype, consrc, connoinherit, convalidated, conislocal
FROM
pg_constraint
WHERE
conrelid={{foid}}::oid
ORDER by conname;

View File

@ -0,0 +1,6 @@
SELECT
srvname
FROM
pg_foreign_server
ORDER
BY srvname;

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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;

View File

@ -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;

View File

@ -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 %}