mirror of https://github.com/citusdata/citus.git
Merge pull request #762 from citusdata/fix/fix_510_error_out_if_table_to_distribute_has_data
Error out at master_create_distributed_table if the table has any rowspull/755/head
commit
6d2567f1a2
|
@ -28,6 +28,7 @@
|
||||||
#include "distributed/master_metadata_utility.h"
|
#include "distributed/master_metadata_utility.h"
|
||||||
#include "distributed/metadata_cache.h"
|
#include "distributed/metadata_cache.h"
|
||||||
#include "distributed/pg_dist_partition.h"
|
#include "distributed/pg_dist_partition.h"
|
||||||
|
#include "executor/spi.h"
|
||||||
#include "nodes/execnodes.h"
|
#include "nodes/execnodes.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
#include "nodes/pg_list.h"
|
#include "nodes/pg_list.h"
|
||||||
|
@ -48,6 +49,7 @@ static void RecordDistributedRelationDependencies(Oid distributedRelationId,
|
||||||
Node *distributionKey);
|
Node *distributionKey);
|
||||||
static Oid SupportFunctionForColumn(Var *partitionColumn, Oid accessMethodId,
|
static Oid SupportFunctionForColumn(Var *partitionColumn, Oid accessMethodId,
|
||||||
int16 supportFunctionNumber);
|
int16 supportFunctionNumber);
|
||||||
|
static bool LocalTableEmpty(Oid tableId);
|
||||||
|
|
||||||
|
|
||||||
/* exports for SQL callable functions */
|
/* exports for SQL callable functions */
|
||||||
|
@ -122,6 +124,17 @@ master_create_distributed_table(PG_FUNCTION_ARGS)
|
||||||
"foreign tables.")));
|
"foreign tables.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check that the relation does not contain any rows */
|
||||||
|
if (!LocalTableEmpty(distributedRelationId))
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
||||||
|
errmsg("cannot distribute relation \"%s\"",
|
||||||
|
distributedRelationName),
|
||||||
|
errdetail("Relation \"%s\" contains data.",
|
||||||
|
distributedRelationName),
|
||||||
|
errhint("Empty your table before distributing it.")));
|
||||||
|
}
|
||||||
|
|
||||||
distributionKey = BuildDistributionKeyFromColumnName(distributedRelation,
|
distributionKey = BuildDistributionKeyFromColumnName(distributedRelation,
|
||||||
distributionColumnName);
|
distributionColumnName);
|
||||||
distributionKeyString = nodeToString(distributionKey);
|
distributionKeyString = nodeToString(distributionKey);
|
||||||
|
@ -377,3 +390,59 @@ SupportFunctionForColumn(Var *partitionColumn, Oid accessMethodId,
|
||||||
|
|
||||||
return supportFunctionOid;
|
return supportFunctionOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LocalTableEmpty function checks whether given local table contains any row and
|
||||||
|
* returns false if there is any data. This function is only for local tables and
|
||||||
|
* should not be called for distributed tables.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
LocalTableEmpty(Oid tableId)
|
||||||
|
{
|
||||||
|
Oid schemaId = get_rel_namespace(tableId);
|
||||||
|
char *schemaName = get_namespace_name(schemaId);
|
||||||
|
char *tableName = get_rel_name(tableId);
|
||||||
|
char *tableQualifiedName = quote_qualified_identifier(schemaName, tableName);
|
||||||
|
|
||||||
|
int spiConnectionResult = 0;
|
||||||
|
int spiQueryResult = 0;
|
||||||
|
StringInfo selectExistQueryString = makeStringInfo();
|
||||||
|
|
||||||
|
HeapTuple tuple = NULL;
|
||||||
|
Datum hasDataDatum = 0;
|
||||||
|
bool localTableEmpty = false;
|
||||||
|
bool columnNull = false;
|
||||||
|
bool readOnly = true;
|
||||||
|
|
||||||
|
int rowId = 0;
|
||||||
|
int attributeId = 1;
|
||||||
|
|
||||||
|
AssertArg(!IsDistributedTable(tableId));
|
||||||
|
|
||||||
|
spiConnectionResult = SPI_connect();
|
||||||
|
if (spiConnectionResult != SPI_OK_CONNECT)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errmsg("could not connect to SPI manager")));
|
||||||
|
}
|
||||||
|
|
||||||
|
appendStringInfo(selectExistQueryString, SELECT_EXIST_QUERY, tableQualifiedName);
|
||||||
|
|
||||||
|
spiQueryResult = SPI_execute(selectExistQueryString->data, readOnly, 0);
|
||||||
|
if (spiQueryResult != SPI_OK_SELECT)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errmsg("execution was not successful \"%s\"",
|
||||||
|
selectExistQueryString->data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we expect that SELECT EXISTS query will return single value in a single row */
|
||||||
|
Assert(SPI_processed == 1);
|
||||||
|
|
||||||
|
tuple = SPI_tuptable->vals[rowId];
|
||||||
|
hasDataDatum = SPI_getbinval(tuple, SPI_tuptable->tupdesc, attributeId, &columnNull);
|
||||||
|
localTableEmpty = !DatumGetBool(hasDataDatum);
|
||||||
|
|
||||||
|
SPI_finish();
|
||||||
|
|
||||||
|
return localTableEmpty;
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
/* total number of hash tokens (2^32) */
|
/* total number of hash tokens (2^32) */
|
||||||
#define HASH_TOKEN_COUNT INT64CONST(4294967296)
|
#define HASH_TOKEN_COUNT INT64CONST(4294967296)
|
||||||
|
#define SELECT_EXIST_QUERY "SELECT EXISTS (SELECT 1 FROM %s)"
|
||||||
|
|
||||||
/* In-memory representation of a typed tuple in pg_dist_shard. */
|
/* In-memory representation of a typed tuple in pg_dist_shard. */
|
||||||
typedef struct ShardInterval
|
typedef struct ShardInterval
|
||||||
|
|
|
@ -390,7 +390,7 @@ ORDER BY
|
||||||
customer_keys.o_custkey DESC
|
customer_keys.o_custkey DESC
|
||||||
LIMIT 10 OFFSET 20;
|
LIMIT 10 OFFSET 20;
|
||||||
DEBUG: push down of limit count: 30
|
DEBUG: push down of limit count: 30
|
||||||
DEBUG: building index "pg_toast_17021_index" on table "pg_toast_17021"
|
DEBUG: building index "pg_toast_17022_index" on table "pg_toast_17022"
|
||||||
o_custkey | total_order_count
|
o_custkey | total_order_count
|
||||||
-----------+-------------------
|
-----------+-------------------
|
||||||
1466 | 1
|
1466 | 1
|
||||||
|
|
|
@ -75,6 +75,12 @@ CREATE TABLE nation (
|
||||||
n_name char(25) not null,
|
n_name char(25) not null,
|
||||||
n_regionkey integer not null,
|
n_regionkey integer not null,
|
||||||
n_comment varchar(152));
|
n_comment varchar(152));
|
||||||
|
\COPY nation FROM STDIN WITH CSV
|
||||||
|
SELECT master_create_distributed_table('nation', 'n_nationkey', 'append');
|
||||||
|
ERROR: cannot distribute relation "nation"
|
||||||
|
DETAIL: Relation "nation" contains data.
|
||||||
|
HINT: Empty your table before distributing it.
|
||||||
|
TRUNCATE nation;
|
||||||
SELECT master_create_distributed_table('nation', 'n_nationkey', 'append');
|
SELECT master_create_distributed_table('nation', 'n_nationkey', 'append');
|
||||||
master_create_distributed_table
|
master_create_distributed_table
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
|
@ -61,6 +61,19 @@ CREATE TABLE nation (
|
||||||
n_name char(25) not null,
|
n_name char(25) not null,
|
||||||
n_regionkey integer not null,
|
n_regionkey integer not null,
|
||||||
n_comment varchar(152));
|
n_comment varchar(152));
|
||||||
|
|
||||||
|
\COPY nation FROM STDIN WITH CSV
|
||||||
|
1,'name',1,'comment_1'
|
||||||
|
2,'name',2,'comment_2'
|
||||||
|
3,'name',3,'comment_3'
|
||||||
|
4,'name',4,'comment_4'
|
||||||
|
5,'name',5,'comment_5'
|
||||||
|
\.
|
||||||
|
|
||||||
|
SELECT master_create_distributed_table('nation', 'n_nationkey', 'append');
|
||||||
|
|
||||||
|
TRUNCATE nation;
|
||||||
|
|
||||||
SELECT master_create_distributed_table('nation', 'n_nationkey', 'append');
|
SELECT master_create_distributed_table('nation', 'n_nationkey', 'append');
|
||||||
|
|
||||||
CREATE TABLE part (
|
CREATE TABLE part (
|
||||||
|
|
Loading…
Reference in New Issue