mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-15 01:53:41 +08:00
Fix non-default tablespaces with constraints
If a hypertable uses a non-default tablespace for its primary or unique constraints with additional DEFERRABLE or INITIALLY DEFERRED characteristics then any chunk creation will fail with syntax error. We now set the tablespace via a separate command for such constraints for the chunks. Fixes #6338
This commit is contained in:
parent
8745063bd4
commit
51d92a3638
2
.unreleased/fix_6339
Normal file
2
.unreleased/fix_6339
Normal file
@ -0,0 +1,2 @@
|
||||
Fixes: #6339 Fix tablespace with constraints
|
||||
Thanks: @lyp-bobi for reporting the issue
|
@ -40,10 +40,6 @@ BEGIN
|
||||
|
||||
def := pg_get_constraintdef(constraint_oid);
|
||||
|
||||
IF indx_tablespace IS NOT NULL THEN
|
||||
def := format('%s USING INDEX TABLESPACE %I', def, indx_tablespace);
|
||||
END IF;
|
||||
|
||||
ELSIF constraint_type = 't' THEN
|
||||
-- constraint triggers are copied separately with normal triggers
|
||||
def := NULL;
|
||||
@ -63,6 +59,18 @@ BEGIN
|
||||
$$ ALTER TABLE %I.%I ADD CONSTRAINT %I %s $$,
|
||||
chunk_row.schema_name, chunk_row.table_name, chunk_constraint_row.constraint_name, def
|
||||
);
|
||||
|
||||
-- if constraint (primary or unique) needs a tablespace then add it
|
||||
-- via a separate ALTER INDEX SET TABLESPACE command. We cannot append it
|
||||
-- to the "def" string above since it leads to a SYNTAX error when
|
||||
-- "DEFERRABLE" or "INITIALLY DEFERRED" are used in the constraint
|
||||
IF indx_tablespace IS NOT NULL THEN
|
||||
EXECUTE pg_catalog.format(
|
||||
$$ ALTER INDEX %I.%I SET TABLESPACE %I $$,
|
||||
chunk_row.schema_name, chunk_constraint_row.constraint_name, indx_tablespace
|
||||
);
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
END
|
||||
$BODY$ SET search_path TO pg_catalog, pg_temp;
|
||||
|
@ -333,3 +333,72 @@ BEGIN
|
||||
END LOOP;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
DROP FUNCTION _timescaledb_functions.chunk_constraint_add_table_constraint(
|
||||
chunk_constraint_row _timescaledb_catalog.chunk_constraint
|
||||
);
|
||||
|
||||
CREATE FUNCTION _timescaledb_functions.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;
|
||||
constraint_type CHAR;
|
||||
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
|
||||
RAISE 'cannot create dimension constraint %', chunk_constraint_row;
|
||||
ELSIF chunk_constraint_row.hypertable_constraint_name IS NOT NULL THEN
|
||||
|
||||
SELECT oid, contype INTO STRICT constraint_oid, constraint_type 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;
|
||||
|
||||
IF constraint_type IN ('p','u') THEN
|
||||
-- since primary keys and unique constraints are backed by an index
|
||||
-- they might have an index tablespace assigned
|
||||
-- the tablspace is not part of the constraint definition so
|
||||
-- we have to append it explicitly to preserve it
|
||||
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;
|
||||
|
||||
def := pg_get_constraintdef(constraint_oid);
|
||||
|
||||
IF indx_tablespace IS NOT NULL THEN
|
||||
def := format('%s USING INDEX TABLESPACE %I', def, indx_tablespace);
|
||||
END IF;
|
||||
|
||||
ELSIF constraint_type = 't' THEN
|
||||
-- constraint triggers are copied separately with normal triggers
|
||||
def := NULL;
|
||||
ELSE
|
||||
def := pg_get_constraintdef(constraint_oid);
|
||||
END IF;
|
||||
|
||||
ELSE
|
||||
RAISE 'unknown constraint type';
|
||||
END IF;
|
||||
|
||||
IF def IS NOT NULL THEN
|
||||
-- to allow for custom types with operators outside of pg_catalog
|
||||
-- we set search_path to @extschema@
|
||||
SET LOCAL search_path TO @extschema@, pg_temp;
|
||||
EXECUTE pg_catalog.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$ SET search_path TO pg_catalog, pg_temp;
|
||||
|
@ -812,7 +812,7 @@ CREATE TABLE tbl (
|
||||
fk_id int,
|
||||
id int,
|
||||
time timestamp,
|
||||
CONSTRAINT pk PRIMARY KEY (time, id) USING INDEX TABLESPACE tablespace1);
|
||||
CONSTRAINT pk PRIMARY KEY (time, id) USING INDEX TABLESPACE tablespace1 DEFERRABLE INITIALLY DEFERRED);
|
||||
SELECT create_hypertable('tbl', 'time');
|
||||
WARNING: column type "timestamp without time zone" used for "time" does not follow best practices
|
||||
create_hypertable
|
||||
|
@ -612,7 +612,7 @@ CREATE TABLE tbl (
|
||||
fk_id int,
|
||||
id int,
|
||||
time timestamp,
|
||||
CONSTRAINT pk PRIMARY KEY (time, id) USING INDEX TABLESPACE tablespace1);
|
||||
CONSTRAINT pk PRIMARY KEY (time, id) USING INDEX TABLESPACE tablespace1 DEFERRABLE INITIALLY DEFERRED);
|
||||
|
||||
SELECT create_hypertable('tbl', 'time');
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user