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

View File

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

View File

@ -24,6 +24,7 @@
extern bool InsertSelectIntoDistributedTable(Query *query);
extern bool InsertSelectIntoLocalTable(Query *query);
extern Query * ReorderInsertSelectTargetLists(Query *originalQuery,
RangeTblEntry *insertRte,
RangeTblEntry *subqueryRte);

View File

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

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

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