mirror of https://github.com/citusdata/citus.git
Allow noop updates of the partition column
parent
be113e99cc
commit
6f6cb1a0d6
|
@ -42,6 +42,7 @@
|
||||||
#include "nodes/pg_list.h"
|
#include "nodes/pg_list.h"
|
||||||
#include "nodes/primnodes.h"
|
#include "nodes/primnodes.h"
|
||||||
#include "optimizer/clauses.h"
|
#include "optimizer/clauses.h"
|
||||||
|
#include "optimizer/predtest.h"
|
||||||
#include "optimizer/restrictinfo.h"
|
#include "optimizer/restrictinfo.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "storage/lock.h"
|
#include "storage/lock.h"
|
||||||
|
@ -67,6 +68,8 @@ static bool MasterIrreducibleExpression(Node *expression, bool *varArgument,
|
||||||
bool *badCoalesce);
|
bool *badCoalesce);
|
||||||
static bool MasterIrreducibleExpressionWalker(Node *expression, WalkerState *state);
|
static bool MasterIrreducibleExpressionWalker(Node *expression, WalkerState *state);
|
||||||
static char MostPermissiveVolatileFlag(char left, char right);
|
static char MostPermissiveVolatileFlag(char left, char right);
|
||||||
|
static bool TargetEntryChangesValue(TargetEntry *targetEntry, Var *column,
|
||||||
|
FromExpr *joinTree);
|
||||||
static Task * RouterModifyTask(Query *originalQuery, Query *query);
|
static Task * RouterModifyTask(Query *originalQuery, Query *query);
|
||||||
static ShardInterval * TargetShardIntervalForModify(Query *query);
|
static ShardInterval * TargetShardIntervalForModify(Query *query);
|
||||||
static List * QueryRestrictList(Query *query);
|
static List * QueryRestrictList(Query *query);
|
||||||
|
@ -286,7 +289,7 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
{
|
{
|
||||||
bool hasVarArgument = false; /* A STABLE function is passed a Var argument */
|
bool hasVarArgument = false; /* A STABLE function is passed a Var argument */
|
||||||
bool hasBadCoalesce = false; /* CASE/COALESCE passed a mutable function */
|
bool hasBadCoalesce = false; /* CASE/COALESCE passed a mutable function */
|
||||||
FromExpr *joinTree = NULL;
|
FromExpr *joinTree = queryTree->jointree;
|
||||||
ListCell *targetEntryCell = NULL;
|
ListCell *targetEntryCell = NULL;
|
||||||
|
|
||||||
foreach(targetEntryCell, queryTree->targetList)
|
foreach(targetEntryCell, queryTree->targetList)
|
||||||
|
@ -308,12 +311,14 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandType == CMD_UPDATE &&
|
if (commandType == CMD_UPDATE &&
|
||||||
targetEntry->resno == partitionColumn->varattno)
|
TargetEntryChangesValue(targetEntry, partitionColumn,
|
||||||
|
queryTree->jointree))
|
||||||
{
|
{
|
||||||
specifiesPartitionValue = true;
|
specifiesPartitionValue = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetEntry->resno == partitionColumn->varattno &&
|
if (commandType == CMD_INSERT &&
|
||||||
|
targetEntry->resno == partitionColumn->varattno &&
|
||||||
!IsA(targetEntry->expr, Const))
|
!IsA(targetEntry->expr, Const))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
@ -329,7 +334,6 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
joinTree = queryTree->jointree;
|
|
||||||
if (joinTree != NULL)
|
if (joinTree != NULL)
|
||||||
{
|
{
|
||||||
if (contain_volatile_functions(joinTree->quals))
|
if (contain_volatile_functions(joinTree->quals))
|
||||||
|
@ -680,6 +684,55 @@ MostPermissiveVolatileFlag(char left, char right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TargetEntryChangesValue determines whether the given target entry may
|
||||||
|
* change the value in a given column, given a join tree. The result is
|
||||||
|
* true unless the expression refers directly to the column, or the
|
||||||
|
* expression is a value that is implied by the qualifiers of the join
|
||||||
|
* tree, or the target entry sets a different column.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
TargetEntryChangesValue(TargetEntry *targetEntry, Var *column, FromExpr *joinTree)
|
||||||
|
{
|
||||||
|
bool isColumnValueChanged = true;
|
||||||
|
Expr *setExpr = targetEntry->expr;
|
||||||
|
|
||||||
|
if (targetEntry->resno != column->varattno)
|
||||||
|
{
|
||||||
|
/* target entry of the form SET some_other_col = <x> */
|
||||||
|
isColumnValueChanged = false;
|
||||||
|
}
|
||||||
|
else if (IsA(setExpr, Var))
|
||||||
|
{
|
||||||
|
Var *newValue = (Var *) setExpr;
|
||||||
|
if (newValue->varattno == column->varattno)
|
||||||
|
{
|
||||||
|
/* target entry of the form SET col = table.col */
|
||||||
|
isColumnValueChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsA(setExpr, Const))
|
||||||
|
{
|
||||||
|
Const *newValue = (Const *) setExpr;
|
||||||
|
List *restrictClauseList = WhereClauseList(joinTree);
|
||||||
|
OpExpr *equalityExpr = MakeOpExpression(column, BTEqualStrategyNumber);
|
||||||
|
Const *rightConst = (Const *) get_rightop((Expr *) equalityExpr);
|
||||||
|
|
||||||
|
rightConst->constvalue = newValue->constvalue;
|
||||||
|
rightConst->constisnull = newValue->constisnull;
|
||||||
|
rightConst->constbyval = newValue->constbyval;
|
||||||
|
|
||||||
|
if (predicate_implied_by(list_make1(equalityExpr), restrictClauseList))
|
||||||
|
{
|
||||||
|
/* target entry of the form SET col = <x> WHERE col = <x> AND ... */
|
||||||
|
isColumnValueChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isColumnValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RouterModifyTask builds a Task to represent a modification performed by
|
* RouterModifyTask builds a Task to represent a modification performed by
|
||||||
* the provided query against the provided shard interval. This task contains
|
* the provided query against the provided shard interval. This task contains
|
||||||
|
|
|
@ -396,6 +396,12 @@ ERROR: distributed modifications must target exactly one shard
|
||||||
-- attempting to change the partition key is unsupported
|
-- attempting to change the partition key is unsupported
|
||||||
UPDATE limit_orders SET id = 0 WHERE id = 246;
|
UPDATE limit_orders SET id = 0 WHERE id = 246;
|
||||||
ERROR: modifying the partition value of rows is not allowed
|
ERROR: modifying the partition value of rows is not allowed
|
||||||
|
UPDATE limit_orders SET id = 0 WHERE id = 0 OR id = 246;
|
||||||
|
ERROR: modifying the partition value of rows is not allowed
|
||||||
|
-- setting the partition column value to itself is allowed
|
||||||
|
UPDATE limit_orders SET id = 246 WHERE id = 246;
|
||||||
|
UPDATE limit_orders SET id = 246 WHERE id = 246 AND symbol = 'GM';
|
||||||
|
UPDATE limit_orders SET id = limit_orders.id WHERE id = 246;
|
||||||
-- UPDATEs with a FROM clause are unsupported
|
-- UPDATEs with a FROM clause are unsupported
|
||||||
UPDATE limit_orders SET limit_price = 0.00 FROM bidders
|
UPDATE limit_orders SET limit_price = 0.00 FROM bidders
|
||||||
WHERE limit_orders.id = 246 AND
|
WHERE limit_orders.id = 246 AND
|
||||||
|
|
|
@ -284,6 +284,12 @@ UPDATE limit_orders SET limit_price = 0.00;
|
||||||
|
|
||||||
-- attempting to change the partition key is unsupported
|
-- attempting to change the partition key is unsupported
|
||||||
UPDATE limit_orders SET id = 0 WHERE id = 246;
|
UPDATE limit_orders SET id = 0 WHERE id = 246;
|
||||||
|
UPDATE limit_orders SET id = 0 WHERE id = 0 OR id = 246;
|
||||||
|
|
||||||
|
-- setting the partition column value to itself is allowed
|
||||||
|
UPDATE limit_orders SET id = 246 WHERE id = 246;
|
||||||
|
UPDATE limit_orders SET id = 246 WHERE id = 246 AND symbol = 'GM';
|
||||||
|
UPDATE limit_orders SET id = limit_orders.id WHERE id = 246;
|
||||||
|
|
||||||
-- UPDATEs with a FROM clause are unsupported
|
-- UPDATEs with a FROM clause are unsupported
|
||||||
UPDATE limit_orders SET limit_price = 0.00 FROM bidders
|
UPDATE limit_orders SET limit_price = 0.00 FROM bidders
|
||||||
|
|
Loading…
Reference in New Issue