2727
2828
2929#define ALLOC_EXP 2
30+ #define PARENT_NAME_FMT "{parent_table}"
3031
3132
3233/*
@@ -64,6 +65,9 @@ static const struct config_enum_entry pg_pathman_insert_into_fdw_options[] = {
6465bool pg_pathman_enable_partition_filter = true;
6566int pg_pathman_insert_into_fdw = PF_FDW_INSERT_POSTGRES ;
6667
68+ bool pg_pathman_enable_fallback_relation = true;
69+ char * pg_pathman_fallback_relation_name ;
70+
6771CustomScanMethods partition_filter_plan_methods ;
6872CustomExecMethods partition_filter_exec_methods ;
6973
@@ -128,6 +132,25 @@ init_partition_filter_static_data(void)
128132NULL ,
129133NULL ,
130134NULL );
135+
136+ DefineCustomBoolVariable ("pg_pathman.enable_fallback_relation" ,
137+ "Enables fallback relation for COPY when partitioning key returns NULL" ,
138+ NULL ,
139+ & pg_pathman_enable_fallback_relation ,
140+ false,
141+ PGC_USERSET ,
142+ 0 ,
143+ NULL ,
144+ NULL ,
145+ NULL );
146+
147+ DefineCustomStringVariable ("pg_pathman.fallback_relation_name" ,
148+ "Partition name for NULL tuples in COPY command" ,
149+ NULL ,
150+ & pg_pathman_fallback_relation_name ,
151+ "pathman_" PARENT_NAME_FMT "_fallback" ,
152+ PGC_SUSET ,0 ,
153+ NULL ,NULL ,NULL );
131154}
132155
133156
@@ -270,9 +293,6 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *parts_storage)
270293child_rel = heap_open (partid ,NoLock );
271294CheckValidResultRel (child_rel ,parts_storage -> command_type );
272295
273- /* Build Var translation list for 'inserted_cols' */
274- make_inh_translation_list (parent_rel ,child_rel ,0 ,& translated_vars );
275-
276296/* Create RangeTblEntry for partition */
277297child_rte = makeNode (RangeTblEntry );
278298child_rte -> rtekind = RTE_RELATION ;
@@ -281,6 +301,9 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *parts_storage)
281301child_rte -> eref = parent_rte -> eref ;
282302child_rte -> requiredPerms = parent_rte -> requiredPerms ;
283303child_rte -> checkAsUser = parent_rte -> checkAsUser ;
304+
305+ /* Build Var translation list for 'inserted_cols' */
306+ make_translation_list (parent_rel ,child_rel ,0 ,& translated_vars );
284307child_rte -> insertedCols = translate_col_privs (parent_rte -> insertedCols ,
285308translated_vars );
286309child_rte -> updatedCols = translate_col_privs (parent_rte -> updatedCols ,
@@ -473,6 +496,76 @@ select_partition_for_insert(Datum value, Oid value_type,
473496return rri_holder ;
474497}
475498
499+ static char *
500+ get_fallback_relation_name (Oid parent_relid )
501+ {
502+ char * parent_name = get_rel_name (parent_relid ),
503+ * s = pstrdup (pg_pathman_fallback_relation_name );
504+ StringInfoData str ;
505+ char * pos ;
506+
507+ initStringInfo (& str );
508+
509+ if (strstr (s ,PARENT_NAME_FMT )!= NULL )
510+ {
511+ while ((pos = strstr (s ,PARENT_NAME_FMT ))!= NULL )
512+ {
513+ int tmpl_len = strlen (PARENT_NAME_FMT );
514+
515+ appendBinaryStringInfo (& str ,s ,pos - s );
516+ appendBinaryStringInfo (& str ,parent_name ,strlen (parent_name ));
517+ appendBinaryStringInfo (& str ,pos + tmpl_len ,strlen (s )- (pos - s )- tmpl_len );
518+ memset (s ,0 ,tmpl_len );
519+ }
520+ }
521+ else appendStringInfoString (& str ,s );
522+ pfree (s );
523+
524+ return str .data ;
525+ }
526+
527+ static Oid
528+ get_fallback_relation (Oid parent_relid )
529+ {
530+ char * name = get_fallback_relation_name (parent_relid );
531+ Oid result ,
532+ nsp ;
533+
534+ nsp = get_rel_namespace (parent_relid );
535+ result = get_relname_relid (name ,nsp );
536+ if (result == InvalidOid )
537+ {
538+ RangeVar * rv ;
539+ char * nspname = get_namespace_name (nsp );
540+
541+ rv = makeRangeVar (nspname ,name ,-1 );
542+ result = create_single_partition_internal (parent_relid ,rv ,NULL , false);
543+ }
544+
545+ return result ;
546+ }
547+
548+ /*
549+ * Return holder for fallback partition
550+ */
551+ ResultRelInfoHolder *
552+ get_relation_for_fallback (const PartRelationInfo * prel ,
553+ ResultPartsStorage * parts_storage ,
554+ EState * estate )
555+ {
556+ MemoryContext old_mcxt ;
557+ ResultRelInfoHolder * rri_holder ;
558+ Oid parent_relid = PrelParentRelid (prel ),
559+ fallback_relid ;
560+
561+ /* Replace parent table with a suitable partition */
562+ old_mcxt = MemoryContextSwitchTo (estate -> es_query_cxt );
563+ fallback_relid = get_fallback_relation (parent_relid );
564+ rri_holder = scan_result_parts_storage (fallback_relid ,parts_storage );
565+ MemoryContextSwitchTo (old_mcxt );
566+
567+ return rri_holder ;
568+ }
476569
477570/*
478571 * --------------------------------