Merge pull request #1580 from citusdata/change_error_message_of_local_dist

Add error detail if query contains both local and distributed tables
pull/1591/head
Burak Velioglu 2017-09-25 10:05:37 -07:00 committed by GitHub
commit 24dc95ee98
6 changed files with 77 additions and 10 deletions

View File

@ -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;
} }

View File

@ -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")));
} }

View File

@ -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);

View File

@ -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

View File

@ -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
------------------------------------ ------------------------------------
------------------------------------ ------------------------------------

View File

@ -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