Skip to content

Commit

Permalink
Implement column module and its features for foreign table.#640, #6373,
Browse files Browse the repository at this point in the history
  • Loading branch information
yogeshmahajan-1903 committed Sep 12, 2023
1 parent 3240392 commit d4cdaa5
Show file tree
Hide file tree
Showing 56 changed files with 2,023 additions and 154 deletions.
Binary file modified docs/en_US/images/foreign_table_columns.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, gone
from pgadmin.utils.compile_template_name import compile_template_path
from pgadmin.utils.driver import get_driver
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
columns import utils as column_utils


class ForeignTableModule(SchemaChildModule):
Expand Down Expand Up @@ -88,6 +89,10 @@ def register(self, app, options):
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
constraints import blueprint as 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)


Expand Down Expand Up @@ -216,6 +221,7 @@ class ForeignTableView(PGChildNodeView)
'get_foreign_servers': [{'get': 'get_foreign_servers'},
{'get': 'get_foreign_servers'}],
'get_tables': [{'get': 'get_tables'}, {'get': 'get_tables'}],
'set_trigger': [{'put': 'enable_disable_triggers'}],
'get_columns': [{'get': 'get_columns'}, {'get': 'get_columns'}],
'select_sql': [{'get': 'select_sql'}],
'insert_sql': [{'get': 'insert_sql'}],
Expand Down Expand Up @@ -451,7 +457,9 @@ def nodes(self, gid, sid, did, scid):
scid,
row['name'],
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(
Expand Down Expand Up @@ -1160,15 +1168,14 @@ def _format_columns(self, columns):
"""
cols = []
for c in columns:
if len(c) > 0:
if '[]' in c['datatype']:
c['datatype'] = c['datatype'].replace('[]', '')
if len(c) > 0 and 'cltype' in c:
if '[]' in c['cltype']:
c['cltype'] = c['cltype'].replace('[]', '')
c['isArrayType'] = True
else:
c['isArrayType'] = False
cols.append(c)

return cols
return cols if cols else columns

def _fetch_properties(self, gid, sid, did, scid, foid, inherits=False, ):
"""
Expand Down Expand Up @@ -1238,18 +1245,44 @@ def _fetch_properties(self, gid, sid, did, scid, foid, inherits=False, ):
if not status:
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:
data['columns'] = cols['rows']

# Get Inherited table names from their OID
is_error, errmsg = self._get_inherited_table_name(data, inherits)

if is_error:
return False, internal_server_error(errormsg=errmsg)

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):
"""
The Length and the precision of the Datatype should be separated.
Expand All @@ -1262,11 +1295,11 @@ def _get_datatype_precision(self, cols):
substr = self.extract_type_length_precision(c)
typlen = substr.split(",")
if len(typlen) > 1:
c['typlen'] = self.convert_typlen_to_int(typlen)
c['precision'] = self.convert_precision_to_int(typlen)
c['attlen'] = self.convert_typlen_to_int(typlen)
c['attprecision'] = self.convert_precision_to_int(typlen)
else:
c['typlen'] = self.convert_typlen_to_int(typlen)
c['precision'] = None
c['attlen'] = self.convert_typlen_to_int(typlen)
c['attprecision'] = None

# Get formatted Column Options
if 'attfdwoptions' in c and c['attfdwoptions'] != '':
Expand Down Expand Up @@ -1393,7 +1426,7 @@ def select_sql(self, gid, sid, did, scid, foid):

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:
columns = ", ".join(columns)
Expand Down Expand Up @@ -1434,7 +1467,7 @@ def insert_sql(self, gid, sid, did, scid, foid):
# Now we have all list of columns which we need
if 'columns' in data:
for c in data['columns']:
columns.append(self.qtIdent(self.conn, c['attname']))
columns.append(self.qtIdent(self.conn, c['name']))
values.append('?')

if len(columns) > 0:
Expand Down Expand Up @@ -1475,7 +1508,7 @@ def update_sql(self, gid, sid, did, scid, foid):
# Now we have all list of columns which we need
if 'columns' in data:
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) == 1:
Expand Down Expand Up @@ -1676,6 +1709,66 @@ def modify_data_for_schema_diff(self, data, old_data):

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)
ForeignTableView.register_node_view(blueprint)
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
Do not remove these imports as they will be automatically imported by the view
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 \
import blueprint as triggers_modules
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
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
Original file line number Diff line number Diff line change
@@ -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)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit d4cdaa5

Please sign in to comment.