Fixed issues reported while testing foreign table node. #640
parent
078a959e3d
commit
7ce07f7dcf
|
@ -10,6 +10,7 @@
|
|||
"""Implements the Foreign Table Module."""
|
||||
|
||||
import sys
|
||||
import re
|
||||
from functools import wraps
|
||||
|
||||
import json
|
||||
|
@ -28,11 +29,14 @@ from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
|
|||
from pgadmin.browser.utils import PGChildNodeView
|
||||
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
||||
make_response as ajax_response, gone
|
||||
from pgadmin.utils.compile_template_name import compile_template_path
|
||||
from pgadmin.utils.driver import get_driver
|
||||
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
||||
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
||||
columns import utils as column_utils
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
||||
triggers import utils as trigger_utils
|
||||
|
||||
|
||||
class ForeignTableModule(SchemaChildModule):
|
||||
|
@ -188,6 +192,8 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||
node_type = blueprint.node_type
|
||||
node_label = "Foreign Table"
|
||||
BASE_TEMPLATE_PATH = 'foreign_tables/sql/#{0}#'
|
||||
double_newline = '\n\n'
|
||||
pattern = '\n{2,}'
|
||||
|
||||
parent_ids = [
|
||||
{'type': 'int', 'id': 'gid'},
|
||||
|
@ -403,6 +409,17 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||
self.template_path = \
|
||||
self.BASE_TEMPLATE_PATH.format(self.manager.version)
|
||||
|
||||
self.foreign_table_column_template_path = compile_template_path(
|
||||
'foreign_table_columns/sql', self.manager.version)
|
||||
|
||||
self.column_template_path = compile_template_path(
|
||||
'columns/sql', self.manager.version)
|
||||
|
||||
# Template for trigger node
|
||||
self.trigger_template_path = \
|
||||
'triggers/sql/{0}/#{1}#'.format(self.manager.server_type,
|
||||
self.manager.version)
|
||||
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return wrap
|
||||
|
@ -918,6 +935,11 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||
|
||||
SQL = sql_header + SQL
|
||||
|
||||
trigger_sql = self._get_resql_for_triggers(
|
||||
foid, data['basensp'], data['name'])
|
||||
|
||||
SQL = SQL + trigger_sql
|
||||
|
||||
return ajax_response(response=SQL.strip('\n'))
|
||||
|
||||
@check_precondition
|
||||
|
@ -1012,9 +1034,9 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||
:return:
|
||||
"""
|
||||
for c in data['columns']['changed']:
|
||||
old_col_options = c['attfdwoptions'] = []
|
||||
if 'attfdwoptions' in c and c['attfdwoptions']:
|
||||
old_col_options = c['attfdwoptions']
|
||||
old_col_options = []
|
||||
if 'coloptions' in c and c['coloptions']:
|
||||
old_col_options = c['coloptions']
|
||||
|
||||
old_col_frmt_options = {}
|
||||
|
||||
|
@ -1089,7 +1111,13 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||
data['is_schema_diff'] = True
|
||||
old_data['columns_for_schema_diff'] = old_data['columns']
|
||||
|
||||
self._format_columns_data(data, old_data)
|
||||
# If name is not present in request data
|
||||
if 'name' not in data:
|
||||
data['name'] = old_data['name']
|
||||
|
||||
# If name if not present
|
||||
if 'schema' not in data:
|
||||
data['schema'] = old_data['basensp']
|
||||
|
||||
# Parse Privileges
|
||||
ForeignTableView._parse_privileges(data)
|
||||
|
@ -1109,6 +1137,37 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||
"/".join([self.template_path, self._UPDATE_SQL]),
|
||||
data=data, o_data=old_data, conn=self.conn
|
||||
)
|
||||
|
||||
# Removes trailing new lines
|
||||
if sql:
|
||||
sql = sql.strip('\n') + self.double_newline
|
||||
|
||||
# Parse/Format columns & create sql
|
||||
if 'columns' in data:
|
||||
# Parse the data coming from client
|
||||
data = column_utils.parse_format_columns(data, mode='edit')
|
||||
|
||||
columns = data['columns']
|
||||
column_sql = '\n'
|
||||
|
||||
# If column(s) is/are deleted
|
||||
column_sql = self._check_for_column_delete(columns, data,
|
||||
column_sql)
|
||||
|
||||
# If column(s) is/are changed
|
||||
column_sql = self._check_for_column_update(columns, data,
|
||||
column_sql, foid)
|
||||
|
||||
# If column(s) is/are added
|
||||
column_sql = self._check_for_column_add(columns, data,
|
||||
column_sql)
|
||||
|
||||
# Combine all the SQL together
|
||||
sql += column_sql.strip('\n')
|
||||
|
||||
sql = re.sub(self.pattern, self.double_newline, sql)
|
||||
sql = sql.strip('\n')
|
||||
|
||||
return sql, data['name'] if 'name' in data else old_data['name']
|
||||
else:
|
||||
data['columns'] = self._format_columns(data['columns'])
|
||||
|
@ -1123,6 +1182,83 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||
conn=self.conn)
|
||||
return sql, data['name']
|
||||
|
||||
def _check_for_column_delete(self, columns, data, column_sql):
|
||||
# If column(s) is/are deleted
|
||||
if 'deleted' in columns:
|
||||
for c in columns['deleted']:
|
||||
c['schema'] = data['schema']
|
||||
c['table'] = data['name']
|
||||
# Sql for drop column
|
||||
if 'inheritedfrom' not in c:
|
||||
column_sql += render_template("/".join(
|
||||
[self.foreign_table_column_template_path,
|
||||
self._DELETE_SQL]),
|
||||
data=c, conn=self.conn).strip('\n') + \
|
||||
self.double_newline
|
||||
return column_sql
|
||||
|
||||
def _check_for_column_update(self, columns, data, column_sql, tid):
|
||||
# Here we will be needing previous properties of column
|
||||
# so that we can compare & update it
|
||||
if 'changed' in columns:
|
||||
for c in columns['changed']:
|
||||
c['schema'] = data['schema']
|
||||
c['table'] = data['name']
|
||||
|
||||
properties_sql = render_template(
|
||||
"/".join([self.column_template_path,
|
||||
self._PROPERTIES_SQL]),
|
||||
tid=tid,
|
||||
clid=c['attnum'] if 'attnum' in c else None,
|
||||
show_sys_objects=self.blueprint.show_system_objects
|
||||
)
|
||||
|
||||
status, res = self.conn.execute_dict(properties_sql)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
old_col_data = res['rows'][0]
|
||||
|
||||
old_col_data['cltype'], \
|
||||
old_col_data['hasSqrBracket'] = \
|
||||
column_utils.type_formatter(old_col_data['cltype'])
|
||||
old_col_data = \
|
||||
column_utils.convert_length_precision_to_string(
|
||||
old_col_data)
|
||||
old_col_data = column_utils.fetch_length_precision(
|
||||
old_col_data)
|
||||
|
||||
old_col_data['cltype'] = \
|
||||
DataTypeReader.parse_type_name(
|
||||
old_col_data['cltype'])
|
||||
|
||||
# Sql for alter column
|
||||
if 'inheritedfrom' not in c and \
|
||||
'inheritedfromtable' not in c:
|
||||
column_sql += render_template("/".join(
|
||||
[self.foreign_table_column_template_path,
|
||||
self._UPDATE_SQL]),
|
||||
data=c, o_data=old_col_data, conn=self.conn
|
||||
).strip('\n') + self.double_newline
|
||||
return column_sql
|
||||
|
||||
def _check_for_column_add(self, columns, data, column_sql):
|
||||
# If column(s) is/are added
|
||||
if 'added' in columns:
|
||||
for c in columns['added']:
|
||||
c['schema'] = data['schema']
|
||||
c['table'] = data['name']
|
||||
|
||||
c = column_utils.convert_length_precision_to_string(c)
|
||||
|
||||
if 'inheritedfrom' not in c and \
|
||||
'inheritedfromtable' not in c:
|
||||
column_sql += render_template("/".join(
|
||||
[self.foreign_table_column_template_path,
|
||||
self._CREATE_SQL]),
|
||||
data=c, conn=self.conn).strip('\n') + \
|
||||
self.double_newline
|
||||
return column_sql
|
||||
|
||||
@check_precondition
|
||||
def dependents(self, gid, sid, did, scid, foid):
|
||||
"""
|
||||
|
@ -1248,6 +1384,14 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||
for col in cols['rows']:
|
||||
column_utils.fetch_length_precision(col)
|
||||
|
||||
if 'attoptions' in col and col['attoptions'] != '':
|
||||
col['attoptions'] = column_utils.parse_column_variables(
|
||||
col['attoptions'])
|
||||
|
||||
if 'attfdwoptions' in col and col['attfdwoptions'] != '':
|
||||
col['coloptions'] = column_utils.parse_options_for_column(
|
||||
col['attfdwoptions'])
|
||||
|
||||
self._get_edit_types(cols['rows'])
|
||||
|
||||
if cols and 'rows' in cols:
|
||||
|
@ -1768,6 +1912,32 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||
except Exception as e:
|
||||
return internal_server_error(errormsg=str(e))
|
||||
|
||||
def _get_resql_for_triggers(self, tid, schema,
|
||||
table):
|
||||
"""
|
||||
########################################
|
||||
# Reverse engineered sql for TRIGGERS
|
||||
########################################
|
||||
"""
|
||||
sql = render_template("/".join([self.trigger_template_path,
|
||||
self._NODES_SQL]), tid=tid)
|
||||
status, rset = self.conn.execute_2darray(sql)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=rset)
|
||||
|
||||
trigger_sql = ''
|
||||
for row in rset['rows']:
|
||||
trigger_sql = trigger_utils.get_reverse_engineered_sql(
|
||||
self.conn, schema=schema, table=table, tid=tid,
|
||||
trid=row['oid'], datlastsysoid=self._DATABASE_LAST_SYSTEM_OID,
|
||||
show_system_objects=self.blueprint.show_system_objects,
|
||||
template_path=None)
|
||||
trigger_sql = "\n" + trigger_sql
|
||||
|
||||
trigger_sql = re.sub(self.pattern, self.double_newline,
|
||||
trigger_sql)
|
||||
return trigger_sql
|
||||
|
||||
|
||||
SchemaDiffRegistry(blueprint.node_type, ForeignTableView)
|
||||
ForeignTableView.register_node_view(blueprint)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
ALTER FOREIGN TABLE public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "col_3_$%{}[]()&*^!@""'`\/#" TYPE time(10) with time zone ;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
|
|
|
@ -3,7 +3,7 @@ ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
|||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "new_col_1_$%{}[]()&*^!@""'`\/#" OPTIONS (ADD column_name 'test');
|
||||
ALTER FOREIGN TABLE public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "new_col_1_$%{}[]()&*^!@""'`\/#" TYPE real;
|
||||
|
||||
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."new_col_1_$%{}[]()&*^!@""'`\/#"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
ALTER FOREIGN TABLE public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "col_3_$%{}[]()&*^!@""'`\/#" TYPE time(10) with time zone ;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
|
|
|
@ -3,7 +3,7 @@ ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
|||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "new_col_1_$%{}[]()&*^!@""'`\/#" OPTIONS (ADD column_name 'test');
|
||||
ALTER FOREIGN TABLE public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "new_col_1_$%{}[]()&*^!@""'`\/#" TYPE real;
|
||||
|
||||
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."new_col_1_$%{}[]()&*^!@""'`\/#"
|
||||
|
|
|
@ -62,6 +62,25 @@ export default class ForeignTableSchema extends BaseUISchema {
|
|||
return isEmptyString(colstate.inheritedfrom);
|
||||
}
|
||||
|
||||
inSchemaWithColumnCheck(state) {
|
||||
if(this.nodeInfo && ('schema' in this.nodeInfo)) {
|
||||
if(this.isNew(state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We will disable control if it's system columns
|
||||
// inheritedfrom check is useful when we use this schema in table node
|
||||
// inheritedfrom has value then we should disable it
|
||||
if (!isEmptyString(state.inheritedfrom)){
|
||||
return true;
|
||||
}
|
||||
|
||||
// ie: it's position is less than 1
|
||||
return !(!_.isUndefined(state.attnum) && state.attnum > 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getTableOid(tabId) {
|
||||
// Here we will fetch the table oid from table name
|
||||
// iterate over list to find table oid
|
||||
|
@ -265,7 +284,7 @@ export class ColumnSchema extends BaseUISchema {
|
|||
attlen: undefined,
|
||||
attprecision: undefined,
|
||||
defval: undefined,
|
||||
attnotnull: undefined,
|
||||
attnotnull: false,
|
||||
collspcname: undefined,
|
||||
attstattarget:undefined,
|
||||
attnum: undefined,
|
||||
|
@ -279,6 +298,8 @@ export class ColumnSchema extends BaseUISchema {
|
|||
this.nodeInfo = nodeInfo;
|
||||
this.cltypeOptions = datatypeOptions;
|
||||
this.collspcnameOptions = collspcnameOptions;
|
||||
|
||||
this.datatypes = [];
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
|
@ -295,6 +316,28 @@ export class ColumnSchema extends BaseUISchema {
|
|||
return (!_.isUndefined(colconstype) && !_.isNull(colconstype) && colconstype == 'g');
|
||||
}
|
||||
|
||||
attlenRange(state) {
|
||||
for(let o of this.datatypes) {
|
||||
if ( state.cltype == o.value ) {
|
||||
if(o.length) return {min: o.min_val || 0, max: o.max_val};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
attprecisionRange(state) {
|
||||
for(let o of this.datatypes) {
|
||||
if ( state.cltype == o.value ) {
|
||||
if(o.precision) return {min: o.min_val || 0, max: o.max_val};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
attCell(state) {
|
||||
return { cell: this.attlenRange(state) ? 'int' : '' };
|
||||
}
|
||||
|
||||
get baseFields() {
|
||||
let obj = this;
|
||||
|
||||
|
@ -323,7 +366,7 @@ export class ColumnSchema extends BaseUISchema {
|
|||
},
|
||||
options: obj.cltypeOptions,
|
||||
optionsLoaded: (options)=>{
|
||||
obj.type_options = options;
|
||||
obj.datatypes = options;
|
||||
},
|
||||
cell: (row)=>{
|
||||
return {
|
||||
|
@ -364,124 +407,91 @@ export class ColumnSchema extends BaseUISchema {
|
|||
}
|
||||
},
|
||||
{
|
||||
id: 'inheritedfrom', label: gettext('Inherited From'), cell: 'label',
|
||||
type: 'label', readonly: true, editable: false, mode: ['create','properties', 'edit'],
|
||||
id: 'inheritedfrom', label: gettext('Inherited from'), cell: 'label', type: 'text',
|
||||
readonly: true, editable: false, mode: ['create','properties', 'edit'],
|
||||
},
|
||||
{
|
||||
id: 'attnum', label: gettext('Position'), cell: 'text',
|
||||
type: 'text', disabled: obj.inCatalog(), mode: ['properties'],
|
||||
},
|
||||
{
|
||||
id: 'attlen', label: gettext('Length'), cell: 'int',
|
||||
deps: ['cltype'], type: 'int', group: gettext('Definition'), minWidth: 60,
|
||||
disabled: (state) => {
|
||||
let val = state.attlen;
|
||||
// We will store type from selected from combobox
|
||||
if(!(_.isUndefined(state.inheritedid)
|
||||
|| _.isNull(state.inheritedid)
|
||||
|| _.isUndefined(state.inheritedfrom)
|
||||
|| _.isNull(state.inheritedfrom))) {
|
||||
|
||||
if (!_.isUndefined(val)) {
|
||||
state.attlen = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
let of_type = state.cltype,
|
||||
has_length = false;
|
||||
if(obj.type_options) {
|
||||
state.is_tlength = false;
|
||||
|
||||
// iterating over all the types
|
||||
_.each(obj.type_options, function(o) {
|
||||
// if type from selected from combobox matches in options
|
||||
if ( of_type == o.value ) {
|
||||
// if length is allowed for selected type
|
||||
if(o.length)
|
||||
{
|
||||
// set the values in model
|
||||
has_length = true;
|
||||
state.is_tlength = true;
|
||||
state.min_val = o.min_val;
|
||||
state.max_val = o.max_val;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!has_length && !_.isUndefined(val)) {
|
||||
state.attlen = undefined;
|
||||
}
|
||||
|
||||
return !(state.is_tlength);
|
||||
}
|
||||
if (!has_length && !_.isUndefined(val)) {
|
||||
state.attlen = undefined;
|
||||
}
|
||||
return true;
|
||||
id: 'attlen',
|
||||
label: gettext('Length'),
|
||||
group: gettext('Definition'),
|
||||
deps: ['cltype'],
|
||||
type: 'int',
|
||||
minWidth: 60,
|
||||
cell: (state)=>{
|
||||
return obj.attCell(state);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'attprecision', label: gettext('Scale'), cell: 'int', minWidth: 60,
|
||||
depChange: (state)=>{
|
||||
let range = this.attlenRange(state);
|
||||
if(range) {
|
||||
return {
|
||||
...state, min_val_attlen: range.min, max_val_attlen: range.max,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...state, attlen: null,
|
||||
};
|
||||
}
|
||||
},
|
||||
disabled: function(state) {
|
||||
return !obj.attlenRange(state);
|
||||
},
|
||||
editable: function(state) {
|
||||
// inheritedfrom has value then we should disable it
|
||||
if (!isEmptyString(state.inheritedfrom)) {
|
||||
return false;
|
||||
}
|
||||
return Boolean(obj.attlenRange(state));
|
||||
},
|
||||
|
||||
|
||||
},{
|
||||
id: 'min_val_attlen', skipChange: true, visible: false, type: '',
|
||||
},{
|
||||
id: 'max_val_attlen', skipChange: true, visible: false, type: '',
|
||||
},{
|
||||
id: 'attprecision', label: gettext('Scale'), width: 60, disableResizing: true,
|
||||
deps: ['cltype'], type: 'int', group: gettext('Definition'),
|
||||
disabled: (state) => {
|
||||
let val = state.attprecision;
|
||||
if(!(_.isUndefined(state.inheritedid)
|
||||
|| _.isNull(state.inheritedid)
|
||||
|| _.isUndefined(state.inheritedfrom)
|
||||
|| _.isNull(state.inheritedfrom))) {
|
||||
|
||||
if (!_.isUndefined(val)) {
|
||||
state.attprecision = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
let of_type = state.cltype,
|
||||
has_precision = false;
|
||||
|
||||
if(obj.type_options) {
|
||||
state.is_precision = false;
|
||||
// iterating over all the types
|
||||
_.each(obj.type_options, function(o) {
|
||||
// if type from selected from combobox matches in options
|
||||
if ( of_type == o.value ) {
|
||||
// if precession is allowed for selected type
|
||||
if(o.precision)
|
||||
{
|
||||
has_precision = true;
|
||||
// set the values in model
|
||||
state.is_precision = true;
|
||||
state.min_val = o.min_val;
|
||||
state.max_val = o.max_val;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!has_precision && !_.isUndefined(val)) {
|
||||
state.attprecision = undefined;
|
||||
}
|
||||
return !(state.is_precision);
|
||||
}
|
||||
if (!has_precision && !_.isUndefined(val)) {
|
||||
state.attprecision = undefined;
|
||||
}
|
||||
return true;
|
||||
cell: (state)=>{
|
||||
return obj.attCell(state);
|
||||
},
|
||||
depChange: (state)=>{
|
||||
let range = this.attprecisionRange(state);
|
||||
if(range) {
|
||||
return {
|
||||
...state, min_val_attprecision: range.min, max_val_attprecision: range.max,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...state, attprecision: null,
|
||||
};
|
||||
}
|
||||
},
|
||||
disabled: function(state) {
|
||||
return !this.attprecisionRange(state);
|
||||
},
|
||||
editable: function(state) {
|
||||
// inheritedfrom has value then we should disable it
|
||||
if (!isEmptyString(state.inheritedfrom)) {
|
||||
return false;
|
||||
}
|
||||
return Boolean(this.attprecisionRange(state));
|
||||
},
|
||||
},{
|
||||
id: 'min_val_attprecision', skipChange: true, visible: false, type: '',
|
||||
},{
|
||||
id: 'max_val_attprecision', skipChange: true, visible: false, type: '',
|
||||
},
|
||||
{
|
||||
id: 'attstattarget', label: gettext('Statistics'), cell: 'text',
|
||||
type: 'text', disabled: (state) => {
|
||||
if (obj.isNew()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj.nodeInfo.server.version < 90200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (_.isUndefined(state.inheritedid) || _.isNull(state.inheritedid) ||
|
||||
_.isUndefined(state.inheritedfrom) || _.isNull(state.inheritedfrom)) ? true : false;
|
||||
}, mode: ['properties', 'edit'],
|
||||
id: 'attstattarget',
|
||||
label: gettext('Statistics'),
|
||||
cell: 'text',
|
||||
type: 'text',
|
||||
readonly: obj.inSchemaWithColumnCheck,
|
||||
mode: ['properties', 'edit'],
|
||||
group: gettext('Definition'),
|
||||
},
|
||||
{
|
||||
|
@ -529,10 +539,9 @@ export class ColumnSchema extends BaseUISchema {
|
|||
group: gettext('Constraints'),
|
||||
type: (state)=>{
|
||||
let options = [
|
||||
{
|
||||
'label': gettext('NONE'),
|
||||
'value': 'n'},
|
||||
]; // You can't change the existing column to Generated column.
|
||||
{ 'label': gettext('NONE'), 'value': 'n'},
|
||||
];
|
||||
// You can't change the existing column to Generated column.
|
||||
if (this.isNew(state)) {
|
||||
options.push({
|
||||
'label': gettext('GENERATED'),
|
||||
|
@ -585,8 +594,10 @@ export class ColumnSchema extends BaseUISchema {
|
|||
disabled: (state)=>{
|
||||
if (!(_.isUndefined(obj.isNew)) && !obj.isNew(state)) { return false; }
|
||||
|
||||
return (_.isUndefined(state.inheritedid) || _.isNull(state.inheritedid) ||
|
||||
_.isUndefined(state.inheritedfrom) || _.isNull(state.inheritedfrom)) ? true : false;
|
||||
return (_.isUndefined(state.inheritedid)
|
||||
|| _.isNull(state.inheritedid) ||
|
||||
_.isUndefined(state.inheritedfrom) ||
|
||||
_.isNull(state.inheritedfrom));
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -10,18 +10,21 @@ ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
|||
{% if 'coloptions' in data and data.coloptions != None and data.coloptions|length > 0 %}
|
||||
{% set coloptions = data.coloptions %}
|
||||
{% if data.name %}
|
||||
{% set colname = data.name %}
|
||||
{% else %}
|
||||
{% set colname = o_data.name %}
|
||||
{% endif %}
|
||||
{% if 'added' in coloptions and coloptions.added|length > 0 %}
|
||||
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||
ALTER COLUMN {{conn|qtIdent(data.name)}} OPTIONS (ADD {% for opt in coloptions.added %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(opt.option) }} {{ opt.value|qtLiteral(conn) }}{% endfor %});
|
||||
ALTER COLUMN {{conn|qtIdent(colname)}} OPTIONS (ADD {% for opt in coloptions.added %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(opt.option) }} {{ opt.value|qtLiteral(conn) }}{% endfor %});
|
||||
{% endif %}
|
||||
{% if 'changed' in coloptions and coloptions.changed|length > 0 %}
|
||||
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||
ALTER COLUMN {{conn|qtIdent(data.name)}} OPTIONS (SET {% for opt in coloptions.changed %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(opt.option) }} {{ opt.value|qtLiteral(conn) }}{% endfor %});
|
||||
ALTER COLUMN {{conn|qtIdent(colname)}} OPTIONS (SET {% for opt in coloptions.changed %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(opt.option) }} {{ opt.value|qtLiteral(conn) }}{% endfor %});
|
||||
{% endif %}
|
||||
{% if 'deleted' in coloptions and coloptions.deleted|length > 0 %}
|
||||
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||
ALTER COLUMN {{conn|qtIdent(data.name)}} OPTIONS (DROP {% for opt in coloptions.deleted %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(opt.option) }}{% endfor %});
|
||||
{% endif %}
|
||||
ALTER COLUMN {{conn|qtIdent(colname)}} OPTIONS (DROP {% for opt in coloptions.deleted %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(opt.option) }}{% endfor %});
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{### Alter column type and collation ###}
|
||||
|
@ -31,7 +34,7 @@ ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
|||
-- The SQL statement below would normally be used to alter the cltype for the {{o_data.name}} column, however,
|
||||
-- the current datatype cannot be cast to the target cltype so this conversion cannot be made automatically.
|
||||
{% endif %}
|
||||
{% if data.col_type_conversion is defined and data.col_type_conversion == False %} -- {% endif %}ALTER FOREIGN TABLE {{conn|qtIdent(data.schema, data.table)}}
|
||||
{% if data.col_type_conversion is defined and data.col_type_conversion == False %} -- {% endif %}ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||
{% if data.col_type_conversion is defined and data.col_type_conversion == False %} -- {% endif %} ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} TYPE {{ GET_TYPE.UPDATE_TYPE_SQL(conn, data, o_data) }}{% if data.collspcname and data.collspcname != o_data.collspcname %}
|
||||
COLLATE {{data.collspcname}}{% elif o_data.collspcname %} COLLATE {{o_data.collspcname}}{% endif %};
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ CREATE FOREIGN TABLE{% if add_not_exists_clause %} IF NOT EXISTS{% endif %} {{ c
|
|||
{% for o in c.coloptions %}{% if o.option is defined and o.value is defined %}
|
||||
{% if loop.first %} OPTIONS ({% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral(conn)}}{% if loop.last %}){% endif %}{% endif %}
|
||||
{% endfor %}{% endif %}
|
||||
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
||||
{% if c.attnotnull %} NOT NULL{% endif %}
|
||||
{% if c.defval is defined and c.defval is not none %} DEFAULT {{c.defval}}{% endif %}
|
||||
{% if c.collname %} COLLATE {{c.collname}}{% endif %}
|
||||
{% if not loop.last %},
|
||||
|
|
|
@ -20,7 +20,7 @@ CREATE FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, o_data.name) }}(
|
|||
{% for o in c.coloptions %}{% if o.option is defined and o.value is defined %}
|
||||
{% if loop.first %} OPTIONS ({% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral(conn)}}{% if loop.last %}){% endif %}{% endif %}
|
||||
{% endfor %}{% endif %}
|
||||
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
||||
{% if c.attnotnull %} NOT NULL{% endif %}
|
||||
{% if c.typdefault is defined and c.typdefault is not none %} DEFAULT {{c.typdefault}}{% endif %}
|
||||
{% if c.collname %} COLLATE {{c.collname}}{% endif %}
|
||||
{% if not loop.last %},
|
||||
|
|
|
@ -15,14 +15,16 @@ WITH INH_TABLES AS
|
|||
)
|
||||
SELECT INH.inheritedfrom, INH.inheritedid, att.attoptions, att.atttypid, attfdwoptions,
|
||||
att.attname as name, att.attndims, att.atttypmod, pg_catalog.format_type(t.oid,NULL) AS cltype,
|
||||
att.attnotnull, att.attstattarget, att.attnum, pg_catalog.format_type(t.oid, att.atttypmod) AS fulltype,
|
||||
att.attnotnull, att.attstorage, att.attstattarget, att.attnum, pg_catalog.format_type(t.oid, att.atttypmod) AS fulltype,
|
||||
CASE WHEN t.typelem > 0 THEN t.typelem ELSE t.oid END as elemoid,
|
||||
(CASE WHEN (att.attidentity in ('a', 'd')) THEN 'i' WHEN (att.attgenerated in ('s')) THEN 'g' ELSE 'n' END) AS colconstype,
|
||||
(CASE WHEN (att.attgenerated in ('s')) THEN pg_catalog.pg_get_expr(def.adbin, def.adrelid) END) AS genexpr,
|
||||
(SELECT nspname FROM pg_catalog.pg_namespace WHERE oid = t.typnamespace) as typnspname,
|
||||
pg_catalog.format_type(t.oid,NULL) AS typname,
|
||||
CASE WHEN length(cn.nspname::text) > 0 AND length(cl.collname::text) > 0 THEN
|
||||
pg_catalog.concat(cn.nspname, '."', cl.collname,'"')
|
||||
ELSE '' END AS collname,
|
||||
pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS typdefault,
|
||||
pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS defval,
|
||||
(SELECT COUNT(1) from pg_catalog.pg_type t2 WHERE t2.typname=t.typname) > 1 AS isdup,
|
||||
des.description
|
||||
FROM
|
||||
|
|
|
@ -12,80 +12,6 @@ ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, o_data.name) }}
|
|||
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
OWNER TO {{ conn|qtIdent(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 IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
DROP COLUMN {{conn|qtIdent(c.name)}};
|
||||
|
||||
{% 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 IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ADD COLUMN {{conn|qtIdent(c.name)}} {{ c.cltype }}{% if c.attlen %}({{c.attlen}}{% if c.attprecision %}, {{c.attprecision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}
|
||||
{% if c.coloptions %}
|
||||
{% for o in c.coloptions %}{% if o.option is defined and o.value is defined %}
|
||||
{% if loop.first %} OPTIONS ({% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral(conn)}}{% if loop.last %}){% endif %}{% endif %}
|
||||
{% endfor %}{% endif %}
|
||||
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
||||
{% if c.defval is defined and c.defval is not none %} DEFAULT {{c.defval}}{% endif %}
|
||||
{% if c.collname %} COLLATE {{c.collname}}{% endif %};
|
||||
|
||||
{% endif %}
|
||||
{% endfor -%}
|
||||
{% for c in data.columns.changed %}
|
||||
{% set col_name = o_data['columns'][c.attnum]['name'] %}
|
||||
{% if c.name %}{% if c.name != o_data['columns'][c.attnum]['name'] %}
|
||||
{% set col_name = c.name %}
|
||||
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
RENAME COLUMN {{conn|qtIdent(o_data['columns'][c.attnum]['name'])}} TO {{conn|qtIdent(c.name)}};
|
||||
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if c.attnotnull != o_data['columns'][c.attnum]['attnotnull'] %}
|
||||
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}}{% if c.attnotnull %} SET{% else %} DROP{% endif %} NOT NULL;
|
||||
|
||||
{% endif %}
|
||||
{% if c.cltype != o_data['columns'][c.attnum]['cltype'] or c.attlen != o_data['columns'][c.attnum]['attlen'] or
|
||||
c.attprecision != o_data['columns'][c.attnum]['attprecision'] %}
|
||||
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}} TYPE {{ c.cltype }}{% if c.attlen %}({{c.attlen}}{% if c.attprecision %}, {{c.attprecision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %};
|
||||
|
||||
{% endif %}
|
||||
{% if c.typdefault is defined and 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 is defined and c.typdefault != '' %} SET DEFAULT {{c.typdefault}}{% else %} DROP DEFAULT{% endif %};
|
||||
|
||||
{% endif %}
|
||||
{% if c.attstattarget != o_data['columns'][c.attnum]['attstattarget'] %}
|
||||
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}} SET STATISTICS {% if c.attstattarget %}{{c.attstattarget}}{% else %}-1{% endif %};
|
||||
|
||||
{% endif %}
|
||||
{% if c.coloptions_updated %}
|
||||
{% for o in c.coloptions_updated.deleted %}
|
||||
{% if o.option %}
|
||||
{% if loop.first %}ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}} OPTIONS (DROP {% endif %}{% if not loop.first %}, {% endif %}{{o.option}}{% if loop.last %}){% endif %};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for o in c.coloptions_updated.added %}
|
||||
{% if o.option is defined and o.value is defined %}
|
||||
{% if loop.first %}ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}} OPTIONS (ADD {% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral(conn)}}{% if loop.last %});{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for o in c.coloptions_updated.changed %}
|
||||
{% if o.option is defined and o.value is defined %}
|
||||
{% if loop.first %}ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||
ALTER COLUMN {{conn|qtIdent(col_name)}} OPTIONS (SET {% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral(conn)}}{% if loop.last %});{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.inherits and data.inherits|length > 0%}
|
||||
{% if o_data.inherits == None or o_data.inherits == 'None' %}
|
||||
|
|
|
@ -233,7 +233,7 @@
|
|||
"name": "Update Foreign Table: With existing foreign table.",
|
||||
"is_positive_test": true,
|
||||
"inventory_data": {
|
||||
"query": "\"CREATE FOREIGN TABLE %s.%s (col1 character varying(10) OPTIONS (columnoptionkey 'columnOptionVal') NULL ) SERVER %s;\" %(schema_name, foreign_table_name, fsrv_name)"
|
||||
"query": "\"CREATE FOREIGN TABLE %s.%s (col1 character varying(10) OPTIONS (column_name 'columnOptionVal') NULL ) SERVER %s;\" %(schema_name, foreign_table_name, fsrv_name)"
|
||||
},
|
||||
"test_data": {
|
||||
"description": "This is foreign table update comment",
|
||||
|
@ -264,7 +264,7 @@
|
|||
{
|
||||
"coloptions": [
|
||||
{
|
||||
"option": "OptionKey",
|
||||
"option": "column_name",
|
||||
"value": "OptionValue"
|
||||
}
|
||||
],
|
||||
|
@ -279,7 +279,7 @@
|
|||
"attstattarget": -1,
|
||||
"attoptions": null,
|
||||
"attfdwoptions": [
|
||||
"ColOptionKey=ColOptionValue"
|
||||
"column_name=ColOptionValue"
|
||||
],
|
||||
"attndims": 0,
|
||||
"atttypmod": -1,
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 bigint NULL,
|
||||
col2 text NULL COLLATE pg_catalog."default"
|
||||
col1 bigint NOT NULL,
|
||||
col2 text COLLATE pg_catalog."default"
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (schema_name 'public', table_name 'test_table');
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 bigint NULL,
|
||||
col2 text NULL COLLATE pg_catalog."default"
|
||||
col1 bigint NOT NULL,
|
||||
col2 text COLLATE pg_catalog."default"
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (schema_name 'public', table_name 'test_table');
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 integer NULL
|
||||
col1 integer
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (schema_name 'test_public', table_name 'test_table');
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
DROP COLUMN col2;
|
||||
OPTIONS (SET schema_name 'test_public');
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN col1 DROP NOT NULL;
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#" DROP COLUMN IF EXISTS col2;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN col1 TYPE integer;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN col1 SET STATISTICS -1;
|
||||
ALTER COLUMN col1 DROP NOT NULL;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
OPTIONS (SET schema_name 'test_public');
|
||||
ALTER COLUMN col1 SET STATISTICS 10;
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 bigint NULL,
|
||||
col2 text NULL COLLATE pg_catalog."default"
|
||||
col1 bigint NOT NULL,
|
||||
col2 text COLLATE pg_catalog."default"
|
||||
)
|
||||
SERVER test_fs_for_foreign_table;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN col1 bigint NULL;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN col2 text NULL;
|
||||
|
||||
COMMENT ON FOREIGN TABLE public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
IS 'Test Comment';
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN col1 bigint NOT NULL;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN col2 text;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 integer NULL
|
||||
col1 integer
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (table_name 'test_table');
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 bigint NULL,
|
||||
col2 text NULL COLLATE pg_catalog."default"
|
||||
col1 bigint,
|
||||
col2 text COLLATE pg_catalog."default"
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (schema_name 'public', table_name 'test_table');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
CREATE FOREIGN TABLE public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 bigint NULL,
|
||||
col2 text NULL
|
||||
col1 bigint,
|
||||
col2 text
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (schema_name 'public', table_name 'test_table');
|
||||
|
|
|
@ -99,7 +99,8 @@
|
|||
"ftsrvname": "test_fs_for_foreign_table",
|
||||
"columns": []
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"type": "alter",
|
||||
"name": "Alter Foreign Table comment and add columns",
|
||||
"endpoint": "NODE-foreign_table.obj_id",
|
||||
|
@ -111,7 +112,8 @@
|
|||
"added": [{
|
||||
"name":"col1",
|
||||
"cltype":"bigint",
|
||||
"coloptions":[]
|
||||
"coloptions":[],
|
||||
"attnotnull": true
|
||||
},{
|
||||
"name":"col2",
|
||||
"cltype":"text",
|
||||
|
@ -121,7 +123,8 @@
|
|||
},
|
||||
"expected_sql_file": "alter_comment_add_columns.sql",
|
||||
"expected_msql_file": "alter_comment_add_columns_msql.sql"
|
||||
},{
|
||||
},
|
||||
{
|
||||
"type": "alter",
|
||||
"name": "Alter Foreign Table add constraints and options",
|
||||
"endpoint": "NODE-foreign_table.obj_id",
|
||||
|
@ -148,7 +151,8 @@
|
|||
},
|
||||
"expected_sql_file": "alter_add_cons_opts.sql",
|
||||
"expected_msql_file": "alter_add_cons_opts_msql.sql"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"type": "alter",
|
||||
"name": "Alter Foreign Table add privileges",
|
||||
"endpoint": "NODE-foreign_table.obj_id",
|
||||
|
@ -169,7 +173,8 @@
|
|||
},
|
||||
"expected_sql_file": "alter_add_priv.sql",
|
||||
"expected_msql_file": "alter_add_priv_msql.sql"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"type": "alter",
|
||||
"name": "Alter Foreign Table change option and column",
|
||||
"endpoint": "NODE-foreign_table.obj_id",
|
||||
|
@ -187,10 +192,11 @@
|
|||
"name": "col1",
|
||||
"attnum": 1,
|
||||
"attoptions": null,
|
||||
"attnotnull":false,
|
||||
"attstattarget": 10,
|
||||
"collname": "",
|
||||
"coloptions": [],
|
||||
"cltype": "integer",
|
||||
"fulltype": "bigint"
|
||||
"cltype": "integer"
|
||||
}],
|
||||
"deleted": [{
|
||||
"name":"col2",
|
||||
|
@ -200,7 +206,8 @@
|
|||
},
|
||||
"expected_sql_file": "alter_col_opts.sql",
|
||||
"expected_msql_file": "alter_col_opts_msql.sql"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"type": "alter",
|
||||
"name": "Alter Foreign Table remove option, constraint, privileges",
|
||||
"endpoint": "NODE-foreign_table.obj_id",
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 bigint NULL,
|
||||
col2 text NULL COLLATE pg_catalog."default"
|
||||
col1 bigint NOT NULL,
|
||||
col2 text COLLATE pg_catalog."default"
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (schema_name 'public', table_name 'test_table');
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 bigint NULL,
|
||||
col2 text NULL COLLATE pg_catalog."default"
|
||||
col1 bigint NOT NULL,
|
||||
col2 text COLLATE pg_catalog."default"
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (schema_name 'public', table_name 'test_table');
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 integer NULL
|
||||
col1 integer
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (schema_name 'test_public', table_name 'test_table');
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
DROP COLUMN col2;
|
||||
OPTIONS (SET schema_name 'test_public');
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN col1 DROP NOT NULL;
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#" DROP COLUMN IF EXISTS col2;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN col1 TYPE integer;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN col1 SET STATISTICS -1;
|
||||
ALTER COLUMN col1 DROP NOT NULL;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
OPTIONS (SET schema_name 'test_public');
|
||||
ALTER COLUMN col1 SET STATISTICS 10;
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 bigint NULL,
|
||||
col2 text NULL COLLATE pg_catalog."default"
|
||||
col1 bigint NOT NULL,
|
||||
col2 text COLLATE pg_catalog."default"
|
||||
)
|
||||
SERVER test_fs_for_foreign_table;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN col1 bigint NULL;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN col2 text NULL;
|
||||
|
||||
COMMENT ON FOREIGN TABLE public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
IS 'Test Comment';
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN col1 bigint NOT NULL;
|
||||
|
||||
ALTER FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN col2 text;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 integer NULL
|
||||
col1 integer
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (table_name 'test_table');
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
-- DROP FOREIGN TABLE IF EXISTS public."FT1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
CREATE FOREIGN TABLE IF NOT EXISTS public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 bigint NULL,
|
||||
col2 text NULL COLLATE pg_catalog."default"
|
||||
col1 bigint,
|
||||
col2 text COLLATE pg_catalog."default"
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (schema_name 'public', table_name 'test_table');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
CREATE FOREIGN TABLE public."FT1_$%{}[]()&*^!@""'`\/#"(
|
||||
col1 bigint NULL,
|
||||
col2 text NULL
|
||||
col1 bigint,
|
||||
col2 text
|
||||
)
|
||||
SERVER test_fs_for_foreign_table
|
||||
OPTIONS (schema_name 'public', table_name 'test_table');
|
||||
|
|
|
@ -109,7 +109,8 @@
|
|||
"added": [{
|
||||
"name":"col1",
|
||||
"cltype":"bigint",
|
||||
"coloptions":[]
|
||||
"coloptions":[],
|
||||
"attnotnull": true
|
||||
},{
|
||||
"name":"col2",
|
||||
"cltype":"text",
|
||||
|
@ -185,10 +186,11 @@
|
|||
"name": "col1",
|
||||
"attnum": 1,
|
||||
"attoptions": null,
|
||||
"attnotnull":false,
|
||||
"attstattarget": 10,
|
||||
"collname": "",
|
||||
"coloptions": [],
|
||||
"cltype": "integer",
|
||||
"fulltype": "bigint"
|
||||
"cltype": "integer"
|
||||
}],
|
||||
"deleted": [{
|
||||
"name":"col2",
|
||||
|
|
|
@ -82,16 +82,17 @@ export default class ColumnSchema extends BaseUISchema {
|
|||
}
|
||||
|
||||
if(this.nodeInfo && ('schema' in this.nodeInfo)) {
|
||||
// We will disable control if it's system columns
|
||||
// inheritedfrom check is useful when we use this schema in table node
|
||||
// inheritedfrom has value then we should disable it
|
||||
if(!_.isUndefined(state.inheritedfrom)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(this.isNew(state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We will disable control if it's system columns
|
||||
// inheritedfrom check is useful when we use this schema in table node
|
||||
// inheritedfrom has value then we should disable it
|
||||
if (!isEmptyString(state.inheritedfrom)){
|
||||
return true;
|
||||
}
|
||||
|
||||
// ie: it's position is less than 1
|
||||
return !(!_.isUndefined(state.attnum) && state.attnum > 0);
|
||||
}
|
||||
|
|
|
@ -139,12 +139,7 @@ def column_formatter(conn, tid, clid, data, edit_types_list=None,
|
|||
|
||||
# We need to format variables according to client js collection
|
||||
if 'attoptions' in data and data['attoptions'] is not None:
|
||||
spcoptions = []
|
||||
for spcoption in data['attoptions']:
|
||||
k, v = spcoption.split('=')
|
||||
spcoptions.append({'name': k, 'value': v})
|
||||
|
||||
data['attoptions'] = spcoptions
|
||||
data['attoptions'] = parse_column_variables(data['attoptions'])
|
||||
|
||||
# Need to format security labels according to client js collection
|
||||
if 'seclabels' in data and data['seclabels'] is not None:
|
||||
|
@ -157,7 +152,7 @@ def column_formatter(conn, tid, clid, data, edit_types_list=None,
|
|||
|
||||
# Get formatted Column Options
|
||||
if 'attfdwoptions' in data and data['attfdwoptions'] != '':
|
||||
data['coloptions'] = _parse_options_for_column(data['attfdwoptions'])
|
||||
data['coloptions'] = parse_options_for_column(data['attfdwoptions'])
|
||||
|
||||
# We need to parse & convert ACL coming from database to json format
|
||||
SQL = render_template("/".join([template_path, 'acl.sql']),
|
||||
|
@ -194,7 +189,7 @@ def column_formatter(conn, tid, clid, data, edit_types_list=None,
|
|||
return data
|
||||
|
||||
|
||||
def _parse_options_for_column(db_variables):
|
||||
def parse_options_for_column(db_variables):
|
||||
"""
|
||||
Function to format the output for variables.
|
||||
|
||||
|
@ -446,3 +441,13 @@ def fetch_length_precision(data):
|
|||
data['attprecision'] = None
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def parse_column_variables(col_variables):
|
||||
# We need to format variables according to client js collection
|
||||
spcoptions = []
|
||||
if col_variables is not None:
|
||||
for spcoption in col_variables:
|
||||
k, v = spcoption.split('=')
|
||||
spcoptions.append({'name': k, 'value': v})
|
||||
return spcoptions
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
WITH INH_TABLES AS
|
||||
(SELECT
|
||||
at.attname AS name, ph.inhparent AS inheritedid, ph.inhseqno,
|
||||
pg_catalog.concat(nmsp_parent.nspname, '.',parent.relname ) AS inheritedfrom
|
||||
FROM
|
||||
pg_catalog.pg_attribute at
|
||||
JOIN
|
||||
pg_catalog.pg_inherits ph ON ph.inhparent = at.attrelid AND ph.inhrelid = 33896::oid
|
||||
JOIN
|
||||
pg_catalog.pg_class parent ON ph.inhparent = parent.oid
|
||||
JOIN
|
||||
pg_catalog.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 DISTINCT ON (att.attnum) att.attname as name, att.atttypid, att.attlen, att.attnum, att.attndims,
|
||||
att.atttypmod, att.attacl, att.attnotnull, att.attoptions, att.attfdwoptions, att.attstattarget,
|
||||
att.attstorage, att.attidentity,
|
||||
|
@ -5,6 +20,8 @@ SELECT DISTINCT ON (att.attnum) att.attname as name, att.atttypid, att.attlen, a
|
|||
pg_catalog.format_type(ty.oid,NULL) AS typname,
|
||||
pg_catalog.format_type(ty.oid,att.atttypmod) AS displaytypname,
|
||||
pg_catalog.format_type(ty.oid,att.atttypmod) AS cltype,
|
||||
inh.inheritedfrom,
|
||||
inh.inheritedid,
|
||||
CASE WHEN ty.typelem > 0 THEN ty.typelem ELSE ty.oid END as elemoid,
|
||||
(SELECT nspname FROM pg_catalog.pg_namespace WHERE oid = ty.typnamespace) as typnspname,
|
||||
ty.typstorage AS defaultstorage,
|
||||
|
@ -31,6 +48,7 @@ FROM pg_catalog.pg_attribute att
|
|||
LEFT OUTER JOIN pg_catalog.pg_namespace nspc ON coll.collnamespace=nspc.oid
|
||||
LEFT OUTER JOIN pg_catalog.pg_sequence seq ON cs.oid=seq.seqrelid
|
||||
LEFT OUTER JOIN pg_catalog.pg_class tab on tab.oid = att.attrelid
|
||||
LEFT OUTER join INH_TABLES as INH ON att.attname = INH.name
|
||||
WHERE att.attrelid = {{tid}}::oid
|
||||
{% if clid %}
|
||||
AND att.attnum = {{clid}}::int
|
||||
|
|
Loading…
Reference in New Issue