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 void CastSelectTargetList(List *selectTargetList, Oid targetRelationId,
|
||||
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
|
||||
* 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
|
||||
* rewrite/rewriteManip.c.
|
||||
*/
|
||||
bool
|
||||
InsertSelectIntoDistributedTable(Query *query)
|
||||
static bool
|
||||
CheckInsertSelectQuery(Query *query)
|
||||
{
|
||||
CmdType commandType = query->commandType;
|
||||
List *fromList = NULL;
|
||||
RangeTblRef *rangeTableReference = NULL;
|
||||
RangeTblEntry *subqueryRte = NULL;
|
||||
RangeTblEntry *insertRte = NULL;
|
||||
|
||||
if (commandType != CMD_INSERT)
|
||||
{
|
||||
|
@ -117,12 +162,6 @@ InsertSelectIntoDistributedTable(Query *query)
|
|||
/* ensure that there is a query */
|
||||
Assert(IsA(subqueryRte->subquery, Query));
|
||||
|
||||
insertRte = ExtractInsertRangeTableEntry(query);
|
||||
if (!IsDistributedTable(insertRte->relid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2976,6 +2976,11 @@ NeedsDistributedPlanning(Query *queryTree)
|
|||
|
||||
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 "
|
||||
"distributed relations")));
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
|
||||
extern bool InsertSelectIntoDistributedTable(Query *query);
|
||||
extern bool InsertSelectIntoLocalTable(Query *query);
|
||||
extern Query * ReorderInsertSelectTargetLists(Query *originalQuery,
|
||||
RangeTblEntry *insertRte,
|
||||
RangeTblEntry *subqueryRte);
|
||||
|
|
|
@ -336,7 +336,7 @@ step s1-initialize:
|
|||
|
||||
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;;
|
||||
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');
|
||||
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
|
||||
------------------------------------
|
||||
------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue