Skip to content

Commit 480ff13

Browse files
committed
Add insert support using expressions
1 parent a36a14c commit 480ff13

File tree

6 files changed

+114
-8
lines changed

6 files changed

+114
-8
lines changed

src/include/init.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ extern PathmanInitState pg_pathman_init_state;
5050
*/
5151
#define IsPathmanEnabled() ( pg_pathman_init_state.pg_pathman_enable )
5252

53+
/*
54+
* Enable or disable pg_pathman
55+
*/
56+
#define EnablePathman(b) ( pg_pathman_init_state.pg_pathman_enable = (b) )
57+
5358
/*
5459
* Check if pg_pathman is initialized & enabled.
5560
*/

src/include/partition_creation.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ Node * build_raw_hash_check_tree(const char *base_expr,
8080
void drop_check_constraint(Oid relid, AttrNumber attnum);
8181

8282
/* expression parsing functions */
83-
Node *get_expression_node(Oid relid, const char *expr, bool analyze);
83+
Node *get_expression_node(Oid relid, const char *expr, bool analyze,
84+
RTEMapItem **rte_map);
8485
Oid get_partition_expr_type(Oid relid, const char *expr);
8586

8687

@@ -152,5 +153,4 @@ typedef struct
152153
void invoke_part_callback(init_callback_params *cb_params);
153154
bool validate_part_callback(Oid procid, bool emit_error);
154155

155-
156156
#endif /* PARTITION_CREATION_H */

src/include/relation_info.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ typedef struct
113113
max;
114114
} RangeEntry;
115115

116+
/* Used to convert 'varno' attributes accodirdingly to working query */
117+
typedef struct
118+
{
119+
Oid relid; /* relid by which we can determine what rte we need in current query */
120+
int res_idx; /* varno will be used for Var */
121+
} RTEMapItem;
122+
116123
/*
117124
* PartRelationInfo
118125
* Per-relation partitioning information
@@ -127,8 +134,9 @@ typedef struct
127134
Oid *children; /* Oids of child partitions */
128135
RangeEntry *ranges; /* per-partition range entry or NULL */
129136

137+
Expr *expr; /* planned expression */
138+
RTEMapItem *expr_map; /* 'varno' map */
130139
PartType parttype; /* partitioning type (HASH | RANGE) */
131-
Expr *expr;
132140
Oid atttype; /* expression type */
133141
int32 atttypmod; /* expression type modifier */
134142
bool attbyval; /* is partitioned column stored by value? */
@@ -164,7 +172,6 @@ typedef enum
164172
PPS_NOT_SURE /* can't determine (not transactional state) */
165173
} PartParentSearch;
166174

167-
168175
/*
169176
* PartRelationInfo field access macros.
170177
*/

src/partition_creation.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,7 +1296,7 @@ build_raw_hash_check_tree(const char *base_expr,
12961296

12971297
Oid hash_proc;
12981298
TypeCacheEntry *tce;
1299-
Node *expr = get_expression_node(relid, base_expr, false);
1299+
Node *expr = get_expression_node(relid, base_expr, false, NULL);
13001300

13011301
tce = lookup_type_cache(value_type, TYPECACHE_HASH_PROC);
13021302
hash_proc = tce->hash_proc;
@@ -1686,7 +1686,7 @@ text_to_regprocedure(text *proc_signature)
16861686
static Node *
16871687
parse_expression(Oid relid, const char *expr, char **query_string_out)
16881688
{
1689-
char *fmt = "SELECT (%s) FROM %s.%s";
1689+
char *fmt = "SELECT (%s) FROM ONLY %s.%s";
16901690
char *relname = get_rel_name(relid),
16911691
*namespace_name = get_namespace_name(get_rel_namespace(relid));
16921692
List *parsetree_list;
@@ -2056,7 +2056,7 @@ static bool location_cleaning_walker(Node *node, void *context)
20562056

20572057
/* By given relation id and expression returns node */
20582058
Node *
2059-
get_expression_node(Oid relid, const char *expr, bool analyze)
2059+
get_expression_node(Oid relid, const char *expr, bool analyze, RTEMapItem **rte_map)
20602060
{
20612061
List *querytree_list;
20622062
List *target_list;
@@ -2082,6 +2082,25 @@ get_expression_node(Oid relid, const char *expr, bool analyze)
20822082
query = (Query *)lfirst(list_head(querytree_list));
20832083
plan = pg_plan_query(query, 0, NULL);
20842084

2085+
if (rte_map != NULL)
2086+
{
2087+
int i = 0;
2088+
int len = list_length(plan->rtable);
2089+
ListCell *cell;
2090+
2091+
*rte_map = (RTEMapItem *)palloc0(sizeof(RTEMapItem) * (len + 1));
2092+
foreach(cell, plan->rtable)
2093+
{
2094+
RangeTblEntry *tbl = lfirst(cell);
2095+
/* only plain relation RTE */
2096+
Assert(tbl->relid > 0);
2097+
(*rte_map)[i].relid = tbl->relid;
2098+
(*rte_map)[i].res_idx = -1;
2099+
2100+
i++;
2101+
}
2102+
}
2103+
20852104
target_entry = lfirst(list_head(plan->planTree->targetlist));
20862105

20872106
/* Hooks can work now */

src/partition_filter.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,72 @@ partition_filter_create_scan_state(CustomScan *node)
528528
return (Node *) state;
529529
}
530530

531+
static void
532+
adapt_rte_map(List *es_rangetable, RTEMapItem *rte_map)
533+
{
534+
int i = 0;
535+
ListCell *cell;
536+
537+
while (true)
538+
{
539+
int j = 1; /* rangetable entries are counting from 1 */
540+
bool found = false;
541+
542+
RTEMapItem *item = &rte_map[i++];
543+
if (item->relid == 0) /* end of array */
544+
break;
545+
546+
foreach(cell, es_rangetable)
547+
{
548+
RangeTblEntry *entry = lfirst(cell);
549+
if (entry->relid == item->relid) {
550+
item->res_idx = j;
551+
found = true;
552+
break;
553+
}
554+
555+
j++;
556+
}
557+
558+
if (!found)
559+
elog(ERROR, "Didn't found RTE entry for relid %d in expression",
560+
item->relid);
561+
}
562+
}
563+
564+
static bool
565+
adapt_walker(Node *node, void *context)
566+
{
567+
if (node == NULL)
568+
return false;
569+
570+
if (IsA(node, Var))
571+
{
572+
PartRelationInfo *prel = (PartRelationInfo *)context;
573+
int i = 0;
574+
Var *var = (Var *)node;
575+
576+
while (true)
577+
{
578+
RTEMapItem *item = &prel->expr_map[i];
579+
if (item->relid == 0)
580+
break;
581+
582+
if (var->varno == (i + 1))
583+
{
584+
var->varno = item->res_idx;
585+
return false;
586+
}
587+
588+
i++;
589+
}
590+
591+
elog(ERROR, "Didn't found relation for Var in expression");
592+
}
593+
594+
return expression_tree_walker(node, adapt_walker, context);
595+
}
596+
531597
void
532598
partition_filter_begin(CustomScanState *node, EState *estate, int eflags)
533599
{
@@ -571,6 +637,7 @@ partition_filter_exec(CustomScanState *node)
571637
Datum value;
572638
ExprDoneCond itemIsDone;
573639
ExprState *expr_state;
640+
TupleTableSlot *orig_slot;
574641

575642
/* Fetch PartRelationInfo for this partitioned relation */
576643
prel = get_pathman_relation_info(state->partitioned_table);
@@ -591,14 +658,22 @@ partition_filter_exec(CustomScanState *node)
591658
if (isnull)
592659
elog(ERROR, ERR_PART_ATTR_NULL); */
593660

661+
/* Modify expression to our needs */
662+
adapt_rte_map(estate->es_range_table, prel->expr_map);
663+
expression_tree_walker((Node *)prel->expr, adapt_walker, (void *) prel);
664+
594665
/* Prepare state before execution */
595666
expr_state = ExecPrepareExpr(prel->expr, estate);
596667

597668
/* Switch to per-tuple context */
598669
old_cxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
599670

600671
/* Execute expression */
672+
orig_slot = econtext->ecxt_scantuple;
673+
econtext->ecxt_scantuple = slot;
601674
value = ExecEvalExpr(expr_state, econtext, &isnull, &itemIsDone);
675+
econtext->ecxt_scantuple = orig_slot;
676+
602677
if (isnull)
603678
elog(ERROR, ERR_PART_ATTR_NULL);
604679

src/relation_info.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ refresh_pathman_relation_info(Oid relid,
144144
* Save parsed expression to cache and use already saved expression type
145145
* from config
146146
*/
147-
prel->expr = (Expr *) get_expression_node(relid, expr, true);
147+
prel->expr = (Expr *) get_expression_node(relid, expr, true, &prel->expr_map);
148148
prel->atttype = expr_type;
149149

150150
tp = SearchSysCache1(TYPEOID, values[Anum_pathman_config_atttype - 1]);

0 commit comments

Comments
 (0)