@@ -94,6 +94,13 @@ typedef struct
94
94
} transform_query_cxt ;
95
95
96
96
97
+ typedef struct
98
+ {
99
+ Index child_varno ;
100
+ List * translated_vars ;
101
+ } adjust_appendrel_varnos_cxt ;
102
+
103
+
97
104
98
105
static bool pathman_transform_query_walker (Node * node , void * context );
99
106
@@ -103,6 +110,7 @@ static void handle_modification_query(Query *parse, transform_query_cxt *context
103
110
static void partition_filter_visitor (Plan * plan , void * context );
104
111
105
112
static Node * eval_extern_params_mutator (Node * node , ParamListInfo params );
113
+ static bool adjust_appendrel_varnos (Node * node , adjust_appendrel_varnos_cxt * context );
106
114
107
115
108
116
/*
@@ -366,20 +374,20 @@ handle_modification_query(Query *parse, transform_query_cxt *context)
366
374
WrapperNode * wrap ;
367
375
Expr * expr ;
368
376
WalkerContext wcxt ;
369
- Index result_rel ;
377
+ Index result_rti ;
370
378
int num_selected ;
371
379
ParamListInfo params ;
372
380
373
381
/* Fetch index of result relation */
374
- result_rel = parse -> resultRelation ;
382
+ result_rti = parse -> resultRelation ;
375
383
376
384
/* Exit if it's not a DELETE or UPDATE query */
377
- if (result_rel == 0 ||
385
+ if (result_rti == 0 ||
378
386
(parse -> commandType != CMD_UPDATE &&
379
387
parse -> commandType != CMD_DELETE ))
380
388
return ;
381
389
382
- rte = rt_fetch (result_rel , parse -> rtable );
390
+ rte = rt_fetch (result_rti , parse -> rtable );
383
391
384
392
/* Exit if it's DELETE FROM ONLY table */
385
393
if (!rte -> inh ) return ;
@@ -406,7 +414,7 @@ handle_modification_query(Query *parse, transform_query_cxt *context)
406
414
expr = (Expr * ) eval_extern_params_mutator ((Node * ) expr , params );
407
415
408
416
/* Prepare partitioning expression */
409
- prel_expr = PrelExpressionForRelid (prel , result_rel );
417
+ prel_expr = PrelExpressionForRelid (prel , result_rti );
410
418
411
419
/* Parse syntax tree and extract partition ranges */
412
420
InitWalkerContext (& wcxt , prel_expr , prel , NULL );
@@ -430,13 +438,14 @@ handle_modification_query(Query *parse, transform_query_cxt *context)
430
438
Relation child_rel ,
431
439
parent_rel ;
432
440
433
- void * tuple_map ; /* we don't need the map itself */
434
-
435
441
LOCKMODE lockmode = RowExclusiveLock ; /* UPDATE | DELETE */
436
442
437
443
HeapTuple syscache_htup ;
438
444
char child_relkind ;
439
445
446
+ List * translated_vars ;
447
+ adjust_appendrel_varnos_cxt aav_cxt ;
448
+
440
449
/* Lock 'child' table */
441
450
LockRelationOid (child , lockmode );
442
451
@@ -460,19 +469,23 @@ handle_modification_query(Query *parse, transform_query_cxt *context)
460
469
child_rel = heap_open (child , NoLock );
461
470
parent_rel = heap_open (parent , NoLock );
462
471
463
- /* Build a conversion map (may be trivial, i.e. NULL) */
464
- tuple_map = build_part_tuple_map (parent_rel , child_rel );
465
- if (tuple_map )
466
- free_conversion_map ((TupleConversionMap * ) tuple_map );
472
+ make_inh_translation_list (parent_rel , child_rel , 0 , & translated_vars );
473
+
474
+ /* Translate varnos for this child */
475
+ aav_cxt .child_varno = result_rti ;
476
+ aav_cxt .translated_vars = translated_vars ;
477
+ if (adjust_appendrel_varnos ((Node * ) parse , & aav_cxt ))
478
+ return ; /* failed to perform rewrites */
479
+
480
+ /* Translate column privileges for this child */
481
+ rte -> selectedCols = translate_col_privs (rte -> selectedCols , translated_vars );
482
+ rte -> insertedCols = translate_col_privs (rte -> insertedCols , translated_vars );
483
+ rte -> updatedCols = translate_col_privs (rte -> updatedCols , translated_vars );
467
484
468
485
/* Close relations (should remain locked, though) */
469
486
heap_close (child_rel , NoLock );
470
487
heap_close (parent_rel , NoLock );
471
488
472
- /* Exit if tuple map was NOT trivial */
473
- if (tuple_map ) /* just checking the pointer! */
474
- return ;
475
-
476
489
/* Update RTE's relid and relkind (for FDW) */
477
490
rte -> relid = child ;
478
491
rte -> relkind = child_relkind ;
@@ -490,6 +503,128 @@ handle_modification_query(Query *parse, transform_query_cxt *context)
490
503
}
491
504
}
492
505
506
+ /* Replace extern param nodes with consts */
507
+ static Node *
508
+ eval_extern_params_mutator (Node * node , ParamListInfo params )
509
+ {
510
+ if (node == NULL )
511
+ return NULL ;
512
+
513
+ if (IsA (node , Param ))
514
+ {
515
+ Param * param = (Param * ) node ;
516
+
517
+ Assert (params );
518
+
519
+ /* Look to see if we've been given a value for this Param */
520
+ if (param -> paramkind == PARAM_EXTERN &&
521
+ param -> paramid > 0 &&
522
+ param -> paramid <= params -> numParams )
523
+ {
524
+ ParamExternData * prm = & params -> params [param -> paramid - 1 ];
525
+
526
+ if (OidIsValid (prm -> ptype ))
527
+ {
528
+ /* OK to substitute parameter value? */
529
+ if (prm -> pflags & PARAM_FLAG_CONST )
530
+ {
531
+ /*
532
+ * Return a Const representing the param value.
533
+ * Must copy pass-by-ref datatypes, since the
534
+ * Param might be in a memory context
535
+ * shorter-lived than our output plan should be.
536
+ */
537
+ int16 typLen ;
538
+ bool typByVal ;
539
+ Datum pval ;
540
+
541
+ Assert (prm -> ptype == param -> paramtype );
542
+ get_typlenbyval (param -> paramtype ,
543
+ & typLen , & typByVal );
544
+ if (prm -> isnull || typByVal )
545
+ pval = prm -> value ;
546
+ else
547
+ pval = datumCopy (prm -> value , typByVal , typLen );
548
+ return (Node * ) makeConst (param -> paramtype ,
549
+ param -> paramtypmod ,
550
+ param -> paramcollid ,
551
+ (int ) typLen ,
552
+ pval ,
553
+ prm -> isnull ,
554
+ typByVal );
555
+ }
556
+ }
557
+ }
558
+ }
559
+
560
+ return expression_tree_mutator (node , eval_extern_params_mutator ,
561
+ (void * ) params );
562
+ }
563
+
564
+ static bool
565
+ adjust_appendrel_varnos (Node * node , adjust_appendrel_varnos_cxt * context )
566
+ {
567
+ if (node == NULL )
568
+ return false;
569
+
570
+ if (IsA (node , Query ))
571
+ {
572
+ Query * query = (Query * ) node ;
573
+ ListCell * lc ;
574
+
575
+ foreach (lc , query -> targetList )
576
+ {
577
+ TargetEntry * te = (TargetEntry * ) lfirst (lc );
578
+ Var * child_var ;
579
+
580
+ if (te -> resjunk )
581
+ continue ;
582
+
583
+ if (te -> resno > list_length (context -> translated_vars ))
584
+ return true;
585
+
586
+ child_var = list_nth (context -> translated_vars , te -> resno - 1 );
587
+ if (!child_var )
588
+ return true;
589
+
590
+ /* Transform attribute number */
591
+ te -> resno = child_var -> varattno ;
592
+ }
593
+
594
+ return query_tree_walker ((Query * ) node ,
595
+ adjust_appendrel_varnos ,
596
+ context ,
597
+ QTW_IGNORE_RC_SUBQUERIES );
598
+ }
599
+
600
+ if (IsA (node , Var ))
601
+ {
602
+ Var * var = (Var * ) node ;
603
+
604
+ /* Don't tranform system columns & other relations' Vars */
605
+ if (var -> varoattno > 0 && var -> varno == context -> child_varno )
606
+ {
607
+ Var * child_var ;
608
+
609
+ if (var -> varattno > list_length (context -> translated_vars ))
610
+ return true;
611
+
612
+ child_var = list_nth (context -> translated_vars , var -> varattno - 1 );
613
+ if (!child_var )
614
+ return true;
615
+
616
+ /* Transform attribute number */
617
+ var -> varattno = child_var -> varattno ;
618
+ }
619
+
620
+ return false;
621
+ }
622
+
623
+ return expression_tree_walker (node ,
624
+ adjust_appendrel_varnos ,
625
+ context );
626
+ }
627
+
493
628
494
629
/*
495
630
* -------------------------------
@@ -592,65 +727,6 @@ get_rel_parenthood_status(RangeTblEntry *rte)
592
727
}
593
728
594
729
595
- /* Replace extern param nodes with consts */
596
- static Node *
597
- eval_extern_params_mutator (Node * node , ParamListInfo params )
598
- {
599
- if (node == NULL )
600
- return NULL ;
601
-
602
- if (IsA (node , Param ))
603
- {
604
- Param * param = (Param * ) node ;
605
-
606
- Assert (params );
607
-
608
- /* Look to see if we've been given a value for this Param */
609
- if (param -> paramkind == PARAM_EXTERN &&
610
- param -> paramid > 0 &&
611
- param -> paramid <= params -> numParams )
612
- {
613
- ParamExternData * prm = & params -> params [param -> paramid - 1 ];
614
-
615
- if (OidIsValid (prm -> ptype ))
616
- {
617
- /* OK to substitute parameter value? */
618
- if (prm -> pflags & PARAM_FLAG_CONST )
619
- {
620
- /*
621
- * Return a Const representing the param value.
622
- * Must copy pass-by-ref datatypes, since the
623
- * Param might be in a memory context
624
- * shorter-lived than our output plan should be.
625
- */
626
- int16 typLen ;
627
- bool typByVal ;
628
- Datum pval ;
629
-
630
- Assert (prm -> ptype == param -> paramtype );
631
- get_typlenbyval (param -> paramtype ,
632
- & typLen , & typByVal );
633
- if (prm -> isnull || typByVal )
634
- pval = prm -> value ;
635
- else
636
- pval = datumCopy (prm -> value , typByVal , typLen );
637
- return (Node * ) makeConst (param -> paramtype ,
638
- param -> paramtypmod ,
639
- param -> paramcollid ,
640
- (int ) typLen ,
641
- pval ,
642
- prm -> isnull ,
643
- typByVal );
644
- }
645
- }
646
- }
647
- }
648
-
649
- return expression_tree_mutator (node , eval_extern_params_mutator ,
650
- (void * ) params );
651
- }
652
-
653
-
654
730
/*
655
731
* -----------------------------------------------
656
732
* Count number of times we've visited planner()
0 commit comments