@@ -245,6 +245,9 @@ static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
245
245
const char * objlabel );
246
246
static const char * getAttrName (int attrnum , TableInfo * tblInfo );
247
247
static const char * fmtCopyColumnList (const TableInfo * ti );
248
+ static bool nonemptyReloptions (const char * reloptions );
249
+ static void fmtReloptionsArray (Archive * fout , PQExpBuffer buffer ,
250
+ const char * reloptions , const char * prefix );
248
251
static void do_sql_command (PGconn * conn , const char * query );
249
252
static void check_sql_result (PGresult * res , PGconn * conn , const char * query ,
250
253
ExecStatusType expected );
@@ -3956,8 +3959,8 @@ getTables(int *numTables)
3956
3959
"d.refobjid AS owning_tab, "
3957
3960
"d.refobjsubid AS owning_col, "
3958
3961
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3959
- "array_to_string( c.reloptions, ', ') AS reloptions, "
3960
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
3962
+ " c.reloptions AS reloptions, "
3963
+ "tc.reloptions AS toast_reloptions "
3961
3964
"FROM pg_class c "
3962
3965
"LEFT JOIN pg_depend d ON "
3963
3966
"(c.relkind = '%c' AND "
@@ -3992,8 +3995,8 @@ getTables(int *numTables)
3992
3995
"d.refobjid AS owning_tab, "
3993
3996
"d.refobjsubid AS owning_col, "
3994
3997
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3995
- "array_to_string( c.reloptions, ', ') AS reloptions, "
3996
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
3998
+ " c.reloptions AS reloptions, "
3999
+ "tc.reloptions AS toast_reloptions "
3997
4000
"FROM pg_class c "
3998
4001
"LEFT JOIN pg_depend d ON "
3999
4002
"(c.relkind = '%c' AND "
@@ -4027,8 +4030,8 @@ getTables(int *numTables)
4027
4030
"d.refobjid AS owning_tab, "
4028
4031
"d.refobjsubid AS owning_col, "
4029
4032
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4030
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4031
- "array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
4033
+ " c.reloptions AS reloptions, "
4034
+ "tc.reloptions AS toast_reloptions "
4032
4035
"FROM pg_class c "
4033
4036
"LEFT JOIN pg_depend d ON "
4034
4037
"(c.relkind = '%c' AND "
@@ -4062,7 +4065,7 @@ getTables(int *numTables)
4062
4065
"d.refobjid AS owning_tab, "
4063
4066
"d.refobjsubid AS owning_col, "
4064
4067
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4065
- "array_to_string( c.reloptions, ', ') AS reloptions, "
4068
+ " c.reloptions AS reloptions, "
4066
4069
"NULL AS toast_reloptions "
4067
4070
"FROM pg_class c "
4068
4071
"LEFT JOIN pg_depend d ON "
@@ -4497,7 +4500,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
4497
4500
i_conoid ,
4498
4501
i_condef ,
4499
4502
i_tablespace ,
4500
- i_options ;
4503
+ i_indreloptions ;
4501
4504
int ntups ;
4502
4505
4503
4506
for (i = 0 ; i < numTables ; i ++ )
@@ -4545,7 +4548,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
4545
4548
"c.oid AS conoid, "
4546
4549
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
4547
4550
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
4548
- "array_to_string( t.reloptions, ', ') AS options "
4551
+ " t.reloptions AS indreloptions "
4549
4552
"FROM pg_catalog.pg_index i "
4550
4553
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
4551
4554
"LEFT JOIN pg_catalog.pg_constraint c "
@@ -4571,7 +4574,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
4571
4574
"c.oid AS conoid, "
4572
4575
"null AS condef, "
4573
4576
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
4574
- "array_to_string( t.reloptions, ', ') AS options "
4577
+ " t.reloptions AS indreloptions "
4575
4578
"FROM pg_catalog.pg_index i "
4576
4579
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
4577
4580
"LEFT JOIN pg_catalog.pg_depend d "
@@ -4600,7 +4603,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
4600
4603
"c.oid AS conoid, "
4601
4604
"null AS condef, "
4602
4605
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
4603
- "null AS options "
4606
+ "null AS indreloptions "
4604
4607
"FROM pg_catalog.pg_index i "
4605
4608
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
4606
4609
"LEFT JOIN pg_catalog.pg_depend d "
@@ -4628,7 +4631,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
4628
4631
"c.oid AS conoid, "
4629
4632
"null AS condef, "
4630
4633
"NULL AS tablespace, "
4631
- "null AS options "
4634
+ "null AS indreloptions "
4632
4635
"FROM pg_catalog.pg_index i "
4633
4636
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
4634
4637
"LEFT JOIN pg_catalog.pg_depend d "
@@ -4659,7 +4662,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
4659
4662
"t.oid AS conoid, "
4660
4663
"null AS condef, "
4661
4664
"NULL AS tablespace, "
4662
- "null AS options "
4665
+ "null AS indreloptions "
4663
4666
"FROM pg_index i, pg_class t "
4664
4667
"WHERE t.oid = i.indexrelid "
4665
4668
"AND i.indrelid = '%u'::oid "
@@ -4685,7 +4688,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
4685
4688
"t.oid AS conoid, "
4686
4689
"null AS condef, "
4687
4690
"NULL AS tablespace, "
4688
- "null AS options "
4691
+ "null AS indreloptions "
4689
4692
"FROM pg_index i, pg_class t "
4690
4693
"WHERE t.oid = i.indexrelid "
4691
4694
"AND i.indrelid = '%u'::oid "
@@ -4713,7 +4716,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
4713
4716
i_conoid = PQfnumber (res , "conoid" );
4714
4717
i_condef = PQfnumber (res , "condef" );
4715
4718
i_tablespace = PQfnumber (res , "tablespace" );
4716
- i_options = PQfnumber (res , "options " );
4719
+ i_indreloptions = PQfnumber (res , "indreloptions " );
4717
4720
4718
4721
indxinfo = (IndxInfo * ) malloc (ntups * sizeof (IndxInfo ));
4719
4722
constrinfo = (ConstraintInfo * ) malloc (ntups * sizeof (ConstraintInfo ));
@@ -4732,7 +4735,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
4732
4735
indxinfo [j ].indexdef = strdup (PQgetvalue (res , j , i_indexdef ));
4733
4736
indxinfo [j ].indnkeys = atoi (PQgetvalue (res , j , i_indnkeys ));
4734
4737
indxinfo [j ].tablespace = strdup (PQgetvalue (res , j , i_tablespace ));
4735
- indxinfo [j ].options = strdup (PQgetvalue (res , j , i_options ));
4738
+ indxinfo [j ].indreloptions = strdup (PQgetvalue (res , j , i_indreloptions ));
4736
4739
4737
4740
/*
4738
4741
* In pre-7.4 releases, indkeys may contain more entries than
@@ -12448,23 +12451,24 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
12448
12451
if (tbinfo -> relkind == RELKIND_FOREIGN_TABLE )
12449
12452
appendPQExpBuffer (q , "\nSERVER %s" , fmtId (srvname ));
12450
12453
12451
- if ((tbinfo -> reloptions && strlen ( tbinfo -> reloptions ) > 0 ) ||
12452
- (tbinfo -> toast_reloptions && strlen ( tbinfo -> toast_reloptions ) > 0 ))
12454
+ if (nonemptyReloptions (tbinfo -> reloptions ) ||
12455
+ nonemptyReloptions (tbinfo -> toast_reloptions ))
12453
12456
{
12454
12457
bool addcomma = false;
12455
12458
12456
- appendPQExpBuffer (q , "\nWITH (" );
12457
- if (tbinfo -> reloptions && strlen (tbinfo -> reloptions ) > 0 )
12459
+ appendPQExpBufferStr (q , "\nWITH (" );
12460
+ if (nonemptyReloptions (tbinfo -> reloptions ))
12458
12461
{
12459
12462
addcomma = true;
12460
- appendPQExpBuffer ( q , "%s" , tbinfo -> reloptions );
12463
+ fmtReloptionsArray ( fout , q , tbinfo -> reloptions , "" );
12461
12464
}
12462
- if (tbinfo -> toast_reloptions && strlen (tbinfo -> toast_reloptions ) > 0 )
12465
+ if (nonemptyReloptions (tbinfo -> toast_reloptions ))
12463
12466
{
12464
- appendPQExpBuffer (q , "%s%s" , addcomma ? ", " : "" ,
12465
- tbinfo -> toast_reloptions );
12467
+ if (addcomma )
12468
+ appendPQExpBufferStr (q , ", " );
12469
+ fmtReloptionsArray (fout , q , tbinfo -> toast_reloptions , "toast." );
12466
12470
}
12467
- appendPQExpBuffer (q , ")" );
12471
+ appendPQExpBufferChar (q , ')' );
12468
12472
}
12469
12473
12470
12474
/* Dump generic options if any */
@@ -12959,8 +12963,12 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
12959
12963
12960
12964
appendPQExpBuffer (q , ")" );
12961
12965
12962
- if (indxinfo -> options && strlen (indxinfo -> options ) > 0 )
12963
- appendPQExpBuffer (q , " WITH (%s)" , indxinfo -> options );
12966
+ if (nonemptyReloptions (indxinfo -> indreloptions ))
12967
+ {
12968
+ appendPQExpBufferStr (q , " WITH (" );
12969
+ fmtReloptionsArray (fout , q , indxinfo -> indreloptions , "" );
12970
+ appendPQExpBufferChar (q , ')' );
12971
+ }
12964
12972
12965
12973
if (coninfo -> condeferrable )
12966
12974
{
@@ -14572,6 +14580,83 @@ fmtCopyColumnList(const TableInfo *ti)
14572
14580
return q -> data ;
14573
14581
}
14574
14582
14583
+ /*
14584
+ * Check if a reloptions array is nonempty.
14585
+ */
14586
+ static bool
14587
+ nonemptyReloptions (const char * reloptions )
14588
+ {
14589
+ /* Don't want to print it if it's just "{}" */
14590
+ return (reloptions != NULL && strlen (reloptions ) > 2 );
14591
+ }
14592
+
14593
+ /*
14594
+ * Format a reloptions array and append it to the given buffer.
14595
+ *
14596
+ * "prefix" is prepended to the option names; typically it's "" or "toast.".
14597
+ *
14598
+ * Note: this logic should generally match the backend's flatten_reloptions()
14599
+ * (in adt/ruleutils.c).
14600
+ */
14601
+ static void
14602
+ fmtReloptionsArray (Archive * fout , PQExpBuffer buffer , const char * reloptions ,
14603
+ const char * prefix )
14604
+ {
14605
+ char * * options ;
14606
+ int noptions ;
14607
+ int i ;
14608
+
14609
+ if (!parsePGArray (reloptions , & options , & noptions ))
14610
+ {
14611
+ write_msg (NULL , "WARNING: could not parse reloptions array\n" );
14612
+ if (options )
14613
+ free (options );
14614
+ return ;
14615
+ }
14616
+
14617
+ for (i = 0 ; i < noptions ; i ++ )
14618
+ {
14619
+ char * option = options [i ];
14620
+ char * name ;
14621
+ char * separator ;
14622
+ char * value ;
14623
+
14624
+ /*
14625
+ * Each array element should have the form name=value. If the "=" is
14626
+ * missing for some reason, treat it like an empty value.
14627
+ */
14628
+ name = option ;
14629
+ separator = strchr (option , '=' );
14630
+ if (separator )
14631
+ {
14632
+ * separator = '\0' ;
14633
+ value = separator + 1 ;
14634
+ }
14635
+ else
14636
+ value = "" ;
14637
+
14638
+ if (i > 0 )
14639
+ appendPQExpBufferStr (buffer , ", " );
14640
+ appendPQExpBuffer (buffer , "%s%s=" , prefix , fmtId (name ));
14641
+
14642
+ /*
14643
+ * In general we need to quote the value; but to avoid unnecessary
14644
+ * clutter, do not quote if it is an identifier that would not need
14645
+ * quoting. (We could also allow numbers, but that is a bit trickier
14646
+ * than it looks --- for example, are leading zeroes significant? We
14647
+ * don't want to assume very much here about what custom reloptions
14648
+ * might mean.)
14649
+ */
14650
+ if (strcmp (fmtId (value ), value ) == 0 )
14651
+ appendPQExpBufferStr (buffer , value );
14652
+ else
14653
+ appendStringLiteralAH (buffer , value , fout );
14654
+ }
14655
+
14656
+ if (options )
14657
+ free (options );
14658
+ }
14659
+
14575
14660
/*
14576
14661
* Convenience subroutine to execute a SQL command and check for
14577
14662
* COMMAND_OK status.
0 commit comments