Skip to content

Instantly share code, notes, and snippets.

@willglynn
Created September 21, 2012 01:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save willglynn/3759322 to your computer and use it in GitHub Desktop.
Save willglynn/3759322 to your computer and use it in GitHub Desktop.
Automatic index generation for all hstore keys
CREATE OR REPLACE FUNCTION indexes_for_hstore_column(full_table_name varchar, hstore_column varchar) RETURNS SETOF varchar AS $$
DECLARE
table_oid oid;
table_name varchar;
schema_name varchar;
key varchar;
index_name varchar;
index_exists integer;
unique_keys_query varchar;
create_index_statement varchar;
BEGIN
-- Split full_table_name on dots to account for schemas
schema_name := split_part(full_table_name, '.', 1);
table_name := split_part(full_table_name, '.', 2);
-- Fill in 'public' if there was no dot
IF table_name IS NULL THEN
table_name := schema_name;
schema_name := 'public';
END IF;
-- Get the OID of the table we're working on
SELECT oid INTO table_oid
FROM pg_catalog.pg_class
WHERE relname=table_name AND relnamespace=(
SELECT oid FROM pg_catalog.pg_namespace
WHERE nspname=schema_name
);
-- Generate a query that will get a list of unique keys in the target column
unique_keys_query := format(
'SELECT DISTINCT (each(%I)).key FROM %I.%I',
hstore_column, schema_name, table_name
);
-- Loop over those keys
FOR key IN EXECUTE unique_keys_query LOOP
-- Generate the name of this index based on the [table, hstore, key] combination
index_name := table_name || '_' || hstore_column || '_' || key || '_key';
-- Test for existence of an index with this name
--
-- No, this does not check whether the index is indexing the right thing,
-- but I'm going to assume it does :-P
SELECT count(*) INTO index_exists
FROM pg_catalog.pg_class
WHERE relkind='i' AND relname=index_name AND relnamespace=(
SELECT oid FROM pg_catalog.pg_namespace
WHERE nspname=schema_name
);
-- If there is no such index...
IF index_exists = 0 THEN
-- ...build a query to create it...
create_index_statement := format(
'CREATE INDEX %I ON %I.%I ((%I->%L));',
index_name, schema_name, table_name,
hstore_column, key
);
-- ...and put it in the list of statements to output
RETURN NEXT create_index_statement;
END IF;
END LOOP;
-- Pass back whatever statements we've accumulated
RETURN;
END
$$ LANGUAGE plpgsql STABLE;
@willglynn
Copy link
Author

This is terrible, just terrible. But... once the idea entered my brain, I had to run with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment