Skip to content

Commit 7e4709f

Browse files
committed
Optimize inserts, fix update triggers
1 parent f565717 commit 7e4709f

13 files changed

+195
-184
lines changed

init.sql

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -857,15 +857,8 @@ LANGUAGE C STRICT;
857857
* Build check constraint name for a specified relation's column.
858858
*/
859859
CREATE OR REPLACE FUNCTION @extschema@.build_check_constraint_name(
860-
partition_relid REGCLASS,
861-
attribute INT2)
862-
RETURNS TEXT AS 'pg_pathman', 'build_check_constraint_name_attnum'
863-
LANGUAGE C STRICT;
864-
865-
CREATE OR REPLACE FUNCTION @extschema@.build_check_constraint_name(
866-
partition_relid REGCLASS,
867-
attribute TEXT)
868-
RETURNS TEXT AS 'pg_pathman', 'build_check_constraint_name_attname'
860+
partition_relid REGCLASS)
861+
RETURNS TEXT AS 'pg_pathman', 'build_check_constraint_name'
869862
LANGUAGE C STRICT;
870863

871864
/*

range.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ $$ LANGUAGE plpgsql;
6363

6464
CREATE OR REPLACE FUNCTION @extschema@.prepare_for_partitioning(
6565
parent_relid REGCLASS,
66-
expresssion TEXT,
66+
expression TEXT,
6767
partition_data BOOLEAN)
6868
RETURNS VOID AS
6969
$$

src/debug_print.c

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -101,32 +101,3 @@ irange_print(IndexRange irange)
101101

102102
return str.data;
103103
}
104-
105-
/*
106-
* Print Datum as cstring
107-
*/
108-
#ifdef __GNUC__
109-
__attribute__((unused))
110-
#endif
111-
static char *
112-
datum_print(Datum origval, Oid typid)
113-
{
114-
Oid typoutput;
115-
bool typisvarlena;
116-
Datum val;
117-
118-
/* Query output function */
119-
getTypeOutputInfo(typid, &typoutput, &typisvarlena);
120-
121-
if (typisvarlena && VARATT_IS_EXTERNAL_ONDISK(origval))
122-
return NULL; //unchanged-toast-datum
123-
else if (!typisvarlena)
124-
val = origval;
125-
else
126-
{
127-
/* Definitely detoasted Datum */
128-
val = PointerGetDatum(PG_DETOAST_DATUM(origval));
129-
}
130-
131-
return OidOutputFunctionCall(typoutput, val);
132-
}

src/include/partition_filter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ typedef struct
9696
bool warning_triggered; /* warning message counter */
9797

9898
TupleTableSlot *tup_convert_slot; /* slot for rebuilt tuples */
99-
10099
ExprContext *tup_convert_econtext; /* ExprContext for projections */
100+
101+
ExprState *expr_state; /* for partitioning expression */
101102
} PartitionFilterState;
102103

103104

src/include/relation_info.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "postgres.h"
1616
#include "access/attnum.h"
1717
#include "fmgr.h"
18+
#include "nodes/bitmapset.h"
1819
#include "nodes/nodes.h"
1920
#include "nodes/primnodes.h"
2021
#include "port/atomics.h"

src/include/utils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,9 @@ Datum extract_binary_interval_from_text(Datum interval_text,
6565
char ** deconstruct_text_array(Datum array, int *array_size);
6666
RangeVar ** qualified_relnames_to_rangevars(char **relnames, size_t nrelnames);
6767

68+
AttrNumber *get_pathman_attributes_map(const PartRelationInfo *prel,
69+
Relation child);
70+
71+
List *get_part_expression_columns(const PartRelationInfo *prel);
6872

6973
#endif /* PATHMAN_UTILS_H */

src/partition_creation.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ static void create_single_partition_common(Oid parent_relid,
6666
Oid partition_relid,
6767
Constraint *check_constraint,
6868
init_callback_params *callback_params,
69-
const char *partitioned_column);
69+
List *trigger_columns);
7070

7171
static Oid create_single_partition_internal(Oid parent_relid,
7272
RangeVar *partition_rv,
@@ -167,6 +167,7 @@ create_single_hash_partition_internal(Oid parent_relid,
167167
Constraint *check_constr;
168168
Node *expr;
169169
init_callback_params callback_params;
170+
List *trigger_columns;
170171

171172
/* Generate a name if asked to */
172173
if (!partition_rv)
@@ -1697,6 +1698,10 @@ validate_part_expression(Node *node, void *context)
16971698
" with partitioning relation");
16981699
return false;
16991700
}
1701+
1702+
if (IsA(node, Param))
1703+
elog(ERROR, "Partitioning expression should not contain parameters");
1704+
17001705
return expression_tree_walker(node, validate_part_expression, context);
17011706
}
17021707

@@ -1835,8 +1840,12 @@ get_part_expression_info(Oid relid, const char *expr_string,
18351840
target_entry = linitial(plan->planTree->targetlist);
18361841

18371842
expr_node = (Node *) target_entry->expr;
1843+
18381844
expr_node = eval_const_expressions(NULL, expr_node);
18391845
validate_part_expression(expr_node, NULL);
1846+
if (contain_mutable_functions(expr_node))
1847+
elog(ERROR, "Expression should not contain mutable functions");
1848+
18401849
out_string = nodeToString(expr_node);
18411850

18421851
MemoryContextSwitchTo(oldcontext);
@@ -1852,32 +1861,27 @@ get_part_expression_info(Oid relid, const char *expr_string,
18521861
return expr_info;
18531862
}
18541863

1855-
struct extract_columns_names_context
1864+
struct extract_column_names_context
18561865
{
18571866
List *columns;
18581867
};
18591868

18601869
/* Extract column names from raw expression */
18611870
static bool
1862-
extract_column_names(Node *node, struct extract_raw_columns_context *ctx)
1871+
extract_column_names(Node *node, struct extract_column_names_context *ctx)
18631872
{
18641873
if (node == NULL)
1865-
return false
1874+
return false;
18661875

18671876
if (IsA(node, ColumnRef))
18681877
{
18691878
ListCell *lc;
1870-
ColumnRef *col = (ColumnRef *) node;
1871-
foreach(lc, col->fields)
1872-
{
1873-
if (IsA(lfirst(lc)), Value)
1874-
{
1875-
ctx->columns = lappend(strVal(lfirst(lc)));
1876-
}
1877-
}
1879+
foreach(lc, ((ColumnRef *) node)->fields)
1880+
if (IsA(lfirst(lc), String))
1881+
ctx->columns = lappend(ctx->columns, strVal(lfirst(lc)));
18781882
}
18791883

1880-
return raw_expression_tree_walker(node, extract_raw_columns, ctx);
1884+
return raw_expression_tree_walker(node, extract_column_names, ctx);
18811885
}
18821886

18831887
/*
@@ -1899,7 +1903,10 @@ get_constraint_expression(Oid parent_relid, Oid *expr_type, List **columns)
18991903
elog(ERROR, "table \"%s\" is not partitioned",
19001904
get_rel_name_or_relid(parent_relid));
19011905

1902-
/* Fetch expression for constraint */
1906+
/*
1907+
* We need expression type for hash functions. Range functions don't need
1908+
* this feature.
1909+
*/
19031910
if (expr_type)
19041911
*expr_type = DatumGetObjectId(config_values[Anum_pathman_config_atttype - 1]);
19051912

src/partition_filter.c

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,8 @@ partition_filter_create_scan_state(CustomScan *node)
523523
Assert(state->on_conflict_action >= ONCONFLICT_NONE ||
524524
state->on_conflict_action <= ONCONFLICT_UPDATE);
525525

526+
state->expr_state = NULL;
527+
526528
/* There should be exactly one subplan */
527529
Assert(list_length(node->custom_plans) == 1);
528530

@@ -532,11 +534,42 @@ partition_filter_create_scan_state(CustomScan *node)
532534
void
533535
partition_filter_begin(CustomScanState *node, EState *estate, int eflags)
534536
{
535-
PartitionFilterState *state = (PartitionFilterState *) node;
537+
Index varno = 1;
538+
Node *expr;
539+
MemoryContext old_cxt;
540+
PartitionFilterState *state = (PartitionFilterState *) node;
541+
const PartRelationInfo *prel;
542+
ListCell *lc;
536543

537544
/* It's convenient to store PlanState in 'custom_ps' */
538545
node->custom_ps = list_make1(ExecInitNode(state->subplan, estate, eflags));
539546

547+
if (state->expr_state == NULL)
548+
{
549+
/* Fetch PartRelationInfo for this partitioned relation */
550+
prel = get_pathman_relation_info(state->partitioned_table);
551+
Assert(prel != NULL);
552+
553+
/* Change varno in Vars according to range table */
554+
expr = copyObject(prel->expr);
555+
foreach(lc, estate->es_range_table)
556+
{
557+
RangeTblEntry *entry = lfirst(lc);
558+
if (entry->relid == state->partitioned_table)
559+
{
560+
if (varno > 1)
561+
ChangeVarNodes(expr, 1, varno, 0);
562+
break;
563+
}
564+
varno += 1;
565+
}
566+
567+
/* Prepare state for expression execution */
568+
old_cxt = MemoryContextSwitchTo(estate->es_query_cxt);
569+
state->expr_state = ExecInitExpr((Expr *) expr, NULL);
570+
MemoryContextSwitchTo(old_cxt);
571+
}
572+
540573
/* Init ResultRelInfo cache */
541574
init_result_parts_storage(&state->result_parts, estate,
542575
state->on_conflict_action != ONCONFLICT_NONE,
@@ -571,11 +604,7 @@ partition_filter_exec(CustomScanState *node)
571604
bool isnull;
572605
Datum value;
573606
ExprDoneCond itemIsDone;
574-
ExprState *expr_state;
575-
ListCell *lc;
576-
Index varno = 1;
577607
TupleTableSlot *tmp_slot;
578-
Node *expr;
579608

580609
/* Fetch PartRelationInfo for this partitioned relation */
581610
prel = get_pathman_relation_info(state->partitioned_table);
@@ -589,33 +618,13 @@ partition_filter_exec(CustomScanState *node)
589618
return slot;
590619
}
591620

592-
/* Find proper varno for Vars in expression */
593-
foreach(lc, estate->es_range_table)
594-
{
595-
RangeTblEntry *entry = (RangeTblEntry *) lfirst(lc);
596-
if (entry->relid == prel->key)
597-
break;
598-
599-
varno++;
600-
}
601-
602-
/* Change varno according to range table */
603-
expr = copyObject(prel->expr);
604-
if (varno != 1)
605-
ChangeVarNodes(expr, 1, varno, 0);
606-
607-
/* Prepare state for expression execution */
608-
old_cxt = MemoryContextSwitchTo(estate->es_query_cxt);
609-
expr_state = ExecInitExpr((Expr *) expr, NULL);
610-
MemoryContextSwitchTo(old_cxt);
611-
612621
/* Switch to per-tuple context */
613622
old_cxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
614623

615624
/* Execute expression */
616625
tmp_slot = econtext->ecxt_scantuple;
617626
econtext->ecxt_scantuple = slot;
618-
value = ExecEvalExpr(expr_state, econtext, &isnull, &itemIsDone);
627+
value = ExecEvalExpr(state->expr_state, econtext, &isnull, &itemIsDone);
619628
econtext->ecxt_scantuple = tmp_slot;
620629

621630
if (isnull)

0 commit comments

Comments
 (0)