timescaledb/sql/chunk_constraint.sql
Tyler Fontaine 1bccedf3f8 Limit Index Tablespace Lookup To p and u Constraints
This resolves an issue when using both constraints with index
tablespaces AND constraints that have no indexes on a single hypertable.

chunk_constraint_add_table_constraint() was attempting to add
`USING INDEX TABLESPACE` to all constraints when a given hypertable had
any constraint configured to use a tablespace, resulting in a SYNTAX
error and blocking the creation of new chunks.

The solution here is to limit index tablespace lookups to only the
constraint types which use indexes: primary key and unique so that only
those constraits will have `USING INDEX TABLESPACE` prepended when
necessary.
2020-11-04 08:39:44 -06:00

58 lines
2.3 KiB
PL/PgSQL

-- This file and its contents are licensed under the Apache License 2.0.
-- Please see the included NOTICE for copyright information and
-- LICENSE-APACHE for a copy of the license.
-- Creates a constraint on a chunk.
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_constraint_add_table_constraint(
chunk_constraint_row _timescaledb_catalog.chunk_constraint
)
RETURNS VOID LANGUAGE PLPGSQL AS
$BODY$
DECLARE
chunk_row _timescaledb_catalog.chunk;
hypertable_row _timescaledb_catalog.hypertable;
constraint_oid OID;
check_sql TEXT;
def TEXT;
indx_tablespace NAME;
tablespace_def TEXT;
BEGIN
SELECT * INTO STRICT chunk_row FROM _timescaledb_catalog.chunk c WHERE c.id = chunk_constraint_row.chunk_id;
SELECT * INTO STRICT hypertable_row FROM _timescaledb_catalog.hypertable h WHERE h.id = chunk_row.hypertable_id;
IF chunk_constraint_row.dimension_slice_id IS NOT NULL THEN
check_sql = _timescaledb_internal.dimension_slice_get_constraint_sql(chunk_constraint_row.dimension_slice_id);
IF check_sql IS NOT NULL THEN
def := format('CHECK (%s)', check_sql);
ELSE
def := NULL;
END IF;
ELSIF chunk_constraint_row.hypertable_constraint_name IS NOT NULL THEN
SELECT oid INTO STRICT constraint_oid FROM pg_constraint
WHERE conname=chunk_constraint_row.hypertable_constraint_name AND
conrelid = format('%I.%I', hypertable_row.schema_name, hypertable_row.table_name)::regclass::oid;
SELECT T.spcname INTO indx_tablespace
FROM pg_constraint C, pg_class I, pg_tablespace T
WHERE C.oid = constraint_oid AND C.contype IN ('p', 'u') AND I.oid = C.conindid AND I.reltablespace = T.oid;
IF indx_tablespace IS NOT NULL THEN
tablespace_def := format(' USING INDEX TABLESPACE %I', indx_tablespace);
ELSE
tablespace_def := '';
END IF;
def := pg_get_constraintdef(constraint_oid) || tablespace_def;
ELSE
RAISE 'unknown constraint type';
END IF;
IF def IS NOT NULL THEN
EXECUTE format(
$$ ALTER TABLE %I.%I ADD CONSTRAINT %I %s $$,
chunk_row.schema_name, chunk_row.table_name, chunk_constraint_row.constraint_name, def
);
END IF;
END
$BODY$;