mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-12-23 07:34:35 -06:00
Added support of Aggregate and Operator node in view-only mode. Fixes #3834
This commit is contained in:
parent
7b85253465
commit
39992a817d
@ -9,7 +9,7 @@ This release contains a number of bug fixes and new features since the release o
|
||||
New features
|
||||
************
|
||||
|
||||
|
||||
| `Issue #3834 <https://redmine.postgresql.org/issues/3834>`_ - Added support of Aggregate and Operator node in view-only mode.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
@ -0,0 +1,374 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
""" Implements Aggregate Node """
|
||||
|
||||
from functools import wraps
|
||||
|
||||
from flask import render_template
|
||||
from flask_babelex import gettext
|
||||
|
||||
import pgadmin.browser.server_groups.servers.databases as database
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
|
||||
import SchemaChildModule
|
||||
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
|
||||
|
||||
|
||||
class AggregateModule(SchemaChildModule):
|
||||
"""
|
||||
class AggregateModule(SchemaChildModule)
|
||||
|
||||
A module class for Aggregate node derived from SchemaChildModule.
|
||||
|
||||
Methods:
|
||||
-------
|
||||
* __init__(*args, **kwargs)
|
||||
- Method is used to initialize the Aggregate and it's base module.
|
||||
|
||||
* get_nodes(gid, sid, did, scid, agid)
|
||||
- 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 = 'aggregate'
|
||||
_COLLECTION_LABEL = gettext("Aggregates")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Method is used to initialize the AggregateModule and it's base module.
|
||||
|
||||
Args:
|
||||
*args:
|
||||
**kwargs:
|
||||
"""
|
||||
|
||||
super(AggregateModule, self).__init__(*args, **kwargs)
|
||||
self.min_ver = 90100
|
||||
self.max_ver = None
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
Generate the collection node
|
||||
"""
|
||||
yield self.generate_browser_collection_node(scid)
|
||||
|
||||
@property
|
||||
def script_load(self):
|
||||
"""
|
||||
Load the module script for database, when any of the database node is
|
||||
initialized.
|
||||
"""
|
||||
return database.DatabaseModule.node_type
|
||||
|
||||
@property
|
||||
def node_inode(self):
|
||||
return False
|
||||
|
||||
|
||||
blueprint = AggregateModule(__name__)
|
||||
|
||||
|
||||
class AggregateView(PGChildNodeView):
|
||||
"""
|
||||
This class is responsible for generating routes for Aggregate node
|
||||
|
||||
Methods:
|
||||
-------
|
||||
* __init__(**kwargs)
|
||||
- Method is used to initialize the AggregateView and it's base view.
|
||||
|
||||
* check_precondition()
|
||||
- This function will behave as a decorator which will checks
|
||||
database connection before running view, it will also attaches
|
||||
manager,conn & template_path properties to self
|
||||
|
||||
* list()
|
||||
- This function is used to list all the Aggregate nodes within that
|
||||
collection.
|
||||
|
||||
* nodes()
|
||||
- This function will used to create all the child node within that
|
||||
collection, Here it will create all the Aggregate node.
|
||||
|
||||
* properties(gid, sid, did, scid, agid)
|
||||
- This function will show the properties of the selected Aggregate node
|
||||
|
||||
|
||||
* sql(gid, sid, did, scid):
|
||||
- This function will generate sql to show it in sql pane for the
|
||||
selected Aggregate node.
|
||||
"""
|
||||
|
||||
node_type = blueprint.node_type
|
||||
node_label = "Aggregate"
|
||||
|
||||
parent_ids = [
|
||||
{'type': 'int', 'id': 'gid'},
|
||||
{'type': 'int', 'id': 'sid'},
|
||||
{'type': 'int', 'id': 'did'},
|
||||
{'type': 'int', 'id': 'scid'}
|
||||
]
|
||||
ids = [
|
||||
{'type': 'int', 'id': 'agid'}
|
||||
]
|
||||
|
||||
operations = dict({
|
||||
'obj': [
|
||||
{'get': 'properties', 'delete': 'delete', 'put': 'update'},
|
||||
{'get': 'list', 'post': 'create', 'delete': 'delete'}
|
||||
],
|
||||
'delete': [{'delete': 'delete'}, {'delete': 'delete'}],
|
||||
'children': [{'get': 'children'}],
|
||||
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
|
||||
'sql': [{'get': 'sql'}]
|
||||
})
|
||||
|
||||
def check_precondition(f):
|
||||
"""
|
||||
This function will behave as a decorator which will checks
|
||||
database connection before running view, it will also attaches
|
||||
manager,conn & template_path properties to self
|
||||
"""
|
||||
|
||||
@wraps(f)
|
||||
def wrap(*args, **kwargs):
|
||||
# Here args[0] will hold self & kwargs will hold gid,sid,did
|
||||
self = args[0]
|
||||
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
|
||||
kwargs['sid']
|
||||
)
|
||||
self.conn = self.manager.connection(did=kwargs['did'])
|
||||
self.datlastsysoid = \
|
||||
self.manager.db_info[kwargs['did']]['datlastsysoid'] \
|
||||
if self.manager.db_info is not None and \
|
||||
kwargs['did'] in self.manager.db_info else 0
|
||||
|
||||
self.datistemplate = False
|
||||
if (
|
||||
self.manager.db_info is not None and
|
||||
kwargs['did'] in self.manager.db_info and
|
||||
'datistemplate' in self.manager.db_info[kwargs['did']]
|
||||
):
|
||||
self.datistemplate = self.manager.db_info[
|
||||
kwargs['did']]['datistemplate']
|
||||
|
||||
# Set the template path for the SQL scripts
|
||||
self.template_path = compile_template_path(
|
||||
'aggregates/sql/',
|
||||
self.manager.server_type,
|
||||
self.manager.version
|
||||
)
|
||||
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return wrap
|
||||
|
||||
@check_precondition
|
||||
def list(self, gid, sid, did, scid):
|
||||
"""
|
||||
This function is used to list all the aggregate nodes within that
|
||||
collection.
|
||||
|
||||
Args:
|
||||
gid: Server group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
|
||||
Returns:
|
||||
JSON of available aggregate nodes
|
||||
"""
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._NODES_SQL]), scid=scid)
|
||||
status, res = self.conn.execute_dict(SQL)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
return ajax_response(
|
||||
response=res['rows'],
|
||||
status=200
|
||||
)
|
||||
|
||||
@check_precondition
|
||||
def nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
This function will used to create all the child node within that
|
||||
collection.
|
||||
Here it will create all the aggregate node.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
|
||||
Returns:
|
||||
JSON of available aggregate child nodes
|
||||
"""
|
||||
|
||||
res = []
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._NODES_SQL]), scid=scid)
|
||||
status, rset = self.conn.execute_2darray(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=rset)
|
||||
|
||||
for row in rset['rows']:
|
||||
res.append(
|
||||
self.blueprint.generate_browser_node(
|
||||
row['oid'],
|
||||
scid,
|
||||
row['name'],
|
||||
icon="icon-aggregate"
|
||||
))
|
||||
|
||||
return make_json_response(
|
||||
data=res,
|
||||
status=200
|
||||
)
|
||||
|
||||
@check_precondition
|
||||
def node(self, gid, sid, did, scid, agid):
|
||||
"""
|
||||
This function will fetch properties of the aggregate node.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
agid: Aggregate ID
|
||||
|
||||
Returns:
|
||||
JSON of given aggregate node
|
||||
"""
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._NODES_SQL]), agid=agid)
|
||||
status, rset = self.conn.execute_2darray(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=rset)
|
||||
|
||||
for row in rset['rows']:
|
||||
return make_json_response(
|
||||
data=self.blueprint.generate_browser_node(
|
||||
row['oid'],
|
||||
scid,
|
||||
row['name'],
|
||||
icon="icon-aggregate"
|
||||
),
|
||||
status=200
|
||||
)
|
||||
|
||||
return gone(self.not_found_error_msg())
|
||||
|
||||
@check_precondition
|
||||
def properties(self, gid, sid, did, scid, agid):
|
||||
"""
|
||||
This function will show the properties of the selected aggregate node.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
scid: Schema ID
|
||||
agid: Aggregate ID
|
||||
|
||||
Returns:
|
||||
JSON of selected aggregate node
|
||||
"""
|
||||
|
||||
status, res = self._fetch_properties(scid, agid)
|
||||
if not status:
|
||||
return res
|
||||
|
||||
return ajax_response(
|
||||
response=res,
|
||||
status=200
|
||||
)
|
||||
|
||||
def _fetch_properties(self, scid, agid):
|
||||
"""
|
||||
This function fetch the properties for the specified object.
|
||||
|
||||
:param scid: Schema ID
|
||||
:param agid: Aggregate ID
|
||||
"""
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._PROPERTIES_SQL]),
|
||||
scid=scid, agid=agid,
|
||||
datlastsysoid=self.datlastsysoid)
|
||||
status, res = self.conn.execute_dict(SQL)
|
||||
|
||||
if not status:
|
||||
return False, internal_server_error(errormsg=res)
|
||||
|
||||
if len(res['rows']) == 0:
|
||||
return False, gone(self.not_found_error_msg())
|
||||
|
||||
res['rows'][0]['is_sys_obj'] = (
|
||||
res['rows'][0]['oid'] <= self.datlastsysoid or self.datistemplate)
|
||||
|
||||
return True, res['rows'][0]
|
||||
|
||||
@check_precondition
|
||||
def sql(self, gid, sid, did, scid, agid, **kwargs):
|
||||
"""
|
||||
This function will generates reverse engineered sql for aggregate
|
||||
object
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
agid: Aggregate ID
|
||||
json_resp: True then return json response
|
||||
"""
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._PROPERTIES_SQL]),
|
||||
scid=scid, agid=agid)
|
||||
status, res = self.conn.execute_dict(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
if len(res['rows']) == 0:
|
||||
return gone(self.not_found_error_msg())
|
||||
|
||||
data = res['rows'][0]
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._CREATE_SQL]),
|
||||
data=data)
|
||||
|
||||
sql_header = "-- Aggregate: {0};\n\n-- ".format(data['name'])
|
||||
|
||||
sql_header += render_template("/".join([self.template_path,
|
||||
self._DELETE_SQL]),
|
||||
data=data)
|
||||
SQL = sql_header + '\n' + SQL.strip('\n')
|
||||
|
||||
return ajax_response(response=SQL)
|
||||
|
||||
|
||||
AggregateView.register_node_view(blueprint)
|
@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#cadff1;stroke:#6f6f6f;stroke-linecap:round;stroke-miterlimit:10;}.cls-2{fill:#9cbe44;}.cls-3{fill:#888;}</style></defs><rect class="cls-1" x="4.5" y="3.23" width="7" height="9.54" rx="1"/><rect class="cls-2" x="6.02" y="4.84" width="4" height="2"/><rect class="cls-3" x="6.14" y="7.66" width="1.5" height="1.36"/><rect class="cls-3" x="8.52" y="7.66" width="1.5" height="1.36"/><rect class="cls-3" x="6.14" y="10.02" width="1.5" height="1.36"/><rect class="cls-3" x="8.52" y="10.02" width="1.5" height="1.36"/></svg>
|
After Width: | Height: | Size: 635 B |
@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#cadff1;stroke:#6f6f6f;stroke-linecap:round;stroke-miterlimit:10;}.cls-2{fill:#9cbe44;}.cls-3{fill:#888;}</style></defs><rect class="cls-1" x="2.48" y="1.21" width="7" height="9.54" rx="1"/><rect class="cls-2" x="4" y="2.83" width="4" height="2"/><rect class="cls-3" x="4.12" y="5.64" width="1.5" height="1.36"/><rect class="cls-3" x="6.5" y="5.64" width="1.5" height="1.36"/><rect class="cls-3" x="4.12" y="8" width="1.5" height="1.36"/><rect class="cls-3" x="6.5" y="8" width="1.5" height="1.36"/><rect class="cls-1" x="4.5" y="3.23" width="7" height="9.54" rx="1"/><rect class="cls-2" x="6.02" y="4.84" width="4" height="2"/><rect class="cls-3" x="6.14" y="7.66" width="1.5" height="1.36"/><rect class="cls-3" x="8.52" y="7.66" width="1.5" height="1.36"/><rect class="cls-3" x="6.14" y="10.02" width="1.5" height="1.36"/><rect class="cls-3" x="8.52" y="10.02" width="1.5" height="1.36"/><rect class="cls-1" x="6.52" y="5.25" width="7" height="9.54" rx="1"/><rect class="cls-2" x="8.04" y="6.86" width="4" height="2"/><rect class="cls-3" x="8.16" y="9.67" width="1.5" height="1.36"/><rect class="cls-3" x="10.54" y="9.67" width="1.5" height="1.36"/><rect class="cls-3" x="8.16" y="12.03" width="1.5" height="1.36"/><rect class="cls-3" x="10.54" y="12.03" width="1.5" height="1.36"/></svg>
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,86 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import AggregateSchema from './aggregate.ui';
|
||||
|
||||
define('pgadmin.node.aggregate', [
|
||||
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
|
||||
'sources/pgadmin', 'pgadmin.browser',
|
||||
'pgadmin.node.schema.dir/child', 'pgadmin.browser.collection',
|
||||
], function(gettext, url_for, $, _, pgAdmin, pgBrowser, schemaChild) {
|
||||
|
||||
if (!pgBrowser.Nodes['coll-aggregate']) {
|
||||
pgAdmin.Browser.Nodes['coll-aggregate'] =
|
||||
pgAdmin.Browser.Collection.extend({
|
||||
node: 'aggregate',
|
||||
label: gettext('Aggregates'),
|
||||
type: 'coll-aggregate',
|
||||
columns: ['name', 'owner', 'description'],
|
||||
canDrop: false,
|
||||
canDropCascade: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (!pgBrowser.Nodes['aggregate']) {
|
||||
pgAdmin.Browser.Nodes['aggregate'] = schemaChild.SchemaChildNode.extend({
|
||||
type: 'aggregate',
|
||||
sqlAlterHelp: 'sql-alteraggregate.html',
|
||||
sqlCreateHelp: 'sql-createaggregate.html',
|
||||
label: gettext('Aggregate'),
|
||||
collection_type: 'coll-aggregate',
|
||||
hasSQL: true,
|
||||
hasDepends: false,
|
||||
canDrop: false,
|
||||
canDropCascade: false,
|
||||
Init: function() {
|
||||
/* Avoid mulitple registration of menus */
|
||||
if (this.initialized)
|
||||
return;
|
||||
|
||||
this.initialized = true;
|
||||
},
|
||||
model: pgAdmin.Browser.Node.Model.extend({
|
||||
idAttribute: 'oid',
|
||||
|
||||
// Default values!
|
||||
initialize: function(attrs, args) {
|
||||
var isNew = (_.size(attrs) === 0);
|
||||
|
||||
if (isNew) {
|
||||
var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
|
||||
var schemaInfo = args.node_info.schema;
|
||||
|
||||
this.set({'owner': userInfo.name}, {silent: true});
|
||||
this.set({'schema': schemaInfo._label}, {silent: true});
|
||||
}
|
||||
pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
|
||||
},
|
||||
|
||||
schema: [{
|
||||
id: 'name', label: gettext('Aggregate'), cell: 'string',
|
||||
type: 'text', mode: ['properties', 'create', 'edit'],
|
||||
},{
|
||||
id: 'owner', label: gettext('Owner'), cell: 'string',
|
||||
type: 'text', mode: ['properties', 'create', 'edit'],
|
||||
control: 'node-list-by-name',
|
||||
node: 'role',
|
||||
},{
|
||||
id: 'description', label: gettext('Comment'), cell: 'string',
|
||||
type: 'multiline', mode: ['properties', 'create', 'edit'],
|
||||
}
|
||||
],
|
||||
}),
|
||||
getSchema: ()=>{
|
||||
let schema = new AggregateSchema();
|
||||
return schema;
|
||||
}
|
||||
});
|
||||
}
|
||||
return pgBrowser.Nodes['aggregate'];
|
||||
});
|
@ -0,0 +1,185 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
|
||||
import gettext from 'sources/gettext';
|
||||
|
||||
export default class AggregateSchema extends BaseUISchema {
|
||||
constructor(fieldOptions = {},initValues) {
|
||||
super({
|
||||
name: undefined,
|
||||
oid: undefined,
|
||||
owner: undefined,
|
||||
description: undefined,
|
||||
schema: null,
|
||||
input_types: undefined,
|
||||
state_type: undefined,
|
||||
state_func: undefined,
|
||||
state_data_size: 0,
|
||||
final_type: undefined,
|
||||
final_func: undefined,
|
||||
final_func_modify: undefined,
|
||||
final_extra_param: undefined,
|
||||
initial_val: undefined,
|
||||
moving_state_type: undefined,
|
||||
moving_state_func: undefined,
|
||||
moving_state_data_size: 0,
|
||||
moving_final_type: undefined,
|
||||
moving_final_func: undefined,
|
||||
moving_final_func_modify: undefined,
|
||||
moving_final_extra_param: undefined,
|
||||
moving_initial_val: undefined,
|
||||
moving_inverse_func: undefined,
|
||||
combine_func: undefined,
|
||||
serialization_func: undefined,
|
||||
deserialization_func: undefined,
|
||||
sort_oper: undefined,
|
||||
...initValues
|
||||
});
|
||||
this.fieldOptions = fieldOptions;
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'oid';
|
||||
}
|
||||
|
||||
get baseFields() {
|
||||
return [
|
||||
{
|
||||
id: 'name', label: gettext('Name'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'oid', label: gettext('OID'),
|
||||
type: 'text', mode: ['properties'],
|
||||
},
|
||||
{
|
||||
id: 'owner', label: gettext('Owner'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'schema', label: gettext('Schema'),
|
||||
mode: ['create', 'edit'],
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'is_sys_obj', label: gettext('System aggregate?'),
|
||||
cell: 'boolean', type: 'switch', mode: ['properties'],
|
||||
},
|
||||
{
|
||||
id: 'description', label: gettext('Comment'),
|
||||
type: 'multiline', mode: ['properties', 'create', 'edit'],
|
||||
readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'input_types', label: gettext('Input types'),
|
||||
group: gettext('Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'state_type', label: gettext('State type'),
|
||||
group: gettext('Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'state_func', label: gettext('State function'),
|
||||
group: gettext('Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'state_data_size', label: gettext('State data size'),
|
||||
group: gettext('Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'final_type', label: gettext('Final type'),
|
||||
group: gettext('Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'final_func', label: gettext('Final function'),
|
||||
group: gettext('Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'final_func_modify', label: gettext('Final function modify'),
|
||||
group: gettext('Options'), min_version: 110000,
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'final_extra_param', label: gettext('Pass extra arguments to final function'),
|
||||
group: gettext('Options'), type: 'switch', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'initial_val', label: gettext('Initial condition'),
|
||||
group: gettext('Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'moving_state_type', label: gettext('State type'),
|
||||
group: gettext('Moving Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'moving_state_func', label: gettext('State function'),
|
||||
group: gettext('Moving Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'moving_state_data_size', label: gettext('State data size'),
|
||||
group: gettext('Moving Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'moving_final_func', label: gettext('Final function'),
|
||||
group: gettext('Moving Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'moving_final_func_modify', label: gettext('Final function modify'),
|
||||
group: gettext('Moving Options'), min_version: 110000,
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'moving_final_extra_param', label: gettext('Pass extra arguments to final function'),
|
||||
group: gettext('Moving Options'), type: 'switch', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'moving_inverse_func', label: gettext('Inverse function'),
|
||||
group: gettext('Moving Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'moving_initial_val', label: gettext('Initial condition'),
|
||||
group: gettext('Moving Options'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'sort_oper', label: gettext('Sort operator'),
|
||||
group: gettext('Advanced'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'combine_func', label: gettext('Combine function'),
|
||||
group: gettext('Advanced'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'serialization_func', label: gettext('Serialization function'),
|
||||
group: gettext('Advanced'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'deserialization_func', label: gettext('Deserialization function'),
|
||||
group: gettext('Advanced'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
{% if data %}
|
||||
CREATE AGGREGATE {{conn|qtIdent(data.schema, data.name)}}({% if data.input_types %}{{data.input_types}}{% endif %}) (
|
||||
SFUNC = {{data.state_func}},
|
||||
STYPE = {{data.state_type}} {% if data.state_data_size %},
|
||||
SSPACE = {{data.state_data_size}}{% endif %}{% if data.final_func %},
|
||||
FINALFUNC = {{data.final_func}}{% endif %}{% if data.final_extra_param %},
|
||||
FINALFUNC_EXTRA{% endif %}{% if data.final_func_modify %},
|
||||
FINALFUNC_MODIFY = {{data.final_func_modify}}{% endif %}{% if data.combine_func %},
|
||||
COMBINEFUNC = {{data.combine_func}}{% endif %}{% if data.serialization_func %},
|
||||
SERIALFUNC = {{data.serialization_func}}{% endif %}{% if data.deserialization_func %},
|
||||
DESERIALFUNC = {{data.deserialization_func}}{% endif %}{% if data.initial_val %},
|
||||
INITCOND = '{{data.initial_val}}'::text{% endif %}{% if data.moving_state_func %},
|
||||
MSFUNC = {{data.moving_state_func}}{% endif %}{% if data.moving_inverse_func %},
|
||||
MINVFUNC = {{data.moving_inverse_func}}{% endif %}{% if data.moving_state_type %},
|
||||
MSTYPE = {{data.moving_state_type}}{% endif %}{% if data.moving_state_data_size %},
|
||||
MSSPACE = {{data.moving_state_data_size}}{% endif %}{% if data.moving_final_func %},
|
||||
MFINALFUNC = {{data.moving_final_func}}{% endif %}{% if data.moving_final_extra_param %},
|
||||
MFINALFUNC_EXTRA{% endif %}{% if data.moving_final_func_modify %},
|
||||
MFINALFUNC_MODIFY = {{data.moving_final_func_modify}}{% endif %}{% if data.moving_initial_val %},
|
||||
MINITCOND = '{{data.moving_initial_val}}'::text{% endif %}{% if data.sort_oper %},
|
||||
SORTOP = {{data.sort_oper}}{% endif %}
|
||||
|
||||
);
|
||||
{% endif %}
|
@ -0,0 +1,47 @@
|
||||
SELECT aggfnoid::oid as oid, proname as name, ns.nspname as schema,
|
||||
pg_catalog.pg_get_userbyid(proowner) as owner,
|
||||
COALESCE(pg_catalog.pg_get_function_arguments(aggfnoid::oid), '') as input_types, proacl,
|
||||
CASE WHEN ag.aggkind = 'n' THEN 'normal'
|
||||
WHEN ag.aggkind = 'o' THEN 'ordered-set'
|
||||
WHEN ag.aggkind = 'h' THEN 'hypothetical-set'
|
||||
ELSE 'unknown' END as kind,
|
||||
CASE WHEN aggtransfn = '-'::regproc THEN null ELSE aggtransfn END as state_func,
|
||||
CASE WHEN aggfinalfn = '-'::regproc THEN null ELSE aggfinalfn END as final_func,
|
||||
CASE WHEN aggcombinefn = '-'::regproc THEN null ELSE aggcombinefn END as combine_func,
|
||||
CASE WHEN aggserialfn = '-'::regproc THEN null ELSE aggserialfn END as serialization_func,
|
||||
CASE WHEN aggdeserialfn = '-'::regproc THEN null ELSE aggdeserialfn END as deserialization_func,
|
||||
CASE WHEN aggmtransfn = '-'::regproc THEN null ELSE aggmtransfn END as moving_state_func,
|
||||
CASE WHEN aggmfinalfn = '-'::regproc THEN null ELSE aggmfinalfn END as moving_final_func,
|
||||
CASE WHEN aggminvtransfn = '-'::regproc THEN null ELSE aggminvtransfn END as moving_inverse_func,
|
||||
CASE WHEN ag.aggfinalmodify = 'r' THEN 'READ_ONLY'
|
||||
WHEN ag.aggfinalmodify = 's' THEN 'SHAREABLE'
|
||||
WHEN ag.aggfinalmodify = 'w' THEN 'READ_WRITE'
|
||||
ELSE 'unknown' END as final_func_modify,
|
||||
CASE WHEN ag.aggmfinalmodify = 'r' THEN 'READ_ONLY'
|
||||
WHEN ag.aggmfinalmodify = 's' THEN 'SHAREABLE'
|
||||
WHEN ag.aggmfinalmodify = 'w' THEN 'READ_WRITE'
|
||||
ELSE 'unknown' END as moving_final_func_modify,
|
||||
agginitval as initial_val, aggminitval as moving_initial_val,
|
||||
op.oprname as sort_oper, aggfinalextra as final_extra_param, aggmfinalextra as moving_final_extra_param,
|
||||
aggtransspace as state_data_size, aggmtransspace as moving_state_data_size,
|
||||
CASE WHEN (tt.typlen = -1 AND tt.typelem != 0) THEN
|
||||
(SELECT at.typname FROM pg_type at WHERE at.oid = tt.typelem) || '[]'
|
||||
ELSE tt.typname END as state_type,
|
||||
CASE WHEN (tf.typlen = -1 AND tf.typelem != 0) THEN
|
||||
(SELECT at.typname FROM pg_catalog.pg_type at WHERE at.oid = tf.typelem) || '[]'
|
||||
ELSE tf.typname END as final_type,
|
||||
CASE WHEN (tm.typlen = -1 AND tm.typelem != 0) THEN
|
||||
(SELECT at.typname FROM pg_type at WHERE at.oid = tm.typelem) || '[]'
|
||||
ELSE tm.typname END as moving_state_type,
|
||||
description
|
||||
FROM pg_catalog.pg_aggregate ag
|
||||
LEFT OUTER JOIN pg_catalog.pg_proc pr ON pr.oid = ag.aggfnoid
|
||||
LEFT OUTER JOIN pg_catalog.pg_namespace ns ON ns.oid=pr.pronamespace
|
||||
LEFT OUTER JOIN pg_catalog.pg_type tt on tt.oid=aggtranstype
|
||||
LEFT OUTER JOIN pg_catalog.pg_type tf on tf.oid=prorettype
|
||||
LEFT OUTER JOIN pg_catalog.pg_type tm on tm.oid=aggmtranstype
|
||||
LEFT OUTER JOIN pg_catalog.pg_operator op on op.oid = ag.aggsortop
|
||||
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=aggfnoid::oid AND des.classoid='pg_aggregate'::regclass)
|
||||
WHERE pronamespace = {{scid}}::oid
|
||||
{% if agid %} AND ag.aggfnoid = {{agid}}::oid {% endif %}
|
||||
ORDER BY name;
|
@ -0,0 +1,24 @@
|
||||
{% if data %}
|
||||
CREATE OR REPLACE AGGREGATE {{conn|qtIdent(data.schema, data.name)}}({% if data.input_types %}{{data.input_types}}{% endif %}) (
|
||||
SFUNC = {{data.state_func}},
|
||||
STYPE = {{data.state_type}} {% if data.state_data_size %},
|
||||
SSPACE = {{data.state_data_size}}{% endif %}{% if data.final_func %},
|
||||
FINALFUNC = {{data.final_func}}{% endif %}{% if data.final_extra_param %},
|
||||
FINALFUNC_EXTRA{% endif %}{% if data.final_func_modify %},
|
||||
FINALFUNC_MODIFY = {{data.final_func_modify}}{% endif %}{% if data.combine_func %},
|
||||
COMBINEFUNC = {{data.combine_func}}{% endif %}{% if data.serialization_func %},
|
||||
SERIALFUNC = {{data.serialization_func}}{% endif %}{% if data.deserialization_func %},
|
||||
DESERIALFUNC = {{data.deserialization_func}}{% endif %}{% if data.initial_val %},
|
||||
INITCOND = '{{data.initial_val}}'::text{% endif %}{% if data.moving_state_func %},
|
||||
MSFUNC = {{data.moving_state_func}}{% endif %}{% if data.moving_inverse_func %},
|
||||
MINVFUNC = {{data.moving_inverse_func}}{% endif %}{% if data.moving_state_type %},
|
||||
MSTYPE = {{data.moving_state_type}}{% endif %}{% if data.moving_state_data_size %},
|
||||
MSSPACE = {{data.moving_state_data_size}}{% endif %}{% if data.moving_final_func %},
|
||||
MFINALFUNC = {{data.moving_final_func}}{% endif %}{% if data.moving_final_extra_param %},
|
||||
MFINALFUNC_EXTRA{% endif %}{% if data.moving_final_func_modify %},
|
||||
MFINALFUNC_MODIFY = {{data.moving_final_func_modify}}{% endif %}{% if data.moving_initial_val %},
|
||||
MINITCOND = '{{data.moving_initial_val}}'::text{% endif %}{% if data.sort_oper %},
|
||||
SORTOP = {{data.sort_oper}}{% endif %}
|
||||
|
||||
);
|
||||
{% endif %}
|
@ -0,0 +1,22 @@
|
||||
{% if data %}
|
||||
CREATE AGGREGATE {{conn|qtIdent(data.schema, data.name)}}({% if data.input_types %}{{data.input_types}}{% endif %}) (
|
||||
SFUNC = {{data.state_func}},
|
||||
STYPE = {{data.state_type}} {% if data.state_data_size %},
|
||||
SSPACE = {{data.state_data_size}}{% endif %}{% if data.final_func %},
|
||||
FINALFUNC = {{data.final_func}}{% endif %}{% if data.final_extra_param %},
|
||||
FINALFUNC_EXTRA{% endif %}{% if data.combine_func %},
|
||||
COMBINEFUNC = {{data.combine_func}}{% endif %}{% if data.serialization_func %},
|
||||
SERIALFUNC = {{data.serialization_func}}{% endif %}{% if data.deserialization_func %},
|
||||
DESERIALFUNC = {{data.deserialization_func}}{% endif %}{% if data.initial_val %},
|
||||
INITCOND = '{{data.initial_val}}'::text{% endif %}{% if data.moving_state_func %},
|
||||
MSFUNC = {{data.moving_state_func}}{% endif %}{% if data.moving_inverse_func %},
|
||||
MINVFUNC = {{data.moving_inverse_func}}{% endif %}{% if data.moving_state_type %},
|
||||
MSTYPE = {{data.moving_state_type}}{% endif %}{% if data.moving_state_data_size %},
|
||||
MSSPACE = {{data.moving_state_data_size}}{% endif %}{% if data.moving_final_func %},
|
||||
MFINALFUNC = {{data.moving_final_func}}{% endif %}{% if data.moving_final_extra_param %},
|
||||
MFINALFUNC_EXTRA{% endif %}{% if data.moving_initial_val %},
|
||||
MINITCOND = '{{data.moving_initial_val}}'::text{% endif %}{% if data.sort_oper %},
|
||||
SORTOP = {{data.sort_oper}}{% endif %}
|
||||
|
||||
);
|
||||
{% endif %}
|
@ -0,0 +1,3 @@
|
||||
{% if data %}
|
||||
DROP AGGREGATE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}({% if data.input_types %}{{data.input_types}}{% endif %}){% if cascade %} CASCADE{% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,14 @@
|
||||
SELECT aggfnoid::oid as oid,
|
||||
proname || '(' || COALESCE(pg_catalog.pg_get_function_arguments(aggfnoid::oid), '') || ')' AS name,
|
||||
pg_catalog.pg_get_userbyid(proowner) AS owner
|
||||
FROM pg_aggregate ag
|
||||
LEFT OUTER JOIN pg_catalog.pg_proc pr ON pr.oid = ag.aggfnoid
|
||||
LEFT OUTER JOIN pg_catalog.pg_type tt on tt.oid=aggtranstype
|
||||
LEFT OUTER JOIN pg_catalog.pg_type tf on tf.oid=prorettype
|
||||
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=aggfnoid::oid AND des.classoid='pg_aggregate'::regclass)
|
||||
{% if scid %}
|
||||
WHERE pronamespace = {{scid}}::oid
|
||||
{% elif agid %}
|
||||
WHERE ag.aggfnoid = {{agid}}::oid
|
||||
{% endif %}
|
||||
ORDER BY name;
|
@ -0,0 +1,39 @@
|
||||
SELECT aggfnoid::oid as oid, proname as name, ns.nspname as schema,
|
||||
pg_catalog.pg_get_userbyid(proowner) as owner,
|
||||
COALESCE(pg_catalog.pg_get_function_arguments(aggfnoid::oid), '') as input_types, proacl,
|
||||
CASE WHEN ag.aggkind = 'n' THEN 'normal'
|
||||
WHEN ag.aggkind = 'o' THEN 'ordered-set'
|
||||
WHEN ag.aggkind = 'h' THEN 'hypothetical-set'
|
||||
ELSE 'unknown' END as kind,
|
||||
CASE WHEN aggtransfn = '-'::regproc THEN null ELSE aggtransfn END as state_func,
|
||||
CASE WHEN aggfinalfn = '-'::regproc THEN null ELSE aggfinalfn END as final_func,
|
||||
CASE WHEN aggcombinefn = '-'::regproc THEN null ELSE aggcombinefn END as combine_func,
|
||||
CASE WHEN aggserialfn = '-'::regproc THEN null ELSE aggserialfn END as serialization_func,
|
||||
CASE WHEN aggdeserialfn = '-'::regproc THEN null ELSE aggdeserialfn END as deserialization_func,
|
||||
CASE WHEN aggmtransfn = '-'::regproc THEN null ELSE aggmtransfn END as moving_state_func,
|
||||
CASE WHEN aggmfinalfn = '-'::regproc THEN null ELSE aggmfinalfn END as moving_final_func,
|
||||
CASE WHEN aggminvtransfn = '-'::regproc THEN null ELSE aggminvtransfn END as moving_inverse_func,
|
||||
agginitval as initial_val, aggminitval as moving_initial_val,
|
||||
op.oprname as sort_oper, aggfinalextra as final_extra_param, aggmfinalextra as moving_final_extra_param,
|
||||
aggtransspace as state_data_size, aggmtransspace as moving_state_data_size,
|
||||
CASE WHEN (tt.typlen = -1 AND tt.typelem != 0) THEN
|
||||
(SELECT at.typname FROM pg_type at WHERE at.oid = tt.typelem) || '[]'
|
||||
ELSE tt.typname END as state_type,
|
||||
CASE WHEN (tf.typlen = -1 AND tf.typelem != 0) THEN
|
||||
(SELECT at.typname FROM pg_catalog.pg_type at WHERE at.oid = tf.typelem) || '[]'
|
||||
ELSE tf.typname END as final_type,
|
||||
CASE WHEN (tm.typlen = -1 AND tm.typelem != 0) THEN
|
||||
(SELECT at.typname FROM pg_type at WHERE at.oid = tm.typelem) || '[]'
|
||||
ELSE tm.typname END as moving_state_type,
|
||||
description
|
||||
FROM pg_catalog.pg_aggregate ag
|
||||
LEFT OUTER JOIN pg_catalog.pg_proc pr ON pr.oid = ag.aggfnoid
|
||||
LEFT OUTER JOIN pg_catalog.pg_namespace ns ON ns.oid=pr.pronamespace
|
||||
LEFT OUTER JOIN pg_catalog.pg_type tt on tt.oid=aggtranstype
|
||||
LEFT OUTER JOIN pg_catalog.pg_type tf on tf.oid=prorettype
|
||||
LEFT OUTER JOIN pg_catalog.pg_type tm on tm.oid=aggmtranstype
|
||||
LEFT OUTER JOIN pg_catalog.pg_operator op on op.oid = ag.aggsortop
|
||||
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=aggfnoid::oid AND des.classoid='pg_aggregate'::regclass)
|
||||
WHERE pronamespace = {{scid}}::oid
|
||||
{% if agid %} AND ag.aggfnoid = {{agid}}::oid {% endif %}
|
||||
ORDER BY name;
|
@ -0,0 +1,377 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
""" Implements Operator Node """
|
||||
|
||||
from functools import wraps
|
||||
|
||||
from flask import render_template
|
||||
from flask_babelex import gettext
|
||||
|
||||
import pgadmin.browser.server_groups.servers.databases as database
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
|
||||
import SchemaChildModule
|
||||
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
|
||||
|
||||
|
||||
class OperatorModule(SchemaChildModule):
|
||||
"""
|
||||
class OperatorModule(SchemaChildModule)
|
||||
|
||||
A module class for Operator node derived from SchemaChildModule.
|
||||
|
||||
Methods:
|
||||
-------
|
||||
* __init__(*args, **kwargs)
|
||||
- Method is used to initialize the Operator and it's base module.
|
||||
|
||||
* get_nodes(gid, sid, did, scid, opid)
|
||||
- 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 = 'operator'
|
||||
_COLLECTION_LABEL = gettext("Operators")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Method is used to initialize the OperatorModule and it's base module.
|
||||
|
||||
Args:
|
||||
*args:
|
||||
**kwargs:
|
||||
"""
|
||||
|
||||
super(OperatorModule, self).__init__(*args, **kwargs)
|
||||
self.min_ver = 90100
|
||||
self.max_ver = None
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
Generate the collection node
|
||||
"""
|
||||
yield self.generate_browser_collection_node(scid)
|
||||
|
||||
@property
|
||||
def script_load(self):
|
||||
"""
|
||||
Load the module script for database, when any of the database node is
|
||||
initialized.
|
||||
"""
|
||||
return database.DatabaseModule.node_type
|
||||
|
||||
@property
|
||||
def node_inode(self):
|
||||
return False
|
||||
|
||||
|
||||
blueprint = OperatorModule(__name__)
|
||||
|
||||
|
||||
class OperatorView(PGChildNodeView):
|
||||
"""
|
||||
This class is responsible for generating routes for Operator node
|
||||
|
||||
Methods:
|
||||
-------
|
||||
* __init__(**kwargs)
|
||||
- Method is used to initialize the OperatorView and it's base view.
|
||||
|
||||
* check_precondition()
|
||||
- This function will behave as a decorator which will checks
|
||||
database connection before running view, it will also attaches
|
||||
manager,conn & template_path properties to self
|
||||
|
||||
* list()
|
||||
- This function is used to list all the Operator nodes within that
|
||||
collection.
|
||||
|
||||
* nodes()
|
||||
- This function will used to create all the child node within that
|
||||
collection, Here it will create all the Operator node.
|
||||
|
||||
* properties(gid, sid, did, scid, opid)
|
||||
- This function will show the properties of the selected Operator node
|
||||
|
||||
* sql(gid, sid, did, scid):
|
||||
- This function will generate sql to show it in sql pane for the
|
||||
selected Operator node.
|
||||
"""
|
||||
|
||||
node_type = blueprint.node_type
|
||||
node_label = "Operator"
|
||||
|
||||
parent_ids = [
|
||||
{'type': 'int', 'id': 'gid'},
|
||||
{'type': 'int', 'id': 'sid'},
|
||||
{'type': 'int', 'id': 'did'},
|
||||
{'type': 'int', 'id': 'scid'}
|
||||
]
|
||||
ids = [
|
||||
{'type': 'int', 'id': 'opid'}
|
||||
]
|
||||
|
||||
operations = dict({
|
||||
'obj': [
|
||||
{'get': 'properties', 'delete': 'delete', 'put': 'update'},
|
||||
{'get': 'list', 'post': 'create', 'delete': 'delete'}
|
||||
],
|
||||
'delete': [{'delete': 'delete'}, {'delete': 'delete'}],
|
||||
'children': [{'get': 'children'}],
|
||||
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
|
||||
'sql': [{'get': 'sql'}]
|
||||
})
|
||||
|
||||
def check_precondition(f):
|
||||
"""
|
||||
This function will behave as a decorator which will checks
|
||||
database connection before running view, it will also attaches
|
||||
manager,conn & template_path properties to self
|
||||
"""
|
||||
|
||||
@wraps(f)
|
||||
def wrap(*args, **kwargs):
|
||||
# Here args[0] will hold self & kwargs will hold gid,sid,did
|
||||
self = args[0]
|
||||
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
|
||||
kwargs['sid']
|
||||
)
|
||||
self.conn = self.manager.connection(did=kwargs['did'])
|
||||
self.datlastsysoid = \
|
||||
self.manager.db_info[kwargs['did']]['datlastsysoid'] \
|
||||
if self.manager.db_info is not None and \
|
||||
kwargs['did'] in self.manager.db_info else 0
|
||||
|
||||
self.datistemplate = False
|
||||
if (
|
||||
self.manager.db_info is not None and
|
||||
kwargs['did'] in self.manager.db_info and
|
||||
'datistemplate' in self.manager.db_info[kwargs['did']]
|
||||
):
|
||||
self.datistemplate = self.manager.db_info[
|
||||
kwargs['did']]['datistemplate']
|
||||
|
||||
# Set the template path for the SQL scripts
|
||||
self.template_path = compile_template_path(
|
||||
'operators/sql/',
|
||||
self.manager.server_type,
|
||||
self.manager.version
|
||||
)
|
||||
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return wrap
|
||||
|
||||
@check_precondition
|
||||
def list(self, gid, sid, did, scid):
|
||||
"""
|
||||
This function is used to list all the operator nodes within that
|
||||
collection.
|
||||
|
||||
Args:
|
||||
gid: Server group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
|
||||
Returns:
|
||||
JSON of available operator nodes
|
||||
"""
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._NODES_SQL]), scid=scid)
|
||||
status, res = self.conn.execute_dict(SQL)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
return ajax_response(
|
||||
response=res['rows'],
|
||||
status=200
|
||||
)
|
||||
|
||||
@check_precondition
|
||||
def nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
This function will used to create all the child node within that
|
||||
collection.
|
||||
Here it will create all the operator node.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
|
||||
Returns:
|
||||
JSON of available operator child nodes
|
||||
"""
|
||||
|
||||
res = []
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._NODES_SQL]), scid=scid)
|
||||
status, rset = self.conn.execute_2darray(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=rset)
|
||||
|
||||
for row in rset['rows']:
|
||||
res.append(
|
||||
self.blueprint.generate_browser_node(
|
||||
row['oid'],
|
||||
scid,
|
||||
row['name'],
|
||||
icon="icon-operator"
|
||||
))
|
||||
|
||||
return make_json_response(
|
||||
data=res,
|
||||
status=200
|
||||
)
|
||||
|
||||
@check_precondition
|
||||
def node(self, gid, sid, did, scid, opid):
|
||||
"""
|
||||
This function will fetch properties of the operator node.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
opid: Operator ID
|
||||
|
||||
Returns:
|
||||
JSON of given operator node
|
||||
"""
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._NODES_SQL]), opid=opid)
|
||||
status, rset = self.conn.execute_2darray(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=rset)
|
||||
|
||||
for row in rset['rows']:
|
||||
return make_json_response(
|
||||
data=self.blueprint.generate_browser_node(
|
||||
row['oid'],
|
||||
scid,
|
||||
row['name'],
|
||||
icon="icon-operator"
|
||||
),
|
||||
status=200
|
||||
)
|
||||
|
||||
return gone(self.not_found_error_msg())
|
||||
|
||||
@check_precondition
|
||||
def properties(self, gid, sid, did, scid, opid):
|
||||
"""
|
||||
This function will show the properties of the selected operator node.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
scid: Schema ID
|
||||
opid: Operator ID
|
||||
|
||||
Returns:
|
||||
JSON of selected operator node
|
||||
"""
|
||||
|
||||
status, res = self._fetch_properties(scid, opid)
|
||||
if not status:
|
||||
return res
|
||||
|
||||
return ajax_response(
|
||||
response=res,
|
||||
status=200
|
||||
)
|
||||
|
||||
def _fetch_properties(self, scid, opid):
|
||||
"""
|
||||
This function fetch the properties for the specified object.
|
||||
|
||||
:param scid: Schema ID
|
||||
:param opid: Operator ID
|
||||
"""
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._PROPERTIES_SQL]),
|
||||
scid=scid, opid=opid,
|
||||
datlastsysoid=self.datlastsysoid)
|
||||
status, res = self.conn.execute_dict(SQL)
|
||||
|
||||
if not status:
|
||||
return False, internal_server_error(errormsg=res)
|
||||
|
||||
if len(res['rows']) == 0:
|
||||
return False, gone(self.not_found_error_msg())
|
||||
|
||||
res['rows'][0]['is_sys_obj'] = (
|
||||
res['rows'][0]['oid'] <= self.datlastsysoid or self.datistemplate)
|
||||
|
||||
return True, res['rows'][0]
|
||||
|
||||
@check_precondition
|
||||
def sql(self, gid, sid, did, scid, opid):
|
||||
"""
|
||||
This function will generates reverse engineered sql for operator
|
||||
object
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
opid: Operator ID
|
||||
json_resp: True then return json response
|
||||
"""
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._PROPERTIES_SQL]),
|
||||
scid=scid, opid=opid)
|
||||
status, res = self.conn.execute_dict(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
if len(res['rows']) == 0:
|
||||
return gone(self.not_found_error_msg())
|
||||
|
||||
data = res['rows'][0]
|
||||
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._CREATE_SQL]),
|
||||
data=data)
|
||||
|
||||
sql_header = "-- Operator: {0};\n\n-- ".format(data['name'])
|
||||
|
||||
sql_header += render_template("/".join([self.template_path,
|
||||
self._DELETE_SQL]),
|
||||
name=data['name'],
|
||||
oprnamespace=data['schema'],
|
||||
lefttype=data['lefttype'],
|
||||
righttype=data['righttype'],
|
||||
)
|
||||
SQL = sql_header + '\n' + SQL.strip('\n')
|
||||
|
||||
return ajax_response(response=SQL)
|
||||
|
||||
|
||||
OperatorView.register_node_view(blueprint)
|
@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#d4e3f3;}.cls-2{fill:#6f6f6f;}</style></defs><polygon class="cls-1" points="2.15 7.15 2.15 4.65 4.65 4.65 4.65 2.15 7.15 2.15 7.15 7.15 2.15 7.15"/><path class="cls-2" d="M6.65,2.65v4h-4V5.15h2.5V2.65h1.5m1-1H4.15v2.5H1.65v3.5h6v-6Z"/><polygon class="cls-1" points="4.15 9.15 4.15 6.65 6.65 6.65 6.65 4.15 9.15 4.15 9.15 9.15 4.15 9.15"/><path class="cls-2" d="M8.65,4.65v4h-4V7.15h2.5V4.65h1.5m1-1H6.15v2.5H3.65v3.5h6v-6Z"/><polygon class="cls-1" points="8.85 13.85 8.85 11.35 6.35 11.35 6.35 8.85 8.85 8.85 8.85 6.35 11.35 6.35 11.35 8.85 13.85 8.85 13.85 11.35 11.35 11.35 11.35 13.85 8.85 13.85"/><path class="cls-2" d="M10.85,6.85v2.5h2.5v1.5h-2.5v2.5H9.35v-2.5H6.85V9.35h2.5V6.85h1.5m1-1H8.35v2.5H5.85v3.5h2.5v2.5h3.5v-2.5h2.5V8.35h-2.5V5.85Z"/></svg>
|
After Width: | Height: | Size: 875 B |
@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#d4e3f3;stroke:#6f6f6f;stroke-miterlimit:10;}</style></defs><polygon class="cls-1" points="13 6.85 9.15 6.85 9.15 3 6.85 3 6.85 6.85 3 6.85 3 9.15 6.85 9.15 6.85 13 9.15 13 9.15 9.15 13 9.15 13 6.85"/></svg>
|
After Width: | Height: | Size: 325 B |
@ -0,0 +1,86 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import OperatorSchema from './operator.ui';
|
||||
|
||||
define('pgadmin.node.operator', [
|
||||
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
|
||||
'sources/pgadmin', 'pgadmin.browser',
|
||||
'pgadmin.node.schema.dir/child', 'pgadmin.browser.collection',
|
||||
], function(gettext, url_for, $, _, pgAdmin, pgBrowser, schemaChild) {
|
||||
|
||||
if (!pgBrowser.Nodes['coll-operator']) {
|
||||
pgAdmin.Browser.Nodes['coll-operator'] =
|
||||
pgAdmin.Browser.Collection.extend({
|
||||
node: 'operator',
|
||||
label: gettext('Operators'),
|
||||
type: 'coll-operator',
|
||||
columns: ['name', 'owner', 'description'],
|
||||
canDrop: false,
|
||||
canDropCascade: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (!pgBrowser.Nodes['operator']) {
|
||||
pgAdmin.Browser.Nodes['operator'] = schemaChild.SchemaChildNode.extend({
|
||||
type: 'operator',
|
||||
sqlAlterHelp: 'sql-alteroperator.html',
|
||||
sqlCreateHelp: 'sql-createoperator.html',
|
||||
label: gettext('Operator'),
|
||||
collection_type: 'coll-operator',
|
||||
hasSQL: true,
|
||||
hasDepends: false,
|
||||
canDrop: false,
|
||||
canDropCascade: false,
|
||||
Init: function() {
|
||||
/* Avoid mulitple registration of menus */
|
||||
if (this.initialized)
|
||||
return;
|
||||
|
||||
this.initialized = true;
|
||||
},
|
||||
model: pgAdmin.Browser.Node.Model.extend({
|
||||
idAttribute: 'oid',
|
||||
|
||||
// Default values!
|
||||
initialize: function(attrs, args) {
|
||||
var isNew = (_.size(attrs) === 0);
|
||||
|
||||
if (isNew) {
|
||||
var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
|
||||
var schemaInfo = args.node_info.schema;
|
||||
|
||||
this.set({'owner': userInfo.name}, {silent: true});
|
||||
this.set({'schema': schemaInfo._label}, {silent: true});
|
||||
}
|
||||
pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
|
||||
},
|
||||
|
||||
schema: [{
|
||||
id: 'name', label: gettext('Operator'), cell: 'string',
|
||||
type: 'text', mode: ['properties', 'create', 'edit'],
|
||||
},{
|
||||
id: 'owner', label: gettext('Owner'), cell: 'string',
|
||||
type: 'text', mode: ['properties', 'create', 'edit'],
|
||||
control: 'node-list-by-name',
|
||||
node: 'role',
|
||||
},{
|
||||
id: 'description', label: gettext('Comment'), cell: 'string',
|
||||
type: 'multiline', mode: ['properties', 'create', 'edit'],
|
||||
}
|
||||
],
|
||||
}),
|
||||
getSchema: ()=>{
|
||||
let schema = new OperatorSchema();
|
||||
return schema;
|
||||
}
|
||||
});
|
||||
}
|
||||
return pgBrowser.Nodes['operator'];
|
||||
});
|
@ -0,0 +1,125 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
|
||||
import gettext from 'sources/gettext';
|
||||
|
||||
export default class OperatorSchema extends BaseUISchema {
|
||||
constructor(fieldOptions = {},initValues) {
|
||||
super({
|
||||
name: undefined,
|
||||
oid: undefined,
|
||||
owner: undefined,
|
||||
description: undefined,
|
||||
schema: null,
|
||||
lefttype: undefined,
|
||||
righttype: undefined,
|
||||
operproc:undefined,
|
||||
joinproc: undefined,
|
||||
restrproc: undefined,
|
||||
commutator: undefined,
|
||||
negator:undefined,
|
||||
support_hash: false,
|
||||
support_merge: false,
|
||||
...initValues
|
||||
});
|
||||
this.fieldOptions = fieldOptions;
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'oid';
|
||||
}
|
||||
|
||||
get baseFields() {
|
||||
return [
|
||||
{
|
||||
id: 'name', label: gettext('Name'), type: 'tel',
|
||||
readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'oid', label: gettext('OID'),
|
||||
type: 'text', mode: ['properties']
|
||||
},
|
||||
{
|
||||
id: 'owner', label: gettext('Owner'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'schema', label: gettext('Schema'),
|
||||
mode: ['create', 'edit'],
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'is_sys_obj', label: gettext('System operator?'),
|
||||
cell: 'boolean', type: 'switch', mode: ['properties'],
|
||||
},
|
||||
{
|
||||
id: 'description', label: gettext('Comment'),
|
||||
type: 'multiline', mode: ['properties', 'create', 'edit'],
|
||||
readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'lefttype', label: gettext('Left type'),
|
||||
group: gettext('Definition'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'righttype', label: gettext('Right type'),
|
||||
group: gettext('Definition'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'resulttype', label: gettext('Result type'),
|
||||
group: gettext('Definition'),
|
||||
type: 'text', mode: ['properties'],
|
||||
},
|
||||
{
|
||||
id: 'oprkind', label: gettext('Kind'),
|
||||
group: gettext('Definition'),
|
||||
type: 'text', mode: ['properties'],
|
||||
},
|
||||
{
|
||||
id: 'operproc', label: gettext('Operator function'),
|
||||
group: gettext('Definition'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'restrproc', label: gettext('Restrict function'),
|
||||
group: gettext('Implementation'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'joinproc', label: gettext('Join function'),
|
||||
group: gettext('Implementation'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'commutator', label: gettext('Commutator'),
|
||||
group: gettext('Implementation'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'negator', label: gettext('Negator'),
|
||||
group: gettext('Implementation'),
|
||||
type: 'text', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'support_hash', label: gettext('Supports hash'),
|
||||
group: gettext('Implementation'),
|
||||
cell: 'boolean', type: 'switch', readonly: true,
|
||||
},
|
||||
{
|
||||
id: 'support_merge', label: gettext('Supports merge'),
|
||||
group: gettext('Implementation'),
|
||||
cell: 'boolean', type: 'switch', readonly: true,
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
{% if data %}
|
||||
CREATE OPERATOR {{data.schema}}.{{data.name}} (
|
||||
FUNCTION = {{data.operproc}}{% if data.lefttype %},
|
||||
LEFTARG = {{data.lefttype}}{% endif %}{% if data.righttype %},
|
||||
RIGHTARG = {{data.righttype}}{% endif %}{% if data.commutator %},
|
||||
COMMUTATOR = {{data.commutator}}{% endif %}{% if data.negator %},
|
||||
NEGATOR = {{data.negator}}{% endif %}{% if data.restrproc %},
|
||||
RESTRICT = {{data.restrproc}}{% endif %}{% if data.joinproc %},
|
||||
JOIN = {{data.joinproc}}{% endif %}{% if data.support_hash %},
|
||||
HASHES{% endif %}{% if data.support_merge %}, MERGES{% endif %}
|
||||
|
||||
);
|
||||
{% endif %}
|
@ -0,0 +1,13 @@
|
||||
{% if data %}
|
||||
CREATE OPERATOR {{data.schema}}.{{data.name}} (
|
||||
PROCEDURE = {{data.operproc}}{% if data.lefttype %},
|
||||
LEFTARG = {{data.lefttype}}{% endif %}{% if data.righttype %},
|
||||
RIGHTARG = {{data.righttype}}{% endif %}{% if data.commutator %},
|
||||
COMMUTATOR = {{data.commutator}}{% endif %}{% if data.negator %},
|
||||
NEGATOR = {{data.negator}}{% endif %}{% if data.restrproc %},
|
||||
RESTRICT = {{data.restrproc}}{% endif %}{% if data.joinproc %},
|
||||
JOIN = {{data.joinproc}}{% endif %}{% if data.support_hash %},
|
||||
HASHES{% endif %}{% if data.support_merge %}, MERGES{% endif %}
|
||||
|
||||
);
|
||||
{% endif %}
|
@ -0,0 +1,13 @@
|
||||
{% if lefttype %}
|
||||
{% set ltype = lefttype %}
|
||||
{% else %}
|
||||
{% set ltype = none %}
|
||||
{% endif %}
|
||||
{% if righttype %}
|
||||
{% set rtype = righttype %}
|
||||
{% else %}
|
||||
{% set rtype = none %}
|
||||
{% endif %}
|
||||
{% if name %}
|
||||
DROP OPERATOR IF EXISTS {{conn|qtIdent(oprnamespace)}}.{{name}} ({{ltype}} , {{rtype}}){% if cascade %} CASCADE{% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,23 @@
|
||||
SELECT op.oid, pg_catalog.pg_get_userbyid(op.oprowner) as owner,
|
||||
CASE WHEN lt.typname IS NOT NULL AND rt.typname IS NOT NULL THEN
|
||||
op.oprname || ' (' || pg_catalog.format_type(lt.oid, NULL) || ', ' || pg_catalog.format_type(rt.oid, NULL) || ')'
|
||||
WHEN lt.typname IS NULL AND rt.typname IS NOT NULL THEN
|
||||
op.oprname || ' (' || pg_catalog.format_type(rt.oid, NULL) || ')'
|
||||
WHEN lt.typname IS NOT NULL AND rt.typname IS NULL THEN
|
||||
op.oprname || ' (' || pg_catalog.format_type(lt.oid, NULL) || ')'
|
||||
ELSE op.oprname || '()'
|
||||
END as name,
|
||||
lt.typname as lefttype, rt.typname as righttype
|
||||
FROM pg_catalog.pg_operator op
|
||||
LEFT OUTER JOIN pg_catalog.pg_type lt ON lt.oid=op.oprleft
|
||||
LEFT OUTER JOIN pg_catalog.pg_type rt ON rt.oid=op.oprright
|
||||
JOIN pg_catalog.pg_type et on et.oid=op.oprresult
|
||||
LEFT OUTER JOIN pg_catalog.pg_operator co ON co.oid=op.oprcom
|
||||
LEFT OUTER JOIN pg_catalog.pg_operator ne ON ne.oid=op.oprnegate
|
||||
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=op.oid AND des.classoid='pg_operator'::regclass)
|
||||
{% if scid %}
|
||||
WHERE op.oprnamespace = {{scid}}::oid
|
||||
{% elif opid %}
|
||||
WHERE op.oid = {{opid}}::oid
|
||||
{% endif %}
|
||||
ORDER BY op.oprname;
|
@ -0,0 +1,25 @@
|
||||
SELECT op.oid, op.oprname as name, ns.nspname as schema,
|
||||
pg_catalog.pg_get_userbyid(op.oprowner) as owner,
|
||||
op.oprcanhash as support_hash, op.oprcanmerge as support_merge,
|
||||
ns.nspname as schema,
|
||||
CASE WHEN op.oprkind = 'b' THEN 'infix'
|
||||
WHEN op.oprkind = 'l' THEN 'prefix'
|
||||
WHEN op.oprkind = 'r' THEN 'postfix'
|
||||
ELSE 'unknown' END as oprkind, et.typname as resulttype,
|
||||
pg_catalog.format_type(lt.oid, NULL) as lefttype,
|
||||
pg_catalog.format_type(rt.oid, NULL) as righttype,
|
||||
co.oprname as commutator, op.oprcode as operproc,
|
||||
ne.oprname as negator, description,
|
||||
CASE WHEN op.oprrest = '-'::regproc THEN null ELSE op.oprrest END as restrproc,
|
||||
CASE WHEN op.oprjoin = '-'::regproc THEN null ELSE op.oprjoin END as joinproc
|
||||
FROM pg_catalog.pg_operator op
|
||||
LEFT OUTER JOIN pg_catalog.pg_namespace ns ON ns.oid=op.oprnamespace
|
||||
LEFT OUTER JOIN pg_catalog.pg_type lt ON lt.oid=op.oprleft
|
||||
LEFT OUTER JOIN pg_catalog.pg_type rt ON rt.oid=op.oprright
|
||||
JOIN pg_catalog.pg_type et on et.oid=op.oprresult
|
||||
LEFT OUTER JOIN pg_catalog.pg_operator co ON co.oid=op.oprcom
|
||||
LEFT OUTER JOIN pg_catalog.pg_operator ne ON ne.oid=op.oprnegate
|
||||
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=op.oid AND des.classoid='pg_operator'::regclass)
|
||||
WHERE op.oprnamespace = {{scid}}::oid
|
||||
{% if opid %} AND op.oid = {{opid}}::oid {% endif %}
|
||||
ORDER BY op.oprname;
|
@ -182,7 +182,8 @@ class DataTypeReader:
|
||||
'label': row['typname'], 'value': row['typname'],
|
||||
'typval': typeval, 'precision': precision,
|
||||
'length': length, 'min_val': min_val, 'max_val': max_val,
|
||||
'is_collatable': row['is_collatable']
|
||||
'is_collatable': row['is_collatable'],
|
||||
'oid': row['oid']
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
|
@ -44,6 +44,8 @@ function MappedFormControlBase({type, value, id, onChange, className, visible, i
|
||||
return <FormInputText name={name} value={value} onChange={onTextChange} className={className} inputRef={inputRef} {...props} type='int'/>;
|
||||
case 'numeric':
|
||||
return <FormInputText name={name} value={value} onChange={onTextChange} className={className} inputRef={inputRef} {...props} type='numeric'/>;
|
||||
case 'tel':
|
||||
return <FormInputText name={name} value={value} onChange={onTextChange} className={className} inputRef={inputRef} {...props} type='tel'/>;
|
||||
case 'text':
|
||||
return <FormInputText name={name} value={value} onChange={onTextChange} className={className} inputRef={inputRef} {...props}/>;
|
||||
case 'multiline':
|
||||
|
@ -320,7 +320,7 @@ export const InputText = forwardRef(({
|
||||
let changeVal = e.target.value;
|
||||
|
||||
/* For type number, we set type as tel with number regex to get validity.*/
|
||||
if(['numeric', 'int'].indexOf(type) > -1) {
|
||||
if(['numeric', 'int', 'tel'].indexOf(type) > -1) {
|
||||
if(!e.target.validity.valid && changeVal !== '' && changeVal !== '-') {
|
||||
return;
|
||||
}
|
||||
@ -347,7 +347,7 @@ export const InputText = forwardRef(({
|
||||
id: cid,
|
||||
maxLength: maxlength,
|
||||
'aria-describedby': helpid,
|
||||
...(type ? {pattern: patterns[type]} : {})
|
||||
...(type ? {pattern: !_.isUndefined(controlProps) && !_.isUndefined(controlProps.pattern) ? controlProps.pattern : patterns[type]} : {})
|
||||
}}
|
||||
readOnly={Boolean(readonly)}
|
||||
disabled={Boolean(disabled)}
|
||||
|
@ -0,0 +1,95 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import jasmineEnzyme from 'jasmine-enzyme';
|
||||
import React from 'react';
|
||||
import '../helper/enzyme.helper';
|
||||
import { createMount } from '@material-ui/core/test-utils';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import {messages} from '../fake_messages';
|
||||
import SchemaView from '../../../pgadmin/static/js/SchemaView';
|
||||
import AggregateSchema from '../../../pgadmin/browser/server_groups/servers/databases/schemas/aggregates/static/js/aggregate.ui';
|
||||
|
||||
|
||||
describe('AggregateSchema', ()=>{
|
||||
let mount;
|
||||
let schemaObj = new AggregateSchema();
|
||||
let getInitData = ()=>Promise.resolve({});
|
||||
|
||||
/* Use createMount so that material ui components gets the required context */
|
||||
/* https://material-ui.com/guides/testing/#api */
|
||||
beforeAll(()=>{
|
||||
mount = createMount();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mount.cleanUp();
|
||||
});
|
||||
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
/* messages used by validators */
|
||||
pgAdmin.Browser = pgAdmin.Browser || {};
|
||||
pgAdmin.Browser.messages = pgAdmin.Browser.messages || messages;
|
||||
pgAdmin.Browser.utils = pgAdmin.Browser.utils || {};
|
||||
});
|
||||
|
||||
it('create', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={schemaObj}
|
||||
viewHelperProps={{
|
||||
mode: 'create',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
disableDialogHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('edit', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={schemaObj}
|
||||
getInitData={getInitData}
|
||||
viewHelperProps={{
|
||||
mode: 'edit',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
disableDialogHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('properties', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='tab'
|
||||
schema={schemaObj}
|
||||
getInitData={getInitData}
|
||||
viewHelperProps={{
|
||||
mode: 'properties',
|
||||
}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
/>);
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,95 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import jasmineEnzyme from 'jasmine-enzyme';
|
||||
import React from 'react';
|
||||
import '../helper/enzyme.helper';
|
||||
import { createMount } from '@material-ui/core/test-utils';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import {messages} from '../fake_messages';
|
||||
import SchemaView from '../../../pgadmin/static/js/SchemaView';
|
||||
import OperatorSchema from '../../../pgadmin/browser/server_groups/servers/databases/schemas/operators/static/js/operator.ui';
|
||||
|
||||
|
||||
describe('OperatorSchema', ()=>{
|
||||
let mount;
|
||||
let schemaObj = new OperatorSchema();
|
||||
let getInitData = ()=>Promise.resolve({});
|
||||
|
||||
/* Use createMount so that material ui components gets the required context */
|
||||
/* https://material-ui.com/guides/testing/#api */
|
||||
beforeAll(()=>{
|
||||
mount = createMount();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mount.cleanUp();
|
||||
});
|
||||
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
/* messages used by validators */
|
||||
pgAdmin.Browser = pgAdmin.Browser || {};
|
||||
pgAdmin.Browser.messages = pgAdmin.Browser.messages || messages;
|
||||
pgAdmin.Browser.utils = pgAdmin.Browser.utils || {};
|
||||
});
|
||||
|
||||
it('create', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={schemaObj}
|
||||
viewHelperProps={{
|
||||
mode: 'create',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
disableDialogHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('edit', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={schemaObj}
|
||||
getInitData={getInitData}
|
||||
viewHelperProps={{
|
||||
mode: 'edit',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
disableDialogHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('properties', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='tab'
|
||||
schema={schemaObj}
|
||||
getInitData={getInitData}
|
||||
viewHelperProps={{
|
||||
mode: 'properties',
|
||||
}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
/>);
|
||||
});
|
||||
});
|
||||
|
@ -506,6 +506,8 @@ module.exports = [{
|
||||
'pure|pgadmin.node.table',
|
||||
'pure|pgadmin.node.partition',
|
||||
'pure|pgadmin.node.compound_trigger',
|
||||
'pure|pgadmin.node.aggregate',
|
||||
'pure|pgadmin.node.operator',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
@ -226,6 +226,7 @@ var webpackShimConfig = {
|
||||
'pgadmin.node.publication': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/publications/static/js/publication'),
|
||||
'pgadmin.node.subscription': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription'),
|
||||
'pgadmin.node.catalog': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/static/js/catalog'),
|
||||
'pgadmin.node.aggregate': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/aggregates/static/js/aggregate'),
|
||||
'pgadmin.node.catalog_object': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/static/js/catalog_object'),
|
||||
'pgadmin.node.catalog_object_column': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/static/js/catalog_object_column'),
|
||||
'pgadmin.node.check_constraint': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/static/js/check_constraint'),
|
||||
@ -255,6 +256,7 @@ var webpackShimConfig = {
|
||||
'pgadmin.node.index': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index'),
|
||||
'pgadmin.node.language': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/languages/static/js/language'),
|
||||
'pgadmin.node.mview': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview'),
|
||||
'pgadmin.node.operator': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/operators/static/js/operator'),
|
||||
'pgadmin.node.package': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package'),
|
||||
'pgadmin.node.partition': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition'),
|
||||
'pgadmin.node.pga_job': path.join(__dirname, './pgadmin/browser/server_groups/servers/pgagent/static/js/pga_job'),
|
||||
|
Loading…
Reference in New Issue
Block a user