mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-18 03:23:37 +08:00
Block NO INHERIT constraints on hypertables
Constraints with the NO INHERIT option does not make sense on a hypertable's root table since these will not be enforced. Previously, NO INHERIT constraints were blocked on chunks, and were thus not enforced until chunk creation time, allowing creation of NO INHERIT constraints on empty hypertables, but then causing failure at chunk-creation time. Instead, NO INHERIT constraints are now properly blocked at the hypertable level.
This commit is contained in:
parent
e362e9cf18
commit
cbc5e60abe
@ -581,13 +581,6 @@ chunk_constraint_need_on_chunk(Form_pg_constraint conform)
|
|||||||
* of constraints (unique, primary key, and foreign key constraints)
|
* of constraints (unique, primary key, and foreign key constraints)
|
||||||
* are not inherited."
|
* are not inherited."
|
||||||
*/
|
*/
|
||||||
if (conform->connoinherit)
|
|
||||||
{
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_IO_OPERATION_NOT_SUPPORTED),
|
|
||||||
errmsg("NO INHERIT option not supported on hypertables: %s", conform->conname.data)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
#include <nodes/memnodes.h>
|
#include <nodes/memnodes.h>
|
||||||
#include <catalog/namespace.h>
|
#include <catalog/namespace.h>
|
||||||
#include <catalog/pg_inherits_fn.h>
|
#include <catalog/pg_inherits_fn.h>
|
||||||
|
#include <catalog/pg_constraint_fn.h>
|
||||||
|
#include <catalog/pg_constraint.h>
|
||||||
|
#include <catalog/indexing.h>
|
||||||
#include <commands/tablespace.h>
|
#include <commands/tablespace.h>
|
||||||
#include <commands/dbcommands.h>
|
#include <commands/dbcommands.h>
|
||||||
#include <commands/schemacmds.h>
|
#include <commands/schemacmds.h>
|
||||||
@ -849,6 +852,46 @@ hypertable_create_schema(const char *schema_name)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that existing table constraints are supported.
|
||||||
|
*
|
||||||
|
* Hypertables do not support some constraints. For instance, NO INHERIT
|
||||||
|
* constraints cannot be enforced on a hypertable since they only exist on the
|
||||||
|
* parent table, which will have no tuples.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
hypertable_validate_constraints(Oid relid)
|
||||||
|
{
|
||||||
|
Relation catalog;
|
||||||
|
SysScanDesc scan;
|
||||||
|
ScanKeyData scankey;
|
||||||
|
HeapTuple tuple;
|
||||||
|
|
||||||
|
catalog = heap_open(ConstraintRelationId, AccessShareLock);
|
||||||
|
|
||||||
|
ScanKeyInit(&scankey, Anum_pg_constraint_conrelid, BTEqualStrategyNumber,
|
||||||
|
F_OIDEQ, ObjectIdGetDatum(relid));
|
||||||
|
|
||||||
|
scan = systable_beginscan(catalog, ConstraintRelidIndexId, true,
|
||||||
|
NULL, 1, &scankey);
|
||||||
|
|
||||||
|
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
|
||||||
|
{
|
||||||
|
Form_pg_constraint form = (Form_pg_constraint) GETSTRUCT(tuple);
|
||||||
|
|
||||||
|
if (form->contype == CONSTRAINT_CHECK && form->connoinherit)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
||||||
|
errmsg("cannot have NO INHERIT constraints on hypertable \"%s\"",
|
||||||
|
get_rel_name(relid)),
|
||||||
|
errhint("Remove all NO INHERIT constraints from table \"%s\" before making it a hypertable.",
|
||||||
|
get_rel_name(relid))));
|
||||||
|
}
|
||||||
|
|
||||||
|
systable_endscan(scan);
|
||||||
|
heap_close(catalog, AccessShareLock);
|
||||||
|
}
|
||||||
|
|
||||||
TS_FUNCTION_INFO_V1(hypertable_create);
|
TS_FUNCTION_INFO_V1(hypertable_create);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -947,6 +990,9 @@ hypertable_create(PG_FUNCTION_ARGS)
|
|||||||
errmsg("invalid relation type")));
|
errmsg("invalid relation type")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check that the table doesn't have any unsupported constraints */
|
||||||
|
hypertable_validate_constraints(table_relid);
|
||||||
|
|
||||||
table_has_data = table_has_tuples(table_relid, GetActiveSnapshot(), NoLock);
|
table_has_data = table_has_tuples(table_relid, GetActiveSnapshot(), NoLock);
|
||||||
|
|
||||||
if (!migrate_data && table_has_data)
|
if (!migrate_data && table_has_data)
|
||||||
|
@ -918,6 +918,13 @@ verify_constraint_hypertable(Hypertable *ht, Node *constr_node)
|
|||||||
contype = constr->contype;
|
contype = constr->contype;
|
||||||
keys = (contype == CONSTR_EXCLUSION) ? constr->exclusions : constr->keys;
|
keys = (contype == CONSTR_EXCLUSION) ? constr->exclusions : constr->keys;
|
||||||
indexname = constr->indexname;
|
indexname = constr->indexname;
|
||||||
|
|
||||||
|
/* NO INHERIT constraints do not really make sense on a hypertable */
|
||||||
|
if (constr->is_no_inherit)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
||||||
|
errmsg("cannot have NO INHERIT constraints on hypertable \"%s\"",
|
||||||
|
get_rel_name(ht->main_table_relid))));
|
||||||
}
|
}
|
||||||
else if (IsA(constr_node, IndexStmt))
|
else if (IsA(constr_node, IndexStmt))
|
||||||
{
|
{
|
||||||
|
@ -545,3 +545,33 @@ SELECT * FROM create_hypertable('hyper_ex_invalid', 'time', chunk_time_interval=
|
|||||||
NOTICE: adding not-null constraint to column "time"
|
NOTICE: adding not-null constraint to column "time"
|
||||||
ERROR: cannot create a unique index without the column "time" (used in partitioning)
|
ERROR: cannot create a unique index without the column "time" (used in partitioning)
|
||||||
\set ON_ERROR_STOP 1
|
\set ON_ERROR_STOP 1
|
||||||
|
--- NO INHERIT constraints (not allowed) ----
|
||||||
|
CREATE TABLE hyper_noinherit (
|
||||||
|
time BIGINT,
|
||||||
|
sensor_1 NUMERIC NULL DEFAULT 1 CHECK (sensor_1 > 0) NO INHERIT
|
||||||
|
);
|
||||||
|
SELECT * FROM test.show_constraints('hyper_noinherit');
|
||||||
|
Constraint | Type | Columns | Index | Expr
|
||||||
|
--------------------------------+------+------------+-------+---------------------------
|
||||||
|
hyper_noinherit_sensor_1_check | c | {sensor_1} | - | (sensor_1 > (0)::numeric)
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT * FROM create_hypertable('hyper_noinherit', 'time', chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
|
||||||
|
ERROR: cannot have NO INHERIT constraints on hypertable "hyper_noinherit"
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
CREATE TABLE hyper_noinherit_alter (
|
||||||
|
time BIGINT,
|
||||||
|
sensor_1 NUMERIC NULL DEFAULT 1
|
||||||
|
);
|
||||||
|
SELECT * FROM create_hypertable('hyper_noinherit_alter', 'time', chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
|
||||||
|
NOTICE: adding not-null constraint to column "time"
|
||||||
|
create_hypertable
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
ALTER TABLE hyper_noinherit_alter ADD CONSTRAINT check_noinherit CHECK (sensor_1 > 0) NO INHERIT;
|
||||||
|
ERROR: cannot have NO INHERIT constraints on hypertable "hyper_noinherit_alter"
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
@ -398,3 +398,27 @@ CREATE TABLE hyper_ex_invalid (
|
|||||||
\set ON_ERROR_STOP 0
|
\set ON_ERROR_STOP 0
|
||||||
SELECT * FROM create_hypertable('hyper_ex_invalid', 'time', chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
|
SELECT * FROM create_hypertable('hyper_ex_invalid', 'time', chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
|
||||||
\set ON_ERROR_STOP 1
|
\set ON_ERROR_STOP 1
|
||||||
|
|
||||||
|
|
||||||
|
--- NO INHERIT constraints (not allowed) ----
|
||||||
|
CREATE TABLE hyper_noinherit (
|
||||||
|
time BIGINT,
|
||||||
|
sensor_1 NUMERIC NULL DEFAULT 1 CHECK (sensor_1 > 0) NO INHERIT
|
||||||
|
);
|
||||||
|
|
||||||
|
SELECT * FROM test.show_constraints('hyper_noinherit');
|
||||||
|
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT * FROM create_hypertable('hyper_noinherit', 'time', chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
|
||||||
|
CREATE TABLE hyper_noinherit_alter (
|
||||||
|
time BIGINT,
|
||||||
|
sensor_1 NUMERIC NULL DEFAULT 1
|
||||||
|
);
|
||||||
|
|
||||||
|
SELECT * FROM create_hypertable('hyper_noinherit_alter', 'time', chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
|
||||||
|
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
ALTER TABLE hyper_noinherit_alter ADD CONSTRAINT check_noinherit CHECK (sensor_1 > 0) NO INHERIT;
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user