Re: Schemas: status report, call for developers - Mailing list pgsql-hackers

From Ian Barwick
Subject Re: Schemas: status report, call for developers
Date
Msg-id 200205261956.49018.barwick@gmx.net
Whole thread Raw
In response to Re: Schemas: status report, call for developers  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: Schemas: status report, call for developers
List pgsql-hackers
On Wednesday 01 May 2002 06:38, Tom Lane wrote:
> Ian Barwick <barwick@gmx.net> writes:
> > How can I restrict the query to the schemas in the
> > current search path, i.e. the schema names returned
> > by SELECT current_schemas() ?
>
> Well, this is the issue open for public discussion.
>
> We could define some function along the lines of
> "is_visible_table(oid) returns bool", and then you could use
> that as a WHERE clause in your query.  But I'm worried about
> the performance implications --- is_visible_table() would have
> to do several retail probes of the system tables, and I don't
> see any way to optimize that across hundreds of table OIDs.
>
> I have a nagging feeling that this could be answered by defining
> a view on pg_class that only shows visible tables ... but I don't
> quite see how to define that efficiently, either.  Ideas anyone?

(time passes...)

How about a function such as the one attached: "select_schemas_setof()"
which returns the OIDs of the schemas in the current search path as
a set. (Note: "select_schemas_setof()" as shown is a userspace C function.)

It works like this:
 template1=# CREATE DATABASE schema_test; CREATE DATABASE template1=# \c schema_test You are now connected to database
schema_test.schema_test=# CREATE OR REPLACE FUNCTION current_schemas_setof() schema_test-# RETURNS setof OID
schema_test-#as '/path/to/current_schemas_setof.so' schema_test-# LANGUAGE 'C'; CREATE FUNCTION 


I can then do this:
 schema_test=# CREATE SCHEMA foo; CREATE SCHEMA schema_test=# CREATE TABLE foo.mytab(col1 int, col2 text); CREATE TABLE
schema_test=#CREATE SCHEMA bar; CREATE SCHEMA schema_test=# CREATE TABLE bar.mytab(col1 int, col2 text); CREATE TABLE
schema_test=#SET search_path = public, foo, bar; SET schema_test=# SELECT current_schemas(); current_schemas
------------------{public,foo,bar} (1 row) 
 schema_test=# SELECT current_schemas_setof, n.nspname schema_test-#   FROM public.current_schemas_setof() cs,
pg_namespacen schema_test-#  WHERE cs.current_schemas_setof = n.oid; current_schemas_setof | nspname
----------------------+------------                16563 | pg_temp_1                    11 | pg_catalog
2200 | public                 24828 | foo                 24835 | bar (3 rows) 


With the function in place I can then create an SQL function like this:
 CREATE OR REPLACE FUNCTION public.first_visible_namespace(name) RETURNS oid AS 'SELECT n.oid    FROM pg_namespace n,
pg_classc, public.current_schemas_setof() cs   WHERE c.relname= $1     AND c.relnamespace=n.oid     AND n.oid=
cs.current_schemas_setof  LIMIT 1' LANGUAGE 'sql'; 

which can be used like this:
 schema_test=# select public.first_visible_namespace('mytab'); first_visible_namespace -------------------------
          24828 (1 row) 

i.e. finds the first visible schema containing an unqualified relation name.
24828 corresponds to the OID of schema "foo".

The following VIEW:
 CREATE VIEW public.desc_table_view AS SELECT n.nspname AS "Schema",       c.relname AS "Table",       a.attname AS
"Column",      format_type    (a.atttypid, a.atttypmod) AS "Type" FROM pg_class c, pg_attribute a, pg_namespace n WHERE
a.attnum> 0   AND c.relkind IN ('r', 'v', 'S')   AND a.attrelid = c.oid   AND c.relnamespace=n.oid   AND n.oid IN
(SELECTfirst_visible_namespace(c.relname)) ORDER BY a.attnum; 

then provides a simplified simulation of psql's slash command \d [NAME] for
unqualified relation names, e.g.:
 schema_test=# SELECT * FROM public.desc_table_view WHERE "Table" = 'mytab'; Schema | Table | Column |  Type
--------+-------+--------+---------foo    | mytab | col1   | integer foo    | mytab | col2   | text (2 rows)
schema_test=#SET search_path= bar, foo, public; SET schema_test=# SELECT * FROM public.desc_table_view WHERE "Table" =
'mytab';Schema | Table | Column |  Type --------+-------+--------+--------- bar    | mytab | col1   | integer bar    |
mytab| col2   | text (2 rows) 
 schema_test=# SET search_path= public; SET schema_test=# SELECT * FROM public.desc_table_view WHERE "Table" = 'mytab';
Schema| Table | Column | Type --------+-------+--------+------ (0 rows) 


which I think is the desired behaviour. Currently \d [NAME] produces this: schema_test=# SET search_path= bar, foo,
public;SET schema_test=# \d mytab         Table "mytab" Column |  Type   | Modifiers--------+---------+----------- col1
 | integer | col1   | integer | col2   | text    | col2   | text    | 

i.e. finds and describes "foo.mytab" and "bar.mytab".

(Note: "SELECT * FROM public.desc_table_view" will just dump an unordered
list of all columns for the first visible instance of each table name).

Assuming "current_schemas_setof()" can be implemented as an internal function,
(I haven't managed it myself yet :-( ), I suspect it is a more efficient
alternative to a putative "is_visible_table(oid)" and could be used in psql
(and elsewhere) to resolve the schemas of unqualified relation names.
Thoughts? (Or am I barking up the wrong tree?)

BTW is anyone working on schema support in psql? If the various definition
issues raised by Tom Lane at the start of this thread are resolved (discussion
seems to have trailed off without a consensus), I have some free time in June
and would be willing to take it on.


Ian Barwick



pgsql-hackers by date:

Previous
From: Ian Barwick
Date:
Subject: Re: Q: unexpected result from SRF in SQL
Next
From: Tom Lane
Date:
Subject: Re: pgstatindex