mirror of https://github.com/citusdata/citus.git
Change error message of queries with distributed and local table
Citus can handle INSERT INTO ... SELECT queries if the query inserts into local table by reading data from distributed table. The opposite way is not correct. With this commit we warn the user if the latter option is used.pull/1580/head
parent
fb70400b61
commit
0a56ed910b
|
@ -64,6 +64,7 @@ static DeferredErrorMessage * CoordinatorInsertSelectSupported(Query *insertSele
|
||||||
static Query * WrapSubquery(Query *subquery);
|
static Query * WrapSubquery(Query *subquery);
|
||||||
static void CastSelectTargetList(List *selectTargetList, Oid targetRelationId,
|
static void CastSelectTargetList(List *selectTargetList, Oid targetRelationId,
|
||||||
List *insertTargetList);
|
List *insertTargetList);
|
||||||
|
static bool CheckInsertSelectQuery(Query *query);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -73,18 +74,62 @@ static void CastSelectTargetList(List *selectTargetList, Oid targetRelationId,
|
||||||
*
|
*
|
||||||
* Note that the input query should be the original parsetree of
|
* Note that the input query should be the original parsetree of
|
||||||
* the query (i.e., not passed trough the standard planner).
|
* the query (i.e., not passed trough the standard planner).
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
InsertSelectIntoDistributedTable(Query *query)
|
||||||
|
{
|
||||||
|
bool insertSelectQuery = CheckInsertSelectQuery(query);
|
||||||
|
|
||||||
|
if (insertSelectQuery)
|
||||||
|
{
|
||||||
|
RangeTblEntry *insertRte = ExtractInsertRangeTableEntry(query);
|
||||||
|
if (IsDistributedTable(insertRte->relid))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* InsertSelectIntoLocalTable checks whether INSERT INTO ... SELECT inserts
|
||||||
|
* into local table. Note that query must be a sample of INSERT INTO ... SELECT
|
||||||
|
* type of query.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
InsertSelectIntoLocalTable(Query *query)
|
||||||
|
{
|
||||||
|
bool insertSelectQuery = CheckInsertSelectQuery(query);
|
||||||
|
|
||||||
|
if (insertSelectQuery)
|
||||||
|
{
|
||||||
|
RangeTblEntry *insertRte = ExtractInsertRangeTableEntry(query);
|
||||||
|
if (!IsDistributedTable(insertRte->relid))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CheckInsertSelectQuery returns true when the input query is an INSERT INTO
|
||||||
|
* ... SELECT kind of query.
|
||||||
*
|
*
|
||||||
* This function is inspired from getInsertSelectQuery() on
|
* This function is inspired from getInsertSelectQuery() on
|
||||||
* rewrite/rewriteManip.c.
|
* rewrite/rewriteManip.c.
|
||||||
*/
|
*/
|
||||||
bool
|
static bool
|
||||||
InsertSelectIntoDistributedTable(Query *query)
|
CheckInsertSelectQuery(Query *query)
|
||||||
{
|
{
|
||||||
CmdType commandType = query->commandType;
|
CmdType commandType = query->commandType;
|
||||||
List *fromList = NULL;
|
List *fromList = NULL;
|
||||||
RangeTblRef *rangeTableReference = NULL;
|
RangeTblRef *rangeTableReference = NULL;
|
||||||
RangeTblEntry *subqueryRte = NULL;
|
RangeTblEntry *subqueryRte = NULL;
|
||||||
RangeTblEntry *insertRte = NULL;
|
|
||||||
|
|
||||||
if (commandType != CMD_INSERT)
|
if (commandType != CMD_INSERT)
|
||||||
{
|
{
|
||||||
|
@ -117,12 +162,6 @@ InsertSelectIntoDistributedTable(Query *query)
|
||||||
/* ensure that there is a query */
|
/* ensure that there is a query */
|
||||||
Assert(IsA(subqueryRte->subquery, Query));
|
Assert(IsA(subqueryRte->subquery, Query));
|
||||||
|
|
||||||
insertRte = ExtractInsertRangeTableEntry(query);
|
|
||||||
if (!IsDistributedTable(insertRte->relid))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2976,6 +2976,11 @@ NeedsDistributedPlanning(Query *queryTree)
|
||||||
|
|
||||||
if (hasLocalRelation && hasDistributedRelation)
|
if (hasLocalRelation && hasDistributedRelation)
|
||||||
{
|
{
|
||||||
|
if (InsertSelectIntoLocalTable(queryTree))
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errmsg("cannot INSERT rows from a distributed query into a "
|
||||||
|
"local table")));
|
||||||
|
}
|
||||||
ereport(ERROR, (errmsg("cannot plan queries which include both local and "
|
ereport(ERROR, (errmsg("cannot plan queries which include both local and "
|
||||||
"distributed relations")));
|
"distributed relations")));
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
|
|
||||||
extern bool InsertSelectIntoDistributedTable(Query *query);
|
extern bool InsertSelectIntoDistributedTable(Query *query);
|
||||||
|
extern bool InsertSelectIntoLocalTable(Query *query);
|
||||||
extern Query * ReorderInsertSelectTargetLists(Query *originalQuery,
|
extern Query * ReorderInsertSelectTargetLists(Query *originalQuery,
|
||||||
RangeTblEntry *insertRte,
|
RangeTblEntry *insertRte,
|
||||||
RangeTblEntry *subqueryRte);
|
RangeTblEntry *subqueryRte);
|
||||||
|
|
|
@ -336,7 +336,7 @@ step s1-initialize:
|
||||||
|
|
||||||
step s1-begin: BEGIN;
|
step s1-begin: BEGIN;
|
||||||
step s1-insert-select: INSERT INTO insert_of_insert_select_hash SELECT * FROM select_of_insert_select_hash ORDER BY 1, 2 LIMIT 5;;
|
step s1-insert-select: INSERT INTO insert_of_insert_select_hash SELECT * FROM select_of_insert_select_hash ORDER BY 1, 2 LIMIT 5;;
|
||||||
ERROR: cannot plan queries which include both local and distributed relations
|
ERROR: cannot INSERT rows from a distributed query into a local table
|
||||||
step s2-distribute-table-on-inserted: SELECT create_distributed_table('insert_of_insert_select_hash', 'id');
|
step s2-distribute-table-on-inserted: SELECT create_distributed_table('insert_of_insert_select_hash', 'id');
|
||||||
create_distributed_table
|
create_distributed_table
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
------------------------------------
|
------------------------------------
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
-- Insert into local table
|
||||||
|
------------------------------------
|
||||||
|
------------------------------------
|
||||||
|
CREATE TABLE test_table_1(id int);
|
||||||
|
INSERT INTO test_table_1
|
||||||
|
SELECT user_id FROM users_table;
|
||||||
|
ERROR: cannot INSERT rows from a distributed query into a local table
|
||||||
|
DROP TABLE test_table_1;
|
||||||
|
------------------------------------
|
||||||
|
------------------------------------
|
||||||
-- Vanilla funnel query
|
-- Vanilla funnel query
|
||||||
------------------------------------
|
------------------------------------
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
|
------------------------------------
|
||||||
|
------------------------------------
|
||||||
|
-- Insert into local table
|
||||||
|
------------------------------------
|
||||||
|
------------------------------------
|
||||||
|
CREATE TABLE test_table_1(id int);
|
||||||
|
|
||||||
|
INSERT INTO test_table_1
|
||||||
|
SELECT user_id FROM users_table;
|
||||||
|
|
||||||
|
DROP TABLE test_table_1;
|
||||||
|
|
||||||
------------------------------------
|
------------------------------------
|
||||||
------------------------------------
|
------------------------------------
|
||||||
-- Vanilla funnel query
|
-- Vanilla funnel query
|
||||||
|
|
Loading…
Reference in New Issue