On Sat, 2006-06-03 at 13:43 -0400, Michael Bayer wrote:
> we've had a lot of issues with Postgres and using  
> information_schema.  whereas MySQL's information_schema support was  
> pointless, Postgres mostly works, but performs very slowly unless you  
> VACUUM your database every hour.  we've had reports of primary keys  
> not being reflected for tables across user names as well.

The information schema is implemented as a set of views on
system relations.  I suspect vacuuming every hour is not really
the issue, unless you are doing a lot of metadata changes.
A "VACUUM FULL ANALYZE" by a database superuser is probably
a good thing once your table metadata settles down.  This
is something the DBA would take care of, one of the reasons
that implementation programmers aren't usually permitted
to create ad hock changes to tables.

As to the reason that some attributes are only visible to
relation owners look for the "u.usesysid = c.relowner" and
the subsequent criteria in the definition of the view.
So it is on purpose.  I would guess that it meets some security
criteria in the standard since they actually went to the trouble
of adding it in.  One question to ask might be are people relying
on being DB superusers or were specific grants made?  (examine
the output of \z from psql).  The information schema doesn't
take into account DB superusers:

sat=# \d information_schema.columns
                     View "information_schema.columns"
          Column          |                Type                |
Modifiers
--------------------------+------------------------------------+-----------
 table_catalog            | information_schema.sql_identifier  |
 table_schema             | information_schema.sql_identifier  |
 table_name               | information_schema.sql_identifier  |
 column_name              | information_schema.sql_identifier  |
 ordinal_position         | information_schema.cardinal_number |
 column_default           | information_schema.character_data  |
 is_nullable              | information_schema.character_data  |
 data_type                | information_schema.character_data  |
 character_maximum_length | information_schema.cardinal_number |
 character_octet_length   | information_schema.cardinal_number |
 numeric_precision        | information_schema.cardinal_number |
 numeric_precision_radix  | information_schema.cardinal_number |
 numeric_scale            | information_schema.cardinal_number |
 datetime_precision       | information_schema.cardinal_number |
 interval_type            | information_schema.character_data  |
 interval_precision       | information_schema.character_data  |
 character_set_catalog    | information_schema.sql_identifier  |
 character_set_schema     | information_schema.sql_identifier  |
 character_set_name       | information_schema.sql_identifier  |
 collation_catalog        | information_schema.sql_identifier  |
 collation_schema         | information_schema.sql_identifier  |
 collation_name           | information_schema.sql_identifier  |
 domain_catalog           | information_schema.sql_identifier  |
 domain_schema            | information_schema.sql_identifier  |
 domain_name              | information_schema.sql_identifier  |
 udt_catalog              | information_schema.sql_identifier  |
 udt_schema               | information_schema.sql_identifier  |
 udt_name                 | information_schema.sql_identifier  |
 scope_catalog            | information_schema.sql_identifier  |
 scope_schema             | information_schema.sql_identifier  |
 scope_name               | information_schema.sql_identifier  |
 maximum_cardinality      | information_schema.cardinal_number |
 dtd_identifier           | information_schema.sql_identifier  |
 is_self_referencing      | information_schema.character_data  |
View definition:
 SELECT current_database()::information_schema.sql_identifier AS
table_catalog, nc.nspname::information_schema.sql_identifier AS
table_schema, c.relname::information_schema.sql_identifier AS
table_name, a.attname::information_schema.sql_identifier AS column_name,
a.attnum::information_schema.cardinal_number AS ordinal_position,
        CASE
            WHEN u.usename = "current_user"() THEN ad.adsrc
            ELSE NULL::text
        END::information_schema.character_data AS column_default,
        CASE
            WHEN a.attnotnull OR t.typtype = 'd'::"char" AND
t.typnotnull THEN 'NO'::text
            ELSE 'YES'::text
        END::information_schema.character_data AS is_nullable,
        CASE
            WHEN t.typtype = 'd'::"char" THEN
            CASE
                WHEN bt.typelem <> 0::oid AND bt.typlen = -1 THEN
'ARRAY'::text
                WHEN nbt.nspname = 'pg_catalog'::name THEN
format_type(t.typbasetype, NULL::integer)
                ELSE 'USER-DEFINED'::text
            END
            ELSE
            CASE
                WHEN t.typelem <> 0::oid AND t.typlen = -1 THEN
'ARRAY'::text
                WHEN nt.nspname = 'pg_catalog'::name THEN
format_type(a.atttypid, NULL::integer)
                ELSE 'USER-DEFINED'::text
            END
        END::information_schema.character_data AS data_type,
information_schema._pg_char_max_length(information_schema._pg_truetypid(a.*, 
t.*), information_schema._pg_truetypmod(a.*, 
t.*))::information_schema.cardinal_number AS character_maximum_length, 
information_schema._pg_char_octet_length(information_schema._pg_truetypid(a.*, 
t.*), information_schema._pg_truetypmod(a.*, 
t.*))::information_schema.cardinal_number AS character_octet_length, 
information_schema._pg_numeric_precision(information_schema._pg_truetypid(a.*, 
t.*), information_schema._pg_truetypmod(a.*, 
t.*))::information_schema.cardinal_number AS numeric_precision, 
information_schema._pg_numeric_precision_radix(information_schema._pg_truetypid(a.*,
 t.*), information_schema._pg_truetypmod(a.*, 
t.*))::information_schema.cardinal_number AS numeric_precision_radix, 
information_schema._pg_numeric_scale(information_schema._pg_truetypid(a.*, 
t.*), information_schema._pg_truetypmod(a.*, 
t.*))::information_schema.cardinal_number AS numeric_scale, 
information_schema._pg_datetime_prec
 ision(information_schema._pg_truetypid(a.*, t.*), 
information_schema._pg_truetypmod(a.*, 
t.*))::information_schema.cardinal_number AS datetime_precision, 
NULL::information_schema.character_data::information_schema.character_data AS 
interval_type, 
NULL::information_schema.character_data::information_schema.character_data AS 
interval_precision, 
NULL::information_schema.sql_identifier::information_schema.sql_identifier AS 
character_set_catalog, 
NULL::information_schema.sql_identifier::information_schema.sql_identifier AS 
character_set_schema, 
NULL::information_schema.sql_identifier::information_schema.sql_identifier AS 
character_set_name, 
NULL::information_schema.sql_identifier::information_schema.sql_identifier AS 
collation_catalog, 
NULL::information_schema.sql_identifier::information_schema.sql_identifier AS 
collation_schema, 
NULL::information_schema.sql_identifier::information_schema.sql_identifier AS 
collation_name,
        CASE
            WHEN t.typtype = 'd'::"char" THEN current_database()
            ELSE NULL::name
        END::information_schema.sql_identifier AS domain_catalog,
        CASE
            WHEN t.typtype = 'd'::"char" THEN nt.nspname
            ELSE NULL::name
        END::information_schema.sql_identifier AS domain_schema,
        CASE
            WHEN t.typtype = 'd'::"char" THEN t.typname
            ELSE NULL::name
        END::information_schema.sql_identifier AS domain_name,
current_database()::information_schema.sql_identifier AS udt_catalog,
COALESCE(nbt.nspname, nt.nspname)::information_schema.sql_identifier AS
udt_schema, COALESCE(bt.typname,
t.typname)::information_schema.sql_identifier AS udt_name,
NULL::information_schema.sql_identifier::information_schema.sql_identifier AS 
scope_catalog, 
NULL::information_schema.sql_identifier::information_schema.sql_identifier AS 
scope_schema, 
NULL::information_schema.sql_identifier::information_schema.sql_identifier AS 
scope_name, 
NULL::information_schema.cardinal_number::information_schema.cardinal_number AS 
maximum_cardinality, a.attnum::information_schema.sql_identifier AS 
dtd_identifier, 
'NO'::information_schema.character_data::information_schema.character_data AS 
is_self_referencing
   FROM pg_attribute a
   LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum =
ad.adnum, pg_class c, pg_namespace nc, pg_user u, pg_type t
   JOIN pg_namespace nt ON t.typnamespace = nt.oid
   LEFT JOIN (pg_type bt
   JOIN pg_namespace nbt ON bt.typnamespace = nbt.oid) ON t.typtype =
'd'::"char" AND t.typbasetype = bt.oid
  WHERE a.attrelid = c.oid AND a.atttypid = t.oid AND u.usesysid =
c.relowner AND nc.oid = c.relnamespace AND a.attnum > 0 AND NOT
a.attisdropped AND (c.relkind = 'r'::"char" OR c.relkind = 'v'::"char")
AND (u.usename = "current_user"() OR has_table_privilege(c.oid,
'SELECT'::text) OR has_table_privilege(c.oid, 'INSERT'::text) OR
has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid,
'REFERENCES'::text));

For column usage information only the table owner is permitted.
(note r.relowner = u.usesysid AND u.usename = "current_user"()):

sat=# \d information_schema.key_column_usage
             View "information_schema.key_column_usage"
       Column       |                Type                | Modifiers
--------------------+------------------------------------+-----------
 constraint_catalog | information_schema.sql_identifier  |
 constraint_schema  | information_schema.sql_identifier  |
 constraint_name    | information_schema.sql_identifier  |
 table_catalog      | information_schema.sql_identifier  |
 table_schema       | information_schema.sql_identifier  |
 table_name         | information_schema.sql_identifier  |
 column_name        | information_schema.sql_identifier  |
 ordinal_position   | information_schema.cardinal_number |
View definition:
 SELECT current_database()::information_schema.sql_identifier AS
constraint_catalog, nc.nspname::information_schema.sql_identifier AS
constraint_schema, c.conname::information_schema.sql_identifier AS
constraint_name, current_database()::information_schema.sql_identifier
AS table_catalog, nr.nspname::information_schema.sql_identifier AS
table_schema, r.relname::information_schema.sql_identifier AS
table_name, a.attname::information_schema.sql_identifier AS column_name,
pos.n::information_schema.cardinal_number AS ordinal_position
   FROM pg_namespace nr, pg_class r, pg_attribute a, pg_namespace nc,
pg_constraint c, pg_user u, information_schema._pg_keypositions() pos(n)
  WHERE nr.oid = r.relnamespace AND r.oid = a.attrelid AND r.oid =
c.conrelid AND nc.oid = c.connamespace AND c.conkey[pos.n] = a.attnum
AND NOT a.attisdropped AND (c.contype = 'p'::"char" OR c.contype =
'u'::"char" OR c.contype = 'f'::"char") AND r.relkind = 'r'::"char" AND
r.relowner = u.usesysid AND u.usename = "current_user"();


> what does the list think of dumping information_schema usage  
> altogther and using PG's own schema tables for reflection ?

The problem with this of course will be that it can/will
change from release to release.  And since you'll still be
accessing the metadata tables it will still require the
"VACUUM FULL ANALYZE" step after many metadata operations.

Our approach was to write a python program, using DBAPI, to
create the python files with the class definitions.
The program is only run by the database owner which is
always different than any applications that perform
data operations.

The DB tables are always and only defined by an external
entity diagram (logical data model and physical schema).

Users of the tables, particularly web applications, are
only granted the minimum SQL privileges necessary for their
tasks.  The capability to execute DDL operations would
specifically be prohibited.  It is only in small personal
type projects or, at most, initial development that that type
of interaction would occur.  For most deployed applications
the "db.create(table)" would/should never (for security
reasons) be possible.

HTH,
William.



_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users

Reply via email to