@@ -263,6 +263,9 @@ static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
263
263
const char * objlabel );
264
264
static const char * getAttrName (int attrnum , TableInfo * tblInfo );
265
265
static const char * fmtCopyColumnList (const TableInfo * ti , PQExpBuffer buffer );
266
+ static bool nonemptyReloptions (const char * reloptions );
267
+ static void fmtReloptionsArray (Archive * fout , PQExpBuffer buffer ,
268
+ const char * reloptions , const char * prefix );
266
269
static char * get_synchronized_snapshot (Archive * fout );
267
270
static PGresult * ExecuteSqlQueryForSingleRow (Archive * fout , char * query );
268
271
static void setupDumpWorker (Archive * AHX , RestoreOptions * ropt );
@@ -4336,10 +4339,10 @@ getTables(Archive *fout, int *numTables)
4336
4339
"d.refobjid AS owning_tab, "
4337
4340
"d.refobjsubid AS owning_col, "
4338
4341
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4339
- "array_to_string( array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded'), ', ') AS reloptions, "
4342
+ "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
4340
4343
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
4341
4344
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
4342
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4345
+ "tc.reloptions AS toast_reloptions "
4343
4346
"FROM pg_class c "
4344
4347
"LEFT JOIN pg_depend d ON "
4345
4348
"(c.relkind = '%c' AND "
@@ -4376,10 +4379,10 @@ getTables(Archive *fout, int *numTables)
4376
4379
"d.refobjid AS owning_tab, "
4377
4380
"d.refobjsubid AS owning_col, "
4378
4381
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4379
- "array_to_string( array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded'), ', ') AS reloptions, "
4382
+ "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
4380
4383
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
4381
4384
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
4382
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4385
+ "tc.reloptions AS toast_reloptions "
4383
4386
"FROM pg_class c "
4384
4387
"LEFT JOIN pg_depend d ON "
4385
4388
"(c.relkind = '%c' AND "
@@ -4416,8 +4419,8 @@ getTables(Archive *fout, int *numTables)
4416
4419
"d.refobjid AS owning_tab, "
4417
4420
"d.refobjsubid AS owning_col, "
4418
4421
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4419
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4420
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4422
+ " c.reloptions AS reloptions, "
4423
+ "tc.reloptions AS toast_reloptions "
4421
4424
"FROM pg_class c "
4422
4425
"LEFT JOIN pg_depend d ON "
4423
4426
"(c.relkind = '%c' AND "
@@ -4454,8 +4457,8 @@ getTables(Archive *fout, int *numTables)
4454
4457
"d.refobjid AS owning_tab, "
4455
4458
"d.refobjsubid AS owning_col, "
4456
4459
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4457
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4458
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4460
+ " c.reloptions AS reloptions, "
4461
+ "tc.reloptions AS toast_reloptions "
4459
4462
"FROM pg_class c "
4460
4463
"LEFT JOIN pg_depend d ON "
4461
4464
"(c.relkind = '%c' AND "
@@ -4491,8 +4494,8 @@ getTables(Archive *fout, int *numTables)
4491
4494
"d.refobjid AS owning_tab, "
4492
4495
"d.refobjsubid AS owning_col, "
4493
4496
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4494
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4495
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4497
+ " c.reloptions AS reloptions, "
4498
+ "tc.reloptions AS toast_reloptions "
4496
4499
"FROM pg_class c "
4497
4500
"LEFT JOIN pg_depend d ON "
4498
4501
"(c.relkind = '%c' AND "
@@ -4528,7 +4531,7 @@ getTables(Archive *fout, int *numTables)
4528
4531
"d.refobjid AS owning_tab, "
4529
4532
"d.refobjsubid AS owning_col, "
4530
4533
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4531
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4534
+ " c.reloptions AS reloptions, "
4532
4535
"NULL AS toast_reloptions "
4533
4536
"FROM pg_class c "
4534
4537
"LEFT JOIN pg_depend d ON "
@@ -4987,7 +4990,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
4987
4990
i_conoid ,
4988
4991
i_condef ,
4989
4992
i_tablespace ,
4990
- i_options ,
4993
+ i_indreloptions ,
4991
4994
i_relpages ;
4992
4995
int ntups ;
4993
4996
@@ -5044,7 +5047,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5044
5047
"c.oid AS conoid, "
5045
5048
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
5046
5049
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5047
- "array_to_string( t.reloptions, ', ') AS options "
5050
+ " t.reloptions AS indreloptions "
5048
5051
"FROM pg_catalog.pg_index i "
5049
5052
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5050
5053
"LEFT JOIN pg_catalog.pg_constraint c "
@@ -5075,7 +5078,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5075
5078
"c.oid AS conoid, "
5076
5079
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
5077
5080
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5078
- "array_to_string( t.reloptions, ', ') AS options "
5081
+ " t.reloptions AS indreloptions "
5079
5082
"FROM pg_catalog.pg_index i "
5080
5083
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5081
5084
"LEFT JOIN pg_catalog.pg_constraint c "
@@ -5102,7 +5105,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5102
5105
"c.oid AS conoid, "
5103
5106
"null AS condef, "
5104
5107
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5105
- "array_to_string( t.reloptions, ', ') AS options "
5108
+ " t.reloptions AS indreloptions "
5106
5109
"FROM pg_catalog.pg_index i "
5107
5110
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5108
5111
"LEFT JOIN pg_catalog.pg_depend d "
@@ -5132,7 +5135,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5132
5135
"c.oid AS conoid, "
5133
5136
"null AS condef, "
5134
5137
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5135
- "null AS options "
5138
+ "null AS indreloptions "
5136
5139
"FROM pg_catalog.pg_index i "
5137
5140
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5138
5141
"LEFT JOIN pg_catalog.pg_depend d "
@@ -5161,7 +5164,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5161
5164
"c.oid AS conoid, "
5162
5165
"null AS condef, "
5163
5166
"NULL AS tablespace, "
5164
- "null AS options "
5167
+ "null AS indreloptions "
5165
5168
"FROM pg_catalog.pg_index i "
5166
5169
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
5167
5170
"LEFT JOIN pg_catalog.pg_depend d "
@@ -5193,7 +5196,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5193
5196
"t.oid AS conoid, "
5194
5197
"null AS condef, "
5195
5198
"NULL AS tablespace, "
5196
- "null AS options "
5199
+ "null AS indreloptions "
5197
5200
"FROM pg_index i, pg_class t "
5198
5201
"WHERE t.oid = i.indexrelid "
5199
5202
"AND i.indrelid = '%u'::oid "
@@ -5220,7 +5223,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5220
5223
"t.oid AS conoid, "
5221
5224
"null AS condef, "
5222
5225
"NULL AS tablespace, "
5223
- "null AS options "
5226
+ "null AS indreloptions "
5224
5227
"FROM pg_index i, pg_class t "
5225
5228
"WHERE t.oid = i.indexrelid "
5226
5229
"AND i.indrelid = '%u'::oid "
@@ -5249,7 +5252,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5249
5252
i_conoid = PQfnumber (res , "conoid" );
5250
5253
i_condef = PQfnumber (res , "condef" );
5251
5254
i_tablespace = PQfnumber (res , "tablespace" );
5252
- i_options = PQfnumber (res , "options " );
5255
+ i_indreloptions = PQfnumber (res , "indreloptions " );
5253
5256
5254
5257
indxinfo = (IndxInfo * ) pg_malloc (ntups * sizeof (IndxInfo ));
5255
5258
constrinfo = (ConstraintInfo * ) pg_malloc (ntups * sizeof (ConstraintInfo ));
@@ -5268,7 +5271,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
5268
5271
indxinfo [j ].indexdef = pg_strdup (PQgetvalue (res , j , i_indexdef ));
5269
5272
indxinfo [j ].indnkeys = atoi (PQgetvalue (res , j , i_indnkeys ));
5270
5273
indxinfo [j ].tablespace = pg_strdup (PQgetvalue (res , j , i_tablespace ));
5271
- indxinfo [j ].options = pg_strdup (PQgetvalue (res , j , i_options ));
5274
+ indxinfo [j ].indreloptions = pg_strdup (PQgetvalue (res , j , i_indreloptions ));
5272
5275
5273
5276
/*
5274
5277
* In pre-7.4 releases, indkeys may contain more entries than
@@ -13201,8 +13204,12 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
13201
13204
tbinfo -> dobj .catId .oid , false);
13202
13205
13203
13206
appendPQExpBuffer (q , "CREATE VIEW %s" , fmtId (tbinfo -> dobj .name ));
13204
- if (tbinfo -> reloptions && strlen (tbinfo -> reloptions ) > 0 )
13205
- appendPQExpBuffer (q , " WITH (%s)" , tbinfo -> reloptions );
13207
+ if (nonemptyReloptions (tbinfo -> reloptions ))
13208
+ {
13209
+ appendPQExpBufferStr (q , " WITH (" );
13210
+ fmtReloptionsArray (fout , q , tbinfo -> reloptions , "" );
13211
+ appendPQExpBufferChar (q , ')' );
13212
+ }
13206
13213
result = createViewAsClause (fout , tbinfo );
13207
13214
appendPQExpBuffer (q , " AS\n%s" , result -> data );
13208
13215
destroyPQExpBuffer (result );
@@ -13446,21 +13453,22 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
13446
13453
appendPQExpBuffer (q , "\nSERVER %s" , fmtId (srvname ));
13447
13454
}
13448
13455
13449
- if ((tbinfo -> reloptions && strlen ( tbinfo -> reloptions ) > 0 ) ||
13450
- (tbinfo -> toast_reloptions && strlen ( tbinfo -> toast_reloptions ) > 0 ))
13456
+ if (nonemptyReloptions (tbinfo -> reloptions ) ||
13457
+ nonemptyReloptions (tbinfo -> toast_reloptions ))
13451
13458
{
13452
13459
bool addcomma = false;
13453
13460
13454
13461
appendPQExpBufferStr (q , "\nWITH (" );
13455
- if (tbinfo -> reloptions && strlen (tbinfo -> reloptions ) > 0 )
13462
+ if (nonemptyReloptions (tbinfo -> reloptions ))
13456
13463
{
13457
13464
addcomma = true;
13458
- appendPQExpBufferStr ( q , tbinfo -> reloptions );
13465
+ fmtReloptionsArray ( fout , q , tbinfo -> reloptions , "" );
13459
13466
}
13460
- if (tbinfo -> toast_reloptions && strlen (tbinfo -> toast_reloptions ) > 0 )
13467
+ if (nonemptyReloptions (tbinfo -> toast_reloptions ))
13461
13468
{
13462
- appendPQExpBuffer (q , "%s%s" , addcomma ? ", " : "" ,
13463
- tbinfo -> toast_reloptions );
13469
+ if (addcomma )
13470
+ appendPQExpBufferStr (q , ", " );
13471
+ fmtReloptionsArray (fout , q , tbinfo -> toast_reloptions , "toast." );
13464
13472
}
13465
13473
appendPQExpBufferChar (q , ')' );
13466
13474
}
@@ -14034,8 +14042,12 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
14034
14042
14035
14043
appendPQExpBufferChar (q , ')' );
14036
14044
14037
- if (indxinfo -> options && strlen (indxinfo -> options ) > 0 )
14038
- appendPQExpBuffer (q , " WITH (%s)" , indxinfo -> options );
14045
+ if (nonemptyReloptions (indxinfo -> indreloptions ))
14046
+ {
14047
+ appendPQExpBufferStr (q , " WITH (" );
14048
+ fmtReloptionsArray (fout , q , indxinfo -> indreloptions , "" );
14049
+ appendPQExpBufferChar (q , ')' );
14050
+ }
14039
14051
14040
14052
if (coninfo -> condeferrable )
14041
14053
{
@@ -14895,11 +14907,12 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
14895
14907
/*
14896
14908
* Apply view's reloptions when its ON SELECT rule is separate.
14897
14909
*/
14898
- if (rinfo -> reloptions && strlen (rinfo -> reloptions ) > 0 )
14910
+ if (nonemptyReloptions (rinfo -> reloptions ))
14899
14911
{
14900
- appendPQExpBuffer (cmd , "ALTER VIEW %s SET (%s);\n" ,
14901
- fmtId (tbinfo -> dobj .name ),
14902
- rinfo -> reloptions );
14912
+ appendPQExpBuffer (cmd , "ALTER VIEW %s SET (" ,
14913
+ fmtId (tbinfo -> dobj .name ));
14914
+ fmtReloptionsArray (fout , cmd , rinfo -> reloptions , "" );
14915
+ appendPQExpBufferStr (cmd , ");\n" );
14903
14916
}
14904
14917
14905
14918
/*
@@ -15769,6 +15782,83 @@ fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer)
15769
15782
return buffer -> data ;
15770
15783
}
15771
15784
15785
+ /*
15786
+ * Check if a reloptions array is nonempty.
15787
+ */
15788
+ static bool
15789
+ nonemptyReloptions (const char * reloptions )
15790
+ {
15791
+ /* Don't want to print it if it's just "{}" */
15792
+ return (reloptions != NULL && strlen (reloptions ) > 2 );
15793
+ }
15794
+
15795
+ /*
15796
+ * Format a reloptions array and append it to the given buffer.
15797
+ *
15798
+ * "prefix" is prepended to the option names; typically it's "" or "toast.".
15799
+ *
15800
+ * Note: this logic should generally match the backend's flatten_reloptions()
15801
+ * (in adt/ruleutils.c).
15802
+ */
15803
+ static void
15804
+ fmtReloptionsArray (Archive * fout , PQExpBuffer buffer , const char * reloptions ,
15805
+ const char * prefix )
15806
+ {
15807
+ char * * options ;
15808
+ int noptions ;
15809
+ int i ;
15810
+
15811
+ if (!parsePGArray (reloptions , & options , & noptions ))
15812
+ {
15813
+ write_msg (NULL , "WARNING: could not parse reloptions array\n" );
15814
+ if (options )
15815
+ free (options );
15816
+ return ;
15817
+ }
15818
+
15819
+ for (i = 0 ; i < noptions ; i ++ )
15820
+ {
15821
+ char * option = options [i ];
15822
+ char * name ;
15823
+ char * separator ;
15824
+ char * value ;
15825
+
15826
+ /*
15827
+ * Each array element should have the form name=value. If the "=" is
15828
+ * missing for some reason, treat it like an empty value.
15829
+ */
15830
+ name = option ;
15831
+ separator = strchr (option , '=' );
15832
+ if (separator )
15833
+ {
15834
+ * separator = '\0' ;
15835
+ value = separator + 1 ;
15836
+ }
15837
+ else
15838
+ value = "" ;
15839
+
15840
+ if (i > 0 )
15841
+ appendPQExpBufferStr (buffer , ", " );
15842
+ appendPQExpBuffer (buffer , "%s%s=" , prefix , fmtId (name ));
15843
+
15844
+ /*
15845
+ * In general we need to quote the value; but to avoid unnecessary
15846
+ * clutter, do not quote if it is an identifier that would not need
15847
+ * quoting. (We could also allow numbers, but that is a bit trickier
15848
+ * than it looks --- for example, are leading zeroes significant? We
15849
+ * don't want to assume very much here about what custom reloptions
15850
+ * might mean.)
15851
+ */
15852
+ if (strcmp (fmtId (value ), value ) == 0 )
15853
+ appendPQExpBufferStr (buffer , value );
15854
+ else
15855
+ appendStringLiteralAH (buffer , value , fout );
15856
+ }
15857
+
15858
+ if (options )
15859
+ free (options );
15860
+ }
15861
+
15772
15862
/*
15773
15863
* Execute an SQL query and verify that we got exactly one row back.
15774
15864
*/
0 commit comments