mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Added search object functionality. Fixes #2172
This commit is contained in:
committed by
Akshay Joshi
parent
f77aa3284f
commit
e1f990190e
@@ -64,6 +64,8 @@ display. To open the *Preferences* dialog, select *Preferences* from the *File*
|
||||
for the dialog. You can access additional Postgres help by navigating through
|
||||
the *Help* menu, and selecting the name of the resource that you wish to open.
|
||||
|
||||
You can search for objects in the database using the :ref:`Search objects <search_objects>`
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
@@ -74,6 +76,7 @@ the *Help* menu, and selecting the name of the resource that you wish to open.
|
||||
tree_control
|
||||
preferences
|
||||
keyboard_shortcuts
|
||||
search_objects
|
||||
|
||||
Before using pgAdmin to manage objects that reside on a server, you must define a
|
||||
connection to the server; for more information please see *Connecting to a Server*
|
||||
|
BIN
docs/en_US/images/search_objects.png
Normal file
BIN
docs/en_US/images/search_objects.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 184 KiB |
Binary file not shown.
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 42 KiB |
@@ -9,6 +9,7 @@ This release contains a number of bug fixes and new features since the release o
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #2172 <https://redmine.postgresql.org/issues/2172>`_ - Added search object functionality.
|
||||
| `Issue #2186 <https://redmine.postgresql.org/issues/2186>`_ - Added LDAP authentication support.
|
||||
| `Issue #5184 <https://redmine.postgresql.org/issues/5184>`_ - Added support for parameter toast_tuple_target and parallel_workers of the table.
|
||||
| `Issue #5264 <https://redmine.postgresql.org/issues/5264>`_ - Added support of Packages, Sequences and Synonyms to the Schema Diff.
|
||||
|
34
docs/en_US/search_objects.rst
Normal file
34
docs/en_US/search_objects.rst
Normal file
@@ -0,0 +1,34 @@
|
||||
.. _search_objects:
|
||||
|
||||
***********************
|
||||
`Search objects`:index:
|
||||
***********************
|
||||
|
||||
.. image:: images/search_objects.png
|
||||
:alt: Search objects dialog
|
||||
:align: center
|
||||
|
||||
With this dialog, you can search for almost any kind of objects in a
|
||||
database.
|
||||
|
||||
You can access it by right clicking a database or any of its child nodes
|
||||
and select "Search objects". You can also access it by hitting the
|
||||
shortcut (default ALT+SHIFT+S).
|
||||
|
||||
The minimum pattern length are 3 characters. The search performed is
|
||||
non-casesensitive and will find all objets whose name contains the pattern.
|
||||
You can only search for object names.
|
||||
|
||||
The result is presented in the grid with object name, object type and
|
||||
the object tree path in the :ref:`browser <tree_control>`. You can double
|
||||
click on a result row to select the object in the
|
||||
:ref:`browser <tree_control>`. If the object is greyed out, this means that you
|
||||
have not enabled those object types in the :ref:`preferences <preferences>`,
|
||||
so you can't double click on it.
|
||||
|
||||
You can filter based on a particular object type by selecting one from the
|
||||
object type dropdown. If the search button is hit when one of the object type
|
||||
is selected then only those types will be fetch from the database.
|
||||
An object type will not be visible in the dropdown if the database server
|
||||
does not support it or if it is not enabled from the
|
||||
:ref:`preferences <preferences>`.
|
@@ -18,4 +18,6 @@ the selected browser node.
|
||||
* Use the :ref:`View Data <editgrid>` button to view/edit the data stored in a
|
||||
selected table.
|
||||
* Use the :ref:`Filtered Rows <viewdata_filter>` button to access the Data Filter popup
|
||||
to apply a filter to a set of data for viewing/editing.
|
||||
to apply a filter to a set of data for viewing/editing.
|
||||
* Use the :ref:`Search objects <search_objects>` button to access the search objects
|
||||
dialog. It helps you search any database object.
|
@@ -249,6 +249,21 @@ def register_browser_preferences(self):
|
||||
fields=fields
|
||||
)
|
||||
|
||||
self.preference.register(
|
||||
'keyboard_shortcuts',
|
||||
'sub_menu_search_objects',
|
||||
gettext('Search objects'),
|
||||
'keyboardshortcut',
|
||||
{
|
||||
'alt': True,
|
||||
'shift': True,
|
||||
'control': False,
|
||||
'key': {'key_code': 83, 'char': 's'}
|
||||
},
|
||||
category_label=gettext('Keyboard shortcuts'),
|
||||
fields=fields
|
||||
)
|
||||
|
||||
self.preference.register(
|
||||
'keyboard_shortcuts',
|
||||
'sub_menu_create',
|
||||
|
@@ -24,7 +24,7 @@ define('pgadmin.node.extension', [
|
||||
pgAdmin.Browser.Nodes['coll-extension'] =
|
||||
pgAdmin.Browser.Collection.extend({
|
||||
node: 'extension',
|
||||
label: gettext('Extension'),
|
||||
label: gettext('Extensions'),
|
||||
type: 'coll-extension',
|
||||
columns: ['name', 'owner', 'comment'],
|
||||
});
|
||||
|
@@ -0,0 +1,11 @@
|
||||
SELECT
|
||||
nsp.oid, nspname AS name
|
||||
FROM
|
||||
pg_namespace nsp
|
||||
WHERE nspparent = {{scid}}::oid
|
||||
{% if pkgid %}
|
||||
AND nsp.oid = {{pkgid}}::oid
|
||||
{% endif %}
|
||||
AND nspobjecttype = 0
|
||||
AND nspcompoundtrigger = false
|
||||
ORDER BY nspname;
|
@@ -54,8 +54,8 @@ class IndexConstraintModule(ConstraintTypeModule):
|
||||
initialized.
|
||||
"""
|
||||
|
||||
NODE_TYPE = 'Index constraint'
|
||||
COLLECTION_LABEL = _('index_constraint')
|
||||
NODE_TYPE = 'index_constraint'
|
||||
COLLECTION_LABEL = _('Index constraint')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
|
@@ -29,8 +29,11 @@ from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
||||
|
||||
|
||||
def backend_supported(module, manager, **kwargs):
|
||||
if 'tid' in kwargs and CollectionNodeModule.BackendSupported(
|
||||
module, manager, **kwargs):
|
||||
|
||||
if CollectionNodeModule.BackendSupported(module, manager, **kwargs):
|
||||
if 'tid' not in kwargs:
|
||||
return True
|
||||
|
||||
conn = manager.connection(did=kwargs['did'])
|
||||
|
||||
template_path = 'partitions/sql/{0}/#{0}#{1}#'.format(
|
||||
|
@@ -21,19 +21,19 @@ else:
|
||||
|
||||
class TestBackendSupport(BaseTestGenerator):
|
||||
scenarios = [
|
||||
('when tid is not present in arguments, should return None and no '
|
||||
'query should be done',
|
||||
('when tid is not present in arguments, but server version'
|
||||
'is supported then return True',
|
||||
dict(
|
||||
manager=dict(
|
||||
server_type="",
|
||||
version=""
|
||||
server_type="pg",
|
||||
version="100000"
|
||||
),
|
||||
input_arguments=dict(did=432),
|
||||
|
||||
collection_node_active=True,
|
||||
connection_execution_return_value=[],
|
||||
|
||||
expected_return_value=None,
|
||||
expected_return_value=True,
|
||||
expect_error_response=False,
|
||||
expected_number_calls_on_render_template=0
|
||||
)),
|
||||
|
@@ -9,6 +9,9 @@
|
||||
(SELECT 1 FROM pg_class WHERE relname = 'tables' AND
|
||||
relnamespace = {{ tbl }}.oid LIMIT 1))
|
||||
{%- endmacro %}
|
||||
{% macro IS_CATALOG_SCHEMA(schema_col_name) -%}
|
||||
{{ schema_col_name }} IN ('pg_catalog', 'pgagent', 'information_schema')
|
||||
{%- endmacro %}
|
||||
{% macro LABELS(tbl, _) -%}
|
||||
CASE {{ tbl }}.nspname
|
||||
WHEN 'pg_catalog' THEN '{{ _( 'PostgreSQL Catalog' ) }} (pg_catalog)'
|
||||
@@ -17,9 +20,24 @@
|
||||
ELSE {{ tbl }}.nspname
|
||||
END AS name
|
||||
{%- endmacro %}
|
||||
{% macro LABELS_SCHEMACOL(schema_col_name, _) -%}
|
||||
CASE {{ schema_col_name }}
|
||||
WHEN 'pg_catalog' THEN '{{ _( 'PostgreSQL Catalog' ) }} (pg_catalog)'
|
||||
WHEN 'pgagent' THEN '{{ _( 'pgAgent Job Scheduler' ) }} (pgagent)'
|
||||
WHEN 'information_schema' THEN '{{ _( 'ANSI' ) }} (information_schema)'
|
||||
ELSE {{ schema_col_name }}
|
||||
END
|
||||
{%- endmacro %}
|
||||
{% macro DB_SUPPORT(tbl) -%}
|
||||
CASE
|
||||
WHEN {{ tbl }}.nspname = ANY('{information_schema}')
|
||||
THEN false
|
||||
ELSE true END
|
||||
{%- endmacro %}
|
||||
{% macro DB_SUPPORT_SCHEMACOL(schema_col_name) -%}
|
||||
CASE
|
||||
WHEN {{ schema_col_name }} = ANY('{information_schema}')
|
||||
THEN false
|
||||
ELSE true END
|
||||
{%- endmacro %}
|
||||
|
||||
|
@@ -13,6 +13,9 @@
|
||||
(SELECT 1 FROM pg_proc
|
||||
WHERE pronamespace = {{ tbl }}.oid and proname = 'run_job' LIMIT 1))
|
||||
{%- endmacro %}
|
||||
{% macro IS_CATALOG_SCHEMA(schema_col_name) -%}
|
||||
{{ schema_col_name }} IN ('pg_catalog', 'pgagent', 'information_schema', 'dbo', 'sys', 'dbms_job_procedure')
|
||||
{%- endmacro %}
|
||||
{% macro LABELS(tbl, _) -%}
|
||||
CASE {{ tbl }}.nspname
|
||||
WHEN 'pg_catalog' THEN '{{ _( 'PostgreSQL Catalog' ) }} (pg_catalog)'
|
||||
@@ -23,9 +26,25 @@
|
||||
ELSE {{ tbl }}.nspname
|
||||
END AS name
|
||||
{%- endmacro %}
|
||||
{% macro DB_SUPPORT(tbl) -%}
|
||||
{% macro LABELS_SCHEMACOL(schema_col_name, _) -%}
|
||||
CASE {{ schema_col_name }}
|
||||
WHEN 'pg_catalog' THEN '{{ _( 'PostgreSQL Catalog' ) }} (pg_catalog)'
|
||||
WHEN 'pgagent' THEN '{{ _( 'pgAgent Job Scheduler' ) }} (pgagent)'
|
||||
WHEN 'information_schema' THEN '{{ _( 'ANSI' ) }} (information_schema)'
|
||||
WHEN 'dbo' THEN 'Redmond (dbo)'
|
||||
WHEN 'sys' THEN 'Redwood (sys)'
|
||||
ELSE {{ schema_col_name }}
|
||||
END
|
||||
{%- endmacro %}
|
||||
{% macro DB_SUPPORT(tbl, schema_col_name) -%}
|
||||
CASE
|
||||
WHEN {{ tbl }}.nspname = ANY('{information_schema,sys,dbo}')
|
||||
THEN false
|
||||
ELSE true END
|
||||
{%- endmacro %}
|
||||
{% macro DB_SUPPORT_SCHEMACOL(schema_col_name) -%}
|
||||
CASE
|
||||
WHEN {{ schema_col_name }} = ANY('{information_schema,sys,dbo}')
|
||||
THEN false
|
||||
ELSE true END
|
||||
{%- endmacro %}
|
||||
|
@@ -18,6 +18,7 @@ define('pgadmin.node.role', [
|
||||
pgAdmin.Browser.Nodes['coll-role'] =
|
||||
pgAdmin.Browser.Collection.extend({
|
||||
node: 'role',
|
||||
label: gettext('Login/Group Roles'),
|
||||
type: 'coll-role',
|
||||
columns: [
|
||||
'rolname', 'rolvaliduntil', 'rolconnlimit', 'rolcanlogin',
|
||||
|
@@ -51,14 +51,23 @@ define([
|
||||
}]);
|
||||
|
||||
// show query tool only in context menu of supported nodes.
|
||||
if (pgAdmin.DataGrid && pgAdmin.unsupported_nodes) {
|
||||
if (_.indexOf(pgAdmin.unsupported_nodes, this.type) == -1) {
|
||||
|
||||
if (pgAdmin.unsupported_nodes && _.indexOf(pgAdmin.unsupported_nodes, this.type) == -1) {
|
||||
if ((this.type == 'database' && this.allowConn) || this.type != 'database') {
|
||||
pgAdmin.Browser.add_menus([{
|
||||
name: 'show_query_tool', node: this.type, module: this,
|
||||
name: 'show_query_tool', node: this.type, module: pgAdmin.DataGrid,
|
||||
applies: ['context'], callback: 'show_query_tool',
|
||||
priority: 998, label: gettext('Query Tool...'),
|
||||
icon: 'pg-font-icon icon-query-tool',
|
||||
}]);
|
||||
|
||||
// show search objects same as query tool
|
||||
pgAdmin.Browser.add_menus([{
|
||||
name: 'search_objects', node: this.type, module: pgAdmin.SearchObjects,
|
||||
applies: ['context'], callback: 'show_search_objects',
|
||||
priority: 997, label: gettext('Search Objects...'),
|
||||
icon: 'fa fa-search',
|
||||
}]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@@ -34,6 +34,7 @@ _.extend(pgBrowser.keyboardNavigation, {
|
||||
'tabbed_panel_forward': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'tabbed_panel_forward').value),
|
||||
'sub_menu_query_tool': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'sub_menu_query_tool').value),
|
||||
'sub_menu_view_data': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'sub_menu_view_data').value),
|
||||
'sub_menu_search_objects': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'sub_menu_search_objects').value),
|
||||
'sub_menu_properties': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'sub_menu_properties').value),
|
||||
'sub_menu_create': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'sub_menu_create').value),
|
||||
'sub_menu_delete': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'sub_menu_delete').value),
|
||||
@@ -55,6 +56,7 @@ _.extend(pgBrowser.keyboardNavigation, {
|
||||
'bindLeftTree': {'shortcuts': this.keyboardShortcut.left_tree_shortcut}, // Main menu,
|
||||
'bindSubMenuQueryTool': {'shortcuts': this.keyboardShortcut.sub_menu_query_tool}, // Sub menu - Open Query Tool,
|
||||
'bindSubMenuViewData': {'shortcuts': this.keyboardShortcut.sub_menu_view_data}, // Sub menu - Open View Data,
|
||||
'bindSubMenuSearchObjects': {'shortcuts': this.keyboardShortcut.sub_menu_search_objects}, // Sub menu - Open search objects,
|
||||
'bindSubMenuProperties': {'shortcuts': this.keyboardShortcut.sub_menu_properties}, // Sub menu - Edit Properties,
|
||||
'bindSubMenuCreate': {'shortcuts': this.keyboardShortcut.sub_menu_create}, // Sub menu - Create Object,
|
||||
'bindSubMenuDelete': {'shortcuts': this.keyboardShortcut.sub_menu_delete}, // Sub menu - Delete object,
|
||||
@@ -261,6 +263,15 @@ _.extend(pgBrowser.keyboardNavigation, {
|
||||
// Call data grid method to render view data
|
||||
pgAdmin.DataGrid.show_data_grid({'mnuid': 1}, tree.i);
|
||||
},
|
||||
bindSubMenuSearchObjects: function() {
|
||||
const tree = this.getTreeDetails();
|
||||
|
||||
if (!tree.d)
|
||||
return;
|
||||
|
||||
// Call data grid method to render view data
|
||||
pgAdmin.SearchObjects.show_search_objects('', tree.i);
|
||||
},
|
||||
bindSubMenuProperties: function() {
|
||||
const tree = this.getTreeDetails();
|
||||
|
||||
|
@@ -177,6 +177,14 @@ define('pgadmin.browser.node', [
|
||||
|
||||
// Show query tool only in context menu of supported nodes.
|
||||
if (_.indexOf(pgAdmin.unsupported_nodes, self.type) == -1) {
|
||||
let enable = function(itemData) {
|
||||
if (itemData._type == 'database' && itemData.allowConn)
|
||||
return true;
|
||||
else if (itemData._type != 'database')
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
pgAdmin.Browser.add_menus([{
|
||||
name: 'show_query_tool',
|
||||
node: self.type,
|
||||
@@ -186,14 +194,15 @@ define('pgadmin.browser.node', [
|
||||
priority: 998,
|
||||
label: gettext('Query Tool...'),
|
||||
icon: 'pg-font-icon icon-query-tool',
|
||||
enable: function(itemData) {
|
||||
if (itemData._type == 'database' && itemData.allowConn)
|
||||
return true;
|
||||
else if (itemData._type != 'database')
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
enable: enable,
|
||||
}]);
|
||||
|
||||
// show search objects same as query tool
|
||||
pgAdmin.Browser.add_menus([{
|
||||
name: 'search_objects', node: self.type, module: pgAdmin.SearchObjects,
|
||||
applies: ['context'], callback: 'show_search_objects',
|
||||
priority: 997, label: gettext('Search Objects...'),
|
||||
icon: 'fa fa-search', enable: enable,
|
||||
}]);
|
||||
}
|
||||
|
||||
|
@@ -46,6 +46,16 @@ let _defaultToolBarButtons = [
|
||||
parentClass: 'pg-toolbar-btn btn-secondary',
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
label: gettext('Search objects'),
|
||||
ariaLabel: gettext('Search objects'),
|
||||
btnClass: 'fa fa-search',
|
||||
text: '',
|
||||
toggled: false,
|
||||
toggleClass: '',
|
||||
parentClass: 'pg-toolbar-btn btn-secondary',
|
||||
enabled: false,
|
||||
},
|
||||
];
|
||||
|
||||
// Place holder for non default tool bar buttons.
|
||||
@@ -92,6 +102,8 @@ export function initializeToolbar(panel, wcDocker) {
|
||||
pgAdmin.DataGrid.show_data_grid({mnuid: 3}, pgAdmin.Browser.tree.selected());
|
||||
else if ('name' in data && data.name === gettext('Filtered Rows'))
|
||||
pgAdmin.DataGrid.show_filtered_row({mnuid: 4}, pgAdmin.Browser.tree.selected());
|
||||
else if ('name' in data && data.name === gettext('Search objects'))
|
||||
pgAdmin.SearchObjects.show_search_objects('', pgAdmin.Browser.tree.selected());
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,7 @@
|
||||
{% block init_script %}
|
||||
try {
|
||||
require(
|
||||
['sources/generated/app.bundle', 'sources/generated/codemirror', 'sources/generated/browser_nodes'],
|
||||
['sources/generated/app.bundle', 'sources/generated/codemirror', 'sources/generated/browser_nodes', 'sources/generated/slickgrid'],
|
||||
function() {
|
||||
},
|
||||
function() {
|
||||
|
@@ -8,7 +8,6 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import 'slickgrid/lib/jquery.event.drag-2.3.0';
|
||||
import 'slickgrid/lib/jquery-ui-1.11.3';
|
||||
import 'slickgrid/slick.core';
|
||||
import 'slickgrid/slick.grid';
|
||||
import 'slickgrid/slick.dataview';
|
||||
@@ -21,5 +20,6 @@ import 'slickgrid/plugins/slick.cellrangeselector';
|
||||
import 'slickgrid/plugins/slick.checkboxselectcolumn';
|
||||
import 'slickgrid/plugins/slick.rowselectionmodel';
|
||||
import 'sources/slickgrid/custom_header_buttons';
|
||||
import 'sources/slickgrid/plugins/slick.autocolumnsize';
|
||||
|
||||
export default window.Slick;
|
||||
|
@@ -5,18 +5,17 @@
|
||||
@import '~tempusdominus-bootstrap-4/build/css/tempusdominus-bootstrap-4.css';
|
||||
@import '~bootstrap4-toggle/css/bootstrap4-toggle.css';
|
||||
@import '~backgrid-filter/backgrid-filter.css';
|
||||
@import '~slickgrid/css/select2.css';
|
||||
@import '~jquery-contextmenu/dist/jquery.contextMenu.css';
|
||||
@import '~webcabin-docker/Build/wcDocker.css';
|
||||
@import '~acitree/css/aciTree.css';
|
||||
@import '~leaflet/dist/leaflet.css';
|
||||
@import '../../../node_modules/select2/dist/css/select2.css';
|
||||
|
||||
@import '~codemirror/lib/codemirror.css';
|
||||
@import '~codemirror/addon/dialog/dialog.css';
|
||||
@import '~codemirror/addon/scroll/simplescrollbars.css';
|
||||
|
||||
@import '~slickgrid/slick.grid.css';
|
||||
@import '~slickgrid/slick-default-theme.css';
|
||||
@import '~slickgrid/css/smoothness/jquery-ui-1.11.3.custom.css';
|
||||
|
||||
@import '../vendor/backgrid/backgrid.css';
|
||||
|
@@ -271,7 +271,8 @@ define([
|
||||
let container = $(self.elements.footer);
|
||||
commonUtils.findAndSetFocus(container.find('button:not([disabled]):last'));
|
||||
}
|
||||
}); });
|
||||
});
|
||||
});
|
||||
this.set('onresize', alertifyDialogStartResizing.bind(this, true));
|
||||
this.set('onresized', alertifyDialogResized.bind(this, true));
|
||||
this.set('onmaximized', alertifyDialogResized);
|
||||
|
@@ -80,6 +80,39 @@ export class Dialog {
|
||||
return serverInformation;
|
||||
}
|
||||
|
||||
retrieveAncestorOfTypeDatabase(item) {
|
||||
let databaseInfo = null;
|
||||
let aciTreeItem = item || this.pgBrowser.treeMenu.selected();
|
||||
let treeNode = this.pgBrowser.treeMenu.findNodeByDomElement(aciTreeItem);
|
||||
|
||||
if (treeNode) {
|
||||
if(treeNode.getData()._type === 'database') {
|
||||
databaseInfo = treeNode.getData();
|
||||
} else {
|
||||
let nodeData = null;
|
||||
treeNode.ancestorNode(
|
||||
(node) => {
|
||||
nodeData = node.getData();
|
||||
if(nodeData._type === 'database') {
|
||||
databaseInfo = nodeData;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (databaseInfo === null) {
|
||||
this.alertify.alert(
|
||||
gettext(this.errorAlertTitle),
|
||||
gettext('Please select a database or its child node from the browser.')
|
||||
);
|
||||
}
|
||||
|
||||
return databaseInfo;
|
||||
}
|
||||
|
||||
hasBinariesConfiguration(serverInformation) {
|
||||
const module = 'paths';
|
||||
let preference_name = 'pg_bin_dir';
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
import * as BackupDialog from '../../../tools/backup/static/js/backup_dialog_wrapper';
|
||||
import {RestoreDialogWrapper} from '../../../tools/restore/static/js/restore_dialog_wrapper';
|
||||
import SearchObjectsDialogWrapper from '../../../tools/search_objects/static/js/search_objects_dialog_wrapper';
|
||||
|
||||
export class DialogFactory {
|
||||
constructor(pgBrowser, $,
|
||||
@@ -25,6 +26,8 @@ export class DialogFactory {
|
||||
create(dialogTitle, typeOfDialog) {
|
||||
if (typeOfDialog === 'restore') {
|
||||
return this.createRestoreDialog(dialogTitle, typeOfDialog);
|
||||
} else if (typeOfDialog === 'search_objects') {
|
||||
return this.createSearchObjectsDialog(dialogTitle, typeOfDialog);
|
||||
} else {
|
||||
return this.createBackupDialog(dialogTitle, typeOfDialog);
|
||||
}
|
||||
@@ -49,4 +52,14 @@ export class DialogFactory {
|
||||
this.dialogModel,
|
||||
this.backform);
|
||||
}
|
||||
|
||||
createSearchObjectsDialog(dialogTitle, typeOfDialog) {
|
||||
return new SearchObjectsDialogWrapper(
|
||||
this.dialogContainerSelector, dialogTitle, typeOfDialog,
|
||||
this.jquery,
|
||||
this.pgBrowser,
|
||||
this.alertify,
|
||||
this.dialogModel,
|
||||
this.backform);
|
||||
}
|
||||
}
|
||||
|
@@ -58,7 +58,11 @@ export class DialogWrapper {
|
||||
let backform_tab = $(alertifyDialog.elements.body).find('.backform-tab');
|
||||
backform_tab.attr('tabindex', -1);
|
||||
this.pgBrowser.keyboardNavigation.getDialogTabNavigator($(alertifyDialog.elements.dialog));
|
||||
const container = backform_tab.find('.tab-content:first > .tab-pane.active:first');
|
||||
let container = backform_tab.find('.tab-content:first > .tab-pane.active:first');
|
||||
|
||||
if(container.length === 0 && alertifyDialog.elements.content.innerHTML) {
|
||||
container = $(alertifyDialog.elements.content);
|
||||
}
|
||||
commonUtils.findAndSetFocus(container);
|
||||
}
|
||||
|
||||
|
@@ -98,7 +98,7 @@
|
||||
function getTemplateWidth(rowEl, template) {
|
||||
var cell = $(rowEl.find('.slick-cell'));
|
||||
cell.append(template);
|
||||
$(cell).find('*').css('position', 'relative');
|
||||
cell.find('*').css('position', 'relative');
|
||||
return cell.outerWidth() + 1;
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
'text-overflow': 'initial',
|
||||
'white-space': 'nowrap',
|
||||
});
|
||||
var gridCanvas = $container.find('.grid-canvas');
|
||||
var gridCanvas = $container.find('.grid-canvas').first();
|
||||
$(gridCanvas).append(rowEl);
|
||||
return rowEl;
|
||||
}
|
||||
|
@@ -50,17 +50,50 @@ export class TreeNode {
|
||||
}
|
||||
|
||||
reload(tree) {
|
||||
this.unload(tree);
|
||||
tree.aciTreeApi.setInode(this.domNode);
|
||||
tree.aciTreeApi.deselect(this.domNode);
|
||||
setTimeout(() => {
|
||||
tree.selectNode(this.domNode);
|
||||
}, 0);
|
||||
return new Promise((resolve)=>{
|
||||
this.unload(tree)
|
||||
.then(()=>{
|
||||
tree.aciTreeApi.setInode(this.domNode);
|
||||
tree.aciTreeApi.deselect(this.domNode);
|
||||
setTimeout(() => {
|
||||
tree.selectNode(this.domNode);
|
||||
}, 0);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
unload(tree) {
|
||||
this.children = [];
|
||||
tree.aciTreeApi.unload(this.domNode);
|
||||
return new Promise((resolve, reject)=>{
|
||||
this.children = [];
|
||||
tree.aciTreeApi.unload(this.domNode, {
|
||||
success: ()=>{
|
||||
resolve(true);
|
||||
},
|
||||
fail: ()=>{
|
||||
reject();
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
open(tree, suppressNoDom) {
|
||||
return new Promise((resolve, reject)=>{
|
||||
if(suppressNoDom && (this.domNode == null || typeof(this.domNode) === 'undefined')) {
|
||||
resolve(true);
|
||||
} else if(tree.aciTreeApi.isOpen(this.domNode)) {
|
||||
resolve(true);
|
||||
} else {
|
||||
tree.aciTreeApi.open(this.domNode, {
|
||||
success: ()=>{
|
||||
resolve(true);
|
||||
},
|
||||
fail: ()=>{
|
||||
reject(true);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -202,6 +235,47 @@ export class Tree {
|
||||
return findInTree(this.rootNode, path.join('.'));
|
||||
}
|
||||
|
||||
findNodeWithToggle(path) {
|
||||
let tree = this;
|
||||
path = path.join('.');
|
||||
|
||||
let onCorrectPath = function(matchPath) {
|
||||
return (matchPath !== undefined && path !== undefined
|
||||
&& (path.startsWith(matchPath + '.') || path === matchPath));
|
||||
};
|
||||
|
||||
return (function findInNode(currentNode) {
|
||||
return new Promise((resolve, reject)=>{
|
||||
if (path === null || path === undefined || path.length === 0) {
|
||||
resolve(null);
|
||||
}
|
||||
/* No point in checking the children if
|
||||
* the path for currentNode itself is not matching
|
||||
*/
|
||||
if (currentNode.path !== undefined && !onCorrectPath(currentNode.path)) {
|
||||
reject(null);
|
||||
} else if (currentNode.path === path) {
|
||||
resolve(currentNode);
|
||||
} else {
|
||||
currentNode.open(tree, true)
|
||||
.then(()=>{
|
||||
for (let i = 0, length = currentNode.children.length; i < length; i++) {
|
||||
let childNode = currentNode.children[i];
|
||||
if(onCorrectPath(childNode.path)) {
|
||||
resolve(findInNode(childNode));
|
||||
return;
|
||||
}
|
||||
}
|
||||
reject(null);
|
||||
})
|
||||
.catch(()=>{
|
||||
reject(null);
|
||||
});
|
||||
}
|
||||
});
|
||||
})(this.rootNode);
|
||||
}
|
||||
|
||||
findNodeByDomElement(domElement) {
|
||||
const path = this.translateTreeNodeIdFromACITree(domElement);
|
||||
if(!path || !path[0]) {
|
||||
@@ -215,8 +289,19 @@ export class Tree {
|
||||
return this.aciTreeApi.selected();
|
||||
}
|
||||
|
||||
selectNode(aciTreeIdentifier) {
|
||||
/* scrollIntoView will scroll only to top and bottom
|
||||
* Logic can be added for scroll to middle
|
||||
*/
|
||||
scrollTo(domElement) {
|
||||
domElement.scrollIntoView();
|
||||
}
|
||||
|
||||
selectNode(aciTreeIdentifier, scrollOnSelect) {
|
||||
this.aciTreeApi.select(aciTreeIdentifier);
|
||||
|
||||
if(scrollOnSelect) {
|
||||
this.scrollTo(aciTreeIdentifier[0]);
|
||||
}
|
||||
}
|
||||
|
||||
createOrUpdateNode(id, data, parent, domNode) {
|
||||
@@ -227,6 +312,7 @@ export class Tree {
|
||||
const oldNode = this.findNode(oldNodePath);
|
||||
if (oldNode !== null) {
|
||||
oldNode.data = data;
|
||||
oldNode.domNode = domNode;
|
||||
return oldNode;
|
||||
}
|
||||
|
||||
@@ -238,6 +324,18 @@ export class Tree {
|
||||
return node;
|
||||
}
|
||||
|
||||
unloadNode(id, data, domNode, parentPath) {
|
||||
let oldNodePath = [id];
|
||||
const parent = this.findNode(parentPath);
|
||||
if(parent !== null && parent !== undefined) {
|
||||
oldNodePath = [parent.path, id];
|
||||
}
|
||||
const oldNode = this.findNode(oldNodePath);
|
||||
if(oldNode) {
|
||||
oldNode.children = [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the JQuery object that contains the ACI Tree
|
||||
* this method is responsible for registering this tree class
|
||||
@@ -252,16 +350,20 @@ export class Tree {
|
||||
$treeJQuery.on('acitree', function (event, api, item, eventName) {
|
||||
if (api.isItem(item)) {
|
||||
/* If the id of node is changed, the path should also be changed */
|
||||
if (eventName === 'added' || eventName === 'idset') {
|
||||
if (['added', 'idset', 'beforeunload'].indexOf(eventName) != -1) {
|
||||
const id = api.getId(item);
|
||||
const data = api.itemData(item);
|
||||
|
||||
if(eventName === 'added') {
|
||||
this.prepareDraggable(data, item);
|
||||
}
|
||||
|
||||
const parentId = this.translateTreeNodeIdFromACITree(api.parent(item));
|
||||
this.addNewNode(id, data, item, parentId);
|
||||
|
||||
if(eventName === 'beforeunload') {
|
||||
this.unloadNode(id, data, item, parentId);
|
||||
} else {
|
||||
if(eventName === 'added') {
|
||||
this.prepareDraggable(data, item);
|
||||
}
|
||||
|
||||
this.addNewNode(id, data, item, parentId);
|
||||
}
|
||||
if(data.errmsg) {
|
||||
Alertify.error(data.errmsg);
|
||||
}
|
||||
|
@@ -32,11 +32,12 @@ export function findAndSetFocus(container) {
|
||||
* browser. For eg, in safari focus() works only when element has
|
||||
* tabindex="0", whereas in Chrome it works in any case
|
||||
*/
|
||||
|
||||
if (first_el.length == 0) {
|
||||
first_el = container
|
||||
.find(`
|
||||
.pgadmin-controls:first input:enabled,
|
||||
.pgadmin-controls:first .btn:not(.toggle),
|
||||
.pgadmin-controls:first,
|
||||
.ajs-commands:first,
|
||||
.CodeMirror-scroll`)
|
||||
.find('*[tabindex]:not([tabindex="-1"])');
|
||||
|
@@ -119,21 +119,18 @@
|
||||
}
|
||||
|
||||
.success-in-footer {
|
||||
border-radius: 5px;
|
||||
border: 1px solid transparent;
|
||||
|
||||
.alert-text {
|
||||
border-color: $color-success-light;
|
||||
}
|
||||
border-radius: $border-radius;
|
||||
border: 1px solid $color-success-light;
|
||||
background: $color-success-light;
|
||||
}
|
||||
|
||||
.info-in-footer {
|
||||
border-radius: $border-radius;
|
||||
border: 1px solid $color-primary;
|
||||
border-radius: 4px;
|
||||
height: 35px;
|
||||
background: $color-primary-light;
|
||||
|
||||
.alert-text {
|
||||
border: none;
|
||||
.fa {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -166,7 +166,7 @@
|
||||
|
||||
.wcTabIcon {
|
||||
background-position: center;
|
||||
padding: 0px 10px;
|
||||
padding: 0rem 0.75rem;
|
||||
|
||||
&.fa, &.pg-font-icon{
|
||||
padding: 0rem 0.25rem 0rem 0rem
|
||||
|
87
web/pgadmin/tools/search_objects/__init__.py
Normal file
87
web/pgadmin/tools/search_objects/__init__.py
Normal file
@@ -0,0 +1,87 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""Implements Search Object feature"""
|
||||
|
||||
from flask import request
|
||||
from flask_babelex import gettext
|
||||
from flask_security import login_required
|
||||
|
||||
from pgadmin.utils import PgAdminModule
|
||||
from pgadmin.utils.ajax import make_json_response, bad_request,\
|
||||
internal_server_error
|
||||
from pgadmin.utils.preferences import Preferences
|
||||
from pgadmin.tools.search_objects.utils import SearchObjectsHelper
|
||||
|
||||
MODULE_NAME = 'search_objects'
|
||||
|
||||
|
||||
class SearchObjectsModule(PgAdminModule):
|
||||
LABEL = gettext('Search objects')
|
||||
|
||||
def get_exposed_url_endpoints(self):
|
||||
"""
|
||||
Returns:
|
||||
list: URL endpoints for search_object module
|
||||
"""
|
||||
return ['search_objects.search', 'search_objects.types']
|
||||
|
||||
def show_system_objects(self):
|
||||
"""
|
||||
return system preference objects
|
||||
"""
|
||||
return self.pref_show_system_objects.get()
|
||||
|
||||
def register_preferences(self):
|
||||
"""
|
||||
Get show_system_objects preference
|
||||
"""
|
||||
browser_preference = Preferences.module('browser')
|
||||
self.pref_show_system_objects =\
|
||||
browser_preference.preference('show_system_objects')
|
||||
|
||||
|
||||
# Create blueprint for BackupModule class
|
||||
blueprint = SearchObjectsModule(
|
||||
MODULE_NAME, __name__, static_url_path=''
|
||||
)
|
||||
|
||||
|
||||
@blueprint.route("/", endpoint='index')
|
||||
@login_required
|
||||
def index():
|
||||
return bad_request(errormsg=_("This URL cannot be called directly."))
|
||||
|
||||
|
||||
@blueprint.route("types/<int:sid>/<int:did>", endpoint='types')
|
||||
@login_required
|
||||
def types(sid, did):
|
||||
so_obj = SearchObjectsHelper(sid, did, blueprint.show_system_objects())
|
||||
return make_json_response(data=so_obj.get_supported_types())
|
||||
|
||||
|
||||
@blueprint.route("search/<int:sid>/<int:did>", endpoint='search')
|
||||
@login_required
|
||||
def search(sid, did):
|
||||
"""
|
||||
URL args:
|
||||
text <required>: search text
|
||||
type <optional>: type of object to be searched.
|
||||
"""
|
||||
text = request.args.get('text', None)
|
||||
obj_type = request.args.get('type', None)
|
||||
|
||||
so_obj = SearchObjectsHelper(sid, did, blueprint.show_system_objects())
|
||||
|
||||
status, res = so_obj.search(text, obj_type)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
return make_json_response(data=res)
|
90
web/pgadmin/tools/search_objects/static/js/search_objects.js
Normal file
90
web/pgadmin/tools/search_objects/static/js/search_objects.js
Normal file
@@ -0,0 +1,90 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
define([
|
||||
'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'pgadmin.alertifyjs',
|
||||
'sources/pgadmin', 'sources/csrf', 'pgadmin.browser.toolbar',
|
||||
'pgadmin.search_objects/search_objects_dialog',
|
||||
], function(
|
||||
gettext, url_for, $, _, alertify, pgAdmin, csrfToken, toolBar, SearchObjectsDialog
|
||||
) {
|
||||
|
||||
var pgBrowser = pgAdmin.Browser;
|
||||
if (pgAdmin.SearchObjects)
|
||||
return pgAdmin.SearchObjects;
|
||||
|
||||
pgAdmin.SearchObjects = {
|
||||
init: function() {
|
||||
if (this.initialized)
|
||||
return;
|
||||
|
||||
this.initialized = true;
|
||||
csrfToken.setPGCSRFToken(pgAdmin.csrf_token_header, pgAdmin.csrf_token);
|
||||
|
||||
// Define the nodes on which the menus to be appear
|
||||
var menus = [{
|
||||
name: 'search_objects',
|
||||
module: this,
|
||||
applies: ['tools'],
|
||||
callback: 'show_search_objects',
|
||||
enable: this.search_objects_enabled,
|
||||
priority: 1,
|
||||
label: gettext('Search objects'),
|
||||
}, {
|
||||
name: 'search_objects',
|
||||
module: this,
|
||||
applies: ['context'],
|
||||
callback: 'show_search_objects',
|
||||
enable: this.search_objects_enabled,
|
||||
priority: 1,
|
||||
label: gettext('Search objects'),
|
||||
}];
|
||||
|
||||
pgBrowser.add_menus(menus);
|
||||
return this;
|
||||
},
|
||||
|
||||
search_objects_enabled: function(obj) {
|
||||
/* Same as query tool */
|
||||
var isEnabled = (() => {
|
||||
if (!_.isUndefined(obj) && !_.isNull(obj)) {
|
||||
if (_.indexOf(pgAdmin.unsupported_nodes, obj._type) == -1) {
|
||||
if (obj._type == 'database' && obj.allowConn) {
|
||||
return true;
|
||||
} else if (obj._type != 'database') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
|
||||
toolBar.enable(gettext('Search objects'), isEnabled);
|
||||
return isEnabled;
|
||||
},
|
||||
|
||||
// Callback to show the dialog
|
||||
show_search_objects: function(action, item) {
|
||||
let dialog = new SearchObjectsDialog.default(
|
||||
pgBrowser,
|
||||
$,
|
||||
alertify,
|
||||
{},
|
||||
);
|
||||
dialog.draw(action, item, {}, pgBrowser.stdW.md, pgBrowser.stdH.lg);
|
||||
},
|
||||
};
|
||||
|
||||
return pgAdmin.SearchObjects;
|
||||
});
|
@@ -0,0 +1,40 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import gettext from 'sources/gettext';
|
||||
import {Dialog} from 'sources/alertify/dialog';
|
||||
import {getPanelTitle} from 'tools/datagrid/static/js/datagrid_panel_title';
|
||||
|
||||
export default class SearchObjectsDialog extends Dialog {
|
||||
constructor(pgBrowser, $, alertify, BackupModel, backform = null) {
|
||||
super(gettext('Search Objects Error'),
|
||||
'<div class=\'search_objects_dialog\'></div>',
|
||||
pgBrowser, $, alertify, BackupModel, backform
|
||||
);
|
||||
}
|
||||
|
||||
dialogName() {
|
||||
return 'search_objects';
|
||||
}
|
||||
|
||||
draw(action, aciTreeItem, params, width=0, height=0) {
|
||||
let dbInfo = this.retrieveAncestorOfTypeDatabase(aciTreeItem);
|
||||
if (!dbInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
let dialogTitle = getPanelTitle(this.pgBrowser, aciTreeItem);
|
||||
dialogTitle = gettext('Search Objects - ') + dialogTitle;
|
||||
const dialog = this.createOrGetDialog(
|
||||
gettext('Search Objects...'),
|
||||
'search_objects'
|
||||
);
|
||||
dialog(dialogTitle).resizeTo(width, height);
|
||||
}
|
||||
}
|
@@ -0,0 +1,649 @@
|
||||
import {getTreeNodeHierarchyFromElement} from 'sources/tree/pgadmin_tree_node';
|
||||
import axios from 'axios/index';
|
||||
import gettext from 'sources/gettext';
|
||||
import url_for from 'sources/url_for';
|
||||
import 'select2';
|
||||
import {DialogWrapper} from 'sources/alertify/dialog_wrapper';
|
||||
import Slick from 'sources/../bundle/slickgrid';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
|
||||
|
||||
export default class SearchObjectsDialogWrapper extends DialogWrapper {
|
||||
constructor(dialogContainerSelector, dialogTitle, typeOfDialog,
|
||||
jquery, pgBrowser, alertify, dialogModel, backform) {
|
||||
super(dialogContainerSelector, dialogTitle, jquery,
|
||||
pgBrowser, alertify, dialogModel, backform);
|
||||
|
||||
this.grid = null;
|
||||
this.dataview = null;
|
||||
this.gridContainer = null;
|
||||
}
|
||||
|
||||
showMessage(text, is_error, call_after_show=()=>{}) {
|
||||
if(text == '' || text == null) {
|
||||
this.statusBar.classList.add('d-none');
|
||||
} else {
|
||||
if(is_error) {
|
||||
this.statusBar.innerHTML = `
|
||||
<div class="error-in-footer">
|
||||
<div class="d-flex px-2 py-1">
|
||||
<div class="pr-2">
|
||||
<i class="fa fa-exclamation-triangle text-danger" aria-hidden="true" role="img"></i>
|
||||
</div>
|
||||
<div role="alert" class="alert-text">${text}</div>
|
||||
<div class="ml-auto close-error-bar">
|
||||
<a class="close-error fa fa-times text-danger"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
this.statusBar.querySelector('.close-error').addEventListener('click', ()=>{
|
||||
this.showMessage(null);
|
||||
});
|
||||
} else {
|
||||
this.statusBar.innerHTML = `
|
||||
<div class="info-in-footer">
|
||||
<div class="d-flex px-2 py-1">
|
||||
<div class="pr-2">
|
||||
<i class="fa fa-info-circle text-primary" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="alert-text" role="alert">${text}</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
this.statusBar.classList.remove('d-none');
|
||||
call_after_show(this.statusBar);
|
||||
}
|
||||
}
|
||||
|
||||
createDialogDOM(dialogContainer) {
|
||||
dialogContainer.innerHTML = `
|
||||
<div class="d-flex flex-column w-100 h-100">
|
||||
<div class="p-2">
|
||||
<div class="row">
|
||||
<div class="col-8 d-flex">
|
||||
<div class="input-group pgadmin-controls">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text fa fa-search" id="labelSearch" aria-label="` + gettext('Search') + `"></span>
|
||||
</div>
|
||||
<input type="search" class="form-control" id="txtGridSearch" placeholder="` + gettext('Type at least 3 characters') + `"
|
||||
tabindex="0" aria-describedby="labelSearch" aria-labelledby="labelSearch" autocomplete="off">
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<button class="btn btn-primary btn-search" disabled>`+ gettext('Search') +`</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<select aria-label="` + gettext('Object types') + `" class="node-types"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-result-container flex-grow-1">
|
||||
<div class="pg-sp-container d-none">
|
||||
<div class="pg-sp-content">
|
||||
<div class="row"><div class="col-12 pg-sp-icon"></div></div>
|
||||
<div class="row"><div class="col-12 pg-sp-text"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-result"></div>
|
||||
</div>
|
||||
<div class='search-result-count p-1'>
|
||||
</div>
|
||||
<div class="pg-prop-status-bar">
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return dialogContainer;
|
||||
}
|
||||
|
||||
updateDimOfSearchResult() {
|
||||
let dim = this.searchResultContainer.getBoundingClientRect();
|
||||
this.searchResult.style.height = dim.height + 'px';
|
||||
this.searchResult.style.width = dim.width + 'px';
|
||||
}
|
||||
|
||||
setLoading(text) {
|
||||
if(text != null) {
|
||||
this.loader.classList.remove('d-none');
|
||||
this.loader.querySelector('.pg-sp-text').innerHTML = text;
|
||||
} else {
|
||||
this.loader.classList.add('d-none');
|
||||
}
|
||||
}
|
||||
|
||||
searchBtnEnabled(enabled) {
|
||||
if(typeof(enabled) != 'undefined') {
|
||||
this.searchBtn.disabled = !enabled;
|
||||
} else {
|
||||
return !this.searchBtn.disabled;
|
||||
}
|
||||
}
|
||||
|
||||
searchBoxVal(val) {
|
||||
if(typeof(val) != 'undefined') {
|
||||
this.searchBox.value = val;
|
||||
} else {
|
||||
return this.searchBox.value.trim();
|
||||
}
|
||||
}
|
||||
|
||||
typesVal(val) {
|
||||
if(typeof(val) != 'undefined') {
|
||||
this.typesSelect.value = val;
|
||||
} else {
|
||||
return this.typesSelect.value;
|
||||
}
|
||||
}
|
||||
|
||||
setTypes(data, enabled=true) {
|
||||
this.jquery(this.typesSelect).empty().select2({
|
||||
data: data,
|
||||
});
|
||||
|
||||
this.typesSelect.disabled = !enabled;
|
||||
}
|
||||
|
||||
setResultCount(count) {
|
||||
if(count != 0 && !count) {
|
||||
count = gettext('Unknown');
|
||||
}
|
||||
this.searchResultCount.innerHTML = count + ' ' +
|
||||
(count===1 ? gettext('match found.'): gettext('matches found.'));
|
||||
}
|
||||
|
||||
showOtherInfo(rowno) {
|
||||
let rowData = this.dataview.getItem(rowno);
|
||||
rowData.name += ` (${rowData.other_info})`;
|
||||
rowData.other_info = null;
|
||||
this.dataview.updateItem(rowData.id, rowData);
|
||||
}
|
||||
|
||||
setGridData(data) {
|
||||
this.dataview.setItems(data);
|
||||
}
|
||||
|
||||
prepareGrid() {
|
||||
this.dataview = new Slick.Data.DataView();
|
||||
|
||||
this.dataview.getItemMetadata = (row)=>{
|
||||
let rowData = this.dataview.getItem(row);
|
||||
if(!rowData.show_node){
|
||||
return {
|
||||
cssClasses: 'object-muted',
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
this.dataview.setFilter((item, args)=>{
|
||||
return !(args && args.type != 'all' && item.type != args.type);
|
||||
});
|
||||
|
||||
/* jquery required for select2 */
|
||||
this.jquery(this.typesSelect).on('change', ()=>{
|
||||
this.dataview.setFilterArgs({ type: this.typesVal() });
|
||||
this.dataview.refresh();
|
||||
});
|
||||
|
||||
this.dataview.onRowCountChanged.subscribe((e, args) => {
|
||||
this.grid.updateRowCount();
|
||||
this.grid.render();
|
||||
this.setResultCount(args.current);
|
||||
});
|
||||
|
||||
this.dataview.onRowsChanged.subscribe((e, args) => {
|
||||
this.grid.invalidateRows(args.rows);
|
||||
this.grid.render();
|
||||
});
|
||||
|
||||
this.grid = new Slick.Grid(
|
||||
this.searchResult,
|
||||
this.dataview,
|
||||
[
|
||||
{ id: 'name', name: gettext('Object name'), field: 'name', sortable: true,
|
||||
formatter: (row, cell, value, columnDef, dataContext) => {
|
||||
let ret_el = `<i class='wcTabIcon ${dataContext.icon}'></i>${value}`;
|
||||
|
||||
if(dataContext.other_info != null && dataContext.other_info != '') {
|
||||
ret_el += ' <span class="object-other-info">(...)</span>';
|
||||
}
|
||||
|
||||
return ret_el;
|
||||
},
|
||||
width: 50,
|
||||
},
|
||||
{ id: 'type', name: gettext('Type'), field: 'type_label', sortable: true, width: 35 },
|
||||
{ id: 'path', name: gettext('Browser path'), field: 'path', sortable: false },
|
||||
],
|
||||
{
|
||||
enableCellNavigation: true,
|
||||
enableColumnReorder: false,
|
||||
multiColumnSort: true,
|
||||
explicitInitialization: true,
|
||||
}
|
||||
);
|
||||
|
||||
this.grid.registerPlugin(new Slick.AutoColumnSize());
|
||||
|
||||
this.grid.setSelectionModel(new Slick.RowSelectionModel({selectActiveRow: true}));
|
||||
|
||||
this.grid.onKeyDown.subscribe((event) => {
|
||||
let activeRow = this.grid.getActiveCell();
|
||||
if(activeRow && !event.ctrlKey && !event.altKey && !event.metaKey && event.keyCode == 9) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
|
||||
if(event.shiftKey) {
|
||||
this.prevToGrid.focus();
|
||||
} else {
|
||||
this.nextToGrid.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.grid.onClick.subscribe((event, args) => {
|
||||
if(event.target.classList.contains('object-other-info')) {
|
||||
this.showOtherInfo(args.row);
|
||||
}
|
||||
});
|
||||
|
||||
this.grid.onDblClick.subscribe((event, args) => {
|
||||
let rowData = this.dataview.getItem(args.row);
|
||||
let treeMenu = this.pgBrowser.treeMenu;
|
||||
|
||||
if(!rowData.show_node) {
|
||||
this.showMessage(
|
||||
gettext('%s objects are disabled in the browser.', rowData.type_label) + ' ' +
|
||||
gettext('You can enable them in the') + ' <a class="pref-dialog-link">' + gettext('preferences dialog') + '</a>.',
|
||||
true,
|
||||
(statusBar)=>{
|
||||
statusBar.querySelector('.pref-dialog-link').addEventListener('click', ()=>{
|
||||
if(pgAdmin.Preferences) {
|
||||
pgAdmin.Preferences.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
return false;
|
||||
}
|
||||
this.showMessage(gettext('Locating...'));
|
||||
treeMenu.findNodeWithToggle(rowData.id_path)
|
||||
.then((treeItem)=>{
|
||||
treeMenu.selectNode(treeItem.domNode, true);
|
||||
this.showMessage(null);
|
||||
})
|
||||
.catch((args)=>{
|
||||
this.showMessage(gettext('Unable to locate this object in the browser.'), true);
|
||||
console.warn(args);
|
||||
});
|
||||
});
|
||||
|
||||
this.grid.onSort.subscribe((event, args) => {
|
||||
let cols = args.sortCols;
|
||||
|
||||
this.dataview.sort(function (dataRow1, dataRow2) {
|
||||
for (var i = 0, l = cols.length; i < l; i++) {
|
||||
var field = cols[i].sortCol.field;
|
||||
var sign = cols[i].sortAsc ? 1 : -1;
|
||||
var value1 = dataRow1[field], value2 = dataRow2[field];
|
||||
var result = (value1 == value2 ? 0 : (value1 > value2 ? 1 : -1)) * sign;
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
onDialogResize() {
|
||||
this.updateDimOfSearchResult();
|
||||
|
||||
if(this.grid) {
|
||||
this.grid.resizeCanvas();
|
||||
this.grid.autosizeColumns();
|
||||
}
|
||||
}
|
||||
|
||||
onDialogShow() {
|
||||
this.focusOnDialog(this);
|
||||
|
||||
setTimeout(()=>{
|
||||
if(!this.grid) {
|
||||
this.prepareGrid();
|
||||
}
|
||||
this.updateDimOfSearchResult();
|
||||
this.grid.init();
|
||||
this.setGridData([]);
|
||||
this.onDialogResize();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
getBaseUrl(endpoint) {
|
||||
return url_for('search_objects.'+endpoint, {
|
||||
sid: this.treeInfo.server._id,
|
||||
did: this.treeInfo.database._id,
|
||||
});
|
||||
}
|
||||
|
||||
getCollNode(node_type) {
|
||||
if('coll-'+node_type in this.pgBrowser.Nodes) {
|
||||
return this.pgBrowser.Nodes['coll-'+node_type];
|
||||
} else if(node_type in this.pgBrowser.Nodes &&
|
||||
typeof(this.pgBrowser.Nodes[node_type].collection_type) === 'string') {
|
||||
return this.pgBrowser.Nodes[this.pgBrowser.Nodes[node_type].collection_type];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
getSelectedNode() {
|
||||
const tree = this.pgBrowser.treeMenu;
|
||||
const selectedNode = tree.selected();
|
||||
if (selectedNode) {
|
||||
return tree.findNodeByDomElement(selectedNode);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
finaliseData(datum) {
|
||||
datum.icon = 'icon-' + datum.type;
|
||||
/* finalise path */
|
||||
[datum.path, datum.id_path] = this.translateSearchObjectsPath(datum.path, datum.catalog_level);
|
||||
/* id is required by slickgrid dataview */
|
||||
datum.id = datum.id_path;
|
||||
return datum;
|
||||
}
|
||||
|
||||
/* This function will translate the path given by search objects API into two parts
|
||||
* 1. The display path on the UI
|
||||
* 2. The tree search path to locate the object on the tree.
|
||||
*
|
||||
* Sample path returned by search objects API
|
||||
* :schema.11:/pg_catalog/:table.2604:/pg_attrdef
|
||||
*
|
||||
* Sample path required by tree locator
|
||||
* Normal object - server_group/1.server/3.coll-database/3.database/13258.coll-schema/13258.schema/2200.coll-table/2200.table/41773
|
||||
* pg_catalog schema - server_group/1.server/3.coll-database/3.database/13258.coll-catalog/13258.catalog/11.coll-table/11.table/2600
|
||||
* Information Schema, dbo, sys - server_group/1.server/3.coll-database/3.database/13258.coll-catalog/13258.catalog/12967.coll-catalog_object/12967.catalog_object/13204
|
||||
*
|
||||
* Column catalog_level has values as
|
||||
* N - Not a catalog schema
|
||||
* D - Catalog schema with DB support - pg_catalog
|
||||
* O - Catalog schema with object support only - info schema, dbo, sys
|
||||
*/
|
||||
translateSearchObjectsPath(path, catalog_level) {
|
||||
if (path === null) {
|
||||
return path;
|
||||
}
|
||||
|
||||
catalog_level = catalog_level || 'N';
|
||||
|
||||
/* path required by tree locator */
|
||||
/* the path received from the backend is after the DB node, initial path setup */
|
||||
let id_path = [
|
||||
this.treeInfo.server_group.id,
|
||||
this.treeInfo.server.id,
|
||||
this.getCollNode('database').type + '/' + this.treeInfo.server._id,
|
||||
this.treeInfo.database.id,
|
||||
];
|
||||
|
||||
let prev_node_id = this.treeInfo.database._id;
|
||||
|
||||
/* add the slash to match regex, remove it from display path later */
|
||||
path = '/' + path;
|
||||
/* the below regex will match all /:server_group.1:/ */
|
||||
let new_path = path.replace(/\/:[a-zA-Z_]+\.[0-9]+:\//g, (token)=>{
|
||||
let orig_token = token;
|
||||
/* remove the slash and colon */
|
||||
token = token.slice(2, -2);
|
||||
let [node_type, node_oid, others] = token.split('.');
|
||||
if(typeof(others) !== 'undefined') {
|
||||
return token;
|
||||
}
|
||||
|
||||
/* schema type is "catalog" for catalog schemas */
|
||||
node_type = (['D', 'O'].indexOf(catalog_level) != -1 && node_type == 'schema') ? 'catalog' : node_type;
|
||||
|
||||
/* catalog like info schema will only have views and tables AKA catalog_object except for pg_catalog */
|
||||
node_type = (catalog_level === 'O' && ['view', 'table'].indexOf(node_type) != -1) ? 'catalog_object' : node_type;
|
||||
|
||||
/* If collection node present then add it */
|
||||
let coll_node = this.getCollNode(node_type);
|
||||
if(coll_node) {
|
||||
/* Add coll node to the path */
|
||||
if(prev_node_id != null) id_path.push(`${coll_node.type}/${prev_node_id}`);
|
||||
|
||||
/* Add the node to the path */
|
||||
id_path.push(`${node_type}/${node_oid}`);
|
||||
|
||||
/* This will be needed for coll node */
|
||||
prev_node_id = node_oid;
|
||||
|
||||
/* This will be displayed in the grid */
|
||||
return `/${coll_node.label}/`;
|
||||
} else if(node_type in this.pgBrowser.Nodes) {
|
||||
/* Add the node to the path */
|
||||
id_path.push(`${node_type}/${node_oid}`);
|
||||
|
||||
/* This will be need for coll node id path */
|
||||
prev_node_id = node_oid;
|
||||
|
||||
/* Remove the token and replace with slash. This will be displayed in the grid */
|
||||
return '/';
|
||||
}
|
||||
prev_node_id = null;
|
||||
return orig_token;
|
||||
});
|
||||
|
||||
/* Remove the slash we had added */
|
||||
new_path = new_path.substring(1);
|
||||
return [new_path, id_path];
|
||||
}
|
||||
|
||||
prepareDialog() {
|
||||
this.showMessage(null);
|
||||
this.setResultCount(0);
|
||||
if(this.grid) {
|
||||
this.grid.destroy();
|
||||
this.grid = null;
|
||||
}
|
||||
|
||||
/* Load types */
|
||||
this.setTypes([{
|
||||
id: -1,
|
||||
text: gettext('Loading...'),
|
||||
value: null,
|
||||
}], false);
|
||||
|
||||
axios.get(
|
||||
this.getBaseUrl('types')
|
||||
).then((res)=>{
|
||||
let types = [{
|
||||
id: 'all',
|
||||
text: 'All types',
|
||||
}];
|
||||
|
||||
for (const key of Object.keys(res.data.data).sort()) {
|
||||
types.push({
|
||||
id: key,
|
||||
text: res.data.data[key],
|
||||
});
|
||||
}
|
||||
this.setTypes(types);
|
||||
}).catch(()=>{
|
||||
this.setTypes([{
|
||||
id: -1,
|
||||
text: gettext('Failed'),
|
||||
value: null,
|
||||
}], false);
|
||||
});
|
||||
}
|
||||
|
||||
main(title) {
|
||||
this.set('title', title);
|
||||
}
|
||||
|
||||
setup() {
|
||||
return {
|
||||
buttons: [{
|
||||
text: '',
|
||||
key: 112,
|
||||
className: 'btn btn-secondary pull-left fa fa-question pg-alertify-icon-button',
|
||||
attrs: {
|
||||
name: 'dialog_help',
|
||||
type: 'button',
|
||||
label: gettext('Help'),
|
||||
'aria-label': gettext('Help'),
|
||||
url: url_for('help.static', {
|
||||
'filename': 'search_objects.html',
|
||||
}),
|
||||
},
|
||||
}, {
|
||||
text: gettext('Close'),
|
||||
key: 27,
|
||||
className: 'btn btn-secondary fa fa-lg fa-times pg-alertify-button',
|
||||
'data-btn-name': 'cancel',
|
||||
}],
|
||||
// Set options for dialog
|
||||
options: {
|
||||
title: this.dialogTitle,
|
||||
//disable both padding and overflow control.
|
||||
padding: !1,
|
||||
overflow: !1,
|
||||
model: 0,
|
||||
resizable: true,
|
||||
maximizable: true,
|
||||
pinnable: false,
|
||||
closableByDimmer: false,
|
||||
modal: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
build() {
|
||||
let tmpEle = document.createElement('div');
|
||||
tmpEle.innerHTML = this.dialogContainerSelector;
|
||||
let dialogContainer = tmpEle.firstChild;
|
||||
|
||||
// Append the container
|
||||
this.elements.content.innerHTML = '';
|
||||
this.elements.content.appendChild(dialogContainer);
|
||||
|
||||
this.createDialogDOM(dialogContainer);
|
||||
this.alertify.pgDialogBuild.apply(this);
|
||||
|
||||
this.loader = dialogContainer.getElementsByClassName('pg-sp-container')[0];
|
||||
|
||||
this.searchBox = dialogContainer.querySelector('#txtGridSearch');
|
||||
this.searchBtn = dialogContainer.querySelector('.btn-search');
|
||||
this.typesSelect = dialogContainer.querySelector('.node-types');
|
||||
this.searchResultContainer = dialogContainer.querySelector('.search-result-container');
|
||||
this.searchResult = dialogContainer.querySelector('.search-result');
|
||||
this.searchResultCount = dialogContainer.querySelector('.search-result-count');
|
||||
this.statusBar = dialogContainer.querySelector('.pg-prop-status-bar');
|
||||
|
||||
/* These two values are required to come out of grid when tab is
|
||||
* pressed in the grid. Slickgrid does not allow any way to come out
|
||||
*/
|
||||
this.nextToGrid = this.elements.footer.querySelector('.ajs-button');
|
||||
this.prevToGrid = this.typesSelect;
|
||||
|
||||
/* init select2 */
|
||||
this.setTypes([{
|
||||
id: -1,
|
||||
text: gettext('Loading...'),
|
||||
value: null,
|
||||
}], false);
|
||||
|
||||
/* on search box change */
|
||||
this.searchBox.addEventListener('input', ()=>{
|
||||
if(this.searchBoxVal().length >= 3) {
|
||||
this.searchBtnEnabled(true);
|
||||
} else {
|
||||
this.searchBtnEnabled(false);
|
||||
}
|
||||
});
|
||||
|
||||
/* on enter key press */
|
||||
this.searchBox.addEventListener('keypress', (e)=>{
|
||||
if(e.keyCode == 13) {
|
||||
e.stopPropagation();
|
||||
if(this.searchBtnEnabled()) {
|
||||
this.searchBtn.dispatchEvent(new Event('click'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* on search button click */
|
||||
this.searchBtn.addEventListener('click', ()=>{
|
||||
this.searchBtnEnabled(false);
|
||||
this.setGridData([]);
|
||||
this.showMessage(null);
|
||||
|
||||
this.setLoading(gettext('Searching....'));
|
||||
axios.get(this.getBaseUrl('search'), {
|
||||
params: {
|
||||
text: this.searchBoxVal(),
|
||||
type: this.typesVal(),
|
||||
},
|
||||
}).then((res)=>{
|
||||
let grid_data = res.data.data.map((row)=>{
|
||||
return this.finaliseData(row);
|
||||
});
|
||||
|
||||
this.setGridData(grid_data);
|
||||
}).catch((error)=>{
|
||||
let errmsg = '';
|
||||
|
||||
if (error.response) {
|
||||
errmsg = error.response.statusText;
|
||||
} else if (error.request) {
|
||||
errmsg = gettext('No response received');
|
||||
} else {
|
||||
errmsg = error.message;
|
||||
}
|
||||
this.showMessage(gettext('An unexpected occurred: %s', errmsg), true);
|
||||
console.warn(error);
|
||||
}).finally(()=>{
|
||||
this.setLoading(null);
|
||||
this.searchBtnEnabled(true);
|
||||
});
|
||||
});
|
||||
|
||||
this.set({
|
||||
'onresized': this.onDialogResize.bind(this),
|
||||
'onmaximized': this.onDialogResize.bind(this),
|
||||
'onrestored': this.onDialogResize.bind(this),
|
||||
'onshow': this.onDialogShow.bind(this),
|
||||
});
|
||||
}
|
||||
|
||||
prepare() {
|
||||
let selectedTreeNode = this.getSelectedNode();
|
||||
if (!this.getSelectedNodeData(selectedTreeNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.treeInfo = getTreeNodeHierarchyFromElement(this.pgBrowser, selectedTreeNode);
|
||||
this.prepareDialog();
|
||||
this.focusOnDialog(this);
|
||||
}
|
||||
|
||||
callback(event) {
|
||||
if (this.wasHelpButtonPressed(event)) {
|
||||
event.cancel = true;
|
||||
this.pgBrowser.showHelp(
|
||||
event.button.element.name,
|
||||
event.button.element.getAttribute('url'),
|
||||
null,
|
||||
null,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,122 @@
|
||||
.search_objects_dialog {
|
||||
height: 100%;
|
||||
|
||||
.object-other-info {
|
||||
&:hover {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.pref-dialog-link {
|
||||
color: $color-fg !important;
|
||||
text-decoration: underline !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-result-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.node-types ~ .select2-container {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.search-result-count {
|
||||
border-top: $panel-border;
|
||||
}
|
||||
|
||||
.ui-widget {
|
||||
font-family: $font-family-primary;
|
||||
font-size: $font-size-base;
|
||||
|
||||
.slick-header.ui-state-default {
|
||||
border: $table-border-width solid $table-border-color;
|
||||
.slick-header-columns {
|
||||
background: $table-bg;
|
||||
color: $color-fg;
|
||||
border-bottom: $panel-border;
|
||||
|
||||
.slick-header-column-sorted {
|
||||
font-style: unset;
|
||||
}
|
||||
|
||||
.ui-state-default {
|
||||
background: $table-bg !important;
|
||||
color: $color-fg !important;
|
||||
padding: $table-header-cell-padding $table-cell-padding;
|
||||
border-right: $table-border-width solid $table-border-color;
|
||||
|
||||
.slick-column-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.slick-sort-indicator {
|
||||
float: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.slick-header-sortable {
|
||||
cursor: pointer !important;
|
||||
|
||||
.slick-sort-indicator-asc {
|
||||
background: none;
|
||||
border-top: none;
|
||||
border-right: 0.25rem solid transparent;
|
||||
border-bottom: 0.25rem solid $color-fg;
|
||||
border-left: 0.25rem solid transparent;
|
||||
}
|
||||
|
||||
.slick-sort-indicator-desc {
|
||||
background: none;
|
||||
border-top: 0.25rem solid $color-fg;
|
||||
border-right: 0.25rem solid transparent;
|
||||
border-bottom: none;
|
||||
border-left: 0.25rem solid transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ui-widget-content {
|
||||
color: $color-fg;
|
||||
&.slick-row {
|
||||
&.object-muted {
|
||||
&.active, &.active:hover, &:hover, & {
|
||||
.slick-cell {
|
||||
color: $text-muted !important;
|
||||
cursor: default !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.active, &.active:hover {
|
||||
.slick-cell {
|
||||
border-top: $table-border-width solid transparent !important;
|
||||
background-color: $tree-bg-selected !important;
|
||||
color: $tree-fg-selected !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
.slick-cell {
|
||||
border-top: $table-border-width solid transparent !important;
|
||||
border-bottom: $table-border-width solid transparent !important;
|
||||
background-color: $tree-bg-hover !important;
|
||||
color: $tree-fg-hover !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.pg-prop-status-bar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
@@ -0,0 +1,435 @@
|
||||
{% import 'catalog/pg/macros/catalogs.sql' as CATALOGS %}
|
||||
{% set all_obj = false %}
|
||||
{% if obj_type == 'all' or obj_type is none %}
|
||||
{% set all_obj = true %}
|
||||
{% endif %}
|
||||
SELECT obj_type, obj_name,
|
||||
REPLACE(obj_path, '/'||sn.schema_name||'/', '/'||{{ CATALOGS.LABELS_SCHEMACOL('sn.schema_name', _) }}||'/') AS obj_path,
|
||||
schema_name, show_node, other_info,
|
||||
CASE
|
||||
WHEN {{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }} THEN
|
||||
CASE WHEN {{ CATALOGS.DB_SUPPORT_SCHEMACOL('sn.schema_name') }} THEN 'D' ELSE 'O' END
|
||||
ELSE 'N'
|
||||
END AS catalog_level
|
||||
FROM (
|
||||
{% if all_obj or obj_type in ['sequence', 'view', 'mview'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN 'sequence'
|
||||
WHEN c.relkind = 'v' THEN 'view'
|
||||
WHEN c.relkind = 'm' THEN 'mview'
|
||||
ELSE 'should not happen'
|
||||
END::text AS obj_type, c.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' ||
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN ':sequence.'
|
||||
WHEN c.relkind = 'v' THEN ':view.'
|
||||
WHEN c.relkind = 'm' THEN ':mview.'
|
||||
ELSE 'should not happen'
|
||||
END || c.oid ||':/' || c.relname AS obj_path, n.nspname AS schema_name,
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN {{ show_node_prefs['sequence'] }}
|
||||
WHEN c.relkind = 'v' THEN {{ show_node_prefs['view'] }}
|
||||
WHEN c.relkind = 'm' THEN {{ show_node_prefs['mview'] }}
|
||||
ELSE False
|
||||
END AS show_node, NULL AS other_info
|
||||
FROM pg_class c
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
{% if all_obj %}
|
||||
WHERE c.relkind in ('S','v','m')
|
||||
{% elif obj_type == 'sequence' %}
|
||||
WHERE c.relkind = 'S'
|
||||
{% elif obj_type == 'view' %}
|
||||
WHERE c.relkind = 'v'
|
||||
{% elif obj_type == 'mview' %}
|
||||
WHERE c.relkind = 'm'
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['table', 'partition'] %}
|
||||
SELECT CASE WHEN c.relispartition THEN 'partition' ELSE 'table' END::text AS obj_type, c.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' || (
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select c.oid as oid, 0 as height,
|
||||
CASE c.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || c.oid || ':/' || c.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
) obj_path, n.nspname AS schema_name,
|
||||
CASE WHEN c.relispartition THEN {{ show_node_prefs['partition'] }}
|
||||
ELSE {{ show_node_prefs['table'] }} END AS show_node,
|
||||
NULL AS other_info
|
||||
FROM pg_class c
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relkind in ('p','r')
|
||||
{% if obj_type == 'table' %}
|
||||
AND NOT c.relispartition
|
||||
{% elif obj_type == 'partition' %}
|
||||
AND c.relispartition
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['index'] %}
|
||||
SELECT 'index'::text AS obj_type, cls.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/:table.'|| tab.oid ||':/' || tab.relname || '/:index.'|| cls.oid ||':/' || cls.relname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_index idx
|
||||
JOIN pg_class cls ON cls.oid=indexrelid
|
||||
JOIN pg_class tab ON tab.oid=indrelid
|
||||
JOIN pg_namespace n ON n.oid=tab.relnamespace
|
||||
LEFT JOIN pg_depend dep ON (dep.classid = cls.tableoid AND dep.objid = cls.oid AND dep.refobjsubid = '0' AND dep.refclassid=(SELECT oid FROM pg_class WHERE relname='pg_constraint') AND dep.deptype='i')
|
||||
LEFT OUTER JOIN pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid)
|
||||
LEFT OUTER JOIN pg_description des ON des.objoid=cls.oid
|
||||
LEFT OUTER JOIN pg_description desp ON (desp.objoid=con.oid AND desp.objsubid = 0)
|
||||
WHERE contype IS NULL
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger_function', 'function'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN t.typname IN ('trigger', 'event_trigger') THEN 'trigger_function'
|
||||
ELSE 'function' END::text AS obj_type, p.proname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' || case when t.typname = 'trigger' then ':trigger_function.' else ':function.' end || p.oid ||':/' || p.proname AS obj_path, n.nspname AS schema_name,
|
||||
CASE WHEN t.typname IN ('trigger', 'event_trigger') THEN {{ show_node_prefs['trigger_function'] }} ELSE {{ show_node_prefs['function'] }} END AS show_node,
|
||||
pg_catalog.pg_get_function_identity_arguments(p.oid) AS other_info
|
||||
from pg_proc p
|
||||
left join pg_namespace n on p.pronamespace = n.oid
|
||||
left join pg_type t on p.prorettype = t.oid
|
||||
WHERE ({{ CATALOGS.DB_SUPPORT('n') }})
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['event_trigger'] %}
|
||||
select 'event_trigger'::text AS obj_type, evtname AS obj_name, ':event_trigger.'||oid||':/' || evtname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info from pg_event_trigger
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['schema'] %}
|
||||
select 'schema'::text AS obj_type, n.nspname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname as obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['schema'] }} AS show_node, NULL AS other_info from pg_namespace n
|
||||
where {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['column'] %}
|
||||
select 'column'::text AS obj_type, a.attname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname || '/' ||
|
||||
case
|
||||
WHEN t.relkind in ('r', 'p') THEN ':table.'
|
||||
WHEN t.relkind = 'v' THEN ':view.'
|
||||
WHEN t.relkind = 'm' THEN ':mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname || '/:column.'|| a.attnum ||':/' || a.attname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['column'] }} AS show_node, NULL AS other_info
|
||||
from pg_attribute a
|
||||
inner join pg_class t on a.attrelid = t.oid and t.relkind in ('r','p','v','m')
|
||||
left join pg_namespace n on t.relnamespace = n.oid where a.attnum > 0
|
||||
and not t.relispartition
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['constraints', 'check_constraint', 'foreign_key', 'primary_key', 'unique_constraint', 'exclusion_constraint'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN 'check_constraint'
|
||||
WHEN c.contype = 'f' THEN 'foreign_key'
|
||||
WHEN c.contype = 'p' THEN 'primary_key'
|
||||
WHEN c.contype = 'u' THEN 'unique_constraint'
|
||||
WHEN c.contype = 'x' THEN 'exclusion_constraint'
|
||||
END::text AS obj_type,
|
||||
case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname||'/'||
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
) ||
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN '/:check_constraint.' ||c.oid
|
||||
WHEN c.contype = 'f' THEN '/:foreign_key.' ||c.conindid
|
||||
WHEN c.contype = 'p' THEN '/:primary_key.' ||c.conindid
|
||||
WHEN c.contype = 'u' THEN '/:unique_constraint.' ||c.conindid
|
||||
WHEN c.contype = 'x' THEN '/:exclusion_constraint.' ||c.conindid
|
||||
END ||':/'|| case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['constraints'] }} AS show_node, NULL AS other_info
|
||||
from pg_constraint c
|
||||
left join pg_class t on c.conrelid = t.oid
|
||||
left join pg_class tf on c.confrelid = tf.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where c.contypid = 0
|
||||
{% if obj_type == 'check_constraint' %}
|
||||
AND c.contype = 'c'
|
||||
{% elif obj_type == 'foreign_key' %}
|
||||
AND c.contype = 'f'
|
||||
{% elif obj_type == 'primary_key' %}
|
||||
AND c.contype = 'p'
|
||||
{% elif obj_type == 'unique_constraint' %}
|
||||
AND c.contype = 'u'
|
||||
{% elif obj_type == 'exclusion_constraint' %}
|
||||
AND c.contype = 'x'
|
||||
{% else %}
|
||||
AND c.contype IN ('c', 'f', 'p', 'u', 'x')
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['rule'] %}
|
||||
select 'rule'::text AS obj_type, r.rulename AS obj_name, ':schema.'||n.oid||':/' || n.nspname|| '/' ||
|
||||
case
|
||||
when t.relkind = 'v' then ':view.'
|
||||
when t.relkind = 'm' then ':mview.'
|
||||
WHEN t.relkind in ('r', 'p') THEN
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
)
|
||||
end
|
||||
||'/:rule.'||r.oid||':/'|| r.rulename AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['rule'] }} AS show_node, NULL AS other_info
|
||||
from pg_rewrite r
|
||||
left join pg_class t on r.ev_class = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger'] %}
|
||||
select 'trigger'::text AS obj_type, tr.tgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname|| '/' ||
|
||||
case
|
||||
when t.relkind = 'v' then ':view.'
|
||||
when t.relkind = 'm' then ':mview.'
|
||||
WHEN t.relkind in ('r', 'p') THEN
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
)
|
||||
end || '/:trigger.'|| tr.oid || ':/' || tr.tgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['trigger'] }} AS show_node, NULL AS other_info
|
||||
from pg_trigger tr
|
||||
left join pg_class t on tr.tgrelid = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where tr.tgisinternal = false
|
||||
and {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['type'] %}
|
||||
SELECT 'type'::text AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname ||
|
||||
'/:type.'|| t.oid ||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['type'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_type t
|
||||
LEFT OUTER JOIN pg_type e ON e.oid=t.typelem
|
||||
LEFT OUTER JOIN pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c'
|
||||
LEFT OUTER JOIN pg_namespace n on t.typnamespace = n.oid
|
||||
WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%'
|
||||
{% if not show_system_objects %}
|
||||
AND ct.oid is NULL
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['cast'] %}
|
||||
SELECT 'cast'::text AS obj_type, format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_name,
|
||||
':cast.'||ca.oid||':/' || format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['cast'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_cast ca
|
||||
JOIN pg_type st ON st.oid=castsource
|
||||
JOIN pg_type tt ON tt.oid=casttarget
|
||||
{% if not show_system_objects %}
|
||||
WHERE ca.oid > {{last_system_oid}}::OID
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['language'] %}
|
||||
SELECT 'language'::text AS obj_type, lanname AS obj_name, ':language.'||lan.oid||':/' || lanname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['language'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_language lan
|
||||
WHERE lanispl IS TRUE
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_configuration'] %}
|
||||
SELECT 'fts_configuration'::text AS obj_type, cfg.cfgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:fts_configuration.'||cfg.oid||':/' || cfg.cfgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_configuration'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_config cfg
|
||||
left join pg_namespace n on cfg.cfgnamespace = n.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_dictionary'] %}
|
||||
SELECT 'fts_dictionary' AS obj_type, dict.dictname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_dictionary.'||dict.oid||':/' || dict.dictname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_dictionary'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_dict dict
|
||||
left join pg_namespace ns on dict.dictnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_parser'] %}
|
||||
SELECT 'fts_parser' AS obj_type, prs.prsname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_parser.'||prs.oid||':/' || prs.prsname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_parser'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_parser prs
|
||||
left join pg_namespace ns on prs.prsnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_template'] %}
|
||||
SELECT 'fts_template' AS obj_type, tmpl.tmplname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_template.'||tmpl.oid||':/' || tmpl.tmplname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_template'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_template tmpl
|
||||
left join pg_namespace ns on tmpl.tmplnamespace = ns.oid
|
||||
AND {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain'] %}
|
||||
select 'domain' AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain'] }} AS show_node, NULL AS other_info
|
||||
from pg_type t
|
||||
inner join pg_namespace n on t.typnamespace = n.oid
|
||||
where t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain_constraints'] %}
|
||||
SELECT 'domain_constraints' AS obj_type,
|
||||
c.conname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname || '/:domain_constraints.'||c.oid||':/' || c.conname AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain_constraints'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_constraint c JOIN pg_type t
|
||||
ON t.oid=contypid JOIN pg_namespace n
|
||||
ON n.oid=t.typnamespace
|
||||
WHERE t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_data_wrapper'] %}
|
||||
select 'foreign_data_wrapper' AS obj_type, fdwname AS obj_name, ':foreign_data_wrapper.'||oid||':/' || fdwname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_data_wrapper'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_data_wrapper
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_server'] %}
|
||||
select 'foreign_server' AS obj_type, sr.srvname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_server'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_server sr
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['user_mapping'] %}
|
||||
select 'user_mapping' AS obj_type, ro.rolname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname || '/:user_mapping.'||ro.oid||':/' || ro.rolname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['user_mapping'] }} AS show_node, NULL AS other_info
|
||||
from pg_user_mapping um
|
||||
inner join pg_roles ro on um.umuser = ro.oid
|
||||
inner join pg_foreign_server sr on um.umserver = sr.oid
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_table'] %}
|
||||
select 'foreign_table' AS obj_type, c.relname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:foreign_table.'||c.oid||':/' || c.relname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['foreign_table'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_table ft
|
||||
inner join pg_class c on ft.ftrelid = c.oid
|
||||
inner join pg_namespace ns on c.relnamespace = ns.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['extension'] %}
|
||||
select 'extension' AS obj_type, x.extname AS obj_name, ':extension.'||x.oid||':/' || x.extname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['extension'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_extension x
|
||||
JOIN pg_namespace n on x.extnamespace=n.oid
|
||||
join pg_available_extensions() e(name, default_version, comment) ON x.extname=e.name
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['collation'] %}
|
||||
SELECT 'collation' AS obj_type, c.collname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:collation.'||c.oid||':/' || c.collname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['collation'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_collation c
|
||||
JOIN pg_namespace n ON n.oid=c.collnamespace
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
|
||||
) sn
|
||||
where lower(sn.obj_name) like '%{{ search_text }}%'
|
||||
{% if not show_system_objects %}
|
||||
AND NOT ({{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }})
|
||||
AND (sn.schema_name IS NOT NULL AND sn.schema_name NOT LIKE 'pg\_%')
|
||||
{% endif %}
|
||||
ORDER BY 1, 2, 3
|
@@ -0,0 +1,452 @@
|
||||
{% import 'catalog/pg/macros/catalogs.sql' as CATALOGS %}
|
||||
{% set all_obj = false %}
|
||||
{% if obj_type == 'all' or obj_type is none %}
|
||||
{% set all_obj = true %}
|
||||
{% endif %}
|
||||
SELECT obj_type, obj_name,
|
||||
REPLACE(obj_path, '/'||sn.schema_name||'/', '/'||{{ CATALOGS.LABELS_SCHEMACOL('sn.schema_name', _) }}||'/') AS obj_path,
|
||||
schema_name, show_node, other_info,
|
||||
CASE
|
||||
WHEN {{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }} THEN
|
||||
CASE WHEN {{ CATALOGS.DB_SUPPORT_SCHEMACOL('sn.schema_name') }} THEN 'D' ELSE 'O' END
|
||||
ELSE 'N'
|
||||
END AS catalog_level
|
||||
FROM (
|
||||
{% if all_obj or obj_type in ['sequence', 'view', 'mview'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN 'sequence'
|
||||
WHEN c.relkind = 'v' THEN 'view'
|
||||
WHEN c.relkind = 'm' THEN 'mview'
|
||||
ELSE 'should not happen'
|
||||
END::text AS obj_type, c.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' ||
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN ':sequence.'
|
||||
WHEN c.relkind = 'v' THEN ':view.'
|
||||
WHEN c.relkind = 'm' THEN ':mview.'
|
||||
ELSE 'should not happen'
|
||||
END || c.oid ||':/' || c.relname AS obj_path, n.nspname AS schema_name,
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN {{ show_node_prefs['sequence'] }}
|
||||
WHEN c.relkind = 'v' THEN {{ show_node_prefs['view'] }}
|
||||
WHEN c.relkind = 'm' THEN {{ show_node_prefs['mview'] }}
|
||||
ELSE False
|
||||
END AS show_node, NULL AS other_info
|
||||
FROM pg_class c
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
{% if all_obj %}
|
||||
WHERE c.relkind in ('S','v','m')
|
||||
{% elif obj_type == 'sequence' %}
|
||||
WHERE c.relkind = 'S'
|
||||
{% elif obj_type == 'view' %}
|
||||
WHERE c.relkind = 'v'
|
||||
{% elif obj_type == 'mview' %}
|
||||
WHERE c.relkind = 'm'
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['table', 'partition'] %}
|
||||
SELECT CASE WHEN c.relispartition THEN 'partition' ELSE 'table' END::text AS obj_type, c.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' || (
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select c.oid as oid, 0 as height,
|
||||
CASE c.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || c.oid || ':/' || c.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
) obj_path, n.nspname AS schema_name,
|
||||
CASE WHEN c.relispartition THEN {{ show_node_prefs['partition'] }}
|
||||
ELSE {{ show_node_prefs['table'] }} END AS show_node,
|
||||
NULL AS other_info
|
||||
FROM pg_class c
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relkind in ('p','r')
|
||||
{% if obj_type == 'table' %}
|
||||
AND NOT c.relispartition
|
||||
{% elif obj_type == 'partition' %}
|
||||
AND c.relispartition
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['index'] %}
|
||||
SELECT 'index'::text AS obj_type, cls.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/:table.'|| tab.oid ||':/' || tab.relname || '/:index.'|| cls.oid ||':/' || cls.relname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_index idx
|
||||
JOIN pg_class cls ON cls.oid=indexrelid
|
||||
JOIN pg_class tab ON tab.oid=indrelid
|
||||
JOIN pg_namespace n ON n.oid=tab.relnamespace
|
||||
LEFT JOIN pg_depend dep ON (dep.classid = cls.tableoid AND dep.objid = cls.oid AND dep.refobjsubid = '0' AND dep.refclassid=(SELECT oid FROM pg_class WHERE relname='pg_constraint') AND dep.deptype='i')
|
||||
LEFT OUTER JOIN pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid)
|
||||
LEFT OUTER JOIN pg_description des ON des.objoid=cls.oid
|
||||
LEFT OUTER JOIN pg_description desp ON (desp.objoid=con.oid AND desp.objsubid = 0)
|
||||
WHERE contype IS NULL
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger_function', 'function', 'procedure'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN t.typname IN ('trigger', 'event_trigger') THEN 'trigger_function'
|
||||
WHEN p.prokind = 'p' THEN 'procedure'
|
||||
ELSE 'function'
|
||||
END::text AS obj_type, p.proname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' ||
|
||||
CASE
|
||||
WHEN t.typname IN ('trigger', 'event_trigger') THEN ':trigger_function.'
|
||||
WHEN p.prokind = 'p' THEN ':procedure.'
|
||||
ELSE ':function.'
|
||||
END || p.oid ||':/' || p.proname AS obj_path, n.nspname AS schema_name,
|
||||
CASE
|
||||
WHEN t.typname IN ('trigger', 'event_trigger') THEN {{ show_node_prefs['trigger_function'] }}
|
||||
WHEN p.prokind = 'p' THEN {{ show_node_prefs['procedure'] }}
|
||||
ELSE {{ show_node_prefs['function'] }}
|
||||
END AS show_node,
|
||||
pg_catalog.pg_get_function_identity_arguments(p.oid) AS other_info
|
||||
from pg_proc p join pg_namespace n
|
||||
on p.pronamespace = n.oid join pg_type t
|
||||
on p.prorettype = t.oid join pg_language lng
|
||||
ON lng.oid=p.prolang
|
||||
WHERE p.prokind IN ('f', 'w', 'p')
|
||||
AND CASE
|
||||
WHEN t.typname IN ('trigger', 'event_trigger') THEN lng.lanname NOT IN ('edbspl', 'sql', 'internal')
|
||||
ELSE true
|
||||
END
|
||||
AND ({{ CATALOGS.DB_SUPPORT('n') }})
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['event_trigger'] %}
|
||||
select 'event_trigger'::text AS obj_type, evtname AS obj_name, ':event_trigger.'||oid||':/' || evtname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info from pg_event_trigger
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['schema'] %}
|
||||
select 'schema'::text AS obj_type, n.nspname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname as obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['schema'] }} AS show_node, NULL AS other_info from pg_namespace n
|
||||
where {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['column'] %}
|
||||
select 'column'::text AS obj_type, a.attname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname || '/' ||
|
||||
case
|
||||
WHEN t.relkind in ('r', 'p') THEN ':table.'
|
||||
WHEN t.relkind = 'v' THEN ':view.'
|
||||
WHEN t.relkind = 'm' THEN ':mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname || '/:column.'|| a.attnum ||':/' || a.attname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['column'] }} AS show_node, NULL AS other_info
|
||||
from pg_attribute a
|
||||
inner join pg_class t on a.attrelid = t.oid and t.relkind in ('r','p','v','m')
|
||||
left join pg_namespace n on t.relnamespace = n.oid where a.attnum > 0
|
||||
and not t.relispartition
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['constraints', 'check_constraint', 'foreign_key', 'primary_key', 'unique_constraint', 'exclusion_constraint'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN 'check_constraint'
|
||||
WHEN c.contype = 'f' THEN 'foreign_key'
|
||||
WHEN c.contype = 'p' THEN 'primary_key'
|
||||
WHEN c.contype = 'u' THEN 'unique_constraint'
|
||||
WHEN c.contype = 'x' THEN 'exclusion_constraint'
|
||||
END::text AS obj_type,
|
||||
case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname||'/'||
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
) ||
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN '/:check_constraint.' ||c.oid
|
||||
WHEN c.contype = 'f' THEN '/:foreign_key.' ||c.conindid
|
||||
WHEN c.contype = 'p' THEN '/:primary_key.' ||c.conindid
|
||||
WHEN c.contype = 'u' THEN '/:unique_constraint.' ||c.conindid
|
||||
WHEN c.contype = 'x' THEN '/:exclusion_constraint.' ||c.conindid
|
||||
END ||':/'|| case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['constraints'] }} AS show_node, NULL AS other_info
|
||||
from pg_constraint c
|
||||
left join pg_class t on c.conrelid = t.oid
|
||||
left join pg_class tf on c.confrelid = tf.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where c.contypid = 0
|
||||
{% if obj_type == 'check_constraint' %}
|
||||
AND c.contype = 'c'
|
||||
{% elif obj_type == 'foreign_key' %}
|
||||
AND c.contype = 'f'
|
||||
{% elif obj_type == 'primary_key' %}
|
||||
AND c.contype = 'p'
|
||||
{% elif obj_type == 'unique_constraint' %}
|
||||
AND c.contype = 'u'
|
||||
{% elif obj_type == 'exclusion_constraint' %}
|
||||
AND c.contype = 'x'
|
||||
{% else %}
|
||||
AND c.contype IN ('c', 'f', 'p', 'u', 'x')
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['rule'] %}
|
||||
select 'rule'::text AS obj_type, r.rulename AS obj_name, ':schema.'||n.oid||':/' || n.nspname|| '/' ||
|
||||
case
|
||||
when t.relkind = 'v' then ':view.'
|
||||
when t.relkind = 'm' then ':mview.'
|
||||
WHEN t.relkind in ('r', 'p') THEN
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
)
|
||||
end
|
||||
||'/:rule.'||r.oid||':/'|| r.rulename AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['rule'] }} AS show_node, NULL AS other_info
|
||||
from pg_rewrite r
|
||||
left join pg_class t on r.ev_class = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger'] %}
|
||||
select 'trigger'::text AS obj_type, tr.tgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname|| '/' ||
|
||||
case
|
||||
when t.relkind = 'v' then ':view.'
|
||||
when t.relkind = 'm' then ':mview.'
|
||||
WHEN t.relkind in ('r', 'p') THEN
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
)
|
||||
end || '/:trigger.'|| tr.oid || ':/' || tr.tgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['trigger'] }} AS show_node, NULL AS other_info
|
||||
from pg_trigger tr
|
||||
left join pg_class t on tr.tgrelid = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where tr.tgisinternal = false
|
||||
and {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['type'] %}
|
||||
SELECT 'type'::text AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname ||
|
||||
'/:type.'|| t.oid ||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['type'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_type t
|
||||
LEFT OUTER JOIN pg_type e ON e.oid=t.typelem
|
||||
LEFT OUTER JOIN pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c'
|
||||
LEFT OUTER JOIN pg_namespace n on t.typnamespace = n.oid
|
||||
WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%'
|
||||
{% if not show_system_objects %}
|
||||
AND ct.oid is NULL
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['cast'] %}
|
||||
SELECT 'cast'::text AS obj_type, format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_name,
|
||||
':cast.'||ca.oid||':/' || format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['cast'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_cast ca
|
||||
JOIN pg_type st ON st.oid=castsource
|
||||
JOIN pg_type tt ON tt.oid=casttarget
|
||||
{% if not show_system_objects %}
|
||||
WHERE ca.oid > {{last_system_oid}}::OID
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['language'] %}
|
||||
SELECT 'language'::text AS obj_type, lanname AS obj_name, ':language.'||lan.oid||':/' || lanname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['language'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_language lan
|
||||
WHERE lanispl IS TRUE
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_configuration'] %}
|
||||
SELECT 'fts_configuration'::text AS obj_type, cfg.cfgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:fts_configuration.'||cfg.oid||':/' || cfg.cfgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_configuration'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_config cfg
|
||||
left join pg_namespace n on cfg.cfgnamespace = n.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_dictionary'] %}
|
||||
SELECT 'fts_dictionary' AS obj_type, dict.dictname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_dictionary.'||dict.oid||':/' || dict.dictname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_dictionary'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_dict dict
|
||||
left join pg_namespace ns on dict.dictnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_parser'] %}
|
||||
SELECT 'fts_parser' AS obj_type, prs.prsname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_parser.'||prs.oid||':/' || prs.prsname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_parser'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_parser prs
|
||||
left join pg_namespace ns on prs.prsnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_template'] %}
|
||||
SELECT 'fts_template' AS obj_type, tmpl.tmplname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_template.'||tmpl.oid||':/' || tmpl.tmplname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_template'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_template tmpl
|
||||
left join pg_namespace ns on tmpl.tmplnamespace = ns.oid
|
||||
AND {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain'] %}
|
||||
select 'domain' AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain'] }} AS show_node, NULL AS other_info
|
||||
from pg_type t
|
||||
inner join pg_namespace n on t.typnamespace = n.oid
|
||||
where t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain_constraints'] %}
|
||||
SELECT 'domain_constraints' AS obj_type,
|
||||
c.conname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname || '/:domain_constraints.'||c.oid||':/' || c.conname AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain_constraints'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_constraint c JOIN pg_type t
|
||||
ON t.oid=contypid JOIN pg_namespace n
|
||||
ON n.oid=t.typnamespace
|
||||
WHERE t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_data_wrapper'] %}
|
||||
select 'foreign_data_wrapper' AS obj_type, fdwname AS obj_name, ':foreign_data_wrapper.'||oid||':/' || fdwname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_data_wrapper'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_data_wrapper
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_server'] %}
|
||||
select 'foreign_server' AS obj_type, sr.srvname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_server'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_server sr
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['user_mapping'] %}
|
||||
select 'user_mapping' AS obj_type, ro.rolname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname || '/:user_mapping.'||ro.oid||':/' || ro.rolname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['user_mapping'] }} AS show_node, NULL AS other_info
|
||||
from pg_user_mapping um
|
||||
inner join pg_roles ro on um.umuser = ro.oid
|
||||
inner join pg_foreign_server sr on um.umserver = sr.oid
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_table'] %}
|
||||
select 'foreign_table' AS obj_type, c.relname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:foreign_table.'||c.oid||':/' || c.relname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['foreign_table'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_table ft
|
||||
inner join pg_class c on ft.ftrelid = c.oid
|
||||
inner join pg_namespace ns on c.relnamespace = ns.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['extension'] %}
|
||||
select 'extension' AS obj_type, x.extname AS obj_name, ':extension.'||x.oid||':/' || x.extname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['extension'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_extension x
|
||||
JOIN pg_namespace n on x.extnamespace=n.oid
|
||||
join pg_available_extensions() e(name, default_version, comment) ON x.extname=e.name
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['collation'] %}
|
||||
SELECT 'collation' AS obj_type, c.collname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:collation.'||c.oid||':/' || c.collname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['collation'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_collation c
|
||||
JOIN pg_namespace n ON n.oid=c.collnamespace
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
|
||||
) sn
|
||||
where lower(sn.obj_name) like '%{{ search_text }}%'
|
||||
{% if not show_system_objects %}
|
||||
AND NOT ({{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }})
|
||||
AND (sn.schema_name IS NOT NULL AND sn.schema_name NOT LIKE 'pg\_%')
|
||||
{% endif %}
|
||||
ORDER BY 1, 2, 3
|
@@ -0,0 +1,367 @@
|
||||
{% import 'catalog/pg/macros/catalogs.sql' as CATALOGS %}
|
||||
{% set all_obj = false %}
|
||||
{% if obj_type == 'all' or obj_type is none %}
|
||||
{% set all_obj = true %}
|
||||
{% endif %}
|
||||
SELECT obj_type, obj_name,
|
||||
REPLACE(obj_path, '/'||sn.schema_name||'/', '/'||{{ CATALOGS.LABELS_SCHEMACOL('sn.schema_name', _) }}||'/') AS obj_path,
|
||||
schema_name, show_node, other_info,
|
||||
CASE
|
||||
WHEN {{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }} THEN
|
||||
CASE WHEN {{ CATALOGS.DB_SUPPORT_SCHEMACOL('sn.schema_name') }} THEN 'D' ELSE 'O' END
|
||||
ELSE 'N'
|
||||
END AS catalog_level
|
||||
FROM (
|
||||
{% if all_obj or obj_type in ['table', 'sequence', 'view', 'mview'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.relkind = 'r' THEN 'table'
|
||||
WHEN c.relkind = 'S' THEN 'sequence'
|
||||
WHEN c.relkind = 'v' THEN 'view'
|
||||
WHEN c.relkind = 'm' THEN 'mview'
|
||||
ELSE 'should not happen'
|
||||
END::text AS obj_type, c.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' ||
|
||||
CASE
|
||||
WHEN c.relkind = 'r' THEN ':table.'
|
||||
WHEN c.relkind = 'S' THEN ':sequence.'
|
||||
WHEN c.relkind = 'v' THEN ':view.'
|
||||
WHEN c.relkind = 'm' THEN ':mview.'
|
||||
ELSE 'should not happen'
|
||||
END || c.oid ||':/' || c.relname AS obj_path, n.nspname AS schema_name,
|
||||
CASE
|
||||
WHEN c.relkind = 'r' THEN {{ show_node_prefs['table'] }}
|
||||
WHEN c.relkind = 'S' THEN {{ show_node_prefs['sequence'] }}
|
||||
WHEN c.relkind = 'v' THEN {{ show_node_prefs['view'] }}
|
||||
WHEN c.relkind = 'm' THEN {{ show_node_prefs['mview'] }}
|
||||
ELSE False
|
||||
END AS show_node, NULL AS other_info
|
||||
FROM pg_class c
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
{% if all_obj %}
|
||||
WHERE c.relkind in ('r','S','v','m')
|
||||
{% elif obj_type == 'table' %}
|
||||
WHERE c.relkind = 'r'
|
||||
{% elif obj_type == 'sequence' %}
|
||||
WHERE c.relkind = 'S'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% elif obj_type == 'view' %}
|
||||
WHERE c.relkind = 'v'
|
||||
{% elif obj_type == 'mview' %}
|
||||
WHERE c.relkind = 'm'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['index'] %}
|
||||
SELECT 'index'::text AS obj_type, cls.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/:table.'|| tab.oid ||':/' || tab.relname || '/:index.'|| cls.oid ||':/' || cls.relname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_index idx
|
||||
JOIN pg_class cls ON cls.oid=indexrelid
|
||||
JOIN pg_class tab ON tab.oid=indrelid
|
||||
JOIN pg_namespace n ON n.oid=tab.relnamespace
|
||||
LEFT JOIN pg_depend dep ON (dep.classid = cls.tableoid AND dep.objid = cls.oid AND dep.refobjsubid = '0' AND dep.refclassid=(SELECT oid FROM pg_class WHERE relname='pg_constraint') AND dep.deptype='i')
|
||||
LEFT OUTER JOIN pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid)
|
||||
LEFT OUTER JOIN pg_description des ON des.objoid=cls.oid
|
||||
LEFT OUTER JOIN pg_description desp ON (desp.objoid=con.oid AND desp.objsubid = 0)
|
||||
WHERE contype IS NULL
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger_function', 'function'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN t.typname IN ('trigger', 'event_trigger') THEN 'trigger_function'
|
||||
ELSE 'function' END::text AS obj_type, p.proname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' || case when t.typname = 'trigger' then ':trigger_function.' else ':function.' end || p.oid ||':/' || p.proname AS obj_path, n.nspname AS schema_name,
|
||||
CASE WHEN t.typname IN ('trigger', 'event_trigger') THEN {{ show_node_prefs['trigger_function'] }} ELSE {{ show_node_prefs['function'] }} END AS show_node,
|
||||
pg_catalog.pg_get_function_identity_arguments(p.oid) AS other_info
|
||||
from pg_proc p
|
||||
left join pg_namespace n on p.pronamespace = n.oid
|
||||
left join pg_type t on p.prorettype = t.oid
|
||||
WHERE ({{ CATALOGS.DB_SUPPORT('n') }})
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['event_trigger'] %}
|
||||
select 'event_trigger'::text AS obj_type, evtname AS obj_name, ':event_trigger.'||oid||':/' || evtname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info from pg_event_trigger
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['schema'] %}
|
||||
select 'schema'::text AS obj_type, n.nspname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname as obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['schema'] }} AS show_node, NULL AS other_info from pg_namespace n
|
||||
where {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['column'] %}
|
||||
select 'column'::text AS obj_type, a.attname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname || '/' ||
|
||||
case
|
||||
WHEN t.relkind = 'r' THEN ':table.'
|
||||
WHEN t.relkind = 'v' THEN ':view.'
|
||||
WHEN t.relkind = 'm' THEN ':mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname || '/:column.'|| a.attnum ||':/' || a.attname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['column'] }} AS show_node, NULL AS other_info
|
||||
from pg_attribute a
|
||||
inner join pg_class t on a.attrelid = t.oid and t.relkind in ('r','v','m')
|
||||
left join pg_namespace n on t.relnamespace = n.oid where a.attnum > 0
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['constraints', 'check_constraint', 'foreign_key', 'primary_key', 'unique_constraint', 'exclusion_constraint'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN 'check_constraint'
|
||||
WHEN c.contype = 'f' THEN 'foreign_key'
|
||||
WHEN c.contype = 'p' THEN 'primary_key'
|
||||
WHEN c.contype = 'u' THEN 'unique_constraint'
|
||||
WHEN c.contype = 'x' THEN 'exclusion_constraint'
|
||||
END::text AS obj_type,
|
||||
case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname||'/:table.'|| t.oid || ':/'||t.relname||
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN '/:check_constraint.' ||c.oid
|
||||
WHEN c.contype = 'f' THEN '/:foreign_key.' ||c.conindid
|
||||
WHEN c.contype = 'p' THEN '/:primary_key.' ||c.conindid
|
||||
WHEN c.contype = 'u' THEN '/:unique_constraint.' ||c.conindid
|
||||
WHEN c.contype = 'x' THEN '/:exclusion_constraint.' ||c.conindid
|
||||
END ||':/'|| case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['constraints'] }} AS show_node, NULL AS other_info
|
||||
from pg_constraint c
|
||||
left join pg_class t on c.conrelid = t.oid
|
||||
left join pg_class tf on c.confrelid = tf.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where c.contypid = 0
|
||||
{% if obj_type == 'check_constraint' %}
|
||||
AND c.contype = 'c'
|
||||
{% elif obj_type == 'foreign_key' %}
|
||||
AND c.contype = 'f'
|
||||
{% elif obj_type == 'primary_key' %}
|
||||
AND c.contype = 'p'
|
||||
{% elif obj_type == 'unique_constraint' %}
|
||||
AND c.contype = 'u'
|
||||
{% elif obj_type == 'exclusion_constraint' %}
|
||||
AND c.contype = 'x'
|
||||
{% else %}
|
||||
AND c.contype IN ('c', 'f', 'p', 'u', 'x')
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['rule'] %}
|
||||
select 'rule'::text AS obj_type, r.rulename AS obj_name, ':schema.'||n.oid||':/' || n.nspname||
|
||||
case
|
||||
WHEN t.relkind = 'r' THEN '/:table.'
|
||||
when t.relkind = 'v' then '/:view.'
|
||||
when t.relkind = 'm' then '/:mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname ||'/:rule.'||r.oid||':/'|| r.rulename AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['rule'] }} AS show_node, NULL AS other_info
|
||||
from pg_rewrite r
|
||||
left join pg_class t on r.ev_class = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger'] %}
|
||||
select 'trigger'::text AS obj_type, tr.tgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname||
|
||||
case
|
||||
WHEN t.relkind = 'r' THEN '/:table.'
|
||||
when t.relkind = 'v' then '/:view.'
|
||||
when t.relkind = 'm' then '/:mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname || '/:trigger.'|| tr.oid || ':/' || tr.tgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['trigger'] }} AS show_node, NULL AS other_info
|
||||
from pg_trigger tr
|
||||
left join pg_class t on tr.tgrelid = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where tr.tgisinternal = false
|
||||
and {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['type'] %}
|
||||
SELECT 'type'::text AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname ||
|
||||
'/:type.'|| t.oid ||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['type'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_type t
|
||||
LEFT OUTER JOIN pg_type e ON e.oid=t.typelem
|
||||
LEFT OUTER JOIN pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c'
|
||||
LEFT OUTER JOIN pg_namespace n on t.typnamespace = n.oid
|
||||
WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%'
|
||||
{% if not show_system_objects %}
|
||||
AND ct.oid is NULL
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['cast'] %}
|
||||
SELECT 'cast'::text AS obj_type, format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_name,
|
||||
':cast.'||ca.oid||':/' || format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['cast'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_cast ca
|
||||
JOIN pg_type st ON st.oid=castsource
|
||||
JOIN pg_type tt ON tt.oid=casttarget
|
||||
{% if not show_system_objects %}
|
||||
WHERE ca.oid > {{last_system_oid}}::OID
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['language'] %}
|
||||
SELECT 'language'::text AS obj_type, lanname AS obj_name, ':language.'||lan.oid||':/' || lanname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['language'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_language lan
|
||||
WHERE lanispl IS TRUE
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_configuration'] %}
|
||||
SELECT 'fts_configuration'::text AS obj_type, cfg.cfgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:fts_configuration.'||cfg.oid||':/' || cfg.cfgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_configuration'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_config cfg
|
||||
left join pg_namespace n on cfg.cfgnamespace = n.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_dictionary'] %}
|
||||
SELECT 'fts_dictionary'::text AS obj_type, dict.dictname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_dictionary.'||dict.oid||':/' || dict.dictname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_dictionary'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_dict dict
|
||||
left join pg_namespace ns on dict.dictnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_parser'] %}
|
||||
SELECT 'fts_parser'::text AS obj_type, prs.prsname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_parser.'||prs.oid||':/' || prs.prsname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_parser'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_parser prs
|
||||
left join pg_namespace ns on prs.prsnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_template'] %}
|
||||
SELECT 'fts_template'::text AS obj_type, tmpl.tmplname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_template.'||tmpl.oid||':/' || tmpl.tmplname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_template'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_template tmpl
|
||||
left join pg_namespace ns on tmpl.tmplnamespace = ns.oid
|
||||
AND {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain'] %}
|
||||
select 'domain'::text AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain'] }} AS show_node, NULL AS other_info
|
||||
from pg_type t
|
||||
inner join pg_namespace n on t.typnamespace = n.oid
|
||||
where t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain_constraints'] %}
|
||||
SELECT 'domain_constraints'::text AS obj_type,
|
||||
c.conname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname || '/:domain_constraints.'||c.oid||':/' || c.conname AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain_constraints'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_constraint c JOIN pg_type t
|
||||
ON t.oid=contypid JOIN pg_namespace n
|
||||
ON n.oid=t.typnamespace
|
||||
WHERE t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_data_wrapper'] %}
|
||||
select 'foreign_data_wrapper'::text AS obj_type, fdwname AS obj_name, ':foreign_data_wrapper.'||oid||':/' || fdwname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_data_wrapper'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_data_wrapper
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_server'] %}
|
||||
select 'foreign_server'::text AS obj_type, sr.srvname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_server'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_server sr
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['user_mapping'] %}
|
||||
select 'user_mapping'::text AS obj_type, ro.rolname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname || '/:user_mapping.'||ro.oid||':/' || ro.rolname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['user_mapping'] }} AS show_node, NULL AS other_info
|
||||
from pg_user_mapping um
|
||||
inner join pg_roles ro on um.umuser = ro.oid
|
||||
inner join pg_foreign_server sr on um.umserver = sr.oid
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_table'] %}
|
||||
select 'foreign_table'::text AS obj_type, c.relname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:foreign_table.'||c.oid||':/' || c.relname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['foreign_table'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_table ft
|
||||
inner join pg_class c on ft.ftrelid = c.oid
|
||||
inner join pg_namespace ns on c.relnamespace = ns.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['extension'] %}
|
||||
select 'extension'::text AS obj_type, x.extname AS obj_name, ':extension.'||x.oid||':/' || x.extname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['extension'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_extension x
|
||||
JOIN pg_namespace n on x.extnamespace=n.oid
|
||||
join pg_available_extensions() e(name, default_version, comment) ON x.extname=e.name
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['collation'] %}
|
||||
SELECT 'collation'::text AS obj_type, c.collname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:collation.'||c.oid||':/' || c.collname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['collation'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_collation c
|
||||
JOIN pg_namespace n ON n.oid=c.collnamespace
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
|
||||
) sn
|
||||
where lower(sn.obj_name) like '%{{ search_text }}%'
|
||||
{% if not show_system_objects %}
|
||||
AND NOT ({{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }})
|
||||
AND (sn.schema_name IS NOT NULL AND sn.schema_name NOT LIKE 'pg\_%')
|
||||
{% endif %}
|
||||
ORDER BY 1, 2, 3
|
@@ -0,0 +1,493 @@
|
||||
{% import 'catalog/ppas/macros/catalogs.sql' as CATALOGS %}
|
||||
{% set all_obj = false %}
|
||||
{% if obj_type == 'all' or obj_type is none %}
|
||||
{% set all_obj = true %}
|
||||
{% endif %}
|
||||
SELECT obj_type, obj_name,
|
||||
REPLACE(obj_path, '/'||sn.schema_name||'/', '/'||{{ CATALOGS.LABELS_SCHEMACOL('sn.schema_name', _) }}||'/') AS obj_path,
|
||||
schema_name, show_node, other_info,
|
||||
CASE
|
||||
WHEN {{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }} THEN
|
||||
CASE WHEN {{ CATALOGS.DB_SUPPORT_SCHEMACOL('sn.schema_name') }} THEN 'D' ELSE 'O' END
|
||||
ELSE 'N'
|
||||
END AS catalog_level
|
||||
FROM (
|
||||
{% if all_obj or obj_type in ['sequence', 'view', 'mview'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN 'sequence'
|
||||
WHEN c.relkind = 'v' THEN 'view'
|
||||
WHEN c.relkind = 'm' THEN 'mview'
|
||||
ELSE 'should not happen'
|
||||
END::text AS obj_type, c.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' ||
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN ':sequence.'
|
||||
WHEN c.relkind = 'v' THEN ':view.'
|
||||
WHEN c.relkind = 'm' THEN ':mview.'
|
||||
ELSE 'should not happen'
|
||||
END || c.oid ||':/' || c.relname AS obj_path, n.nspname AS schema_name,
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN {{ show_node_prefs['sequence'] }}
|
||||
WHEN c.relkind = 'v' THEN {{ show_node_prefs['view'] }}
|
||||
WHEN c.relkind = 'm' THEN {{ show_node_prefs['mview'] }}
|
||||
ELSE False
|
||||
END AS show_node, NULL AS other_info
|
||||
FROM pg_class c
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
{% if all_obj %}
|
||||
WHERE c.relkind in ('S','v','m')
|
||||
{% elif obj_type == 'sequence' %}
|
||||
WHERE c.relkind = 'S'
|
||||
{% elif obj_type == 'view' %}
|
||||
WHERE c.relkind = 'v'
|
||||
{% elif obj_type == 'mview' %}
|
||||
WHERE c.relkind = 'm'
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['table', 'partition'] %}
|
||||
SELECT CASE WHEN c.relispartition THEN 'partition' ELSE 'table' END::text AS obj_type, c.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' || (
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select c.oid as oid, 0 as height,
|
||||
CASE c.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || c.oid || ':/' || c.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
) obj_path, n.nspname AS schema_name,
|
||||
CASE WHEN c.relispartition THEN {{ show_node_prefs['partition'] }}
|
||||
ELSE {{ show_node_prefs['table'] }} END AS show_node,
|
||||
NULL AS other_info
|
||||
FROM pg_class c
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relkind in ('p','r')
|
||||
{% if obj_type == 'table' %}
|
||||
AND NOT c.relispartition
|
||||
{% elif obj_type == 'partition' %}
|
||||
AND c.relispartition
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['index'] %}
|
||||
SELECT 'index'::text AS obj_type, cls.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/:table.'|| tab.oid ||':/' || tab.relname || '/:index.'|| cls.oid ||':/' || cls.relname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_index idx
|
||||
JOIN pg_class cls ON cls.oid=indexrelid
|
||||
JOIN pg_class tab ON tab.oid=indrelid
|
||||
JOIN pg_namespace n ON n.oid=tab.relnamespace
|
||||
LEFT JOIN pg_depend dep ON (dep.classid = cls.tableoid AND dep.objid = cls.oid AND dep.refobjsubid = '0' AND dep.refclassid=(SELECT oid FROM pg_class WHERE relname='pg_constraint') AND dep.deptype='i')
|
||||
LEFT OUTER JOIN pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid)
|
||||
LEFT OUTER JOIN pg_description des ON des.objoid=cls.oid
|
||||
LEFT OUTER JOIN pg_description desp ON (desp.objoid=con.oid AND desp.objsubid = 0)
|
||||
WHERE contype IS NULL
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger_function', 'function', 'procedure', 'edbfunc', 'edbproc'] %}
|
||||
SELECT fd.obj_type, fd.obj_name,
|
||||
CASE
|
||||
WHEN fd.obj_type = 'function' THEN
|
||||
':schema.'|| fd.schema_oid || ':/' || fd.schema_name || '/:function.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'procedure' THEN
|
||||
':schema.'|| fd.schema_oid || ':/' || fd.schema_name || '/:procedure.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'trigger_function' THEN
|
||||
':schema.'|| fd.schema_oid || ':/' || fd.schema_name || '/:trigger_function.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'edbfunc' THEN
|
||||
':schema.'|| fd.next_schema_oid || ':/' || fd.next_schema_name || '/:package.'|| fd.schema_oid || ':/' || fd.schema_name || '/:edbfunc.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'edbproc' THEN
|
||||
':schema.'|| fd.next_schema_oid || ':/' || fd.next_schema_name || '/:package.'|| fd.schema_oid || ':/' || fd.schema_name || '/:edbproc.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
ELSE NULL
|
||||
END AS obj_path,
|
||||
CASE
|
||||
WHEN fd.obj_type IN ('function', 'procedure', 'trigger_function') THEN fd.schema_name
|
||||
WHEN fd.obj_type IN ('edbfunc', 'edbproc') THEN fd.next_schema_name
|
||||
ELSE NULL
|
||||
END AS schema_name,
|
||||
CASE
|
||||
WHEN fd.obj_type = 'function' THEN {{ show_node_prefs['function'] }}
|
||||
WHEN fd.obj_type = 'procedure' THEN {{ show_node_prefs['procedure'] }}
|
||||
WHEN fd.obj_type = 'trigger_function' THEN {{ show_node_prefs['trigger_function'] }}
|
||||
WHEN fd.obj_type = 'edbfunc' THEN {{ show_node_prefs['edbfunc'] }}
|
||||
WHEN fd.obj_type = 'edbproc' THEN {{ show_node_prefs['edbproc'] }}
|
||||
ELSE NULL
|
||||
END AS show_node, other_info
|
||||
FROM (
|
||||
SELECT
|
||||
CASE
|
||||
WHEN t.typname IN ('trigger', 'event_trigger') THEN 'trigger_function'
|
||||
WHEN pr.protype = '0'::char THEN
|
||||
CASE WHEN np.oid IS NOT NULL THEN 'edbfunc' ELSE 'function' END
|
||||
WHEN pr.protype = '1'::char THEN
|
||||
CASE WHEN np.oid IS NOT NULL THEN 'edbproc' ELSE 'procedure' END
|
||||
ELSE null
|
||||
END::text AS obj_type, pr.proname AS obj_name, pr.oid AS obj_oid, n.oid AS schema_oid, n.nspname AS schema_name, np.oid next_schema_oid, np.nspname next_schema_name,
|
||||
pg_catalog.pg_get_function_identity_arguments(pr.oid) AS other_info
|
||||
FROM pg_proc pr left join pg_namespace n
|
||||
ON pr.pronamespace = n.oid left JOIN pg_namespace np
|
||||
ON np.oid=n.nspparent left JOIN pg_type t
|
||||
ON t.oid = pr.prorettype left JOIN pg_language l
|
||||
ON l.oid = pr.prolang
|
||||
WHERE NOT (t.typname = 'trigger' AND l.lanname = 'edbspl')
|
||||
AND ({{ CATALOGS.DB_SUPPORT('n') }} AND {{ CATALOGS.DB_SUPPORT('np') }})
|
||||
) fd
|
||||
{% if not all_obj %}
|
||||
WHERE fd.obj_type = '{{ obj_type }}'
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['event_trigger'] %}
|
||||
select 'event_trigger'::text AS obj_type, evtname AS obj_name, ':event_trigger.'||oid||':/' || evtname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info from pg_event_trigger
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['schema'] %}
|
||||
select 'schema'::text AS obj_type, n.nspname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname as obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['schema'] }} AS show_node, NULL AS other_info from pg_namespace n
|
||||
where n.nspparent = 0
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['column'] %}
|
||||
select 'column'::text AS obj_type, a.attname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname || '/' ||
|
||||
case
|
||||
WHEN t.relkind in ('r', 'p') THEN ':table.'
|
||||
WHEN t.relkind = 'v' THEN ':view.'
|
||||
WHEN t.relkind = 'm' THEN ':mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname || '/:column.'|| a.attnum ||':/' || a.attname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['column'] }} AS show_node, NULL AS other_info
|
||||
from pg_attribute a
|
||||
inner join pg_class t on a.attrelid = t.oid and t.relkind in ('r','p','v','m')
|
||||
left join pg_namespace n on t.relnamespace = n.oid where a.attnum > 0
|
||||
and not t.relispartition
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['constraints', 'check_constraint', 'foreign_key', 'primary_key', 'unique_constraint', 'exclusion_constraint'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN 'check_constraint'
|
||||
WHEN c.contype = 'f' THEN 'foreign_key'
|
||||
WHEN c.contype = 'p' THEN 'primary_key'
|
||||
WHEN c.contype = 'u' THEN 'unique_constraint'
|
||||
WHEN c.contype = 'x' THEN 'exclusion_constraint'
|
||||
END::text AS obj_type,
|
||||
case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname||'/'||
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
) ||
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN '/:check_constraint.' ||c.oid
|
||||
WHEN c.contype = 'f' THEN '/:foreign_key.' ||c.conindid
|
||||
WHEN c.contype = 'p' THEN '/:primary_key.' ||c.conindid
|
||||
WHEN c.contype = 'u' THEN '/:unique_constraint.' ||c.conindid
|
||||
WHEN c.contype = 'x' THEN '/:exclusion_constraint.' ||c.conindid
|
||||
END ||':/'|| case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['constraints'] }} AS show_node, NULL AS other_info
|
||||
from pg_constraint c
|
||||
left join pg_class t on c.conrelid = t.oid
|
||||
left join pg_class tf on c.confrelid = tf.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where c.contypid = 0
|
||||
{% if obj_type == 'check_constraint' %}
|
||||
AND c.contype = 'c'
|
||||
{% elif obj_type == 'foreign_key' %}
|
||||
AND c.contype = 'f'
|
||||
{% elif obj_type == 'primary_key' %}
|
||||
AND c.contype = 'p'
|
||||
{% elif obj_type == 'unique_constraint' %}
|
||||
AND c.contype = 'u'
|
||||
{% elif obj_type == 'exclusion_constraint' %}
|
||||
AND c.contype = 'x'
|
||||
{% else %}
|
||||
AND c.contype IN ('c', 'f', 'p', 'u', 'x')
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['rule'] %}
|
||||
select 'rule'::text AS obj_type, r.rulename AS obj_name, ':schema.'||n.oid||':/' || n.nspname|| '/' ||
|
||||
case
|
||||
when t.relkind = 'v' then ':view.'
|
||||
when t.relkind = 'm' then ':mview.'
|
||||
WHEN t.relkind in ('r', 'p') THEN
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
)
|
||||
end
|
||||
||'/:rule.'||r.oid||':/'|| r.rulename AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['rule'] }} AS show_node, NULL AS other_info
|
||||
from pg_rewrite r
|
||||
left join pg_class t on r.ev_class = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger'] %}
|
||||
select 'trigger'::text AS obj_type, tr.tgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname||
|
||||
case
|
||||
WHEN t.relkind = 'r' THEN '/:table.'
|
||||
when t.relkind = 'v' then '/:view.'
|
||||
when t.relkind = 'm' then '/:mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname || '/:trigger.'|| tr.oid || ':/' || tr.tgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['trigger'] }} AS show_node, NULL AS other_info
|
||||
from pg_trigger tr
|
||||
left join pg_class t on tr.tgrelid = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where tr.tgisinternal = false
|
||||
and {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['type'] %}
|
||||
SELECT 'type'::text AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname ||
|
||||
'/:type.'|| t.oid ||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['type'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_type t
|
||||
LEFT OUTER JOIN pg_type e ON e.oid=t.typelem
|
||||
LEFT OUTER JOIN pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c'
|
||||
LEFT OUTER JOIN pg_namespace n on t.typnamespace = n.oid
|
||||
WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%'
|
||||
{% if not show_system_objects %}
|
||||
AND ct.oid is NULL
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['cast'] %}
|
||||
SELECT 'cast'::text AS obj_type, format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_name,
|
||||
':cast.'||ca.oid||':/' || format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['cast'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_cast ca
|
||||
JOIN pg_type st ON st.oid=castsource
|
||||
JOIN pg_type tt ON tt.oid=casttarget
|
||||
{% if not show_system_objects %}
|
||||
WHERE ca.oid > {{last_system_oid}}::OID
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['language'] %}
|
||||
SELECT 'language'::text AS obj_type, lanname AS obj_name, ':language.'||lan.oid||':/' || lanname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['language'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_language lan
|
||||
WHERE lanispl IS TRUE
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_configuration'] %}
|
||||
SELECT 'fts_configuration'::text AS obj_type, cfg.cfgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:fts_configuration.'||cfg.oid||':/' || cfg.cfgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_configuration'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_config cfg
|
||||
left join pg_namespace n on cfg.cfgnamespace = n.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_dictionary'] %}
|
||||
SELECT 'fts_dictionary' AS obj_type, dict.dictname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_dictionary.'||dict.oid||':/' || dict.dictname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_dictionary'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_dict dict
|
||||
left join pg_namespace ns on dict.dictnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_parser'] %}
|
||||
SELECT 'fts_parser' AS obj_type, prs.prsname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_parser.'||prs.oid||':/' || prs.prsname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_parser'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_parser prs
|
||||
left join pg_namespace ns on prs.prsnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_template'] %}
|
||||
SELECT 'fts_template' AS obj_type, tmpl.tmplname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_template.'||tmpl.oid||':/' || tmpl.tmplname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_template'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_template tmpl
|
||||
left join pg_namespace ns on tmpl.tmplnamespace = ns.oid
|
||||
AND {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain'] %}
|
||||
select 'domain' AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain'] }} AS show_node, NULL AS other_info
|
||||
from pg_type t
|
||||
inner join pg_namespace n on t.typnamespace = n.oid
|
||||
where t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain_constraints'] %}
|
||||
SELECT 'domain_constraints' AS obj_type,
|
||||
c.conname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname || '/:domain_constraints.'||c.oid||':/' || c.conname AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain_constraints'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_constraint c JOIN pg_type t
|
||||
ON t.oid=contypid JOIN pg_namespace n
|
||||
ON n.oid=t.typnamespace
|
||||
WHERE t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_data_wrapper'] %}
|
||||
select 'foreign_data_wrapper' AS obj_type, fdwname AS obj_name, ':foreign_data_wrapper.'||oid||':/' || fdwname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_data_wrapper'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_data_wrapper
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_server'] %}
|
||||
select 'foreign_server' AS obj_type, sr.srvname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_server'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_server sr
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['user_mapping'] %}
|
||||
select 'user_mapping' AS obj_type, ro.rolname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname || '/:user_mapping.'||ro.oid||':/' || ro.rolname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['user_mapping'] }} AS show_node, NULL AS other_info
|
||||
from pg_user_mapping um
|
||||
inner join pg_roles ro on um.umuser = ro.oid
|
||||
inner join pg_foreign_server sr on um.umserver = sr.oid
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_table'] %}
|
||||
select 'foreign_table' AS obj_type, c.relname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:foreign_table.'||c.oid||':/' || c.relname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['foreign_table'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_table ft
|
||||
inner join pg_class c on ft.ftrelid = c.oid
|
||||
inner join pg_namespace ns on c.relnamespace = ns.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['extension'] %}
|
||||
select 'extension' AS obj_type, x.extname AS obj_name, ':extension.'||x.oid||':/' || x.extname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['extension'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_extension x
|
||||
JOIN pg_namespace n on x.extnamespace=n.oid
|
||||
join pg_available_extensions() e(name, default_version, comment) ON x.extname=e.name
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['collation'] %}
|
||||
SELECT 'collation' AS obj_type, c.collname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:collation.'||c.oid||':/' || c.collname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['collation'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_collation c
|
||||
JOIN pg_namespace n ON n.oid=c.collnamespace
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['synonym'] %}
|
||||
SELECT 'synonym' AS obj_type, s.synname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:synonym.'||s.oid||':/' || s.synname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['synonym'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_synonym s
|
||||
JOIN pg_namespace n ON n.oid=s.synnamespace
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['package'] %}
|
||||
SELECT 'package' AS obj_type, p.nspname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:package.'||p.oid||':/' || p.nspname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['package'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_namespace p
|
||||
JOIN pg_namespace n ON n.oid=p.nspparent
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['edbvar'] %}
|
||||
SELECT 'edbvar' AS obj_type, v.varname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname || '/:package.'||p.oid||':/' || p.nspname || '/:edbvar.'||v.oid||':/' || v.varname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['edbvar'] }} AS show_node, NULL AS other_info
|
||||
FROM edb_variable v JOIN pg_namespace p
|
||||
ON v.varpackage = p.oid JOIN pg_namespace n
|
||||
ON p.nspparent = n.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('p') }}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
) sn
|
||||
where lower(sn.obj_name) like '%{{ search_text }}%'
|
||||
{% if not show_system_objects %}
|
||||
AND NOT ({{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }})
|
||||
AND (sn.schema_name IS NOT NULL AND sn.schema_name NOT LIKE 'pg\_%')
|
||||
{% endif %}
|
||||
ORDER BY 1, 2, 3
|
@@ -0,0 +1,516 @@
|
||||
{% import 'catalog/ppas/macros/catalogs.sql' as CATALOGS %}
|
||||
{% set all_obj = false %}
|
||||
{% if obj_type == 'all' or obj_type is none %}
|
||||
{% set all_obj = true %}
|
||||
{% endif %}
|
||||
SELECT obj_type, obj_name,
|
||||
REPLACE(obj_path, '/'||sn.schema_name||'/', '/'||{{ CATALOGS.LABELS_SCHEMACOL('sn.schema_name', _) }}||'/') AS obj_path,
|
||||
schema_name, show_node, other_info,
|
||||
CASE
|
||||
WHEN {{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }} THEN
|
||||
CASE WHEN {{ CATALOGS.DB_SUPPORT_SCHEMACOL('sn.schema_name') }} THEN 'D' ELSE 'O' END
|
||||
ELSE 'N'
|
||||
END AS catalog_level
|
||||
FROM (
|
||||
{% if all_obj or obj_type in ['sequence', 'view', 'mview'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN 'sequence'
|
||||
WHEN c.relkind = 'v' THEN 'view'
|
||||
WHEN c.relkind = 'm' THEN 'mview'
|
||||
ELSE 'should not happen'
|
||||
END::text AS obj_type, c.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' ||
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN ':sequence.'
|
||||
WHEN c.relkind = 'v' THEN ':view.'
|
||||
WHEN c.relkind = 'm' THEN ':mview.'
|
||||
ELSE 'should not happen'
|
||||
END || c.oid ||':/' || c.relname AS obj_path, n.nspname AS schema_name,
|
||||
CASE
|
||||
WHEN c.relkind = 'S' THEN {{ show_node_prefs['sequence'] }}
|
||||
WHEN c.relkind = 'v' THEN {{ show_node_prefs['view'] }}
|
||||
WHEN c.relkind = 'm' THEN {{ show_node_prefs['mview'] }}
|
||||
ELSE False
|
||||
END AS show_node, NULL AS other_info
|
||||
FROM pg_class c
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
{% if all_obj %}
|
||||
WHERE c.relkind in ('S','v','m')
|
||||
{% elif obj_type == 'sequence' %}
|
||||
WHERE c.relkind = 'S'
|
||||
{% elif obj_type == 'view' %}
|
||||
WHERE c.relkind = 'v'
|
||||
{% elif obj_type == 'mview' %}
|
||||
WHERE c.relkind = 'm'
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['table', 'partition'] %}
|
||||
SELECT CASE WHEN c.relispartition THEN 'partition' ELSE 'table' END::text AS obj_type, c.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' || (
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select c.oid as oid, 0 as height,
|
||||
CASE c.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || c.oid || ':/' || c.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
) obj_path, n.nspname AS schema_name,
|
||||
CASE WHEN c.relispartition THEN {{ show_node_prefs['partition'] }}
|
||||
ELSE {{ show_node_prefs['table'] }} END AS show_node,
|
||||
NULL AS other_info
|
||||
FROM pg_class c
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relkind in ('p','r')
|
||||
{% if obj_type == 'table' %}
|
||||
AND NOT c.relispartition
|
||||
{% elif obj_type == 'partition' %}
|
||||
AND c.relispartition
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['index'] %}
|
||||
SELECT 'index'::text AS obj_type, cls.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/:table.'|| tab.oid ||':/' || tab.relname || '/:index.'|| cls.oid ||':/' || cls.relname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_index idx
|
||||
JOIN pg_class cls ON cls.oid=indexrelid
|
||||
JOIN pg_class tab ON tab.oid=indrelid
|
||||
JOIN pg_namespace n ON n.oid=tab.relnamespace
|
||||
LEFT JOIN pg_depend dep ON (dep.classid = cls.tableoid AND dep.objid = cls.oid AND dep.refobjsubid = '0' AND dep.refclassid=(SELECT oid FROM pg_class WHERE relname='pg_constraint') AND dep.deptype='i')
|
||||
LEFT OUTER JOIN pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid)
|
||||
LEFT OUTER JOIN pg_description des ON des.objoid=cls.oid
|
||||
LEFT OUTER JOIN pg_description desp ON (desp.objoid=con.oid AND desp.objsubid = 0)
|
||||
WHERE contype IS NULL
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger_function', 'function', 'procedure', 'edbfunc', 'edbproc'] %}
|
||||
SELECT fd.obj_type, fd.obj_name,
|
||||
CASE
|
||||
WHEN fd.obj_type = 'function' THEN
|
||||
':schema.'|| fd.schema_oid || ':/' || fd.schema_name || '/:function.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'procedure' THEN
|
||||
':schema.'|| fd.schema_oid || ':/' || fd.schema_name || '/:procedure.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'trigger_function' THEN
|
||||
':schema.'|| fd.schema_oid || ':/' || fd.schema_name || '/:trigger_function.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'edbfunc' THEN
|
||||
':schema.'|| fd.next_schema_oid || ':/' || fd.next_schema_name || '/:package.'|| fd.schema_oid || ':/' || fd.schema_name || '/:edbfunc.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'edbproc' THEN
|
||||
':schema.'|| fd.next_schema_oid || ':/' || fd.next_schema_name || '/:package.'|| fd.schema_oid || ':/' || fd.schema_name || '/:edbproc.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
ELSE NULL
|
||||
END AS obj_path,
|
||||
CASE
|
||||
WHEN fd.obj_type IN ('function', 'procedure', 'trigger_function') THEN fd.schema_name
|
||||
WHEN fd.obj_type IN ('edbfunc', 'edbproc') THEN fd.next_schema_name
|
||||
ELSE NULL
|
||||
END AS schema_name,
|
||||
CASE
|
||||
WHEN fd.obj_type = 'function' THEN {{ show_node_prefs['function'] }}
|
||||
WHEN fd.obj_type = 'procedure' THEN {{ show_node_prefs['procedure'] }}
|
||||
WHEN fd.obj_type = 'trigger_function' THEN {{ show_node_prefs['trigger_function'] }}
|
||||
WHEN fd.obj_type = 'edbfunc' THEN {{ show_node_prefs['edbfunc'] }}
|
||||
WHEN fd.obj_type = 'edbproc' THEN {{ show_node_prefs['edbproc'] }}
|
||||
ELSE NULL
|
||||
END AS show_node, other_info
|
||||
FROM (
|
||||
SELECT
|
||||
CASE
|
||||
WHEN t.typname IN ('trigger', 'event_trigger') THEN 'trigger_function'
|
||||
WHEN pr.protype = '0'::char THEN
|
||||
CASE WHEN np.oid IS NOT NULL THEN 'edbfunc' ELSE 'function' END
|
||||
WHEN pr.protype = '1'::char THEN
|
||||
CASE WHEN np.oid IS NOT NULL THEN 'edbproc' ELSE 'procedure' END
|
||||
ELSE null
|
||||
END::text AS obj_type, pr.proname AS obj_name, pr.oid AS obj_oid, n.oid AS schema_oid, n.nspname AS schema_name, np.oid next_schema_oid, np.nspname next_schema_name,
|
||||
pg_catalog.pg_get_function_identity_arguments(pr.oid) AS other_info
|
||||
FROM pg_proc pr left join pg_namespace n
|
||||
ON pr.pronamespace = n.oid left JOIN pg_namespace np
|
||||
ON np.oid=n.nspparent left JOIN pg_type t
|
||||
ON t.oid = pr.prorettype left JOIN pg_language l
|
||||
ON l.oid = pr.prolang
|
||||
WHERE NOT (t.typname = 'trigger' AND l.lanname = 'edbspl')
|
||||
AND ({{ CATALOGS.DB_SUPPORT('n') }} AND {{ CATALOGS.DB_SUPPORT('np') }})
|
||||
) fd
|
||||
{% if not all_obj %}
|
||||
WHERE fd.obj_type = '{{ obj_type }}'
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['event_trigger'] %}
|
||||
select 'event_trigger'::text AS obj_type, evtname AS obj_name, ':event_trigger.'||oid||':/' || evtname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info from pg_event_trigger
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['schema'] %}
|
||||
select 'schema'::text AS obj_type, n.nspname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname as obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['schema'] }} AS show_node, NULL AS other_info from pg_namespace n
|
||||
where n.nspparent = 0
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['column'] %}
|
||||
select 'column'::text AS obj_type, a.attname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname || '/' ||
|
||||
case
|
||||
WHEN t.relkind in ('r', 'p') THEN ':table.'
|
||||
WHEN t.relkind = 'v' THEN ':view.'
|
||||
WHEN t.relkind = 'm' THEN ':mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname || '/:column.'|| a.attnum ||':/' || a.attname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['column'] }} AS show_node, NULL AS other_info
|
||||
from pg_attribute a
|
||||
inner join pg_class t on a.attrelid = t.oid and t.relkind in ('r','p','v','m')
|
||||
left join pg_namespace n on t.relnamespace = n.oid where a.attnum > 0
|
||||
and not t.relispartition
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['constraints', 'check_constraint', 'foreign_key', 'primary_key', 'unique_constraint', 'exclusion_constraint'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN 'check_constraint'
|
||||
WHEN c.contype = 'f' THEN 'foreign_key'
|
||||
WHEN c.contype = 'p' THEN 'primary_key'
|
||||
WHEN c.contype = 'u' THEN 'unique_constraint'
|
||||
WHEN c.contype = 'x' THEN 'exclusion_constraint'
|
||||
END::text AS obj_type,
|
||||
case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname||'/'||
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
) ||
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN '/:check_constraint.' ||c.oid
|
||||
WHEN c.contype = 'f' THEN '/:foreign_key.' ||c.conindid
|
||||
WHEN c.contype = 'p' THEN '/:primary_key.' ||c.conindid
|
||||
WHEN c.contype = 'u' THEN '/:unique_constraint.' ||c.conindid
|
||||
WHEN c.contype = 'x' THEN '/:exclusion_constraint.' ||c.conindid
|
||||
END ||':/'|| case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['constraints'] }} AS show_node, NULL AS other_info
|
||||
from pg_constraint c
|
||||
left join pg_class t on c.conrelid = t.oid
|
||||
left join pg_class tf on c.confrelid = tf.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where c.contypid = 0
|
||||
{% if obj_type == 'check_constraint' %}
|
||||
AND c.contype = 'c'
|
||||
{% elif obj_type == 'foreign_key' %}
|
||||
AND c.contype = 'f'
|
||||
{% elif obj_type == 'primary_key' %}
|
||||
AND c.contype = 'p'
|
||||
{% elif obj_type == 'unique_constraint' %}
|
||||
AND c.contype = 'u'
|
||||
{% elif obj_type == 'exclusion_constraint' %}
|
||||
AND c.contype = 'x'
|
||||
{% else %}
|
||||
AND c.contype IN ('c', 'f', 'p', 'u', 'x')
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['rule'] %}
|
||||
select 'rule'::text AS obj_type, r.rulename AS obj_name, ':schema.'||n.oid||':/' || n.nspname|| '/' ||
|
||||
case
|
||||
when t.relkind = 'v' then ':view.'
|
||||
when t.relkind = 'm' then ':mview.'
|
||||
WHEN t.relkind in ('r', 'p') THEN
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
)
|
||||
end
|
||||
||'/:rule.'||r.oid||':/'|| r.rulename AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['rule'] }} AS show_node, NULL AS other_info
|
||||
from pg_rewrite r
|
||||
left join pg_class t on r.ev_class = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger', 'compound_trigger'] %}
|
||||
select
|
||||
CASE WHEN tr.tgpackageoid != 0 THEN 'compound_trigger' ELSE 'trigger' END::text AS obj_type, tr.tgname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname|| '/' ||
|
||||
case
|
||||
when t.relkind = 'v' then ':view.'
|
||||
when t.relkind = 'm' then ':mview.'
|
||||
WHEN t.relkind in ('r', 'p') THEN
|
||||
(
|
||||
WITH RECURSIVE table_path_data as (
|
||||
select t.oid as oid, 0 as height,
|
||||
CASE t.relispartition WHEN true THEN ':partition.' ELSE ':table.' END || t.oid || ':/' || t.relname as path
|
||||
union
|
||||
select rel.oid, pt.height+1 as height,
|
||||
CASE rel.relispartition WHEN true THEN ':partition.' ELSE ':table.' END
|
||||
|| rel.oid || ':/' || rel.relname || '/' || pt.path as path
|
||||
from pg_class rel JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
|
||||
join pg_inherits inh ON inh.inhparent = rel.oid
|
||||
join table_path_data pt ON inh.inhrelid = pt.oid
|
||||
)
|
||||
select path from table_path_data order by height desc limit 1
|
||||
)
|
||||
end || CASE WHEN tr.tgpackageoid != 0 THEN '/:compound_trigger.' ELSE '/:trigger.' END || tr.oid || ':/' || tr.tgname AS obj_path, n.nspname AS schema_name,
|
||||
CASE WHEN tr.tgpackageoid != 0 THEN {{ show_node_prefs['compound_trigger'] }} ELSE {{ show_node_prefs['trigger'] }} END AS show_node,
|
||||
NULL AS other_info
|
||||
from pg_trigger tr
|
||||
left join pg_class t on tr.tgrelid = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where tr.tgisinternal = false
|
||||
and {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% if obj_type == 'compound_trigger' %}
|
||||
AND tr.tgpackageoid != 0
|
||||
{% elif obj_type == 'trigger' %}
|
||||
AND tr.tgpackageoid = 0
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['type'] %}
|
||||
SELECT 'type'::text AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname ||
|
||||
'/:type.'|| t.oid ||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['type'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_type t
|
||||
LEFT OUTER JOIN pg_type e ON e.oid=t.typelem
|
||||
LEFT OUTER JOIN pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c'
|
||||
LEFT OUTER JOIN pg_namespace n on t.typnamespace = n.oid
|
||||
WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%'
|
||||
{% if not show_system_objects %}
|
||||
AND ct.oid is NULL
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['cast'] %}
|
||||
SELECT 'cast'::text AS obj_type, format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_name,
|
||||
':cast.'||ca.oid||':/' || format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['cast'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_cast ca
|
||||
JOIN pg_type st ON st.oid=castsource
|
||||
JOIN pg_type tt ON tt.oid=casttarget
|
||||
{% if not show_system_objects %}
|
||||
WHERE ca.oid > {{last_system_oid}}::OID
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['language'] %}
|
||||
SELECT 'language'::text AS obj_type, lanname AS obj_name, ':language.'||lan.oid||':/' || lanname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['language'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_language lan
|
||||
WHERE lanispl IS TRUE
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_configuration'] %}
|
||||
SELECT 'fts_configuration'::text AS obj_type, cfg.cfgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:fts_configuration.'||cfg.oid||':/' || cfg.cfgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_configuration'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_config cfg
|
||||
left join pg_namespace n on cfg.cfgnamespace = n.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_dictionary'] %}
|
||||
SELECT 'fts_dictionary'::text AS obj_type, dict.dictname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_dictionary.'||dict.oid||':/' || dict.dictname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_dictionary'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_dict dict
|
||||
left join pg_namespace ns on dict.dictnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_parser'] %}
|
||||
SELECT 'fts_parser'::text AS obj_type, prs.prsname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_parser.'||prs.oid||':/' || prs.prsname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_parser'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_parser prs
|
||||
left join pg_namespace ns on prs.prsnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_template'] %}
|
||||
SELECT 'fts_template'::text AS obj_type, tmpl.tmplname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_template.'||tmpl.oid||':/' || tmpl.tmplname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_template'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_template tmpl
|
||||
left join pg_namespace ns on tmpl.tmplnamespace = ns.oid
|
||||
AND {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain'] %}
|
||||
select 'domain'::text AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain'] }} AS show_node, NULL AS other_info
|
||||
from pg_type t
|
||||
inner join pg_namespace n on t.typnamespace = n.oid
|
||||
where t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain_constraints'] %}
|
||||
SELECT 'domain_constraints'::text AS obj_type,
|
||||
c.conname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname || '/:domain_constraints.'||c.oid||':/' || c.conname AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain_constraints'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_constraint c JOIN pg_type t
|
||||
ON t.oid=contypid JOIN pg_namespace n
|
||||
ON n.oid=t.typnamespace
|
||||
WHERE t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_data_wrapper'] %}
|
||||
select 'foreign_data_wrapper'::text AS obj_type, fdwname AS obj_name, ':foreign_data_wrapper.'||oid||':/' || fdwname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_data_wrapper'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_data_wrapper
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_server'] %}
|
||||
select 'foreign_server' AS obj_type, sr.srvname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_server'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_server sr
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['user_mapping'] %}
|
||||
select 'user_mapping' AS obj_type, ro.rolname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname || '/:user_mapping.'||ro.oid||':/' || ro.rolname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['user_mapping'] }} AS show_node, NULL AS other_info
|
||||
from pg_user_mapping um
|
||||
inner join pg_roles ro on um.umuser = ro.oid
|
||||
inner join pg_foreign_server sr on um.umserver = sr.oid
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_table'] %}
|
||||
select 'foreign_table' AS obj_type, c.relname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:foreign_table.'||c.oid||':/' || c.relname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['foreign_table'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_table ft
|
||||
inner join pg_class c on ft.ftrelid = c.oid
|
||||
inner join pg_namespace ns on c.relnamespace = ns.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['extension'] %}
|
||||
select 'extension' AS obj_type, x.extname AS obj_name, ':extension.'||x.oid||':/' || x.extname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['extension'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_extension x
|
||||
JOIN pg_namespace n on x.extnamespace=n.oid
|
||||
join pg_available_extensions() e(name, default_version, comment) ON x.extname=e.name
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['collation'] %}
|
||||
SELECT 'collation' AS obj_type, c.collname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:collation.'||c.oid||':/' || c.collname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['collation'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_collation c
|
||||
JOIN pg_namespace n ON n.oid=c.collnamespace
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['synonym'] %}
|
||||
SELECT 'synonym' AS obj_type, s.synname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:synonym.'||s.oid||':/' || s.synname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['synonym'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_synonym s
|
||||
JOIN pg_namespace n ON n.oid=s.synnamespace
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['package'] %}
|
||||
SELECT 'package' AS obj_type, p.nspname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:package.'||p.oid||':/' || p.nspname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['package'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_namespace p
|
||||
JOIN pg_namespace n ON n.oid=p.nspparent
|
||||
WHERE p.nspcompoundtrigger = false
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['edbvar'] %}
|
||||
SELECT 'edbvar' AS obj_type, v.varname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname || '/:package.'||p.oid||':/' || p.nspname || '/:edbvar.'||v.oid||':/' || v.varname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['edbvar'] }} AS show_node, NULL AS other_info
|
||||
FROM edb_variable v JOIN pg_namespace p
|
||||
ON v.varpackage = p.oid JOIN pg_namespace n
|
||||
ON p.nspparent = n.oid
|
||||
WHERE p.nspcompoundtrigger = false
|
||||
AND {{ CATALOGS.DB_SUPPORT('p') }}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
) sn
|
||||
where lower(sn.obj_name) like '%{{ search_text }}%'
|
||||
{% if not show_system_objects %}
|
||||
AND NOT ({{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }})
|
||||
AND (sn.schema_name IS NOT NULL AND sn.schema_name NOT LIKE 'pg\_%')
|
||||
{% endif %}
|
||||
ORDER BY 1, 2, 3
|
@@ -0,0 +1,437 @@
|
||||
{% import 'catalog/ppas/macros/catalogs.sql' as CATALOGS %}
|
||||
{% set all_obj = false %}
|
||||
{% if obj_type == 'all' or obj_type is none %}
|
||||
{% set all_obj = true %}
|
||||
{% endif %}
|
||||
SELECT obj_type, obj_name,
|
||||
REPLACE(obj_path, '/'||sn.schema_name||'/', '/'||{{ CATALOGS.LABELS_SCHEMACOL('sn.schema_name', _) }}||'/') AS obj_path,
|
||||
schema_name, show_node, other_info,
|
||||
CASE
|
||||
WHEN {{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }} THEN
|
||||
CASE WHEN {{ CATALOGS.DB_SUPPORT_SCHEMACOL('sn.schema_name') }} THEN 'D' ELSE 'O' END
|
||||
ELSE 'N'
|
||||
END AS catalog_level
|
||||
FROM (
|
||||
{% if all_obj or obj_type in ['table', 'sequence', 'view', 'mview'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.relkind = 'r' THEN 'table'
|
||||
WHEN c.relkind = 'S' THEN 'sequence'
|
||||
WHEN c.relkind = 'v' THEN 'view'
|
||||
WHEN c.relkind = 'm' THEN 'mview'
|
||||
ELSE 'should not happen'
|
||||
END::text::text AS obj_type, c.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/' ||
|
||||
CASE
|
||||
WHEN c.relkind = 'r' THEN ':table.'
|
||||
WHEN c.relkind = 'S' THEN ':sequence.'
|
||||
WHEN c.relkind = 'v' THEN ':view.'
|
||||
WHEN c.relkind = 'm' THEN ':mview.'
|
||||
ELSE 'should not happen'
|
||||
END || c.oid ||':/' || c.relname AS obj_path, n.nspname AS schema_name,
|
||||
CASE
|
||||
WHEN c.relkind = 'r' THEN {{ show_node_prefs['table'] }}
|
||||
WHEN c.relkind = 'S' THEN {{ show_node_prefs['sequence'] }}
|
||||
WHEN c.relkind = 'v' THEN {{ show_node_prefs['view'] }}
|
||||
WHEN c.relkind = 'm' THEN {{ show_node_prefs['mview'] }}
|
||||
ELSE False
|
||||
END AS show_node, NULL AS other_info
|
||||
FROM pg_class c
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
{% if all_obj %}
|
||||
WHERE c.relkind in ('r','S','v','m')
|
||||
{% elif obj_type == 'table' %}
|
||||
WHERE c.relkind = 'r'
|
||||
{% elif obj_type == 'sequence' %}
|
||||
WHERE c.relkind = 'S'
|
||||
{% elif obj_type == 'view' %}
|
||||
WHERE c.relkind = 'v'
|
||||
{% elif obj_type == 'mview' %}
|
||||
WHERE c.relkind = 'm'
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['index'] %}
|
||||
SELECT 'index'::text::text AS obj_type, cls.relname AS obj_name,
|
||||
':schema.'|| n.oid || ':/' || n.nspname || '/:table.'|| tab.oid ||':/' || tab.relname || '/:index.'|| cls.oid ||':/' || cls.relname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_index idx
|
||||
JOIN pg_class cls ON cls.oid=indexrelid
|
||||
JOIN pg_class tab ON tab.oid=indrelid
|
||||
JOIN pg_namespace n ON n.oid=tab.relnamespace
|
||||
LEFT JOIN pg_depend dep ON (dep.classid = cls.tableoid AND dep.objid = cls.oid AND dep.refobjsubid = '0' AND dep.refclassid=(SELECT oid FROM pg_class WHERE relname='pg_constraint') AND dep.deptype='i')
|
||||
LEFT OUTER JOIN pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid)
|
||||
LEFT OUTER JOIN pg_description des ON des.objoid=cls.oid
|
||||
LEFT OUTER JOIN pg_description desp ON (desp.objoid=con.oid AND desp.objsubid = 0)
|
||||
WHERE contype IS NULL
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger_function', 'function', 'procedure', 'edbfunc', 'edbproc'] %}
|
||||
SELECT fd.obj_type, fd.obj_name,
|
||||
CASE
|
||||
WHEN fd.obj_type = 'function' THEN
|
||||
':schema.'|| fd.schema_oid || ':/' || fd.schema_name || '/:function.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'procedure' THEN
|
||||
':schema.'|| fd.schema_oid || ':/' || fd.schema_name || '/:procedure.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'trigger_function' THEN
|
||||
':schema.'|| fd.schema_oid || ':/' || fd.schema_name || '/:trigger_function.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'edbfunc' THEN
|
||||
':schema.'|| fd.next_schema_oid || ':/' || fd.next_schema_name || '/:package.'|| fd.schema_oid || ':/' || fd.schema_name || '/:edbfunc.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
WHEN fd.obj_type = 'edbproc' THEN
|
||||
':schema.'|| fd.next_schema_oid || ':/' || fd.next_schema_name || '/:package.'|| fd.schema_oid || ':/' || fd.schema_name || '/:edbproc.' || fd.obj_oid ||':/' || fd.obj_name
|
||||
ELSE NULL
|
||||
END AS obj_path,
|
||||
CASE
|
||||
WHEN fd.obj_type IN ('function', 'procedure', 'trigger_function') THEN fd.schema_name
|
||||
WHEN fd.obj_type IN ('edbfunc', 'edbproc') THEN fd.next_schema_name
|
||||
ELSE NULL
|
||||
END AS schema_name,
|
||||
CASE
|
||||
WHEN fd.obj_type = 'function' THEN {{ show_node_prefs['function'] }}
|
||||
WHEN fd.obj_type = 'procedure' THEN {{ show_node_prefs['procedure'] }}
|
||||
WHEN fd.obj_type = 'trigger_function' THEN {{ show_node_prefs['trigger_function'] }}
|
||||
WHEN fd.obj_type = 'edbfunc' THEN {{ show_node_prefs['edbfunc'] }}
|
||||
WHEN fd.obj_type = 'edbproc' THEN {{ show_node_prefs['edbproc'] }}
|
||||
ELSE NULL
|
||||
END AS show_node, other_info
|
||||
FROM (
|
||||
SELECT
|
||||
CASE
|
||||
WHEN t.typname IN ('trigger', 'event_trigger') THEN 'trigger_function'
|
||||
WHEN pr.protype = '0'::char THEN
|
||||
CASE WHEN np.oid IS NOT NULL THEN 'edbfunc' ELSE 'function' END
|
||||
WHEN pr.protype = '1'::char THEN
|
||||
CASE WHEN np.oid IS NOT NULL THEN 'edbproc' ELSE 'procedure' END
|
||||
ELSE null
|
||||
END::text::text AS obj_type, pr.proname AS obj_name, pr.oid AS obj_oid, n.oid AS schema_oid, n.nspname AS schema_name, np.oid next_schema_oid, np.nspname next_schema_name,
|
||||
pg_catalog.pg_get_function_identity_arguments(pr.oid) AS other_info
|
||||
FROM pg_proc pr left join pg_namespace n
|
||||
ON pr.pronamespace = n.oid left JOIN pg_namespace np
|
||||
ON np.oid=n.nspparent left JOIN pg_type t
|
||||
ON t.oid = pr.prorettype left JOIN pg_language l
|
||||
ON l.oid = pr.prolang
|
||||
WHERE NOT (t.typname = 'trigger' AND l.lanname = 'edbspl')
|
||||
AND ({{ CATALOGS.DB_SUPPORT('n') }} AND {{ CATALOGS.DB_SUPPORT('np') }})
|
||||
) fd
|
||||
{% if not all_obj %}
|
||||
WHERE fd.obj_type = '{{ obj_type }}'
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['event_trigger'] %}
|
||||
select 'event_trigger'::text::text AS obj_type, evtname AS obj_name, ':event_trigger.'||oid||':/' || evtname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['index'] }} AS show_node, NULL AS other_info from pg_event_trigger
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['schema'] %}
|
||||
select 'schema'::text::text AS obj_type, n.nspname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname as obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['schema'] }} AS show_node, NULL AS other_info from pg_namespace n
|
||||
where n.nspparent = 0
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['column'] %}
|
||||
select 'column'::text::text AS obj_type, a.attname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname || '/' ||
|
||||
case
|
||||
WHEN t.relkind = 'r' THEN ':table.'
|
||||
WHEN t.relkind = 'v' THEN ':view.'
|
||||
WHEN t.relkind = 'm' THEN ':mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname || '/:column.'|| a.attnum ||':/' || a.attname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['column'] }} AS show_node, NULL AS other_info
|
||||
from pg_attribute a
|
||||
inner join pg_class t on a.attrelid = t.oid and t.relkind in ('r','v','m')
|
||||
left join pg_namespace n on t.relnamespace = n.oid where a.attnum > 0
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['constraints', 'check_constraint', 'foreign_key', 'primary_key', 'unique_constraint', 'exclusion_constraint'] %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN 'check_constraint'
|
||||
WHEN c.contype = 'f' THEN 'foreign_key'
|
||||
WHEN c.contype = 'p' THEN 'primary_key'
|
||||
WHEN c.contype = 'u' THEN 'unique_constraint'
|
||||
WHEN c.contype = 'x' THEN 'exclusion_constraint'
|
||||
END::text::text AS obj_type,
|
||||
case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname||'/:table.'|| t.oid || ':/'||t.relname||
|
||||
CASE
|
||||
WHEN c.contype = 'c' THEN '/:check_constraint.' ||c.oid
|
||||
WHEN c.contype = 'f' THEN '/:foreign_key.' ||c.conindid
|
||||
WHEN c.contype = 'p' THEN '/:primary_key.' ||c.conindid
|
||||
WHEN c.contype = 'u' THEN '/:unique_constraint.' ||c.conindid
|
||||
WHEN c.contype = 'x' THEN '/:exclusion_constraint.' ||c.conindid
|
||||
END ||':/'|| case when tf.relname is null then c.conname else c.conname || ' -> ' || tf.relname end AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['constraints'] }} AS show_node, NULL AS other_info
|
||||
from pg_constraint c
|
||||
left join pg_class t on c.conrelid = t.oid
|
||||
left join pg_class tf on c.confrelid = tf.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where c.contypid = 0
|
||||
{% if obj_type == 'check_constraint' %}
|
||||
AND c.contype = 'c'
|
||||
{% elif obj_type == 'foreign_key' %}
|
||||
AND c.contype = 'f'
|
||||
{% elif obj_type == 'primary_key' %}
|
||||
AND c.contype = 'p'
|
||||
{% elif obj_type == 'unique_constraint' %}
|
||||
AND c.contype = 'u'
|
||||
{% elif obj_type == 'exclusion_constraint' %}
|
||||
AND c.contype = 'x'
|
||||
{% else %}
|
||||
AND c.contype IN ('c', 'f', 'p', 'u', 'x')
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['rule'] %}
|
||||
select 'rule'::text::text AS obj_type, r.rulename AS obj_name, ':schema.'||n.oid||':/' || n.nspname||
|
||||
case
|
||||
WHEN t.relkind = 'r' THEN '/:table.'
|
||||
when t.relkind = 'v' then '/:view.'
|
||||
when t.relkind = 'm' then '/:mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname ||'/:rule.'||r.oid||':/'|| r.rulename AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['rule'] }} AS show_node, NULL AS other_info
|
||||
from pg_rewrite r
|
||||
left join pg_class t on r.ev_class = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['trigger'] %}
|
||||
select 'trigger'::text::text AS obj_type, tr.tgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname||
|
||||
case
|
||||
WHEN t.relkind = 'r' THEN '/:table.'
|
||||
when t.relkind = 'v' then '/:view.'
|
||||
when t.relkind = 'm' then '/:mview.'
|
||||
else 'should not happen'
|
||||
end || t.oid || ':/' || t.relname || '/:trigger.'|| tr.oid || ':/' || tr.tgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['trigger'] }} AS show_node, NULL AS other_info
|
||||
from pg_trigger tr
|
||||
left join pg_class t on tr.tgrelid = t.oid
|
||||
left join pg_namespace n on t.relnamespace = n.oid
|
||||
where tr.tgisinternal = false
|
||||
and {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['type'] %}
|
||||
SELECT 'type'::text::text AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname ||
|
||||
'/:type.'|| t.oid ||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['type'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_type t
|
||||
LEFT OUTER JOIN pg_type e ON e.oid=t.typelem
|
||||
LEFT OUTER JOIN pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c'
|
||||
LEFT OUTER JOIN pg_namespace n on t.typnamespace = n.oid
|
||||
WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%'
|
||||
{% if not show_system_objects %}
|
||||
AND ct.oid is NULL
|
||||
{% endif %}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['cast'] %}
|
||||
SELECT 'cast'::text::text AS obj_type, format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_name,
|
||||
':cast.'||ca.oid||':/' || format_type(st.oid,NULL) ||'->'|| format_type(tt.oid,tt.typtypmod) AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['cast'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_cast ca
|
||||
JOIN pg_type st ON st.oid=castsource
|
||||
JOIN pg_type tt ON tt.oid=casttarget
|
||||
{% if not show_system_objects %}
|
||||
WHERE ca.oid > {{last_system_oid}}::OID
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['language'] %}
|
||||
SELECT 'language'::text::text AS obj_type, lanname AS obj_name, ':language.'||lan.oid||':/' || lanname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['language'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_language lan
|
||||
WHERE lanispl IS TRUE
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_configuration'] %}
|
||||
SELECT 'fts_configuration'::text::text AS obj_type, cfg.cfgname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:fts_configuration.'||cfg.oid||':/' || cfg.cfgname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_configuration'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_config cfg
|
||||
left join pg_namespace n on cfg.cfgnamespace = n.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_dictionary'] %}
|
||||
SELECT 'fts_dictionary'::text::text AS obj_type, dict.dictname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_dictionary.'||dict.oid||':/' || dict.dictname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_dictionary'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_dict dict
|
||||
left join pg_namespace ns on dict.dictnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_parser'] %}
|
||||
SELECT 'fts_parser'::text::text AS obj_type, prs.prsname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_parser.'||prs.oid||':/' || prs.prsname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_parser'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_parser prs
|
||||
left join pg_namespace ns on prs.prsnamespace = ns.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['fts_template'] %}
|
||||
SELECT 'fts_template'::text::text AS obj_type, tmpl.tmplname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:fts_template.'||tmpl.oid||':/' || tmpl.tmplname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['fts_template'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_ts_template tmpl
|
||||
left join pg_namespace ns on tmpl.tmplnamespace = ns.oid
|
||||
AND {{ CATALOGS.DB_SUPPORT('ns') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain'] %}
|
||||
select 'domain'::text::text AS obj_type, t.typname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain'] }} AS show_node, NULL AS other_info
|
||||
from pg_type t
|
||||
inner join pg_namespace n on t.typnamespace = n.oid
|
||||
where t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['domain_constraints'] %}
|
||||
SELECT 'domain_constraints'::text::text AS obj_type,
|
||||
c.conname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:domain.'||t.oid||':/' || t.typname || '/:domain_constraints.'||c.oid||':/' || c.conname AS obj_path,
|
||||
n.nspname AS schema_name,
|
||||
{{ show_node_prefs['domain_constraints'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_constraint c JOIN pg_type t
|
||||
ON t.oid=contypid JOIN pg_namespace n
|
||||
ON n.oid=t.typnamespace
|
||||
WHERE t.typtype = 'd'
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_data_wrapper'] %}
|
||||
select 'foreign_data_wrapper'::text AS obj_type, fdwname AS obj_name, ':foreign_data_wrapper.'||oid||':/' || fdwname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_data_wrapper'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_data_wrapper
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_server'] %}
|
||||
select 'foreign_server'::text AS obj_type, sr.srvname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['foreign_server'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_server sr
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['user_mapping'] %}
|
||||
select 'user_mapping'::text AS obj_type, ro.rolname AS obj_name, ':foreign_data_wrapper.'||fdw.oid||':/' || fdw.fdwname || '/:foreign_server.'||sr.oid||':/' || sr.srvname || '/:user_mapping.'||ro.oid||':/' || ro.rolname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['user_mapping'] }} AS show_node, NULL AS other_info
|
||||
from pg_user_mapping um
|
||||
inner join pg_roles ro on um.umuser = ro.oid
|
||||
inner join pg_foreign_server sr on um.umserver = sr.oid
|
||||
inner join pg_foreign_data_wrapper fdw on sr.srvfdw = fdw.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['foreign_table'] %}
|
||||
select 'foreign_table'::text AS obj_type, c.relname AS obj_name, ':schema.'||ns.oid||':/' || ns.nspname || '/:foreign_table.'||c.oid||':/' || c.relname AS obj_path, ns.nspname AS schema_name,
|
||||
{{ show_node_prefs['foreign_table'] }} AS show_node, NULL AS other_info
|
||||
from pg_foreign_table ft
|
||||
inner join pg_class c on ft.ftrelid = c.oid
|
||||
inner join pg_namespace ns on c.relnamespace = ns.oid
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['extension'] %}
|
||||
select 'extension'::text AS obj_type, x.extname AS obj_name, ':extension.'||x.oid||':/' || x.extname AS obj_path, ''::text AS schema_name,
|
||||
{{ show_node_prefs['extension'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_extension x
|
||||
JOIN pg_namespace n on x.extnamespace=n.oid
|
||||
join pg_available_extensions() e(name, default_version, comment) ON x.extname=e.name
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['collation'] %}
|
||||
SELECT 'collation'::text AS obj_type, c.collname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:collation.'||c.oid||':/' || c.collname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['collation'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_collation c
|
||||
JOIN pg_namespace n ON n.oid=c.collnamespace
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['synonym'] %}
|
||||
SELECT 'synonym'::text AS obj_type, s.synname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:synonym.'||s.oid||':/' || s.synname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['synonym'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_synonym s
|
||||
JOIN pg_namespace n ON n.oid=s.synnamespace
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['package'] %}
|
||||
SELECT 'package'::text AS obj_type, p.nspname AS obj_name, ':schema.'||n.oid||':/' || n.nspname || '/:package.'||p.oid||':/' || p.nspname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['package'] }} AS show_node, NULL AS other_info
|
||||
FROM pg_namespace p
|
||||
JOIN pg_namespace n ON n.oid=p.nspparent
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
{% if all_obj %}
|
||||
UNION
|
||||
{% endif %}
|
||||
{% if all_obj or obj_type in ['edbvar'] %}
|
||||
SELECT 'edbvar'::text AS obj_type, v.varname AS obj_name,
|
||||
':schema.'||n.oid||':/' || n.nspname || '/:package.'||p.oid||':/' || p.nspname || '/:edbvar.'||v.oid||':/' || v.varname AS obj_path, n.nspname AS schema_name,
|
||||
{{ show_node_prefs['edbvar'] }} AS show_node, NULL AS other_info
|
||||
FROM edb_variable v JOIN pg_namespace p
|
||||
ON v.varpackage = p.oid JOIN pg_namespace n
|
||||
ON p.nspparent = n.oid
|
||||
WHERE {{ CATALOGS.DB_SUPPORT('p') }}
|
||||
AND {{ CATALOGS.DB_SUPPORT('n') }}
|
||||
{% endif %}
|
||||
) sn
|
||||
where lower(sn.obj_name) like '%{{ search_text }}%'
|
||||
{% if not show_system_objects %}
|
||||
AND NOT ({{ CATALOGS.IS_CATALOG_SCHEMA('sn.schema_name') }})
|
||||
AND (sn.schema_name IS NOT NULL AND sn.schema_name NOT LIKE 'pg\_%')
|
||||
{% endif %}
|
||||
ORDER BY 1, 2, 3
|
0
web/pgadmin/tools/search_objects/tests/__init__.py
Normal file
0
web/pgadmin/tools/search_objects/tests/__init__.py
Normal file
75
web/pgadmin/tools/search_objects/tests/test_api_search.py
Normal file
75
web/pgadmin/tools/search_objects/tests/test_api_search.py
Normal file
@@ -0,0 +1,75 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import json
|
||||
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression import parent_node_dict
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
|
||||
try:
|
||||
from urllib import urlencode
|
||||
except Exception as e:
|
||||
from urllib.parse import urlencode
|
||||
|
||||
|
||||
class SearchObjectsApiSearch(BaseTestGenerator):
|
||||
""" This class will test search API of search objects. """
|
||||
scenarios = [
|
||||
('Search with all types', dict(text='emp', type='all', singles=False)),
|
||||
('Search with None types', dict(text='emp', type=None, singles=False)),
|
||||
('Search for all single types',
|
||||
dict(text='emp', type=None, singles=True)),
|
||||
]
|
||||
|
||||
def runFor(self, text=None, type=None):
|
||||
url_params = dict(
|
||||
text=text
|
||||
)
|
||||
if type is not None:
|
||||
url_params['type'] = type
|
||||
|
||||
url_params = urlencode(url_params)
|
||||
response = self.tester.get(self.base_url + '?' + url_params)
|
||||
|
||||
self.assertEquals(response.status_code, 200)
|
||||
|
||||
def runTest(self):
|
||||
database_info = parent_node_dict["database"][-1]
|
||||
server_id = database_info["server_id"]
|
||||
db_id = database_info["db_id"]
|
||||
|
||||
db_con = database_utils.connect_database(self,
|
||||
utils.SERVER_GROUP,
|
||||
server_id,
|
||||
db_id)
|
||||
if not db_con["info"] == "Database connected.":
|
||||
raise Exception("Could not connect to database to add the schema.")
|
||||
|
||||
self.base_url = '/search_objects/search/' \
|
||||
+ str(server_id) + '/' + str(db_id)
|
||||
|
||||
if not self.singles:
|
||||
self.runFor(text=self.text, type=self.type)
|
||||
else:
|
||||
# test for all the node types individually
|
||||
types_url = '/search_objects/types/' +\
|
||||
str(server_id) + '/' + str(db_id)
|
||||
response = self.tester.get(types_url)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
types_data = json.loads(response.data.decode('utf-8'))['data']
|
||||
|
||||
for a_type in types_data:
|
||||
print('Running search for type {0}'.format(a_type),
|
||||
file=sys.stderr)
|
||||
self.runFor(text=self.text, type=a_type)
|
47
web/pgadmin/tools/search_objects/tests/test_api_types.py
Normal file
47
web/pgadmin/tools/search_objects/tests/test_api_types.py
Normal file
@@ -0,0 +1,47 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import json
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression import parent_node_dict
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
|
||||
|
||||
class SearchObjectsApiTypes(BaseTestGenerator):
|
||||
""" This class will test types API of search objects. """
|
||||
scenarios = [
|
||||
# Fetching default URL for schema node.
|
||||
('Types API URL', dict(url='/search_objects/types'))
|
||||
]
|
||||
|
||||
def runTest(self):
|
||||
database_info = parent_node_dict["database"][-1]
|
||||
server_id = database_info["server_id"]
|
||||
|
||||
db_id = database_info["db_id"]
|
||||
db_con = database_utils.connect_database(self,
|
||||
utils.SERVER_GROUP,
|
||||
server_id,
|
||||
db_id)
|
||||
if not db_con["info"] == "Database connected.":
|
||||
raise Exception("Could not connect to database to add the schema.")
|
||||
|
||||
url = self.url + '/' + str(server_id) + '/' + str(db_id)
|
||||
response = self.tester.get(url)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
|
||||
# repsonse data should be dict
|
||||
response_data = json.loads(response.data.decode('utf-8'))['data']
|
||||
self.assertEquals(type(response_data), dict)
|
||||
|
||||
# response data key values should not be None
|
||||
for key, value in response_data.items():
|
||||
self.assertIsNotNone(value, 'Key {0} has value None'.format(key))
|
@@ -0,0 +1,117 @@
|
||||
import sys
|
||||
|
||||
from pgadmin.tools.search_objects.utils import SearchObjectsHelper, current_app
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
|
||||
if sys.version_info < (3, 3):
|
||||
from mock import patch, MagicMock
|
||||
else:
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
|
||||
class SearchObjectsHelperTest(BaseTestGenerator):
|
||||
scenarios = [
|
||||
('scenario', dict(
|
||||
node_blueprints=[
|
||||
dict(node_type='table', coll_label='Tables',
|
||||
backend_supported=True),
|
||||
dict(node_type='view', coll_label='Views',
|
||||
backend_supported=False),
|
||||
dict(node_type='index', coll_label='Indexes',
|
||||
backend_supported=True),
|
||||
dict(node_type='role', coll_label='Roles',
|
||||
backend_supported=True)
|
||||
],
|
||||
all_node_types=['table', 'view', 'index'],
|
||||
expected_show_node_prefs=dict(table=True, view=False, index=True),
|
||||
expected_supported_types=dict(table='Tables', index='Indexes'),
|
||||
expected_supported_types_skip=dict(table='Tables', view='Views',
|
||||
index='Indexes'),
|
||||
execute_dict_return_value=(
|
||||
True, dict(rows=[
|
||||
dict(obj_name='name1', obj_type='table',
|
||||
obj_path='some/path', show_node=True,
|
||||
other_info=None, catalog_level='N'),
|
||||
dict(obj_name='name2', obj_type='view',
|
||||
obj_path='some1/path', show_node=True,
|
||||
other_info=None, catalog_level='D'),
|
||||
dict(obj_name='name3', obj_type='index',
|
||||
obj_path='some2/path1', show_node=True,
|
||||
other_info='oid', catalog_level='O'),
|
||||
])),
|
||||
expected_search_op=(
|
||||
True, [
|
||||
dict(name='name1', type='table', type_label='Tables',
|
||||
path='some/path',
|
||||
show_node=True, other_info=None, catalog_level='N'),
|
||||
dict(name='name2', type='view', type_label='Views',
|
||||
path='some1/path',
|
||||
show_node=True, other_info=None, catalog_level='D'),
|
||||
dict(name='name3', type='index', type_label='Indexes',
|
||||
path='some2/path1',
|
||||
show_node=True, other_info='oid', catalog_level='O'),
|
||||
]
|
||||
)
|
||||
))
|
||||
]
|
||||
|
||||
def __create_manager(self):
|
||||
connection = MagicMock(
|
||||
execute_dict=MagicMock(),
|
||||
db='somedb'
|
||||
)
|
||||
connection.execute_dict.return_value = self.execute_dict_return_value
|
||||
|
||||
def connection_function(did):
|
||||
return connection
|
||||
|
||||
return MagicMock(
|
||||
connection=connection_function
|
||||
)
|
||||
|
||||
@patch('pgadmin.tools.search_objects.utils.get_node_blueprint')
|
||||
@patch('pgadmin.tools.search_objects.utils.get_driver')
|
||||
def runTest(self, get_driver_mock, get_node_blueprint_mock):
|
||||
manager = self.__create_manager()
|
||||
|
||||
get_driver_mock.return_value = MagicMock(
|
||||
connection_manager=lambda session_id: manager)
|
||||
|
||||
def __get_node_blueprint_mock(node_type):
|
||||
blueprints = self.node_blueprints
|
||||
blueprint = None
|
||||
for data in blueprints:
|
||||
if node_type == data['node_type']:
|
||||
blueprint = MagicMock(
|
||||
BackendSupported=MagicMock(
|
||||
return_value=data['backend_supported']),
|
||||
collection_label=data['coll_label'],
|
||||
show_node=data['backend_supported'],
|
||||
)
|
||||
return blueprint
|
||||
|
||||
get_node_blueprint_mock.side_effect = __get_node_blueprint_mock
|
||||
|
||||
with self.app.app_context():
|
||||
|
||||
so_obj = SearchObjectsHelper(2, 18456,
|
||||
node_types=self.all_node_types)
|
||||
so_obj.get_sql = MagicMock(return_value='dummy query')
|
||||
|
||||
# test template path
|
||||
manager.server_type = 'pg'
|
||||
manager.version = 906000
|
||||
self.assertEquals(so_obj.get_template_path(),
|
||||
'search_objects/sql/pg/#906000#')
|
||||
|
||||
self.assertEquals(so_obj.get_show_node_prefs(),
|
||||
self.expected_show_node_prefs)
|
||||
|
||||
self.assertEquals(so_obj.get_supported_types(),
|
||||
self.expected_supported_types)
|
||||
|
||||
self.assertEquals(so_obj.get_supported_types(skip_check=True),
|
||||
self.expected_supported_types_skip)
|
||||
|
||||
self.assertEquals(so_obj.search('searchtext', 'all'),
|
||||
self.expected_search_op)
|
131
web/pgadmin/tools/search_objects/utils.py
Normal file
131
web/pgadmin/tools/search_objects/utils.py
Normal file
@@ -0,0 +1,131 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
from flask import current_app, render_template
|
||||
from flask_babelex import gettext
|
||||
|
||||
from pgadmin.utils.driver import get_driver
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
|
||||
|
||||
def get_node_blueprint(node_type):
|
||||
blueprint = None
|
||||
node_type = 'NODE-' + node_type
|
||||
if node_type in current_app.blueprints:
|
||||
blueprint = current_app.blueprints[node_type]
|
||||
|
||||
return blueprint
|
||||
|
||||
|
||||
class SearchObjectsHelper:
|
||||
def __init__(self, sid, did, show_system_objects=False, node_types=None):
|
||||
self.sid = sid
|
||||
self.did = did
|
||||
self.show_system_objects = show_system_objects
|
||||
self.manager = get_driver(
|
||||
PG_DEFAULT_DRIVER
|
||||
).connection_manager(sid)
|
||||
|
||||
self._all_node_types = [
|
||||
'cast', 'fts_dictionary', 'check_constraint',
|
||||
'exclusion_constraint', 'foreign_key',
|
||||
'primary_key', 'unique_constraint', 'constraints', 'trigger',
|
||||
'table', 'compound_trigger', 'rule', 'column', 'partition',
|
||||
'index', 'type', 'domain', 'domain_constraints', 'schema',
|
||||
'synonym', 'sequence', 'edbvar', 'edbfunc', 'edbproc', 'package',
|
||||
'foreign_table', 'fts_parser', 'function', 'procedure',
|
||||
'trigger_function', 'fts_template', 'collation', 'view', 'mview',
|
||||
'fts_configuration', 'extension', 'language',
|
||||
'event_trigger', 'foreign_server', 'user_mapping',
|
||||
'foreign_data_wrapper'
|
||||
] if node_types is None else node_types
|
||||
|
||||
@property
|
||||
def all_node_types(self):
|
||||
return self._all_node_types
|
||||
|
||||
def get_template_path(self):
|
||||
return 'search_objects/sql/{0}/#{1}#'.format(
|
||||
self.manager.server_type, self.manager.version)
|
||||
|
||||
def get_show_node_prefs(self):
|
||||
return_types = {}
|
||||
for node_type in self.all_node_types:
|
||||
blueprint = get_node_blueprint(node_type)
|
||||
if blueprint is None:
|
||||
continue
|
||||
|
||||
return_types[node_type] = blueprint.show_node
|
||||
return return_types
|
||||
|
||||
def get_supported_types(self, skip_check=False):
|
||||
return_types = {}
|
||||
for node_type in self.all_node_types:
|
||||
blueprint = get_node_blueprint(node_type)
|
||||
if blueprint is None:
|
||||
continue
|
||||
|
||||
if blueprint.BackendSupported(self.manager, is_catalog=False,
|
||||
did=self.did) or skip_check:
|
||||
if node_type in ['edbfunc', 'edbproc']:
|
||||
return_types[node_type] =\
|
||||
gettext('Package {0}').format(
|
||||
blueprint.collection_label)
|
||||
else:
|
||||
return_types[node_type] = blueprint.collection_label
|
||||
|
||||
return return_types
|
||||
|
||||
def get_sql(self, sql_file, **kwargs):
|
||||
return render_template(
|
||||
"/".join([self.get_template_path(), sql_file]),
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def finalize_id_path(self, path, base_path):
|
||||
if base_path is not None:
|
||||
path = '{0}/{1}'.format(base_path, path)
|
||||
|
||||
return path
|
||||
|
||||
def search(self, text, obj_type=None):
|
||||
conn = self.manager.connection(did=self.did)
|
||||
last_system_oid = (self.manager.db_info[self.did])['datlastsysoid'] \
|
||||
if self.manager.db_info is not None and self.did in \
|
||||
self.manager.db_info else 0
|
||||
|
||||
show_node_prefs = self.get_show_node_prefs()
|
||||
node_labels = self.get_supported_types(skip_check=True)
|
||||
# Column catalog_level has values as
|
||||
# N - Not a catalog schema
|
||||
# D - Catalog schema with DB support - pg_catalog
|
||||
# O - Catalog schema with object support only - info schema, dbo, sys
|
||||
status, res = conn.execute_dict(
|
||||
self.get_sql('search.sql', search_text=text, obj_type=obj_type,
|
||||
show_system_objects=self.show_system_objects,
|
||||
show_node_prefs=show_node_prefs, _=gettext,
|
||||
last_system_oid=last_system_oid)
|
||||
)
|
||||
|
||||
if not status:
|
||||
return status, res
|
||||
|
||||
ret_val = [
|
||||
{
|
||||
'name': row['obj_name'],
|
||||
'type': row['obj_type'],
|
||||
'type_label': node_labels[row['obj_type']],
|
||||
'path': row['obj_path'],
|
||||
'show_node': row['show_node'],
|
||||
'other_info': row['other_info'],
|
||||
'catalog_level': row['catalog_level'],
|
||||
}
|
||||
for row in res['rows']
|
||||
]
|
||||
return True, ret_val
|
@@ -112,7 +112,7 @@ li {
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
.slick-header-column.ui-state-default {
|
||||
#datagrid .slick-header-column.ui-state-default {
|
||||
height: 32px !important;
|
||||
}
|
||||
|
||||
|
@@ -19,5 +19,7 @@ define(function () {
|
||||
'datagrid.initialize_query_tool_with_did': '/initialize/query_tool/<int:sgid>/<int:sid>/<int:did>',
|
||||
'restore.create_job': '/restore/job/<int:sid>',
|
||||
'datagrid.panel': '/panel/<int:trans_id>',
|
||||
'search_objects.types': '/search_objects/types/<int:sid>/<int:did>',
|
||||
'search_objects.search': '/search_objects/search/<int:sid>/<int:did>',
|
||||
};
|
||||
});
|
||||
|
@@ -0,0 +1,155 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import SearchObjectsDialog from 'tools/search_objects/static/js/search_objects_dialog';
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import axios from 'axios/index';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('SearchObjectsDialog', () => {
|
||||
let soDialog;
|
||||
let pgBrowser;
|
||||
let jquerySpy;
|
||||
let alertifySpy;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser = {
|
||||
treeMenu: new TreeFake(),
|
||||
Nodes: {
|
||||
server: {
|
||||
hasId: true,
|
||||
label: 'server',
|
||||
getTreeNodeHierarchy: jasmine.createSpy('server.getTreeNodeHierarchy'),
|
||||
},
|
||||
database: {
|
||||
hasId: true,
|
||||
label: 'database',
|
||||
getTreeNodeHierarchy: jasmine.createSpy('db.getTreeNodeHierarchy'),
|
||||
},
|
||||
schema: {
|
||||
hasId: true,
|
||||
label: 'schema',
|
||||
getTreeNodeHierarchy: jasmine.createSpy('db.getTreeNodeHierarchy'),
|
||||
},
|
||||
},
|
||||
stdW: {
|
||||
sm: 500,
|
||||
md: 700,
|
||||
lg: 900,
|
||||
default: 500,
|
||||
},
|
||||
stdH: {
|
||||
sm: 200,
|
||||
md: 400,
|
||||
lg: 550,
|
||||
default: 550,
|
||||
},
|
||||
};
|
||||
pgBrowser.Nodes.server.hasId = true;
|
||||
pgBrowser.Nodes.database.hasId = true;
|
||||
jquerySpy = jasmine.createSpy('jquerySpy');
|
||||
|
||||
const hierarchy = {
|
||||
children: [
|
||||
{
|
||||
id: 'root',
|
||||
children: [
|
||||
{
|
||||
id: 'serverTreeNode',
|
||||
data: {
|
||||
_id: 10,
|
||||
_type: 'server',
|
||||
user: {name: 'username'},
|
||||
label: 'theserver',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'some_database',
|
||||
data: {
|
||||
_type: 'database',
|
||||
_id: 11,
|
||||
label: 'thedatabase',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'ppasServer',
|
||||
data: {
|
||||
_type: 'server',
|
||||
server_type: 'ppas',
|
||||
children: [
|
||||
{id: 'someNodeUnderneathPPASServer'},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
pgBrowser.treeMenu = TreeFake.build(hierarchy);
|
||||
});
|
||||
|
||||
describe('#draw', () => {
|
||||
let networkMock;
|
||||
beforeEach(() => {
|
||||
networkMock = new MockAdapter(axios);
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']);
|
||||
alertifySpy['search_objects'] = jasmine.createSpy('search_objects');
|
||||
soDialog = new SearchObjectsDialog(
|
||||
pgBrowser,
|
||||
jquerySpy,
|
||||
alertifySpy,
|
||||
null
|
||||
);
|
||||
|
||||
pgBrowser.get_preference = jasmine.createSpy('get_preferences');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
networkMock.restore();
|
||||
});
|
||||
|
||||
context('there are no ancestors of the type database', () => {
|
||||
it('does not create a dialog', () => {
|
||||
pgBrowser.treeMenu.selectNode([{id: 'serverTreeNode'}]);
|
||||
soDialog.draw(null, null, null);
|
||||
expect(alertifySpy['search_objects']).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('display an alert with a Backup Error', () => {
|
||||
soDialog.draw(null, [{id: 'serverTreeNode'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Search Objects Error',
|
||||
'Please select a database or its child node from the browser.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('there is an ancestor of the type database', () => {
|
||||
let soDialogResizeToSpy;
|
||||
beforeEach(() => {
|
||||
soDialogResizeToSpy = jasmine.createSpyObj('soDialogResizeToSpy', ['resizeTo']);
|
||||
alertifySpy['search_objects'].and
|
||||
.returnValue(soDialogResizeToSpy);
|
||||
});
|
||||
|
||||
it('displays the dialog when database node selected', (done) => {
|
||||
soDialog.draw(null, [{id: 'some_database'}], null, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['search_objects']).toHaveBeenCalledWith('Search Objects - thedatabase/username@theserver');
|
||||
expect(soDialogResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@@ -0,0 +1,545 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import SearchObjectsDialogWrapper from 'tools/search_objects/static/js/search_objects_dialog_wrapper';
|
||||
import axios from 'axios/index';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
|
||||
|
||||
let context = describe;
|
||||
|
||||
describe('SearchObjectsDialogWrapper', () => {
|
||||
let jquerySpy;
|
||||
let pgBrowser;
|
||||
let alertifySpy;
|
||||
let dialogModelKlassSpy = null;
|
||||
let backform;
|
||||
let soDialogWrapper;
|
||||
let noDataNode;
|
||||
let serverTreeNode;
|
||||
let databaseTreeNode;
|
||||
let viewSchema;
|
||||
let soJQueryContainerSpy;
|
||||
let soNodeChildNodeSpy;
|
||||
let soNode;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser = {
|
||||
treeMenu: new TreeFake(),
|
||||
Nodes: {
|
||||
server: {
|
||||
hasId: true,
|
||||
getTreeNodeHierarchy: jasmine.createSpy('getTreeNodeHierarchy'),
|
||||
},
|
||||
database: {
|
||||
hasId: true,
|
||||
getTreeNodeHierarchy: jasmine.createSpy('getTreeNodeHierarchy'),
|
||||
},
|
||||
'coll-sometype': {
|
||||
type: 'coll-sometype',
|
||||
hasId: false,
|
||||
label: 'Some types coll',
|
||||
},
|
||||
sometype: {
|
||||
type: 'sometype',
|
||||
hasId: true,
|
||||
},
|
||||
someothertype: {
|
||||
type: 'someothertype',
|
||||
hasId: true,
|
||||
collection_type: 'coll-sometype',
|
||||
},
|
||||
'coll-edbfunc': {
|
||||
type: 'coll-edbfunc',
|
||||
hasId: true,
|
||||
label: 'Functions',
|
||||
},
|
||||
'coll-edbproc': {
|
||||
type: 'coll-edbfunc',
|
||||
hasId: true,
|
||||
label: 'Procedures',
|
||||
},
|
||||
'coll-edbvar': {
|
||||
type: 'coll-edbfunc',
|
||||
hasId: true,
|
||||
label: 'Variables',
|
||||
},
|
||||
},
|
||||
keyboardNavigation: jasmine.createSpyObj('keyboardNavigation', ['getDialogTabNavigator']),
|
||||
};
|
||||
noDataNode = pgBrowser.treeMenu.addNewNode('level1.1', undefined, [{id: 'level1'}]);
|
||||
serverTreeNode = pgBrowser.treeMenu.addNewNode('level2.1', {
|
||||
_type: 'server',
|
||||
_id: 10,
|
||||
label: 'some-tree-label',
|
||||
}, [{id: 'level2.1'}]);
|
||||
databaseTreeNode = new TreeNode('database-tree-node', {
|
||||
_type: 'database',
|
||||
_id: 123,
|
||||
_label: 'some-database-label',
|
||||
}, [{id: 'database-tree-node'}]);
|
||||
pgBrowser.treeMenu.addChild(serverTreeNode, databaseTreeNode);
|
||||
|
||||
jquerySpy = jasmine.createSpy('jquerySpy');
|
||||
soNode = {
|
||||
__internal: {
|
||||
buttons: [{}, {}, {}, {
|
||||
element: {
|
||||
disabled: false,
|
||||
},
|
||||
}],
|
||||
},
|
||||
elements: {
|
||||
body: {
|
||||
childNodes: [
|
||||
{},
|
||||
],
|
||||
},
|
||||
content: jasmine.createSpyObj('content', ['appendChild', 'attr']),
|
||||
},
|
||||
};
|
||||
|
||||
soJQueryContainerSpy = jasmine.createSpyObj('soJQueryContainer', ['get', 'attr']);
|
||||
soJQueryContainerSpy.get.and.returnValue(soJQueryContainerSpy);
|
||||
|
||||
viewSchema = {};
|
||||
backform = jasmine.createSpyObj('backform', ['generateViewSchema', 'Dialog']);
|
||||
backform.generateViewSchema.and.returnValue(viewSchema);
|
||||
|
||||
soNodeChildNodeSpy = jasmine.createSpyObj('something', ['addClass']);
|
||||
jquerySpy.and.callFake((selector) => {
|
||||
if (selector === '<div class=\'search_objects_dialog\'></div>') {
|
||||
return soJQueryContainerSpy;
|
||||
} else if (selector === soNode.elements.body.childNodes[0]) {
|
||||
return soNodeChildNodeSpy;
|
||||
}
|
||||
});
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']);
|
||||
|
||||
});
|
||||
|
||||
describe('#prepare', () => {
|
||||
beforeEach(() => {
|
||||
soDialogWrapper = new SearchObjectsDialogWrapper(
|
||||
'<div class=\'search_objects_dialog\'></div>',
|
||||
'soDialogTitle',
|
||||
'search_objects',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
soDialogWrapper = Object.assign(soDialogWrapper, soNode);
|
||||
spyOn(soDialogWrapper, 'prepareDialog').and.callThrough();
|
||||
spyOn(soDialogWrapper, 'setTypes');
|
||||
spyOn(soDialogWrapper, 'setResultCount');
|
||||
});
|
||||
|
||||
context('no tree element is selected', () => {
|
||||
it('does not prepare dialog', () => {
|
||||
spyOn(soDialogWrapper, 'prepareDialog');
|
||||
soDialogWrapper.prepare();
|
||||
expect(soDialogWrapper.prepareDialog).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
context('selected tree node has no data', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.treeMenu.selectNode(noDataNode.domNode);
|
||||
});
|
||||
|
||||
it('does not prepare the dialog', () => {
|
||||
spyOn(soDialogWrapper, 'prepareDialog');
|
||||
soDialogWrapper.prepare();
|
||||
expect(soDialogWrapper.prepareDialog).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
context('tree element is selected', () => {
|
||||
let gridDestroySpy;
|
||||
let networkMock;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser.treeMenu.selectNode(databaseTreeNode.domNode);
|
||||
soDialogWrapper.grid = jasmine.createSpyObj('grid', ['destroy']);
|
||||
spyOn(soDialogWrapper, 'showMessage');
|
||||
gridDestroySpy = spyOn(soDialogWrapper.grid, 'destroy');
|
||||
|
||||
networkMock = new MockAdapter(axios);
|
||||
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
networkMock.restore();
|
||||
});
|
||||
|
||||
it('creates dialog and displays it', () => {
|
||||
soDialogWrapper.prepare();
|
||||
expect(soDialogWrapper.prepareDialog).toHaveBeenCalled();
|
||||
expect(soDialogWrapper.showMessage).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
|
||||
it('if grid set then destroy it', () => {
|
||||
soDialogWrapper.prepare();
|
||||
expect(gridDestroySpy).toHaveBeenCalled();
|
||||
expect(soDialogWrapper.grid).toBe(null);
|
||||
});
|
||||
|
||||
it('set result count to 0', () => {
|
||||
soDialogWrapper.prepare();
|
||||
expect(soDialogWrapper.setResultCount).toHaveBeenCalledWith(0);
|
||||
});
|
||||
|
||||
it('setTypes called before and after the ajax success', (done) => {
|
||||
networkMock.onGet('/search_objects/types/10/123').reply(200, {
|
||||
'data': {
|
||||
'type1': 'Type Label 1',
|
||||
'type2': 'Type Label 2',
|
||||
},
|
||||
});
|
||||
|
||||
soDialogWrapper.prepare();
|
||||
|
||||
expect(soDialogWrapper.setTypes.calls.argsFor(0)).toEqual([
|
||||
[{ id: -1, text: 'Loading...', value: null }], false,
|
||||
]);
|
||||
|
||||
setTimeout(()=>{
|
||||
expect(soDialogWrapper.setTypes.calls.argsFor(1)).toEqual([
|
||||
[{id: 'all', text: 'All types'},
|
||||
{id: 'type1', text: 'Type Label 1'},
|
||||
{id: 'type2', text: 'Type Label 2'}],
|
||||
]);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('setTypes called after the ajax fail', (done) => {
|
||||
networkMock.onGet('/search_objects/types/10/123').reply(500);
|
||||
|
||||
soDialogWrapper.prepare();
|
||||
|
||||
expect(soDialogWrapper.setTypes.calls.argsFor(0)).toEqual([
|
||||
[{ id: -1, text: 'Loading...', value: null }], false,
|
||||
]);
|
||||
|
||||
setTimeout(()=>{
|
||||
expect(soDialogWrapper.setTypes.calls.argsFor(1)).toEqual([
|
||||
[{id: -1, text: 'Failed', value: null }], false,
|
||||
]);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('showMessage', () => {
|
||||
beforeEach(() => {
|
||||
soDialogWrapper = new SearchObjectsDialogWrapper(
|
||||
'<div class=\'search_objects_dialog\'></div>',
|
||||
'soDialogTitle',
|
||||
'search_objects',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
soDialogWrapper.statusBar = document.createElement('div');
|
||||
soDialogWrapper.statusBar.classList.add('d-none');
|
||||
document.body.appendChild(soDialogWrapper.statusBar);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(soDialogWrapper.statusBar);
|
||||
});
|
||||
it('when info message', ()=>{
|
||||
soDialogWrapper.showMessage('locating', false);
|
||||
expect(soDialogWrapper.statusBar.classList.contains('d-none')).toBe(false);
|
||||
expect(soDialogWrapper.statusBar.querySelector('.error-in-footer')).toBe(null);
|
||||
expect(soDialogWrapper.statusBar.querySelector('.info-in-footer')).not.toBe(null);
|
||||
expect(soDialogWrapper.statusBar.querySelector('.alert-text').innerHTML).toEqual('locating');
|
||||
});
|
||||
|
||||
it('when error message', ()=>{
|
||||
soDialogWrapper.showMessage('some error', true);
|
||||
expect(soDialogWrapper.statusBar.classList.contains('d-none')).toBe(false);
|
||||
expect(soDialogWrapper.statusBar.querySelector('.error-in-footer')).not.toBe(null);
|
||||
expect(soDialogWrapper.statusBar.querySelector('.info-in-footer')).toBe(null);
|
||||
expect(soDialogWrapper.statusBar.querySelector('.alert-text').innerHTML).toEqual('some error');
|
||||
});
|
||||
|
||||
it('when no message', ()=>{
|
||||
soDialogWrapper.showMessage(null);
|
||||
expect(soDialogWrapper.statusBar.classList.contains('d-none')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('function', () => {
|
||||
beforeEach(() => {
|
||||
soDialogWrapper = new SearchObjectsDialogWrapper(
|
||||
'<div class=\'search_objects_dialog\'></div>',
|
||||
'soDialogTitle',
|
||||
'search_objects',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
});
|
||||
|
||||
it('updateDimOfSearchResult', ()=>{
|
||||
soDialogWrapper.searchResultContainer = document.createElement('div');
|
||||
soDialogWrapper.searchResult = document.createElement('div');
|
||||
spyOn(soDialogWrapper.searchResultContainer, 'getBoundingClientRect').and.returnValue({height:100, width: 50});
|
||||
|
||||
soDialogWrapper.updateDimOfSearchResult();
|
||||
expect(soDialogWrapper.searchResult.style.height).toEqual('100px');
|
||||
expect(soDialogWrapper.searchResult.style.width).toEqual('50px');
|
||||
});
|
||||
|
||||
it('setLoading', ()=>{
|
||||
soDialogWrapper.loader = document.createElement('div');
|
||||
soDialogWrapper.loader.innerHTML = `
|
||||
<div class="pg-sp-text"></div>
|
||||
`;
|
||||
|
||||
soDialogWrapper.setLoading('loading');
|
||||
expect(soDialogWrapper.loader.classList.contains('d-none')).toBe(false);
|
||||
expect(soDialogWrapper.loader.querySelector('.pg-sp-text').innerHTML).toEqual('loading');
|
||||
|
||||
soDialogWrapper.setLoading(null);
|
||||
expect(soDialogWrapper.loader.classList.contains('d-none')).toBe(true);
|
||||
});
|
||||
|
||||
it('searchBtnEnabled', ()=>{
|
||||
soDialogWrapper.searchBtn = document.createElement('button');
|
||||
|
||||
soDialogWrapper.searchBtnEnabled(true);
|
||||
expect(soDialogWrapper.searchBtn.disabled).toEqual(false);
|
||||
expect(soDialogWrapper.searchBtnEnabled()).toEqual(true);
|
||||
|
||||
soDialogWrapper.searchBtnEnabled(false);
|
||||
expect(soDialogWrapper.searchBtn.disabled).toEqual(true);
|
||||
expect(soDialogWrapper.searchBtnEnabled()).toEqual(false);
|
||||
});
|
||||
|
||||
it('searchBoxVal', ()=>{
|
||||
soDialogWrapper.searchBox = document.createElement('input');
|
||||
soDialogWrapper.searchBoxVal('abc');
|
||||
expect(soDialogWrapper.searchBox.value).toEqual('abc');
|
||||
expect(soDialogWrapper.searchBoxVal()).toEqual('abc');
|
||||
});
|
||||
|
||||
it('typesVal', ()=>{
|
||||
soDialogWrapper.typesSelect = document.createElement('select');
|
||||
let opt = document.createElement('option');
|
||||
opt.appendChild( document.createTextNode('Some type') );
|
||||
opt.value = 'sometype';
|
||||
soDialogWrapper.typesSelect.appendChild(opt);
|
||||
|
||||
soDialogWrapper.typesVal('sometype');
|
||||
expect(soDialogWrapper.typesSelect.value).toEqual('sometype');
|
||||
expect(soDialogWrapper.typesVal()).toEqual('sometype');
|
||||
});
|
||||
|
||||
it('setGridData', ()=>{
|
||||
soDialogWrapper.dataview = jasmine.createSpyObj('dataview', ['setItems']);
|
||||
soDialogWrapper.setGridData([{id:'somedata'}]);
|
||||
expect(soDialogWrapper.dataview.setItems).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('setGridData', ()=>{
|
||||
soDialogWrapper.searchResultCount = document.createElement('span');
|
||||
|
||||
soDialogWrapper.setResultCount(0);
|
||||
expect(soDialogWrapper.searchResultCount.innerHTML).toEqual('0 matches found.');
|
||||
|
||||
soDialogWrapper.setResultCount(1);
|
||||
expect(soDialogWrapper.searchResultCount.innerHTML).toEqual('1 match found.');
|
||||
|
||||
soDialogWrapper.setResultCount();
|
||||
expect(soDialogWrapper.searchResultCount.innerHTML).toEqual('Unknown matches found.');
|
||||
});
|
||||
|
||||
it('onDialogResize', ()=>{
|
||||
soDialogWrapper.grid = jasmine.createSpyObj('grid', ['autosizeColumns', 'resizeCanvas']);
|
||||
spyOn(soDialogWrapper, 'updateDimOfSearchResult');
|
||||
|
||||
soDialogWrapper.onDialogResize();
|
||||
expect(soDialogWrapper.updateDimOfSearchResult).toHaveBeenCalled();
|
||||
expect(soDialogWrapper.grid.resizeCanvas).toHaveBeenCalled();
|
||||
expect(soDialogWrapper.grid.autosizeColumns).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onDialogShow', (done)=>{
|
||||
spyOn(soDialogWrapper, 'prepareGrid').and.callFake(function() {
|
||||
this.grid = jasmine.createSpyObj('grid', ['init']);
|
||||
});
|
||||
|
||||
spyOn(soDialogWrapper, 'focusOnDialog');
|
||||
spyOn(soDialogWrapper, 'updateDimOfSearchResult');
|
||||
spyOn(soDialogWrapper, 'setGridData');
|
||||
spyOn(soDialogWrapper, 'onDialogResize');
|
||||
|
||||
|
||||
soDialogWrapper.onDialogShow();
|
||||
setTimeout(()=>{
|
||||
expect(soDialogWrapper.prepareGrid).toHaveBeenCalled();
|
||||
expect(soDialogWrapper.focusOnDialog).toHaveBeenCalled();
|
||||
expect(soDialogWrapper.setGridData).toHaveBeenCalledWith([]);
|
||||
expect(soDialogWrapper.onDialogResize).toHaveBeenCalled();
|
||||
done();
|
||||
}, 750);
|
||||
});
|
||||
|
||||
context('getCollNode', ()=>{
|
||||
it('type have same coll node', ()=>{
|
||||
let collNode = soDialogWrapper.getCollNode('sometype');
|
||||
expect(collNode.type).toEqual('coll-sometype');
|
||||
});
|
||||
|
||||
it('type does not same coll node', ()=>{
|
||||
let collNode = soDialogWrapper.getCollNode('someothertype');
|
||||
expect(collNode.type).toEqual('coll-sometype');
|
||||
});
|
||||
|
||||
it('type does not have coll node at all', ()=>{
|
||||
let collNode = soDialogWrapper.getCollNode('database');
|
||||
expect(collNode).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
it('finaliseData', ()=>{
|
||||
spyOn(soDialogWrapper, 'translateSearchObjectsPath').and.returnValue(['disp/path', 'id/path']);
|
||||
let data = soDialogWrapper.finaliseData({
|
||||
name: 'objname',
|
||||
type: 'sometype',
|
||||
type_label: 'Some types coll',
|
||||
path: ':some.123:/path',
|
||||
show_node: true,
|
||||
});
|
||||
expect(data).toEqual({
|
||||
id: 'id/path',
|
||||
icon: 'icon-sometype',
|
||||
name: 'objname',
|
||||
type: 'sometype',
|
||||
type_label: 'Some types coll',
|
||||
path: 'disp/path',
|
||||
id_path: 'id/path',
|
||||
show_node: true,
|
||||
});
|
||||
});
|
||||
|
||||
context('translateSearchObjectsPath', ()=>{
|
||||
let path = null, catalog_level = null;
|
||||
beforeEach(()=>{
|
||||
pgBrowser.Nodes = {
|
||||
'server_group': {
|
||||
type:'server_group',
|
||||
label: 'Server group',
|
||||
},
|
||||
'server': {
|
||||
type:'server',
|
||||
label: 'Server',
|
||||
},
|
||||
'coll-database': {
|
||||
type:'coll-database',
|
||||
label: 'Databases',
|
||||
},
|
||||
'database': {
|
||||
type:'database',
|
||||
label: 'Database',
|
||||
},
|
||||
'coll-schema': {
|
||||
type:'coll-schema',
|
||||
label: 'Schemas',
|
||||
},
|
||||
'schema': {
|
||||
type:'schema',
|
||||
label: 'Schema',
|
||||
},
|
||||
'coll-table': {
|
||||
type:'coll-table',
|
||||
label: 'Tables',
|
||||
},
|
||||
'table': {
|
||||
type:'table',
|
||||
label: 'Table',
|
||||
},
|
||||
'sometype': {
|
||||
type:'sometype',
|
||||
label: 'Some type',
|
||||
collection_type: 'coll-table',
|
||||
},
|
||||
'coll-catalog': {
|
||||
type:'coll-catalog',
|
||||
label: 'Catalogs',
|
||||
},
|
||||
'catalog': {
|
||||
type:'catalog',
|
||||
label: 'Catalog',
|
||||
},
|
||||
'coll-catalog_object': {
|
||||
type:'coll-catalog_object',
|
||||
label: 'Catalog Objects',
|
||||
},
|
||||
'catalog_object': {
|
||||
type:'catalog_object',
|
||||
label: 'catalog object',
|
||||
},
|
||||
};
|
||||
|
||||
soDialogWrapper.treeInfo = {
|
||||
'server_group': {'id': 'server_group/1', '_id': 1},
|
||||
'server': {'id': 'server/3', '_id': 3},
|
||||
'database': {'id': 'database/18456', '_id': 18456},
|
||||
};
|
||||
});
|
||||
it('regular schema', ()=>{
|
||||
path = ':schema.2200:/test_db/:table.2604:/sampletab';
|
||||
catalog_level = 'N';
|
||||
|
||||
let retVal = soDialogWrapper.translateSearchObjectsPath(path, catalog_level);
|
||||
expect(retVal).toEqual([
|
||||
'Schemas/test_db/Tables/sampletab',
|
||||
['server_group/1','server/3','coll-database/3','database/18456','coll-schema/18456','schema/2200','coll-table/2200','table/2604'],
|
||||
]);
|
||||
});
|
||||
|
||||
context('catalog schema', ()=>{
|
||||
it('with db support', ()=>{
|
||||
path = ':schema.11:/PostgreSQL Catalog (pg_catalog)/:table.2604:/pg_class';
|
||||
catalog_level = 'D';
|
||||
|
||||
let retVal = soDialogWrapper.translateSearchObjectsPath(path, catalog_level);
|
||||
expect(retVal).toEqual([
|
||||
'Catalogs/PostgreSQL Catalog (pg_catalog)/Tables/pg_class',
|
||||
['server_group/1','server/3','coll-database/3','database/18456','coll-catalog/18456','catalog/11','coll-table/11','table/2604'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('with object support only', ()=>{
|
||||
path = ':schema.11:/ANSI (information_schema)/:table.2604:/attributes';
|
||||
catalog_level = 'O';
|
||||
|
||||
let retVal = soDialogWrapper.translateSearchObjectsPath(path, catalog_level);
|
||||
expect(retVal).toEqual([
|
||||
'Catalogs/ANSI (information_schema)/Catalog Objects/attributes',
|
||||
['server_group/1','server/3','coll-database/3','database/18456','coll-catalog/18456','catalog/11','coll-catalog_object/11','catalog_object/2604'],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@@ -41,6 +41,9 @@ export class TreeFake extends Tree {
|
||||
this.aciTreeToOurTreeTranslator = {};
|
||||
this.aciTreeApi = jasmine.createSpyObj(
|
||||
'ACITreeApi', ['setInode', 'unload', 'deselect', 'select']);
|
||||
this.aciTreeApi.unload.and.callFake(function(domNode, config) {
|
||||
config.success();
|
||||
});
|
||||
}
|
||||
|
||||
addNewNode(id, data, domNode, path) {
|
||||
|
@@ -246,39 +246,70 @@ describe('tree tests', () => {
|
||||
|
||||
tree.aciTreeApi = jasmine.createSpyObj(
|
||||
'ACITreeApi', ['setInode', 'unload', 'deselect', 'select']);
|
||||
tree.aciTreeApi.unload.and.callFake((domNode, config) => {
|
||||
config.success();
|
||||
});
|
||||
});
|
||||
|
||||
it('reloads the node and its children', () => {
|
||||
level2.reload(tree);
|
||||
expect(tree.findNodeByDomElement([{id: 'level2'}])).toEqual(level2);
|
||||
it('reloads the node and its children', (done) => {
|
||||
level2.reload(tree)
|
||||
.then(()=>{
|
||||
expect(tree.findNodeByDomElement([{id: 'level2'}])).toEqual(level2);
|
||||
done();
|
||||
})
|
||||
.catch((error)=>{
|
||||
fail(error);
|
||||
});
|
||||
});
|
||||
|
||||
it('does not reload the children of node', () => {
|
||||
level2.reload(tree);
|
||||
expect(tree.findNodeByDomElement([{id: 'level3'}])).toBeNull();
|
||||
it('does not reload the children of node', (done) => {
|
||||
level2.reload(tree)
|
||||
.then(()=>{
|
||||
expect(tree.findNodeByDomElement([{id: 'level3'}])).toBeNull();
|
||||
done();
|
||||
})
|
||||
.catch((error)=>{
|
||||
fail(error);
|
||||
});
|
||||
});
|
||||
|
||||
it('select the node', (done) => {
|
||||
level2.reload(tree);
|
||||
setTimeout(() => {
|
||||
expect(tree.selected()).toEqual([{id: 'level2'}]);
|
||||
done();
|
||||
}, 20);
|
||||
level2.reload(tree)
|
||||
.then(()=>{
|
||||
setTimeout(() => {
|
||||
expect(tree.selected()).toEqual([{id: 'level2'}]);
|
||||
done();
|
||||
}, 20);
|
||||
})
|
||||
.catch((error)=>{
|
||||
fail(error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ACITree specific', () => {
|
||||
it('sets the current node as a Inode, changing the Icon back to +', () => {
|
||||
level2.reload(tree);
|
||||
expect(tree.aciTreeApi.setInode).toHaveBeenCalledWith([{id: 'level2'}]);
|
||||
it('sets the current node as a Inode, changing the Icon back to +', (done) => {
|
||||
level2.reload(tree)
|
||||
.then(()=>{
|
||||
expect(tree.aciTreeApi.setInode).toHaveBeenCalledWith([{id: 'level2'}]);
|
||||
done();
|
||||
})
|
||||
.catch((error)=>{
|
||||
fail(error);
|
||||
});
|
||||
});
|
||||
|
||||
it('deselect the node and selects it again to trigger ACI tree' +
|
||||
' events', (done) => {
|
||||
level2.reload(tree);
|
||||
setTimeout(() => {
|
||||
expect(tree.aciTreeApi.deselect).toHaveBeenCalledWith([{id: 'level2'}]);
|
||||
done();
|
||||
}, 20);
|
||||
level2.reload(tree)
|
||||
.then(()=>{
|
||||
setTimeout(() => {
|
||||
expect(tree.aciTreeApi.deselect).toHaveBeenCalledWith([{id: 'level2'}]);
|
||||
done();
|
||||
}, 20);
|
||||
})
|
||||
.catch((error)=>{
|
||||
fail(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -292,17 +323,32 @@ describe('tree tests', () => {
|
||||
level2 = tree.addNewNode('level2', {data: 'data'}, ['<li>level2</li>'], ['level1']);
|
||||
tree.addNewNode('level3', {data: 'more data'}, ['<li>level3</li>'], ['level1', 'level2']);
|
||||
tree.aciTreeApi = jasmine.createSpyObj('ACITreeApi', ['unload']);
|
||||
tree.aciTreeApi.unload.and.callFake((domNode, config) => {
|
||||
config.success();
|
||||
});
|
||||
});
|
||||
|
||||
it('unloads the children of the current node', () => {
|
||||
level2.unload(tree);
|
||||
expect(tree.findNodeByDomElement([{id: 'level2'}])).toEqual(level2);
|
||||
expect(tree.findNodeByDomElement([{id: 'level3'}])).toBeNull();
|
||||
it('unloads the children of the current node', (done) => {
|
||||
level2.unload(tree)
|
||||
.then(()=>{
|
||||
expect(tree.findNodeByDomElement([{id: 'level2'}])).toEqual(level2);
|
||||
expect(tree.findNodeByDomElement([{id: 'level3'}])).toBeNull();
|
||||
done();
|
||||
})
|
||||
.catch((error)=>{
|
||||
fail(error);
|
||||
});
|
||||
});
|
||||
|
||||
it('calls unload on the ACI Tree', () => {
|
||||
level2.unload(tree);
|
||||
expect(tree.aciTreeApi.unload).toHaveBeenCalledWith(['<li>level2</li>']);
|
||||
it('calls unload on the ACI Tree', (done) => {
|
||||
level2.unload(tree)
|
||||
.then(()=>{
|
||||
expect(tree.aciTreeApi.unload).toHaveBeenCalledWith(['<li>level2</li>'], jasmine.any(Object));
|
||||
done();
|
||||
})
|
||||
.catch((error)=>{
|
||||
fail(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -494,7 +494,8 @@ module.exports = [{
|
||||
',pgadmin.tools.debugger.controller' +
|
||||
',pgadmin.tools.debugger.direct' +
|
||||
',pgadmin.node.pga_job' +
|
||||
',pgadmin.tools.schema_diff',
|
||||
',pgadmin.tools.schema_diff' +
|
||||
',pgadmin.tools.search_objects',
|
||||
},
|
||||
}, {
|
||||
test: require.resolve('snapsvg'),
|
||||
|
@@ -277,6 +277,8 @@ var webpackShimConfig = {
|
||||
'pgadmin.tools.restore': path.join(__dirname, './pgadmin/tools/restore/static/js/restore'),
|
||||
'pgadmin.tools.schema_diff': path.join(__dirname, './pgadmin/tools/schema_diff/static/js/schema_diff'),
|
||||
'pgadmin.tools.schema_diff_ui': path.join(__dirname, './pgadmin/tools/schema_diff/static/js/schema_diff_ui'),
|
||||
'pgadmin.tools.search_objects': path.join(__dirname, './pgadmin/tools/search_objects/static/js/search_objects'),
|
||||
'pgadmin.search_objects': path.join(__dirname, './pgadmin/tools/search_objects/static/js'),
|
||||
'pgadmin.tools.user_management': path.join(__dirname, './pgadmin/tools/user_management/static/js/user_management'),
|
||||
'pgadmin.user_management.current_user': '/user_management/current_user',
|
||||
'slick.pgadmin.editors': path.join(__dirname, './pgadmin/tools/../static/js/slickgrid/editors'),
|
||||
|
@@ -105,6 +105,7 @@ module.exports = {
|
||||
'pgadmin.browser.preferences': path.join(__dirname, './pgadmin/browser/static/js/preferences'),
|
||||
'pgadmin.browser.activity': path.join(__dirname, './pgadmin/browser/static/js/activity'),
|
||||
'bundled_codemirror': path.join(__dirname, './pgadmin/static/bundle/codemirror'),
|
||||
'tools': path.join(__dirname, './pgadmin/tools/'),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
1177
web/yarn.lock
1177
web/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user