mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
This commit is contained in:
parent
5736e173ea
commit
3cd547f879
Binary file not shown.
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 88 KiB |
@ -10,11 +10,10 @@
|
|||||||
"""Implements the Foreign Table Module."""
|
"""Implements the Foreign Table Module."""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from flask import render_template, make_response, request, jsonify, \
|
from flask import render_template, request, jsonify, \
|
||||||
current_app
|
current_app
|
||||||
from flask_babel import gettext
|
from flask_babel import gettext
|
||||||
|
|
||||||
@ -29,10 +28,11 @@ from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
|
|||||||
from pgadmin.browser.utils import PGChildNodeView
|
from pgadmin.browser.utils import PGChildNodeView
|
||||||
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
||||||
make_response as ajax_response, gone
|
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.utils.driver import get_driver
|
||||||
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
||||||
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
||||||
|
columns import utils as column_utils
|
||||||
|
|
||||||
|
|
||||||
class ForeignTableModule(SchemaChildModule):
|
class ForeignTableModule(SchemaChildModule):
|
||||||
@ -88,6 +88,10 @@ class ForeignTableModule(SchemaChildModule):
|
|||||||
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
||||||
constraints import blueprint as module
|
constraints import blueprint as module
|
||||||
self.submodules.append(module)
|
self.submodules.append(module)
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas. \
|
||||||
|
foreign_tables.foreign_table_columns import \
|
||||||
|
foreign_table_column_blueprint as module
|
||||||
|
self.submodules.append(module)
|
||||||
super().register(app, options)
|
super().register(app, options)
|
||||||
|
|
||||||
|
|
||||||
@ -216,6 +220,7 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
'get_foreign_servers': [{'get': 'get_foreign_servers'},
|
'get_foreign_servers': [{'get': 'get_foreign_servers'},
|
||||||
{'get': 'get_foreign_servers'}],
|
{'get': 'get_foreign_servers'}],
|
||||||
'get_tables': [{'get': 'get_tables'}, {'get': 'get_tables'}],
|
'get_tables': [{'get': 'get_tables'}, {'get': 'get_tables'}],
|
||||||
|
'set_trigger': [{'put': 'enable_disable_triggers'}],
|
||||||
'get_columns': [{'get': 'get_columns'}, {'get': 'get_columns'}],
|
'get_columns': [{'get': 'get_columns'}, {'get': 'get_columns'}],
|
||||||
'select_sql': [{'get': 'select_sql'}],
|
'select_sql': [{'get': 'select_sql'}],
|
||||||
'insert_sql': [{'get': 'insert_sql'}],
|
'insert_sql': [{'get': 'insert_sql'}],
|
||||||
@ -451,7 +456,9 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
scid,
|
scid,
|
||||||
row['name'],
|
row['name'],
|
||||||
icon="icon-foreign_table",
|
icon="icon-foreign_table",
|
||||||
description=row['description']
|
description=row['description'],
|
||||||
|
tigger_count=row['triggercount'],
|
||||||
|
has_enable_triggers=row['has_enable_triggers'],
|
||||||
))
|
))
|
||||||
|
|
||||||
return make_json_response(
|
return make_json_response(
|
||||||
@ -1160,15 +1167,14 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
"""
|
"""
|
||||||
cols = []
|
cols = []
|
||||||
for c in columns:
|
for c in columns:
|
||||||
if len(c) > 0:
|
if len(c) > 0 and 'cltype' in c:
|
||||||
if '[]' in c['datatype']:
|
if '[]' in c['cltype']:
|
||||||
c['datatype'] = c['datatype'].replace('[]', '')
|
c['cltype'] = c['cltype'].replace('[]', '')
|
||||||
c['isArrayType'] = True
|
c['isArrayType'] = True
|
||||||
else:
|
else:
|
||||||
c['isArrayType'] = False
|
c['isArrayType'] = False
|
||||||
cols.append(c)
|
cols.append(c)
|
||||||
|
return cols if cols else columns
|
||||||
return cols
|
|
||||||
|
|
||||||
def _fetch_properties(self, gid, sid, did, scid, foid, inherits=False, ):
|
def _fetch_properties(self, gid, sid, did, scid, foid, inherits=False, ):
|
||||||
"""
|
"""
|
||||||
@ -1238,18 +1244,44 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
if not status:
|
if not status:
|
||||||
return False, internal_server_error(errormsg=cols)
|
return False, internal_server_error(errormsg=cols)
|
||||||
|
|
||||||
self._get_datatype_precision(cols)
|
# Fetch length and precision data
|
||||||
|
for col in cols['rows']:
|
||||||
|
column_utils.fetch_length_precision(col)
|
||||||
|
|
||||||
|
self._get_edit_types(cols['rows'])
|
||||||
|
|
||||||
if cols and 'rows' in cols:
|
if cols and 'rows' in cols:
|
||||||
data['columns'] = cols['rows']
|
data['columns'] = cols['rows']
|
||||||
|
|
||||||
# Get Inherited table names from their OID
|
# Get Inherited table names from their OID
|
||||||
is_error, errmsg = self._get_inherited_table_name(data, inherits)
|
is_error, errmsg = self._get_inherited_table_name(data, inherits)
|
||||||
|
|
||||||
if is_error:
|
if is_error:
|
||||||
return False, internal_server_error(errormsg=errmsg)
|
return False, internal_server_error(errormsg=errmsg)
|
||||||
|
|
||||||
return True, data
|
return True, data
|
||||||
|
|
||||||
|
def _get_edit_types(self, cols):
|
||||||
|
edit_types = {}
|
||||||
|
for col in cols:
|
||||||
|
edit_types[col['atttypid']] = []
|
||||||
|
|
||||||
|
if len(cols) > 0:
|
||||||
|
SQL = render_template("/".join([self.template_path,
|
||||||
|
'edit_mode_types_multi.sql']),
|
||||||
|
type_ids=",".join(map(lambda x: str(x),
|
||||||
|
edit_types.keys())))
|
||||||
|
status, res = self.conn.execute_2darray(SQL)
|
||||||
|
for row in res['rows']:
|
||||||
|
edit_types[row['main_oid']] = sorted(row['edit_types'])
|
||||||
|
|
||||||
|
for column in cols:
|
||||||
|
edit_type_list = edit_types[column['atttypid']]
|
||||||
|
edit_type_list.append(column['fulltype'])
|
||||||
|
column['edit_types'] = sorted(edit_type_list)
|
||||||
|
column['cltype'] = \
|
||||||
|
DataTypeReader.parse_type_name(column['cltype'])
|
||||||
|
|
||||||
def _get_datatype_precision(self, cols):
|
def _get_datatype_precision(self, cols):
|
||||||
"""
|
"""
|
||||||
The Length and the precision of the Datatype should be separated.
|
The Length and the precision of the Datatype should be separated.
|
||||||
@ -1262,11 +1294,11 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
substr = self.extract_type_length_precision(c)
|
substr = self.extract_type_length_precision(c)
|
||||||
typlen = substr.split(",")
|
typlen = substr.split(",")
|
||||||
if len(typlen) > 1:
|
if len(typlen) > 1:
|
||||||
c['typlen'] = self.convert_typlen_to_int(typlen)
|
c['attlen'] = self.convert_typlen_to_int(typlen)
|
||||||
c['precision'] = self.convert_precision_to_int(typlen)
|
c['attprecision'] = self.convert_precision_to_int(typlen)
|
||||||
else:
|
else:
|
||||||
c['typlen'] = self.convert_typlen_to_int(typlen)
|
c['attlen'] = self.convert_typlen_to_int(typlen)
|
||||||
c['precision'] = None
|
c['attprecision'] = None
|
||||||
|
|
||||||
# Get formatted Column Options
|
# Get formatted Column Options
|
||||||
if 'attfdwoptions' in c and c['attfdwoptions'] != '':
|
if 'attfdwoptions' in c and c['attfdwoptions'] != '':
|
||||||
@ -1393,7 +1425,7 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
|
|
||||||
columns = []
|
columns = []
|
||||||
for c in data['columns']:
|
for c in data['columns']:
|
||||||
columns.append(self.qtIdent(self.conn, c['attname']))
|
columns.append(self.qtIdent(self.conn, c['name']))
|
||||||
|
|
||||||
if len(columns) > 0:
|
if len(columns) > 0:
|
||||||
columns = ", ".join(columns)
|
columns = ", ".join(columns)
|
||||||
@ -1434,7 +1466,7 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
# Now we have all list of columns which we need
|
# Now we have all list of columns which we need
|
||||||
if 'columns' in data:
|
if 'columns' in data:
|
||||||
for c in data['columns']:
|
for c in data['columns']:
|
||||||
columns.append(self.qtIdent(self.conn, c['attname']))
|
columns.append(self.qtIdent(self.conn, c['name']))
|
||||||
values.append('?')
|
values.append('?')
|
||||||
|
|
||||||
if len(columns) > 0:
|
if len(columns) > 0:
|
||||||
@ -1475,7 +1507,7 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
# Now we have all list of columns which we need
|
# Now we have all list of columns which we need
|
||||||
if 'columns' in data:
|
if 'columns' in data:
|
||||||
for c in data['columns']:
|
for c in data['columns']:
|
||||||
columns.append(self.qtIdent(self.conn, c['attname']))
|
columns.append(self.qtIdent(self.conn, c['name']))
|
||||||
|
|
||||||
if len(columns) > 0:
|
if len(columns) > 0:
|
||||||
if len(columns) == 1:
|
if len(columns) == 1:
|
||||||
@ -1676,6 +1708,66 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
|
|
||||||
data['ftoptions'] = tmp_ftoptions
|
data['ftoptions'] = tmp_ftoptions
|
||||||
|
|
||||||
|
@check_precondition
|
||||||
|
def enable_disable_triggers(self, gid, sid, did, scid, foid):
|
||||||
|
"""
|
||||||
|
This function will enable/disable trigger(s) on the table object
|
||||||
|
|
||||||
|
Args:
|
||||||
|
gid: Server Group ID
|
||||||
|
sid: Server ID
|
||||||
|
did: Database ID
|
||||||
|
scid: Schema ID
|
||||||
|
tid: Table ID
|
||||||
|
"""
|
||||||
|
# Below will decide if it's simple drop or drop with cascade call
|
||||||
|
data = request.form if request.form else json.loads(
|
||||||
|
request.data
|
||||||
|
)
|
||||||
|
# Convert str 'true' to boolean type
|
||||||
|
is_enable_trigger = data['is_enable_trigger']
|
||||||
|
|
||||||
|
try:
|
||||||
|
if foid is not None:
|
||||||
|
status, data = self._fetch_properties(
|
||||||
|
gid, sid, did, scid, foid, inherits=True)
|
||||||
|
if not status:
|
||||||
|
return data
|
||||||
|
elif not data:
|
||||||
|
return gone(self.not_found_error_msg())
|
||||||
|
|
||||||
|
SQL = render_template(
|
||||||
|
"/".join([self.template_path, 'enable_disable_trigger.sql']),
|
||||||
|
data=data, is_enable_trigger=is_enable_trigger
|
||||||
|
)
|
||||||
|
status, res = self.conn.execute_scalar(SQL)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=res)
|
||||||
|
|
||||||
|
SQL = render_template(
|
||||||
|
"/".join([self.template_path, 'get_enabled_triggers.sql']),
|
||||||
|
tid=foid
|
||||||
|
)
|
||||||
|
|
||||||
|
status, trigger_res = self.conn.execute_scalar(SQL)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=res)
|
||||||
|
|
||||||
|
return make_json_response(
|
||||||
|
success=1,
|
||||||
|
info=gettext("Trigger(s) have been disabled")
|
||||||
|
if is_enable_trigger == 'D'
|
||||||
|
else gettext("Trigger(s) have been enabled"),
|
||||||
|
data={
|
||||||
|
'id': foid,
|
||||||
|
'scid': scid,
|
||||||
|
'has_enable_triggers': trigger_res
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return internal_server_error(errormsg=str(e))
|
||||||
|
|
||||||
|
|
||||||
SchemaDiffRegistry(blueprint.node_type, ForeignTableView)
|
SchemaDiffRegistry(blueprint.node_type, ForeignTableView)
|
||||||
ForeignTableView.register_node_view(blueprint)
|
ForeignTableView.register_node_view(blueprint)
|
||||||
|
@ -5,9 +5,10 @@ foreign tables.
|
|||||||
Do not remove these imports as they will be automatically imported by the view
|
Do not remove these imports as they will be automatically imported by the view
|
||||||
module as its children
|
module as its children
|
||||||
"""
|
"""
|
||||||
from pgadmin.browser.server_groups.servers.databases.schemas.tables.columns \
|
|
||||||
import blueprint as columns_module
|
|
||||||
from pgadmin.browser.server_groups.servers.databases.schemas.tables.triggers \
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.triggers \
|
||||||
import blueprint as triggers_modules
|
import blueprint as triggers_modules
|
||||||
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
||||||
constraints import blueprint as constraints_modules
|
constraints import blueprint as constraints_modules
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.\
|
||||||
|
foreign_tables.foreign_table_columns import foreign_table_column_blueprint\
|
||||||
|
as foreign_tables_columns_modules
|
||||||
|
@ -0,0 +1,97 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
""" Implements Column Node for foreign table """
|
||||||
|
import pgadmin.browser.server_groups.servers.databases as database
|
||||||
|
from flask_babel import gettext
|
||||||
|
from pgadmin.browser.collection import CollectionNodeModule
|
||||||
|
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.columns \
|
||||||
|
import ColumnsView
|
||||||
|
|
||||||
|
|
||||||
|
class ForeignTableColumnsModule(CollectionNodeModule):
|
||||||
|
"""
|
||||||
|
class ColumnsModule(CollectionNodeModule)
|
||||||
|
|
||||||
|
A module class for Column node derived from CollectionNodeModule.
|
||||||
|
|
||||||
|
Methods:
|
||||||
|
-------
|
||||||
|
* __init__(*args, **kwargs)
|
||||||
|
- Method is used to initialize the Column and it's base module.
|
||||||
|
|
||||||
|
* get_nodes(gid, sid, did, scid, tid)
|
||||||
|
- Method is used to generate the browser collection node.
|
||||||
|
|
||||||
|
* node_inode()
|
||||||
|
- Method is overridden from its base class to make the node as leaf node.
|
||||||
|
|
||||||
|
* script_load()
|
||||||
|
- Load the module script for schema, when any of the server node is
|
||||||
|
initialized.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_NODE_TYPE = 'foreign_table_column'
|
||||||
|
_COLLECTION_LABEL = gettext("Columns")
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Method is used to initialize the ColumnModule and it's base module.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*args:
|
||||||
|
**kwargs:
|
||||||
|
"""
|
||||||
|
self.min_ver = None
|
||||||
|
self.max_ver = None
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_nodes(self, gid, sid, did, scid, foid, **kwargs):
|
||||||
|
"""
|
||||||
|
Generate the collection node
|
||||||
|
"""
|
||||||
|
if self.has_nodes(
|
||||||
|
sid, did, scid=scid, tid=foid,
|
||||||
|
base_template_path=ForeignTableColumnsView.BASE_TEMPLATE_PATH):
|
||||||
|
yield self.generate_browser_collection_node(foid)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def script_load(self):
|
||||||
|
"""
|
||||||
|
Load the module script for server, when any of the server-group node is
|
||||||
|
initialized.
|
||||||
|
"""
|
||||||
|
return database.DatabaseModule.node_type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def node_inode(self):
|
||||||
|
"""
|
||||||
|
Load the module node as a leaf node
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def module_use_template_javascript(self):
|
||||||
|
"""
|
||||||
|
Returns whether Jinja2 template is used for generating the javascript
|
||||||
|
module.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
foreign_table_column_blueprint = ForeignTableColumnsModule(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ForeignTableColumnsView(ColumnsView):
|
||||||
|
node_type = foreign_table_column_blueprint.node_type
|
||||||
|
node_label = "Column"
|
||||||
|
|
||||||
|
|
||||||
|
ForeignTableColumnsView.register_node_view(foreign_table_column_blueprint)
|
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#e1fff9;}.cls-2{fill:none;stroke:#aecec8;stroke-linejoin:round;stroke-width:0.75px;}.cls-3{fill:#16a085;}</style></defs><title>coll-column</title><g id="_2" data-name="2"><rect class="cls-1" x="4.15" y="1.95" width="5.5" height="9.9" rx="1" ry="1"/><line class="cls-2" x1="4.7" y1="6.9" x2="9.1" y2="6.9"/><line class="cls-2" x1="4.7" y1="9.1" x2="9.1" y2="9.1"/><path class="cls-3" d="M4.9,5.18l4,0v5.55a.35.35,0,0,1-.35.35H5.25a.35.35,0,0,1-.35-.35V5.18m-.75-.75v6.32a1.1,1.1,0,0,0,1.1,1.1h3.3a1.1,1.1,0,0,0,1.1-1.1V4.46l-5.5,0Z"/><path class="cls-3" d="M8.55,2.7A.35.35,0,0,1,8.9,3V4.5h-4V3a.35.35,0,0,1,.35-.35h3.3m0-.75H5.25A1.1,1.1,0,0,0,4.15,3v2.2h5.5V3A1.1,1.1,0,0,0,8.55,2Z"/><rect class="cls-1" x="6.35" y="4.15" width="5.5" height="9.9" rx="1" ry="1"/><line class="cls-2" x1="6.9" y1="9.1" x2="11.3" y2="9.1"/><line class="cls-2" x1="6.9" y1="11.3" x2="11.3" y2="11.3"/><path class="cls-3" d="M7.1,7.38l4,0V13a.35.35,0,0,1-.35.35H7.45A.35.35,0,0,1,7.1,13V7.38m-.75-.75V13A1.1,1.1,0,0,0,7.45,14h3.3a1.1,1.1,0,0,0,1.1-1.1V6.66l-5.5,0Z"/><path class="cls-3" d="M10.75,4.9a.35.35,0,0,1,.35.35V6.7h-4V5.25a.35.35,0,0,1,.35-.35h3.3m0-.75H7.45a1.1,1.1,0,0,0-1.1,1.1v2.2h5.5V5.25a1.1,1.1,0,0,0-1.1-1.1Z"/></g></svg>
|
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="20" height="20"><defs><style>.cls-1{fill:#e1fff9;}.cls-2{fill:none;stroke:#aecec8;stroke-linejoin:round;stroke-width:0.75px;}.cls-3{fill:#16a085;}</style></defs><title>column</title><g id="_2" data-name="2"><rect class="cls-1" x="5.3" y="2.15" width="5.4" height="11.7" rx="1" ry="1"/><line class="cls-2" x1="5.75" y1="8" x2="10.25" y2="8"/><line class="cls-2" x1="5.75" y1="10.7" x2="10.25" y2="10.7"/><path class="cls-3" d="M6,5.83l3.9,0V13a.15.15,0,0,1-.15.15H6.2A.15.15,0,0,1,6,13V5.83M5.3,5.08V13a.9.9,0,0,0,.9.9H9.8a.9.9,0,0,0,.9-.9V5.1l-5.4,0Z"/><path class="cls-3" d="M9.8,2.9A.15.15,0,0,1,10,3V5H6V3A.15.15,0,0,1,6.2,2.9H9.8m0-.75H6.2a.9.9,0,0,0-.9.9v2.7h5.4V3a.9.9,0,0,0-.9-.9Z"/></g></svg>
|
After Width: | Height: | Size: 768 B |
@ -0,0 +1,70 @@
|
|||||||
|
/////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// pgAdmin 4 - PostgreSQL Tools
|
||||||
|
//
|
||||||
|
// Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||||
|
// This software is released under the PostgreSQL Licence
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
import { getNodeColumnSchema } from '../../../static/js/foreign_table.ui';
|
||||||
|
|
||||||
|
define('pgadmin.node.foreign_table_column', [
|
||||||
|
'sources/gettext', 'sources/url_for', 'pgadmin.browser',
|
||||||
|
'pgadmin.node.schema.dir/schema_child_tree_node', 'pgadmin.browser.collection',
|
||||||
|
], function(
|
||||||
|
gettext, url_for, pgBrowser
|
||||||
|
) {
|
||||||
|
|
||||||
|
if (!pgBrowser.Nodes['coll-foreign_table_column']) {
|
||||||
|
pgBrowser.Nodes['coll-foreign_table_column'] =
|
||||||
|
pgBrowser.Collection.extend({
|
||||||
|
node: 'foreign_table_column',
|
||||||
|
label: gettext('Columns'),
|
||||||
|
type: 'coll-foreign_table_column',
|
||||||
|
columns: ['name', 'cltype', 'description']
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pgBrowser.Nodes['foreign_table_column']) {
|
||||||
|
pgBrowser.Nodes['foreign_table_column'] = pgBrowser.Node.extend({
|
||||||
|
// Foreign table is added in parent_type to support triggers on
|
||||||
|
// foreign table where we need column information.
|
||||||
|
parent_type: ['foreign_table'],
|
||||||
|
collection_type: ['coll-foreign_table'],
|
||||||
|
type: 'foreign_table_column',
|
||||||
|
label: gettext('Column'),
|
||||||
|
hasSQL: true,
|
||||||
|
sqlAlterHelp: 'sql-altertable.html',
|
||||||
|
sqlCreateHelp: 'sql-altertable.html',
|
||||||
|
dialogHelp: url_for('help.static', {'filename': 'column_dialog.html'}),
|
||||||
|
canDrop: true,
|
||||||
|
canDropCascade: false,
|
||||||
|
hasDepends: true,
|
||||||
|
hasStatistics: true,
|
||||||
|
Init: function() {
|
||||||
|
/* Avoid multiple registration of menus */
|
||||||
|
if (this.initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.initialized = true;
|
||||||
|
pgBrowser.add_menus([{
|
||||||
|
name: 'create_column_on_coll', node: 'coll-foreign_table_column', module: this,
|
||||||
|
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||||
|
category: 'create', priority: 4, label: gettext('Column...'),
|
||||||
|
data: {action: 'create'}, enable: 'canCreate',
|
||||||
|
},{
|
||||||
|
name: 'create_column_onTable', node: 'foreign_table', module: this,
|
||||||
|
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||||
|
category: 'create', priority: 4, label: gettext('Column...'),
|
||||||
|
data: {action: 'create'}, enable: 'canCreate',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
getSchema: function(treeNodeInfo, itemNodeData) {
|
||||||
|
return getNodeColumnSchema(treeNodeInfo, itemNodeData, pgBrowser);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return pgBrowser.Nodes['foreign_table_column'];
|
||||||
|
});
|
@ -0,0 +1,8 @@
|
|||||||
|
ALTER FOREIGN TABLE public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ALTER COLUMN "col_3_$%{}[]()&*^!@""'`\/#" TYPE time(10) with time zone ;
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ALTER COLUMN "col_3_$%{}[]()&*^!@""'`\/#" DROP NOT NULL;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_3_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'test comment modification';
|
@ -0,0 +1,9 @@
|
|||||||
|
-- Column: public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_3_$%{}[]()&*^!@""'`\/#"
|
||||||
|
|
||||||
|
-- ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN IF EXISTS "col_3_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_3_$%{}[]()&*^!@""'`\/#" time(6) with time zone DEFAULT now();
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_3_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'test comment modification';
|
@ -0,0 +1,5 @@
|
|||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ALTER COLUMN "col_4_$%{}[]()&*^!@""'`\/#" OPTIONS (SET column_name 'test_options_update');
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ALTER COLUMN "col_4_$%{}[]()&*^!@""'`\/#"
|
||||||
|
SET (n_distinct=111);
|
@ -0,0 +1,13 @@
|
|||||||
|
-- Column: public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_4_$%{}[]()&*^!@""'`\/#"
|
||||||
|
|
||||||
|
-- ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN IF EXISTS "col_4_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_4_$%{}[]()&*^!@""'`\/#" bigint OPTIONS (column_name 'test_options_update') NOT NULL GENERATED ALWAYS AS ((1000 + 1)) STORED;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_4_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'test comment';
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ALTER COLUMN "col_4_$%{}[]()&*^!@""'`\/#"
|
||||||
|
SET (n_distinct=111);
|
@ -0,0 +1,5 @@
|
|||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_3_$%{}[]()&*^!@""'`\/#" time with time zone NOT NULL DEFAULT now();
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_3_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'test comment';
|
@ -0,0 +1,9 @@
|
|||||||
|
-- Column: public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_3_$%{}[]()&*^!@""'`\/#"
|
||||||
|
|
||||||
|
-- ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN IF EXISTS "col_3_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_3_$%{}[]()&*^!@""'`\/#" time with time zone NOT NULL DEFAULT now();
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_3_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'test comment';
|
@ -0,0 +1,9 @@
|
|||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_4_$%{}[]()&*^!@""'`\/#" bigint OPTIONS (column_name 'test_options') NOT NULL GENERATED ALWAYS AS (1000+1) STORED;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_4_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'test comment';
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ALTER COLUMN "col_4_$%{}[]()&*^!@""'`\/#"
|
||||||
|
SET (n_distinct=1);
|
@ -0,0 +1,13 @@
|
|||||||
|
-- Column: public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_4_$%{}[]()&*^!@""'`\/#"
|
||||||
|
|
||||||
|
-- ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN IF EXISTS "col_4_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_4_$%{}[]()&*^!@""'`\/#" bigint OPTIONS (column_name 'test_options') NOT NULL GENERATED ALWAYS AS ((1000 + 1)) STORED;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_4_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'test comment';
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ALTER COLUMN "col_4_$%{}[]()&*^!@""'`\/#"
|
||||||
|
SET (n_distinct=1);
|
@ -0,0 +1,213 @@
|
|||||||
|
{
|
||||||
|
"scenarios": [
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create FDW for foreign table",
|
||||||
|
"endpoint": "NODE-foreign_data_wrapper.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_data_wrapper.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "test_fdw_for_foreign_table_columns",
|
||||||
|
"fdwacl": [],
|
||||||
|
"fdwoptions": []
|
||||||
|
},
|
||||||
|
"store_object_id": "True"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create foreign server for foreign table",
|
||||||
|
"endpoint": "NODE-foreign_server.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_server.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name":"test_fs_for_foreign_table_column"
|
||||||
|
},
|
||||||
|
"store_object_id": "True"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create Foreign Table for testing column node.",
|
||||||
|
"endpoint": "NODE-foreign_table.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_table.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "foreign_table_2_$%{}[]()&*^!@\"'`\\/#",
|
||||||
|
"columns": [],
|
||||||
|
"schema": "public",
|
||||||
|
"basensp": "public",
|
||||||
|
"ftsrvname": "test_fs_for_foreign_table_column",
|
||||||
|
"owner": "postgres",
|
||||||
|
"ftoptions": [],
|
||||||
|
"inherits": [],
|
||||||
|
"relacl": [],
|
||||||
|
"seclabels": []
|
||||||
|
},
|
||||||
|
"store_object_id": "True"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create FT Column (Integer/Numeric type)",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql",
|
||||||
|
"data": {
|
||||||
|
"name": "col_1_$%{}[]()&*^!@\"'`\\/#",
|
||||||
|
"description": "Comment for create",
|
||||||
|
"cltype": "numeric",
|
||||||
|
"attlen":"10",
|
||||||
|
"attprecision":"5",
|
||||||
|
"colconstype":"n",
|
||||||
|
"attnotnull": true,
|
||||||
|
"attoptions": [],
|
||||||
|
"seclabels": [],
|
||||||
|
"defval": "1"
|
||||||
|
},
|
||||||
|
"expected_sql_file": "create_column_numeric.sql",
|
||||||
|
"expected_msql_file": "create_column_numeric.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "alter",
|
||||||
|
"name": "Alter FT Column (Integer/Numeric type)",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql_id",
|
||||||
|
"data": {
|
||||||
|
"attnum": 1,
|
||||||
|
"name": "new_col_1_$%{}[]()&*^!@\"'`\\/#",
|
||||||
|
"description": "Comment for alter",
|
||||||
|
"cltype": "real",
|
||||||
|
"coloptions":{"added":[{"option":"column_name","value":"test"}]}
|
||||||
|
},
|
||||||
|
"expected_sql_file": "alter_column_numeric.sql",
|
||||||
|
"expected_msql_file": "alter_column_numeric.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "delete",
|
||||||
|
"name": "Drop FT Column (Integer/Numeric type)",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "new_col_1_$%{}[]()&*^!@\"'`\\/#"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create FT Column with text & default value",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql",
|
||||||
|
"data": {
|
||||||
|
"name": "col_2_$%{}[]()&*^!@\"'`\\/#",
|
||||||
|
"cltype": "text",
|
||||||
|
"description": "test comment",
|
||||||
|
"attnotnull": true,
|
||||||
|
"colconstype": "n",
|
||||||
|
"defval": "'xyz'"
|
||||||
|
},
|
||||||
|
"expected_sql_file": "create_column_text_with_default_value.sql",
|
||||||
|
"expected_msql_file": "create_column_text_with_default_value.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "alter",
|
||||||
|
"name": "Alter FT Column with text & update default value",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql_id",
|
||||||
|
"data": {
|
||||||
|
"attnum": 2,
|
||||||
|
"defval": "'changed default value'"
|
||||||
|
},
|
||||||
|
"expected_sql_file": "alter_column_text_with_default_value.sql",
|
||||||
|
"expected_msql_file": "alter_column_text_with_default_value.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "delete",
|
||||||
|
"name": "Drop FT column with text & update default value",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "col_2_$%{}[]()&*^!@\"'`\\/#"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create FT Column with time with time zone & default value using function",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql",
|
||||||
|
"data": {
|
||||||
|
"name": "col_3_$%{}[]()&*^!@\"'`\\/#",
|
||||||
|
"cltype": "time with time zone",
|
||||||
|
"attacl": [],
|
||||||
|
"description": "test comment",
|
||||||
|
"attnotnull": true,
|
||||||
|
"colconstype": "n",
|
||||||
|
"defval": "now()"
|
||||||
|
},
|
||||||
|
"expected_sql_file": "create_column_timestamp_with_default_value_using_function.sql",
|
||||||
|
"expected_msql_file": "create_column_timestamp_with_default_value_using_function.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "alter",
|
||||||
|
"name": "Alter FT Column with time with time zone & update length",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql_id",
|
||||||
|
"data": {
|
||||||
|
"attlen": "10",
|
||||||
|
"attnotnull": false,
|
||||||
|
"attnum":3,
|
||||||
|
"description": "test comment modification"
|
||||||
|
},
|
||||||
|
"expected_sql_file": "alter_column_timestamp_with_default_value_using_function.sql",
|
||||||
|
"expected_msql_file": "alter_column_timestamp_with_default_value_using_function.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "delete",
|
||||||
|
"name": "Drop FT Column with time with time zone",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "col_3_$%{}[]()&*^!@\"'`\\/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create FT Column with integer & generated always with expression, column option, variables",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql",
|
||||||
|
"data": {"name":"col_4_$%{}[]()&*^!@\"'`\\/#",
|
||||||
|
"description":"test comment",
|
||||||
|
"cltype":"bigint",
|
||||||
|
"attnotnull":true,
|
||||||
|
"coloptions":[{"option":"column_name","value":"test_options"}],
|
||||||
|
"colconstype":"g",
|
||||||
|
"is_tlength":false,
|
||||||
|
"is_precision":false,
|
||||||
|
"genexpr":"1000+1",
|
||||||
|
"attoptions":[{"name":"n_distinct","value":"1"}]},
|
||||||
|
"expected_sql_file": "create_column_with_integer_generated_always_column_option_variables.sql",
|
||||||
|
"expected_msql_file": "create_column_with_integer_generated_always_column_option_variables.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "alter",
|
||||||
|
"name": "Alter FT Column with integer & generated always with expression, column option, variables",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql_id",
|
||||||
|
"data":{
|
||||||
|
"attoptions":{
|
||||||
|
"changed":[{"name":"n_distinct","value":"111"}]},
|
||||||
|
"coloptions":{"changed":[{"option":"column_name","value":"test_options_update"}]},
|
||||||
|
"attnum":4},
|
||||||
|
"expected_sql_file": "alter_column_with_integer_generated_always_column_option_variables.sql",
|
||||||
|
"expected_msql_file": "alter_column_with_integer_generated_always_column_option_variables.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "delete",
|
||||||
|
"name": "Drop FT Column with time with time zone",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_columnn.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name":"col_4_$%{}[]()&*^!@\"'`\\/#"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]}
|
@ -0,0 +1,16 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
|
|
||||||
|
|
||||||
|
class ForeignTableGeneratorTestCase(BaseTestGenerator):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
return []
|
@ -0,0 +1,154 @@
|
|||||||
|
{
|
||||||
|
"column_create": [
|
||||||
|
{
|
||||||
|
"name": "Create: Add FT column with valid data",
|
||||||
|
"is_positive_test": true,
|
||||||
|
"inventory_data": {},
|
||||||
|
"test_data": {
|
||||||
|
"name": "test_ft_column_add_",
|
||||||
|
"description": "Comment for create",
|
||||||
|
"cltype": "numeric",
|
||||||
|
"attlen":"10",
|
||||||
|
"attprecision":"5",
|
||||||
|
"coloptions":[],
|
||||||
|
"colconstype":"n",
|
||||||
|
"attnotnull": true,
|
||||||
|
"attoptions": [],
|
||||||
|
"seclabels": [],
|
||||||
|
"defval": "1"
|
||||||
|
},
|
||||||
|
"mocking_required": false,
|
||||||
|
"mock_data": {},
|
||||||
|
"expected_data": {
|
||||||
|
"status_code": 200,
|
||||||
|
"error_msg": null,
|
||||||
|
"test_result_data": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Create: Add FT column with valid data while server down",
|
||||||
|
"is_positive_test": false,
|
||||||
|
"inventory_data": {},
|
||||||
|
"test_data": {
|
||||||
|
"name": "test_column_add_",
|
||||||
|
"cltype": "\"char\"",
|
||||||
|
"attacl": [],
|
||||||
|
"is_primary_key": false,
|
||||||
|
"attnotnull": false,
|
||||||
|
"attlen": null,
|
||||||
|
"attprecision": null,
|
||||||
|
"attoptions": [],
|
||||||
|
"seclabels": [],
|
||||||
|
"description": {
|
||||||
|
"comment": "jsoncomment"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mocking_required": true,
|
||||||
|
"mock_data": {
|
||||||
|
"function_name": "pgadmin.utils.driver.psycopg3.connection.Connection.execute_scalar",
|
||||||
|
"return_value": "[(False, 'Mocked Internal Server Error'),(True,True)]"
|
||||||
|
},
|
||||||
|
"expected_data": {
|
||||||
|
"status_code": 500,
|
||||||
|
"error_msg": "Mocked Internal Server Error",
|
||||||
|
"test_result_data": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"column_delete": [
|
||||||
|
{
|
||||||
|
"name": "Delete: Existing FT column",
|
||||||
|
"is_positive_test": true,
|
||||||
|
"inventory_data": {},
|
||||||
|
"test_data": {},
|
||||||
|
"mocking_required": false,
|
||||||
|
"mock_data": {},
|
||||||
|
"expected_data": {
|
||||||
|
"status_code": 200,
|
||||||
|
"error_msg": null,
|
||||||
|
"test_result_data": {}
|
||||||
|
},
|
||||||
|
"is_list": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete: Multiple existing FT column",
|
||||||
|
"is_positive_test": true,
|
||||||
|
"inventory_data": {},
|
||||||
|
"test_data": {},
|
||||||
|
"mocking_required": false,
|
||||||
|
"mock_data": {},
|
||||||
|
"expected_data": {
|
||||||
|
"status_code": 200,
|
||||||
|
"error_msg": null,
|
||||||
|
"test_result_data": {}
|
||||||
|
},
|
||||||
|
"is_list": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete: Non-existing FT column",
|
||||||
|
"is_positive_test": false,
|
||||||
|
"inventory_data": {},
|
||||||
|
"test_data": {
|
||||||
|
"column_id": 9999999
|
||||||
|
},
|
||||||
|
"mocking_required": false,
|
||||||
|
"mock_data": {},
|
||||||
|
"expected_data": {
|
||||||
|
"status_code": 200,
|
||||||
|
"error_msg": "Error: Object not found.",
|
||||||
|
"test_result_data": {}
|
||||||
|
},
|
||||||
|
"is_list": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete: Existing FT column while server down",
|
||||||
|
"is_positive_test": false,
|
||||||
|
"inventory_data": {},
|
||||||
|
"test_data": {},
|
||||||
|
"mocking_required": true,
|
||||||
|
"mock_data": {
|
||||||
|
"function_name": "pgadmin.utils.driver.psycopg3.connection.Connection.execute_dict",
|
||||||
|
"return_value": "[(False,'Mocked Internal Server Error')]"
|
||||||
|
},
|
||||||
|
"expected_data": {
|
||||||
|
"status_code": 500,
|
||||||
|
"error_msg": "Mocked Internal Server Error",
|
||||||
|
"test_result_data": {}
|
||||||
|
},
|
||||||
|
"is_list": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"column_get": [
|
||||||
|
{
|
||||||
|
"name": "Get details: For existing FT column",
|
||||||
|
"is_positive_test": true,
|
||||||
|
"inventory_data": {},
|
||||||
|
"test_data": {},
|
||||||
|
"mocking_required": false,
|
||||||
|
"mock_data": {},
|
||||||
|
"expected_data": {
|
||||||
|
"status_code": 200,
|
||||||
|
"error_msg": null,
|
||||||
|
"test_result_data": {}
|
||||||
|
},
|
||||||
|
"is_list": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get details: For existing FT column while server down",
|
||||||
|
"is_positive_test": false,
|
||||||
|
"inventory_data": {},
|
||||||
|
"test_data": {},
|
||||||
|
"mocking_required": true,
|
||||||
|
"mock_data": {
|
||||||
|
"function_name": "pgadmin.utils.driver.psycopg3.connection.Connection.execute_dict",
|
||||||
|
"return_value": "[(False,'Mocked Internal Server Error')]"
|
||||||
|
},
|
||||||
|
"expected_data": {
|
||||||
|
"status_code": 500,
|
||||||
|
"error_msg": "Mocked Internal Server Error",
|
||||||
|
"test_result_data": {}
|
||||||
|
},
|
||||||
|
"is_list": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
RENAME "col_1_$%{}[]()&*^!@""'`\/#" TO "new_col_1_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
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 COLUMN "new_col_1_$%{}[]()&*^!@""'`\/#" TYPE real;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."new_col_1_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'Comment for alter';
|
@ -0,0 +1,9 @@
|
|||||||
|
-- Column: public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."new_col_1_$%{}[]()&*^!@""'`\/#"
|
||||||
|
|
||||||
|
-- ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN IF EXISTS "new_col_1_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "new_col_1_$%{}[]()&*^!@""'`\/#" real OPTIONS (column_name 'test') NOT NULL DEFAULT 1;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."new_col_1_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'Comment for alter';
|
@ -0,0 +1,2 @@
|
|||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ALTER COLUMN "col_2_$%{}[]()&*^!@""'`\/#" SET DEFAULT 'changed default value';
|
@ -0,0 +1,9 @@
|
|||||||
|
-- Column: public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
|
||||||
|
-- ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN IF EXISTS "col_2_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" text COLLATE pg_catalog."default" NOT NULL DEFAULT 'changed default value'::text;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'test comment';
|
@ -0,0 +1,5 @@
|
|||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_1_$%{}[]()&*^!@""'`\/#" numeric(10, 5) NOT NULL DEFAULT 1;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_1_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'Comment for create';
|
@ -0,0 +1,9 @@
|
|||||||
|
-- Column: public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_1_$%{}[]()&*^!@""'`\/#"
|
||||||
|
|
||||||
|
-- ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN IF EXISTS "col_1_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_1_$%{}[]()&*^!@""'`\/#" numeric(10,5) NOT NULL DEFAULT 1;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_1_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'Comment for create';
|
@ -0,0 +1,5 @@
|
|||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" text NOT NULL DEFAULT 'xyz';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'test comment';
|
@ -0,0 +1,9 @@
|
|||||||
|
-- Column: public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
|
||||||
|
-- ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN IF EXISTS "col_2_$%{}[]()&*^!@""'`\/#";
|
||||||
|
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS public."foreign_table_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" text COLLATE pg_catalog."default" NOT NULL DEFAULT 'xyz'::text;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public."foreign_table_2_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
|
||||||
|
IS 'test comment';
|
@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"scenarios": [
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create FDW for foreign table",
|
||||||
|
"endpoint": "NODE-foreign_data_wrapper.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_data_wrapper.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "test_fdw_for_foreign_table_columns",
|
||||||
|
"fdwacl": [],
|
||||||
|
"fdwoptions": []
|
||||||
|
},
|
||||||
|
"store_object_id": "True"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create foreign server for foreign table",
|
||||||
|
"endpoint": "NODE-foreign_server.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_server.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name":"test_fs_for_foreign_table_column"
|
||||||
|
},
|
||||||
|
"store_object_id": "True"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create Foreign Table for testing column node.",
|
||||||
|
"endpoint": "NODE-foreign_table.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_table.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "foreign_table_2_$%{}[]()&*^!@\"'`\\/#",
|
||||||
|
"columns": [],
|
||||||
|
"schema": "public",
|
||||||
|
"basensp": "public",
|
||||||
|
"ftsrvname": "test_fs_for_foreign_table_column",
|
||||||
|
"owner": "postgres",
|
||||||
|
"ftoptions": [],
|
||||||
|
"inherits": [],
|
||||||
|
"relacl": [],
|
||||||
|
"seclabels": []
|
||||||
|
},
|
||||||
|
"store_object_id": "True"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create FT Column (Integer/Numeric type)",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql",
|
||||||
|
"data": {
|
||||||
|
"name": "col_1_$%{}[]()&*^!@\"'`\\/#",
|
||||||
|
"description": "Comment for create",
|
||||||
|
"cltype": "numeric",
|
||||||
|
"attlen":"10",
|
||||||
|
"attprecision":"5",
|
||||||
|
"coloptions":[],
|
||||||
|
"colconstype":"n",
|
||||||
|
"attnotnull": true,
|
||||||
|
"attoptions": [],
|
||||||
|
"seclabels": [],
|
||||||
|
"defval": "1"
|
||||||
|
},
|
||||||
|
"expected_sql_file": "create_column_numeric.sql",
|
||||||
|
"expected_msql_file": "create_column_numeric.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "alter",
|
||||||
|
"name": "Alter FT Column (Integer/Numeric type)",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql_id",
|
||||||
|
"data": {
|
||||||
|
"attnum": 1,
|
||||||
|
"name": "new_col_1_$%{}[]()&*^!@\"'`\\/#",
|
||||||
|
"description": "Comment for alter",
|
||||||
|
"cltype": "real",
|
||||||
|
"coloptions":{"added":[{"option":"column_name","value":"test"}]}
|
||||||
|
},
|
||||||
|
"expected_sql_file": "alter_column_numeric.sql",
|
||||||
|
"expected_msql_file": "alter_column_numeric.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "delete",
|
||||||
|
"name": "Drop FT Column (Integer/Numeric type)",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "new_col_1_$%{}[]()&*^!@\"'`\\/#"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "create",
|
||||||
|
"name": "Create FT Column with text & default value",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql",
|
||||||
|
"data": {
|
||||||
|
"name": "col_2_$%{}[]()&*^!@\"'`\\/#",
|
||||||
|
"cltype": "text",
|
||||||
|
"description": "test comment",
|
||||||
|
"attnotnull": true,
|
||||||
|
"colconstype": "n",
|
||||||
|
"defval": "'xyz'"
|
||||||
|
},
|
||||||
|
"expected_sql_file": "create_column_text_with_default_value.sql",
|
||||||
|
"expected_msql_file": "create_column_text_with_default_value.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "alter",
|
||||||
|
"name": "Alter FT Column with text & update default value",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"msql_endpoint": "NODE-foreign_table_column.msql_id",
|
||||||
|
"data": {
|
||||||
|
"attnum": 2,
|
||||||
|
"defval": "'changed default value'"
|
||||||
|
},
|
||||||
|
"expected_sql_file": "alter_column_text_with_default_value.sql",
|
||||||
|
"expected_msql_file": "alter_column_text_with_default_value.msql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "delete",
|
||||||
|
"name": "Drop FT column with text & update default value",
|
||||||
|
"endpoint": "NODE-foreign_table_column.obj_id",
|
||||||
|
"sql_endpoint": "NODE-foreign_table_column.sql_id",
|
||||||
|
"data": {
|
||||||
|
"name": "col_2_$%{}[]()&*^!@\"'`\\/#"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]}
|
@ -0,0 +1,111 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.foreign_tables.\
|
||||||
|
tests import utils as ft_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
|
||||||
|
utils as schema_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||||
|
database_utils
|
||||||
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
|
from regression import parent_node_dict
|
||||||
|
from regression.python_test_utils import test_utils as utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.foreign_tables.\
|
||||||
|
foreign_table_columns. tests import utils as columns_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.foreign_data_wrappers. \
|
||||||
|
foreign_servers.tests import utils as fsrv_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.foreign_data_wrappers. \
|
||||||
|
tests import utils as fdw_utils
|
||||||
|
|
||||||
|
|
||||||
|
class ColumnAddTestCase(BaseTestGenerator):
|
||||||
|
"""This class will add new column under table node."""
|
||||||
|
url = '/browser/foreign_table_column/obj/'
|
||||||
|
|
||||||
|
# Generates scenarios
|
||||||
|
scenarios = utils.generate_scenarios("column_create",
|
||||||
|
columns_utils.test_cases)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
# Load test data
|
||||||
|
self.data = self.test_data
|
||||||
|
|
||||||
|
# Get parent schema info
|
||||||
|
self.db_name = parent_node_dict["database"][-1]["db_name"]
|
||||||
|
self.schema_info = parent_node_dict['schema'][-1]
|
||||||
|
self.server_id = self.schema_info['server_id']
|
||||||
|
self.db_id = self.schema_info['db_id']
|
||||||
|
|
||||||
|
# Create db connection
|
||||||
|
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
||||||
|
self.server_id, self.db_id)
|
||||||
|
if not db_con['data']["connected"]:
|
||||||
|
raise Exception("Could not connect to database to add a table.")
|
||||||
|
|
||||||
|
# Create schema
|
||||||
|
self.schema_name = self.schema_info['schema_name']
|
||||||
|
self.schema_id = self.schema_info['schema_id']
|
||||||
|
schema_response = schema_utils.verify_schemas(self.server,
|
||||||
|
self.db_name,
|
||||||
|
self.schema_name)
|
||||||
|
if not schema_response:
|
||||||
|
raise Exception("Could not find the schema to add a table.")
|
||||||
|
|
||||||
|
# Create FDW, server & table
|
||||||
|
self.fdw_name = "fdw_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
self.fsrv_name = "fsrv_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
self.ft_name = "ft_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
|
||||||
|
self.fdw_id = fdw_utils.create_fdw(self.server, self.db_name,
|
||||||
|
self.fdw_name)
|
||||||
|
self.fsrv_id = fsrv_utils.create_fsrv(self.server, self.db_name,
|
||||||
|
self.fsrv_name, self.fdw_name)
|
||||||
|
self.ft_id = ft_utils.create_foreign_table(self.server, self.db_name,
|
||||||
|
self.schema_name,
|
||||||
|
self.fsrv_name,
|
||||||
|
self.ft_name)
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
"""This function will add column under table node."""
|
||||||
|
if "name" in self.data:
|
||||||
|
self.data["name"] = self.data["name"] + (str(uuid.uuid4())[1:8])
|
||||||
|
|
||||||
|
if self.is_positive_test:
|
||||||
|
response = columns_utils.api_create(self)
|
||||||
|
|
||||||
|
# Assert response
|
||||||
|
utils.assert_status_code(self, response)
|
||||||
|
|
||||||
|
# Verify in backend
|
||||||
|
self.assertIsNotNone(columns_utils.verify_column
|
||||||
|
(self.server, self.db_name,
|
||||||
|
self.data["name"]),
|
||||||
|
"Column not found")
|
||||||
|
else:
|
||||||
|
if self.mocking_required:
|
||||||
|
with patch(self.mock_data["function_name"],
|
||||||
|
side_effect=eval(self.mock_data["return_value"])):
|
||||||
|
response = columns_utils.api_create(self)
|
||||||
|
else:
|
||||||
|
if 'table_id' in self.data:
|
||||||
|
self.table_id = self.data['table_id']
|
||||||
|
|
||||||
|
response = columns_utils.api_create(self)
|
||||||
|
|
||||||
|
# Assert response
|
||||||
|
utils.assert_status_code(self, response)
|
||||||
|
utils.assert_error_message(self, response)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
# Disconnect the database
|
||||||
|
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
@ -0,0 +1,132 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
|
||||||
|
utils as schema_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||||
|
database_utils
|
||||||
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
|
from regression import parent_node_dict
|
||||||
|
from regression.python_test_utils import test_utils as utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.foreign_tables.\
|
||||||
|
foreign_table_columns. tests import utils as columns_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.foreign_data_wrappers. \
|
||||||
|
foreign_servers.tests import utils as fsrv_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.foreign_data_wrappers. \
|
||||||
|
tests import utils as fdw_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.foreign_tables.\
|
||||||
|
tests import utils as ft_utils
|
||||||
|
|
||||||
|
|
||||||
|
class ColumnDeleteTestCase(BaseTestGenerator):
|
||||||
|
"""This class will delete column under table node."""
|
||||||
|
url = '/browser/foreign_table_column/obj/'
|
||||||
|
|
||||||
|
# Generates scenarios
|
||||||
|
scenarios = utils.generate_scenarios("column_delete",
|
||||||
|
columns_utils.test_cases)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
# Load test data
|
||||||
|
self.data = self.test_data
|
||||||
|
|
||||||
|
# Get parent schema info
|
||||||
|
self.db_name = parent_node_dict["database"][-1]["db_name"]
|
||||||
|
self.schema_info = parent_node_dict['schema'][-1]
|
||||||
|
self.server_id = self.schema_info['server_id']
|
||||||
|
self.db_id = self.schema_info['db_id']
|
||||||
|
|
||||||
|
# Create db connection
|
||||||
|
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
||||||
|
self.server_id, self.db_id)
|
||||||
|
if not db_con['data']["connected"]:
|
||||||
|
raise Exception("Could not connect to database to add a table.")
|
||||||
|
|
||||||
|
# Create schema
|
||||||
|
self.schema_name = self.schema_info['schema_name']
|
||||||
|
self.schema_id = self.schema_info['schema_id']
|
||||||
|
schema_response = schema_utils.verify_schemas(self.server,
|
||||||
|
self.db_name,
|
||||||
|
self.schema_name)
|
||||||
|
if not schema_response:
|
||||||
|
raise Exception("Could not find the schema to add a table.")
|
||||||
|
|
||||||
|
# Create FDW, server & table
|
||||||
|
self.fdw_name = "fdw_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
self.fsrv_name = "fsrv_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
self.ft_name = "ft_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
|
||||||
|
self.fdw_id = fdw_utils.create_fdw(self.server, self.db_name,
|
||||||
|
self.fdw_name)
|
||||||
|
self.fsrv_id = fsrv_utils.create_fsrv(self.server, self.db_name,
|
||||||
|
self.fsrv_name, self.fdw_name)
|
||||||
|
self.ft_id = ft_utils.create_foreign_table(self.server, self.db_name,
|
||||||
|
self.schema_name,
|
||||||
|
self.fsrv_name,
|
||||||
|
self.ft_name)
|
||||||
|
|
||||||
|
# Create column
|
||||||
|
self.column_name = "test_column_delete_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
self.column_id = columns_utils.create_column(self.server,
|
||||||
|
self.db_name,
|
||||||
|
self.schema_name,
|
||||||
|
self.ft_name,
|
||||||
|
self.column_name)
|
||||||
|
|
||||||
|
self.column_name_1 = "test_column_delete_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
|
||||||
|
self.column_id_1 = columns_utils.create_column(self.server,
|
||||||
|
self.db_name,
|
||||||
|
self.schema_name,
|
||||||
|
self.ft_name,
|
||||||
|
self.column_name_1)
|
||||||
|
# Verify column creation
|
||||||
|
col_response = columns_utils.verify_column(self.server, self.db_name,
|
||||||
|
self.column_name)
|
||||||
|
if not col_response:
|
||||||
|
raise Exception("Could not find the column to drop.")
|
||||||
|
|
||||||
|
col_response = columns_utils.verify_column(self.server, self.db_name,
|
||||||
|
self.column_name_1)
|
||||||
|
if not col_response:
|
||||||
|
raise Exception("Could not find the column to drop.")
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
"""This function will drop column under table node."""
|
||||||
|
|
||||||
|
if self.is_positive_test:
|
||||||
|
if self.is_list:
|
||||||
|
self.data["ids"] = [self.column_id, self.column_id_1]
|
||||||
|
response = columns_utils.api_delete(self, "")
|
||||||
|
else:
|
||||||
|
response = columns_utils.api_delete(self)
|
||||||
|
|
||||||
|
# Assert response
|
||||||
|
utils.assert_status_code(self, response)
|
||||||
|
else:
|
||||||
|
if self.mocking_required:
|
||||||
|
with patch(self.mock_data["function_name"],
|
||||||
|
side_effect=eval(self.mock_data["return_value"])):
|
||||||
|
response = columns_utils.api_delete(self)
|
||||||
|
else:
|
||||||
|
if 'column_id' in self.data:
|
||||||
|
self.column_id = self.data['column_id']
|
||||||
|
response = columns_utils.api_delete(self)
|
||||||
|
|
||||||
|
# Assert response
|
||||||
|
utils.assert_status_code(self, response)
|
||||||
|
utils.assert_error_message(self, response)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
# Disconnect the database
|
||||||
|
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
@ -0,0 +1,125 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
|
||||||
|
utils as schema_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||||
|
database_utils
|
||||||
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
|
from regression import parent_node_dict
|
||||||
|
from regression.python_test_utils import test_utils as utils
|
||||||
|
from . import utils as columns_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.foreign_tables.\
|
||||||
|
foreign_table_columns. tests import utils as columns_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.foreign_data_wrappers. \
|
||||||
|
foreign_servers.tests import utils as fsrv_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.foreign_data_wrappers. \
|
||||||
|
tests import utils as fdw_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.foreign_tables.\
|
||||||
|
tests import utils as ft_utils
|
||||||
|
|
||||||
|
|
||||||
|
class ColumnGetTestCase(BaseTestGenerator):
|
||||||
|
"""This class will get column under table node."""
|
||||||
|
url = '/browser/foreign_table_column/obj/'
|
||||||
|
|
||||||
|
# Generates scenarios
|
||||||
|
scenarios = utils.generate_scenarios("column_get",
|
||||||
|
columns_utils.test_cases)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
# Load test data
|
||||||
|
self.data = self.test_data
|
||||||
|
|
||||||
|
# Get parent schema info
|
||||||
|
self.db_name = parent_node_dict["database"][-1]["db_name"]
|
||||||
|
self.schema_info = parent_node_dict['schema'][-1]
|
||||||
|
self.server_id = self.schema_info['server_id']
|
||||||
|
self.db_id = self.schema_info['db_id']
|
||||||
|
|
||||||
|
# Create db connection
|
||||||
|
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
||||||
|
self.server_id, self.db_id)
|
||||||
|
if not db_con['data']["connected"]:
|
||||||
|
raise Exception("Could not connect to database to add a table.")
|
||||||
|
|
||||||
|
# Create schema
|
||||||
|
self.schema_name = self.schema_info['schema_name']
|
||||||
|
self.schema_id = self.schema_info['schema_id']
|
||||||
|
schema_response = schema_utils.verify_schemas(self.server,
|
||||||
|
self.db_name,
|
||||||
|
self.schema_name)
|
||||||
|
if not schema_response:
|
||||||
|
raise Exception("Could not find the schema to add a table.")
|
||||||
|
|
||||||
|
# Create FDW, server & table
|
||||||
|
self.fdw_name = "fdw_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
self.fsrv_name = "fsrv_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
self.ft_name = "ft_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
|
||||||
|
self.fdw_id = fdw_utils.create_fdw(self.server, self.db_name,
|
||||||
|
self.fdw_name)
|
||||||
|
self.fsrv_id = fsrv_utils.create_fsrv(self.server, self.db_name,
|
||||||
|
self.fsrv_name, self.fdw_name)
|
||||||
|
self.ft_id = ft_utils.create_foreign_table(self.server, self.db_name,
|
||||||
|
self.schema_name,
|
||||||
|
self.fsrv_name,
|
||||||
|
self.ft_name)
|
||||||
|
|
||||||
|
# Create column
|
||||||
|
self.column_name = "test_column_delete_%s" % (str(uuid.uuid4())[1:8])
|
||||||
|
self.column_id = columns_utils.create_column(self.server,
|
||||||
|
self.db_name,
|
||||||
|
self.schema_name,
|
||||||
|
self.ft_name,
|
||||||
|
self.column_name)
|
||||||
|
if self.is_list:
|
||||||
|
# Create column
|
||||||
|
self.column_name_1 = "test_column_delete_%s" % \
|
||||||
|
(str(uuid.uuid4())[1:8])
|
||||||
|
self.column_id_1 = columns_utils.create_column(self.server,
|
||||||
|
self.db_name,
|
||||||
|
self.schema_name,
|
||||||
|
self.ft_name,
|
||||||
|
self.column_name_1)
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
"""This function will fetch the column under table node."""
|
||||||
|
if self.is_positive_test:
|
||||||
|
if self.is_list:
|
||||||
|
response = columns_utils.api_get(self, "")
|
||||||
|
else:
|
||||||
|
response = columns_utils.api_get(self)
|
||||||
|
|
||||||
|
# Assert response
|
||||||
|
utils.assert_status_code(self, response)
|
||||||
|
else:
|
||||||
|
if self.mocking_required:
|
||||||
|
with patch(self.mock_data["function_name"],
|
||||||
|
side_effect=eval(self.mock_data["return_value"])):
|
||||||
|
if self.is_list:
|
||||||
|
response = columns_utils.api_get(self, "")
|
||||||
|
else:
|
||||||
|
response = columns_utils.api_get(self)
|
||||||
|
else:
|
||||||
|
if 'column_id' in self.data:
|
||||||
|
self.column_id = self.data['column_id']
|
||||||
|
response = columns_utils.api_get(self)
|
||||||
|
|
||||||
|
# Assert response
|
||||||
|
utils.assert_status_code(self, response)
|
||||||
|
utils.assert_error_message(self, response)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
# Disconnect the database
|
||||||
|
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
@ -0,0 +1,203 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
from regression.python_test_utils import test_utils as utils
|
||||||
|
|
||||||
|
# Load test data from json file.
|
||||||
|
CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
with open(CURRENT_PATH + "/column_test_data.json") as data_file:
|
||||||
|
test_cases = json.load(data_file)
|
||||||
|
|
||||||
|
|
||||||
|
# api method calls
|
||||||
|
def api_create(self):
|
||||||
|
return self.tester.post("{0}{1}/{2}/{3}/{4}/{5}/".
|
||||||
|
format(self.url, utils.SERVER_GROUP,
|
||||||
|
self.server_id, self.db_id,
|
||||||
|
self.schema_id, self.ft_id),
|
||||||
|
data=json.dumps(self.data),
|
||||||
|
content_type='html/json'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def api_delete(self, column_id=None):
|
||||||
|
if column_id is None:
|
||||||
|
column_id = self.column_id
|
||||||
|
return self.tester.delete("{0}{1}/{2}/{3}/{4}/{5}/{6}".
|
||||||
|
format(self.url, utils.SERVER_GROUP,
|
||||||
|
self.server_id, self.db_id,
|
||||||
|
self.schema_id, self.ft_id, column_id),
|
||||||
|
data=json.dumps(self.data),
|
||||||
|
follow_redirects=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def api_get(self, column_id=None):
|
||||||
|
if column_id is None:
|
||||||
|
column_id = self.column_id
|
||||||
|
return self.tester.get("{0}{1}/{2}/{3}/{4}/{5}/{6}".
|
||||||
|
format(self.url, utils.SERVER_GROUP,
|
||||||
|
self.server_id, self.db_id, self.schema_id,
|
||||||
|
self.ft_id, column_id),
|
||||||
|
data=json.dumps(self.data),
|
||||||
|
follow_redirects=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def api_get_msql(self, url_encode_data):
|
||||||
|
return self.tester.get("{0}{1}/{2}/{3}/{4}/{5}/{6}?{7}".
|
||||||
|
format(self.url, utils.SERVER_GROUP, self.server_id,
|
||||||
|
self.db_id,
|
||||||
|
self.schema_id, self.ft_id,
|
||||||
|
self.column_id,
|
||||||
|
urlencode(url_encode_data)),
|
||||||
|
follow_redirects=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def api_put(self):
|
||||||
|
return self.tester.put("{0}{1}/{2}/{3}/{4}/{5}/{6}".
|
||||||
|
format(self.url, utils.SERVER_GROUP, self.server_id,
|
||||||
|
self.db_id, self.schema_id, self.ft_id,
|
||||||
|
self.column_id),
|
||||||
|
data=json.dumps(self.data),
|
||||||
|
follow_redirects=True)
|
||||||
|
|
||||||
|
|
||||||
|
def create_column(server, db_name, schema_name, table_name, col_name,
|
||||||
|
col_data_type='char'):
|
||||||
|
"""
|
||||||
|
This function creates a column under provided table.
|
||||||
|
:param server: server details
|
||||||
|
:type server: dict
|
||||||
|
:param db_name: database name
|
||||||
|
:type db_name: str
|
||||||
|
:param schema_name: schema name
|
||||||
|
:type schema_name: str
|
||||||
|
:param table_name: table name
|
||||||
|
:type table_name: str
|
||||||
|
:param col_name: column name
|
||||||
|
:type col_name: str
|
||||||
|
:param col_data_type: column data type
|
||||||
|
:type col_data_type: str
|
||||||
|
:return ft_id: table id
|
||||||
|
:rtype: int
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
connection = utils.get_db_connection(db_name,
|
||||||
|
server['username'],
|
||||||
|
server['db_password'],
|
||||||
|
server['host'],
|
||||||
|
server['port'],
|
||||||
|
server['sslmode'])
|
||||||
|
old_isolation_level = connection.isolation_level
|
||||||
|
utils.set_isolation_level(connection, 0)
|
||||||
|
pg_cursor = connection.cursor()
|
||||||
|
query = "ALTER FOREIGN TABLE %s.%s ADD COLUMN %s %s" % \
|
||||||
|
(schema_name, table_name, col_name, col_data_type)
|
||||||
|
pg_cursor.execute(query)
|
||||||
|
utils.set_isolation_level(connection, old_isolation_level)
|
||||||
|
connection.commit()
|
||||||
|
# Get column position of newly added column
|
||||||
|
pg_cursor.execute("select attnum from pg_attribute where"
|
||||||
|
" attname='%s'" % col_name)
|
||||||
|
col = pg_cursor.fetchone()
|
||||||
|
col_pos = ''
|
||||||
|
if col:
|
||||||
|
col_pos = col[0]
|
||||||
|
connection.close()
|
||||||
|
return col_pos
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc(file=sys.stderr)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def create_identity_column(server, db_name, schema_name, table_name,
|
||||||
|
col_name, col_data_type='bigint'):
|
||||||
|
"""
|
||||||
|
This function creates a column under provided table.
|
||||||
|
:param server: server details
|
||||||
|
:type server: dict
|
||||||
|
:param db_name: database name
|
||||||
|
:type db_name: str
|
||||||
|
:param schema_name: schema name
|
||||||
|
:type schema_name: str
|
||||||
|
:param table_name: table name
|
||||||
|
:type table_name: str
|
||||||
|
:param col_name: column name
|
||||||
|
:type col_name: str
|
||||||
|
:param col_data_type: column data type
|
||||||
|
:type col_data_type: str
|
||||||
|
:return table_id: table id
|
||||||
|
:rtype: int
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
connection = utils.get_db_connection(db_name,
|
||||||
|
server['username'],
|
||||||
|
server['db_password'],
|
||||||
|
server['host'],
|
||||||
|
server['port'],
|
||||||
|
server['sslmode'])
|
||||||
|
old_isolation_level = connection.isolation_level
|
||||||
|
utils.set_isolation_level(connection, 0)
|
||||||
|
pg_cursor = connection.cursor()
|
||||||
|
query = "ALTER TABLE %s.%s ADD COLUMN %s %s " \
|
||||||
|
"GENERATED ALWAYS AS IDENTITY" % \
|
||||||
|
(schema_name, table_name, col_name, col_data_type)
|
||||||
|
pg_cursor.execute(query)
|
||||||
|
utils.set_isolation_level(connection, old_isolation_level)
|
||||||
|
connection.commit()
|
||||||
|
# Get column position of newly added column
|
||||||
|
pg_cursor.execute("select attnum from pg_attribute where"
|
||||||
|
" attname='%s'" % col_name)
|
||||||
|
col = pg_cursor.fetchone()
|
||||||
|
col_pos = ''
|
||||||
|
if col:
|
||||||
|
col_pos = col[0]
|
||||||
|
connection.close()
|
||||||
|
return col_pos
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc(file=sys.stderr)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def verify_column(server, db_name, col_name):
|
||||||
|
"""
|
||||||
|
This function verifies table exist in database or not.
|
||||||
|
:param server: server details
|
||||||
|
:type server: dict
|
||||||
|
:param db_name: database name
|
||||||
|
:type db_name: str
|
||||||
|
:param col_name: column name
|
||||||
|
:type col_name: str
|
||||||
|
:return table: table record from database
|
||||||
|
:rtype: tuple
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
connection = utils.get_db_connection(db_name,
|
||||||
|
server['username'],
|
||||||
|
server['db_password'],
|
||||||
|
server['host'],
|
||||||
|
server['port'],
|
||||||
|
server['sslmode'])
|
||||||
|
pg_cursor = connection.cursor()
|
||||||
|
pg_cursor.execute("select * from pg_attribute where attname='%s'" %
|
||||||
|
col_name)
|
||||||
|
col = pg_cursor.fetchone()
|
||||||
|
connection.close()
|
||||||
|
return col
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc(file=sys.stderr)
|
||||||
|
raise
|
@ -11,15 +11,16 @@ import { getNodeVariableSchema } from '../../../../../static/js/variable.ui';
|
|||||||
import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
|
import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
|
||||||
import ForeignTableSchema from './foreign_table.ui';
|
import ForeignTableSchema from './foreign_table.ui';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import Notify from '../../../../../../../../static/js/helpers/Notifier';
|
||||||
|
|
||||||
/* Create and Register Foreign Table Collection and Node. */
|
/* Create and Register Foreign Table Collection and Node. */
|
||||||
define('pgadmin.node.foreign_table', [
|
define('pgadmin.node.foreign_table', ['pgadmin.tables.js/enable_disable_triggers',
|
||||||
'sources/gettext', 'sources/url_for', 'pgadmin.browser',
|
'sources/gettext', 'sources/url_for', 'pgadmin.browser',
|
||||||
'pgadmin.node.schema.dir/child', 'pgadmin.node.schema.dir/schema_child_tree_node',
|
'pgadmin.node.schema.dir/child', 'pgadmin.node.schema.dir/schema_child_tree_node',
|
||||||
'pgadmin.browser.collection','pgadmin.node.column',
|
'pgadmin.browser.collection','pgadmin.node.column',
|
||||||
'pgadmin.node.constraints'
|
'pgadmin.node.constraints'
|
||||||
], function(
|
], function(
|
||||||
gettext, url_for, pgBrowser, schemaChild, schemaChildTreeNode
|
tableFunctions, gettext, url_for, pgBrowser, schemaChild, schemaChildTreeNode,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if (!pgBrowser.Nodes['coll-foreign_table']) {
|
if (!pgBrowser.Nodes['coll-foreign_table']) {
|
||||||
@ -69,9 +70,54 @@ define('pgadmin.node.foreign_table', [
|
|||||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||||
category: 'create', priority: 4, label: gettext('Foreign Table...'),
|
category: 'create', priority: 4, label: gettext('Foreign Table...'),
|
||||||
data: {action: 'create', check: false}, enable: 'canCreate',
|
data: {action: 'create', check: false}, enable: 'canCreate',
|
||||||
},
|
},{
|
||||||
|
// To enable/disable all triggers for the table
|
||||||
|
name: 'enable_all_triggers', node: 'foreign_table', module: this,
|
||||||
|
applies: ['object', 'context'], callback: 'enable_triggers_on_table',
|
||||||
|
category: gettext('Trigger(s)'), priority: 4, label: gettext('Enable All'),
|
||||||
|
enable : 'canCreate_with_trigger_enable',
|
||||||
|
data: {
|
||||||
|
data_disabled: gettext('The selected tree node does not support this option.'),
|
||||||
|
action: 'create'
|
||||||
|
},
|
||||||
|
},{
|
||||||
|
name: 'disable_all_triggers', node: 'foreign_table', module: this,
|
||||||
|
applies: ['object', 'context'], callback: 'disable_triggers_on_table',
|
||||||
|
category: gettext('Trigger(s)'), priority: 4, label: gettext('Disable All'),
|
||||||
|
enable : 'canCreate_with_trigger_disable',
|
||||||
|
data: {
|
||||||
|
data_disabled: gettext('The selected tree node does not support this option.'),
|
||||||
|
action: 'create'
|
||||||
|
}}
|
||||||
]);
|
]);
|
||||||
|
},
|
||||||
|
callbacks: {
|
||||||
|
/* Enable trigger(s) on table */
|
||||||
|
enable_triggers_on_table: function(args) {
|
||||||
|
tableFunctions.enableTriggers(
|
||||||
|
pgBrowser.tree,
|
||||||
|
Notify,
|
||||||
|
this.generate_url.bind(this),
|
||||||
|
args
|
||||||
|
);
|
||||||
|
},
|
||||||
|
/* Disable trigger(s) on table */
|
||||||
|
disable_triggers_on_table: function(args) {
|
||||||
|
tableFunctions.disableTriggers(
|
||||||
|
pgBrowser.tree,
|
||||||
|
Notify,
|
||||||
|
this.generate_url.bind(this),
|
||||||
|
args
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Check to whether table has disable trigger(s)
|
||||||
|
canCreate_with_trigger_enable: function(itemData) {
|
||||||
|
return itemData.tigger_count > 0 && (itemData.has_enable_triggers == 0 || itemData.has_enable_triggers < itemData.tigger_count);
|
||||||
|
},
|
||||||
|
// Check to whether table has enable trigger(s)
|
||||||
|
canCreate_with_trigger_disable: function(itemData) {
|
||||||
|
return itemData.tigger_count > 0 && itemData.has_enable_triggers > 0;
|
||||||
},
|
},
|
||||||
getSchema: function(treeNodeInfo, itemNodeData) {
|
getSchema: function(treeNodeInfo, itemNodeData) {
|
||||||
return new ForeignTableSchema(
|
return new ForeignTableSchema(
|
||||||
|
@ -12,6 +12,7 @@ import SecLabelSchema from '../../../../../static/js/sec_label.ui';
|
|||||||
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
|
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
|
||||||
import OptionsSchema from '../../../../../static/js/options.ui';
|
import OptionsSchema from '../../../../../static/js/options.ui';
|
||||||
import { isEmptyString } from 'sources/validators';
|
import { isEmptyString } from 'sources/validators';
|
||||||
|
import VariableSchema from 'top/browser/server_groups/servers/static/js/variable.ui';
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
|
import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
|
||||||
@ -167,7 +168,7 @@ export default class ForeignTableSchema extends BaseUISchema {
|
|||||||
id: 'columns', label: gettext('Columns'), cell: 'text',
|
id: 'columns', label: gettext('Columns'), cell: 'text',
|
||||||
type: 'collection', group: gettext('Columns'), mode: ['edit', 'create'],
|
type: 'collection', group: gettext('Columns'), mode: ['edit', 'create'],
|
||||||
schema: this.columnsObj,
|
schema: this.columnsObj,
|
||||||
canAdd: true, canDelete: true, canEdit: true, columns: ['attname', 'datatype', 'inheritedfrom'],
|
canAdd: true, canDelete: true, canEdit: true, columns: ['name', 'cltype', 'attprecision', 'attlen', 'inheritedfrom'],
|
||||||
// For each row edit/delete button enable/disable
|
// For each row edit/delete button enable/disable
|
||||||
canEditRow: this.canEditDeleteRowColumns,
|
canEditRow: this.canEditDeleteRowColumns,
|
||||||
canDeleteRow: this.canEditDeleteRowColumns,
|
canDeleteRow: this.canEditDeleteRowColumns,
|
||||||
@ -256,27 +257,28 @@ export function getNodeColumnSchema(treeNodeInfo, itemNodeData, pgBrowser) {
|
|||||||
export class ColumnSchema extends BaseUISchema {
|
export class ColumnSchema extends BaseUISchema {
|
||||||
constructor(initValues, getPrivilegeRoleSchema, nodeInfo, datatypeOptions, collspcnameOptions) {
|
constructor(initValues, getPrivilegeRoleSchema, nodeInfo, datatypeOptions, collspcnameOptions) {
|
||||||
super({
|
super({
|
||||||
attname: undefined,
|
name: undefined,
|
||||||
datatype: undefined,
|
description: undefined,
|
||||||
typlen: undefined,
|
atttypid: undefined,
|
||||||
precision: undefined,
|
cltype: undefined,
|
||||||
typdefault: undefined,
|
edit_types: undefined,
|
||||||
|
attlen: undefined,
|
||||||
|
attprecision: undefined,
|
||||||
|
defval: undefined,
|
||||||
attnotnull: undefined,
|
attnotnull: undefined,
|
||||||
collname: undefined,
|
collspcname: undefined,
|
||||||
|
attstattarget:undefined,
|
||||||
attnum: undefined,
|
attnum: undefined,
|
||||||
inheritedfrom: undefined,
|
inheritedfrom: undefined,
|
||||||
inheritedid: undefined,
|
inheritedid: undefined,
|
||||||
attstattarget: undefined,
|
|
||||||
coloptions: [],
|
coloptions: [],
|
||||||
|
colconstype: 'n',
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
|
this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
|
||||||
this.nodeInfo = nodeInfo;
|
this.nodeInfo = nodeInfo;
|
||||||
this.datatypeOptions = datatypeOptions;
|
this.cltypeOptions = datatypeOptions;
|
||||||
this.collspcnameOptions = collspcnameOptions;
|
this.collspcnameOptions = collspcnameOptions;
|
||||||
|
|
||||||
this.datatypes = [];
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get idAttribute() {
|
get idAttribute() {
|
||||||
@ -287,43 +289,93 @@ export class ColumnSchema extends BaseUISchema {
|
|||||||
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)) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check whether the column is a generated column
|
||||||
|
isTypeGenerated(state) {
|
||||||
|
let colconstype = state.colconstype;
|
||||||
|
return (!_.isUndefined(colconstype) && !_.isNull(colconstype) && colconstype == 'g');
|
||||||
|
}
|
||||||
|
|
||||||
get baseFields() {
|
get baseFields() {
|
||||||
let obj = this;
|
let obj = this;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: 'attname', label: gettext('Name'), cell: 'text',
|
id: 'name', label: gettext('Name'), cell: 'text',
|
||||||
type: 'text', editable: obj.editable_check_for_column, noEmpty: true,
|
type: 'text', editable: obj.editable_check_for_column, noEmpty: true,
|
||||||
minWidth: 115,
|
minWidth: 115,
|
||||||
|
disabled: (state)=>{
|
||||||
|
return state.is_inherited;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'datatype', label: gettext('Data type'), minWidth: 150,
|
id: 'description', label: gettext('Comment'), cell: 'text',
|
||||||
group: gettext('Definition'), noEmpty: true,
|
type: 'multiline', mode: ['properties', 'create', 'edit'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'cltype',
|
||||||
|
label: gettext('Data type'),
|
||||||
|
minWidth: 150,
|
||||||
|
group: gettext('Definition'),
|
||||||
|
noEmpty: true,
|
||||||
editable: obj.editable_check_for_column,
|
editable: obj.editable_check_for_column,
|
||||||
options: obj.datatypeOptions,
|
disabled: (state)=>{
|
||||||
|
return state.is_inherited;
|
||||||
|
},
|
||||||
|
options: obj.cltypeOptions,
|
||||||
optionsLoaded: (options)=>{
|
optionsLoaded: (options)=>{
|
||||||
obj.datatypes = options;
|
|
||||||
obj.type_options = options;
|
obj.type_options = options;
|
||||||
},
|
},
|
||||||
cell: 'select',
|
cell: (row)=>{
|
||||||
|
return {
|
||||||
|
cell: 'select',
|
||||||
|
options: this.cltypeOptions,
|
||||||
|
controlProps: {
|
||||||
|
allowClear: false,
|
||||||
|
filter: (options)=>{
|
||||||
|
let result = options;
|
||||||
|
let edit_types = row?.edit_types || [];
|
||||||
|
if(!obj.isNew(row) && !this.inErd) {
|
||||||
|
result = _.filter(options, (o)=>edit_types.indexOf(o.value) > -1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
type: (state)=>{
|
||||||
|
return {
|
||||||
|
type: 'select',
|
||||||
|
options: this.cltypeOptions,
|
||||||
|
controlProps: {
|
||||||
|
allowClear: false,
|
||||||
|
filter: (options)=>{
|
||||||
|
let result = options;
|
||||||
|
let edit_types = state?.edit_types || [];
|
||||||
|
if(!obj.isNew(state) && !this.inErd) {
|
||||||
|
result = _.filter(options, (o)=>edit_types.indexOf(o.value) > -1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
controlProps: {
|
controlProps: {
|
||||||
allowClear: false,
|
allowClear: false,
|
||||||
},
|
}
|
||||||
type: 'select'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'inheritedfrom', label: gettext('Inherited From'), cell: 'label',
|
id: 'inheritedfrom', label: gettext('Inherited From'), cell: 'label',
|
||||||
type: 'label', readonly: true, editable: false, mode: ['properties', 'edit'],
|
type: 'label', readonly: true, editable: false, mode: ['create','properties', 'edit'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'attnum', label: gettext('Position'), cell: 'text',
|
id: 'attnum', label: gettext('Position'), cell: 'text',
|
||||||
type: 'text', disabled: obj.inCatalog(), mode: ['properties'],
|
type: 'text', disabled: obj.inCatalog(), mode: ['properties'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'typlen', label: gettext('Length'), cell: 'int',
|
id: 'attlen', label: gettext('Length'), cell: 'int',
|
||||||
deps: ['datatype'], type: 'int', group: gettext('Definition'), width: 120, minWidth: 120,
|
deps: ['cltype'], type: 'int', group: gettext('Definition'), minWidth: 60,
|
||||||
disabled: (state) => {
|
disabled: (state) => {
|
||||||
let val = state.typlen;
|
let val = state.attlen;
|
||||||
// We will store type from selected from combobox
|
// We will store type from selected from combobox
|
||||||
if(!(_.isUndefined(state.inheritedid)
|
if(!(_.isUndefined(state.inheritedid)
|
||||||
|| _.isNull(state.inheritedid)
|
|| _.isNull(state.inheritedid)
|
||||||
@ -331,12 +383,12 @@ export class ColumnSchema extends BaseUISchema {
|
|||||||
|| _.isNull(state.inheritedfrom))) {
|
|| _.isNull(state.inheritedfrom))) {
|
||||||
|
|
||||||
if (!_.isUndefined(val)) {
|
if (!_.isUndefined(val)) {
|
||||||
state.typlen = undefined;
|
state.attlen = undefined;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let of_type = state.datatype,
|
let of_type = state.cltype,
|
||||||
has_length = false;
|
has_length = false;
|
||||||
if(obj.type_options) {
|
if(obj.type_options) {
|
||||||
state.is_tlength = false;
|
state.is_tlength = false;
|
||||||
@ -358,34 +410,34 @@ export class ColumnSchema extends BaseUISchema {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!has_length && !_.isUndefined(val)) {
|
if (!has_length && !_.isUndefined(val)) {
|
||||||
state.typlen = undefined;
|
state.attlen = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !(state.is_tlength);
|
return !(state.is_tlength);
|
||||||
}
|
}
|
||||||
if (!has_length && !_.isUndefined(val)) {
|
if (!has_length && !_.isUndefined(val)) {
|
||||||
state.typlen = undefined;
|
state.attlen = undefined;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'precision', label: gettext('Precision'), cell: 'int', minWidth: 60,
|
id: 'attprecision', label: gettext('Scale'), cell: 'int', minWidth: 60,
|
||||||
deps: ['datatype'], type: 'int', group: gettext('Definition'),
|
deps: ['cltype'], type: 'int', group: gettext('Definition'),
|
||||||
disabled: (state) => {
|
disabled: (state) => {
|
||||||
let val = state.precision;
|
let val = state.attprecision;
|
||||||
if(!(_.isUndefined(state.inheritedid)
|
if(!(_.isUndefined(state.inheritedid)
|
||||||
|| _.isNull(state.inheritedid)
|
|| _.isNull(state.inheritedid)
|
||||||
|| _.isUndefined(state.inheritedfrom)
|
|| _.isUndefined(state.inheritedfrom)
|
||||||
|| _.isNull(state.inheritedfrom))) {
|
|| _.isNull(state.inheritedfrom))) {
|
||||||
|
|
||||||
if (!_.isUndefined(val)) {
|
if (!_.isUndefined(val)) {
|
||||||
state.precision = undefined;
|
state.attprecision = undefined;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let of_type = state.datatype,
|
let of_type = state.cltype,
|
||||||
has_precision = false;
|
has_precision = false;
|
||||||
|
|
||||||
if(obj.type_options) {
|
if(obj.type_options) {
|
||||||
@ -406,34 +458,16 @@ export class ColumnSchema extends BaseUISchema {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!has_precision && !_.isUndefined(val)) {
|
if (!has_precision && !_.isUndefined(val)) {
|
||||||
state.precision = undefined;
|
state.attprecision = undefined;
|
||||||
}
|
}
|
||||||
return !(state.is_precision);
|
return !(state.is_precision);
|
||||||
}
|
}
|
||||||
if (!has_precision && !_.isUndefined(val)) {
|
if (!has_precision && !_.isUndefined(val)) {
|
||||||
state.precision = undefined;
|
state.attprecision = undefined;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'typdefault', label: gettext('Default'), cell: 'text',
|
|
||||||
type: 'text', group: gettext('Definition'),
|
|
||||||
controlProps: {placeholder: gettext('Enter an expression or a value.')},
|
|
||||||
editable: (state) => {
|
|
||||||
if(!(_.isUndefined(state.inheritedid)
|
|
||||||
|| _.isNull(state.inheritedid)
|
|
||||||
|| _.isUndefined(state.inheritedfrom)
|
|
||||||
|| _.isNull(state.inheritedfrom))) { return false; }
|
|
||||||
|
|
||||||
return obj.nodeInfo.server.version >= 90300;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'attnotnull', label: gettext('Not NULL?'), cell: 'switch',
|
|
||||||
type: 'switch', minWidth: 80,
|
|
||||||
group: gettext('Definition'), editable: obj.editable_check_for_column,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'attstattarget', label: gettext('Statistics'), cell: 'text',
|
id: 'attstattarget', label: gettext('Statistics'), cell: 'text',
|
||||||
type: 'text', disabled: (state) => {
|
type: 'text', disabled: (state) => {
|
||||||
@ -451,9 +485,103 @@ export class ColumnSchema extends BaseUISchema {
|
|||||||
group: gettext('Definition'),
|
group: gettext('Definition'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'collname', label: gettext('Collation'), cell: 'select',
|
id: 'attstorage', label: gettext('Storage'), group: gettext('Definition'),
|
||||||
|
type: 'select', mode: ['properties', 'edit'],
|
||||||
|
cell: 'select', readonly: obj.inSchemaWithColumnCheck,
|
||||||
|
controlProps: { placeholder: gettext('Select storage'),
|
||||||
|
allowClear: false,
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{label: 'PLAIN', value: 'p'},
|
||||||
|
{label: 'MAIN', value: 'm'},
|
||||||
|
{label: 'EXTERNAL', value: 'e'},
|
||||||
|
{label: 'EXTENDED', value: 'x'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'defval',
|
||||||
|
label: gettext('Default'),
|
||||||
|
cell: 'text',
|
||||||
|
type: 'text',
|
||||||
|
group: gettext('Constraints'),
|
||||||
|
editable: (state) => {
|
||||||
|
if(!(_.isUndefined(state.inheritedid)
|
||||||
|
|| _.isNull(state.inheritedid)
|
||||||
|
|| _.isUndefined(state.inheritedfrom)
|
||||||
|
|| _.isNull(state.inheritedfrom))) { return false; }
|
||||||
|
|
||||||
|
return obj.nodeInfo.server.version >= 90300;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'attnotnull',
|
||||||
|
label: gettext('Not NULL?'),
|
||||||
|
cell: 'switch',
|
||||||
|
type: 'switch',
|
||||||
|
minWidth: 80,
|
||||||
|
group: gettext('Constraints'),
|
||||||
|
editable: obj.editable_check_for_column,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'colconstype',
|
||||||
|
label: gettext('Type'),
|
||||||
|
cell: 'text',
|
||||||
|
group: gettext('Constraints'),
|
||||||
|
type: (state)=>{
|
||||||
|
let options = [
|
||||||
|
{
|
||||||
|
'label': gettext('NONE'),
|
||||||
|
'value': 'n'},
|
||||||
|
]; // You can't change the existing column to Generated column.
|
||||||
|
if (this.isNew(state)) {
|
||||||
|
options.push({
|
||||||
|
'label': gettext('GENERATED'),
|
||||||
|
'value': 'g',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
options.push({
|
||||||
|
'label': gettext('GENERATED'),
|
||||||
|
'value': 'g',
|
||||||
|
'disabled': true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: 'toggle',
|
||||||
|
options: options,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
disabled: function(state) {
|
||||||
|
return (!this.isNew(state) && state.colconstype == 'g');
|
||||||
|
},
|
||||||
|
min_version: 120000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'genexpr',
|
||||||
|
label: gettext('Expression'),
|
||||||
|
type: 'text',
|
||||||
|
mode: ['properties', 'create', 'edit'],
|
||||||
|
group: gettext('Constraints'),
|
||||||
|
min_version: 120000,
|
||||||
|
deps: ['colconstype'],
|
||||||
|
visible: this.isTypeGenerated,
|
||||||
|
readonly: function(state) {
|
||||||
|
return !this.isNew(state);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'attoptions', label: gettext('Variables'), type: 'collection',
|
||||||
|
group: gettext('Variables'),
|
||||||
|
schema: new VariableSchema([
|
||||||
|
{label: 'n_distinct', value: 'n_distinct', vartype: 'string'},
|
||||||
|
{label: 'n_distinct_inherited', value: 'n_distinct_inherited', vartype: 'string'}
|
||||||
|
], null, null, ['name', 'value']),
|
||||||
|
uniqueCol : ['name'], mode: ['edit', 'create'],
|
||||||
|
canAdd: true, canEdit: false, canDelete: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'collspcname', label: gettext('Collation'), cell: 'select',
|
||||||
type: 'select', group: gettext('Definition'),
|
type: 'select', group: gettext('Definition'),
|
||||||
deps: ['datatype'], options: obj.collspcnameOptions,
|
deps: ['cltype'], options: obj.collspcnameOptions,
|
||||||
disabled: (state)=>{
|
disabled: (state)=>{
|
||||||
if (!(_.isUndefined(obj.isNew)) && !obj.isNew(state)) { return false; }
|
if (!(_.isUndefined(obj.isNew)) && !obj.isNew(state)) { return false; }
|
||||||
|
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
{% import 'macros/variable.macros' as VARIABLE %}
|
||||||
|
{% import 'types/macros/get_full_type_sql_format.macros' as GET_TYPE %}
|
||||||
|
{### Add column ###}
|
||||||
|
{% if data.name and data.cltype %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
ADD COLUMN {{conn|qtIdent(data.name)}} {% if is_sql %}{{data.displaytypname}}{% else %}{{ GET_TYPE.CREATE_TYPE_SQL(conn, data.cltype, data.attlen, data.attprecision, data.hasSqrBracket) }}{% endif %}
|
||||||
|
{### Add coloptions to column ###}
|
||||||
|
{% if data.coloptions %}{% for o in data.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 data.collspcname %}
|
||||||
|
COLLATE {{data.collspcname}}{% endif %}{% if data.attnotnull %}
|
||||||
|
NOT NULL{% endif %}{% if data.defval is defined and data.defval is not none and data.defval != '' and data.colconstype != 'g' %}
|
||||||
|
DEFAULT {{data.defval}}{% endif %}{% if data.colconstype == 'g' and data.genexpr and data.genexpr != '' %}
|
||||||
|
GENERATED ALWAYS AS ({{data.genexpr}}) STORED{% endif %}{% endif %};
|
||||||
|
|
||||||
|
{### Add comments ###}
|
||||||
|
{% if data and data.description and data.description != None %}
|
||||||
|
COMMENT ON COLUMN {{conn|qtIdent(data.schema, data.table, data.name)}}
|
||||||
|
IS {{data.description|qtLiteral(conn)}};
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{### Add variables to column ###}
|
||||||
|
{% if data.attoptions %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
{{ VARIABLE.SET(conn, 'COLUMN', data.name, data.attoptions) }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{### Alter column statistics value ###}
|
||||||
|
{% if data.attstattarget is defined and data.attstattarget > -1 %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
ALTER COLUMN {{conn|qtTypeIdent(data.name)}} SET STATISTICS {{data.attstattarget}};
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{### Alter column storage value ###}
|
||||||
|
{% if data.attstorage is defined and data.attstorage != data.defaultstorage %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
ALTER COLUMN {{conn|qtTypeIdent(data.name)}} SET STORAGE {%if data.attstorage == 'p' %}
|
||||||
|
PLAIN{% elif data.attstorage == 'm'%}MAIN{% elif data.attstorage == 'e'%}
|
||||||
|
EXTERNAL{% elif data.attstorage == 'x'%}EXTENDED{% endif %};
|
||||||
|
{% endif %}
|
@ -0,0 +1 @@
|
|||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}} DROP COLUMN IF EXISTS {{conn|qtIdent(data.name)}};
|
@ -0,0 +1,110 @@
|
|||||||
|
{% import 'macros/variable.macros' as VARIABLE %}
|
||||||
|
{% import 'types/macros/get_full_type_sql_format.macros' as GET_TYPE %}
|
||||||
|
{### Rename column name ###}
|
||||||
|
{% if data.name and data.name != o_data.name %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
RENAME {{conn|qtIdent(o_data.name)}} TO {{conn|qtIdent(data.name)}};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{### Add/Update column options ###}
|
||||||
|
{% if 'coloptions' in data and data.coloptions != None and data.coloptions|length > 0 %}
|
||||||
|
{% set coloptions = data.coloptions %}
|
||||||
|
{% if data.name %}
|
||||||
|
{% 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 %});
|
||||||
|
{% 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 %});
|
||||||
|
{% 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 %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{### Alter column type and collation ###}
|
||||||
|
{% if (data.cltype and data.cltype != o_data.cltype) or (data.attlen is defined and data.attlen != o_data.attlen) or (data.attprecision is defined and data.attprecision != o_data.attprecision) or (data.collspcname and data.collspcname != o_data.collspcname) or data.col_type_conversion is defined %}
|
||||||
|
{% if data.col_type_conversion is defined and data.col_type_conversion == False %}
|
||||||
|
-- WARNING:
|
||||||
|
-- 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 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 %};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{### Alter column default value ###}
|
||||||
|
{% if is_view_only and data.defval is defined and data.defval is not none and data.defval != '' and data.defval != o_data.defval %}
|
||||||
|
ALTER VIEW {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} SET DEFAULT {{data.defval}};
|
||||||
|
{% elif data.defval is defined and data.defval is not none and data.defval != '' and data.defval != o_data.defval %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} SET DEFAULT {{data.defval}};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{### Drop column default value ###}
|
||||||
|
{% if data.defval is defined and (data.defval == '' or data.defval is none) and data.defval != o_data.defval %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} DROP DEFAULT;
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{### Alter column not null value ###}
|
||||||
|
{% if 'attnotnull' in data and data.attnotnull != o_data.attnotnull %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} {% if data.attnotnull %}SET{% else %}DROP{% endif %} NOT NULL;
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{### Alter column statistics value ###}
|
||||||
|
{% if data.attstattarget is defined and data.attstattarget != o_data.attstattarget %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} SET STATISTICS {{data.attstattarget}};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{### Alter column storage value ###}
|
||||||
|
{% if data.attstorage is defined and data.attstorage != o_data.attstorage %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} SET STORAGE {%if data.attstorage == 'p' %}
|
||||||
|
PLAIN{% elif data.attstorage == 'm'%}MAIN{% elif data.attstorage == 'e'%}
|
||||||
|
EXTERNAL{% elif data.attstorage == 'x'%}EXTENDED{% endif %};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% if data.description is defined and data.description != None %}
|
||||||
|
{% if data.name %}
|
||||||
|
COMMENT ON COLUMN {{conn|qtIdent(data.schema, data.table, data.name)}}
|
||||||
|
{% else %}
|
||||||
|
COMMENT ON COLUMN {{conn|qtIdent(data.schema, data.table, o_data.name)}}
|
||||||
|
{% endif %}
|
||||||
|
IS {{data.description|qtLiteral(conn)}};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{### Update column variables ###}
|
||||||
|
{% if 'attoptions' in data and data.attoptions != None and data.attoptions|length > 0 %}
|
||||||
|
{% set variables = data.attoptions %}
|
||||||
|
{% if 'deleted' in variables and variables.deleted|length > 0 %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
{% if data.name %}
|
||||||
|
{{ VARIABLE.UNSET(conn, 'COLUMN', data.name, variables.deleted) }}
|
||||||
|
{% else %}
|
||||||
|
{{ VARIABLE.UNSET(conn, 'COLUMN', o_data.name, variables.deleted) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'added' in variables and variables.added|length > 0 %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
{% if data.name %}
|
||||||
|
{{ VARIABLE.SET(conn, 'COLUMN', data.name, variables.added) }}
|
||||||
|
{% else %}
|
||||||
|
{{ VARIABLE.SET(conn, 'COLUMN', o_data.name, variables.added) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'changed' in variables and variables.changed|length > 0 %}
|
||||||
|
ALTER FOREIGN TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
|
||||||
|
{% if data.name %}
|
||||||
|
{{ VARIABLE.SET(conn, 'COLUMN', data.name, variables.changed) }}
|
||||||
|
{% else %}
|
||||||
|
{{ VARIABLE.SET(conn, 'COLUMN', o_data.name, variables.changed) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
@ -7,12 +7,12 @@ CREATE FOREIGN TABLE{% if add_not_exists_clause %} IF NOT EXISTS{% endif %} {{ c
|
|||||||
{% for c in data.columns %}
|
{% for c in data.columns %}
|
||||||
{% if (not c.inheritedfrom or c.inheritedfrom =='' or c.inheritedfrom == None or c.inheritedfrom == 'None' ) %}
|
{% if (not c.inheritedfrom or c.inheritedfrom =='' or c.inheritedfrom == None or c.inheritedfrom == 'None' ) %}
|
||||||
{% if is_columns.append('1') %}{% endif %}
|
{% if is_columns.append('1') %}{% endif %}
|
||||||
{{conn|qtIdent(c.attname)}} {% if is_sql %}{{ c.fulltype }}{% else %}{{c.datatype }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}{% endif %}{% if c.coloptions %}
|
{{conn|qtIdent(c.name)}} {% if is_sql %}{{ c.fulltype }}{% else %}{{c.cltype }}{% if c.attlen %}({{c.attlen}}{% if c.attprecision %}, {{c.attprecision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}{% endif %}{% if c.coloptions %}
|
||||||
{% for o in c.coloptions %}{% if o.option is defined and o.value is defined %}
|
{% 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 %}
|
{% if loop.first %} OPTIONS ({% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral(conn)}}{% if loop.last %}){% endif %}{% endif %}
|
||||||
{% endfor %}{% endif %}
|
{% endfor %}{% endif %}
|
||||||
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
||||||
{% if c.typdefault is defined and c.typdefault is not none %} DEFAULT {{c.typdefault}}{% endif %}
|
{% if c.defval is defined and c.defval is not none %} DEFAULT {{c.defval}}{% endif %}
|
||||||
{% if c.collname %} COLLATE {{c.collname}}{% endif %}
|
{% if c.collname %} COLLATE {{c.collname}}{% endif %}
|
||||||
{% if not loop.last %},
|
{% if not loop.last %},
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -51,7 +51,7 @@ COMMENT ON FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}
|
|||||||
{% for c in data.columns %}
|
{% for c in data.columns %}
|
||||||
{% if c.description %}
|
{% if c.description %}
|
||||||
|
|
||||||
COMMENT ON COLUMN {{conn|qtIdent(data.basensp, data.name, c.attname)}}
|
COMMENT ON COLUMN {{conn|qtIdent(data.basensp, data.name, c.name)}}
|
||||||
IS {{c.description|qtLiteral(conn)}};
|
IS {{c.description|qtLiteral(conn)}};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
SELECT t.main_oid, pg_catalog.ARRAY_AGG(t.typname) as edit_types
|
||||||
|
FROM
|
||||||
|
(SELECT pc.castsource AS main_oid, pg_catalog.format_type(tt.oid,NULL) AS typname
|
||||||
|
FROM pg_catalog.pg_type tt
|
||||||
|
JOIN pg_catalog.pg_cast pc ON tt.oid=pc.casttarget
|
||||||
|
WHERE pc.castsource IN ({{type_ids}})
|
||||||
|
AND pc.castcontext IN ('i', 'a')
|
||||||
|
UNION
|
||||||
|
SELECT tt.typbasetype AS main_oid, pg_catalog.format_type(tt.oid,NULL) AS typname
|
||||||
|
FROM pg_catalog.pg_type tt
|
||||||
|
WHERE tt.typbasetype IN ({{type_ids}})
|
||||||
|
) t
|
||||||
|
GROUP BY t.main_oid;
|
@ -0,0 +1,3 @@
|
|||||||
|
{% set enable_map = {'O':'ENABLE', 'D':'DISABLE'} %}
|
||||||
|
ALTER FOREIGN TABLE {{ conn|qtIdent(data.basensp, data.name) }}
|
||||||
|
{{ enable_map[is_enable_trigger] }} TRIGGER ALL;
|
@ -16,7 +16,7 @@ CREATE FOREIGN TABLE {{ conn|qtIdent(o_data.basensp, o_data.name) }}(
|
|||||||
{% for c in columns %}
|
{% for c in columns %}
|
||||||
{% if (not c.inheritedfrom or c.inheritedfrom =='' or c.inheritedfrom == None or c.inheritedfrom == 'None' ) %}
|
{% if (not c.inheritedfrom or c.inheritedfrom =='' or c.inheritedfrom == None or c.inheritedfrom == 'None' ) %}
|
||||||
{% if is_columns.append('1') %}{% endif %}
|
{% if is_columns.append('1') %}{% endif %}
|
||||||
{{conn|qtIdent(c.attname)}} {% if is_sql %}{{ c.fulltype }}{% else %}{{c.datatype }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}{% endif %}{% if c.coloptions %}
|
{{conn|qtIdent(c.name)}} {% if is_sql %}{{ c.fulltype }}{% else %}{{c.cltype }}{% if c.attlen %}({{c.attlen}}{% if c.attprecision %}, {{c.attprecision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}{% endif %}{% if c.coloptions %}
|
||||||
{% for o in c.coloptions %}{% if o.option is defined and o.value is defined %}
|
{% 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 %}
|
{% if loop.first %} OPTIONS ({% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral(conn)}}{% if loop.last %}){% endif %}{% endif %}
|
||||||
{% endfor %}{% endif %}
|
{% endfor %}{% endif %}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
WITH INH_TABLES AS
|
WITH INH_TABLES AS
|
||||||
(SELECT
|
(SELECT
|
||||||
distinct on (at.attname) attname, ph.inhparent AS inheritedid, ph.inhseqno,
|
at.attname AS name, ph.inhparent AS inheritedid, ph.inhseqno,
|
||||||
pg_catalog.concat(nmsp_parent.nspname, '.',parent.relname ) AS inheritedfrom
|
pg_catalog.concat(nmsp_parent.nspname, '.',parent.relname ) AS inheritedfrom
|
||||||
FROM
|
FROM
|
||||||
pg_catalog.pg_attribute at
|
pg_catalog.pg_attribute at
|
||||||
@ -13,9 +13,12 @@ WITH INH_TABLES AS
|
|||||||
GROUP BY at.attname, ph.inhparent, ph.inhseqno, inheritedfrom
|
GROUP BY at.attname, ph.inhparent, ph.inhseqno, inheritedfrom
|
||||||
ORDER BY at.attname, ph.inhparent, ph.inhseqno, inheritedfrom
|
ORDER BY at.attname, ph.inhparent, ph.inhseqno, inheritedfrom
|
||||||
)
|
)
|
||||||
SELECT INH.inheritedfrom, INH.inheritedid, att.attoptions, attfdwoptions,
|
SELECT INH.inheritedfrom, INH.inheritedid, att.attoptions, att.atttypid, attfdwoptions,
|
||||||
att.attname, att.attndims, att.atttypmod, pg_catalog.format_type(t.oid,NULL) AS datatype,
|
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.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,
|
||||||
|
(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
|
CASE WHEN length(cn.nspname::text) > 0 AND length(cl.collname::text) > 0 THEN
|
||||||
pg_catalog.concat(cn.nspname, '."', cl.collname,'"')
|
pg_catalog.concat(cn.nspname, '."', cl.collname,'"')
|
||||||
ELSE '' END AS collname,
|
ELSE '' END AS collname,
|
||||||
@ -25,7 +28,7 @@ SELECT INH.inheritedfrom, INH.inheritedid, att.attoptions, attfdwoptions,
|
|||||||
FROM
|
FROM
|
||||||
pg_catalog.pg_attribute att
|
pg_catalog.pg_attribute att
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
INH_TABLES as INH ON att.attname = INH.attname
|
INH_TABLES as INH ON att.attname = INH.name
|
||||||
JOIN
|
JOIN
|
||||||
pg_catalog.pg_type t ON t.oid=atttypid
|
pg_catalog.pg_type t ON t.oid=atttypid
|
||||||
JOIN
|
JOIN
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
SELECT count(*) FROM pg_catalog.pg_trigger WHERE tgrelid={{tid}} AND tgisinternal = FALSE AND tgenabled = 'O'
|
@ -1,6 +1,6 @@
|
|||||||
{% if attrelid %}
|
{% if attrelid %}
|
||||||
SELECT
|
SELECT
|
||||||
a.attname, pg_catalog.format_type(a.atttypid, NULL) AS datatype,
|
a.attname as name, pg_catalog.format_type(a.atttypid, NULL) AS cltype,
|
||||||
pg_catalog.quote_ident(n.nspname)||'.'||quote_ident(c.relname) as inheritedfrom,
|
pg_catalog.quote_ident(n.nspname)||'.'||quote_ident(c.relname) as inheritedfrom,
|
||||||
c.oid as inheritedid
|
c.oid as inheritedid
|
||||||
FROM
|
FROM
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
SELECT
|
SELECT
|
||||||
c.oid, c.relname AS name, pg_catalog.pg_get_userbyid(relowner) AS owner,
|
c.oid, c.relname AS name, pg_catalog.pg_get_userbyid(relowner) AS owner,
|
||||||
ftoptions, nspname as basensp, description
|
ftoptions, nspname as basensp, description,
|
||||||
|
(SELECT count(*) FROM pg_catalog.pg_trigger WHERE tgrelid=c.oid AND tgisinternal = FALSE) AS triggercount,
|
||||||
|
(SELECT count(*) FROM pg_catalog.pg_trigger WHERE tgrelid=c.oid AND tgisinternal = FALSE AND tgenabled = 'O') AS has_enable_triggers
|
||||||
FROM
|
FROM
|
||||||
pg_catalog.pg_class c
|
pg_catalog.pg_class c
|
||||||
JOIN
|
JOIN
|
||||||
|
@ -17,41 +17,42 @@ ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
|||||||
{% for c in data.columns.deleted %}
|
{% for c in data.columns.deleted %}
|
||||||
{% if (not c.inheritedfrom or c.inheritedfrom =='' or c.inheritedfrom == None or c.inheritedfrom == 'None' ) %}
|
{% 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) }}
|
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||||
DROP COLUMN {{conn|qtIdent(c.attname)}};
|
DROP COLUMN {{conn|qtIdent(c.name)}};
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor -%}
|
{% endfor -%}
|
||||||
{% for c in data.columns.added %}
|
{% for c in data.columns.added %}
|
||||||
{% if (not c.inheritedfrom or c.inheritedfrom =='' or c.inheritedfrom == None or c.inheritedfrom == 'None' ) %}
|
{% 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) }}
|
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||||
ADD COLUMN {{conn|qtIdent(c.attname)}} {{ c.datatype }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %}
|
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 %}
|
{% if c.coloptions %}
|
||||||
{% for o in c.coloptions %}{% if o.option is defined and o.value is defined %}
|
{% 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 %}
|
{% if loop.first %} OPTIONS ({% endif %}{% if not loop.first %}, {% endif %}{{o.option}} {{o.value|qtLiteral(conn)}}{% if loop.last %}){% endif %}{% endif %}
|
||||||
{% endfor %}{% endif %}
|
{% endfor %}{% endif %}
|
||||||
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
{% if c.attnotnull %} NOT NULL{% else %} NULL{% endif %}
|
||||||
{% if c.typdefault is defined and c.typdefault is not none %} DEFAULT {{c.typdefault}}{% endif %}
|
{% if c.defval is defined and c.defval is not none %} DEFAULT {{c.defval}}{% endif %}
|
||||||
{% if c.collname %} COLLATE {{c.collname}}{% endif %};
|
{% if c.collname %} COLLATE {{c.collname}}{% endif %};
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor -%}
|
{% endfor -%}
|
||||||
{% for c in data.columns.changed %}
|
{% for c in data.columns.changed %}
|
||||||
{% set col_name = o_data['columns'][c.attnum]['attname'] %}
|
{% set col_name = o_data['columns'][c.attnum]['name'] %}
|
||||||
{% if c.attname != o_data['columns'][c.attnum]['attname'] %}
|
{% if c.name %}{% if c.name != o_data['columns'][c.attnum]['name'] %}
|
||||||
{% set col_name = c.attname %}
|
{% set col_name = c.name %}
|
||||||
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||||
RENAME COLUMN {{conn|qtIdent(o_data['columns'][c.attnum]['attname'])}} TO {{conn|qtIdent(c.attname)}};
|
RENAME COLUMN {{conn|qtIdent(o_data['columns'][c.attnum]['name'])}} TO {{conn|qtIdent(c.name)}};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if c.attnotnull != o_data['columns'][c.attnum]['attnotnull'] %}
|
{% if c.attnotnull != o_data['columns'][c.attnum]['attnotnull'] %}
|
||||||
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
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;
|
ALTER COLUMN {{conn|qtIdent(col_name)}}{% if c.attnotnull %} SET{% else %} DROP{% endif %} NOT NULL;
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if c.datatype != o_data['columns'][c.attnum]['datatype'] or c.typlen != o_data['columns'][c.attnum]['typlen'] or
|
{% if c.cltype != o_data['columns'][c.attnum]['cltype'] or c.attlen != o_data['columns'][c.attnum]['attlen'] or
|
||||||
c.precision != o_data['columns'][c.attnum]['precision'] %}
|
c.attprecision != o_data['columns'][c.attnum]['attprecision'] %}
|
||||||
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
ALTER FOREIGN TABLE IF EXISTS {{ conn|qtIdent(o_data.basensp, name) }}
|
||||||
ALTER COLUMN {{conn|qtIdent(col_name)}} TYPE {{ c.datatype }}{% if c.typlen %}({{c.typlen}}{% if c.precision %}, {{c.precision}}{% endif %}){% endif %}{% if c.isArrayType %}[]{% endif %};
|
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 %}
|
{% endif %}
|
||||||
{% if c.typdefault is defined and c.typdefault != o_data['columns'][c.attnum]['typdefault'] %}
|
{% if c.typdefault is defined and c.typdefault != o_data['columns'][c.attnum]['typdefault'] %}
|
||||||
@ -83,7 +84,7 @@ 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 %}
|
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 %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif -%}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if data.inherits and data.inherits|length > 0%}
|
{% if data.inherits and data.inherits|length > 0%}
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
"basensp": "schema_name",
|
"basensp": "schema_name",
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
"attname": "ename",
|
"name": "ename",
|
||||||
"datatype": "text",
|
"cltype": "text",
|
||||||
"coloptions": []
|
"coloptions": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -41,8 +41,8 @@
|
|||||||
"basensp": "schema_name",
|
"basensp": "schema_name",
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
"attname": "ename",
|
"name": "ename",
|
||||||
"datatype": "text",
|
"cltype": "text",
|
||||||
"coloptions": []
|
"coloptions": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -72,8 +72,8 @@
|
|||||||
"basensp": "schema_name",
|
"basensp": "schema_name",
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
"attname": "ename",
|
"name": "ename",
|
||||||
"datatype": "text",
|
"cltype": "text",
|
||||||
"coloptions": []
|
"coloptions": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -255,8 +255,8 @@
|
|||||||
"columns": {
|
"columns": {
|
||||||
"added": [
|
"added": [
|
||||||
{
|
{
|
||||||
"attname": "col2",
|
"name": "col2",
|
||||||
"datatype": "character varying[]",
|
"cltype": "character varying[]",
|
||||||
"coloptions": []
|
"coloptions": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -268,8 +268,8 @@
|
|||||||
"value": "OptionValue"
|
"value": "OptionValue"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"attname": "emp",
|
"name": "emp",
|
||||||
"datatype": "\"char\"",
|
"cltype": "\"char\"",
|
||||||
"typdefault": null,
|
"typdefault": null,
|
||||||
"attnotnull": false,
|
"attnotnull": false,
|
||||||
"collname": "pg_catalog.\"default\"",
|
"collname": "pg_catalog.\"default\"",
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
"fdwoptions": []
|
"fdwoptions": []
|
||||||
},
|
},
|
||||||
"store_object_id": "True"
|
"store_object_id": "True"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"type": "create",
|
"type": "create",
|
||||||
"name": "Create foreign server for foreign table",
|
"name": "Create foreign server for foreign table",
|
||||||
"endpoint": "NODE-foreign_server.obj",
|
"endpoint": "NODE-foreign_server.obj",
|
||||||
@ -20,7 +21,8 @@
|
|||||||
"name":"test_fs_for_foreign_table"
|
"name":"test_fs_for_foreign_table"
|
||||||
},
|
},
|
||||||
"store_object_id": "True"
|
"store_object_id": "True"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"type": "create",
|
"type": "create",
|
||||||
"name": "Create Foreign Table with all options",
|
"name": "Create Foreign Table with all options",
|
||||||
"endpoint": "NODE-foreign_table.obj",
|
"endpoint": "NODE-foreign_table.obj",
|
||||||
@ -34,12 +36,12 @@
|
|||||||
"description":"Test Comment",
|
"description":"Test Comment",
|
||||||
"ftsrvname":"test_fs_for_foreign_table",
|
"ftsrvname":"test_fs_for_foreign_table",
|
||||||
"columns":[{
|
"columns":[{
|
||||||
"attname":"col1",
|
"name":"col1",
|
||||||
"datatype":"bigint",
|
"cltype":"bigint",
|
||||||
"coloptions":[]
|
"coloptions":[]
|
||||||
},{
|
},{
|
||||||
"attname":"col2",
|
"name":"col2",
|
||||||
"datatype":"text",
|
"cltype":"text",
|
||||||
"coloptions":[]
|
"coloptions":[]
|
||||||
}],
|
}],
|
||||||
"constraints":[{
|
"constraints":[{
|
||||||
@ -107,12 +109,12 @@
|
|||||||
"description":"Test Comment",
|
"description":"Test Comment",
|
||||||
"columns": {
|
"columns": {
|
||||||
"added": [{
|
"added": [{
|
||||||
"attname":"col1",
|
"name":"col1",
|
||||||
"datatype":"bigint",
|
"cltype":"bigint",
|
||||||
"coloptions":[]
|
"coloptions":[]
|
||||||
},{
|
},{
|
||||||
"attname":"col2",
|
"name":"col2",
|
||||||
"datatype":"text",
|
"cltype":"text",
|
||||||
"coloptions":[]
|
"coloptions":[]
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
@ -182,17 +184,17 @@
|
|||||||
},
|
},
|
||||||
"columns": {
|
"columns": {
|
||||||
"changed": [{
|
"changed": [{
|
||||||
"attname": "col1",
|
"name": "col1",
|
||||||
"attnum": 1,
|
"attnum": 1,
|
||||||
"attoptions": null,
|
"attoptions": null,
|
||||||
"collname": "",
|
"collname": "",
|
||||||
"coloptions": [],
|
"coloptions": [],
|
||||||
"datatype": "integer",
|
"cltype": "integer",
|
||||||
"fulltype": "bigint"
|
"fulltype": "bigint"
|
||||||
}],
|
}],
|
||||||
"deleted": [{
|
"deleted": [{
|
||||||
"attname":"col2",
|
"name":"col2",
|
||||||
"datatype":"text"
|
"cltype":"text"
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -34,12 +34,12 @@
|
|||||||
"description":"Test Comment",
|
"description":"Test Comment",
|
||||||
"ftsrvname":"test_fs_for_foreign_table",
|
"ftsrvname":"test_fs_for_foreign_table",
|
||||||
"columns":[{
|
"columns":[{
|
||||||
"attname":"col1",
|
"name":"col1",
|
||||||
"datatype":"bigint",
|
"cltype":"bigint",
|
||||||
"coloptions":[]
|
"coloptions":[]
|
||||||
},{
|
},{
|
||||||
"attname":"col2",
|
"name":"col2",
|
||||||
"datatype":"text",
|
"cltype":"text",
|
||||||
"coloptions":[]
|
"coloptions":[]
|
||||||
}],
|
}],
|
||||||
"constraints":[{
|
"constraints":[{
|
||||||
@ -107,12 +107,12 @@
|
|||||||
"description":"Test Comment",
|
"description":"Test Comment",
|
||||||
"columns": {
|
"columns": {
|
||||||
"added": [{
|
"added": [{
|
||||||
"attname":"col1",
|
"name":"col1",
|
||||||
"datatype":"bigint",
|
"cltype":"bigint",
|
||||||
"coloptions":[]
|
"coloptions":[]
|
||||||
},{
|
},{
|
||||||
"attname":"col2",
|
"name":"col2",
|
||||||
"datatype":"text",
|
"cltype":"text",
|
||||||
"coloptions":[]
|
"coloptions":[]
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
@ -182,17 +182,17 @@
|
|||||||
},
|
},
|
||||||
"columns": {
|
"columns": {
|
||||||
"changed": [{
|
"changed": [{
|
||||||
"attname": "col1",
|
"name": "col1",
|
||||||
"attnum": 1,
|
"attnum": 1,
|
||||||
"attoptions": null,
|
"attoptions": null,
|
||||||
"collname": "",
|
"collname": "",
|
||||||
"coloptions": [],
|
"coloptions": [],
|
||||||
"datatype": "integer",
|
"cltype": "integer",
|
||||||
"fulltype": "bigint"
|
"fulltype": "bigint"
|
||||||
}],
|
}],
|
||||||
"deleted": [{
|
"deleted": [{
|
||||||
"attname":"col2",
|
"name":"col2",
|
||||||
"datatype":"text"
|
"cltype":"text"
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -25,6 +25,7 @@ from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
|||||||
make_response as ajax_response, gone
|
make_response as ajax_response, gone
|
||||||
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
||||||
columns import utils as column_utils
|
columns import utils as column_utils
|
||||||
|
from pgadmin.utils.compile_template_name import compile_template_path
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
from pgadmin.utils.ajax import ColParamsJSONDecoder
|
from pgadmin.utils.ajax import ColParamsJSONDecoder
|
||||||
@ -214,6 +215,9 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
|
|||||||
self.template_path = self.BASE_TEMPLATE_PATH.format(
|
self.template_path = self.BASE_TEMPLATE_PATH.format(
|
||||||
self.manager.version)
|
self.manager.version)
|
||||||
|
|
||||||
|
self.foreign_table_column_template_path = compile_template_path(
|
||||||
|
'foreign_table_columns/sql', self.manager.version)
|
||||||
|
|
||||||
# Allowed ACL for column 'Select/Update/Insert/References'
|
# Allowed ACL for column 'Select/Update/Insert/References'
|
||||||
self.acl = ['a', 'r', 'w', 'x']
|
self.acl = ['a', 'r', 'w', 'x']
|
||||||
|
|
||||||
@ -420,7 +424,11 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
|
|||||||
column_utils.type_formatter(data['cltype'])
|
column_utils.type_formatter(data['cltype'])
|
||||||
data = column_utils.convert_length_precision_to_string(data)
|
data = column_utils.convert_length_precision_to_string(data)
|
||||||
|
|
||||||
SQL = render_template("/".join([self.template_path,
|
# Check if node is foreign_table_column
|
||||||
|
template_path = self.foreign_table_column_template_path \
|
||||||
|
if self.node_type == 'foreign_table_column' else self.template_path
|
||||||
|
|
||||||
|
SQL = render_template("/".join([template_path,
|
||||||
self._CREATE_SQL]),
|
self._CREATE_SQL]),
|
||||||
data=data, conn=self.conn)
|
data=data, conn=self.conn)
|
||||||
status, res = self.conn.execute_scalar(SQL)
|
status, res = self.conn.execute_scalar(SQL)
|
||||||
@ -493,7 +501,12 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
|
|||||||
data['schema'] = self.schema
|
data['schema'] = self.schema
|
||||||
data['table'] = self.table
|
data['table'] = self.table
|
||||||
|
|
||||||
SQL = render_template("/".join([self.template_path,
|
# Check if node is foreign_table_column
|
||||||
|
template_path = self.foreign_table_column_template_path \
|
||||||
|
if self.node_type == 'foreign_table_column' \
|
||||||
|
else self.template_path
|
||||||
|
|
||||||
|
SQL = render_template("/".join([template_path,
|
||||||
self._DELETE_SQL]),
|
self._DELETE_SQL]),
|
||||||
data=data, conn=self.conn)
|
data=data, conn=self.conn)
|
||||||
status, res = self.conn.execute_scalar(SQL)
|
status, res = self.conn.execute_scalar(SQL)
|
||||||
@ -649,9 +662,15 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
|
|||||||
if 'attacl' in data:
|
if 'attacl' in data:
|
||||||
data['attacl'] = parse_priv_to_db(data['attacl'],
|
data['attacl'] = parse_priv_to_db(data['attacl'],
|
||||||
self.acl)
|
self.acl)
|
||||||
|
|
||||||
|
# Check if node is foreign_table_column
|
||||||
|
template_path = self.foreign_table_column_template_path \
|
||||||
|
if self.node_type == 'foreign_table_column' \
|
||||||
|
else self.template_path
|
||||||
|
|
||||||
# If the request for new object which do not have did
|
# If the request for new object which do not have did
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
"/".join([self.template_path, self._CREATE_SQL]),
|
"/".join([template_path, self._CREATE_SQL]),
|
||||||
data=data, conn=self.conn, is_sql=is_sql
|
data=data, conn=self.conn, is_sql=is_sql
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -687,6 +706,11 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
|
|||||||
data = column_utils.convert_length_precision_to_string(data)
|
data = column_utils.convert_length_precision_to_string(data)
|
||||||
|
|
||||||
if clid is not None:
|
if clid is not None:
|
||||||
|
# Check if node is foreign_table_column
|
||||||
|
template_path = self.foreign_table_column_template_path \
|
||||||
|
if self.node_type == 'foreign_table_column' \
|
||||||
|
else self.template_path
|
||||||
|
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
||||||
tid=tid, clid=clid,
|
tid=tid, clid=clid,
|
||||||
@ -714,7 +738,7 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
|
|||||||
self._parse_acl_to_db_parsing(data, old_data)
|
self._parse_acl_to_db_parsing(data, old_data)
|
||||||
|
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
"/".join([self.template_path, self._UPDATE_SQL]),
|
"/".join([template_path, self._UPDATE_SQL]),
|
||||||
data=data, o_data=old_data, conn=self.conn,
|
data=data, o_data=old_data, conn=self.conn,
|
||||||
is_view_only=is_view_only
|
is_view_only=is_view_only
|
||||||
)
|
)
|
||||||
@ -778,8 +802,12 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
|
|||||||
self.conn, data['schema'], data['table'], data['name'])
|
self.conn, data['schema'], data['table'], data['name'])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Join delete sql
|
||||||
|
template_path = self.foreign_table_column_template_path \
|
||||||
|
if self.node_type == 'foreign_table_column' \
|
||||||
|
else self.template_path
|
||||||
sql_header += render_template(
|
sql_header += render_template(
|
||||||
"/".join([self.template_path, self._DELETE_SQL]),
|
"/".join([template_path, self._DELETE_SQL]),
|
||||||
data=data, conn=self.conn
|
data=data, conn=self.conn
|
||||||
)
|
)
|
||||||
SQL = sql_header + '\n\n' + SQL
|
SQL = sql_header + '\n\n' + SQL
|
||||||
|
@ -155,6 +155,10 @@ def column_formatter(conn, tid, clid, data, edit_types_list=None,
|
|||||||
|
|
||||||
data['seclabels'] = seclabels
|
data['seclabels'] = seclabels
|
||||||
|
|
||||||
|
# Get formatted Column Options
|
||||||
|
if 'attfdwoptions' in data and data['attfdwoptions'] != '':
|
||||||
|
data['coloptions'] = _parse_options_for_column(data['attfdwoptions'])
|
||||||
|
|
||||||
# We need to parse & convert ACL coming from database to json format
|
# We need to parse & convert ACL coming from database to json format
|
||||||
SQL = render_template("/".join([template_path, 'acl.sql']),
|
SQL = render_template("/".join([template_path, 'acl.sql']),
|
||||||
tid=tid, clid=clid)
|
tid=tid, clid=clid)
|
||||||
@ -186,12 +190,44 @@ def column_formatter(conn, tid, clid, data, edit_types_list=None,
|
|||||||
# We will need present type in edit mode
|
# We will need present type in edit mode
|
||||||
edit_types_list.append(data['typname'])
|
edit_types_list.append(data['typname'])
|
||||||
data['edit_types'] = sorted(edit_types_list)
|
data['edit_types'] = sorted(edit_types_list)
|
||||||
|
|
||||||
data['cltype'] = DataTypeReader.parse_type_name(data['cltype'])
|
data['cltype'] = DataTypeReader.parse_type_name(data['cltype'])
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_options_for_column(db_variables):
|
||||||
|
"""
|
||||||
|
Function to format the output for variables.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
db_variables: Variable object
|
||||||
|
|
||||||
|
Expected Object Format:
|
||||||
|
['option1=value1', ..]
|
||||||
|
where:
|
||||||
|
user_name and database are optional
|
||||||
|
Returns:
|
||||||
|
Variable Object in below format:
|
||||||
|
{
|
||||||
|
'variables': [
|
||||||
|
{'name': 'var_name', 'value': 'var_value',
|
||||||
|
'user_name': 'user_name', 'database': 'database_name'},
|
||||||
|
...]
|
||||||
|
}
|
||||||
|
where:
|
||||||
|
user_name and database are optional
|
||||||
|
"""
|
||||||
|
variables_lst = []
|
||||||
|
|
||||||
|
if db_variables is not None:
|
||||||
|
for row in db_variables:
|
||||||
|
# The value may contain equals in string, split on
|
||||||
|
# first equals only
|
||||||
|
var_name, var_value = row.split("=", 1)
|
||||||
|
var_dict = {'option': var_name, 'value': var_value}
|
||||||
|
variables_lst.append(var_dict)
|
||||||
|
return variables_lst
|
||||||
|
|
||||||
|
|
||||||
@get_template_path
|
@get_template_path
|
||||||
def get_formatted_columns(conn, tid, data, other_columns,
|
def get_formatted_columns(conn, tid, data, other_columns,
|
||||||
table_or_type, template_path=None):
|
table_or_type, template_path=None):
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
SELECT DISTINCT ON (att.attnum) att.attname as name, att.atttypid, att.attlen, att.attnum, att.attndims,
|
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.attstattarget,
|
att.atttypmod, att.attacl, att.attnotnull, att.attoptions, att.attfdwoptions, att.attstattarget,
|
||||||
att.attstorage, att.attidentity,
|
att.attstorage, att.attidentity,
|
||||||
pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS defval,
|
pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS defval,
|
||||||
pg_catalog.format_type(ty.oid,NULL) AS typname,
|
pg_catalog.format_type(ty.oid,NULL) AS typname,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
SELECT DISTINCT ON (att.attnum) att.attname as name, att.atttypid, att.attlen, att.attnum, att.attndims,
|
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.attstattarget,
|
att.atttypmod, att.attacl, att.attnotnull, att.attoptions, att.attfdwoptions, att.attstattarget,
|
||||||
att.attstorage, att.attidentity,
|
att.attstorage, att.attidentity,
|
||||||
pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS defval,
|
pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS defval,
|
||||||
pg_catalog.format_type(ty.oid,NULL) AS typname,
|
pg_catalog.format_type(ty.oid,NULL) AS typname,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
SELECT att.attname as name, att.atttypid, att.attlen, att.attnum, att.attndims,
|
SELECT att.attname as name, att.atttypid, att.attlen, att.attnum, att.attndims,
|
||||||
att.atttypmod, att.attacl, att.attnotnull, att.attoptions, att.attstattarget,
|
att.atttypmod, att.attacl, att.attnotnull, att.attoptions, att.attfdwoptions, att.attstattarget,
|
||||||
att.attstorage, att.attidentity,
|
att.attstorage, att.attidentity,
|
||||||
pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS defval,
|
pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS defval,
|
||||||
pg_catalog.format_type(ty.oid,NULL) AS typname,
|
pg_catalog.format_type(ty.oid,NULL) AS typname,
|
||||||
|
@ -228,20 +228,6 @@ describe('ForeignTableColumnSchema', ()=>{
|
|||||||
mount(getEditView(schemaObj, getInitData));
|
mount(getEditView(schemaObj, getInitData));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('column editable', ()=>{
|
|
||||||
let state = {};
|
|
||||||
let editable = _.find(schemaObj.fields, (f)=>f.id=='attname').editable;
|
|
||||||
let status = editable(state);
|
|
||||||
expect(status).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('typdefault editable', ()=>{
|
|
||||||
let state = {};
|
|
||||||
let editable = _.find(schemaObj.fields, (f)=>f.id=='typdefault').editable;
|
|
||||||
let status = editable(state);
|
|
||||||
expect(status).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('typdefault_edit', ()=>{
|
it('typdefault_edit', ()=>{
|
||||||
let defaultSchemaObj = new ForeignTableSchema(
|
let defaultSchemaObj = new ForeignTableSchema(
|
||||||
()=>new MockSchema(),
|
()=>new MockSchema(),
|
||||||
|
@ -710,6 +710,8 @@ class ReverseEngineeredSQLTestCases(BaseTestGenerator):
|
|||||||
self.parent_ids['fsid'] = object_id
|
self.parent_ids['fsid'] = object_id
|
||||||
elif endpoint.__contains__("NODE-role.obj"):
|
elif endpoint.__contains__("NODE-role.obj"):
|
||||||
object_name = object_data['rolname']
|
object_name = object_data['rolname']
|
||||||
|
elif endpoint.__contains__("NODE-foreign_table"):
|
||||||
|
self.parent_ids['tid'] = object_id
|
||||||
|
|
||||||
# Store object id with object name
|
# Store object id with object name
|
||||||
self.all_object_ids[object_name] = object_id
|
self.all_object_ids[object_name] = object_id
|
||||||
|
@ -480,6 +480,7 @@ module.exports = [{
|
|||||||
'pure|pgadmin.node.user_mapping',
|
'pure|pgadmin.node.user_mapping',
|
||||||
'pure|pgadmin.node.schema',
|
'pure|pgadmin.node.schema',
|
||||||
'pure|pgadmin.node.catalog',
|
'pure|pgadmin.node.catalog',
|
||||||
|
'pure|pgadmin.node.foreign_table_column',
|
||||||
'pure|pgadmin.node.catalog_object',
|
'pure|pgadmin.node.catalog_object',
|
||||||
'pure|pgadmin.node.collation',
|
'pure|pgadmin.node.collation',
|
||||||
'pure|pgadmin.node.domain',
|
'pure|pgadmin.node.domain',
|
||||||
|
@ -115,6 +115,7 @@ let webpackShimConfig = {
|
|||||||
'pgadmin.node.foreign_key': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key'),
|
'pgadmin.node.foreign_key': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key'),
|
||||||
'pgadmin.node.foreign_server': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/static/js/foreign_server'),
|
'pgadmin.node.foreign_server': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/static/js/foreign_server'),
|
||||||
'pgadmin.node.foreign_table': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/static/js/foreign_table'),
|
'pgadmin.node.foreign_table': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/static/js/foreign_table'),
|
||||||
|
'pgadmin.node.foreign_table_column': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/foreign_table_columns/static/js/foreign_table_column'),
|
||||||
'pgadmin.node.fts_configuration': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/static/js/fts_configuration'),
|
'pgadmin.node.fts_configuration': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/static/js/fts_configuration'),
|
||||||
'pgadmin.node.fts_dictionary': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/static/js/fts_dictionary'),
|
'pgadmin.node.fts_dictionary': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/static/js/fts_dictionary'),
|
||||||
'pgadmin.node.fts_parser': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/static/js/fts_parser'),
|
'pgadmin.node.fts_parser': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/static/js/fts_parser'),
|
||||||
|
Loading…
Reference in New Issue
Block a user