Thread: Join troubles between pg_index and pg_indexes with capitalization in pg_indexes.tablename
Join troubles between pg_index and pg_indexes with capitalization in pg_indexes.tablename
From
Bob Branch
Date:
I've got a script in which I'm attempting to list all indexes that aren't the PK for a given table. The query I'm using for this is: SELECT i.indexname, i.indexdef FROM pg_indexes i INNER JOIN pg_index p ON p.indrelid = i.tablename::regclass::oid WHERE i.schemaname = 'public' AND i.tablename = 'tablename_goes_here' AND p.indisprimary = false This works for tables with what I'm sure we'd all consider to be "proper" naming (all lower-case, underscores between words), but our database unfortunately has vast numbers of tables that use camel case and spaces in the table names (eg- "Status", "Sales Rep", etc.). This works to get the right records from pg_indexes if I strip out the join, but with the join in place Postgres does as it typically does when you try to use a relation with capitalization in it without quoting. It converts it to lower case, and I get an error like this (working with a table called Status): ERROR: relation "status" does not exist The problem is similar, but different for tables like "Sales Rep" with a space in the name: ERROR: invalid name syntax Is there a way I can modify this query to work with tables that require special quoting for Postgres not to mangle their names? It'd be simple if I didn't need to worry about excluding the PK from the results, but this is part of a script that's dropping and re-creating all the indexes prior to/after a COPY to increase performance, so dropping the PK index is...sub-optimal, at best. -- Bob Branch Database Administrator North American Bancard 250 Stevenson Hwy Troy, MI 48083 bbranch@nabancard.com 248-269-6000 CONFIDENTIALITY NOTICE This e-mail message and any attachments are only for the use of the intended recipient and may contain information that is privileged, confidential or exempt from disclosure under applicable law. If you are not the intended recipient, any disclosure, distribution or other use of this e-mail message or attachments is prohibited. If you have received this e-mail message in error, please delete and notify the sender immediately. Thank you.
Re: Join troubles between pg_index and pg_indexes with capitalization in pg_indexes.tablename
From
"Jean-Yves F. Barbier"
Date:
On Wed, 11 Jan 2012 18:37:23 -0500 Bob Branch <bbranch@nabancard.com> wrote: > > SELECT i.indexname, i.indexdef FROM pg_indexes i > INNER JOIN pg_index p ON p.indrelid = i.tablename::regclass::oid > WHERE i.schemaname = 'public' > AND i.tablename = 'tablename_goes_here' > AND p.indisprimary = false First, your query is incorrect: on my test DB is returns 156 rows for 12 (non PK) indexes on a table. Second, you must enclose unregular table names into either simple & double quotes and use the same kinda query as '\d+ mytable': SELECT c2.relname, i.indisprimary, i.indisunique, i.indisclustered, i.indisvalid, pg_catalog.pg_get_indexdef(i.indexrelid, 0, true), pg_catalog.pg_get_constraintdef(con.oid, true), contype, condeferrable, condeferred, c2.reltablespace FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x')) WHERE c.oid = '"MyUnregularlyNamedTABLE"'::regclass::oid AND c.oid = i.indrelid AND i.indexrelid = c2.oid AND i.indisprimary = 'f' ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname; (also work with regular names). JY -- The greatest disloyalty one can offer to great pioneers is to refuse to move an inch from where they stood.
Re: Join troubles between pg_index and pg_indexes with capitalization in pg_indexes.tablename
From
Tom Lane
Date:
Bob Branch <bbranch@nabancard.com> writes: > I've got a script in which I'm attempting to list all indexes that > aren't the PK for a given table. The query I'm using for this is: > SELECT i.indexname, i.indexdef FROM pg_indexes i > INNER JOIN pg_index p ON p.indrelid = i.tablename::regclass::oid > WHERE i.schemaname = 'public' > AND i.tablename = 'tablename_goes_here' > AND p.indisprimary = false > This works for tables with what I'm sure we'd all consider to be > "proper" naming (all lower-case, underscores between words), but our > database unfortunately has vast numbers of tables that use camel case > and spaces in the table names (eg- "Status", "Sales Rep", etc.). Not to mention that it's utterly unsafe if you have equal table names in different schemas. You should really not be using pg_indexes in this query, as it is a view meant for human consumption, not something helpful for basing further catalog joins on. Try looking directly at pg_class and pg_index. In particular, if all you want is non-PK indexes, you could just do something like select indexrelid::regclass from pg_index where not indisprimary; If you need an explicit join to pg_class (perhaps because you have more filter conditions than just "is it primary"), you should be joining pg_class.oid to indexrelid or indrelid, rather than making something up with table names. The names are not suitable as join keys. regards, tom lane