Added support for the catalog objects under special catalogs. (also,

added support for columns under it).
This commit is contained in:
Murtuza Zabuawala 2016-03-11 01:08:21 +05:30 committed by Ashesh Vashi
parent 87623cb997
commit 5347bdb886
15 changed files with 882 additions and 0 deletions

View File

@ -0,0 +1,300 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
""" Implements Catalog objects Node."""
from flask import render_template
from flask.ext.babel import gettext
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
import SchemaChildModule
import pgadmin.browser.server_groups.servers.databases as database
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
from functools import wraps
class CatalogObjectModule(SchemaChildModule):
"""
class CatalogObjectModule(SchemaChildModule)
A module class for Catalog objects node derived from SchemaChildModule.
Methods:
-------
* __init__(*args, **kwargs)
- Method is used to initialize the Catalog objects and it's base module.
* get_nodes(gid, sid, did, scid, coid)
- Method is used to generate the browser collection node.
* script_load()
- Load the module script for Catalog objects, when any of the server node
is initialized.
"""
NODE_TYPE = 'catalog_object'
COLLECTION_LABEL = gettext("Catalog Objects")
# Flag for not to show node under Schema/Catalog node
# By default its set to True to display node in schema/catalog
# We do not want to display 'Catalog Objects' under Schema/Catalog
# but only in information_schema/sys/dbo
CATALOG_DB_SUPPORTED = False
SUPPORTED_SCHEMAS = ['information_schema', 'sys', 'dbo']
def __init__(self, *args, **kwargs):
"""
Method is used to initialize the CatalogObjectModule and it's base module.
Args:
*args:
**kwargs:
"""
super(CatalogObjectModule, self).__init__(*args, **kwargs)
self.min_ver = None
self.max_ver = None
def get_nodes(self, gid, sid, did, scid):
"""
Generate the collection node
"""
yield self.generate_browser_collection_node(scid)
@property
def script_load(self):
"""
Load the module script for server, when any of the database node is
initialized.
"""
return database.DatabaseModule.NODE_TYPE
blueprint = CatalogObjectModule(__name__)
class CatalogObjectView(PGChildNodeView):
"""
This class is responsible for generating routes for Catalog objects node.
Methods:
-------
* check_precondition()
- This function will behave as a decorator which will checks
database connection before running view, it will also attaches
manager,conn & template_path properties to self
* list()
- Lists all the Catalog objects nodes within that collection.
* nodes()
- Creates all the nodes of type Catalog objects.
* properties(gid, sid, did, scid, coid)
- Shows the properties of the selected Catalog objects node.
* dependency(gid, sid, did, scid):
- Returns the dependencies list for the given catalog object node.
* dependent(gid, sid, did, scid):
- Returns the dependents list for the given Catalog objects node.
"""
node_type = blueprint.node_type
parent_ids = [
{'type': 'int', 'id': 'gid'},
{'type': 'int', 'id': 'sid'},
{'type': 'int', 'id': 'did'},
{'type': 'int', 'id': 'scid'}
]
ids = [
{'type': 'int', 'id': 'coid'}
]
operations = dict({
'obj': [{'get': 'properties'}, {'get': 'list'}],
'children': [{'get': 'children'}],
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
'sql': [{'get': 'sql'}],
'dependency': [{'get': 'dependencies'}],
'dependent': [{'get': 'dependents'}],
'module.js': [{}, {}, {'get': 'module_js'}]
})
def check_precondition(f):
"""
This function will behave as a decorator which will checks
database connection before running view, it will also attaches
manager,conn & template_path properties to self
"""
@wraps(f)
def wrap(*args, **kwargs):
# Here args[0] will hold self & kwargs will hold gid,sid,did
self = args[0]
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
self.template_path = 'catalog_object/sql/{0}/9.1_plus'.format(
'ppas' if self.manager.server_type == 'ppas' else 'pg'
)
return f(*args, **kwargs)
return wrap
@check_precondition
def list(self, gid, sid, did, scid):
"""
This function is used to list all the catalog objects
nodes within that collection.
Args:
gid: Server group ID
sid: Server ID
did: Database ID
scid: Schema ID
Returns:
JSON of available catalog objects nodes
"""
SQL = render_template("/".join([
self.template_path, 'properties.sql'
]), scid=scid
)
status, res = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
return ajax_response(
response=res['rows'],
status=200
)
@check_precondition
def nodes(self, gid, sid, did, scid):
"""
This function will used to create all the child node within that collection.
Here it will create all the catalog objects node.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
Returns:
JSON of available catalog objects child nodes
"""
res = []
SQL = render_template(
"/".join([self.template_path, 'nodes.sql']), scid=scid
)
status, rset = self.conn.execute_2darray(SQL)
if not status:
return internal_server_error(errormsg=rset)
for row in rset['rows']:
res.append(
self.blueprint.generate_browser_node(
row['oid'],
scid,
row['name'],
icon="icon-catalog_object"
))
return make_json_response(
data=res,
status=200
)
@check_precondition
def properties(self, gid, sid, did, scid, coid):
"""
This function will show the properties of the selected
catalog objects node.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
scid: Schema ID
coid: Catalog object ID
Returns:
JSON of selected catalog objects node
"""
SQL = render_template(
"/".join([self.template_path, 'properties.sql']),
scid=scid, coid=coid
)
status, res = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
return ajax_response(
response=res['rows'][0],
status=200
)
@check_precondition
def dependents(self, gid, sid, did, scid, coid):
"""
This function get the dependents and return ajax response
for the catalog objects node.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
coid: catalog objects ID
"""
dependents_result = self.get_dependents(self.conn, coid)
return ajax_response(
response=dependents_result,
status=200
)
@check_precondition
def dependencies(self, gid, sid, did, scid, coid):
"""
This function get the dependencies and return ajax response
for the catalog objects node.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
coid: catalog objects ID
"""
dependencies_result = self.get_dependencies(self.conn, coid)
return ajax_response(
response=dependencies_result,
status=200
)
CatalogObjectView.register_node_view(blueprint)

View File

@ -0,0 +1,343 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
""" Implements Columns Node (For Catalog objects) """
from flask import render_template
from flask.ext.babel import gettext
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.browser.collection import CollectionNodeModule
import pgadmin.browser.server_groups.servers.databases as database
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
from functools import wraps
class CatalogObjectColumnsModule(CollectionNodeModule):
"""
class ColumnModule(CollectionNodeModule)
A module class for column node derived from CollectionNodeModule.
Methods:
-------
* __init__(*args, **kwargs)
- Method is used to initialize the column and it's base module.
* get_nodes(gid, sid, did, scid, coid)
- Method is used to generate the browser collection node.
* node_inode()
- Method is overridden from its base class to make the node as leaf node.
* script_load()
- Load the module script for column, when any of the server node is
initialized.
"""
NODE_TYPE = 'catalog_object_column'
COLLECTION_LABEL = gettext("Columns")
def __init__(self, *args, **kwargs):
"""
Method is used to initialize the ColumnModule and it's base module.
Args:
*args:
**kwargs:
"""
super(CatalogObjectColumnsModule, self).__init__(*args, **kwargs)
self.min_ver = None
self.max_ver = None
def get_nodes(self, gid, sid, did, scid, coid):
"""
Generate the collection node
"""
yield self.generate_browser_collection_node(coid)
@property
def script_load(self):
"""
Load the module script for server, when any of the database node is
initialized.
"""
return database.DatabaseModule.NODE_TYPE
@property
def node_inode(self):
"""
Load the module node as a leaf node
"""
return False
blueprint = CatalogObjectColumnsModule(__name__)
class CatalogObjectColumnsView(PGChildNodeView):
"""
This class is responsible for generating routes for column node
Methods:
-------
* __init__(**kwargs)
- Method is used to initialize the ColumnView and it's base view.
* check_precondition()
- This function will behave as a decorator which will checks
database connection before running view, it will also attaches
manager,conn & template_path properties to self
* list()
- Returns the properties of all the columns for the catalog object.
* nodes()
- Creates and returns all the children nodes of type - catalog object
column.
* properties(gid, sid, did, scid, coid, clid)
- Returns the properties of the given catalog-object column node.
* dependency(gid, sid, did, scid, coid, clid):
- Returns the dependencies list of the given node.
* dependent(gid, sid, did, scid, coid, clid):
- Returns the dependents list of the given node.
"""
node_type = blueprint.node_type
parent_ids = [
{'type': 'int', 'id': 'gid'},
{'type': 'int', 'id': 'sid'},
{'type': 'int', 'id': 'did'},
{'type': 'int', 'id': 'scid'},
{'type': 'int', 'id': 'coid'}
]
ids = [
{'type': 'int', 'id': 'clid'}
]
operations = dict({
'obj': [{'get': 'properties'}, {'get': 'list'}],
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
'sql': [{'get': 'sql'}],
'dependency': [{'get': 'dependencies'}],
'dependent': [{'get': 'dependents'}],
'module.js': [{}, {}, {'get': 'module_js'}]
})
def check_precondition(f):
"""
This function will behave as a decorator which will checks
database connection before running view, it will also attaches
manager,conn & template_path properties to self
"""
@wraps(f)
def wrap(*args, **kwargs):
# Here args[0] will hold self & kwargs will hold gid,sid,did
self = args[0]
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
self.template_path = 'catalog_object_column/sql/9.1_plus'
return f(*args, **kwargs)
return wrap
@check_precondition
def list(self, gid, sid, did, scid, coid):
"""
This function is used to list all the column
nodes within that collection.
Args:
gid: Server group ID
sid: Server ID
did: Database ID
scid: Schema ID
coid: Catalog objects ID
Returns:
JSON of available column nodes
"""
SQL = render_template("/".join([self.template_path,
'properties.sql']), coid=coid)
status, res = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
return ajax_response(
response=res['rows'],
status=200
)
@check_precondition
def nodes(self, gid, sid, did, scid, coid):
"""
This function will used to create all the child node within that collection.
Here it will create all the column node.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
coid: Catalog objects ID
Returns:
JSON of available column child nodes
"""
res = []
SQL = render_template("/".join([self.template_path,
'nodes.sql']), coid=coid)
status, rset = self.conn.execute_2darray(SQL)
if not status:
return internal_server_error(errormsg=rset)
for row in rset['rows']:
res.append(
self.blueprint.generate_browser_node(
row['atttypid'],
coid,
row['attname'],
icon="icon-catalog_object_column"
))
return make_json_response(
data=res,
status=200
)
@check_precondition
def properties(self, gid, sid, did, scid, coid, clid):
"""
This function will show the properties of the selected
column node.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
scid: Schema ID
coid: Catalog object ID
clid: Column ID
Returns:
JSON of selected column node
"""
SQL = render_template("/".join([self.template_path,
'properties.sql']),coid=coid, clid=clid)
status, res = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
return ajax_response(
response=res['rows'][0],
status=200
)
@check_precondition
def dependents(self, gid, sid, did, scid, coid, clid):
"""
This function get the dependents and return ajax response
for the column node.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
coid: Catalog object ID
clid: Column ID
"""
# Specific condition for column which we need to append
where = "WHERE dep.refobjid={0}::OID AND dep.refobjsubid={1}".format(
coid, clid
)
dependents_result = self.get_dependents(
self.conn, clid, where=where
)
# Specific sql to run againt column to fetch dependents
SQL = render_template("/".join([self.template_path,
'depend.sql']), where=where)
status, res = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
for row in res['rows']:
ref_name = row['refname']
if ref_name is None:
continue
dep_type = ''
dep_str = row['deptype']
if dep_str == 'a':
dep_type = 'auto'
elif dep_str == 'n':
dep_type = 'normal'
elif dep_str == 'i':
dep_type = 'internal'
dependents_result.append({'type': 'sequence', 'name': ref_name, 'field': dep_type})
return ajax_response(
response=dependents_result,
status=200
)
@check_precondition
def dependencies(self, gid, sid, did, scid, coid, clid):
"""
This function get the dependencies and return ajax response
for the column node.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
coid: Catalog objects ID
clid: Column ID
"""
# Specific condition for column which we need to append
where = "WHERE dep.objid={0}::OID AND dep.objsubid={1}".format(
coid, clid
)
dependencies_result = self.get_dependencies(
self.conn, clid, where=where
)
return ajax_response(
response=dependencies_result,
status=200
)
CatalogObjectColumnsView.register_node_view(blueprint)

View File

@ -0,0 +1,73 @@
define(
['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'],
function($, _, S, pgAdmin, pgBrowser, alertify) {
if (!pgBrowser.Nodes['coll-catalog_object_column']) {
var databases = pgAdmin.Browser.Nodes['coll-catalog_object_column'] =
pgAdmin.Browser.Collection.extend({
node: 'catalog_object_column',
label: '{{ _('catalog_object_column') }}',
type: 'coll-catalog_object_column'
});
};
if (!pgBrowser.Nodes['catalog_object_column']) {
pgAdmin.Browser.Nodes['catalog_object_column'] =
pgAdmin.Browser.Node.extend({
parent_type: 'catalog_object',
type: 'catalog_object_column',
label: '{{ _('catalog_object_column') }}',
hasSQL: false,
hasDepends: true,
Init: function() {
/* Avoid mulitple registration of menus */
if (this.initialized)
return;
this.initialized = true;
},
model: pgAdmin.Browser.Node.Model.extend({
defaults: {
attname: undefined,
attowner: undefined,
atttypid: undefined,
attnum: undefined,
cltype: undefined,
collspcname: undefined,
attacl: undefined,
description: undefined
},
schema: [{
id: 'attname', label: '{{ _('Column') }}', cell: 'string',
type: 'text', disabled: true
},{
id: 'atttypid', label: '{{ _('Oid') }}', cell: 'string',
type: 'text', disabled: true
},{
id: 'attowner', label: '{{ _('Owner') }}', cell: 'string',
type: 'text', disabled: true
},{
id: 'attnum', label:'{{ _('Position') }}', cell: 'string',
type: 'text', disabled: true
},{
id: 'cltype', label:'{{ _('Data type') }}', cell: 'string',
type: 'text', disabled: true
},{
id: 'collspcname', label:'{{ _('Collation') }}', cell: 'string',
type: 'text', disabled: true
},{
id: 'attacl', label:'{{ _('ACL') }}', cell: 'string',
type: 'text', disabled: true
},{
id: 'description', label:'{{ _('Comment') }}', cell: 'string',
type: 'multiline', disabled: true
}
]
})
});
}
return pgBrowser.Nodes['catalog_object_column'];
});

View File

@ -0,0 +1,10 @@
SELECT
ref.relname AS refname, d2.refclassid, dep.deptype AS deptype
FROM pg_depend dep
LEFT JOIN pg_depend d2 ON dep.objid=d2.objid AND dep.refobjid != d2.refobjid
LEFT JOIN pg_class ref ON ref.oid=d2.refobjid
LEFT JOIN pg_attribute att ON d2.refclassid=att.attrelid AND d2.refobjsubid=att.attnum
{{ where }} AND
dep.classid=(SELECT oid FROM pg_class WHERE relname='pg_attrdef') AND
dep.refobjid NOT IN (SELECT d3.refobjid FROM pg_depend d3 WHERE d3.objid=d2.refobjid)
ORDER BY refname;

View File

@ -0,0 +1,7 @@
SELECT
atttypid, attname
FROM pg_attribute att
WHERE att.attrelid = {{coid}}::oid
AND att.attnum > 0
AND att.attisdropped IS FALSE
ORDER BY att.attnum

View File

@ -0,0 +1,41 @@
SELECT
att.*, def.*, pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS defval,
CASE WHEN att.attndims > 0 THEN 1 ELSE 0 END AS isarray,
format_type(ty.oid,NULL) AS typname,
format_type(ty.oid,att.atttypmod) AS displaytypname,
tn.nspname as typnspname, et.typname as elemtypname,
ty.typstorage AS defaultstorage, cl.relname, na.nspname,
att.attstattarget, description, cs.relname AS sername,
ns.nspname AS serschema,
(SELECT count(1) FROM pg_type t2 WHERE t2.typname=ty.typname) > 1 AS isdup,
indkey, coll.collname, nspc.nspname as collnspname , attoptions,
-- Start pgAdmin4, added to save time on client side parsing
CASE WHEN length(coll.collname) > 0 AND length(nspc.nspname) > 0 THEN
concat(coll.collname,'."',nspc.nspname,'"')
ELSE '' END AS collspcname,
CASE WHEN strpos(format_type(ty.oid,att.atttypmod), '.') > 0 THEN
split_part(format_type(ty.oid,att.atttypmod), '.', 2)
ELSE format_type(ty.oid,att.atttypmod) END AS cltype,
-- End pgAdmin4
EXISTS(SELECT 1 FROM pg_constraint WHERE conrelid=att.attrelid AND contype='f' AND att.attnum=ANY(conkey)) As isfk,
(SELECT array_agg(label) FROM pg_seclabels sl1 WHERE sl1.objoid=att.attrelid AND sl1.objsubid=att.attnum) AS labels,
(SELECT array_agg(provider) FROM pg_seclabels sl2 WHERE sl2.objoid=att.attrelid AND sl2.objsubid=att.attnum) AS providers
FROM pg_attribute att
JOIN pg_type ty ON ty.oid=atttypid
JOIN pg_namespace tn ON tn.oid=ty.typnamespace
JOIN pg_class cl ON cl.oid=att.attrelid
JOIN pg_namespace na ON na.oid=cl.relnamespace
LEFT OUTER JOIN pg_type et ON et.oid=ty.typelem
LEFT OUTER JOIN pg_attrdef def ON adrelid=att.attrelid AND adnum=att.attnum
LEFT OUTER JOIN pg_description des ON (des.objoid=att.attrelid AND des.objsubid=att.attnum AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN (pg_depend JOIN pg_class cs ON objid=cs.oid AND cs.relkind='S') ON refobjid=att.attrelid AND refobjsubid=att.attnum
LEFT OUTER JOIN pg_namespace ns ON ns.oid=cs.relnamespace
LEFT OUTER JOIN pg_index pi ON pi.indrelid=att.attrelid AND indisprimary
LEFT OUTER JOIN pg_collation coll ON att.attcollation=coll.oid
LEFT OUTER JOIN pg_namespace nspc ON coll.collnamespace=nspc.oid
WHERE att.attrelid = {{coid}}::oid{% if clid %}
AND att.atttypid = {{clid}}::oid
{% endif %}
AND att.attnum > 0
AND att.attisdropped IS FALSE
ORDER BY att.attnum

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

View File

@ -0,0 +1,56 @@
define(
['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'],
function($, _, S, pgAdmin, pgBrowser, alertify) {
if (!pgBrowser.Nodes['coll-catalog_object']) {
var databases = pgAdmin.Browser.Nodes['coll-catalog_object'] =
pgAdmin.Browser.Collection.extend({
node: 'catalog_object',
label: '{{ _('Catalog Objects') }}',
type: 'coll-catalog_object'
});
};
if (!pgBrowser.Nodes['catalog_object']) {
pgAdmin.Browser.Nodes['catalog_object'] = pgAdmin.Browser.Node.extend({
parent_type: 'catalog',
type: 'catalog_object',
label: '{{ _('Catalog Object') }}',
hasSQL: false,
hasDepends: true,
Init: function() {
/* Avoid mulitple registration of menus */
if (this.initialized)
return;
this.initialized = true;
},
model: pgAdmin.Browser.Node.Model.extend({
defaults: {
name: undefined,
namespaceowner: undefined,
nspacl: undefined,
description: undefined,
},
schema: [{
id: 'name', label: '{{ _('Name') }}', cell: 'string',
type: 'text', disabled: true
},{
id: 'oid', label:'{{ _('Oid') }}', cell: 'string',
type: 'text', disabled: true
},{
id: 'owner', label:'{{ _('Owner') }}', cell: 'string',
type: 'text', disabled: true
},{
id: 'description', label:'{{ _('Comment') }}', cell: 'string',
type: 'multiline' , disabled: true
}
]
})
});
}
return pgBrowser.Nodes['catalog_object'];
});

View File

@ -0,0 +1,6 @@
SELECT
c.oid, c.relname as name
FROM
pg_class c
WHERE relnamespace = {{scid}}::int
ORDER BY relname;

View File

@ -0,0 +1,12 @@
SELECT
c.oid, c.relname as name, r.rolname AS owner, description
FROM
pg_class c
LEFT OUTER JOIN pg_description d
ON d.objoid=c.oid AND d.classoid='pg_class'::regclass
LEFT JOIN pg_roles r ON c.relowner = r.oid
WHERE
relnamespace = {{scid}}::int
{% if coid %} AND
c.oid = {{coid}}::int
{% endif %} ORDER BY relname;

View File

@ -0,0 +1,11 @@
SELECT
c.oid, c.relname as name
FROM pg_class c
WHERE relnamespace = {{scid}}::int
OR (
-- On EnterpriseDB we need to ignore some objects in the catalog, namely, _*, dual and type_object_source.
select 'sys' ~ (SELECT nsp.nspname FROM pg_namespace nsp WHERE nsp.oid = {{scid}}::int)
AND
(c.relname NOT LIKE '\\_%' AND c.relname = 'dual' AND c.relname = 'type_object_source')
)
ORDER BY relname;

View File

@ -0,0 +1,23 @@
SELECT
c.oid, c.relname as name, r.rolname AS owner, description
FROM
pg_class c
LEFT OUTER JOIN pg_description d
ON d.objoid=c.oid AND d.classoid='pg_class'::regclass
LEFT JOIN pg_roles r ON c.relowner = r.oid
WHERE
relnamespace = {{scid}}::int
{% if coid %} AND
c.oid = {{coid}}::int
{% endif %} OR (
-- On EnterpriseDB - ignore some objects in the catalog, whose name starts
-- with _*, dual and type_object_source.
SELECT 'sys' ~ (
SELECT nsp.nspname FROM pg_namespace nsp
WHERE nsp.oid = {{scid}}::int
) AND (
c.relname NOT LIKE '\\_%' AND c.relname = 'dual' AND
c.relname = 'type_object_source'
)
)
ORDER BY relname;