@@ -89,7 +89,7 @@ def get_join_list(table, schema, graph, filters, fk_sets):
89
89
return join_list
90
90
91
91
92
- def get_copy_selects (schema , filters , safe_tables ):
92
+ def get_copy_selects (schema , filters , safe_tables , safe_fks ):
93
93
restricted_tables = set (filters .keys ())
94
94
controlled_tables = restricted_tables | safe_tables
95
95
@@ -109,7 +109,10 @@ def get_copy_selects(schema, filters, safe_tables):
109
109
filter_set |= {f"{ b } .{ f } " for f in filters .get (b , ())}
110
110
filter_set |= {f"{ a } .{ f } " for f in filters .get (a , ())}
111
111
for fk in fk_sets [(a , b )]:
112
- filter_set .add (f"{ a } .{ fk } = { b } .id" )
112
+ if (a , fk ) in safe_fks :
113
+ filter_set .add (f"({ a } .{ fk } = { b } .id OR { a } .{ fk } IS NULL)" )
114
+ else :
115
+ filter_set .add (f"{ a } .{ fk } = { b } .id" )
113
116
114
117
tables = list (join_tables | {table })
115
118
else :
@@ -137,6 +140,7 @@ def generate_copy_script(
137
140
target_connection = "" ,
138
141
target_owner = "fragdenstaat_de" ,
139
142
safe_tables = "safe_tables.txt" ,
143
+ safe_fks = "safe_fks.txt" ,
140
144
schema_file = "schema.sql" ,
141
145
):
142
146
FILTERS = dict (
@@ -171,6 +175,15 @@ def generate_copy_script(
171
175
["public.{}" .format (x .strip ()) for x in f .readlines () if x .strip ()]
172
176
)
173
177
178
+ with open (safe_fks ) as f :
179
+ safe_fks = set (
180
+ [
181
+ ("public.{}" .format (x .split ()[0 ].strip ()), x .split ()[1 ].strip ())
182
+ for x in f .readlines ()
183
+ if x .strip ()
184
+ ]
185
+ )
186
+
174
187
with open (schema_file ) as f :
175
188
schema = f .read ()
176
189
all_tables = set (TABLE_RE .findall (schema ))
@@ -203,7 +216,7 @@ def generate_copy_script(
203
216
outfile .write (f"psql { target_connection } { target_db } < table_setup.sql\n " )
204
217
205
218
outfile .write (f"export PGPASSWORD='{ source_password } '\n " )
206
- for table , select in get_copy_selects (schema , FILTERS , safe_tables ):
219
+ for table , select in get_copy_selects (schema , FILTERS , safe_tables , safe_fks ):
207
220
outfile .write (f'echo "Copying { table } "\n ' )
208
221
cmd = f"""psql -c "COPY ({ select } ) TO STDOUT;" { source_connection } { source_db } | psql -c "COPY { table } FROM STDIN;" { target_connection } { target_db } \n """
209
222
outfile .write (cmd )
@@ -254,6 +267,7 @@ def main():
254
267
parser .add_argument (
255
268
"--safe_tables" , help = "safe tables file" , default = "safe_tables.txt"
256
269
)
270
+ parser .add_argument ("--safe_fks" , help = "safe fks file" , default = "safe_fks.txt" )
257
271
parser .add_argument (
258
272
"--source_db" ,
259
273
help = "Postgres target connection details" ,
@@ -279,6 +293,7 @@ def main():
279
293
generate_copy_script (
280
294
sys .stdout ,
281
295
safe_tables = args .safe_tables ,
296
+ safe_fks = args .safe_fks ,
282
297
schema_file = args .schema_file ,
283
298
source_connection = args .source_connection ,
284
299
target_connection = args .target_connection ,
0 commit comments