Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cloning with extensions in non default schema #717

Conversation

kbarber
Copy link
Contributor

@kbarber kbarber commented Mar 21, 2024

Related to: #711 and #694

So using this DDL on the sourcedb:

create schema foo;
create extension hstore with schema foo cascade;
create table foo.bar (id int);

This patch attempts to fix the clone failure when there are extensions in different schemas due to the lack of the schema being created correctly beforehand.

For example:

> pgcopydb clone \
>   --source postgres://**********:**********@sourcedb:5432/********** \
>   --target postgres://**********:**********@targetdb:5432/********** \
>   --dir /tmp/pgcopydb \
>   --skip-ext-comments \
>   --no-owner \
>   --no-acl \
>   --fail-fast
17:37:47.536 118 INFO   Running pgcopydb version 0.15 from "/usr/local/bin/pgcopydb"
17:37:47.557 118 INFO   [SOURCE] Copying database from "postgres://**********@sourcedb:5432/**********?keepalives=1&keepalives_idle=10&keepalives_interval=10&keepalives_count=60"
17:37:47.558 118 INFO   [TARGET] Copying database into "postgres://**********@targetdb:5432/**********?keepalives=1&keepalives_idle=10&keepalives_interval=10&keepalives_count=60"
17:37:47.676 118 INFO   Using work dir "/tmp/pgcopydb"
17:37:48.884 118 INFO   Exported snapshot "00000003-03103FD8-1" from the source database
17:37:49.620 129 INFO   STEP 1: fetch source database tables, indexes, and sequences
17:37:51.629 129 INFO   Fetched information for 1 tables (including 0 tables split in 0 partitions total), with an estimated total of 18 quintillion tuples and 0 B on-disk
17:37:51.758 129 INFO   Fetched information for 0 indexes (supporting 0 constraints)
17:37:51.880 129 INFO   Fetching information for 0 sequences
17:37:52.149 129 INFO   Fetched information for 3 extensions
17:37:53.974 129 INFO   Found 0 indexes (supporting 0 constraints) in the target database
17:37:53.990 129 INFO   STEP 2: dump the source database schema (pre/post data)
17:37:53.995 129 INFO    /usr/bin/pg_dump -Fc --snapshot 00000003-03103FD8-1 --section pre-data --exclude-schema foo --exclude-schema heroku_ext --file /tmp/pgcopydb/schema/pre.dump 'postgres://**********@sourcedb:5432/**********?keepalives=1&keepalives_idle=10&keepalives_interval=10&keepalives_count=60'
17:38:04.926 129 INFO    /usr/bin/pg_dump -Fc --snapshot 00000003-03103FD8-1 --section post-data --exclude-schema foo --exclude-schema heroku_ext --file /tmp/pgcopydb/schema/post.dump 'postgres://**********@sourcedb:5432/**********?keepalives=1&keepalives_idle=10&keepalives_interval=10&keepalives_count=60'
17:38:15.277 129 INFO   STEP 3: restore the pre-data section to the target database
17:38:16.284 129 INFO   ALTER DATABASE "**********" SET "search_path" TO '$user', 'public', 'heroku_ext';
17:38:16.685 129 INFO    /usr/bin/pg_restore --dbname 'postgres://**********@targetdb:5432/**********?keepalives=1&keepalives_idle=10&keepalives_interval=10&keepalives_count=60' --jobs 4 --no-owner --no-acl --use-list /tmp/pgcopydb/schema/pre-filtered.list /tmp/pgcopydb/schema/pre.dump
17:38:20.063 129 ERROR  pg_restore: error: could not execute query: ERROR:  schema "foo" does not exist
17:38:20.064 129 ERROR  Command was: CREATE EXTENSION IF NOT EXISTS hstore WITH SCHEMA foo;
17:38:25.261 129 WARN   pg_restore: warning:
17:38:25.261 129 ERROR  errors ignored on restore: 1
17:38:25.279 129 ERROR  Failed to run pg_restore: exit code 1
17:38:25.279 129 ERROR  Failed to prepare schema on the target database, see above for details
17:38:25.279 129 ERROR  Failed to clone source database, see above for details
17:38:25.445 118 ERROR  clone process 129 has terminated [6]

@kbarber kbarber changed the title Cloning with functions in non default schema Cloning with functions in non default schema fails Mar 21, 2024
@kbarber
Copy link
Contributor Author

kbarber commented Mar 21, 2024

@dimitri I was trying to attack the problem from the clone perspective on this patch, it does work: but I'm doubtful. I removed the part of the union that includes all the items in s_namespace but I'm not entirely certain this breaks behaviour elsewhere ... such as filtering on namespaces or something.

@kbarber kbarber changed the title Cloning with functions in non default schema fails Fix cloning with extensions in non default schema Mar 22, 2024
@kbarber kbarber marked this pull request as ready for review March 22, 2024 00:42
@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch from ffa250b to b706b9c Compare March 22, 2024 01:54
@AbhinavKoul
Copy link

Tested this on our instance, it works🎉
Summary

 13:08:19.181 588 NOTICE summary.c:2835            Storing migration summary in JSON file "/tmp/pgcopydb/summary.json"

  OID | Schema |          Name | Parts | copy duration | transmitted bytes | indexes | create index duration 
------+--------+---------------+-------+---------------+-------------------+---------+----------------------
16500 | public | access_tokens |     1 |         793ms |               0 B |       0 |                   0ms
16507 |    foo |           bar |     1 |         806ms |               0 B |       0 |                   0ms


                                               Step   Connection    Duration    Transfer   Concurrency
 --------------------------------------------------   ----------  ----------  ----------  ------------
   Catalog Queries (table ordering, filtering, etc)       source       4s713                         1
                                        Dump Schema       source         26s                         1
                                     Prepare Schema       target         14s                         1
      COPY, INDEX, CONSTRAINTS, VACUUM (wall clock)         both       6s967                        12
                                  COPY (cumulative)         both       1s599      8192 B             4
                          CREATE INDEX (cumulative)       target         0ms                         4
                           CONSTRAINTS (cumulative)       target         0ms                         4
                                VACUUM (cumulative)       target       2s293                         4
                                    Reset Sequences         both       1s243                         1
                         Large Objects (cumulative)       (null)         0ms                         0
                                    Finalize Schema         both       9s384                         4
 --------------------------------------------------   ----------  ----------  ----------  ------------
                          Total Wall Clock Duration         both       1m01s                        20

Trace

13:08:05.464 636 INFO   extensions.c:291          COPY extension "postgis" configuration table heroku_ext.spatial_ref_sys
13:08:05.464 636 SQL    pgsql.c:495               Connecting to [target] "****?keepalives=1&keepalives_idle=10&keepalives_interval=10&keepalives_count=60"
13:08:05.494 640 SQL    pgsql.c:495               Connecting to [target] "****?keepalives=1&keepalives_idle=10&keepalives_interval=10&keepalives_count=60"
13:08:06.317 642 SQL    pgsql.c:1504              [TARGET 3230] SET client_encoding TO 'UTF-8';
13:08:06.353 653 SQL    pgsql.c:1504              [TARGET 3232] BEGIN;
13:08:06.359 643 SQL    pgsql.c:1504              [TARGET 3231] SET client_encoding TO 'UTF-8';
13:08:06.442 642 SQL    pgsql.c:1504              [TARGET 3230] SET extra_float_digits TO 3;
13:08:06.477 653 SQL    pgsql.c:1504              [TARGET 3232] COMMIT;
13:08:06.481 636 SQL    pgsql.c:1504              [TARGET 3234] BEGIN;
13:08:06.493 643 SQL    pgsql.c:1504              [TARGET 3231] SET extra_float_digits TO 3;
13:08:06.499 640 SQL    pgsql.c:1504              [TARGET 3235] SET client_encoding TO 'UTF-8';
13:08:06.501 641 SQL    pgsql.c:1504              [TARGET 3233] SET client_encoding TO 'UTF-8';
13:08:06.568 642 SQL    pgsql.c:1504              [TARGET 3230] SET statement_timeout TO 0;
13:08:06.604 653 SQL    pgsql.c:404               Disconnecting from [target] "****?keepalives=1&keepalives_idle=10&keepalives_interval=10&keepalives_count=60"
13:08:06.618 636 SQL    pgsql.c:2782              copy (SELECT * FROM ONLY heroku_ext.spatial_ref_sys WHERE NOT (
srid BETWEEN 2000 AND 2217
OR srid BETWEEN 2219 AND 2220
OR srid BETWEEN 2222 AND 2292
OR srid BETWEEN 2294 AND 2295
OR srid BETWEEN 2308 AND 2962
OR srid BETWEEN 2964 AND 2973
OR srid BETWEEN 2975 AND 2984
OR srid BETWEEN 2987 AND 3051
OR srid BETWEEN 3054 AND 3138
OR srid BETWEEN 3140 AND 3143
OR srid BETWEEN 3146 AND 3172
OR srid BETWEEN 3174 AND 3791
OR srid BETWEEN 3793 AND 3802
OR srid = 3812
OR srid BETWEEN 3814 AND 3816
OR srid = 3819
OR srid BETWEEN 3821 AND 3829
OR srid BETWEEN 3832 AND 3852
OR srid = 3854
OR srid = 3857
OR srid BETWEEN 3873 AND 3885
OR srid BETWEEN 3887 AND 3893
OR srid BETWEEN 3901 AND 3903
OR srid BETWEEN 3906 AND 3912
OR srid = 3920
OR srid BETWEEN 3942 AND 3950
OR srid BETWEEN 3968 AND 3970
OR srid BETWEEN 3973 AND 3976
OR srid BETWEEN 3978 AND 3979
OR srid BETWEEN 3985 AND 3989
OR srid BETWEEN 3991 AND 3997
OR srid BETWEEN 4000 AND 4063
OR srid = 4071
OR srid BETWEEN 4073 AND 4075
OR srid BETWEEN 4079 AND 4083
OR srid BETWEEN 4087 AND 4088
OR srid BETWEEN 4093 AND 4100
OR srid BETWEEN 4120 AND 4176
OR srid BETWEEN 4178 AND 4185
OR srid BETWEEN 4188 AND 4289
OR srid BETWEEN 4291 AND 4319
OR srid = 4322
OR srid = 4324
OR srid BETWEEN 4326 AND 4415
OR srid BETWEEN 4417 AND 4434
OR srid BETWEEN 4437 AND 4439
OR srid BETWEEN 4455 AND 4457
OR srid BETWEEN 4462 AND 4463
OR srid BETWEEN 4465 AND 4475
OR srid BETWEEN 4479 AND 4559
OR srid BETWEEN 4568 AND 4589
OR srid BETWEEN 4600 AND 4647
OR srid BETWEEN 4652 AND 4824
OR srid = 4826
OR srid = 4839
OR srid BETWEEN 4855 AND 4880
OR srid BETWEEN 4882 AND 4904
OR srid BETWEEN 4906 AND 4999
OR srid BETWEEN 5011 AND 5016
OR srid = 5018
OR srid BETWEEN 5041 AND 5042
OR srid = 5048
OR srid BETWEEN 5069 AND 5072
OR srid BETWEEN 5105 AND 5130
OR srid = 5132
OR srid BETWEEN 5167 AND 5188
OR srid = 5221
OR srid = 5223
OR srid BETWEEN 5228 AND 5229
OR srid BETWEEN 5233 AND 5235
OR srid BETWEEN 5243 AND 5247
OR srid BETWEEN 5250 AND 5259
OR srid BETWEEN 5262 AND 5264
OR srid = 5266
OR srid BETWEEN 5269 AND 5275
OR srid BETWEEN 5292 AND 5311
OR srid = 5316
OR srid = 5318
OR srid BETWEEN 5320 AND 5325
OR srid BETWEEN 5329 AND 5332
OR srid = 5337
OR srid BETWEEN 5340 AND 5349
OR srid BETWEEN 5352 AND 5365
OR srid BETWEEN 5367 AND 5373
OR srid BETWEEN 5379 AND 5383
OR srid BETWEEN 5387 AND 5389
OR srid BETWEEN 5391 AND 5393
OR srid = 5396
OR srid = 5451
OR srid BETWEEN 5456 AND 5464
OR srid BETWEEN 5466 AND 5467
OR srid = 5469
OR srid = 5472
OR srid BETWEEN 5479 AND 5482
OR srid BETWEEN 5487 AND 5490
OR srid BETWEEN 5498 AND 5500
OR srid BETWEEN 5513 AND 5514
OR srid BETWEEN 5518 AND 5520
OR srid BETWEEN 5523 AND 5524
OR srid = 5527
OR srid BETWEEN 5530 AND 5539
OR srid BETWEEN 5544 AND 5546
OR srid BETWEEN 5550 AND 5552
OR srid BETWEEN 5554 AND 5556
OR srid BETWEEN 5558 AND 5583
OR srid BETWEEN 5588 AND 5589
OR srid BETWEEN 5591 AND 5593
OR srid = 5596
OR srid = 5598
OR srid BETWEEN 5623 AND 5625
OR srid BETWEEN 5627 AND 5629
OR srid BETWEEN 5631 AND 5639
OR srid = 5641
OR srid BETWEEN 5643 AND 5644
OR srid = 5646
OR srid BETWEEN 5649 AND 5655
OR srid = 5659
OR srid BETWEEN 5663 AND 5685
OR srid BETWEEN 5698 AND 5700
OR srid BETWEEN 5707 AND 5708
OR srid = 5825
OR srid = 5828
OR srid = 5830
OR srid BETWEEN 5832 AND 5837
OR srid = 5839
OR srid = 5842
OR srid BETWEEN 5844 AND 5858
OR srid BETWEEN 5875 AND 5877
OR srid BETWEEN 5879 AND 5880
OR srid BETWEEN 5884 AND 5887
OR srid = 5890
OR srid BETWEEN 5896 AND 5899
OR srid BETWEEN 5921 AND 5940
OR srid = 5942
OR srid BETWEEN 5945 AND 5976
OR srid BETWEEN 6050 AND 6125
OR srid BETWEEN 6128 AND 6129
OR srid BETWEEN 6133 AND 6135
OR srid = 6141
OR srid BETWEEN 6144 AND 6176
OR srid = 6190
OR srid BETWEEN 6200 AND 6202
OR srid = 6204
OR srid = 6207
OR srid BETWEEN 6210 AND 6211
OR srid = 6307
OR srid BETWEEN 6309 AND 6312
OR srid BETWEEN 6316 AND 6325
OR srid BETWEEN 6328 AND 6356
OR srid BETWEEN 6362 AND 6372
OR srid BETWEEN 6381 AND 6387
OR srid = 6391
OR srid BETWEEN 6393 AND 6637
OR srid = 6646
OR srid BETWEEN 6649 AND 6692
OR srid BETWEEN 6696 AND 6697
OR srid = 6700
OR srid BETWEEN 6703 AND 6709
OR srid BETWEEN 6720 AND 6723
OR srid BETWEEN 6732 AND 6738
OR srid BETWEEN 6781 AND 6863
OR srid BETWEEN 6867 AND 6868
OR srid BETWEEN 6870 AND 6871
OR srid BETWEEN 6875 AND 6876
OR srid BETWEEN 6879 AND 6887
OR srid BETWEEN 6892 AND 6894
OR srid = 6915
OR srid = 6917
OR srid BETWEEN 6922 AND 6925
OR srid = 6927
OR srid BETWEEN 6931 AND 6934
OR srid BETWEEN 6956 AND 6959
OR srid = 6962
OR srid = 6966
OR srid BETWEEN 6978 AND 6991
OR srid BETWEEN 6996 AND 6997
OR srid BETWEEN 7005 AND 7007
OR srid BETWEEN 7034 AND 7042
OR srid BETWEEN 7057 AND 7081
OR srid BETWEEN 7084 AND 7088
OR srid BETWEEN 7109 AND 7128
OR srid BETWEEN 7131 AND 7139
OR srid = 7142
OR srid BETWEEN 7257 AND 7376
OR srid BETWEEN 7400 AND 7423
OR srid BETWEEN 7528 AND 7645
OR srid BETWEEN 7656 AND 7665
OR srid BETWEEN 7677 AND 7686
OR srid BETWEEN 7692 AND 7696
OR srid BETWEEN 7755 AND 7787
OR srid = 7789
OR srid BETWEEN 7791 AND 7801
OR srid BETWEEN 7803 AND 7805
OR srid BETWEEN 7815 AND 7816
OR srid BETWEEN 7825 AND 7831
OR srid BETWEEN 7842 AND 7859
OR srid BETWEEN 7877 AND 7887
OR srid BETWEEN 7899 AND 7912
OR srid BETWEEN 7914 AND 7931
OR srid BETWEEN 7954 AND 7956
OR srid BETWEEN 7991 AND 7992
OR srid BETWEEN 8013 AND 8032
OR srid BETWEEN 8035 AND 8036
OR srid BETWEEN 8042 AND 8045
OR srid BETWEEN 8058 AND 8059
OR srid BETWEEN 8065 AND 8068
OR srid BETWEEN 8082 AND 8086
OR srid = 8088
OR srid BETWEEN 8090 AND 8093
OR srid BETWEEN 8095 AND 8173
OR srid = 8177
OR srid BETWEEN 8179 AND 8182
OR srid BETWEEN 8184 AND 8185
OR srid = 8187
OR srid = 8189
OR srid = 8191
OR srid = 8193
OR srid BETWEEN 8196 AND 8198
OR srid BETWEEN 8200 AND 8210
OR srid BETWEEN 8212 AND 8214
OR srid = 8216
OR srid = 8218
OR srid = 8220
OR srid = 8222
OR srid BETWEEN 8224 AND 8227
OR srid BETWEEN 8230 AND 8233
OR srid = 8235
OR srid BETWEEN 8237 AND 8240
OR srid = 8242
OR srid = 8244
OR srid BETWEEN 8246 AND 8255
OR srid BETWEEN 8311 AND 8353
OR srid = 8360
OR srid = 8370
OR srid BETWEEN 8379 AND 8385
OR srid = 8387
OR srid = 8391
OR srid = 8395
OR srid = 8397
OR srid = 8399
OR srid = 8401
OR srid = 8403
OR srid BETWEEN 8425 AND 8431
OR srid = 8433
OR srid = 8441
OR srid = 8449
OR srid BETWEEN 8455 AND 8456
OR srid BETWEEN 8518 AND 8529
OR srid = 8531
OR srid BETWEEN 8533 AND 8536
OR srid BETWEEN 8538 AND 8545
OR srid BETWEEN 8677 AND 8679
OR srid BETWEEN 8682 AND 8687
OR srid BETWEEN 8692 AND 8693
OR srid BETWEEN 8700 AND 8818
OR srid = 8826
OR srid BETWEEN 8836 AND 8840
OR srid BETWEEN 8857 AND 8860
OR srid BETWEEN 8898 AND 8903
OR srid BETWEEN 8905 AND 8910
OR srid = 8912
OR srid BETWEEN 8988 AND 9019
OR srid BETWEEN 20002 AND 20032
OR srid BETWEEN 20062 AND 20092
OR srid BETWEEN 20135 AND 20138
OR srid BETWEEN 20248 AND 20258
OR srid BETWEEN 20348 AND 20358
OR srid BETWEEN 20436 AND 20440
OR srid = 20499
OR srid BETWEEN 20538 AND 20539
OR srid BETWEEN 20790 AND 20791
OR srid BETWEEN 20822 AND 20824
OR srid BETWEEN 20934 AND 20936
OR srid BETWEEN 21035 AND 21037
OR srid BETWEEN 21095 AND 21097
OR srid = 21100
OR srid BETWEEN 21148 AND 21150
OR srid BETWEEN 21291 AND 21292
OR srid BETWEEN 21413 AND 21423
OR srid BETWEEN 21453 AND 21463
OR srid BETWEEN 21473 AND 21483
OR srid = 21500
OR srid BETWEEN 21780 AND 21782
OR srid BETWEEN 21817 AND 21818
OR srid BETWEEN 21891 AND 21894
OR srid BETWEEN 21896 AND 21899
OR srid BETWEEN 22032 AND 22033
OR srid BETWEEN 22091 AND 22092
OR srid BETWEEN 22171 AND 22177
OR srid BETWEEN 22181 AND 22187
OR srid BETWEEN 22191 AND 22197
OR srid BETWEEN 22234 AND 22236
OR srid = 22275
OR srid = 22277
OR srid = 22279
OR srid = 22281
OR srid = 22283
OR srid = 22285
OR srid = 22287
OR srid = 22289
OR srid = 22291
OR srid = 22293
OR srid = 22300
OR srid = 22332
OR srid BETWEEN 22391 AND 22392
OR srid BETWEEN 22521 AND 22525
OR srid = 22700
OR srid = 22770
OR srid = 22780
OR srid = 22832
OR srid BETWEEN 22991 AND 22994
OR srid BETWEEN 23028 AND 23038
OR srid = 23090
OR srid = 23095
OR srid BETWEEN 23239 AND 23240
OR srid = 23433
OR srid = 23700
OR srid BETWEEN 23830 AND 23853
OR srid BETWEEN 23866 AND 23872
OR srid BETWEEN 23877 AND 23884
OR srid BETWEEN 23886 AND 23894
OR srid BETWEEN 23946 AND 23948
OR srid BETWEEN 24047 AND 24048
OR srid = 24100
OR srid = 24200
OR srid BETWEEN 24305 AND 24306
OR srid BETWEEN 24311 AND 24313
OR srid BETWEEN 24342 AND 24347
OR srid BETWEEN 24370 AND 24383
OR srid = 24500
OR srid BETWEEN 24547 AND 24548
OR srid = 24571
OR srid = 24600
OR srid BETWEEN 24718 AND 24721
OR srid BETWEEN 24817 AND 24821
OR srid BETWEEN 24877 AND 24882
OR srid BETWEEN 24891 AND 24893
OR srid = 25000
OR srid = 25231
OR srid BETWEEN 25391 AND 25395
OR srid = 25700
OR srid BETWEEN 25828 AND 25838
OR srid = 25884
OR srid = 25932
OR srid BETWEEN 26191 AND 26195
OR srid = 26237
OR srid BETWEEN 26331 AND 26332
OR srid BETWEEN 26391 AND 26393
OR srid = 26432
OR srid BETWEEN 26591 AND 26592
OR srid = 26632
OR srid = 26692
OR srid BETWEEN 26701 AND 26722
OR srid BETWEEN 26729 AND 26799
OR srid BETWEEN 26801 AND 26803
OR srid BETWEEN 26811 AND 26815
OR srid BETWEEN 26819 AND 26826
OR srid BETWEEN 26830 AND 26837
OR srid BETWEEN 26841 AND 26870
OR srid BETWEEN 26891 AND 26899
OR srid BETWEEN 26901 AND 26923
OR srid BETWEEN 26929 AND 26946
OR srid BETWEEN 26948 AND 26998
OR srid BETWEEN 27037 AND 27040
OR srid = 27120
OR srid = 27200
OR srid BETWEEN 27205 AND 27232
OR srid BETWEEN 27258 AND 27260
OR srid BETWEEN 27291 AND 27292
OR srid BETWEEN 27391 AND 27398
OR srid = 27429
OR srid BETWEEN 27492 AND 27493
OR srid = 27500
OR srid BETWEEN 27561 AND 27564
OR srid BETWEEN 27571 AND 27574
OR srid BETWEEN 27581 AND 27584
OR srid BETWEEN 27591 AND 27594
OR srid = 27700
OR srid BETWEEN 28191 AND 28193
OR srid = 28232
OR srid BETWEEN 28348 AND 28358
OR srid BETWEEN 28402 AND 28432
OR srid BETWEEN 28462 AND 28492
OR srid = 28600
OR srid BETWEEN 28991 AND 28992
OR srid BETWEEN 29100 AND 29101
OR srid BETWEEN 29118 AND 29122
OR srid BETWEEN 29168 AND 29172
OR srid BETWEEN 29177 AND 29185
OR srid BETWEEN 29187 AND 29195
OR srid BETWEEN 29220 AND 29221
OR srid = 29333
OR srid = 29371
OR srid = 29373
OR srid = 29375
OR srid = 29377
OR srid = 29379
OR srid = 29381
OR srid = 29383
OR srid = 29385
OR srid BETWEEN 29635 AND 29636
OR srid BETWEEN 29700 AND 29702
OR srid BETWEEN 29738 AND 29739
OR srid BETWEEN 29849 AND 29850
OR srid BETWEEN 29871 AND 29873
OR srid BETWEEN 29900 AND 29903
OR srid BETWEEN 30161 AND 30179
OR srid = 30200
OR srid BETWEEN 30339 AND 30340
OR srid BETWEEN 30491 AND 30494
OR srid BETWEEN 30591 AND 30592
OR srid BETWEEN 30729 AND 30732
OR srid BETWEEN 30791 AND 30792
OR srid = 30800
OR srid = 31028
OR srid = 31121
OR srid = 31154
OR srid BETWEEN 31170 AND 31171
OR srid BETWEEN 31251 AND 31259
OR srid BETWEEN 31265 AND 31268
OR srid BETWEEN 31275 AND 31279
OR srid BETWEEN 31281 AND 31297
OR srid = 31300
OR srid = 31370
OR srid BETWEEN 31461 AND 31469
OR srid BETWEEN 31491 AND 31495
OR srid BETWEEN 31528 AND 31529
OR srid = 31600
OR srid = 31700
OR srid BETWEEN 31838 AND 31839
OR srid BETWEEN 31900 AND 31901
OR srid BETWEEN 31917 AND 31922
OR srid BETWEEN 31965 AND 32003
OR srid BETWEEN 32005 AND 32031
OR srid BETWEEN 32033 AND 32062
OR srid BETWEEN 32064 AND 32067
OR srid BETWEEN 32074 AND 32077
OR srid BETWEEN 32081 AND 32086
OR srid BETWEEN 32098 AND 32100
OR srid = 32104
OR srid BETWEEN 32107 AND 32130
OR srid BETWEEN 32133 AND 32158
OR srid = 32161
OR srid BETWEEN 32164 AND 32167
OR srid BETWEEN 32180 AND 32199
OR srid BETWEEN 32201 AND 32260
OR srid BETWEEN 32301 AND 32360
OR srid BETWEEN 32401 AND 32460
OR srid BETWEEN 32501 AND 32560
OR srid BETWEEN 32601 AND 32667
OR srid BETWEEN 32701 AND 32761
OR srid = 32766
OR srid BETWEEN 37001 AND 37008
OR srid BETWEEN 37201 AND 37208
OR srid BETWEEN 37211 AND 37235
OR srid BETWEEN 37237 AND 37243
OR srid BETWEEN 37245 AND 37247
OR srid BETWEEN 37249 AND 37255
OR srid = 37257
OR srid BETWEEN 37259 AND 37260
OR srid BETWEEN 53001 AND 53004
OR srid BETWEEN 53008 AND 53016
OR srid BETWEEN 53018 AND 53019
OR srid BETWEEN 53021 AND 53032
OR srid BETWEEN 53034 AND 53037
OR srid BETWEEN 53042 AND 53043
OR srid = 53046
OR srid BETWEEN 53074 AND 53076
OR srid BETWEEN 54001 AND 54004
OR srid BETWEEN 54008 AND 54016
OR srid BETWEEN 54018 AND 54019
OR srid BETWEEN 54021 AND 54032
OR srid BETWEEN 54034 AND 54037
OR srid BETWEEN 54042 AND 54043
OR srid = 54046
OR srid BETWEEN 54052 AND 54053
OR srid BETWEEN 54074 AND 54076
OR srid BETWEEN 65061 AND 65062
OR srid = 65161
OR srid = 65163
OR srid BETWEEN 102001 AND 102298
OR srid = 102300
OR srid BETWEEN 102304 AND 102459
OR srid BETWEEN 102461 AND 102569
OR srid BETWEEN 102581 AND 102730
OR srid BETWEEN 102733 AND 102758
OR srid BETWEEN 102761 AND 102766
OR srid BETWEEN 102799 AND 102900
OR srid BETWEEN 102962 AND 102963
OR srid BETWEEN 102965 AND 103585
OR srid BETWEEN 103600 AND 103695
OR srid BETWEEN 103700 AND 103871
OR srid BETWEEN 103900 AND 103971
OR srid = 104000
OR srid BETWEEN 104009 AND 104026
OR srid = 104047
OR srid = 104050
OR srid BETWEEN 104100 AND 104145
OR srid BETWEEN 104179 AND 104186
OR srid = 104199
OR srid = 104223
OR srid = 104248
OR srid BETWEEN 104256 AND 104261
OR srid BETWEEN 104286 AND 104287
OR srid BETWEEN 104304 AND 104305
OR srid BETWEEN 104700 AND 104786
OR srid BETWEEN 104800 AND 104871
OR srid = 104896
OR srid BETWEEN 104900 AND 104975
OR srid BETWEEN 104990 AND 104992
OR srid = 900913
)) to stdout;
13:08:06.631 643 SQL    pgsql.c:1504              [TARGET 3231] SET statement_timeout TO 0;
13:08:06.689 588 DEBUG  copydb.c:760              Sub-process 653 exited with code 0
13:08:06.719 641 SQL    pgsql.c:1504              [TARGET 3233] SET extra_float_digits TO 3;
13:08:06.722 640 SQL    pgsql.c:1504              [TARGET 3235] SET extra_float_digits TO 3;
13:08:06.738 642 SQL    pgsql.c:1504              [TARGET 3230] SET default_transaction_read_only TO off;
13:08:06.879 642 SQL    pgsql.c:1504              [TARGET 3230] SET maintenance_work_mem TO '1 GB';
13:08:06.882 643 SQL    pgsql.c:1504              [TARGET 3231] SET default_transaction_read_only TO off;
13:08:06.883 640 SQL    pgsql.c:1504              [TARGET 3235] SET statement_timeout TO 0;
13:08:06.885 641 SQL    pgsql.c:1504              [TARGET 3233] SET statement_timeout TO 0;
13:08:07.008 636 SQL    pgsql.c:2782              copy heroku_ext.spatial_ref_sys from stdin;

Copy link
Owner

@dimitri dimitri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well this is passing all our testing, which include filtering on namespaces. The extension test case also passes, where we deal with extensions separately from the pgcopydb clone command.

The trick here is to be compatible with a target database where the extensions have already been installed in a previous step, out of the pgcopydb scope. What happens with your patch if you create the extension (and its schema) manually in the target instance before running pgcopydb clone?

@kbarber
Copy link
Contributor Author

kbarber commented Mar 22, 2024

What happens with your patch if you create the extension (and its schema) manually in the target instance before running pgcopydb clone?

So if I use --drop-if-exists, it seems to work.

If I do not, I get this error:

16:36:53.636 21 ERROR  pg_restore: error: could not execute query: ERROR:  schema "foo" already exists
16:36:53.636 21 ERROR  Command was: CREATE SCHEMA foo;
16:37:00.019 21 WARN   pg_restore: warning: errors ignored on restore: 1
16:37:00.027 21 ERROR  Failed to run pg_restore: exit code 1
16:37:00.027 21 ERROR  Failed to prepare schema on the target database, see above for details
16:37:00.027 21 ERROR  Failed to clone source database, see above for details
16:37:00.119 10 ERROR  clone process 21 has terminated [6]

@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch from 79396d0 to 8588e7a Compare March 22, 2024 16:59
@dimitri
Copy link
Owner

dimitri commented Mar 22, 2024

I think your test fails because of the code you deleted that handles pre-existing SQL objects in the target database... we need to keep that feature when adding your bug fix.

@kbarber
Copy link
Contributor Author

kbarber commented Mar 22, 2024

I think your test fails because of the code you deleted that handles pre-existing SQL objects in the target database... we need to keep that feature when adding your bug fix.

Yeah without that ^^ the schemas don't get created for the extensions, and we hard fail. It looks like it wasn't filtering on what was in the target database, just the source database. Is that what needs to be fixed here perhaps? Do we need a t_namspace or something to populate the filter?

So it sounds like the desire is: We need to be able to support copying extensions and having their schemas created if they don't exist, if the schema exists we shouldn't throw an error.

Is this because we imagine some users to want to precreate their schemas before a clone?

One idea might also to have a switch for --skip-schemas to add those filters for those who want to avoid schema creation by pgcopydb.

There is another way this could be done. I mean create schema if not exists is a thing, but pg_dump I'm not sure it can drop that. We could pull out the pre-schema creation too I guess and make it more programmatic like the copy extensions style. I hint at this over here on this PR for that side of the problem: #711 (comment)

Although I am wondering about the consistency here: This seems contrary to what I'm seeing for tables however, which will always fail if you try to clone again without --drop-if-exists. For example:

18:32:09.409 65 ERROR  string_utils.c:669        pg_restore: error: 
18:32:09.409 65 ERROR  string_utils.c:669        could not execute query: ERROR:  relation "foo" already exists
18:32:09.409 65 ERROR  string_utils.c:669        Command was: CREATE TABLE public.foo (
18:32:09.409 65 ERROR  string_utils.c:669            id integer
18:32:09.409 65 ERROR  string_utils.c:669        );

@kbarber
Copy link
Contributor Author

kbarber commented Mar 22, 2024

I added a --skip-schemas switch that reverts that filter that was originally there. Now you can run it with schemas & extensions already precreated. LMK if this is a viable approach.

@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch from cdc8f07 to 7bd6ad8 Compare March 25, 2024 18:26
@kbarber
Copy link
Contributor Author

kbarber commented Mar 25, 2024

@dimitri do you think this is enough for now for just the pgcopy clone case, or we need more work

Copy link
Owner

@dimitri dimitri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused about what schemas are skipped and then why the name of the option is --skip-schemas ; it might have to be spelled --skip-create-extension-schema or something like that, although I must confess a shorter name would be appreciated.

Comment on lines 4996 to 4997
/*
* Implement --skip-schemas
*/
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What schemas are we skipping here? I think the comment needs more explaining.

Copy link
Contributor Author

@kbarber kbarber Mar 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a better comment

@@ -23,6 +23,7 @@
--skip-ext-comments Skip restoring COMMENT ON EXTENSION
--skip-collations Skip restoring collations
--skip-vacuum Skip running VACUUM ANALYZE
--skip-schemas Skip creating schemas
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which schema are skipped with this option? I think the short text could be better, but also the long text covering the option in details is missing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improved the text here, am I missing a doc update somewhere for a longer description?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See https://pgcopydb.readthedocs.io/en/latest/ref/pgcopydb_clone.html#options

Also would be good if the options for skipping extension related stuff (comments, schemas) were grouped together in the listing.

@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch 2 times, most recently from cef67f6 to 3f8c7b0 Compare March 28, 2024 12:28
@kbarber
Copy link
Contributor Author

kbarber commented Mar 28, 2024

@dimitri how about --skip-ext-schemas? I've expanded the descriptions also.

@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch from 3f8c7b0 to e1aa7ef Compare March 28, 2024 18:41
@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch from e1aa7ef to d344e9a Compare April 8, 2024 12:17
@kbarber
Copy link
Contributor Author

kbarber commented Apr 8, 2024

Greetings @dimitri would you be able to take a look at this PR again when you have time? Thanks.

@dimitri
Copy link
Owner

dimitri commented Apr 15, 2024

So it sounds like the desire is: We need to be able to support copying extensions and having their schemas created if they don't exist, if the schema exists we shouldn't throw an error.

Yes, please have a look at the following part of the code:

if (!skip && catOid == PG_NAMESPACE_OID)
{
bool exists = false;
if (!copydb_schema_already_exists(specs, name, &exists))
{
log_error("Failed to check if restore name \"%s\" "
"already exists",
name);
destroyPQExpBuffer(listContents);
return false;
}

I would expect that we implement something similar for extensions schemas too, which means we populate the target database with the list of namespaces that extensions depend on. Do you think you could add that to your PR, basically making the --skip-ext-schemas fully automated now?

@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch 3 times, most recently from e99808f to 359682f Compare April 15, 2024 21:03
@kbarber
Copy link
Contributor Author

kbarber commented Apr 15, 2024

So it sounds like the desire is: We need to be able to support copying extensions and having their schemas created if they don't exist, if the schema exists we shouldn't throw an error.

Yes, please have a look at the following part of the code:

if (!skip && catOid == PG_NAMESPACE_OID)
{
bool exists = false;
if (!copydb_schema_already_exists(specs, name, &exists))
{
log_error("Failed to check if restore name \"%s\" "
"already exists",
name);
destroyPQExpBuffer(listContents);
return false;
}

I would expect that we implement something similar for extensions schemas too, which means we populate the target database with the list of namespaces that extensions depend on. Do you think you could add that to your PR, basically making the --skip-ext-schemas fully automated now?

@dimitri thanks for responding. The code you pointed out and copydb_schema_already_exists seems to be doing almost the correct thing already surprisingly but it wasn't working for me. Upon debugging however: I figured out it doesn't match when the ownership of the schema between the source & target is not the same. So I was getting mismatches - if we reduce the lookup to ignore the ownership the skipping of schemas works without me doing anything else.

I think I fixed this in the current PR code feel free to take a look. I added a change to the test file to confirm with a creation of bar schema beforehand to show us a regression. Anyway this seems to work now without a switch to skip schemas; locally between two dbs with different ownership as well.

08:50:11.347 655 NOTICE dump_restore.c:678        Skipping already existing dumpId 12: SCHEMA 18530 - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcdefghijklmnop fqayuutgtrkspv
08:50:11.348 655 NOTICE dump_restore.c:678        Skipping already existing dumpId 11: SCHEMA 18529 - aabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik fqayuutgtrkspv
08:50:11.348 655 NOTICE dump_restore.c:678        Skipping already existing dumpId 10: SCHEMA 18528 - abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik fqayuutgtrkspv
08:50:11.348 655 NOTICE dump_restore.c:678        Skipping already existing dumpId 9: SCHEMA 18105 - foo fqayuutgtrkspv
08:50:11.348 655 NOTICE dump_restore.c:678        Skipping already existing dumpId 7: SCHEMA 17937 - heroku_ext u2sc2mm8l1f6ht
08:50:11.348 655 NOTICE dump_restore.c:678        Skipping already existing dumpId 8: SCHEMA 18104 - public fqayuutgtrkspv

@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch 2 times, most recently from 85bb3cd to c2a33fe Compare April 15, 2024 23:32
@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch 2 times, most recently from fb096f3 to 27d9979 Compare April 16, 2024 09:19
Copy link
Owner

@dimitri dimitri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Thanks for the detective work. I like that you found that we match on schema name and owner and should only match on schema name. About the implementation, see my comments. Is there a way that we can lookup the actual schema name from the schema OID, if we have it, rather than parse the restore list name?

src/bin/pgcopydb/catalog.c Outdated Show resolved Hide resolved
copydb_schema_name_from_restore_list_name(const char *restoreListName,
char *schemaName)
{
if (!(sscanf(restoreListName, "- %64s %*s", schemaName) == 1)) /* IGNORE-BANNED */
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very hopeful way to parse the restore_list_name. When a schema name includes double-quotes, these characters are escaped by being doubled, so we might have up to 128 characters in a schema name. The schema name might contain a space too. The owner name could contain a space also.

Does this archive Table of Contents line contain the schema OID? if yes, we should probably fill-in a SQLite catalog with the list of all the source schemas and then implement an OID lookup in that internal catalog. The way restore_list_name are built is not machine-parsable in the general case.

Copy link
Contributor Author

@kbarber kbarber Apr 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was worrying about it too.

It completely fails to skips anything with a space, this is a toc sample I was looking at from pre-filtered.list.

;12; 2615 18530 SCHEMA - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcdefghijklmnop fqayuutgtrkspv
;11; 2615 18529 SCHEMA - aabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik fqayuutgtrkspv
13; 2615 18531 SCHEMA - abcdefghijklmnopqrstuv wxyz fqayuutgtrkspv
;10; 2615 18528 SCHEMA - abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik fqayuutgtrkspv

There is the OID there, 18530, 18529, 18531.

So the answer you are describing is: do a lookup on the source catalog for the oids from s_namespace retrieving the nspame and then use that to check if the target has already got that nspname in s_namespace.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lookup should be done in the SQLite catalogs, and for that we need to create and fill-in a new s_namespace catalog table in the sourceDB. Once we have that we can lookup the SCHEMA entries by OID in the sourceDB to fetch the schema name (instead of parsing it from the archive contents), and then we can lookup the schema by name in the target database using what you did already.

So yes what you said, with the explicit caching of the whole pg_namespace catalog from the source database in our internal SQLite catalogs.

Copy link
Contributor Author

@kbarber kbarber Apr 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, thats done now I think. I added s_namepace to target, collected the schemas earlier and now we do a lookup by oid, get the name, then lookup that name. Seems to skip the schemas now with spaces in them:

10:54:06.125 620 NOTICE dump_restore.c:678        Skipping already existing dumpId 12: SCHEMA 18530 - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcdefghijklmnop fqayuutgtrkspv
10:54:06.125 620 NOTICE dump_restore.c:678        Skipping already existing dumpId 11: SCHEMA 18529 - aabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik fqayuutgtrkspv
10:54:06.125 620 NOTICE dump_restore.c:678        Skipping already existing dumpId 13: SCHEMA 18531 - abcdefghijklmnopqrstuv wxyz fqayuutgtrkspv
10:54:06.125 620 NOTICE dump_restore.c:678        Skipping already existing dumpId 10: SCHEMA 18528 - abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik fqayuutgtrkspv
10:54:06.125 620 NOTICE dump_restore.c:678        Skipping already existing dumpId 9: SCHEMA 18105 - foo fqayuutgtrkspv
10:54:06.125 620 NOTICE dump_restore.c:678        Skipping already existing dumpId 7: SCHEMA 17937 - heroku_ext u2sc2mm8l1f6ht
10:54:06.126 620 NOTICE dump_restore.c:678        Skipping already existing dumpId 8: SCHEMA 18104 - public fqayuutgtrkspv

I'm just hitting a bug with the insert now into s_namespace throwing an error in some of our tests, I'll try and track that down.

@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch from 27d9979 to 419ec29 Compare April 16, 2024 09:29
Copy link
Owner

@dimitri dimitri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow. Almost there. I added a nitpick change that I think is necessary, and it looks like the last one needed here in this PR!

Comment on lines 357 to 361
DATA_SECTION_ALL
DATA_SECTION_ALL,
DATA_SECTION_NAMESPACES
} CopyDataSection;

#define DATA_SECTION_COUNT (DATA_SECTION_ALL + 1)
#define DATA_SECTION_COUNT (DATA_SECTION_NAMESPACES + 1)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep DATA_SECTION_ALL as the last entry in the list, and then DATA_SECTION_COUNT definition does not need to change either. I think I would insert DATA_SECTION_NAMESPACES just before DATA_SECTION_TABLE_DATA in the enum.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep easy fix, thanks

@kbarber
Copy link
Contributor Author

kbarber commented Apr 16, 2024

Nice! Thanks for the detective work. I like that you found that we match on schema name and owner and should only match on schema name. About the implementation, see my comments. Is there a way that we can lookup the actual schema name from the schema OID, if we have it, rather than parse the restore list name?

@dimitri okay the code is now retrieving the namespaces for the source catalog, and registering the section as it expects so that commands can be repeated safely. It uses that information to lookup the nspname from source catalog using the oid from the archive list, then uses that name on the target catalog to check if it already exists or not.

Looks like its passing, I modified the test to include schemas with spaces to help with regression.

This removes the non-default schema exclusion code to allow
extensions to be transfered with `clone` without interruption.

We add tests to avoid regression.
@kbarber kbarber force-pushed the pgcopydb_clone_with_extensions_from_different_schemas branch from 76e8e1a to 080ad11 Compare April 16, 2024 12:32
@kbarber
Copy link
Contributor Author

kbarber commented Apr 16, 2024

Wow. Almost there. I added a nitpick change that I think is necessary, and it looks like the last one needed here in this PR!

@dimitri Yeah I was wondering about the ordering myself.

Okay I've fixed that, rebased, squashed and the tests are passing again.

@dimitri
Copy link
Owner

dimitri commented Apr 16, 2024

@dimitri okay the code is now retrieving the namespaces for the source catalog, and registering the section as it expects so that commands can be repeated safely. It uses that information to lookup the nspname from source catalog using the oid from the archive list, then uses that name on the target catalog to check if it already exists or not.

Last round of review now, I think we're only missing registering the cache-invalidation for the namespace list at this place in the code, where I would add the DATA_SECTION_NAMESPACES just before DATA_SECTION_TABLE_DATA:

/* compute "allDone" in the context of a sourceDB */
if (s->section == DATA_SECTION_DATABASE_PROPERTIES ||
s->section == DATA_SECTION_TABLE_DATA ||
s->section == DATA_SECTION_SET_SEQUENCES ||
s->section == DATA_SECTION_INDEXES ||
s->section == DATA_SECTION_CONSTRAINTS)
{
allDone = allDone && s->fetched;
}

Looks like its passing, I modified the test to include schemas with spaces to help with regression.

Thanks for that, that's good thinking!

@dimitri dimitri added the bug Something isn't working label Apr 16, 2024
@dimitri dimitri added this to the v0.16 milestone Apr 16, 2024
@dimitri dimitri merged commit 82c406c into dimitri:main Apr 16, 2024
18 checks passed
@dimitri
Copy link
Owner

dimitri commented Apr 16, 2024

Thanks for all the work @kbarber ; we end-up in a much different place than we started at, with a long way to get there, and the result is much better than what we started with. Now, I believe the other needed PR is going to be much simpler with just adding the SCHEMA in the CREATE EXTENSION command, I'm not sure anything else is needed really.

@kbarber
Copy link
Contributor Author

kbarber commented Apr 16, 2024

Yeah thanks @dimitri it was a lot of fun learning how your tool works. Thanks for your patience with me.

Yes, I imagine the other patch looks very different now, but for now, I'm taking a break and going shopping. Thanks again.

dimitri added a commit that referenced this pull request Apr 17, 2024
@kbarber kbarber deleted the pgcopydb_clone_with_extensions_from_different_schemas branch April 18, 2024 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants