mirror of https://github.com/citusdata/citus.git
Merge pull request #5793 from citusdata/seq_expression
commit
c5031ac7b5
|
@ -31,6 +31,7 @@
|
||||||
#include "catalog/pg_opclass.h"
|
#include "catalog/pg_opclass.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_trigger.h"
|
#include "catalog/pg_trigger.h"
|
||||||
|
#include "catalog/pg_type.h"
|
||||||
#include "commands/defrem.h"
|
#include "commands/defrem.h"
|
||||||
#include "commands/extension.h"
|
#include "commands/extension.h"
|
||||||
#include "commands/sequence.h"
|
#include "commands/sequence.h"
|
||||||
|
@ -579,7 +580,7 @@ CreateDistributedTable(Oid relationId, char *distributionColumnName,
|
||||||
* explicitly.
|
* explicitly.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
EnsureSequenceTypeSupported(Oid seqOid, Oid seqTypId, Oid ownerRelationId)
|
EnsureSequenceTypeSupported(Oid seqOid, Oid attributeTypeId, Oid ownerRelationId)
|
||||||
{
|
{
|
||||||
List *citusTableIdList = CitusTableTypeIdList(ANY_CITUS_TABLE_TYPE);
|
List *citusTableIdList = CitusTableTypeIdList(ANY_CITUS_TABLE_TYPE);
|
||||||
citusTableIdList = list_append_unique_oid(citusTableIdList, ownerRelationId);
|
citusTableIdList = list_append_unique_oid(citusTableIdList, ownerRelationId);
|
||||||
|
@ -606,9 +607,9 @@ EnsureSequenceTypeSupported(Oid seqOid, Oid seqTypId, Oid ownerRelationId)
|
||||||
*/
|
*/
|
||||||
if (currentSeqOid == seqOid)
|
if (currentSeqOid == seqOid)
|
||||||
{
|
{
|
||||||
Oid currentSeqTypId = GetAttributeTypeOid(citusTableId,
|
Oid currentAttributeTypId = GetAttributeTypeOid(citusTableId,
|
||||||
currentAttnum);
|
currentAttnum);
|
||||||
if (seqTypId != currentSeqTypId)
|
if (attributeTypeId != currentAttributeTypId)
|
||||||
{
|
{
|
||||||
char *sequenceName = generate_qualified_relation_name(
|
char *sequenceName = generate_qualified_relation_name(
|
||||||
seqOid);
|
seqOid);
|
||||||
|
@ -685,17 +686,29 @@ EnsureDistributedSequencesHaveOneType(Oid relationId, List *dependentSequenceLis
|
||||||
* We should make sure that the type of the column that uses
|
* We should make sure that the type of the column that uses
|
||||||
* that sequence is supported
|
* that sequence is supported
|
||||||
*/
|
*/
|
||||||
Oid seqTypId = GetAttributeTypeOid(relationId, attnum);
|
Oid attributeTypeId = GetAttributeTypeOid(relationId, attnum);
|
||||||
EnsureSequenceTypeSupported(sequenceOid, seqTypId, relationId);
|
EnsureSequenceTypeSupported(sequenceOid, attributeTypeId, relationId);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Alter the sequence's data type in the coordinator if needed.
|
* Alter the sequence's data type in the coordinator if needed.
|
||||||
|
*
|
||||||
|
* First, we should only change the sequence type if the column
|
||||||
|
* is a supported sequence type. For example, if a sequence is used
|
||||||
|
* in an expression which then becomes a text, we should not try to
|
||||||
|
* alter the sequence type to text. Postgres only supports int2, int4
|
||||||
|
* and int8 as the sequence type.
|
||||||
|
*
|
||||||
* A sequence's type is bigint by default and it doesn't change even if
|
* A sequence's type is bigint by default and it doesn't change even if
|
||||||
* it's used in an int column. We should change the type if needed,
|
* it's used in an int column. We should change the type if needed,
|
||||||
* and not allow future ALTER SEQUENCE ... TYPE ... commands for
|
* and not allow future ALTER SEQUENCE ... TYPE ... commands for
|
||||||
* sequences used as defaults in distributed tables
|
* sequences used as defaults in distributed tables.
|
||||||
*/
|
*/
|
||||||
AlterSequenceType(sequenceOid, seqTypId);
|
if (attributeTypeId == INT2OID ||
|
||||||
|
attributeTypeId == INT4OID ||
|
||||||
|
attributeTypeId == INT8OID)
|
||||||
|
{
|
||||||
|
AlterSequenceType(sequenceOid, attributeTypeId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -290,7 +290,8 @@ extern bool GetNodeDiskSpaceStatsForConnection(MultiConnection *connection,
|
||||||
uint64 *availableBytes,
|
uint64 *availableBytes,
|
||||||
uint64 *totalBytes);
|
uint64 *totalBytes);
|
||||||
extern void ExecuteQueryViaSPI(char *query, int SPIOK);
|
extern void ExecuteQueryViaSPI(char *query, int SPIOK);
|
||||||
extern void EnsureSequenceTypeSupported(Oid seqOid, Oid seqTypId, Oid ownerRelationId);
|
extern void EnsureSequenceTypeSupported(Oid seqOid, Oid attributeTypeId, Oid
|
||||||
|
ownerRelationId);
|
||||||
extern void AlterSequenceType(Oid seqOid, Oid typeOid);
|
extern void AlterSequenceType(Oid seqOid, Oid typeOid);
|
||||||
extern void EnsureRelationHasCompatibleSequenceTypes(Oid relationId);
|
extern void EnsureRelationHasCompatibleSequenceTypes(Oid relationId);
|
||||||
#endif /* METADATA_UTILITY_H */
|
#endif /* METADATA_UTILITY_H */
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
CREATE SCHEMA sequences_with_different_types;
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
CREATE TYPE two_big_ints AS (a bigint, b bigint);
|
||||||
|
-- by default, sequences get bigint type
|
||||||
|
CREATE SEQUENCE bigint_sequence_1;
|
||||||
|
CREATE SEQUENCE bigint_sequence_2 START 10000;
|
||||||
|
CREATE SEQUENCE bigint_sequence_3 INCREMENT 10;
|
||||||
|
CREATE SEQUENCE bigint_sequence_4 MINVALUE 1000000;
|
||||||
|
CREATE SEQUENCE bigint_sequence_5;
|
||||||
|
CREATE SEQUENCE bigint_sequence_8;
|
||||||
|
CREATE TABLE table_1
|
||||||
|
(
|
||||||
|
user_id bigint,
|
||||||
|
user_code_1 text DEFAULT (('CD'::text || lpad(nextval('bigint_sequence_1'::regclass)::text, 10, '0'::text))),
|
||||||
|
user_code_2 text DEFAULT nextval('bigint_sequence_2'::regclass)::text,
|
||||||
|
user_code_3 text DEFAULT (nextval('bigint_sequence_3'::regclass) + 1000)::text,
|
||||||
|
user_code_4 float DEFAULT nextval('bigint_sequence_4'::regclass),
|
||||||
|
user_code_5 two_big_ints DEFAULT (nextval('bigint_sequence_5'::regclass), nextval('bigint_sequence_5'::regclass)),
|
||||||
|
user_code_8 jsonb DEFAULT to_jsonb('test'::text) || to_jsonb(nextval('bigint_sequence_8'::regclass))
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('table_1', 'user_id');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
INSERT INTO table_1 VALUES (1, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT), (2, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING *;
|
||||||
|
user_id | user_code_1 | user_code_2 | user_code_3 | user_code_4 | user_code_5 | user_code_8
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1 | CD0000000001 | 10000 | 1001 | 1000000 | (1,2) | ["test", 1]
|
||||||
|
2 | CD0000000002 | 10001 | 1011 | 1000001 | (3,4) | ["test", 2]
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
\c - - - :worker_1_port
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
INSERT INTO table_1 VALUES (3, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT), (4, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING *;
|
||||||
|
user_id | user_code_1 | user_code_2 | user_code_3 | user_code_4 | user_code_5 | user_code_8
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
3 | CD3940649673 | 3940649673949185 | 3940649673950185 | 3.94064967394918e+15 | (3940649673949185,3940649673949186) | ["test", 3940649673949185]
|
||||||
|
4 | CD3940649673 | 3940649673949186 | 3940649673950195 | 3.94064967394919e+15 | (3940649673949187,3940649673949188) | ["test", 3940649673949186]
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
\c - - - :master_port
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
CREATE SEQUENCE bigint_sequence_6;
|
||||||
|
CREATE TABLE table_2
|
||||||
|
(
|
||||||
|
user_id bigint,
|
||||||
|
user_code OID DEFAULT nextval('bigint_sequence_6'::regclass)
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('table_2', 'user_id');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- on the coordinator, the sequence starts from 0
|
||||||
|
INSERT INTO table_2 VALUES (1, DEFAULT) RETURNING *;
|
||||||
|
user_id | user_code
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1 | 1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
\c - - - :worker_1_port
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
-- this fails because on the workers the start value of the sequence
|
||||||
|
-- is greater than the largest value of an oid
|
||||||
|
INSERT INTO table_2 VALUES (1, DEFAULT) RETURNING *;
|
||||||
|
ERROR: OID out of range
|
||||||
|
\c - - - :master_port
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
CREATE SEQUENCE bigint_sequence_7;
|
||||||
|
CREATE TABLE table_3
|
||||||
|
(
|
||||||
|
user_id bigint,
|
||||||
|
user_code boolean DEFAULT ((nextval('bigint_sequence_7'::regclass)%2)::int)::boolean
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('table_3', 'user_id');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
INSERT INTO table_3 VALUES (1, DEFAULT), (2, DEFAULT) RETURNING *;
|
||||||
|
user_id | user_code
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1 | t
|
||||||
|
2 | f
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
\c - - - :worker_1_port
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
INSERT INTO table_3 VALUES (3, DEFAULT), (4, DEFAULT) RETURNING *;
|
||||||
|
user_id | user_code
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
3 | t
|
||||||
|
4 | f
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
\c - - - :master_port
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
|
DROP SCHEMA sequences_with_different_types CASCADE;
|
|
@ -53,7 +53,7 @@ test: subqueries_deep subquery_view subquery_partitioning subqueries_not_support
|
||||||
test: subquery_in_targetlist subquery_in_where subquery_complex_target_list subquery_append
|
test: subquery_in_targetlist subquery_in_where subquery_complex_target_list subquery_append
|
||||||
test: subquery_prepared_statements
|
test: subquery_prepared_statements
|
||||||
test: non_colocated_leaf_subquery_joins non_colocated_subquery_joins
|
test: non_colocated_leaf_subquery_joins non_colocated_subquery_joins
|
||||||
test: cte_inline recursive_view_local_table values
|
test: cte_inline recursive_view_local_table values sequences_with_different_types
|
||||||
test: pg13 pg12
|
test: pg13 pg12
|
||||||
# run pg14 sequentially as it syncs metadata
|
# run pg14 sequentially as it syncs metadata
|
||||||
test: pg14
|
test: pg14
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
CREATE SCHEMA sequences_with_different_types;
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
|
||||||
|
CREATE TYPE two_big_ints AS (a bigint, b bigint);
|
||||||
|
-- by default, sequences get bigint type
|
||||||
|
CREATE SEQUENCE bigint_sequence_1;
|
||||||
|
CREATE SEQUENCE bigint_sequence_2 START 10000;
|
||||||
|
CREATE SEQUENCE bigint_sequence_3 INCREMENT 10;
|
||||||
|
CREATE SEQUENCE bigint_sequence_4 MINVALUE 1000000;
|
||||||
|
CREATE SEQUENCE bigint_sequence_5;
|
||||||
|
CREATE SEQUENCE bigint_sequence_8;
|
||||||
|
|
||||||
|
CREATE TABLE table_1
|
||||||
|
(
|
||||||
|
user_id bigint,
|
||||||
|
user_code_1 text DEFAULT (('CD'::text || lpad(nextval('bigint_sequence_1'::regclass)::text, 10, '0'::text))),
|
||||||
|
user_code_2 text DEFAULT nextval('bigint_sequence_2'::regclass)::text,
|
||||||
|
user_code_3 text DEFAULT (nextval('bigint_sequence_3'::regclass) + 1000)::text,
|
||||||
|
user_code_4 float DEFAULT nextval('bigint_sequence_4'::regclass),
|
||||||
|
user_code_5 two_big_ints DEFAULT (nextval('bigint_sequence_5'::regclass), nextval('bigint_sequence_5'::regclass)),
|
||||||
|
user_code_8 jsonb DEFAULT to_jsonb('test'::text) || to_jsonb(nextval('bigint_sequence_8'::regclass))
|
||||||
|
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('table_1', 'user_id');
|
||||||
|
|
||||||
|
INSERT INTO table_1 VALUES (1, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT), (2, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING *;
|
||||||
|
|
||||||
|
\c - - - :worker_1_port
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
|
||||||
|
INSERT INTO table_1 VALUES (3, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT), (4, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING *;
|
||||||
|
|
||||||
|
|
||||||
|
\c - - - :master_port
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
CREATE SEQUENCE bigint_sequence_6;
|
||||||
|
|
||||||
|
CREATE TABLE table_2
|
||||||
|
(
|
||||||
|
user_id bigint,
|
||||||
|
user_code OID DEFAULT nextval('bigint_sequence_6'::regclass)
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('table_2', 'user_id');
|
||||||
|
|
||||||
|
-- on the coordinator, the sequence starts from 0
|
||||||
|
INSERT INTO table_2 VALUES (1, DEFAULT) RETURNING *;
|
||||||
|
|
||||||
|
\c - - - :worker_1_port
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
|
||||||
|
-- this fails because on the workers the start value of the sequence
|
||||||
|
-- is greater than the largest value of an oid
|
||||||
|
INSERT INTO table_2 VALUES (1, DEFAULT) RETURNING *;
|
||||||
|
|
||||||
|
\c - - - :master_port
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
CREATE SEQUENCE bigint_sequence_7;
|
||||||
|
|
||||||
|
CREATE TABLE table_3
|
||||||
|
(
|
||||||
|
user_id bigint,
|
||||||
|
user_code boolean DEFAULT ((nextval('bigint_sequence_7'::regclass)%2)::int)::boolean
|
||||||
|
);
|
||||||
|
SELECT create_distributed_table('table_3', 'user_id');
|
||||||
|
|
||||||
|
INSERT INTO table_3 VALUES (1, DEFAULT), (2, DEFAULT) RETURNING *;
|
||||||
|
|
||||||
|
\c - - - :worker_1_port
|
||||||
|
SET search_path TO sequences_with_different_types;
|
||||||
|
INSERT INTO table_3 VALUES (3, DEFAULT), (4, DEFAULT) RETURNING *;
|
||||||
|
|
||||||
|
\c - - - :master_port
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
|
DROP SCHEMA sequences_with_different_types CASCADE;
|
Loading…
Reference in New Issue