@@ -70,7 +70,7 @@ static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
70
70
static void _selectTablespace (ArchiveHandle * AH , const char * tablespace );
71
71
static void processEncodingEntry (ArchiveHandle * AH , TocEntry * te );
72
72
static void processStdStringsEntry (ArchiveHandle * AH , TocEntry * te );
73
- static teReqs _tocEntryRequired (TocEntry * te , teSection curSection , RestoreOptions * ropt );
73
+ static teReqs _tocEntryRequired (TocEntry * te , teSection curSection , ArchiveHandle * AH );
74
74
static RestorePass _tocEntryRestorePass (TocEntry * te );
75
75
static bool _tocEntryIsACL (TocEntry * te );
76
76
static void _disableTriggersIfNecessary (ArchiveHandle * AH , TocEntry * te );
@@ -312,7 +312,7 @@ ProcessArchiveRestoreOptions(Archive *AHX)
312
312
if (te -> section != SECTION_NONE )
313
313
curSection = te -> section ;
314
314
315
- te -> reqs = _tocEntryRequired (te , curSection , ropt );
315
+ te -> reqs = _tocEntryRequired (te , curSection , AH );
316
316
}
317
317
318
318
/* Enforce strict names checking */
@@ -488,22 +488,15 @@ RestoreArchive(Archive *AHX)
488
488
* In createDB mode, issue a DROP *only* for the database as a
489
489
* whole. Issuing drops against anything else would be wrong,
490
490
* because at this point we're connected to the wrong database.
491
- * Conversely, if we're not in createDB mode, we'd better not
492
- * issue a DROP against the database at all. (The DATABASE
493
- * PROPERTIES entry, if any, works like the DATABASE entry.)
491
+ * (The DATABASE PROPERTIES entry, if any, should be treated like
492
+ * the DATABASE entry.)
494
493
*/
495
494
if (ropt -> createDB )
496
495
{
497
496
if (strcmp (te -> desc , "DATABASE" ) != 0 &&
498
497
strcmp (te -> desc , "DATABASE PROPERTIES" ) != 0 )
499
498
continue ;
500
499
}
501
- else
502
- {
503
- if (strcmp (te -> desc , "DATABASE" ) == 0 ||
504
- strcmp (te -> desc , "DATABASE PROPERTIES" ) == 0 )
505
- continue ;
506
- }
507
500
508
501
/* Otherwise, drop anything that's selected and has a dropStmt */
509
502
if (((te -> reqs & (REQ_SCHEMA | REQ_DATA )) != 0 ) && te -> dropStmt )
@@ -752,25 +745,6 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
752
745
753
746
AH -> currentTE = te ;
754
747
755
- /* Work out what, if anything, we want from this entry */
756
- reqs = te -> reqs ;
757
-
758
- /*
759
- * Ignore DATABASE and related entries unless createDB is specified. We
760
- * must check this here, not in _tocEntryRequired, because !createDB
761
- * should not prevent emitting these entries to an archive file.
762
- */
763
- if (!ropt -> createDB &&
764
- (strcmp (te -> desc , "DATABASE" ) == 0 ||
765
- strcmp (te -> desc , "DATABASE PROPERTIES" ) == 0 ||
766
- (strcmp (te -> desc , "ACL" ) == 0 &&
767
- strncmp (te -> tag , "DATABASE " , 9 ) == 0 ) ||
768
- (strcmp (te -> desc , "COMMENT" ) == 0 &&
769
- strncmp (te -> tag , "DATABASE " , 9 ) == 0 ) ||
770
- (strcmp (te -> desc , "SECURITY LABEL" ) == 0 &&
771
- strncmp (te -> tag , "DATABASE " , 9 ) == 0 )))
772
- reqs = 0 ;
773
-
774
748
/* Dump any relevant dump warnings to stderr */
775
749
if (!ropt -> suppressDumpWarnings && strcmp (te -> desc , "WARNING" ) == 0 )
776
750
{
@@ -780,6 +754,9 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
780
754
write_msg (modulename , "warning from original dump file: %s\n" , te -> copyStmt );
781
755
}
782
756
757
+ /* Work out what, if anything, we want from this entry */
758
+ reqs = te -> reqs ;
759
+
783
760
defnDumped = false;
784
761
785
762
/*
@@ -1191,7 +1168,7 @@ PrintTOCSummary(Archive *AHX)
1191
1168
if (te -> section != SECTION_NONE )
1192
1169
curSection = te -> section ;
1193
1170
if (ropt -> verbose ||
1194
- (_tocEntryRequired (te , curSection , ropt ) & (REQ_SCHEMA | REQ_DATA )) != 0 )
1171
+ (_tocEntryRequired (te , curSection , AH ) & (REQ_SCHEMA | REQ_DATA )) != 0 )
1195
1172
{
1196
1173
char * sanitized_name ;
1197
1174
char * sanitized_schema ;
@@ -2824,16 +2801,42 @@ StrictNamesCheck(RestoreOptions *ropt)
2824
2801
}
2825
2802
}
2826
2803
2804
+ /*
2805
+ * Determine whether we want to restore this TOC entry.
2806
+ *
2807
+ * Returns 0 if entry should be skipped, or some combination of the
2808
+ * REQ_SCHEMA and REQ_DATA bits if we want to restore schema and/or data
2809
+ * portions of this TOC entry, or REQ_SPECIAL if it's a special entry.
2810
+ */
2827
2811
static teReqs
2828
- _tocEntryRequired (TocEntry * te , teSection curSection , RestoreOptions * ropt )
2812
+ _tocEntryRequired (TocEntry * te , teSection curSection , ArchiveHandle * AH )
2829
2813
{
2830
2814
teReqs res = REQ_SCHEMA | REQ_DATA ;
2815
+ RestoreOptions * ropt = AH -> public .ropt ;
2831
2816
2832
2817
/* ENCODING and STDSTRINGS items are treated specially */
2833
2818
if (strcmp (te -> desc , "ENCODING" ) == 0 ||
2834
2819
strcmp (te -> desc , "STDSTRINGS" ) == 0 )
2835
2820
return REQ_SPECIAL ;
2836
2821
2822
+ /*
2823
+ * DATABASE and DATABASE PROPERTIES also have a special rule: they are
2824
+ * restored in createDB mode, and not restored otherwise, independently of
2825
+ * all else.
2826
+ */
2827
+ if (strcmp (te -> desc , "DATABASE" ) == 0 ||
2828
+ strcmp (te -> desc , "DATABASE PROPERTIES" ) == 0 )
2829
+ {
2830
+ if (ropt -> createDB )
2831
+ return REQ_SCHEMA ;
2832
+ else
2833
+ return 0 ;
2834
+ }
2835
+
2836
+ /*
2837
+ * Process exclusions that affect certain classes of TOC entries.
2838
+ */
2839
+
2837
2840
/* If it's an ACL, maybe ignore it */
2838
2841
if (ropt -> aclsSkip && _tocEntryIsACL (te ))
2839
2842
return 0 ;
@@ -2842,11 +2845,11 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt)
2842
2845
if (ropt -> no_publications && strcmp (te -> desc , "PUBLICATION" ) == 0 )
2843
2846
return 0 ;
2844
2847
2845
- /* If it's security labels , maybe ignore it */
2848
+ /* If it's a security label , maybe ignore it */
2846
2849
if (ropt -> no_security_labels && strcmp (te -> desc , "SECURITY LABEL" ) == 0 )
2847
2850
return 0 ;
2848
2851
2849
- /* If it's a subcription , maybe ignore it */
2852
+ /* If it's a subscription , maybe ignore it */
2850
2853
if (ropt -> no_subscriptions && strcmp (te -> desc , "SUBSCRIPTION" ) == 0 )
2851
2854
return 0 ;
2852
2855
@@ -2870,65 +2873,118 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt)
2870
2873
return 0 ;
2871
2874
}
2872
2875
2873
- /* Check options for selective dump/restore */
2874
- if (ropt -> schemaNames .head != NULL )
2875
- {
2876
- /* If no namespace is specified, it means all. */
2877
- if (!te -> namespace )
2878
- return 0 ;
2879
- if (!(simple_string_list_member (& ropt -> schemaNames , te -> namespace )))
2880
- return 0 ;
2881
- }
2882
-
2883
- if (ropt -> schemaExcludeNames .head != NULL &&
2884
- te -> namespace &&
2885
- simple_string_list_member (& ropt -> schemaExcludeNames , te -> namespace ))
2876
+ /* Ignore it if rejected by idWanted[] (cf. SortTocFromFile) */
2877
+ if (ropt -> idWanted && !ropt -> idWanted [te -> dumpId - 1 ])
2886
2878
return 0 ;
2887
2879
2888
- if (ropt -> selTypes )
2880
+ /*
2881
+ * Check options for selective dump/restore.
2882
+ */
2883
+ if (strcmp (te -> desc , "ACL" ) == 0 ||
2884
+ strcmp (te -> desc , "COMMENT" ) == 0 ||
2885
+ strcmp (te -> desc , "SECURITY LABEL" ) == 0 )
2889
2886
{
2890
- if (strcmp (te -> desc , "TABLE" ) == 0 ||
2891
- strcmp (te -> desc , "TABLE DATA" ) == 0 ||
2892
- strcmp (te -> desc , "VIEW" ) == 0 ||
2893
- strcmp (te -> desc , "FOREIGN TABLE" ) == 0 ||
2894
- strcmp (te -> desc , "MATERIALIZED VIEW" ) == 0 ||
2895
- strcmp (te -> desc , "MATERIALIZED VIEW DATA" ) == 0 ||
2896
- strcmp (te -> desc , "SEQUENCE" ) == 0 ||
2897
- strcmp (te -> desc , "SEQUENCE SET" ) == 0 )
2887
+ /* Database properties react to createDB, not selectivity options. */
2888
+ if (strncmp (te -> tag , "DATABASE " , 9 ) == 0 )
2898
2889
{
2899
- if (!ropt -> selTable )
2900
- return 0 ;
2901
- if (ropt -> tableNames .head != NULL && (!(simple_string_list_member (& ropt -> tableNames , te -> tag ))))
2890
+ if (!ropt -> createDB )
2902
2891
return 0 ;
2903
2892
}
2904
- else if (strcmp (te -> desc , "INDEX" ) == 0 )
2893
+ else if (ropt -> schemaNames .head != NULL ||
2894
+ ropt -> schemaExcludeNames .head != NULL ||
2895
+ ropt -> selTypes )
2905
2896
{
2906
- if (!ropt -> selIndex )
2907
- return 0 ;
2908
- if (ropt -> indexNames .head != NULL && (!(simple_string_list_member (& ropt -> indexNames , te -> tag ))))
2897
+ /*
2898
+ * In a selective dump/restore, we want to restore these dependent
2899
+ * TOC entry types only if their parent object is being restored.
2900
+ * Without selectivity options, we let through everything in the
2901
+ * archive. Note there may be such entries with no parent, eg
2902
+ * non-default ACLs for built-in objects.
2903
+ *
2904
+ * This code depends on the parent having been marked already,
2905
+ * which should be the case; if it isn't, perhaps due to
2906
+ * SortTocFromFile rearrangement, skipping the dependent entry
2907
+ * seems prudent anyway.
2908
+ *
2909
+ * Ideally we'd handle, eg, table CHECK constraints this way too.
2910
+ * But it's hard to tell which of their dependencies is the one to
2911
+ * consult.
2912
+ */
2913
+ if (te -> nDeps != 1 ||
2914
+ TocIDRequired (AH , te -> dependencies [0 ]) == 0 )
2909
2915
return 0 ;
2910
2916
}
2911
- else if (strcmp (te -> desc , "FUNCTION" ) == 0 ||
2912
- strcmp (te -> desc , "PROCEDURE" ) == 0 )
2917
+ }
2918
+ else
2919
+ {
2920
+ /* Apply selective-restore rules for standalone TOC entries. */
2921
+ if (ropt -> schemaNames .head != NULL )
2913
2922
{
2914
- if (!ropt -> selFunction )
2923
+ /* If no namespace is specified, it means all. */
2924
+ if (!te -> namespace )
2915
2925
return 0 ;
2916
- if (ropt -> functionNames . head != NULL && (!( simple_string_list_member (& ropt -> functionNames , te -> tag )) ))
2926
+ if (! simple_string_list_member (& ropt -> schemaNames , te -> namespace ))
2917
2927
return 0 ;
2918
2928
}
2919
- else if (strcmp (te -> desc , "TRIGGER" ) == 0 )
2929
+
2930
+ if (ropt -> schemaExcludeNames .head != NULL &&
2931
+ te -> namespace &&
2932
+ simple_string_list_member (& ropt -> schemaExcludeNames , te -> namespace ))
2933
+ return 0 ;
2934
+
2935
+ if (ropt -> selTypes )
2920
2936
{
2921
- if (!ropt -> selTrigger )
2922
- return 0 ;
2923
- if (ropt -> triggerNames .head != NULL && (!(simple_string_list_member (& ropt -> triggerNames , te -> tag ))))
2937
+ if (strcmp (te -> desc , "TABLE" ) == 0 ||
2938
+ strcmp (te -> desc , "TABLE DATA" ) == 0 ||
2939
+ strcmp (te -> desc , "VIEW" ) == 0 ||
2940
+ strcmp (te -> desc , "FOREIGN TABLE" ) == 0 ||
2941
+ strcmp (te -> desc , "MATERIALIZED VIEW" ) == 0 ||
2942
+ strcmp (te -> desc , "MATERIALIZED VIEW DATA" ) == 0 ||
2943
+ strcmp (te -> desc , "SEQUENCE" ) == 0 ||
2944
+ strcmp (te -> desc , "SEQUENCE SET" ) == 0 )
2945
+ {
2946
+ if (!ropt -> selTable )
2947
+ return 0 ;
2948
+ if (ropt -> tableNames .head != NULL &&
2949
+ !simple_string_list_member (& ropt -> tableNames , te -> tag ))
2950
+ return 0 ;
2951
+ }
2952
+ else if (strcmp (te -> desc , "INDEX" ) == 0 )
2953
+ {
2954
+ if (!ropt -> selIndex )
2955
+ return 0 ;
2956
+ if (ropt -> indexNames .head != NULL &&
2957
+ !simple_string_list_member (& ropt -> indexNames , te -> tag ))
2958
+ return 0 ;
2959
+ }
2960
+ else if (strcmp (te -> desc , "FUNCTION" ) == 0 ||
2961
+ strcmp (te -> desc , "AGGREGATE" ) == 0 ||
2962
+ strcmp (te -> desc , "PROCEDURE" ) == 0 )
2963
+ {
2964
+ if (!ropt -> selFunction )
2965
+ return 0 ;
2966
+ if (ropt -> functionNames .head != NULL &&
2967
+ !simple_string_list_member (& ropt -> functionNames , te -> tag ))
2968
+ return 0 ;
2969
+ }
2970
+ else if (strcmp (te -> desc , "TRIGGER" ) == 0 )
2971
+ {
2972
+ if (!ropt -> selTrigger )
2973
+ return 0 ;
2974
+ if (ropt -> triggerNames .head != NULL &&
2975
+ !simple_string_list_member (& ropt -> triggerNames , te -> tag ))
2976
+ return 0 ;
2977
+ }
2978
+ else
2924
2979
return 0 ;
2925
2980
}
2926
- else
2927
- return 0 ;
2928
2981
}
2929
2982
2930
2983
/*
2931
- * Check if we had a dataDumper. Indicates if the entry is schema or data
2984
+ * Determine whether the TOC entry contains schema and/or data components,
2985
+ * and mask off inapplicable REQ bits. If it had a dataDumper, assume
2986
+ * it's both schema and data. Otherwise it's probably schema-only, but
2987
+ * there are exceptions.
2932
2988
*/
2933
2989
if (!te -> hadDumper )
2934
2990
{
@@ -2952,6 +3008,10 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt)
2952
3008
res = res & ~REQ_DATA ;
2953
3009
}
2954
3010
3011
+ /* If there's no definition command, there's no schema component */
3012
+ if (!te -> defn || !te -> defn [0 ])
3013
+ res = res & ~REQ_SCHEMA ;
3014
+
2955
3015
/*
2956
3016
* Special case: <Init> type with <Max OID> tag; this is obsolete and we
2957
3017
* always ignore it.
@@ -2963,12 +3023,12 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt)
2963
3023
if (ropt -> schemaOnly )
2964
3024
{
2965
3025
/*
2966
- * The sequence_data option overrides schema-only for SEQUENCE SET.
3026
+ * The sequence_data option overrides schemaOnly for SEQUENCE SET.
2967
3027
*
2968
- * In binary-upgrade mode, even with schema-only set, we do not mask
2969
- * out large objects. Only large object definitions, comments and
2970
- * other information should be generated in binary-upgrade mode ( not
2971
- * the actual data).
3028
+ * In binary-upgrade mode, even with schemaOnly set, we do not mask
3029
+ * out large objects. ( Only large object definitions, comments and
3030
+ * other metadata should be generated in binary-upgrade mode, not the
3031
+ * actual data, but that need not concern us here.)
2972
3032
*/
2973
3033
if (!(ropt -> sequence_data && strcmp (te -> desc , "SEQUENCE SET" ) == 0 ) &&
2974
3034
!(ropt -> binary_upgrade &&
@@ -2986,14 +3046,6 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt)
2986
3046
if (ropt -> dataOnly )
2987
3047
res = res & REQ_DATA ;
2988
3048
2989
- /* Mask it if we don't have a schema contribution */
2990
- if (!te -> defn || strlen (te -> defn ) == 0 )
2991
- res = res & ~REQ_SCHEMA ;
2992
-
2993
- /* Finally, if there's a per-ID filter, limit based on that as well */
2994
- if (ropt -> idWanted && !ropt -> idWanted [te -> dumpId - 1 ])
2995
- return 0 ;
2996
-
2997
3049
return res ;
2998
3050
}
2999
3051
0 commit comments