mirror of https://github.com/citusdata/citus.git
Merge pull request #783 from robin900/new-extend-names
Provides safe, backwards-compatible shard-extended names to any object namepull/821/head
commit
6c0fc0c970
|
@ -8,7 +8,7 @@ EXTENSION = citus
|
|||
EXTVERSIONS = 5.0 5.0-1 5.0-2 \
|
||||
5.1-1 5.1-2 5.1-3 5.1-4 5.1-5 5.1-6 5.1-7 5.1-8 \
|
||||
5.2-1 5.2-2 5.2-3 5.2-4 \
|
||||
6.0-1
|
||||
6.0-1 6.0-2
|
||||
|
||||
# All citus--*.sql files in the source directory
|
||||
DATA = $(patsubst $(citus_abs_srcdir)/%.sql,%.sql,$(wildcard $(citus_abs_srcdir)/$(EXTENSION)--*--*.sql))
|
||||
|
@ -60,6 +60,8 @@ $(EXTENSION)--5.2-4.sql: $(EXTENSION)--5.2-3.sql $(EXTENSION)--5.2-3--5.2-4.sql
|
|||
cat $^ > $@
|
||||
$(EXTENSION)--6.0-1.sql: $(EXTENSION)--5.2-4.sql $(EXTENSION)--5.2-4--6.0-1.sql
|
||||
cat $^ > $@
|
||||
$(EXTENSION)--6.0-2.sql: $(EXTENSION)--6.0-1.sql $(EXTENSION)--6.0-1--6.0-2.sql
|
||||
cat $^ > $@
|
||||
|
||||
NO_PGXS = 1
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/* citus--6.0-1--6.0-2.sql */
|
||||
|
||||
CREATE FUNCTION pg_catalog.shard_name(object_name regclass, shard_id bigint)
|
||||
RETURNS text
|
||||
LANGUAGE C STABLE
|
||||
AS 'MODULE_PATHNAME', $$shard_name$$;
|
||||
COMMENT ON FUNCTION pg_catalog.shard_name(object_name regclass, shard_id bigint)
|
||||
IS 'returns shard-extended version of object name';
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Citus extension
|
||||
comment = 'Citus distributed database'
|
||||
default_version = '6.0-1'
|
||||
default_version = '6.0-2'
|
||||
module_pathname = '$libdir/citus'
|
||||
relocatable = false
|
||||
schema = pg_catalog
|
||||
|
|
|
@ -317,14 +317,13 @@ DropShards(Oid relationId, char *schemaName, char *relationName,
|
|||
ShardInterval *shardInterval = (ShardInterval *) lfirst(shardIntervalCell);
|
||||
uint64 shardId = shardInterval->shardId;
|
||||
char *quotedShardName = NULL;
|
||||
StringInfo shardName = makeStringInfo();
|
||||
char *shardRelationName = pnstrdup(relationName, NAMEDATALEN);
|
||||
|
||||
Assert(shardInterval->relationId == relationId);
|
||||
|
||||
/* Build shard relation name. */
|
||||
appendStringInfoString(shardName, relationName);
|
||||
AppendShardIdToStringInfo(shardName, shardId);
|
||||
quotedShardName = quote_qualified_identifier(schemaName, shardName->data);
|
||||
AppendShardIdToName(&shardRelationName, shardId);
|
||||
quotedShardName = quote_qualified_identifier(schemaName, shardRelationName);
|
||||
|
||||
shardPlacementList = ShardPlacementList(shardId);
|
||||
foreach(shardPlacementCell, shardPlacementList)
|
||||
|
@ -386,7 +385,7 @@ DropShards(Oid relationId, char *schemaName, char *relationName,
|
|||
workerName, workerPort);
|
||||
|
||||
ereport(WARNING, (errmsg("could not delete shard \"%s\" on node \"%s:%u\"",
|
||||
shardName->data, workerName, workerPort),
|
||||
shardRelationName, workerName, workerPort),
|
||||
errdetail("Marking this shard placement for deletion")));
|
||||
}
|
||||
|
||||
|
|
|
@ -144,7 +144,6 @@ DropShardsFromWorker(WorkerNode *workerNode, Oid relationId, List *shardInterval
|
|||
char *schemaName = get_namespace_name(schemaId);
|
||||
char *relationName = get_rel_name(relationId);
|
||||
char relationKind = get_rel_relkind(relationId);
|
||||
StringInfo shardName = makeStringInfo();
|
||||
StringInfo workerCommand = makeStringInfo();
|
||||
ListCell *shardIntervalCell = NULL;
|
||||
|
||||
|
@ -170,12 +169,11 @@ DropShardsFromWorker(WorkerNode *workerNode, Oid relationId, List *shardInterval
|
|||
foreach(shardIntervalCell, shardIntervalList)
|
||||
{
|
||||
ShardInterval *shardInterval = (ShardInterval *) lfirst(shardIntervalCell);
|
||||
char *shardName = pnstrdup(relationName, NAMEDATALEN);
|
||||
char *quotedShardName = NULL;
|
||||
|
||||
resetStringInfo(shardName);
|
||||
appendStringInfo(shardName, "%s", relationName);
|
||||
AppendShardIdToStringInfo(shardName, shardInterval->shardId);
|
||||
quotedShardName = quote_qualified_identifier(schemaName, shardName->data);
|
||||
AppendShardIdToName(&shardName, shardInterval->shardId);
|
||||
quotedShardName = quote_qualified_identifier(schemaName, shardName);
|
||||
appendStringInfo(workerCommand, "%s", quotedShardName);
|
||||
|
||||
/* append a comma after the shard name if there are more shards */
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "access/genam.h"
|
||||
#include "access/heapam.h"
|
||||
#include "access/htup_details.h"
|
||||
#include "access/hash.h"
|
||||
#include "access/htup.h"
|
||||
#include "access/skey.h"
|
||||
#include "access/stratnum.h"
|
||||
|
@ -29,6 +30,7 @@
|
|||
#include "catalog/pg_constraint.h"
|
||||
#include "distributed/relay_utility.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "mb/pg_wchar.h"
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/nodeFuncs.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
|
@ -36,9 +38,11 @@
|
|||
#include "nodes/primnodes.h"
|
||||
#include "nodes/value.h"
|
||||
#include "storage/lock.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/elog.h"
|
||||
#include "utils/errcodes.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/palloc.h"
|
||||
#include "utils/relcache.h"
|
||||
|
||||
|
@ -50,6 +54,9 @@ static void AppendShardIdToConstraintName(AlterTableCmd *command, uint64 shardId
|
|||
static void SetSchemaNameIfNotExist(char **schemaName, char *newSchemaName);
|
||||
static bool UpdateWholeRowColumnReferencesWalker(Node *node, uint64 *shardId);
|
||||
|
||||
/* exports for SQL callable functions */
|
||||
PG_FUNCTION_INFO_V1(shard_name);
|
||||
|
||||
/*
|
||||
* RelayEventExtendNames extends relation names in the given parse tree for
|
||||
* certain utility commands. The function more specifically extends table and
|
||||
|
@ -624,32 +631,120 @@ AppendShardIdToName(char **name, uint64 shardId)
|
|||
{
|
||||
char extendedName[NAMEDATALEN];
|
||||
uint32 extendedNameLength = 0;
|
||||
int nameLength = strlen(*name);
|
||||
char shardIdAndSeparator[NAMEDATALEN];
|
||||
int shardIdAndSeparatorLength;
|
||||
uint32 longNameHash = 0;
|
||||
int multiByteClipLength = 0;
|
||||
|
||||
snprintf(extendedName, NAMEDATALEN, "%s%c" UINT64_FORMAT,
|
||||
(*name), SHARD_NAME_SEPARATOR, shardId);
|
||||
snprintf(shardIdAndSeparator, NAMEDATALEN, "%c" UINT64_FORMAT,
|
||||
SHARD_NAME_SEPARATOR, shardId);
|
||||
shardIdAndSeparatorLength = strlen(shardIdAndSeparator);
|
||||
|
||||
/*
|
||||
* Parser should have already checked that the table name has enough space
|
||||
* reserved for appending shardIds. Nonetheless, we perform an additional
|
||||
* check here to verify that the appended name does not overflow.
|
||||
* If *name strlen is < (NAMEDATALEN - shardIdAndSeparatorLength),
|
||||
* it is safe merely to append the separator and shardId.
|
||||
*/
|
||||
extendedNameLength = strlen(extendedName) + 1;
|
||||
if (extendedNameLength >= NAMEDATALEN)
|
||||
|
||||
if (nameLength < (NAMEDATALEN - shardIdAndSeparatorLength))
|
||||
{
|
||||
ereport(ERROR, (errmsg("shard name too long to extend: \"%s\"", (*name))));
|
||||
snprintf(extendedName, NAMEDATALEN, "%s%s", (*name), shardIdAndSeparator);
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, we need to truncate the name further to accommodate
|
||||
* a sufficient hash value. The resulting name will avoid collision
|
||||
* with other hashed names such that for any given schema with
|
||||
* 90 distinct object names that are long enough to require hashing
|
||||
* (typically 57-63 characters), the chance of a collision existing is:
|
||||
*
|
||||
* If randomly generated UTF8 names:
|
||||
* (1e-6) * (9.39323783788e-114) ~= (9.39e-120)
|
||||
* If random case-insensitive ASCII names (letter first, 37 useful characters):
|
||||
* (1e-6) * (2.80380202421e-74) ~= (2.8e-80)
|
||||
* If names sharing only N distinct 45- to 47-character prefixes:
|
||||
* (1e-6) * (1/N) = (1e-6/N)
|
||||
* 1e-7 for 10 distinct prefixes
|
||||
* 5e-8 for 20 distinct prefixes
|
||||
*
|
||||
* In practice, since shard IDs are globally unique, the risk of name collision
|
||||
* exists only amongst objects that pertain to a single distributed table
|
||||
* and are created for each shard: the table name and the names of any indexes
|
||||
* or index-backed constraints. Since there are typically less than five such
|
||||
* names, and almost never more than ten, the expected collision rate even in
|
||||
* the worst case (ten names share same 45- to 47-character prefix) is roughly
|
||||
* 1e-8: one in 100 million schemas will experience a name collision only if ALL
|
||||
* 100 million schemas present the worst-case scenario.
|
||||
*/
|
||||
else
|
||||
{
|
||||
longNameHash = hash_any((unsigned char *) (*name), nameLength);
|
||||
multiByteClipLength = pg_mbcliplen(*name, nameLength, (NAMEDATALEN -
|
||||
shardIdAndSeparatorLength -
|
||||
10));
|
||||
snprintf(extendedName, NAMEDATALEN, "%.*s%c%.8x%s",
|
||||
multiByteClipLength, (*name),
|
||||
SHARD_NAME_SEPARATOR, longNameHash,
|
||||
shardIdAndSeparator);
|
||||
}
|
||||
extendedNameLength = strlen(extendedName) + 1;
|
||||
Assert(extendedNameLength <= NAMEDATALEN);
|
||||
|
||||
(*name) = (char *) repalloc((*name), extendedNameLength);
|
||||
snprintf((*name), extendedNameLength, "%s", extendedName);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AppendShardIdToStringInfo appends shardId to the given name, represented
|
||||
* by a StringInfo.
|
||||
* shard_name() provides a PG function interface to AppendShardNameToId above.
|
||||
*/
|
||||
void
|
||||
AppendShardIdToStringInfo(StringInfo name, uint64 shardId)
|
||||
Datum
|
||||
shard_name(PG_FUNCTION_ARGS)
|
||||
{
|
||||
appendStringInfo(name, "%c" UINT64_FORMAT, SHARD_NAME_SEPARATOR, shardId);
|
||||
Oid relationId = InvalidOid;
|
||||
int64 shardId = 0;
|
||||
char *relationName = NULL;
|
||||
|
||||
/*
|
||||
* Have to check arguments for NULLness as it can't be declared STRICT
|
||||
* because of min/max arguments, which have to be NULLable for new shards.
|
||||
*/
|
||||
if (PG_ARGISNULL(0))
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("object_name cannot be null")));
|
||||
}
|
||||
if (PG_ARGISNULL(1))
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("shard_id cannot be null")));
|
||||
}
|
||||
|
||||
|
||||
relationId = PG_GETARG_OID(0);
|
||||
shardId = PG_GETARG_INT64(1);
|
||||
|
||||
if (shardId <= 0)
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("shard_id cannot be zero or negative value")));
|
||||
}
|
||||
|
||||
|
||||
if (!OidIsValid(relationId))
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("object_name does not reference a valid relation")));
|
||||
}
|
||||
|
||||
relationName = get_rel_name(relationId);
|
||||
|
||||
if (relationName == NULL)
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("object_name does not reference a valid relation")));
|
||||
}
|
||||
|
||||
AppendShardIdToName(&relationName, shardId);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(relationName));
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#ifndef RELAY_UTILITY_H
|
||||
#define RELAY_UTILITY_H
|
||||
|
||||
#include "fmgr.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "nodes/nodes.h"
|
||||
|
||||
|
@ -41,7 +42,5 @@ typedef enum
|
|||
/* Function declarations to extend names in DDL commands */
|
||||
extern void RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId);
|
||||
extern void AppendShardIdToName(char **name, uint64 shardId);
|
||||
extern void AppendShardIdToStringInfo(StringInfo name, uint64 shardId);
|
||||
|
||||
|
||||
#endif /* RELAY_UTILITY_H */
|
||||
|
|
|
@ -0,0 +1,398 @@
|
|||
--
|
||||
-- MULTI_NAME_LENGTHS
|
||||
--
|
||||
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 225000;
|
||||
ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 225000;
|
||||
SET citus.multi_shard_commit_protocol = '2pc';
|
||||
-- Verify that a table name > 56 characters gets hashed properly.
|
||||
CREATE TABLE too_long_12345678901234567890123456789012345678901234567890 (
|
||||
col1 integer not null,
|
||||
col2 integer not null);
|
||||
SELECT master_create_distributed_table('too_long_12345678901234567890123456789012345678901234567890', 'col1', 'hash');
|
||||
master_create_distributed_table
|
||||
---------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT master_create_worker_shards('too_long_12345678901234567890123456789012345678901234567890', '2', '2');
|
||||
master_create_worker_shards
|
||||
-----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d too_long_*
|
||||
Table "public.too_long_12345678901234567890123456789012345678_e0119164_225000"
|
||||
Column | Type | Modifiers
|
||||
--------+---------+-----------
|
||||
col1 | integer | not null
|
||||
col2 | integer | not null
|
||||
|
||||
Table "public.too_long_12345678901234567890123456789012345678_e0119164_225001"
|
||||
Column | Type | Modifiers
|
||||
--------+---------+-----------
|
||||
col1 | integer | not null
|
||||
col2 | integer | not null
|
||||
|
||||
\c - - - :master_port
|
||||
-- Verify that the UDF works and rejects bad arguments.
|
||||
SELECT shard_name(NULL, 666666);
|
||||
ERROR: object_name cannot be null
|
||||
SELECT shard_name(0, 666666);
|
||||
ERROR: object_name does not reference a valid relation
|
||||
SELECT shard_name('too_long_12345678901234567890123456789012345678901234567890'::regclass, 666666);
|
||||
shard_name
|
||||
-----------------------------------------------------------------
|
||||
too_long_12345678901234567890123456789012345678_e0119164_666666
|
||||
(1 row)
|
||||
|
||||
SELECT shard_name('too_long_12345678901234567890123456789012345678901234567890'::regclass, NULL);
|
||||
ERROR: shard_id cannot be null
|
||||
SELECT shard_name('too_long_12345678901234567890123456789012345678901234567890'::regclass, -21);
|
||||
ERROR: shard_id cannot be zero or negative value
|
||||
DROP TABLE too_long_12345678901234567890123456789012345678901234567890 CASCADE;
|
||||
-- Table to use for rename checks.
|
||||
CREATE TABLE name_lengths (
|
||||
col1 integer not null,
|
||||
col2 integer not null,
|
||||
constraint constraint_a UNIQUE (col1)
|
||||
);
|
||||
SELECT master_create_distributed_table('name_lengths', 'col1', 'hash');
|
||||
master_create_distributed_table
|
||||
---------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT master_create_worker_shards('name_lengths', '2', '2');
|
||||
master_create_worker_shards
|
||||
-----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- Verify that we CAN add columns with "too-long names", because
|
||||
-- the columns' names are not extended in the corresponding shard tables.
|
||||
ALTER TABLE name_lengths ADD COLUMN float_col_12345678901234567890123456789012345678901234567890 FLOAT;
|
||||
NOTICE: using one-phase commit for distributed DDL commands
|
||||
HINT: You can enable two-phase commit for extra safety with: SET citus.multi_shard_commit_protocol TO '2pc'
|
||||
ALTER TABLE name_lengths ADD COLUMN date_col_12345678901234567890123456789012345678901234567890 DATE;
|
||||
ALTER TABLE name_lengths ADD COLUMN int_col_12345678901234567890123456789012345678901234567890 INTEGER DEFAULT 1;
|
||||
-- Placeholders for unsupported ALTER TABLE to add constraints with implicit names that are likely too long
|
||||
ALTER TABLE name_lengths ADD UNIQUE (float_col_12345678901234567890123456789012345678901234567890);
|
||||
ERROR: alter table command is currently supported
|
||||
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported.
|
||||
ALTER TABLE name_lengths ADD EXCLUDE (int_col_12345678901234567890123456789012345678901234567890 WITH =);
|
||||
ERROR: alter table command is currently supported
|
||||
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported.
|
||||
ALTER TABLE name_lengths ADD CHECK (date_col_12345678901234567890123456789012345678901234567890 > '2014-01-01'::date);
|
||||
ERROR: alter table command is currently supported
|
||||
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported.
|
||||
\c - - - :worker_1_port
|
||||
\d name_lengths_*
|
||||
Table "public.name_lengths_225002"
|
||||
Column | Type | Modifiers
|
||||
--------------------------------------------------------------+------------------+-----------
|
||||
col1 | integer | not null
|
||||
col2 | integer | not null
|
||||
float_col_12345678901234567890123456789012345678901234567890 | double precision |
|
||||
date_col_12345678901234567890123456789012345678901234567890 | date |
|
||||
int_col_12345678901234567890123456789012345678901234567890 | integer | default 1
|
||||
Indexes:
|
||||
"constraint_a_225002" UNIQUE CONSTRAINT, btree (col1)
|
||||
|
||||
Table "public.name_lengths_225003"
|
||||
Column | Type | Modifiers
|
||||
--------------------------------------------------------------+------------------+-----------
|
||||
col1 | integer | not null
|
||||
col2 | integer | not null
|
||||
float_col_12345678901234567890123456789012345678901234567890 | double precision |
|
||||
date_col_12345678901234567890123456789012345678901234567890 | date |
|
||||
int_col_12345678901234567890123456789012345678901234567890 | integer | default 1
|
||||
Indexes:
|
||||
"constraint_a_225003" UNIQUE CONSTRAINT, btree (col1)
|
||||
|
||||
\c - - - :master_port
|
||||
-- Placeholders for unsupported add constraints with EXPLICIT names that are too long
|
||||
ALTER TABLE name_lengths ADD CONSTRAINT nl_unique_12345678901234567890123456789012345678901234567890 UNIQUE (float_col_12345678901234567890123456789012345678901234567890);
|
||||
ERROR: alter table command is currently supported
|
||||
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported.
|
||||
ALTER TABLE name_lengths ADD CONSTRAINT nl_exclude_12345678901234567890123456789012345678901234567890 EXCLUDE (int_col_12345678901234567890123456789012345678901234567890 WITH =);
|
||||
ERROR: alter table command is currently supported
|
||||
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported.
|
||||
ALTER TABLE name_lengths ADD CONSTRAINT nl_checky_12345678901234567890123456789012345678901234567890 CHECK (date_col_12345678901234567890123456789012345678901234567890 >= '2014-01-01'::date);
|
||||
ERROR: alter table command is currently supported
|
||||
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported.
|
||||
\c - - - :worker_1_port
|
||||
\d nl_*
|
||||
\c - - - :master_port
|
||||
-- Placeholders for RENAME operations
|
||||
ALTER TABLE name_lengths RENAME TO name_len_12345678901234567890123456789012345678901234567890;
|
||||
ERROR: renaming distributed tables or their objects is currently unsupported
|
||||
ALTER TABLE name_lengths RENAME CONSTRAINT unique_12345678901234567890123456789012345678901234567890 TO unique2_12345678901234567890123456789012345678901234567890;
|
||||
ERROR: renaming distributed tables or their objects is currently unsupported
|
||||
-- Verify that CREATE INDEX on already distributed table has proper shard names.
|
||||
CREATE INDEX tmp_idx_12345678901234567890123456789012345678901234567890 ON name_lengths(col2);
|
||||
NOTICE: using one-phase commit for distributed DDL commands
|
||||
HINT: You can enable two-phase commit for extra safety with: SET citus.multi_shard_commit_protocol TO '2pc'
|
||||
\c - - - :worker_1_port
|
||||
\d tmp_idx_*
|
||||
Index "public.tmp_idx_123456789012345678901234567890123456789_5e470afa_225002"
|
||||
Column | Type | Definition
|
||||
--------+---------+------------
|
||||
col2 | integer | col2
|
||||
btree, for table "public.name_lengths_225002"
|
||||
|
||||
Index "public.tmp_idx_123456789012345678901234567890123456789_5e470afa_225003"
|
||||
Column | Type | Definition
|
||||
--------+---------+------------
|
||||
col2 | integer | col2
|
||||
btree, for table "public.name_lengths_225003"
|
||||
|
||||
\c - - - :master_port
|
||||
-- Verify that a new index name > 63 characters is auto-truncated
|
||||
-- by the parser/rewriter before further processing, just as in Postgres.
|
||||
CREATE INDEX tmp_idx_123456789012345678901234567890123456789012345678901234567890 ON name_lengths(col2);
|
||||
NOTICE: identifier "tmp_idx_123456789012345678901234567890123456789012345678901234567890" will be truncated to "tmp_idx_1234567890123456789012345678901234567890123456789012345"
|
||||
NOTICE: using one-phase commit for distributed DDL commands
|
||||
HINT: You can enable two-phase commit for extra safety with: SET citus.multi_shard_commit_protocol TO '2pc'
|
||||
\c - - - :worker_1_port
|
||||
\d tmp_idx_*
|
||||
Index "public.tmp_idx_123456789012345678901234567890123456789_599636aa_225002"
|
||||
Column | Type | Definition
|
||||
--------+---------+------------
|
||||
col2 | integer | col2
|
||||
btree, for table "public.name_lengths_225002"
|
||||
|
||||
Index "public.tmp_idx_123456789012345678901234567890123456789_599636aa_225003"
|
||||
Column | Type | Definition
|
||||
--------+---------+------------
|
||||
col2 | integer | col2
|
||||
btree, for table "public.name_lengths_225003"
|
||||
|
||||
Index "public.tmp_idx_123456789012345678901234567890123456789_5e470afa_225002"
|
||||
Column | Type | Definition
|
||||
--------+---------+------------
|
||||
col2 | integer | col2
|
||||
btree, for table "public.name_lengths_225002"
|
||||
|
||||
Index "public.tmp_idx_123456789012345678901234567890123456789_5e470afa_225003"
|
||||
Column | Type | Definition
|
||||
--------+---------+------------
|
||||
col2 | integer | col2
|
||||
btree, for table "public.name_lengths_225003"
|
||||
|
||||
\c - - - :master_port
|
||||
-- Verify that distributed tables with too-long names
|
||||
-- for CHECK constraints are no trouble.
|
||||
CREATE TABLE sneaky_name_lengths (
|
||||
col1 integer not null,
|
||||
col2 integer not null,
|
||||
int_col_12345678901234567890123456789012345678901234567890 integer not null,
|
||||
CHECK (int_col_12345678901234567890123456789012345678901234567890 > 100)
|
||||
);
|
||||
SELECT master_create_distributed_table('sneaky_name_lengths', 'col1', 'hash');
|
||||
master_create_distributed_table
|
||||
---------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT master_create_worker_shards('sneaky_name_lengths', '2', '2');
|
||||
master_create_worker_shards
|
||||
-----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
DROP TABLE sneaky_name_lengths CASCADE;
|
||||
CREATE TABLE sneaky_name_lengths (
|
||||
int_col_123456789012345678901234567890123456789012345678901234 integer UNIQUE not null,
|
||||
col2 integer not null,
|
||||
CONSTRAINT checky_12345678901234567890123456789012345678901234567890 CHECK (int_col_123456789012345678901234567890123456789012345678901234 > 100)
|
||||
);
|
||||
\d sneaky_name_lengths*
|
||||
Table "public.sneaky_name_lengths"
|
||||
Column | Type | Modifiers
|
||||
----------------------------------------------------------------+---------+-----------
|
||||
int_col_123456789012345678901234567890123456789012345678901234 | integer | not null
|
||||
col2 | integer | not null
|
||||
Indexes:
|
||||
"sneaky_name_lengths_int_col_1234567890123456789012345678901_key" UNIQUE CONSTRAINT, btree (int_col_123456789012345678901234567890123456789012345678901234)
|
||||
Check constraints:
|
||||
"checky_12345678901234567890123456789012345678901234567890" CHECK (int_col_123456789012345678901234567890123456789012345678901234 > 100)
|
||||
|
||||
Index "public.sneaky_name_lengths_int_col_1234567890123456789012345678901_key"
|
||||
Column | Type | Definition
|
||||
----------------------------------------------------------------+---------+----------------------------------------------------------------
|
||||
int_col_123456789012345678901234567890123456789012345678901234 | integer | int_col_123456789012345678901234567890123456789012345678901234
|
||||
unique, btree, for table "public.sneaky_name_lengths"
|
||||
|
||||
SELECT master_create_distributed_table('sneaky_name_lengths', 'int_col_123456789012345678901234567890123456789012345678901234', 'hash');
|
||||
master_create_distributed_table
|
||||
---------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT master_create_worker_shards('sneaky_name_lengths', '2', '2');
|
||||
master_create_worker_shards
|
||||
-----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d sneaky_name_lengths*
|
||||
Table "public.sneaky_name_lengths_225006"
|
||||
Column | Type | Modifiers
|
||||
----------------------------------------------------------------+---------+-----------
|
||||
int_col_123456789012345678901234567890123456789012345678901234 | integer | not null
|
||||
col2 | integer | not null
|
||||
Indexes:
|
||||
"sneaky_name_lengths_int_col_1234567890123456789_6402d2cd_225006" UNIQUE CONSTRAINT, btree (int_col_123456789012345678901234567890123456789012345678901234)
|
||||
Check constraints:
|
||||
"checky_12345678901234567890123456789012345678901234567890" CHECK (int_col_123456789012345678901234567890123456789012345678901234 > 100)
|
||||
|
||||
Table "public.sneaky_name_lengths_225007"
|
||||
Column | Type | Modifiers
|
||||
----------------------------------------------------------------+---------+-----------
|
||||
int_col_123456789012345678901234567890123456789012345678901234 | integer | not null
|
||||
col2 | integer | not null
|
||||
Indexes:
|
||||
"sneaky_name_lengths_int_col_1234567890123456789_6402d2cd_225007" UNIQUE CONSTRAINT, btree (int_col_123456789012345678901234567890123456789012345678901234)
|
||||
Check constraints:
|
||||
"checky_12345678901234567890123456789012345678901234567890" CHECK (int_col_123456789012345678901234567890123456789012345678901234 > 100)
|
||||
|
||||
Index "public.sneaky_name_lengths_int_col_1234567890123456789_6402d2cd_225006"
|
||||
Column | Type | Definition
|
||||
----------------------------------------------------------------+---------+----------------------------------------------------------------
|
||||
int_col_123456789012345678901234567890123456789012345678901234 | integer | int_col_123456789012345678901234567890123456789012345678901234
|
||||
unique, btree, for table "public.sneaky_name_lengths_225006"
|
||||
|
||||
Index "public.sneaky_name_lengths_int_col_1234567890123456789_6402d2cd_225007"
|
||||
Column | Type | Definition
|
||||
----------------------------------------------------------------+---------+----------------------------------------------------------------
|
||||
int_col_123456789012345678901234567890123456789012345678901234 | integer | int_col_123456789012345678901234567890123456789012345678901234
|
||||
unique, btree, for table "public.sneaky_name_lengths_225007"
|
||||
|
||||
\c - - - :master_port
|
||||
DROP TABLE sneaky_name_lengths CASCADE;
|
||||
-- verify that named constraint with too-long name gets hashed properly
|
||||
CREATE TABLE sneaky_name_lengths (
|
||||
col1 integer not null,
|
||||
col2 integer not null,
|
||||
int_col_12345678901234567890123456789012345678901234567890 integer not null,
|
||||
constraint unique_12345678901234567890123456789012345678901234567890 UNIQUE (col1)
|
||||
);
|
||||
SELECT master_create_distributed_table('sneaky_name_lengths', 'col1', 'hash');
|
||||
master_create_distributed_table
|
||||
---------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT master_create_worker_shards('sneaky_name_lengths', '2', '2');
|
||||
master_create_worker_shards
|
||||
-----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d sneaky_name_lengths*
|
||||
Table "public.sneaky_name_lengths_225008"
|
||||
Column | Type | Modifiers
|
||||
------------------------------------------------------------+---------+-----------
|
||||
col1 | integer | not null
|
||||
col2 | integer | not null
|
||||
int_col_12345678901234567890123456789012345678901234567890 | integer | not null
|
||||
Indexes:
|
||||
"unique_1234567890123456789012345678901234567890_a5986f27_225008" UNIQUE CONSTRAINT, btree (col1)
|
||||
|
||||
Table "public.sneaky_name_lengths_225009"
|
||||
Column | Type | Modifiers
|
||||
------------------------------------------------------------+---------+-----------
|
||||
col1 | integer | not null
|
||||
col2 | integer | not null
|
||||
int_col_12345678901234567890123456789012345678901234567890 | integer | not null
|
||||
Indexes:
|
||||
"unique_1234567890123456789012345678901234567890_a5986f27_225009" UNIQUE CONSTRAINT, btree (col1)
|
||||
|
||||
\c - - - :master_port
|
||||
DROP TABLE sneaky_name_lengths CASCADE;
|
||||
-- Verify that much larger shardIds are handled properly
|
||||
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 2250000000000;
|
||||
CREATE TABLE too_long_12345678901234567890123456789012345678901234567890 (
|
||||
col1 integer not null,
|
||||
col2 integer not null);
|
||||
SELECT master_create_distributed_table('too_long_12345678901234567890123456789012345678901234567890', 'col1', 'hash');
|
||||
master_create_distributed_table
|
||||
---------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT master_create_worker_shards('too_long_12345678901234567890123456789012345678901234567890', '2', '2');
|
||||
master_create_worker_shards
|
||||
-----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d too_long_*
|
||||
Table "public.too_long_1234567890123456789012345678901_e0119164_2250000000000"
|
||||
Column | Type | Modifiers
|
||||
--------+---------+-----------
|
||||
col1 | integer | not null
|
||||
col2 | integer | not null
|
||||
|
||||
Table "public.too_long_1234567890123456789012345678901_e0119164_2250000000001"
|
||||
Column | Type | Modifiers
|
||||
--------+---------+-----------
|
||||
col1 | integer | not null
|
||||
col2 | integer | not null
|
||||
|
||||
\c - - - :master_port
|
||||
DROP TABLE too_long_12345678901234567890123456789012345678901234567890 CASCADE;
|
||||
-- Verify that multi-byte boundaries are respected for databases with UTF8 encoding.
|
||||
CREATE TABLE U&"elephant_!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D" UESCAPE '!' (
|
||||
col1 integer not null PRIMARY KEY,
|
||||
col2 integer not null);
|
||||
SELECT master_create_distributed_table(U&'elephant_!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D' UESCAPE '!', 'col1', 'hash');
|
||||
master_create_distributed_table
|
||||
---------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT master_create_worker_shards(U&'elephant_!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D' UESCAPE '!', '2', '2');
|
||||
master_create_worker_shards
|
||||
-----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d elephant_*
|
||||
Index "public.elephant_слонслонслонсло_14d34928_2250000000002"
|
||||
Column | Type | Definition
|
||||
--------+---------+------------
|
||||
col1 | integer | col1
|
||||
primary key, btree, for table "public.elephant_слонслонслонсло_c8b737c2_2250000000002"
|
||||
|
||||
Index "public.elephant_слонслонслонсло_14d34928_2250000000003"
|
||||
Column | Type | Definition
|
||||
--------+---------+------------
|
||||
col1 | integer | col1
|
||||
primary key, btree, for table "public.elephant_слонслонслонсло_c8b737c2_2250000000003"
|
||||
|
||||
Table "public.elephant_слонслонслонсло_c8b737c2_2250000000002"
|
||||
Column | Type | Modifiers
|
||||
--------+---------+-----------
|
||||
col1 | integer | not null
|
||||
col2 | integer | not null
|
||||
Indexes:
|
||||
"elephant_слонслонслонсло_14d34928_2250000000002" PRIMARY KEY, btree (col1)
|
||||
|
||||
Table "public.elephant_слонслонслонсло_c8b737c2_2250000000003"
|
||||
Column | Type | Modifiers
|
||||
--------+---------+-----------
|
||||
col1 | integer | not null
|
||||
col2 | integer | not null
|
||||
Indexes:
|
||||
"elephant_слонслонслонсло_14d34928_2250000000003" PRIMARY KEY, btree (col1)
|
||||
|
||||
\c - - - :master_port
|
||||
-- Clean up.
|
||||
DROP TABLE name_lengths CASCADE;
|
||||
DROP TABLE U&"elephant_!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D" UESCAPE '!' CASCADE;
|
|
@ -17,6 +17,7 @@
|
|||
# ---
|
||||
test: multi_extension
|
||||
test: multi_table_ddl
|
||||
test: multi_name_lengths
|
||||
|
||||
# ----------
|
||||
# The following distributed tests depend on creating a partitioned table and
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
--
|
||||
-- MULTI_NAME_LENGTHS
|
||||
--
|
||||
|
||||
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 225000;
|
||||
ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 225000;
|
||||
|
||||
SET citus.multi_shard_commit_protocol = '2pc';
|
||||
|
||||
-- Verify that a table name > 56 characters gets hashed properly.
|
||||
CREATE TABLE too_long_12345678901234567890123456789012345678901234567890 (
|
||||
col1 integer not null,
|
||||
col2 integer not null);
|
||||
SELECT master_create_distributed_table('too_long_12345678901234567890123456789012345678901234567890', 'col1', 'hash');
|
||||
SELECT master_create_worker_shards('too_long_12345678901234567890123456789012345678901234567890', '2', '2');
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d too_long_*
|
||||
\c - - - :master_port
|
||||
|
||||
-- Verify that the UDF works and rejects bad arguments.
|
||||
SELECT shard_name(NULL, 666666);
|
||||
SELECT shard_name(0, 666666);
|
||||
SELECT shard_name('too_long_12345678901234567890123456789012345678901234567890'::regclass, 666666);
|
||||
SELECT shard_name('too_long_12345678901234567890123456789012345678901234567890'::regclass, NULL);
|
||||
SELECT shard_name('too_long_12345678901234567890123456789012345678901234567890'::regclass, -21);
|
||||
|
||||
DROP TABLE too_long_12345678901234567890123456789012345678901234567890 CASCADE;
|
||||
|
||||
|
||||
-- Table to use for rename checks.
|
||||
CREATE TABLE name_lengths (
|
||||
col1 integer not null,
|
||||
col2 integer not null,
|
||||
constraint constraint_a UNIQUE (col1)
|
||||
);
|
||||
|
||||
SELECT master_create_distributed_table('name_lengths', 'col1', 'hash');
|
||||
SELECT master_create_worker_shards('name_lengths', '2', '2');
|
||||
|
||||
-- Verify that we CAN add columns with "too-long names", because
|
||||
-- the columns' names are not extended in the corresponding shard tables.
|
||||
|
||||
ALTER TABLE name_lengths ADD COLUMN float_col_12345678901234567890123456789012345678901234567890 FLOAT;
|
||||
ALTER TABLE name_lengths ADD COLUMN date_col_12345678901234567890123456789012345678901234567890 DATE;
|
||||
ALTER TABLE name_lengths ADD COLUMN int_col_12345678901234567890123456789012345678901234567890 INTEGER DEFAULT 1;
|
||||
|
||||
-- Placeholders for unsupported ALTER TABLE to add constraints with implicit names that are likely too long
|
||||
ALTER TABLE name_lengths ADD UNIQUE (float_col_12345678901234567890123456789012345678901234567890);
|
||||
ALTER TABLE name_lengths ADD EXCLUDE (int_col_12345678901234567890123456789012345678901234567890 WITH =);
|
||||
ALTER TABLE name_lengths ADD CHECK (date_col_12345678901234567890123456789012345678901234567890 > '2014-01-01'::date);
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d name_lengths_*
|
||||
\c - - - :master_port
|
||||
|
||||
-- Placeholders for unsupported add constraints with EXPLICIT names that are too long
|
||||
ALTER TABLE name_lengths ADD CONSTRAINT nl_unique_12345678901234567890123456789012345678901234567890 UNIQUE (float_col_12345678901234567890123456789012345678901234567890);
|
||||
ALTER TABLE name_lengths ADD CONSTRAINT nl_exclude_12345678901234567890123456789012345678901234567890 EXCLUDE (int_col_12345678901234567890123456789012345678901234567890 WITH =);
|
||||
ALTER TABLE name_lengths ADD CONSTRAINT nl_checky_12345678901234567890123456789012345678901234567890 CHECK (date_col_12345678901234567890123456789012345678901234567890 >= '2014-01-01'::date);
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d nl_*
|
||||
\c - - - :master_port
|
||||
|
||||
-- Placeholders for RENAME operations
|
||||
ALTER TABLE name_lengths RENAME TO name_len_12345678901234567890123456789012345678901234567890;
|
||||
ALTER TABLE name_lengths RENAME CONSTRAINT unique_12345678901234567890123456789012345678901234567890 TO unique2_12345678901234567890123456789012345678901234567890;
|
||||
|
||||
-- Verify that CREATE INDEX on already distributed table has proper shard names.
|
||||
|
||||
CREATE INDEX tmp_idx_12345678901234567890123456789012345678901234567890 ON name_lengths(col2);
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d tmp_idx_*
|
||||
\c - - - :master_port
|
||||
|
||||
-- Verify that a new index name > 63 characters is auto-truncated
|
||||
-- by the parser/rewriter before further processing, just as in Postgres.
|
||||
CREATE INDEX tmp_idx_123456789012345678901234567890123456789012345678901234567890 ON name_lengths(col2);
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d tmp_idx_*
|
||||
\c - - - :master_port
|
||||
|
||||
-- Verify that distributed tables with too-long names
|
||||
-- for CHECK constraints are no trouble.
|
||||
CREATE TABLE sneaky_name_lengths (
|
||||
col1 integer not null,
|
||||
col2 integer not null,
|
||||
int_col_12345678901234567890123456789012345678901234567890 integer not null,
|
||||
CHECK (int_col_12345678901234567890123456789012345678901234567890 > 100)
|
||||
);
|
||||
SELECT master_create_distributed_table('sneaky_name_lengths', 'col1', 'hash');
|
||||
SELECT master_create_worker_shards('sneaky_name_lengths', '2', '2');
|
||||
DROP TABLE sneaky_name_lengths CASCADE;
|
||||
|
||||
CREATE TABLE sneaky_name_lengths (
|
||||
int_col_123456789012345678901234567890123456789012345678901234 integer UNIQUE not null,
|
||||
col2 integer not null,
|
||||
CONSTRAINT checky_12345678901234567890123456789012345678901234567890 CHECK (int_col_123456789012345678901234567890123456789012345678901234 > 100)
|
||||
);
|
||||
\d sneaky_name_lengths*
|
||||
|
||||
SELECT master_create_distributed_table('sneaky_name_lengths', 'int_col_123456789012345678901234567890123456789012345678901234', 'hash');
|
||||
SELECT master_create_worker_shards('sneaky_name_lengths', '2', '2');
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d sneaky_name_lengths*
|
||||
\c - - - :master_port
|
||||
|
||||
DROP TABLE sneaky_name_lengths CASCADE;
|
||||
|
||||
-- verify that named constraint with too-long name gets hashed properly
|
||||
CREATE TABLE sneaky_name_lengths (
|
||||
col1 integer not null,
|
||||
col2 integer not null,
|
||||
int_col_12345678901234567890123456789012345678901234567890 integer not null,
|
||||
constraint unique_12345678901234567890123456789012345678901234567890 UNIQUE (col1)
|
||||
);
|
||||
SELECT master_create_distributed_table('sneaky_name_lengths', 'col1', 'hash');
|
||||
SELECT master_create_worker_shards('sneaky_name_lengths', '2', '2');
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d sneaky_name_lengths*
|
||||
\c - - - :master_port
|
||||
|
||||
DROP TABLE sneaky_name_lengths CASCADE;
|
||||
|
||||
-- Verify that much larger shardIds are handled properly
|
||||
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 2250000000000;
|
||||
CREATE TABLE too_long_12345678901234567890123456789012345678901234567890 (
|
||||
col1 integer not null,
|
||||
col2 integer not null);
|
||||
SELECT master_create_distributed_table('too_long_12345678901234567890123456789012345678901234567890', 'col1', 'hash');
|
||||
SELECT master_create_worker_shards('too_long_12345678901234567890123456789012345678901234567890', '2', '2');
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d too_long_*
|
||||
\c - - - :master_port
|
||||
|
||||
DROP TABLE too_long_12345678901234567890123456789012345678901234567890 CASCADE;
|
||||
|
||||
-- Verify that multi-byte boundaries are respected for databases with UTF8 encoding.
|
||||
CREATE TABLE U&"elephant_!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D" UESCAPE '!' (
|
||||
col1 integer not null PRIMARY KEY,
|
||||
col2 integer not null);
|
||||
SELECT master_create_distributed_table(U&'elephant_!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D' UESCAPE '!', 'col1', 'hash');
|
||||
SELECT master_create_worker_shards(U&'elephant_!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D' UESCAPE '!', '2', '2');
|
||||
|
||||
\c - - - :worker_1_port
|
||||
\d elephant_*
|
||||
\c - - - :master_port
|
||||
|
||||
-- Clean up.
|
||||
DROP TABLE name_lengths CASCADE;
|
||||
DROP TABLE U&"elephant_!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D!0441!043B!043E!043D" UESCAPE '!' CASCADE;
|
Loading…
Reference in New Issue