@ -256,6 +256,9 @@ static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
const char * objlabel ) ;
static const char * getAttrName ( int attrnum , TableInfo * tblInfo ) ;
static const char * fmtCopyColumnList ( const TableInfo * ti , PQExpBuffer buffer ) ;
static bool nonemptyReloptions ( const char * reloptions ) ;
static void fmtReloptionsArray ( Archive * fout , PQExpBuffer buffer ,
const char * reloptions , const char * prefix ) ;
static char * get_synchronized_snapshot ( Archive * fout ) ;
static PGresult * ExecuteSqlQueryForSingleRow ( Archive * fout , char * query ) ;
static void setupDumpWorker ( Archive * AHX , DumpOptions * dopt , RestoreOptions * ropt ) ;
@ -4604,10 +4607,10 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
" d.refobjid AS owning_tab, "
" d.refobjsubid AS owning_col, "
" (SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
" array_to_string(array_ remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded'), ', ') AS reloptions, "
" array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
" CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
" WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
" array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
" tc.reloptions AS toast_reloptions "
" FROM pg_class c "
" LEFT JOIN pg_depend d ON "
" (c.relkind = '%c' AND "
@ -4646,10 +4649,10 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
" d.refobjid AS owning_tab, "
" d.refobjsubid AS owning_col, "
" (SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
" array_to_string(array_ remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded'), ', ') AS reloptions, "
" array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
" CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
" WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
" array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
" tc.reloptions AS toast_reloptions "
" FROM pg_class c "
" LEFT JOIN pg_depend d ON "
" (c.relkind = '%c' AND "
@ -4688,10 +4691,10 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
" d.refobjid AS owning_tab, "
" d.refobjsubid AS owning_col, "
" (SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
" array_to_string(array_ remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded'), ', ') AS reloptions, "
" array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
" CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
" WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
" array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
" tc.reloptions AS toast_reloptions "
" FROM pg_class c "
" LEFT JOIN pg_depend d ON "
" (c.relkind = '%c' AND "
@ -4730,8 +4733,8 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
" d.refobjid AS owning_tab, "
" d.refobjsubid AS owning_col, "
" (SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
" array_to_string( c.reloptions, ', ') AS reloptions, "
" array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
" c.reloptions AS reloptions, "
" tc.reloptions AS toast_reloptions "
" FROM pg_class c "
" LEFT JOIN pg_depend d ON "
" (c.relkind = '%c' AND "
@ -4770,8 +4773,8 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
" d.refobjid AS owning_tab, "
" d.refobjsubid AS owning_col, "
" (SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
" array_to_string( c.reloptions, ', ') AS reloptions, "
" array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
" c.reloptions AS reloptions, "
" tc.reloptions AS toast_reloptions "
" FROM pg_class c "
" LEFT JOIN pg_depend d ON "
" (c.relkind = '%c' AND "
@ -4809,8 +4812,8 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
" d.refobjid AS owning_tab, "
" d.refobjsubid AS owning_col, "
" (SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
" array_to_string( c.reloptions, ', ') AS reloptions, "
" array_to_string(array(SELECT 'toast.' || x FROM unnest( tc.reloptions) x), ', ') AS toast_reloptions "
" c.reloptions AS reloptions, "
" tc.reloptions AS toast_reloptions "
" FROM pg_class c "
" LEFT JOIN pg_depend d ON "
" (c.relkind = '%c' AND "
@ -4848,7 +4851,7 @@ getTables(Archive *fout, DumpOptions *dopt, int *numTables)
" d.refobjid AS owning_tab, "
" d.refobjsubid AS owning_col, "
" (SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
" array_to_string( c.reloptions, ', ') AS reloptions, "
" c.reloptions AS reloptions, "
" NULL AS toast_reloptions "
" FROM pg_class c "
" LEFT JOIN pg_depend d ON "
@ -5321,7 +5324,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
i_conoid ,
i_condef ,
i_tablespace ,
i_options ,
i_indrel options ,
i_relpages ;
int ntups ;
@ -5379,7 +5382,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
" c.oid AS conoid, "
" pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
" (SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
" array_to_string( t.reloptions, ', ') AS options "
" t.reloptions AS indrel options "
" FROM pg_catalog.pg_index i "
" JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
" LEFT JOIN pg_catalog.pg_constraint c "
@ -5410,7 +5413,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
" c.oid AS conoid, "
" pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
" (SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
" array_to_string( t.reloptions, ', ') AS options "
" t.reloptions AS indrel options "
" FROM pg_catalog.pg_index i "
" JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
" LEFT JOIN pg_catalog.pg_constraint c "
@ -5437,7 +5440,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
" c.oid AS conoid, "
" null AS condef, "
" (SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
" array_to_string( t.reloptions, ', ') AS options "
" t.reloptions AS indrel options "
" FROM pg_catalog.pg_index i "
" JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
" LEFT JOIN pg_catalog.pg_depend d "
@ -5467,7 +5470,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
" c.oid AS conoid, "
" null AS condef, "
" (SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
" null AS options "
" null AS indrel options "
" FROM pg_catalog.pg_index i "
" JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
" LEFT JOIN pg_catalog.pg_depend d "
@ -5496,7 +5499,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
" c.oid AS conoid, "
" null AS condef, "
" NULL AS tablespace, "
" null AS options "
" null AS indrel options "
" FROM pg_catalog.pg_index i "
" JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
" LEFT JOIN pg_catalog.pg_depend d "
@ -5528,7 +5531,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
" t.oid AS conoid, "
" null AS condef, "
" NULL AS tablespace, "
" null AS options "
" null AS indrel options "
" FROM pg_index i, pg_class t "
" WHERE t.oid = i.indexrelid "
" AND i.indrelid = '%u'::oid "
@ -5555,7 +5558,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
" t.oid AS conoid, "
" null AS condef, "
" NULL AS tablespace, "
" null AS options "
" null AS indrel options "
" FROM pg_index i, pg_class t "
" WHERE t.oid = i.indexrelid "
" AND i.indrelid = '%u'::oid "
@ -5584,7 +5587,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
i_conoid = PQfnumber ( res , " conoid " ) ;
i_condef = PQfnumber ( res , " condef " ) ;
i_tablespace = PQfnumber ( res , " tablespace " ) ;
i_options = PQfnumber ( res , " options " ) ;
i_indrel options = PQfnumber ( res , " indrel options" ) ;
indxinfo = ( IndxInfo * ) pg_malloc ( ntups * sizeof ( IndxInfo ) ) ;
constrinfo = ( ConstraintInfo * ) pg_malloc ( ntups * sizeof ( ConstraintInfo ) ) ;
@ -5603,7 +5606,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
indxinfo [ j ] . indexdef = pg_strdup ( PQgetvalue ( res , j , i_indexdef ) ) ;
indxinfo [ j ] . indnkeys = atoi ( PQgetvalue ( res , j , i_indnkeys ) ) ;
indxinfo [ j ] . tablespace = pg_strdup ( PQgetvalue ( res , j , i_tablespace ) ) ;
indxinfo [ j ] . options = pg_strdup ( PQgetvalue ( res , j , i_options ) ) ;
indxinfo [ j ] . indrel options = pg_strdup ( PQgetvalue ( res , j , i_indrel options ) ) ;
/*
* In pre - 7.4 releases , indkeys may contain more entries than
@ -10255,7 +10258,8 @@ dumpFunc(Archive *fout, DumpOptions *dopt, FuncInfo *finfo)
" pg_catalog.pg_get_function_result(oid) AS funcresult, "
" array_to_string(protrftypes, ' ') AS protrftypes, "
" proiswindow, provolatile, proisstrict, prosecdef, "
" proleakproof, proconfig, procost, prorows, proparallel, "
" proleakproof, proconfig, procost, prorows, "
" proparallel, "
" (SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
" FROM pg_catalog.pg_proc "
" WHERE oid = '%u'::pg_catalog.oid " ,
@ -13869,8 +13873,12 @@ dumpTableSchema(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
tbinfo - > dobj . catId . oid , false ) ;
appendPQExpBuffer ( q , " CREATE VIEW %s " , fmtId ( tbinfo - > dobj . name ) ) ;
if ( tbinfo - > reloptions & & strlen ( tbinfo - > reloptions ) > 0 )
appendPQExpBuffer ( q , " WITH (%s) " , tbinfo - > reloptions ) ;
if ( nonemptyReloptions ( tbinfo - > reloptions ) )
{
appendPQExpBufferStr ( q , " WITH ( " ) ;
fmtReloptionsArray ( fout , q , tbinfo - > reloptions , " " ) ;
appendPQExpBufferChar ( q , ' ) ' ) ;
}
result = createViewAsClause ( fout , tbinfo ) ;
appendPQExpBuffer ( q , " AS \n %s " , result - > data ) ;
destroyPQExpBuffer ( result ) ;
@ -14114,21 +14122,22 @@ dumpTableSchema(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
appendPQExpBuffer ( q , " \n SERVER %s " , fmtId ( srvname ) ) ;
}
if ( ( tbinfo - > reloptions & & strlen ( tbinfo - > reloptions ) > 0 ) | |
( tbinfo - > toast_reloptions & & strlen ( tbinfo - > toast_reloptions ) > 0 ) )
if ( nonemptyReloptions ( tbinfo - > reloptions ) | |
nonemptyReloptions ( tbinfo - > toast_reloptions ) )
{
bool addcomma = false ;
appendPQExpBufferStr ( q , " \n WITH ( " ) ;
if ( tbinfo - > reloptions & & strlen ( tbinfo - > reloptions ) > 0 )
if ( nonemptyReloptions ( tbinfo - > reloptions ) )
{
addcomma = true ;
appendPQExpBufferStr ( q , tbinfo - > reloptions ) ;
fmtReloptionsArray ( fout , q , tbinfo - > reloptions , " " ) ;
}
if ( tbinfo - > toast_reloptions & & strlen ( tbinfo - > toast_reloptions ) > 0 )
if ( nonemptyReloptions ( tbinfo - > toast_reloptions ) )
{
appendPQExpBuffer ( q , " %s%s " , addcomma ? " , " : " " ,
tbinfo - > toast_reloptions ) ;
if ( addcomma )
appendPQExpBufferStr ( q , " , " ) ;
fmtReloptionsArray ( fout , q , tbinfo - > toast_reloptions , " toast. " ) ;
}
appendPQExpBufferChar ( q , ' ) ' ) ;
}
@ -14710,8 +14719,12 @@ dumpConstraint(Archive *fout, DumpOptions *dopt, ConstraintInfo *coninfo)
appendPQExpBufferChar ( q , ' ) ' ) ;
if ( indxinfo - > options & & strlen ( indxinfo - > options ) > 0 )
appendPQExpBuffer ( q , " WITH (%s) " , indxinfo - > options ) ;
if ( nonemptyReloptions ( indxinfo - > indreloptions ) )
{
appendPQExpBufferStr ( q , " WITH ( " ) ;
fmtReloptionsArray ( fout , q , indxinfo - > indreloptions , " " ) ;
appendPQExpBufferChar ( q , ' ) ' ) ;
}
if ( coninfo - > condeferrable )
{
@ -15571,11 +15584,12 @@ dumpRule(Archive *fout, DumpOptions *dopt, RuleInfo *rinfo)
/*
* Apply view ' s reloptions when its ON SELECT rule is separate .
*/
if ( rinfo - > reloptions & & strlen ( rinfo - > reloptions ) > 0 )
if ( nonemptyReloptions ( rinfo - > reloptions ) )
{
appendPQExpBuffer ( cmd , " ALTER VIEW %s SET (%s); \n " ,
fmtId ( tbinfo - > dobj . name ) ,
rinfo - > reloptions ) ;
appendPQExpBuffer ( cmd , " ALTER VIEW %s SET ( " ,
fmtId ( tbinfo - > dobj . name ) ) ;
fmtReloptionsArray ( fout , cmd , rinfo - > reloptions , " " ) ;
appendPQExpBufferStr ( cmd , " ); \n " ) ;
}
/*
@ -16448,6 +16462,83 @@ fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer)
return buffer - > data ;
}
/*
* Check if a reloptions array is nonempty .
*/
static bool
nonemptyReloptions ( const char * reloptions )
{
/* Don't want to print it if it's just "{}" */
return ( reloptions ! = NULL & & strlen ( reloptions ) > 2 ) ;
}
/*
* Format a reloptions array and append it to the given buffer .
*
* " prefix " is prepended to the option names ; typically it ' s " " or " toast. " .
*
* Note : this logic should generally match the backend ' s flatten_reloptions ( )
* ( in adt / ruleutils . c ) .
*/
static void
fmtReloptionsArray ( Archive * fout , PQExpBuffer buffer , const char * reloptions ,
const char * prefix )
{
char * * options ;
int noptions ;
int i ;
if ( ! parsePGArray ( reloptions , & options , & noptions ) )
{
write_msg ( NULL , " WARNING: could not parse reloptions array \n " ) ;
if ( options )
free ( options ) ;
return ;
}
for ( i = 0 ; i < noptions ; i + + )
{
char * option = options [ i ] ;
char * name ;
char * separator ;
char * value ;
/*
* Each array element should have the form name = value . If the " = " is
* missing for some reason , treat it like an empty value .
*/
name = option ;
separator = strchr ( option , ' = ' ) ;
if ( separator )
{
* separator = ' \0 ' ;
value = separator + 1 ;
}
else
value = " " ;
if ( i > 0 )
appendPQExpBufferStr ( buffer , " , " ) ;
appendPQExpBuffer ( buffer , " %s%s= " , prefix , fmtId ( name ) ) ;
/*
* In general we need to quote the value ; but to avoid unnecessary
* clutter , do not quote if it is an identifier that would not need
* quoting . ( We could also allow numbers , but that is a bit trickier
* than it looks - - - for example , are leading zeroes significant ? We
* don ' t want to assume very much here about what custom reloptions
* might mean . )
*/
if ( strcmp ( fmtId ( value ) , value ) = = 0 )
appendPQExpBufferStr ( buffer , value ) ;
else
appendStringLiteralAH ( buffer , value , fout ) ;
}
if ( options )
free ( options ) ;
}
/*
* Execute an SQL query and verify that we got exactly one row back .
*/