@@ -265,6 +265,9 @@ static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
265
265
const char * objlabel );
266
266
static const char * getAttrName (int attrnum ,TableInfo * tblInfo );
267
267
static const char * fmtCopyColumnList (const TableInfo * ti ,PQExpBuffer buffer );
268
+ static bool nonemptyReloptions (const char * reloptions );
269
+ static void fmtReloptionsArray (Archive * fout ,PQExpBuffer buffer ,
270
+ const char * reloptions ,const char * prefix );
268
271
static char * get_synchronized_snapshot (Archive * fout );
269
272
static PGresult * ExecuteSqlQueryForSingleRow (Archive * fout ,char * query );
270
273
static void setupDumpWorker (Archive * AHX ,RestoreOptions * ropt );
@@ -4295,8 +4298,8 @@ getTables(Archive *fout, int *numTables)
4295
4298
"d.refobjid AS owning_tab, "
4296
4299
"d.refobjsubid AS owning_col, "
4297
4300
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4298
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4299
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4301
+ " c.reloptions AS reloptions, "
4302
+ "tc.reloptions AS toast_reloptions "
4300
4303
"FROM pg_class c "
4301
4304
"LEFT JOIN pg_depend d ON "
4302
4305
"(c.relkind = '%c' AND "
@@ -4333,8 +4336,8 @@ getTables(Archive *fout, int *numTables)
4333
4336
"d.refobjid AS owning_tab, "
4334
4337
"d.refobjsubid AS owning_col, "
4335
4338
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4336
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4337
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4339
+ " c.reloptions AS reloptions, "
4340
+ "tc.reloptions AS toast_reloptions "
4338
4341
"FROM pg_class c "
4339
4342
"LEFT JOIN pg_depend d ON "
4340
4343
"(c.relkind = '%c' AND "
@@ -4371,8 +4374,8 @@ getTables(Archive *fout, int *numTables)
4371
4374
"d.refobjid AS owning_tab, "
4372
4375
"d.refobjsubid AS owning_col, "
4373
4376
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4374
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4375
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4377
+ " c.reloptions AS reloptions, "
4378
+ "tc.reloptions AS toast_reloptions "
4376
4379
"FROM pg_class c "
4377
4380
"LEFT JOIN pg_depend d ON "
4378
4381
"(c.relkind = '%c' AND "
@@ -4408,8 +4411,8 @@ getTables(Archive *fout, int *numTables)
4408
4411
"d.refobjid AS owning_tab, "
4409
4412
"d.refobjsubid AS owning_col, "
4410
4413
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4411
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4412
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4414
+ " c.reloptions AS reloptions, "
4415
+ "tc.reloptions AS toast_reloptions "
4413
4416
"FROM pg_class c "
4414
4417
"LEFT JOIN pg_depend d ON "
4415
4418
"(c.relkind = '%c' AND "
@@ -4445,7 +4448,7 @@ getTables(Archive *fout, int *numTables)
4445
4448
"d.refobjid AS owning_tab, "
4446
4449
"d.refobjsubid AS owning_col, "
4447
4450
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4448
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4451
+ " c.reloptions AS reloptions, "
4449
4452
"NULL AS toast_reloptions "
4450
4453
"FROM pg_class c "
4451
4454
"LEFT JOIN pg_depend d ON "
@@ -4896,7 +4899,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
4896
4899
i_conoid ,
4897
4900
i_condef ,
4898
4901
i_tablespace ,
4899
- i_options ,
4902
+ i_indreloptions ,
4900
4903
i_relpages ;
4901
4904
int ntups ;
4902
4905
@@ -4953,7 +4956,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
4953
4956
"c.oid AS conoid, "
4954
4957
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
4955
4958
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
4956
- "array_to_string( t.reloptions, ', ') ASoptions "
4959
+ " t.reloptions ASindreloptions "
4957
4960
"FROM pg_catalog.pg_index i "
4958
4961
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
4959
4962
"LEFT JOIN pg_catalog.pg_constraint c "
@@ -4980,7 +4983,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
4980
4983
"c.oid AS conoid, "
4981
4984
"null AS condef, "
4982
4985
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
4983
- "array_to_string( t.reloptions, ', ') ASoptions "
4986
+ " t.reloptions ASindreloptions "
4984
4987
"FROM pg_catalog.pg_index i "
4985
4988
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
4986
4989
"LEFT JOIN pg_catalog.pg_depend d "
@@ -5010,7 +5013,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5010
5013
"c.oid AS conoid, "
5011
5014
"null AS condef, "
5012
5015
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5013
- "null ASoptions "
5016
+ "null ASindreloptions "
5014
5017
"FROM pg_catalog.pg_index i "
5015
5018
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5016
5019
"LEFT JOIN pg_catalog.pg_depend d "
@@ -5039,7 +5042,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5039
5042
"c.oid AS conoid, "
5040
5043
"null AS condef, "
5041
5044
"NULL AS tablespace, "
5042
- "null ASoptions "
5045
+ "null ASindreloptions "
5043
5046
"FROM pg_catalog.pg_index i "
5044
5047
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5045
5048
"LEFT JOIN pg_catalog.pg_depend d "
@@ -5071,7 +5074,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5071
5074
"t.oid AS conoid, "
5072
5075
"null AS condef, "
5073
5076
"NULL AS tablespace, "
5074
- "null ASoptions "
5077
+ "null ASindreloptions "
5075
5078
"FROM pg_index i, pg_class t "
5076
5079
"WHERE t.oid = i.indexrelid "
5077
5080
"AND i.indrelid = '%u'::oid "
@@ -5098,7 +5101,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5098
5101
"t.oid AS conoid, "
5099
5102
"null AS condef, "
5100
5103
"NULL AS tablespace, "
5101
- "null ASoptions "
5104
+ "null ASindreloptions "
5102
5105
"FROM pg_index i, pg_class t "
5103
5106
"WHERE t.oid = i.indexrelid "
5104
5107
"AND i.indrelid = '%u'::oid "
@@ -5126,7 +5129,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5126
5129
i_conoid = PQfnumber (res ,"conoid" );
5127
5130
i_condef = PQfnumber (res ,"condef" );
5128
5131
i_tablespace = PQfnumber (res ,"tablespace" );
5129
- i_options = PQfnumber (res ,"options " );
5132
+ i_indreloptions = PQfnumber (res ,"indreloptions " );
5130
5133
5131
5134
indxinfo = (IndxInfo * )pg_malloc (ntups * sizeof (IndxInfo ));
5132
5135
constrinfo = (ConstraintInfo * )pg_malloc (ntups * sizeof (ConstraintInfo ));
@@ -5145,7 +5148,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5145
5148
indxinfo [j ].indexdef = pg_strdup (PQgetvalue (res ,j ,i_indexdef ));
5146
5149
indxinfo [j ].indnkeys = atoi (PQgetvalue (res ,j ,i_indnkeys ));
5147
5150
indxinfo [j ].tablespace = pg_strdup (PQgetvalue (res ,j ,i_tablespace ));
5148
- indxinfo [j ].options = pg_strdup (PQgetvalue (res ,j ,i_options ));
5151
+ indxinfo [j ].indreloptions = pg_strdup (PQgetvalue (res ,j ,i_indreloptions ));
5149
5152
5150
5153
/*
5151
5154
* In pre-7.4 releases, indkeys may contain more entries than
@@ -12896,8 +12899,12 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
12896
12899
tbinfo -> dobj .catId .oid , false);
12897
12900
12898
12901
appendPQExpBuffer (q ,"CREATE VIEW %s" ,fmtId (tbinfo -> dobj .name ));
12899
- if (tbinfo -> reloptions && strlen (tbinfo -> reloptions )> 0 )
12900
- appendPQExpBuffer (q ," WITH (%s)" ,tbinfo -> reloptions );
12902
+ if (nonemptyReloptions (tbinfo -> reloptions ))
12903
+ {
12904
+ appendPQExpBufferStr (q ," WITH (" );
12905
+ fmtReloptionsArray (fout ,q ,tbinfo -> reloptions ,"" );
12906
+ appendPQExpBufferChar (q ,')' );
12907
+ }
12901
12908
result = createViewAsClause (fout ,tbinfo );
12902
12909
appendPQExpBuffer (q ," AS\n%s;\n" ,result -> data );
12903
12910
destroyPQExpBuffer (result );
@@ -13140,23 +13147,24 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
13140
13147
appendPQExpBuffer (q ,"\nSERVER %s" ,fmtId (srvname ));
13141
13148
}
13142
13149
13143
- if ((tbinfo -> reloptions && strlen ( tbinfo -> reloptions ) > 0 )||
13144
- (tbinfo -> toast_reloptions && strlen ( tbinfo -> toast_reloptions ) > 0 ))
13150
+ if (nonemptyReloptions (tbinfo -> reloptions )||
13151
+ nonemptyReloptions (tbinfo -> toast_reloptions ))
13145
13152
{
13146
13153
bool addcomma = false;
13147
13154
13148
- appendPQExpBuffer (q ,"\nWITH (" );
13149
- if (tbinfo -> reloptions && strlen (tbinfo -> reloptions )> 0 )
13155
+ appendPQExpBufferStr (q ,"\nWITH (" );
13156
+ if (nonemptyReloptions (tbinfo -> reloptions ))
13150
13157
{
13151
13158
addcomma = true;
13152
- appendPQExpBuffer ( q , "%s" ,tbinfo -> reloptions );
13159
+ fmtReloptionsArray ( fout , q ,tbinfo -> reloptions , "" );
13153
13160
}
13154
- if (tbinfo -> toast_reloptions && strlen (tbinfo -> toast_reloptions )> 0 )
13161
+ if (nonemptyReloptions (tbinfo -> toast_reloptions ))
13155
13162
{
13156
- appendPQExpBuffer (q ,"%s%s" ,addcomma ?", " :"" ,
13157
- tbinfo -> toast_reloptions );
13163
+ if (addcomma )
13164
+ appendPQExpBufferStr (q ,", " );
13165
+ fmtReloptionsArray (fout ,q ,tbinfo -> toast_reloptions ,"toast." );
13158
13166
}
13159
- appendPQExpBuffer (q ,")" );
13167
+ appendPQExpBufferChar (q ,')' );
13160
13168
}
13161
13169
13162
13170
/* Dump generic options if any */
@@ -13697,8 +13705,12 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
13697
13705
13698
13706
appendPQExpBuffer (q ,")" );
13699
13707
13700
- if (indxinfo -> options && strlen (indxinfo -> options )> 0 )
13701
- appendPQExpBuffer (q ," WITH (%s)" ,indxinfo -> options );
13708
+ if (nonemptyReloptions (indxinfo -> indreloptions ))
13709
+ {
13710
+ appendPQExpBufferStr (q ," WITH (" );
13711
+ fmtReloptionsArray (fout ,q ,indxinfo -> indreloptions ,"" );
13712
+ appendPQExpBufferChar (q ,')' );
13713
+ }
13702
13714
13703
13715
if (coninfo -> condeferrable )
13704
13716
{
@@ -14558,11 +14570,12 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
14558
14570
/*
14559
14571
* Apply view's reloptions when its ON SELECT rule is separate.
14560
14572
*/
14561
- if (rinfo -> reloptions && strlen (rinfo -> reloptions )> 0 )
14573
+ if (nonemptyReloptions (rinfo -> reloptions ))
14562
14574
{
14563
- appendPQExpBuffer (cmd ,"ALTER VIEW %s SET (%s);\n" ,
14564
- fmtId (tbinfo -> dobj .name ),
14565
- rinfo -> reloptions );
14575
+ appendPQExpBuffer (cmd ,"ALTER VIEW %s SET (" ,
14576
+ fmtId (tbinfo -> dobj .name ));
14577
+ fmtReloptionsArray (fout ,cmd ,rinfo -> reloptions ,"" );
14578
+ appendPQExpBufferStr (cmd ,");\n" );
14566
14579
}
14567
14580
14568
14581
/*
@@ -15432,6 +15445,83 @@ fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer)
15432
15445
return buffer -> data ;
15433
15446
}
15434
15447
15448
+ /*
15449
+ * Check if a reloptions array is nonempty.
15450
+ */
15451
+ static bool
15452
+ nonemptyReloptions (const char * reloptions )
15453
+ {
15454
+ /* Don't want to print it if it's just "{}" */
15455
+ return (reloptions != NULL && strlen (reloptions )> 2 );
15456
+ }
15457
+
15458
+ /*
15459
+ * Format a reloptions array and append it to the given buffer.
15460
+ *
15461
+ * "prefix" is prepended to the option names; typically it's "" or "toast.".
15462
+ *
15463
+ * Note: this logic should generally match the backend's flatten_reloptions()
15464
+ * (in adt/ruleutils.c).
15465
+ */
15466
+ static void
15467
+ fmtReloptionsArray (Archive * fout ,PQExpBuffer buffer ,const char * reloptions ,
15468
+ const char * prefix )
15469
+ {
15470
+ char * * options ;
15471
+ int noptions ;
15472
+ int i ;
15473
+
15474
+ if (!parsePGArray (reloptions ,& options ,& noptions ))
15475
+ {
15476
+ write_msg (NULL ,"WARNING: could not parse reloptions array\n" );
15477
+ if (options )
15478
+ free (options );
15479
+ return ;
15480
+ }
15481
+
15482
+ for (i = 0 ;i < noptions ;i ++ )
15483
+ {
15484
+ char * option = options [i ];
15485
+ char * name ;
15486
+ char * separator ;
15487
+ char * value ;
15488
+
15489
+ /*
15490
+ * Each array element should have the form name=value. If the "=" is
15491
+ * missing for some reason, treat it like an empty value.
15492
+ */
15493
+ name = option ;
15494
+ separator = strchr (option ,'=' );
15495
+ if (separator )
15496
+ {
15497
+ * separator = '\0' ;
15498
+ value = separator + 1 ;
15499
+ }
15500
+ else
15501
+ value = "" ;
15502
+
15503
+ if (i > 0 )
15504
+ appendPQExpBufferStr (buffer ,", " );
15505
+ appendPQExpBuffer (buffer ,"%s%s=" ,prefix ,fmtId (name ));
15506
+
15507
+ /*
15508
+ * In general we need to quote the value; but to avoid unnecessary
15509
+ * clutter, do not quote if it is an identifier that would not need
15510
+ * quoting. (We could also allow numbers, but that is a bit trickier
15511
+ * than it looks --- for example, are leading zeroes significant? We
15512
+ * don't want to assume very much here about what custom reloptions
15513
+ * might mean.)
15514
+ */
15515
+ if (strcmp (fmtId (value ),value )== 0 )
15516
+ appendPQExpBufferStr (buffer ,value );
15517
+ else
15518
+ appendStringLiteralAH (buffer ,value ,fout );
15519
+ }
15520
+
15521
+ if (options )
15522
+ free (options );
15523
+ }
15524
+
15435
15525
/*
15436
15526
* Execute an SQL query and verify that we got exactly one row back.
15437
15527
*/