Thread: Bug in the information_schema.referential_constraints view

Bug in the information_schema.referential_constraints view

From
malerba@gnome-db.org
Date:
If PostgreSQL failed to compile on your computer or you found a bug that
is likely to be specific to one platform then please fill out this form
and e-mail it to pgsql-ports@postgresql.org.

To report any other bug, fill out the form below and e-mail it to
pgsql-bugs@postgresql.org.

If you not only found the problem but solved it and generated a patch
then e-mail it to pgsql-patches@postgresql.org instead.  Please use the
command "diff -c" to generate the patch.

You may also enter a bug report at http://www.postgresql.org/ instead of
e-mail-ing this form.

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D
                        POSTGRESQL BUG REPORT TEMPLATE
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D


Your name               :       Vivien MALERBA
Your email address      :       malerba@gnome-db.org


System Configuration
---------------------
  Architecture (example: Intel Pentium)         :Intel Pentium

  Operating System (example: Linux 2.0.26 ELF)  :Linux 2.4.7-10

  PostgreSQL version (example: PostgreSQL-7.3):   PostgreSQL-7.4 Beta 4

  Compiler used (example:  gcc 2.95.2)          :gcc 3.0.2


Please enter a FULL description of your problem:
------------------------------------------------
The information_schema.referential_constraints retuns wrong data because
there is
an incomplete joining condition in the WHERE clause.




Please describe a way to repeat the problem.   Please try to provide a
concise reproducible example, if at all possible:
----------------------------------------------------------------------





If you know how this problem might be fixed, list the solution below:
---------------------------------------------------------------------
Fix the buggy joining condition in the view itself. Here is the working
view (probably
to be integrated into backend/catalog/information_schema.sql).

Sorry, I did not have the time to produce a patch...

CREATE VIEW referential_constraints AS
    SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
           CAST(ncon.nspname AS sql_identifier) AS constraint_schema,
           CAST(con.conname AS sql_identifier) AS constraint_name,
           CAST(current_database() AS sql_identifier) AS
unique_constraint_catalog,
           CAST(npkc.nspname AS sql_identifier) AS unique_constraint_schema,
           CAST(pkc.conname AS sql_identifier) AS unique_constraint_name,

           CAST(
             CASE con.confmatchtype WHEN 'f' THEN 'FULL'
                                    WHEN 'p' THEN 'PARTIAL'
                                    WHEN 'u' THEN 'NONE' END
             AS character_data) AS match_option,

           CAST(
             CASE con.confupdtype WHEN 'c' THEN 'CASCADE'
                                  WHEN 'n' THEN 'SET NULL'
                                  WHEN 'd' THEN 'SET DEFAULT'
                                  WHEN 'r' THEN 'RESTRICT'
                                  WHEN 'a' THEN 'NOACTION' END
             AS character_data) AS update_rule,

           CAST(
             CASE con.confdeltype WHEN 'c' THEN 'CASCADE'
                                  WHEN 'n' THEN 'SET NULL'
                                  WHEN 'd' THEN 'SET DEFAULT'
                                  WHEN 'r' THEN 'RESTRICT'
                                  WHEN 'a' THEN 'NOACTION' END
             AS character_data) AS delete_rule

    FROM pg_namespace ncon,
         pg_constraint con,
         pg_class c,
         pg_constraint pkc,
         pg_namespace npkc,
         pg_user u

    WHERE ncon.oid =3D con.connamespace
          AND con.conrelid =3D c.oid
          AND con.confkey =3D pkc.conkey
          AND pkc.connamespace =3D npkc.oid
          AND c.relowner =3D u.usesysid
          AND c.relkind =3D 'r'
          AND con.contype =3D 'f'
          AND con.confrelid =3D pkc.conrelid
          AND u.usename =3D current_user;

Re: Bug in the information_schema.referential_constraints view

From
Tom Lane
Date:
malerba@gnome-db.org writes:
> The information_schema.referential_constraints retuns wrong data because
> there is an incomplete joining condition in the WHERE clause.
> [ these two conditions need to be added: ]
>           AND con.contype = 'f'
>           AND con.confrelid = pkc.conrelid

I think this is correct as far as it goes, but there are more problems.

For one, I believe we also need to check the contype of the pkc row;
otherwise matches against check constraints are possible.

Another problem is that the view will fail to list FK constraints at all
if it cannot identify a matching unique constraint.  Which there may not
be (the backend code for creating an FK checks for a matching unique
index, quite a different animal).  And the check for match is inadequate
anyway, because it is using "con.confkey = pkc.conkey", which only
matches if the unique constraint lists the same columns *in the same
order* as the FK constraint does.  The backend code does not require
that.

A more robust way to handle things would be to make use of pg_depend to
find the index the FK constraint depends on and then chain to the unique
constraint associated with that index.  However, we need to decide what
to do if there is no such unique constraint.  I don't think "omit the FK
constraint from the view" is the right answer.  We could return nulls
for the unique_constraint_schema and unique_constraint_name, or we could
return the name of the index itself (not standard, but then the
underlying situation isn't standard either).

Comments?

Another question is whether to force an initdb after making this change.
If we don't, existing beta testers may continue to use the incorrect
view definition.

            regards, tom lane

Re: Bug in the information_schema.referential_constraints

From
Peter Eisentraut
Date:
Tom Lane writes:

> >           AND con.contype = 'f'
> >           AND con.confrelid = pkc.conrelid
>
> I think this is correct as far as it goes, but there are more problems.

Added.

> For one, I believe we also need to check the contype of the pkc row;
> otherwise matches against check constraints are possible.

Done.

> Another problem is that the view will fail to list FK constraints at all
> if it cannot identify a matching unique constraint.

If you want information under those conditions, you're looking at the
wrong view.  table_constraints gives you general information about
constraints.

> Which there may not be (the backend code for creating an FK checks for a
> matching unique index, quite a different animal).

I think that should be changed.

> And the check for match is inadequate anyway, because it is using
> "con.confkey = pkc.conkey", which only matches if the unique constraint
> lists the same columns *in the same order* as the FK constraint does.
> The backend code does not require that.

OK, that is indeed a problem.  I'll see if I can up with a solution.

> A more robust way to handle things would be to make use of pg_depend to
> find the index the FK constraint depends on and then chain to the unique
> constraint associated with that index.

I've used pg_depend for some other views, but that entails problems as
well, for example, because they don't track system tables.  It might be
worth a shot in this particular case, though.

> Another question is whether to force an initdb after making this change.
> If we don't, existing beta testers may continue to use the incorrect
> view definition.

I think we will have to.

--
Peter Eisentraut   peter_e@gmx.net

Re: Bug in the information_schema.referential_constraints view

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Tom Lane writes:
>> Another problem is that the view will fail to list FK constraints at all
>> if it cannot identify a matching unique constraint.

> If you want information under those conditions, you're looking at the
> wrong view.  table_constraints gives you general information about
> constraints.

Mmm ... can't say that I agree.  The FK constraint itself is a perfectly
good constraint.  It may be that ignoring such constraints is okay per
the letter of the spec, but given that we have the extension to support
FK constraints on non-constraint-associated indexes, it seems to me that
this view should cope too.

>> Which there may not be (the backend code for creating an FK checks for a
>> matching unique index, quite a different animal).

> I think that should be changed.

No, because that would entail a genuine loss of capability: FK
constraints couldn't be built using indexes that were made by CREATE
UNIQUE INDEX rather than through the unique/pk constraint syntax.
In particular this would mean that non-btree indexes could not be used.
(Yes, I know that as of today we don't have UNIQUE support in any of the
non-btree index types, but that will change.  IIRC Neil Conway has
already been working on unique hashes, and I'm sure GIST will support it
eventually as well.)

>> A more robust way to handle things would be to make use of pg_depend to

> I've used pg_depend for some other views, but that entails problems as
> well, for example, because they don't track system tables.

Good point.  But we don't support explicit foreign key constraints on
system tables, and probably aren't going to start anytime soon, so I
think this is probably okay.

>> Another question is whether to force an initdb after making this change.
>> If we don't, existing beta testers may continue to use the incorrect
>> view definition.

> I think we will have to.

Okay.  I've been reviewing the rest of information_schema and have found
some other issues, but am not all the way through yet.  Please hold off
the initdb force until I've reported on the other stuff.

            regards, tom lane

Re: Bug in the information_schema.referential_constraints

From
Peter Eisentraut
Date:
I have fixed the problem with the keys being in different order and the
problem of missing unique constraints.

Tom Lane writes:

> >> Which there may not be (the backend code for creating an FK checks for a
> >> matching unique index, quite a different animal).
>
> > I think that should be changed.
>
> No, because that would entail a genuine loss of capability: FK
> constraints couldn't be built using indexes that were made by CREATE
> UNIQUE INDEX rather than through the unique/pk constraint syntax.
> In particular this would mean that non-btree indexes could not be used.

But that means the deficiency is elsewhere, namely that you cannot build
non-btree indexes for primary key or unique constraints.

> (Yes, I know that as of today we don't have UNIQUE support in any of the
> non-btree index types, but that will change.  IIRC Neil Conway has
> already been working on unique hashes, and I'm sure GIST will support it
> eventually as well.)

Isn't the whole unique index thing a dead end anyway?  How are we ever
going to get deferrable unique constraints that way?

--
Peter Eisentraut   peter_e@gmx.net

Re: Bug in the information_schema.referential_constraints view

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Tom Lane writes:
>> No, because that would entail a genuine loss of capability: FK
>> constraints couldn't be built using indexes that were made by CREATE
>> UNIQUE INDEX rather than through the unique/pk constraint syntax.
>> In particular this would mean that non-btree indexes could not be used.

> But that means the deficiency is elsewhere, namely that you cannot build
> non-btree indexes for primary key or unique constraints.

So are you proposing we extend the constraint syntax instead?  I think
it's better to keep our nonstandard index support in a separate,
nonstandard statement (CREATE INDEX) rather than mash it together with
spec-mandated syntax.  That seems like a recipe for getting stuck when
the spec adds extensions.

> Isn't the whole unique index thing a dead end anyway?  How are we ever
> going to get deferrable unique constraints that way?

The way that was just discussed --- with a deferrable constraint, you
don't elog immediately when the index detects a collision, but make a
note to recheck that particular key value at the time the constraint
should be enforced.  I can't imagine that we'd want to do unique
constraints without any index support.  How would you avoid having to
check lots and lots of uninteresting rows?

            regards, tom lane