default_partition_v2.patch
application/x-download
Filename: default_partition_v2.patch
Type: application/x-download
Part: 0
Patch
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| src/backend/catalog/partition.c | 52 | 0 |
| src/backend/parser/gram.y | 1 | 1 |
| src/backend/parser/parse_utilcmd.c | 39 | 36 |
| src/backend/utils/adt/ruleutils.c | 6 | 1 |
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index e01ef86..2e675ba 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -90,6 +90,10 @@ typedef struct PartitionBoundInfoData
* for range partitioned tables */
int null_index; /* Index of the null-accepting partition; -1
* for range partitioned tables */
+ bool has_def; /* Is there a default partition? Currently false
+ * for a range partitioned table */
+ bool def_index; /* Index of the default list partition. -1 for
+ * range partitioned tables */
} PartitionBoundInfoData;
/*
@@ -166,6 +170,8 @@ RelationBuildPartitionDesc(Relation rel)
/* List partitioning specific */
PartitionListValue **all_values = NULL;
bool found_null = false;
+ bool found_def = false;
+ int def_index = -1;
int null_index = -1;
/* Range partitioning specific */
@@ -239,6 +245,8 @@ RelationBuildPartitionDesc(Relation rel)
i = 0;
found_null = false;
null_index = -1;
+ found_def = false;
+ def_index = -1;
foreach(cell, boundspecs)
{
ListCell *c;
@@ -249,6 +257,15 @@ RelationBuildPartitionDesc(Relation rel)
foreach(c, spec->listdatums)
{
+ Node *value = lfirst(c);
+
+ if (IsA(value, DefElem))
+ {
+ found_def = true;
+ def_index = i;
+ continue;
+ }
+
Const *val = lfirst(c);
PartitionListValue *list_value = NULL;
@@ -459,6 +476,7 @@ RelationBuildPartitionDesc(Relation rel)
case PARTITION_STRATEGY_LIST:
{
boundinfo->has_null = found_null;
+ boundinfo->has_def = found_def;
boundinfo->indexes = (int *) palloc(ndatums * sizeof(int));
/*
@@ -496,6 +514,11 @@ RelationBuildPartitionDesc(Relation rel)
if (mapping[null_index] == -1)
mapping[null_index] = next_index++;
}
+ if (found_def)
+ {
+ if (mapping[def_index] == -1)
+ mapping[def_index] = next_index++;
+ }
/* All partition must now have a valid mapping */
Assert(next_index == nparts);
@@ -504,6 +527,11 @@ RelationBuildPartitionDesc(Relation rel)
boundinfo->null_index = mapping[null_index];
else
boundinfo->null_index = -1;
+
+ if (found_def)
+ boundinfo->def_index = mapping[def_index];
+ else
+ boundinfo->def_index = -1;
break;
}
@@ -1558,6 +1586,19 @@ generate_partition_qual(Relation rel)
bound = stringToNode(TextDatumGetCString(boundDatum));
ReleaseSysCache(tuple);
+ /* Return if it is a default list partition */
+ PartitionBoundSpec *spec = (PartitionBoundSpec *)bound;
+ ListCell *cell;
+ foreach(cell, spec->listdatums)
+ {
+ Node *value = lfirst(cell);
+ if (IsA(value, DefElem))
+ {
+ /* Keep the parent locked until commit */
+ heap_close(parent, NoLock);
+ return result;
+ }
+ }
my_qual = get_qual_from_partbound(rel, parent, bound);
/* Add the parent's quals to the list (if any) */
@@ -1771,6 +1812,17 @@ get_partition_for_tuple(PartitionDispatch *pd,
result = -1;
*failed_at = parent;
*failed_slot = slot;
+ /*
+ * If partitioned table has a default partition, return
+ * its sequence number
+ */
+ if (partdesc->boundinfo->has_def)
+ result = parent->indexes[partdesc->boundinfo->def_index];
+ else
+ {
+ result = -1;
+ *failed_at = RelationGetRelid(parent->reldesc);
+ }
break;
}
else if (parent->indexes[cur_index] >= 0)
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 6316688..ebb7db7 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -2594,6 +2594,7 @@ partbound_datum:
Sconst { $$ = makeStringConst($1, @1); }
| NumericOnly { $$ = makeAConst($1, @1); }
| NULL_P { $$ = makeNullAConst(@1); }
+ | DEFAULT { $$ = (Node *)makeDefElem("DEFAULT", NULL, @1); }
;
partbound_datum_list:
@@ -2601,7 +2602,6 @@ partbound_datum_list:
| partbound_datum_list ',' partbound_datum
{ $$ = lappend($1, $3); }
;
-
range_datum_list:
PartitionRangeDatum { $$ = list_make1($1); }
| range_datum_list ',' PartitionRangeDatum
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 673276a..ba05ac8 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -3088,47 +3088,50 @@ transformPartitionBound(ParseState *pstate, Relation parent, Node *bound)
result_spec->listdatums = NIL;
foreach(cell, spec->listdatums)
{
- A_Const *con = (A_Const *) lfirst(cell);
- Node *value;
- ListCell *cell2;
- bool duplicate;
-
- value = (Node *) make_const(pstate, &con->val, con->location);
- value = coerce_to_target_type(pstate,
- value, exprType(value),
- get_partition_col_typid(key, 0),
- get_partition_col_typmod(key, 0),
- COERCION_ASSIGNMENT,
- COERCE_IMPLICIT_CAST,
- -1);
-
- if (value == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("specified value cannot be cast to type \"%s\" of column \"%s\"",
- format_type_be(get_partition_col_typid(key, 0)),
- colname),
- parser_errposition(pstate,
- exprLocation((Node *) con))));
-
- /* Simplify the expression */
- value = (Node *) expression_planner((Expr *) value);
-
- /* Don't add to the result if the value is a duplicate */
- duplicate = false;
- foreach(cell2, result_spec->listdatums)
+ Node *value = lfirst(cell);
+ /* Perform the transformation only for non default partition */
+ if (!IsA(value, DefElem))
{
- Const *value2 = (Const *) lfirst(cell2);
+ A_Const *con = (A_Const *) lfirst(cell);
+ ListCell *cell2;
+ bool duplicate;
+
+ value = (Node *) make_const(pstate, &con->val, con->location);
+ value = coerce_to_target_type(pstate,
+ value, exprType(value),
+ get_partition_col_typid(key, 0),
+ get_partition_col_typmod(key, 0),
+ COERCION_ASSIGNMENT,
+ COERCE_IMPLICIT_CAST,
+ -1);
+
+ if (value == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("specified value cannot be cast to type \"%s\" of column \"%s\"",
+ format_type_be(get_partition_col_typid(key, 0)),
+ colname),
+ parser_errposition(pstate,
+ exprLocation((Node *) con))));
- if (equal(value, value2))
+ /* Simplify the expression */
+ value = (Node *) expression_planner((Expr *) value);
+
+ /* Don't add to the result if the value is a duplicate */
+ duplicate = false;
+ foreach(cell2, result_spec->listdatums)
{
- duplicate = true;
- break;
+ Const *value2 = (Const *) lfirst(cell2);
+
+ if (equal(value, value2))
+ {
+ duplicate = true;
+ break;
+ }
}
+ if (duplicate)
+ continue;
}
- if (duplicate)
- continue;
-
result_spec->listdatums = lappend(result_spec->listdatums,
value);
}
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 5c82325..ffdf633 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -8487,8 +8487,13 @@ get_rule_expr(Node *node, deparse_context *context,
sep = "";
foreach(cell, spec->listdatums)
{
+ Node *value = lfirst(cell);
Const *val = lfirst(cell);
-
+ if (IsA(value, DefElem))
+ {
+ appendStringInfoString(buf, "DEFAULT");
+ continue;
+ }
appendStringInfoString(buf, sep);
get_const_expr(val, context, -1);
sep = ", ";