Postgres method array_position(array, element)
, like other things in SQL, is 1-based. For example:
SELECT array_position(array[4,5,6], 5) -- returns 2
But, I'm doing the following query to retrieve non-unique indexes from pg_catalog, along with their columns:
SELECT non_unique_indexes.indname AS index_name,
non_unique_indexes.relname AS table_name,
columns.column_name AS column_name,
array_position(non_unique_indexes.indkey, columns.ordinal_position::smallint) AS column_position,
CASE non_unique_indexes.indoption[array_position(non_unique_indexes.indkey, columns.ordinal_position::smallint)]
WHEN 1 THEN 'DESC'
WHEN 3 THEN 'DESC'
ELSE 'ASC'
END AS direction
FROM (
SELECT pg_namespace.nspname,
pg_class_tables.relname,
pg_class_indexes.relname AS indname,
pg_index.indkey,
pg_index.indoption,
pg_tablespace.spcname
FROM pg_catalog.pg_index
INNER JOIN pg_catalog.pg_class pg_class_tables ON pg_class_tables.oid = pg_index.indrelid
INNER JOIN pg_catalog.pg_class pg_class_indexes ON pg_class_indexes.oid = pg_index.indexrelid
INNER JOIN pg_catalog.pg_tablespace ON pg_tablespace.oid = pg_class_indexes.reltablespace
INNER JOIN pg_catalog.pg_namespace ON pg_namespace.oid = pg_class_indexes.relnamespace
WHERE pg_index.indisunique = false
AND pg_namespace.nspname = 'my_schema'
) non_unique_indexes
INNER JOIN information_schema.columns ON columns.table_schema = non_unique_indexes.nspname
AND columns.table_name = non_unique_indexes.relname
AND columns.ordinal_position = ANY(non_unique_indexes.indkey)
ORDER BY non_unique_indexes.relname,
non_unique_indexes.indname,
array_position(non_unique_indexes.indkey, columns.ordinal_position::smallint)
The 4th select searches the indkey
array for the column's ordinal_position
, so for each column it gets its position in the index.
Funny thing is that first column has position 0, so I had to add + 1
to have it 1-based.
The subsequent CASE
expression, where the very same value is used as index for retrieving n-th element of indoption
, curiously works fine even though []
operator is 1-based as well:
SELECT (array[4,5,6])[2] -- returns 5
How is this?
I'm currently on PG 9.6.