@@ -251,6 +251,9 @@ static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
251251 const char * objlabel );
252252static const char * getAttrName (int attrnum , TableInfo * tblInfo );
253253static 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 );
254257static char * get_synchronized_snapshot (Archive * fout );
255258static PGresult * ExecuteSqlQueryForSingleRow (Archive * fout , char * query );
256259static void setupDumpWorker (Archive * AHX , DumpOptions * dopt , RestoreOptions * ropt );
@@ -4585,10 +4588,10 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
45854588 "d.refobjid AS owning_tab, "
45864589 "d.refobjsubid AS owning_col, "
45874590 "(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, "
45894592 "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
45904593 "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 "
45924595 "FROM pg_class c "
45934596 "LEFT JOIN pg_depend d ON "
45944597 "(c.relkind = '%c' AND "
@@ -4627,10 +4630,10 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
46274630 "d.refobjid AS owning_tab, "
46284631 "d.refobjsubid AS owning_col, "
46294632 "(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, "
46314634 "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
46324635 "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 "
46344637 "FROM pg_class c "
46354638 "LEFT JOIN pg_depend d ON "
46364639 "(c.relkind = '%c' AND "
@@ -4669,10 +4672,10 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
46694672 "d.refobjid AS owning_tab, "
46704673 "d.refobjsubid AS owning_col, "
46714674 "(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, "
46734676 "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
46744677 "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 "
46764679 "FROM pg_class c "
46774680 "LEFT JOIN pg_depend d ON "
46784681 "(c.relkind = '%c' AND "
@@ -4711,8 +4714,8 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
47114714 "d.refobjid AS owning_tab, "
47124715 "d.refobjsubid AS owning_col, "
47134716 "(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 "
47164719 "FROM pg_class c "
47174720 "LEFT JOIN pg_depend d ON "
47184721 "(c.relkind = '%c' AND "
@@ -4751,8 +4754,8 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
47514754 "d.refobjid AS owning_tab, "
47524755 "d.refobjsubid AS owning_col, "
47534756 "(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 "
47564759 "FROM pg_class c "
47574760 "LEFT JOIN pg_depend d ON "
47584761 "(c.relkind = '%c' AND "
@@ -4790,8 +4793,8 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
47904793 "d.refobjid AS owning_tab, "
47914794 "d.refobjsubid AS owning_col, "
47924795 "(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 "
47954798 "FROM pg_class c "
47964799 "LEFT JOIN pg_depend d ON "
47974800 "(c.relkind = '%c' AND "
@@ -4829,7 +4832,7 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
48294832 "d.refobjid AS owning_tab, "
48304833 "d.refobjsubid AS owning_col, "
48314834 "(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, "
48334836 "NULL AS toast_reloptions "
48344837 "FROM pg_class c "
48354838 "LEFT JOIN pg_depend d ON "
@@ -5302,7 +5305,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
53025305 i_conoid ,
53035306 i_condef ,
53045307 i_tablespace ,
5305- i_options ,
5308+ i_indreloptions ,
53065309 i_relpages ;
53075310 int ntups ;
53085311
@@ -5360,7 +5363,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
53605363 "c.oid AS conoid, "
53615364 "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
53625365 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5363- "array_to_string( t.reloptions, ', ') AS options "
5366+ " t.reloptions AS indreloptions "
53645367 "FROM pg_catalog.pg_index i "
53655368 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
53665369 "LEFT JOIN pg_catalog.pg_constraint c "
@@ -5391,7 +5394,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
53915394 "c.oid AS conoid, "
53925395 "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
53935396 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5394- "array_to_string( t.reloptions, ', ') AS options "
5397+ " t.reloptions AS indreloptions "
53955398 "FROM pg_catalog.pg_index i "
53965399 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
53975400 "LEFT JOIN pg_catalog.pg_constraint c "
@@ -5418,7 +5421,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
54185421 "c.oid AS conoid, "
54195422 "null AS condef, "
54205423 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5421- "array_to_string( t.reloptions, ', ') AS options "
5424+ " t.reloptions AS indreloptions "
54225425 "FROM pg_catalog.pg_index i "
54235426 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
54245427 "LEFT JOIN pg_catalog.pg_depend d "
@@ -5448,7 +5451,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
54485451 "c.oid AS conoid, "
54495452 "null AS condef, "
54505453 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
5451- "null AS options "
5454+ "null AS indreloptions "
54525455 "FROM pg_catalog.pg_index i "
54535456 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
54545457 "LEFT JOIN pg_catalog.pg_depend d "
@@ -5477,7 +5480,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
54775480 "c.oid AS conoid, "
54785481 "null AS condef, "
54795482 "NULL AS tablespace, "
5480- "null AS options "
5483+ "null AS indreloptions "
54815484 "FROM pg_catalog.pg_index i "
54825485 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
54835486 "LEFT JOIN pg_catalog.pg_depend d "
@@ -5509,7 +5512,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
55095512 "t.oid AS conoid, "
55105513 "null AS condef, "
55115514 "NULL AS tablespace, "
5512- "null AS options "
5515+ "null AS indreloptions "
55135516 "FROM pg_index i, pg_class t "
55145517 "WHERE t.oid = i.indexrelid "
55155518 "AND i.indrelid = '%u'::oid "
@@ -5536,7 +5539,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
55365539 "t.oid AS conoid, "
55375540 "null AS condef, "
55385541 "NULL AS tablespace, "
5539- "null AS options "
5542+ "null AS indreloptions "
55405543 "FROM pg_index i, pg_class t "
55415544 "WHERE t.oid = i.indexrelid "
55425545 "AND i.indrelid = '%u'::oid "
@@ -5565,7 +5568,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
55655568 i_conoid = PQfnumber (res , "conoid" );
55665569 i_condef = PQfnumber (res , "condef" );
55675570 i_tablespace = PQfnumber (res , "tablespace" );
5568- i_options = PQfnumber (res , "options " );
5571+ i_indreloptions = PQfnumber (res , "indreloptions " );
55695572
55705573 indxinfo = (IndxInfo * ) pg_malloc (ntups * sizeof (IndxInfo ));
55715574 constrinfo = (ConstraintInfo * ) pg_malloc (ntups * sizeof (ConstraintInfo ));
@@ -5584,7 +5587,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
55845587 indxinfo [j ].indexdef = pg_strdup (PQgetvalue (res , j , i_indexdef ));
55855588 indxinfo [j ].indnkeys = atoi (PQgetvalue (res , j , i_indnkeys ));
55865589 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 ));
55885591
55895592 /*
55905593 * In pre-7.4 releases, indkeys may contain more entries than
@@ -13810,8 +13813,12 @@ dumpTableSchema(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
1381013813 tbinfo -> dobj .catId .oid , false);
1381113814
1381213815 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+ }
1381513822 result = createViewAsClause (fout , tbinfo );
1381613823 appendPQExpBuffer (q , " AS\n%s" , result -> data );
1381713824 destroyPQExpBuffer (result );
@@ -14055,21 +14062,22 @@ dumpTableSchema(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
1405514062 appendPQExpBuffer (q , "\nSERVER %s" , fmtId (srvname ));
1405614063 }
1405714064
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 ))
1406014067 {
1406114068 bool addcomma = false;
1406214069
1406314070 appendPQExpBufferStr (q , "\nWITH (" );
14064- if (tbinfo -> reloptions && strlen (tbinfo -> reloptions ) > 0 )
14071+ if (nonemptyReloptions (tbinfo -> reloptions ))
1406514072 {
1406614073 addcomma = true;
14067- appendPQExpBufferStr ( q , tbinfo -> reloptions );
14074+ fmtReloptionsArray ( fout , q , tbinfo -> reloptions , "" );
1406814075 }
14069- if (tbinfo -> toast_reloptions && strlen (tbinfo -> toast_reloptions ) > 0 )
14076+ if (nonemptyReloptions (tbinfo -> toast_reloptions ))
1407014077 {
14071- appendPQExpBuffer (q , "%s%s" , addcomma ? ", " : "" ,
14072- tbinfo -> toast_reloptions );
14078+ if (addcomma )
14079+ appendPQExpBufferStr (q , ", " );
14080+ fmtReloptionsArray (fout , q , tbinfo -> toast_reloptions , "toast." );
1407314081 }
1407414082 appendPQExpBufferChar (q , ')' );
1407514083 }
@@ -14651,8 +14659,12 @@ dumpConstraint(Archive *fout, DumpOptions *dopt, ConstraintInfo *coninfo)
1465114659
1465214660 appendPQExpBufferChar (q , ')' );
1465314661
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+ }
1465614668
1465714669 if (coninfo -> condeferrable )
1465814670 {
@@ -15512,11 +15524,12 @@ dumpRule(Archive *fout, DumpOptions *dopt, RuleInfo *rinfo)
1551215524 /*
1551315525 * Apply view's reloptions when its ON SELECT rule is separate.
1551415526 */
15515- if (rinfo -> reloptions && strlen (rinfo -> reloptions ) > 0 )
15527+ if (nonemptyReloptions (rinfo -> reloptions ))
1551615528 {
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" );
1552015533 }
1552115534
1552215535 /*
@@ -16389,6 +16402,83 @@ fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer)
1638916402 return buffer -> data ;
1639016403}
1639116404
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+
1639216482/*
1639316483 * Execute an SQL query and verify that we got exactly one row back.
1639416484 */
0 commit comments