18
18
#include "runtime_merge_append.h"
19
19
20
20
#include "postgres.h"
21
- #include "fmgr.h"
21
+ #include "access/heapam.h"
22
+ #include "access/transam.h"
23
+ #include "access/xact.h"
24
+ #include "catalog/pg_type.h"
25
+ #include "executor/spi.h"
22
26
#include "miscadmin.h"
23
- #include "nodes/makefuncs.h"
24
- #include "nodes/nodeFuncs.h"
25
- #include "nodes/pg_list.h"
26
- #include "nodes/relation.h"
27
- #include "nodes/primnodes.h"
28
27
#include "optimizer/clauses.h"
29
- #include "optimizer/paths.h"
30
- #include "optimizer/pathnode.h"
31
- #include "optimizer/planner.h"
32
28
#include "optimizer/prep.h"
33
29
#include "optimizer/restrictinfo.h"
34
30
#include "optimizer/cost.h"
35
- #include "parser/analyze.h"
36
- #include "utils/hsearch.h"
37
31
#include "utils/rel.h"
38
- #include "utils/elog.h"
39
- #include "utils/array.h"
40
32
#include "utils/guc.h"
41
33
#include "utils/lsyscache.h"
42
34
#include "utils/selfuncs.h"
35
+ #include "utils/snapmgr.h"
43
36
#include "utils/memutils.h"
44
- #include "access/heapam.h"
45
- #include "storage/ipc.h"
46
- #include "catalog/pg_type.h"
47
37
#include "foreign/fdwapi.h"
38
+ #include "fmgr.h"
48
39
49
40
50
41
PG_MODULE_MAGIC ;
@@ -112,7 +103,7 @@ static Path *get_cheapest_parameterized_child_path(PlannerInfo *root, RelOptInfo
112
103
113
104
114
105
/*
115
- * Entry point
106
+ * Set initial values for all Postmaster's forks.
116
107
*/
117
108
void
118
109
_PG_init (void )
@@ -161,8 +152,8 @@ _PG_init(void)
161
152
}
162
153
163
154
/*
164
- * Disables inheritance for partitioned by pathman relations. It must be done to
165
- * prevent PostgresSQL from full search.
155
+ * Disables inheritance for partitioned by pathman relations.
156
+ * It must be done to prevent PostgresSQL from exhaustive search.
166
157
*/
167
158
void
168
159
disable_inheritance (Query * parse )
@@ -171,7 +162,6 @@ disable_inheritance(Query *parse)
171
162
RangeTblEntry * rte ;
172
163
PartRelationInfo * prel ;
173
164
MemoryContext oldcontext ;
174
- bool found ;
175
165
176
166
/* If query contains CTE (WITH statement) then handle subqueries too */
177
167
disable_inheritance_cte (parse );
@@ -189,10 +179,12 @@ disable_inheritance(Query *parse)
189
179
if (rte -> inh )
190
180
{
191
181
/* Look up this relation in pathman relations */
192
- prel = get_pathman_relation_info (rte -> relid , & found );
193
- if (prel != NULL && found )
182
+ prel = get_pathman_relation_info (rte -> relid , NULL );
183
+ if (prel )
194
184
{
185
+ /* We'll set this flag later */
195
186
rte -> inh = false;
187
+
196
188
/*
197
189
* Sometimes user uses the ONLY statement and in this case
198
190
* rte->inh is also false. We should differ the case
@@ -754,6 +746,118 @@ finish_least_greatest(WrapperNode *wrap, WalkerContext *context)
754
746
context -> hasGreatest = false;
755
747
}
756
748
749
+ /*
750
+ * Append partitions (if needed) and return Oid of the partition to contain value.
751
+ *
752
+ * NB: This function should not be called directly, use create_partitions() instead.
753
+ */
754
+ Oid
755
+ create_partitions_internal (Oid relid , Datum value , Oid value_type )
756
+ {
757
+ int ret ;
758
+ char * sql ;
759
+ PartRelationInfo * prel ;
760
+ FmgrInfo cmp_func ;
761
+ MemoryContext old_mcxt = CurrentMemoryContext ;
762
+ Oid partid = InvalidOid ; /* default value */
763
+
764
+ if ((prel = get_pathman_relation_info (relid , NULL )) == NULL )
765
+ {
766
+ elog (LOG , "Cannot fetch PartRelationInfo for relation %u [%u]" ,
767
+ relid , MyProcPid );
768
+
769
+ return InvalidOid ;
770
+ }
771
+
772
+ if ((ret = SPI_connect ()) < 0 )
773
+ {
774
+ elog (LOG , "create_partitions_internal(): SPI_connect returned %d" , ret );
775
+
776
+ return InvalidOid ;
777
+ }
778
+
779
+ /* Comparison function */
780
+ fill_type_cmp_fmgr_info (& cmp_func , value_type , prel -> atttype );
781
+
782
+ /* Perform PL procedure */
783
+ sql = psprintf ("SELECT %s.append_partitions_on_demand_internal($1, $2)" ,
784
+ get_namespace_name (get_pathman_schema ()));
785
+
786
+ PG_TRY ();
787
+ {
788
+ Oid oids [] = { OIDOID , value_type };
789
+ Datum vals [] = { ObjectIdGetDatum (relid ), value };
790
+ bool nulls [] = { false, false };
791
+ bool isnull ;
792
+
793
+ /* TODO: maybe this could be rewritten with FunctionCall */
794
+ ret = SPI_execute_with_args (sql , 2 , oids , vals , nulls , false, 0 );
795
+ if (ret == SPI_OK_SELECT )
796
+ {
797
+ TupleDesc tupdesc = SPI_tuptable -> tupdesc ;
798
+ HeapTuple tuple = SPI_tuptable -> vals [0 ];
799
+
800
+ Assert (SPI_processed == 1 );
801
+
802
+ partid = DatumGetObjectId (SPI_getbinval (tuple , tupdesc , 1 , & isnull ));
803
+ }
804
+ }
805
+ PG_CATCH ();
806
+ {
807
+ ErrorData * edata ;
808
+
809
+ MemoryContextSwitchTo (old_mcxt );
810
+ edata = CopyErrorData ();
811
+ FlushErrorState ();
812
+
813
+ elog (LOG , "create_partitions_internal(): %s [%u]" ,
814
+ edata -> message , MyProcPid );
815
+
816
+ FreeErrorData (edata );
817
+ }
818
+ PG_END_TRY ();
819
+
820
+ SPI_finish ();
821
+
822
+ return partid ;
823
+ }
824
+
825
+ /*
826
+ * Create RANGE partitions (if needed) using either BGW or current backend.
827
+ *
828
+ * Returns Oid of the partition to store 'value'.
829
+ */
830
+ Oid
831
+ create_partitions (Oid relid , Datum value , Oid value_type )
832
+ {
833
+ TransactionId rel_xmin ;
834
+
835
+ /* Check that table is partitioned and fetch xmin */
836
+ if (pathman_config_contains_relation (relid , NULL , NULL , & rel_xmin ))
837
+ {
838
+ /* If table was partitioned in some previous xact, run BGWorker */
839
+ if (TransactionIdPrecedes (rel_xmin , GetCurrentTransactionId ()))
840
+ {
841
+ elog (DEBUG2 , "create_partitions(): chose BGW [%u]" , MyProcPid );
842
+ return create_partitions_bg_worker (relid , value , value_type );
843
+ }
844
+ /* Else it'd better for the current backend to create partitions */
845
+ else
846
+ {
847
+ elog (DEBUG2 , "create_partitions(): chose backend [%u]" , MyProcPid );
848
+ return create_partitions_internal (relid , value , value_type );
849
+ }
850
+ }
851
+ else
852
+ elog (ERROR , "Relation %u is not partitioned by pg_pathman" , relid );
853
+
854
+ return InvalidOid ; /* keep compiler happy */
855
+ }
856
+
857
+ /*
858
+ * Given RangeEntry array and 'value', return selected
859
+ * RANGE partitions inside the WrapperNode.
860
+ */
757
861
void
758
862
select_range_partitions (const Datum value ,
759
863
FmgrInfo * cmp_func ,
0 commit comments