@@ -251,6 +251,9 @@ static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
251
251
const char * objlabel );
252
252
static const char * getAttrName (int attrnum ,TableInfo * tblInfo );
253
253
static const char * fmtCopyColumnList (const TableInfo * ti ,PQExpBuffer buffer );
254
+ static bool nonemptyReloptions (const char * reloptions );
255
+ static void fmtReloptionsArray (Archive * fout ,PQExpBuffer buffer ,
256
+ const char * reloptions ,const char * prefix );
254
257
static char * get_synchronized_snapshot (Archive * fout );
255
258
static PGresult * ExecuteSqlQueryForSingleRow (Archive * fout ,char * query );
256
259
static void setupDumpWorker (Archive * AHX ,DumpOptions * dopt ,RestoreOptions * ropt );
@@ -4585,10 +4588,10 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
4585
4588
"d.refobjid AS owning_tab, "
4586
4589
"d.refobjsubid AS owning_col, "
4587
4590
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4588
- "array_to_string( array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded'), ', ') AS reloptions, "
4591
+ "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
4589
4592
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
4590
4593
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
4591
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4594
+ "tc.reloptions AS toast_reloptions "
4592
4595
"FROM pg_class c "
4593
4596
"LEFT JOIN pg_depend d ON "
4594
4597
"(c.relkind = '%c' AND "
@@ -4627,10 +4630,10 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
4627
4630
"d.refobjid AS owning_tab, "
4628
4631
"d.refobjsubid AS owning_col, "
4629
4632
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4630
- "array_to_string( array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded'), ', ') AS reloptions, "
4633
+ "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
4631
4634
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
4632
4635
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
4633
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4636
+ "tc.reloptions AS toast_reloptions "
4634
4637
"FROM pg_class c "
4635
4638
"LEFT JOIN pg_depend d ON "
4636
4639
"(c.relkind = '%c' AND "
@@ -4669,10 +4672,10 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
4669
4672
"d.refobjid AS owning_tab, "
4670
4673
"d.refobjsubid AS owning_col, "
4671
4674
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4672
- "array_to_string( array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded'), ', ') AS reloptions, "
4675
+ "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
4673
4676
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
4674
4677
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
4675
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4678
+ "tc.reloptions AS toast_reloptions "
4676
4679
"FROM pg_class c "
4677
4680
"LEFT JOIN pg_depend d ON "
4678
4681
"(c.relkind = '%c' AND "
@@ -4711,8 +4714,8 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
4711
4714
"d.refobjid AS owning_tab, "
4712
4715
"d.refobjsubid AS owning_col, "
4713
4716
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4714
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4715
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4717
+ " c.reloptions AS reloptions, "
4718
+ "tc.reloptions AS toast_reloptions "
4716
4719
"FROM pg_class c "
4717
4720
"LEFT JOIN pg_depend d ON "
4718
4721
"(c.relkind = '%c' AND "
@@ -4751,8 +4754,8 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
4751
4754
"d.refobjid AS owning_tab, "
4752
4755
"d.refobjsubid AS owning_col, "
4753
4756
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4754
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4755
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4757
+ " c.reloptions AS reloptions, "
4758
+ "tc.reloptions AS toast_reloptions "
4756
4759
"FROM pg_class c "
4757
4760
"LEFT JOIN pg_depend d ON "
4758
4761
"(c.relkind = '%c' AND "
@@ -4790,8 +4793,8 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
4790
4793
"d.refobjid AS owning_tab, "
4791
4794
"d.refobjsubid AS owning_col, "
4792
4795
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4793
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4794
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4796
+ " c.reloptions AS reloptions, "
4797
+ "tc.reloptions AS toast_reloptions "
4795
4798
"FROM pg_class c "
4796
4799
"LEFT JOIN pg_depend d ON "
4797
4800
"(c.relkind = '%c' AND "
@@ -4829,7 +4832,7 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
4829
4832
"d.refobjid AS owning_tab, "
4830
4833
"d.refobjsubid AS owning_col, "
4831
4834
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4832
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4835
+ " c.reloptions AS reloptions, "
4833
4836
"NULL AS toast_reloptions "
4834
4837
"FROM pg_class c "
4835
4838
"LEFT JOIN pg_depend d ON "
@@ -5302,7 +5305,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5302
5305
i_conoid ,
5303
5306
i_condef ,
5304
5307
i_tablespace ,
5305
- i_options ,
5308
+ i_indreloptions ,
5306
5309
i_relpages ;
5307
5310
int ntups ;
5308
5311
@@ -5360,7 +5363,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5360
5363
"c.oid AS conoid, "
5361
5364
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
5362
5365
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5363
- "array_to_string( t.reloptions, ', ') ASoptions "
5366
+ " t.reloptions ASindreloptions "
5364
5367
"FROM pg_catalog.pg_index i "
5365
5368
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5366
5369
"LEFT JOIN pg_catalog.pg_constraint c "
@@ -5391,7 +5394,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5391
5394
"c.oid AS conoid, "
5392
5395
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
5393
5396
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5394
- "array_to_string( t.reloptions, ', ') ASoptions "
5397
+ " t.reloptions ASindreloptions "
5395
5398
"FROM pg_catalog.pg_index i "
5396
5399
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5397
5400
"LEFT JOIN pg_catalog.pg_constraint c "
@@ -5418,7 +5421,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5418
5421
"c.oid AS conoid, "
5419
5422
"null AS condef, "
5420
5423
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5421
- "array_to_string( t.reloptions, ', ') ASoptions "
5424
+ " t.reloptions ASindreloptions "
5422
5425
"FROM pg_catalog.pg_index i "
5423
5426
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5424
5427
"LEFT JOIN pg_catalog.pg_depend d "
@@ -5448,7 +5451,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5448
5451
"c.oid AS conoid, "
5449
5452
"null AS condef, "
5450
5453
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5451
- "null ASoptions "
5454
+ "null ASindreloptions "
5452
5455
"FROM pg_catalog.pg_index i "
5453
5456
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5454
5457
"LEFT JOIN pg_catalog.pg_depend d "
@@ -5477,7 +5480,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5477
5480
"c.oid AS conoid, "
5478
5481
"null AS condef, "
5479
5482
"NULL AS tablespace, "
5480
- "null ASoptions "
5483
+ "null ASindreloptions "
5481
5484
"FROM pg_catalog.pg_index i "
5482
5485
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5483
5486
"LEFT JOIN pg_catalog.pg_depend d "
@@ -5509,7 +5512,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5509
5512
"t.oid AS conoid, "
5510
5513
"null AS condef, "
5511
5514
"NULL AS tablespace, "
5512
- "null ASoptions "
5515
+ "null ASindreloptions "
5513
5516
"FROM pg_index i, pg_class t "
5514
5517
"WHERE t.oid = i.indexrelid "
5515
5518
"AND i.indrelid = '%u'::oid "
@@ -5536,7 +5539,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5536
5539
"t.oid AS conoid, "
5537
5540
"null AS condef, "
5538
5541
"NULL AS tablespace, "
5539
- "null ASoptions "
5542
+ "null ASindreloptions "
5540
5543
"FROM pg_index i, pg_class t "
5541
5544
"WHERE t.oid = i.indexrelid "
5542
5545
"AND i.indrelid = '%u'::oid "
@@ -5565,7 +5568,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5565
5568
i_conoid = PQfnumber (res ,"conoid" );
5566
5569
i_condef = PQfnumber (res ,"condef" );
5567
5570
i_tablespace = PQfnumber (res ,"tablespace" );
5568
- i_options = PQfnumber (res ,"options " );
5571
+ i_indreloptions = PQfnumber (res ,"indreloptions " );
5569
5572
5570
5573
indxinfo = (IndxInfo * )pg_malloc (ntups * sizeof (IndxInfo ));
5571
5574
constrinfo = (ConstraintInfo * )pg_malloc (ntups * sizeof (ConstraintInfo ));
@@ -5584,7 +5587,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5584
5587
indxinfo [j ].indexdef = pg_strdup (PQgetvalue (res ,j ,i_indexdef ));
5585
5588
indxinfo [j ].indnkeys = atoi (PQgetvalue (res ,j ,i_indnkeys ));
5586
5589
indxinfo [j ].tablespace = pg_strdup (PQgetvalue (res ,j ,i_tablespace ));
5587
- indxinfo [j ].options = pg_strdup (PQgetvalue (res ,j ,i_options ));
5590
+ indxinfo [j ].indreloptions = pg_strdup (PQgetvalue (res ,j ,i_indreloptions ));
5588
5591
5589
5592
/*
5590
5593
* In pre-7.4 releases, indkeys may contain more entries than
@@ -13810,8 +13813,12 @@ dumpTableSchema(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
13810
13813
tbinfo -> dobj .catId .oid , false);
13811
13814
13812
13815
appendPQExpBuffer (q ,"CREATE VIEW %s" ,fmtId (tbinfo -> dobj .name ));
13813
- if (tbinfo -> reloptions && strlen (tbinfo -> reloptions )> 0 )
13814
- appendPQExpBuffer (q ," WITH (%s)" ,tbinfo -> reloptions );
13816
+ if (nonemptyReloptions (tbinfo -> reloptions ))
13817
+ {
13818
+ appendPQExpBufferStr (q ," WITH (" );
13819
+ fmtReloptionsArray (fout ,q ,tbinfo -> reloptions ,"" );
13820
+ appendPQExpBufferChar (q ,')' );
13821
+ }
13815
13822
result = createViewAsClause (fout ,tbinfo );
13816
13823
appendPQExpBuffer (q ," AS\n%s" ,result -> data );
13817
13824
destroyPQExpBuffer (result );
@@ -14055,21 +14062,22 @@ dumpTableSchema(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
14055
14062
appendPQExpBuffer (q ,"\nSERVER %s" ,fmtId (srvname ));
14056
14063
}
14057
14064
14058
- if ((tbinfo -> reloptions && strlen ( tbinfo -> reloptions ) > 0 )||
14059
- (tbinfo -> toast_reloptions && strlen ( tbinfo -> toast_reloptions ) > 0 ))
14065
+ if (nonemptyReloptions (tbinfo -> reloptions )||
14066
+ nonemptyReloptions (tbinfo -> toast_reloptions ))
14060
14067
{
14061
14068
bool addcomma = false;
14062
14069
14063
14070
appendPQExpBufferStr (q ,"\nWITH (" );
14064
- if (tbinfo -> reloptions && strlen (tbinfo -> reloptions )> 0 )
14071
+ if (nonemptyReloptions (tbinfo -> reloptions ))
14065
14072
{
14066
14073
addcomma = true;
14067
- appendPQExpBufferStr ( q ,tbinfo -> reloptions );
14074
+ fmtReloptionsArray ( fout , q ,tbinfo -> reloptions , "" );
14068
14075
}
14069
- if (tbinfo -> toast_reloptions && strlen (tbinfo -> toast_reloptions )> 0 )
14076
+ if (nonemptyReloptions (tbinfo -> toast_reloptions ))
14070
14077
{
14071
- appendPQExpBuffer (q ,"%s%s" ,addcomma ?", " :"" ,
14072
- tbinfo -> toast_reloptions );
14078
+ if (addcomma )
14079
+ appendPQExpBufferStr (q ,", " );
14080
+ fmtReloptionsArray (fout ,q ,tbinfo -> toast_reloptions ,"toast." );
14073
14081
}
14074
14082
appendPQExpBufferChar (q ,')' );
14075
14083
}
@@ -14651,8 +14659,12 @@ dumpConstraint(Archive *fout, DumpOptions *dopt, ConstraintInfo *coninfo)
14651
14659
14652
14660
appendPQExpBufferChar (q ,')' );
14653
14661
14654
- if (indxinfo -> options && strlen (indxinfo -> options )> 0 )
14655
- appendPQExpBuffer (q ," WITH (%s)" ,indxinfo -> options );
14662
+ if (nonemptyReloptions (indxinfo -> indreloptions ))
14663
+ {
14664
+ appendPQExpBufferStr (q ," WITH (" );
14665
+ fmtReloptionsArray (fout ,q ,indxinfo -> indreloptions ,"" );
14666
+ appendPQExpBufferChar (q ,')' );
14667
+ }
14656
14668
14657
14669
if (coninfo -> condeferrable )
14658
14670
{
@@ -15512,11 +15524,12 @@ dumpRule(Archive *fout, DumpOptions *dopt, RuleInfo *rinfo)
15512
15524
/*
15513
15525
* Apply view's reloptions when its ON SELECT rule is separate.
15514
15526
*/
15515
- if (rinfo -> reloptions && strlen (rinfo -> reloptions )> 0 )
15527
+ if (nonemptyReloptions (rinfo -> reloptions ))
15516
15528
{
15517
- appendPQExpBuffer (cmd ,"ALTER VIEW %s SET (%s);\n" ,
15518
- fmtId (tbinfo -> dobj .name ),
15519
- rinfo -> reloptions );
15529
+ appendPQExpBuffer (cmd ,"ALTER VIEW %s SET (" ,
15530
+ fmtId (tbinfo -> dobj .name ));
15531
+ fmtReloptionsArray (fout ,cmd ,rinfo -> reloptions ,"" );
15532
+ appendPQExpBufferStr (cmd ,");\n" );
15520
15533
}
15521
15534
15522
15535
/*
@@ -16389,6 +16402,83 @@ fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer)
16389
16402
return buffer -> data ;
16390
16403
}
16391
16404
16405
+ /*
16406
+ * Check if a reloptions array is nonempty.
16407
+ */
16408
+ static bool
16409
+ nonemptyReloptions (const char * reloptions )
16410
+ {
16411
+ /* Don't want to print it if it's just "{}" */
16412
+ return (reloptions != NULL && strlen (reloptions )> 2 );
16413
+ }
16414
+
16415
+ /*
16416
+ * Format a reloptions array and append it to the given buffer.
16417
+ *
16418
+ * "prefix" is prepended to the option names; typically it's "" or "toast.".
16419
+ *
16420
+ * Note: this logic should generally match the backend's flatten_reloptions()
16421
+ * (in adt/ruleutils.c).
16422
+ */
16423
+ static void
16424
+ fmtReloptionsArray (Archive * fout ,PQExpBuffer buffer ,const char * reloptions ,
16425
+ const char * prefix )
16426
+ {
16427
+ char * * options ;
16428
+ int noptions ;
16429
+ int i ;
16430
+
16431
+ if (!parsePGArray (reloptions ,& options ,& noptions ))
16432
+ {
16433
+ write_msg (NULL ,"WARNING: could not parse reloptions array\n" );
16434
+ if (options )
16435
+ free (options );
16436
+ return ;
16437
+ }
16438
+
16439
+ for (i = 0 ;i < noptions ;i ++ )
16440
+ {
16441
+ char * option = options [i ];
16442
+ char * name ;
16443
+ char * separator ;
16444
+ char * value ;
16445
+
16446
+ /*
16447
+ * Each array element should have the form name=value. If the "=" is
16448
+ * missing for some reason, treat it like an empty value.
16449
+ */
16450
+ name = option ;
16451
+ separator = strchr (option ,'=' );
16452
+ if (separator )
16453
+ {
16454
+ * separator = '\0' ;
16455
+ value = separator + 1 ;
16456
+ }
16457
+ else
16458
+ value = "" ;
16459
+
16460
+ if (i > 0 )
16461
+ appendPQExpBufferStr (buffer ,", " );
16462
+ appendPQExpBuffer (buffer ,"%s%s=" ,prefix ,fmtId (name ));
16463
+
16464
+ /*
16465
+ * In general we need to quote the value; but to avoid unnecessary
16466
+ * clutter, do not quote if it is an identifier that would not need
16467
+ * quoting. (We could also allow numbers, but that is a bit trickier
16468
+ * than it looks --- for example, are leading zeroes significant? We
16469
+ * don't want to assume very much here about what custom reloptions
16470
+ * might mean.)
16471
+ */
16472
+ if (strcmp (fmtId (value ),value )== 0 )
16473
+ appendPQExpBufferStr (buffer ,value );
16474
+ else
16475
+ appendStringLiteralAH (buffer ,value ,fout );
16476
+ }
16477
+
16478
+ if (options )
16479
+ free (options );
16480
+ }
16481
+
16392
16482
/*
16393
16483
* Execute an SQL query and verify that we got exactly one row back.
16394
16484
*/