1
/*-------------------------------------------------------------------------
4
* pg_dump is a utility for dumping out a postgres database
7
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
8
* Portions Copyright (c) 1994, Regents of the University of California
10
* pg_dump will read the system catalogs in a database and dump out a
11
* script that reproduces the schema in terms of SQL that is understood
14
* Note that pg_dump runs in a transaction-snapshot mode transaction,
15
* so it sees a consistent snapshot of the database including system
16
* catalogs. However, it relies in part on various specialized backend
17
* functions like pg_get_indexdef(), and those things tend to run on
18
* SnapshotNow time, ie they look at the currently committed state. So
19
* it is possible to get 'cache lookup failed' error if someone
20
* performs DDL changes while a dump is happening. The window for this
21
* sort of thing is from the acquisition of the transaction snapshot to
22
* getSchemaData() (when pg_dump acquires AccessShareLock on every
23
* table it intends to dump). It isn't very large, but it can happen.
25
* http://archives.postgresql.org/pgsql-bugs/2010-02/msg00187.php
28
* src/bin/pg_dump/pg_dump.c
30
*-------------------------------------------------------------------------
33
#include "postgres_fe.h"
44
#include "getopt_long.h"
46
#include "access/attnum.h"
47
#include "access/sysattr.h"
48
#include "access/transam.h"
49
#include "catalog/pg_cast.h"
50
#include "catalog/pg_class.h"
51
#include "catalog/pg_default_acl.h"
52
#include "catalog/pg_largeobject.h"
53
#include "catalog/pg_largeobject_metadata.h"
54
#include "catalog/pg_proc.h"
55
#include "catalog/pg_trigger.h"
56
#include "catalog/pg_type.h"
57
#include "libpq/libpq-fs.h"
59
#include "pg_backup_archiver.h"
60
#include "dumputils.h"
69
const char *descr; /* comment for an object */
70
Oid classoid; /* object class (catalog OID) */
71
Oid objoid; /* object OID */
72
int objsubid; /* subobject (table column #) */
77
const char *provider; /* label provider of this security label */
78
const char *label; /* security label for an object */
79
Oid classoid; /* object class (catalog OID) */
80
Oid objoid; /* object OID */
81
int objsubid; /* subobject (table column #) */
85
bool g_verbose; /* User wants verbose narration of our
87
Archive *g_fout; /* the script file */
88
PGconn *g_conn; /* the database connection */
90
/* various user-settable parameters */
94
const char *lockWaitTimeout;
96
/* subquery used to convert user ID (eg, datdba) to user name */
97
static const char *username_subquery;
99
/* obsolete as of 7.3: */
100
static Oid g_last_builtin_oid; /* value of the last builtin oid */
103
* Object inclusion/exclusion lists
105
* The string lists record the patterns given by command-line switches,
106
* which we then convert to lists of OIDs of matching objects.
108
static SimpleStringList schema_include_patterns = {NULL, NULL};
109
static SimpleOidList schema_include_oids = {NULL, NULL};
110
static SimpleStringList schema_exclude_patterns = {NULL, NULL};
111
static SimpleOidList schema_exclude_oids = {NULL, NULL};
113
static SimpleStringList table_include_patterns = {NULL, NULL};
114
static SimpleOidList table_include_oids = {NULL, NULL};
115
static SimpleStringList table_exclude_patterns = {NULL, NULL};
116
static SimpleOidList table_exclude_oids = {NULL, NULL};
118
/* default, if no "inclusion" switches appear, is to dump everything */
119
static bool include_everything = true;
121
char g_opaque_type[10]; /* name for the opaque type */
123
/* placeholders for the delimiters for comments */
124
char g_comment_start[10];
125
char g_comment_end[10];
127
static const CatalogId nilCatalogId = {0, 0};
129
/* these are to avoid passing around info for findNamespace() */
130
static NamespaceInfo *g_namespaces;
131
static int g_numNamespaces;
133
/* flags for various command-line long options */
134
static int binary_upgrade = 0;
135
static int disable_dollar_quoting = 0;
136
static int dump_inserts = 0;
137
static int column_inserts = 0;
138
static int no_security_label = 0;
139
static int no_unlogged_table_data = 0;
140
static int serializable_deferrable = 0;
143
static void help(const char *progname);
144
static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
145
static void expand_schema_name_patterns(SimpleStringList *patterns,
146
SimpleOidList *oids);
147
static void expand_table_name_patterns(SimpleStringList *patterns,
148
SimpleOidList *oids);
149
static NamespaceInfo *findNamespace(Oid nsoid, Oid objoid);
150
static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
151
static void guessConstraintInheritance(TableInfo *tblinfo, int numTables);
152
static void dumpComment(Archive *fout, const char *target,
153
const char *namespace, const char *owner,
154
CatalogId catalogId, int subid, DumpId dumpId);
155
static int findComments(Archive *fout, Oid classoid, Oid objoid,
156
CommentItem **items);
157
static int collectComments(Archive *fout, CommentItem **items);
158
static void dumpSecLabel(Archive *fout, const char *target,
159
const char *namespace, const char *owner,
160
CatalogId catalogId, int subid, DumpId dumpId);
161
static int findSecLabels(Archive *fout, Oid classoid, Oid objoid,
162
SecLabelItem **items);
163
static int collectSecLabels(Archive *fout, SecLabelItem **items);
164
static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
165
static void dumpNamespace(Archive *fout, NamespaceInfo *nspinfo);
166
static void dumpExtension(Archive *fout, ExtensionInfo *extinfo);
167
static void dumpType(Archive *fout, TypeInfo *tyinfo);
168
static void dumpBaseType(Archive *fout, TypeInfo *tyinfo);
169
static void dumpEnumType(Archive *fout, TypeInfo *tyinfo);
170
static void dumpDomain(Archive *fout, TypeInfo *tyinfo);
171
static void dumpCompositeType(Archive *fout, TypeInfo *tyinfo);
172
static void dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo);
173
static void dumpShellType(Archive *fout, ShellTypeInfo *stinfo);
174
static void dumpProcLang(Archive *fout, ProcLangInfo *plang);
175
static void dumpFunc(Archive *fout, FuncInfo *finfo);
176
static void dumpCast(Archive *fout, CastInfo *cast);
177
static void dumpOpr(Archive *fout, OprInfo *oprinfo);
178
static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo);
179
static void dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo);
180
static void dumpCollation(Archive *fout, CollInfo *convinfo);
181
static void dumpConversion(Archive *fout, ConvInfo *convinfo);
182
static void dumpRule(Archive *fout, RuleInfo *rinfo);
183
static void dumpAgg(Archive *fout, AggInfo *agginfo);
184
static void dumpTrigger(Archive *fout, TriggerInfo *tginfo);
185
static void dumpTable(Archive *fout, TableInfo *tbinfo);
186
static void dumpTableSchema(Archive *fout, TableInfo *tbinfo);
187
static void dumpAttrDef(Archive *fout, AttrDefInfo *adinfo);
188
static void dumpSequence(Archive *fout, TableInfo *tbinfo);
189
static void dumpIndex(Archive *fout, IndxInfo *indxinfo);
190
static void dumpConstraint(Archive *fout, ConstraintInfo *coninfo);
191
static void dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo);
192
static void dumpTSParser(Archive *fout, TSParserInfo *prsinfo);
193
static void dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo);
194
static void dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo);
195
static void dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo);
196
static void dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo);
197
static void dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo);
198
static void dumpUserMappings(Archive *fout,
199
const char *servername, const char *namespace,
200
const char *owner, CatalogId catalogId, DumpId dumpId);
201
static void dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo);
203
static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
204
const char *type, const char *name, const char *subname,
205
const char *tag, const char *nspname, const char *owner,
208
static void getDependencies(void);
209
static void getDomainConstraints(TypeInfo *tyinfo);
210
static void getTableData(TableInfo *tblinfo, int numTables, bool oids);
211
static void makeTableDataInfo(TableInfo *tbinfo, bool oids);
212
static void getTableDataFKConstraints(void);
213
static char *format_function_arguments(FuncInfo *finfo, char *funcargs);
214
static char *format_function_arguments_old(FuncInfo *finfo, int nallargs,
218
static char *format_function_signature(FuncInfo *finfo, bool honor_quotes);
219
static const char *convertRegProcReference(const char *proc);
220
static const char *convertOperatorReference(const char *opr);
221
static const char *convertTSFunction(Oid funcOid);
222
static Oid findLastBuiltinOid_V71(const char *);
223
static Oid findLastBuiltinOid_V70(void);
224
static void selectSourceSchema(const char *schemaName);
225
static char *getFormattedTypeName(Oid oid, OidOptions opts);
226
static char *myFormatType(const char *typname, int32 typmod);
227
static const char *fmtQualifiedId(const char *schema, const char *id);
228
static void getBlobs(Archive *AH);
229
static void dumpBlob(Archive *AH, BlobInfo *binfo);
230
static int dumpBlobs(Archive *AH, void *arg);
231
static void dumpDatabase(Archive *AH);
232
static void dumpEncoding(Archive *AH);
233
static void dumpStdStrings(Archive *AH);
234
static void binary_upgrade_set_type_oids_by_type_oid(
235
PQExpBuffer upgrade_buffer, Oid pg_type_oid);
236
static bool binary_upgrade_set_type_oids_by_rel_oid(
237
PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
238
static void binary_upgrade_set_pg_class_oids(PQExpBuffer upgrade_buffer,
239
Oid pg_class_oid, bool is_index);
240
static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
241
DumpableObject *dobj,
242
const char *objlabel);
243
static const char *getAttrName(int attrnum, TableInfo *tblInfo);
244
static const char *fmtCopyColumnList(const TableInfo *ti);
245
static void do_sql_command(PGconn *conn, const char *query);
246
static void check_sql_result(PGresult *res, PGconn *conn, const char *query,
247
ExecStatusType expected);
251
main(int argc, char **argv)
254
const char *filename = NULL;
255
const char *format = "p";
256
const char *dbname = NULL;
257
const char *pghost = NULL;
258
const char *pgport = NULL;
259
const char *username = NULL;
260
const char *dumpencoding = NULL;
261
const char *std_strings;
265
DumpableObject **dobjs;
268
enum trivalue prompt_password = TRI_DEFAULT;
269
int compressLevel = -1;
272
int outputCreateDB = 0;
273
bool outputBlobs = false;
274
int outputNoOwner = 0;
275
char *outputSuperuser = NULL;
276
char *use_role = NULL;
279
RestoreOptions *ropt;
280
ArchiveFormat archiveFormat = archUnknown;
281
ArchiveMode archiveMode;
283
static int disable_triggers = 0;
284
static int outputNoTablespaces = 0;
285
static int use_setsessauth = 0;
287
static struct option long_options[] = {
288
{"data-only", no_argument, NULL, 'a'},
289
{"blobs", no_argument, NULL, 'b'},
290
{"clean", no_argument, NULL, 'c'},
291
{"create", no_argument, NULL, 'C'},
292
{"file", required_argument, NULL, 'f'},
293
{"format", required_argument, NULL, 'F'},
294
{"host", required_argument, NULL, 'h'},
295
{"ignore-version", no_argument, NULL, 'i'},
296
{"no-reconnect", no_argument, NULL, 'R'},
297
{"oids", no_argument, NULL, 'o'},
298
{"no-owner", no_argument, NULL, 'O'},
299
{"port", required_argument, NULL, 'p'},
300
{"schema", required_argument, NULL, 'n'},
301
{"exclude-schema", required_argument, NULL, 'N'},
302
{"schema-only", no_argument, NULL, 's'},
303
{"superuser", required_argument, NULL, 'S'},
304
{"table", required_argument, NULL, 't'},
305
{"exclude-table", required_argument, NULL, 'T'},
306
{"no-password", no_argument, NULL, 'w'},
307
{"password", no_argument, NULL, 'W'},
308
{"username", required_argument, NULL, 'U'},
309
{"verbose", no_argument, NULL, 'v'},
310
{"no-privileges", no_argument, NULL, 'x'},
311
{"no-acl", no_argument, NULL, 'x'},
312
{"compress", required_argument, NULL, 'Z'},
313
{"encoding", required_argument, NULL, 'E'},
314
{"help", no_argument, NULL, '?'},
315
{"version", no_argument, NULL, 'V'},
318
* the following options don't have an equivalent short option letter
320
{"attribute-inserts", no_argument, &column_inserts, 1},
321
{"binary-upgrade", no_argument, &binary_upgrade, 1},
322
{"column-inserts", no_argument, &column_inserts, 1},
323
{"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
324
{"disable-triggers", no_argument, &disable_triggers, 1},
325
{"inserts", no_argument, &dump_inserts, 1},
326
{"lock-wait-timeout", required_argument, NULL, 2},
327
{"no-tablespaces", no_argument, &outputNoTablespaces, 1},
328
{"quote-all-identifiers", no_argument, "e_all_identifiers, 1},
329
{"role", required_argument, NULL, 3},
330
{"serializable-deferrable", no_argument, &serializable_deferrable, 1},
331
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
332
{"no-security-label", no_argument, &no_security_label, 1},
333
{"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
338
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
342
strcpy(g_comment_start, "-- ");
343
g_comment_end[0] = '\0';
344
strcpy(g_opaque_type, "opaque");
346
dataOnly = schemaOnly = false;
347
lockWaitTimeout = NULL;
349
progname = get_progname(argv[0]);
351
/* Set default options based on progname */
352
if (strcmp(progname, "pg_backup") == 0)
357
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
362
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
364
puts("pg_dump (PostgreSQL) " PG_VERSION);
369
while ((c = getopt_long(argc, argv, "abcCE:f:F:h:in:N:oOp:RsS:t:T:U:vwWxZ:",
370
long_options, &optindex)) != -1)
374
case 'a': /* Dump data only */
378
case 'b': /* Dump blobs */
382
case 'c': /* clean (i.e., drop) schema prior to create */
386
case 'C': /* Create DB */
390
case 'E': /* Dump encoding */
391
dumpencoding = optarg;
402
case 'h': /* server host */
407
/* ignored, deprecated option */
410
case 'n': /* include schema(s) */
411
simple_string_list_append(&schema_include_patterns, optarg);
412
include_everything = false;
415
case 'N': /* exclude schema(s) */
416
simple_string_list_append(&schema_exclude_patterns, optarg);
419
case 'o': /* Dump oids */
423
case 'O': /* Don't reconnect to match owner */
427
case 'p': /* server port */
432
/* no-op, still accepted for backwards compatibility */
435
case 's': /* dump schema only */
439
case 'S': /* Username for superuser in plain text output */
440
outputSuperuser = strdup(optarg);
443
case 't': /* include table(s) */
444
simple_string_list_append(&table_include_patterns, optarg);
445
include_everything = false;
448
case 'T': /* exclude table(s) */
449
simple_string_list_append(&table_exclude_patterns, optarg);
456
case 'v': /* verbose */
461
prompt_password = TRI_NO;
465
prompt_password = TRI_YES;
468
case 'x': /* skip ACL dump */
472
case 'Z': /* Compression Level */
473
compressLevel = atoi(optarg);
477
/* This covers the long options. */
480
case 2: /* lock-wait-timeout */
481
lockWaitTimeout = optarg;
484
case 3: /* SET ROLE */
489
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
494
/* Get database name from command line */
496
dbname = argv[optind++];
498
/* Complain if any arguments remain */
501
fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
502
progname, argv[optind]);
503
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
508
/* --column-inserts implies --inserts */
512
if (dataOnly && schemaOnly)
514
write_msg(NULL, "options -s/--schema-only and -a/--data-only cannot be used together\n");
518
if (dataOnly && outputClean)
520
write_msg(NULL, "options -c/--clean and -a/--data-only cannot be used together\n");
524
if (dump_inserts && oids)
526
write_msg(NULL, "options --inserts/--column-inserts and -o/--oids cannot be used together\n");
527
write_msg(NULL, "(The INSERT command cannot set OIDs.)\n");
531
archiveFormat = parseArchiveFormat(format, &archiveMode);
533
/* archiveFormat specific setup */
534
if (archiveFormat == archNull)
538
* Ignore compression level for plain format. XXX: This is a bit
539
* inconsistent, tar-format throws an error instead.
541
if (archiveFormat == archNull)
544
/* Custom and directory formats are compressed by default */
545
if (compressLevel == -1)
547
if (archiveFormat == archCustom || archiveFormat == archDirectory)
548
compressLevel = Z_DEFAULT_COMPRESSION;
553
/* open the output file */
554
g_fout = CreateArchive(filename, archiveFormat, compressLevel, archiveMode);
558
write_msg(NULL, "could not open output file \"%s\" for writing\n", filename);
562
/* Let the archiver know how noisy to be */
563
g_fout->verbose = g_verbose;
565
my_version = parse_version(PG_VERSION);
568
write_msg(NULL, "could not parse version string \"%s\"\n", PG_VERSION);
573
* We allow the server to be back to 7.0, and up to any minor release of
574
* our own major version. (See also version check in pg_dumpall.c.)
576
g_fout->minRemoteVersion = 70000;
577
g_fout->maxRemoteVersion = (my_version / 100) * 100 + 99;
580
* Open the database using the Archiver, so it knows about it. Errors mean
583
g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport,
584
username, prompt_password);
586
/* Set the client encoding if requested */
589
if (PQsetClientEncoding(g_conn, dumpencoding) < 0)
591
write_msg(NULL, "invalid client encoding \"%s\" specified\n",
598
* Get the active encoding and the standard_conforming_strings setting, so
599
* we know how to escape strings.
601
g_fout->encoding = PQclientEncoding(g_conn);
603
std_strings = PQparameterStatus(g_conn, "standard_conforming_strings");
604
g_fout->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
606
/* Set the role if requested */
607
if (use_role && g_fout->remoteVersion >= 80100)
609
PQExpBuffer query = createPQExpBuffer();
611
appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
612
do_sql_command(g_conn, query->data);
613
destroyPQExpBuffer(query);
616
/* Set the datestyle to ISO to ensure the dump's portability */
617
do_sql_command(g_conn, "SET DATESTYLE = ISO");
619
/* Likewise, avoid using sql_standard intervalstyle */
620
if (g_fout->remoteVersion >= 80400)
621
do_sql_command(g_conn, "SET INTERVALSTYLE = POSTGRES");
624
* If supported, set extra_float_digits so that we can dump float data
625
* exactly (given correctly implemented float I/O code, anyway)
627
if (g_fout->remoteVersion >= 90000)
628
do_sql_command(g_conn, "SET extra_float_digits TO 3");
629
else if (g_fout->remoteVersion >= 70400)
630
do_sql_command(g_conn, "SET extra_float_digits TO 2");
633
* If synchronized scanning is supported, disable it, to prevent
634
* unpredictable changes in row ordering across a dump and reload.
636
if (g_fout->remoteVersion >= 80300)
637
do_sql_command(g_conn, "SET synchronize_seqscans TO off");
640
* Disable timeouts if supported.
642
if (g_fout->remoteVersion >= 70300)
643
do_sql_command(g_conn, "SET statement_timeout = 0");
646
* Quote all identifiers, if requested.
648
if (quote_all_identifiers && g_fout->remoteVersion >= 90100)
649
do_sql_command(g_conn, "SET quote_all_identifiers = true");
652
* Disables security label support if server version < v9.1.x
654
if (!no_security_label && g_fout->remoteVersion < 90100)
655
no_security_label = 1;
658
* Start transaction-snapshot mode transaction to dump consistent data.
660
do_sql_command(g_conn, "BEGIN");
661
if (g_fout->remoteVersion >= 90100)
663
if (serializable_deferrable)
664
do_sql_command(g_conn,
665
"SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, "
666
"READ ONLY, DEFERRABLE");
668
do_sql_command(g_conn,
669
"SET TRANSACTION ISOLATION LEVEL REPEATABLE READ");
672
do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
674
/* Select the appropriate subquery to convert user IDs to names */
675
if (g_fout->remoteVersion >= 80100)
676
username_subquery = "SELECT rolname FROM pg_catalog.pg_roles WHERE oid =";
677
else if (g_fout->remoteVersion >= 70300)
678
username_subquery = "SELECT usename FROM pg_catalog.pg_user WHERE usesysid =";
680
username_subquery = "SELECT usename FROM pg_user WHERE usesysid =";
682
/* Find the last built-in OID, if needed */
683
if (g_fout->remoteVersion < 70300)
685
if (g_fout->remoteVersion >= 70100)
686
g_last_builtin_oid = findLastBuiltinOid_V71(PQdb(g_conn));
688
g_last_builtin_oid = findLastBuiltinOid_V70();
690
write_msg(NULL, "last built-in OID is %u\n", g_last_builtin_oid);
693
/* Expand schema selection patterns into OID lists */
694
if (schema_include_patterns.head != NULL)
696
expand_schema_name_patterns(&schema_include_patterns,
697
&schema_include_oids);
698
if (schema_include_oids.head == NULL)
700
write_msg(NULL, "No matching schemas were found\n");
704
expand_schema_name_patterns(&schema_exclude_patterns,
705
&schema_exclude_oids);
706
/* non-matching exclusion patterns aren't an error */
708
/* Expand table selection patterns into OID lists */
709
if (table_include_patterns.head != NULL)
711
expand_table_name_patterns(&table_include_patterns,
712
&table_include_oids);
713
if (table_include_oids.head == NULL)
715
write_msg(NULL, "No matching tables were found\n");
719
expand_table_name_patterns(&table_exclude_patterns,
720
&table_exclude_oids);
721
/* non-matching exclusion patterns aren't an error */
724
* Dumping blobs is now default unless we saw an inclusion switch or -s
725
* ... but even if we did see one of these, -b turns it back on.
727
if (include_everything && !schemaOnly)
731
* Now scan the database and create DumpableObject structs for all the
732
* objects we intend to dump.
734
tblinfo = getSchemaData(&numTables);
736
if (g_fout->remoteVersion < 80400)
737
guessConstraintInheritance(tblinfo, numTables);
741
getTableData(tblinfo, numTables, oids);
743
getTableDataFKConstraints();
750
* Collect dependency data to assist in ordering the objects.
755
* Sort the objects into a safe dump order (no forward references).
757
* In 7.3 or later, we can rely on dependency information to help us
758
* determine a safe order, so the initial sort is mostly for cosmetic
759
* purposes: we sort by name to ensure that logically identical schemas
760
* will dump identically. Before 7.3 we don't have dependencies and we
761
* use OID ordering as an (unreliable) guide to creation order.
763
getDumpableObjects(&dobjs, &numObjs);
765
if (g_fout->remoteVersion >= 70300)
766
sortDumpableObjectsByTypeName(dobjs, numObjs);
768
sortDumpableObjectsByTypeOid(dobjs, numObjs);
770
sortDumpableObjects(dobjs, numObjs);
773
* Create archive TOC entries for all the objects to be dumped, in a safe
777
/* First the special ENCODING and STDSTRINGS entries. */
778
dumpEncoding(g_fout);
779
dumpStdStrings(g_fout);
781
/* The database item is always next, unless we don't want it at all */
782
if (include_everything && !dataOnly)
783
dumpDatabase(g_fout);
785
/* Now the rearrangeable objects. */
786
for (i = 0; i < numObjs; i++)
787
dumpDumpableObject(g_fout, dobjs[i]);
790
* And finally we can do the actual output.
794
ropt = NewRestoreOptions();
795
ropt->filename = (char *) filename;
796
ropt->dropSchema = outputClean;
797
ropt->aclsSkip = aclsSkip;
798
ropt->superuser = outputSuperuser;
799
ropt->createDB = outputCreateDB;
800
ropt->noOwner = outputNoOwner;
801
ropt->noTablespace = outputNoTablespaces;
802
ropt->disable_triggers = disable_triggers;
803
ropt->use_setsessauth = use_setsessauth;
804
ropt->dataOnly = dataOnly;
806
if (compressLevel == -1)
807
ropt->compression = 0;
809
ropt->compression = compressLevel;
811
ropt->suppressDumpWarnings = true; /* We've already shown them */
813
RestoreArchive(g_fout, ropt);
816
CloseArchive(g_fout);
825
help(const char *progname)
827
printf(_("%s dumps a database as a text file or to other formats.\n\n"), progname);
828
printf(_("Usage:\n"));
829
printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
831
printf(_("\nGeneral options:\n"));
832
printf(_(" -f, --file=OUTPUT output file or directory name\n"));
833
printf(_(" -F, --format=c|d|t|p output file format (custom, directory, tar, plain text)\n"));
834
printf(_(" -v, --verbose verbose mode\n"));
835
printf(_(" -Z, --compress=0-9 compression level for compressed formats\n"));
836
printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
837
printf(_(" --help show this help, then exit\n"));
838
printf(_(" --version output version information, then exit\n"));
840
printf(_("\nOptions controlling the output content:\n"));
841
printf(_(" -a, --data-only dump only the data, not the schema\n"));
842
printf(_(" -b, --blobs include large objects in dump\n"));
843
printf(_(" -c, --clean clean (drop) database objects before recreating\n"));
844
printf(_(" -C, --create include commands to create database in dump\n"));
845
printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
846
printf(_(" -n, --schema=SCHEMA dump the named schema(s) only\n"));
847
printf(_(" -N, --exclude-schema=SCHEMA do NOT dump the named schema(s)\n"));
848
printf(_(" -o, --oids include OIDs in dump\n"));
849
printf(_(" -O, --no-owner skip restoration of object ownership in\n"
850
" plain-text format\n"));
851
printf(_(" -s, --schema-only dump only the schema, no data\n"));
852
printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n"));
853
printf(_(" -t, --table=TABLE dump the named table(s) only\n"));
854
printf(_(" -T, --exclude-table=TABLE do NOT dump the named table(s)\n"));
855
printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
856
printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
857
printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
858
printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
859
printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
860
printf(_(" --disable-triggers disable triggers during data-only restore\n"));
861
printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
862
printf(_(" --quote-all-identifiers quote all identifiers, even if not keywords\n"));
863
printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n"));
864
printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
865
printf(_(" --no-security-label do not dump security label assignments\n"));
866
printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
867
printf(_(" --use-set-session-authorization\n"
868
" use SET SESSION AUTHORIZATION commands instead of\n"
869
" ALTER OWNER commands to set ownership\n"));
871
printf(_("\nConnection options:\n"));
872
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
873
printf(_(" -p, --port=PORT database server port number\n"));
874
printf(_(" -U, --username=NAME connect as specified database user\n"));
875
printf(_(" -w, --no-password never prompt for password\n"));
876
printf(_(" -W, --password force password prompt (should happen automatically)\n"));
878
printf(_("\nIf no database name is supplied, then the PGDATABASE environment\n"
879
"variable value is used.\n\n"));
880
printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
888
write_msg(NULL, "*** aborted because of error\n");
893
parseArchiveFormat(const char *format, ArchiveMode *mode)
895
ArchiveFormat archiveFormat;
897
*mode = archModeWrite;
899
if (pg_strcasecmp(format, "a") == 0 || pg_strcasecmp(format, "append") == 0)
901
/* This is used by pg_dumpall, and is not documented */
902
archiveFormat = archNull;
903
*mode = archModeAppend;
905
else if (pg_strcasecmp(format, "c") == 0)
906
archiveFormat = archCustom;
907
else if (pg_strcasecmp(format, "custom") == 0)
908
archiveFormat = archCustom;
909
else if (pg_strcasecmp(format, "d") == 0)
910
archiveFormat = archDirectory;
911
else if (pg_strcasecmp(format, "directory") == 0)
912
archiveFormat = archDirectory;
913
else if (pg_strcasecmp(format, "f") == 0 || pg_strcasecmp(format, "file") == 0)
916
* Dump files into the current directory; for demonstration only, not
919
archiveFormat = archFiles;
920
else if (pg_strcasecmp(format, "p") == 0)
921
archiveFormat = archNull;
922
else if (pg_strcasecmp(format, "plain") == 0)
923
archiveFormat = archNull;
924
else if (pg_strcasecmp(format, "t") == 0)
925
archiveFormat = archTar;
926
else if (pg_strcasecmp(format, "tar") == 0)
927
archiveFormat = archTar;
930
write_msg(NULL, "invalid output format \"%s\" specified\n", format);
933
return archiveFormat;
937
* Find the OIDs of all schemas matching the given list of patterns,
938
* and append them to the given OID list.
941
expand_schema_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
945
SimpleStringListCell *cell;
948
if (patterns->head == NULL)
949
return; /* nothing to do */
951
if (g_fout->remoteVersion < 70300)
953
write_msg(NULL, "server version must be at least 7.3 to use schema selection switches\n");
957
query = createPQExpBuffer();
960
* We use UNION ALL rather than UNION; this might sometimes result in
961
* duplicate entries in the OID list, but we don't care.
964
for (cell = patterns->head; cell; cell = cell->next)
966
if (cell != patterns->head)
967
appendPQExpBuffer(query, "UNION ALL\n");
968
appendPQExpBuffer(query,
969
"SELECT oid FROM pg_catalog.pg_namespace n\n");
970
processSQLNamePattern(g_conn, query, cell->val, false, false,
971
NULL, "n.nspname", NULL,
975
res = PQexec(g_conn, query->data);
976
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
978
for (i = 0; i < PQntuples(res); i++)
980
simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
984
destroyPQExpBuffer(query);
988
* Find the OIDs of all tables matching the given list of patterns,
989
* and append them to the given OID list.
992
expand_table_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
996
SimpleStringListCell *cell;
999
if (patterns->head == NULL)
1000
return; /* nothing to do */
1002
query = createPQExpBuffer();
1005
* We use UNION ALL rather than UNION; this might sometimes result in
1006
* duplicate entries in the OID list, but we don't care.
1009
for (cell = patterns->head; cell; cell = cell->next)
1011
if (cell != patterns->head)
1012
appendPQExpBuffer(query, "UNION ALL\n");
1013
appendPQExpBuffer(query,
1015
"\nFROM pg_catalog.pg_class c"
1016
"\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
1017
"\nWHERE c.relkind in ('%c', '%c', '%c', '%c')\n",
1018
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
1019
RELKIND_FOREIGN_TABLE);
1020
processSQLNamePattern(g_conn, query, cell->val, true, false,
1021
"n.nspname", "c.relname", NULL,
1022
"pg_catalog.pg_table_is_visible(c.oid)");
1025
res = PQexec(g_conn, query->data);
1026
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
1028
for (i = 0; i < PQntuples(res); i++)
1030
simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
1034
destroyPQExpBuffer(query);
1038
* selectDumpableNamespace: policy-setting subroutine
1039
* Mark a namespace as to be dumped or not
1042
selectDumpableNamespace(NamespaceInfo *nsinfo)
1045
* If specific tables are being dumped, do not dump any complete
1046
* namespaces. If specific namespaces are being dumped, dump just those
1047
* namespaces. Otherwise, dump all non-system namespaces.
1049
if (table_include_oids.head != NULL)
1050
nsinfo->dobj.dump = false;
1051
else if (schema_include_oids.head != NULL)
1052
nsinfo->dobj.dump = simple_oid_list_member(&schema_include_oids,
1053
nsinfo->dobj.catId.oid);
1054
else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 ||
1055
strcmp(nsinfo->dobj.name, "information_schema") == 0)
1056
nsinfo->dobj.dump = false;
1058
nsinfo->dobj.dump = true;
1061
* In any case, a namespace can be excluded by an exclusion switch
1063
if (nsinfo->dobj.dump &&
1064
simple_oid_list_member(&schema_exclude_oids,
1065
nsinfo->dobj.catId.oid))
1066
nsinfo->dobj.dump = false;
1070
* selectDumpableTable: policy-setting subroutine
1071
* Mark a table as to be dumped or not
1074
selectDumpableTable(TableInfo *tbinfo)
1077
* If specific tables are being dumped, dump just those tables; else, dump
1078
* according to the parent namespace's dump flag.
1080
if (table_include_oids.head != NULL)
1081
tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids,
1082
tbinfo->dobj.catId.oid);
1084
tbinfo->dobj.dump = tbinfo->dobj.namespace->dobj.dump;
1087
* In any case, a table can be excluded by an exclusion switch
1089
if (tbinfo->dobj.dump &&
1090
simple_oid_list_member(&table_exclude_oids,
1091
tbinfo->dobj.catId.oid))
1092
tbinfo->dobj.dump = false;
1096
* selectDumpableType: policy-setting subroutine
1097
* Mark a type as to be dumped or not
1099
* If it's a table's rowtype or an autogenerated array type, we also apply a
1100
* special type code to facilitate sorting into the desired order. (We don't
1101
* want to consider those to be ordinary types because that would bring tables
1102
* up into the datatype part of the dump order.) Those tests should be made
1103
* first to ensure the objType change is applied regardless of namespace etc.
1106
selectDumpableType(TypeInfo *tyinfo)
1108
/* skip complex types, except for standalone composite types */
1109
if (OidIsValid(tyinfo->typrelid) &&
1110
tyinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
1112
tyinfo->dobj.dump = false;
1113
tyinfo->dobj.objType = DO_DUMMY_TYPE;
1116
/* skip auto-generated array types */
1117
else if (tyinfo->isArray)
1119
tyinfo->dobj.dump = false;
1120
tyinfo->dobj.objType = DO_DUMMY_TYPE;
1123
/* dump only types in dumpable namespaces */
1124
else if (!tyinfo->dobj.namespace->dobj.dump)
1125
tyinfo->dobj.dump = false;
1127
/* skip undefined placeholder types */
1128
else if (!tyinfo->isDefined)
1129
tyinfo->dobj.dump = false;
1132
tyinfo->dobj.dump = true;
1136
* selectDumpableDefaultACL: policy-setting subroutine
1137
* Mark a default ACL as to be dumped or not
1139
* For per-schema default ACLs, dump if the schema is to be dumped.
1140
* Otherwise dump if we are dumping "everything". Note that dataOnly
1141
* and aclsSkip are checked separately.
1144
selectDumpableDefaultACL(DefaultACLInfo *dinfo)
1146
if (dinfo->dobj.namespace)
1147
dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump;
1149
dinfo->dobj.dump = include_everything;
1153
* selectDumpableExtension: policy-setting subroutine
1154
* Mark an extension as to be dumped or not
1156
* Normally, we just dump all extensions. However, in binary-upgrade mode
1157
* it's necessary to skip built-in extensions, since we assume those will
1158
* already be installed in the target database. We identify such extensions
1159
* by their having OIDs in the range reserved for initdb.
1162
selectDumpableExtension(ExtensionInfo *extinfo)
1164
if (binary_upgrade && extinfo->dobj.catId.oid < (Oid) FirstNormalObjectId)
1165
extinfo->dobj.dump = false;
1167
extinfo->dobj.dump = true;
1171
* selectDumpableObject: policy-setting subroutine
1172
* Mark a generic dumpable object as to be dumped or not
1174
* Use this only for object types without a special-case routine above.
1177
selectDumpableObject(DumpableObject *dobj)
1180
* Default policy is to dump if parent namespace is dumpable, or always
1181
* for non-namespace-associated items.
1183
if (dobj->namespace)
1184
dobj->dump = dobj->namespace->dobj.dump;
1190
* Dump a table's contents for loading using the COPY command
1191
* - this routine is called by the Archiver when it wants the table
1196
dumpTableData_copy(Archive *fout, void *dcontext)
1198
TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
1199
TableInfo *tbinfo = tdinfo->tdtable;
1200
const char *classname = tbinfo->dobj.name;
1201
const bool hasoids = tbinfo->hasoids;
1202
const bool oids = tdinfo->oids;
1203
PQExpBuffer q = createPQExpBuffer();
1207
const char *column_list;
1210
write_msg(NULL, "dumping contents of table %s\n", classname);
1213
* Make sure we are in proper schema. We will qualify the table name
1214
* below anyway (in case its name conflicts with a pg_catalog table); but
1215
* this ensures reproducible results in case the table contains regproc,
1216
* regclass, etc columns.
1218
selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
1221
* If possible, specify the column list explicitly so that we have no
1222
* possibility of retrieving data in the wrong column order. (The default
1223
* column ordering of COPY will not be what we want in certain corner
1224
* cases involving ADD COLUMN and inheritance.)
1226
if (g_fout->remoteVersion >= 70300)
1227
column_list = fmtCopyColumnList(tbinfo);
1229
column_list = ""; /* can't select columns in COPY */
1231
if (oids && hasoids)
1233
appendPQExpBuffer(q, "COPY %s %s WITH OIDS TO stdout;",
1234
fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
1238
else if (tdinfo->filtercond)
1240
/* Note: this syntax is only supported in 8.2 and up */
1241
appendPQExpBufferStr(q, "COPY (SELECT ");
1242
/* klugery to get rid of parens in column list */
1243
if (strlen(column_list) > 2)
1245
appendPQExpBufferStr(q, column_list + 1);
1246
q->data[q->len - 1] = ' ';
1249
appendPQExpBufferStr(q, "* ");
1250
appendPQExpBuffer(q, "FROM %s %s) TO stdout;",
1251
fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
1253
tdinfo->filtercond);
1257
appendPQExpBuffer(q, "COPY %s %s TO stdout;",
1258
fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
1262
res = PQexec(g_conn, q->data);
1263
check_sql_result(res, g_conn, q->data, PGRES_COPY_OUT);
1268
ret = PQgetCopyData(g_conn, ©buf, 0);
1271
break; /* done or error */
1275
WriteData(fout, copybuf, ret);
1282
* There was considerable discussion in late July, 2000 regarding
1283
* slowing down pg_dump when backing up large tables. Users with both
1284
* slow & fast (multi-processor) machines experienced performance
1285
* degradation when doing a backup.
1287
* Initial attempts based on sleeping for a number of ms for each ms
1288
* of work were deemed too complex, then a simple 'sleep in each loop'
1289
* implementation was suggested. The latter failed because the loop
1290
* was too tight. Finally, the following was implemented:
1292
* If throttle is non-zero, then
1293
* See how long since the last sleep.
1294
* Work out how long to sleep (based on ratio).
1295
* If sleep is more than 100ms, then
1301
* where the throttle value was the number of ms to sleep per ms of
1302
* work. The calculation was done in each loop.
1304
* Most of the hard work is done in the backend, and this solution
1305
* still did not work particularly well: on slow machines, the ratio
1306
* was 50:1, and on medium paced machines, 1:1, and on fast
1307
* multi-processor machines, it had little or no effect, for reasons
1308
* that were unclear.
1310
* Further discussion ensued, and the proposal was dropped.
1312
* For those people who want this feature, it can be implemented using
1313
* gettimeofday in each loop, calculating the time since last sleep,
1314
* multiplying that by the sleep ratio, then if the result is more
1315
* than a preset 'minimum sleep time' (say 100ms), call the 'select'
1316
* function to sleep for a subsecond period ie.
1318
* select(0, NULL, NULL, NULL, &tvi);
1320
* This will return after the interval specified in the structure tvi.
1321
* Finally, call gettimeofday again to save the 'last sleep time'.
1325
archprintf(fout, "\\.\n\n\n");
1329
/* copy data transfer failed */
1330
write_msg(NULL, "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed.\n", classname);
1331
write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
1332
write_msg(NULL, "The command was: %s\n", q->data);
1336
/* Check command status and return to normal libpq state */
1337
res = PQgetResult(g_conn);
1338
check_sql_result(res, g_conn, q->data, PGRES_COMMAND_OK);
1341
destroyPQExpBuffer(q);
1346
dumpTableData_insert(Archive *fout, void *dcontext)
1348
TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
1349
TableInfo *tbinfo = tdinfo->tdtable;
1350
const char *classname = tbinfo->dobj.name;
1351
PQExpBuffer q = createPQExpBuffer();
1358
* Make sure we are in proper schema. We will qualify the table name
1359
* below anyway (in case its name conflicts with a pg_catalog table); but
1360
* this ensures reproducible results in case the table contains regproc,
1361
* regclass, etc columns.
1363
selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
1365
if (fout->remoteVersion >= 70100)
1367
appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
1368
"SELECT * FROM ONLY %s",
1369
fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
1374
appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
1376
fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
1379
if (tdinfo->filtercond)
1380
appendPQExpBuffer(q, " %s", tdinfo->filtercond);
1382
res = PQexec(g_conn, q->data);
1383
check_sql_result(res, g_conn, q->data, PGRES_COMMAND_OK);
1389
res = PQexec(g_conn, "FETCH 100 FROM _pg_dump_cursor");
1390
check_sql_result(res, g_conn, "FETCH 100 FROM _pg_dump_cursor",
1392
nfields = PQnfields(res);
1393
for (tuple = 0; tuple < PQntuples(res); tuple++)
1395
archprintf(fout, "INSERT INTO %s ", fmtId(classname));
1398
/* corner case for zero-column table */
1399
archprintf(fout, "DEFAULT VALUES;\n");
1404
resetPQExpBuffer(q);
1405
appendPQExpBuffer(q, "(");
1406
for (field = 0; field < nfields; field++)
1409
appendPQExpBuffer(q, ", ");
1410
appendPQExpBufferStr(q, fmtId(PQfname(res, field)));
1412
appendPQExpBuffer(q, ") ");
1413
archputs(q->data, fout);
1415
archprintf(fout, "VALUES (");
1416
for (field = 0; field < nfields; field++)
1419
archprintf(fout, ", ");
1420
if (PQgetisnull(res, tuple, field))
1422
archprintf(fout, "NULL");
1426
/* XXX This code is partially duplicated in ruleutils.c */
1427
switch (PQftype(res, field))
1438
* These types are printed without quotes unless
1439
* they contain values that aren't accepted by the
1440
* scanner unquoted (e.g., 'NaN'). Note that
1441
* strtod() and friends might accept NaN, so we
1442
* can't use that to test.
1444
* In reality we only need to defend against
1445
* infinity and NaN, so we need not get too crazy
1446
* about pattern matching here.
1448
const char *s = PQgetvalue(res, tuple, field);
1450
if (strspn(s, "0123456789 +-eE.") == strlen(s))
1451
archprintf(fout, "%s", s);
1453
archprintf(fout, "'%s'", s);
1459
archprintf(fout, "B'%s'",
1460
PQgetvalue(res, tuple, field));
1464
if (strcmp(PQgetvalue(res, tuple, field), "t") == 0)
1465
archprintf(fout, "true");
1467
archprintf(fout, "false");
1471
/* All other types are printed as string literals. */
1472
resetPQExpBuffer(q);
1473
appendStringLiteralAH(q,
1474
PQgetvalue(res, tuple, field),
1476
archputs(q->data, fout);
1480
archprintf(fout, ");\n");
1482
} while (PQntuples(res) > 0);
1486
archprintf(fout, "\n\n");
1488
do_sql_command(g_conn, "CLOSE _pg_dump_cursor");
1490
destroyPQExpBuffer(q);
1497
* dump the contents of a single table
1499
* Actually, this just makes an ArchiveEntry for the table contents.
1502
dumpTableData(Archive *fout, TableDataInfo *tdinfo)
1504
TableInfo *tbinfo = tdinfo->tdtable;
1505
PQExpBuffer copyBuf = createPQExpBuffer();
1506
DataDumperPtr dumpFn;
1511
/* Dump/restore using COPY */
1512
dumpFn = dumpTableData_copy;
1513
/* must use 2 steps here 'cause fmtId is nonreentrant */
1514
appendPQExpBuffer(copyBuf, "COPY %s ",
1515
fmtId(tbinfo->dobj.name));
1516
appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n",
1517
fmtCopyColumnList(tbinfo),
1518
(tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "");
1519
copyStmt = copyBuf->data;
1523
/* Restore using INSERT */
1524
dumpFn = dumpTableData_insert;
1528
ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
1529
tbinfo->dobj.name, tbinfo->dobj.namespace->dobj.name,
1530
NULL, tbinfo->rolname,
1531
false, "TABLE DATA", SECTION_DATA,
1533
tdinfo->dobj.dependencies, tdinfo->dobj.nDeps,
1536
destroyPQExpBuffer(copyBuf);
1541
* set up dumpable objects representing the contents of tables
1544
getTableData(TableInfo *tblinfo, int numTables, bool oids)
1548
for (i = 0; i < numTables; i++)
1550
/* Skip VIEWs (no data to dump) */
1551
if (tblinfo[i].relkind == RELKIND_VIEW)
1553
/* Skip SEQUENCEs (handled elsewhere) */
1554
if (tblinfo[i].relkind == RELKIND_SEQUENCE)
1556
/* Skip FOREIGN TABLEs (no data to dump) */
1557
if (tblinfo[i].relkind == RELKIND_FOREIGN_TABLE)
1559
/* Skip unlogged tables if so requested */
1560
if (tblinfo[i].relpersistence == RELPERSISTENCE_UNLOGGED
1561
&& no_unlogged_table_data)
1564
if (tblinfo[i].dobj.dump && tblinfo[i].dataObj == NULL)
1565
makeTableDataInfo(&(tblinfo[i]), oids);
1570
* Make a dumpable object for the data of this specific table
1573
makeTableDataInfo(TableInfo *tbinfo, bool oids)
1575
TableDataInfo *tdinfo;
1577
tdinfo = (TableDataInfo *) malloc(sizeof(TableDataInfo));
1579
tdinfo->dobj.objType = DO_TABLE_DATA;
1582
* Note: use tableoid 0 so that this object won't be mistaken for
1583
* something that pg_depend entries apply to.
1585
tdinfo->dobj.catId.tableoid = 0;
1586
tdinfo->dobj.catId.oid = tbinfo->dobj.catId.oid;
1587
AssignDumpId(&tdinfo->dobj);
1588
tdinfo->dobj.name = tbinfo->dobj.name;
1589
tdinfo->dobj.namespace = tbinfo->dobj.namespace;
1590
tdinfo->tdtable = tbinfo;
1591
tdinfo->oids = oids;
1592
tdinfo->filtercond = NULL; /* might get set later */
1593
addObjectDependency(&tdinfo->dobj, tbinfo->dobj.dumpId);
1595
tbinfo->dataObj = tdinfo;
1599
* getTableDataFKConstraints -
1600
* add dump-order dependencies reflecting foreign key constraints
1602
* This code is executed only in a data-only dump --- in schema+data dumps
1603
* we handle foreign key issues by not creating the FK constraints until
1604
* after the data is loaded. In a data-only dump, however, we want to
1605
* order the table data objects in such a way that a table's referenced
1606
* tables are restored first. (In the presence of circular references or
1607
* self-references this may be impossible; we'll detect and complain about
1608
* that during the dependency sorting step.)
1611
getTableDataFKConstraints(void)
1613
DumpableObject **dobjs;
1617
/* Search through all the dumpable objects for FK constraints */
1618
getDumpableObjects(&dobjs, &numObjs);
1619
for (i = 0; i < numObjs; i++)
1621
if (dobjs[i]->objType == DO_FK_CONSTRAINT)
1623
ConstraintInfo *cinfo = (ConstraintInfo *) dobjs[i];
1626
/* Not interesting unless both tables are to be dumped */
1627
if (cinfo->contable == NULL ||
1628
cinfo->contable->dataObj == NULL)
1630
ftable = findTableByOid(cinfo->confrelid);
1631
if (ftable == NULL ||
1632
ftable->dataObj == NULL)
1636
* Okay, make referencing table's TABLE_DATA object depend on the
1637
* referenced table's TABLE_DATA object.
1639
addObjectDependency(&cinfo->contable->dataObj->dobj,
1640
ftable->dataObj->dobj.dumpId);
1648
* guessConstraintInheritance:
1649
* In pre-8.4 databases, we can't tell for certain which constraints
1650
* are inherited. We assume a CHECK constraint is inherited if its name
1651
* matches the name of any constraint in the parent. Originally this code
1652
* tried to compare the expression texts, but that can fail for various
1653
* reasons --- for example, if the parent and child tables are in different
1654
* schemas, reverse-listing of function calls may produce different text
1655
* (schema-qualified or not) depending on search path.
1657
* In 8.4 and up we can rely on the conislocal field to decide which
1658
* constraints must be dumped; much safer.
1660
* This function assumes all conislocal flags were initialized to TRUE.
1661
* It clears the flag on anything that seems to be inherited.
1664
guessConstraintInheritance(TableInfo *tblinfo, int numTables)
1670
for (i = 0; i < numTables; i++)
1672
TableInfo *tbinfo = &(tblinfo[i]);
1674
TableInfo **parents;
1677
/* Sequences and views never have parents */
1678
if (tbinfo->relkind == RELKIND_SEQUENCE ||
1679
tbinfo->relkind == RELKIND_VIEW)
1682
/* Don't bother computing anything for non-target tables, either */
1683
if (!tbinfo->dobj.dump)
1686
numParents = tbinfo->numParents;
1687
parents = tbinfo->parents;
1689
if (numParents == 0)
1690
continue; /* nothing to see here, move along */
1692
/* scan for inherited CHECK constraints */
1693
for (j = 0; j < tbinfo->ncheck; j++)
1695
ConstraintInfo *constr;
1697
constr = &(tbinfo->checkexprs[j]);
1699
for (k = 0; k < numParents; k++)
1703
parent = parents[k];
1704
for (l = 0; l < parent->ncheck; l++)
1706
ConstraintInfo *pconstr = &(parent->checkexprs[l]);
1708
if (strcmp(pconstr->dobj.name, constr->dobj.name) == 0)
1710
constr->conislocal = false;
1714
if (!constr->conislocal)
1724
* dump the database definition
1727
dumpDatabase(Archive *AH)
1729
PQExpBuffer dbQry = createPQExpBuffer();
1730
PQExpBuffer delQry = createPQExpBuffer();
1731
PQExpBuffer creaQry = createPQExpBuffer();
1744
const char *datname,
1752
datname = PQdb(g_conn);
1755
write_msg(NULL, "saving database definition\n");
1757
/* Make sure we are in proper schema */
1758
selectSourceSchema("pg_catalog");
1760
/* Get the database owner and parameters from pg_database */
1761
if (g_fout->remoteVersion >= 80400)
1763
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
1764
"(%s datdba) AS dba, "
1765
"pg_encoding_to_char(encoding) AS encoding, "
1766
"datcollate, datctype, datfrozenxid, "
1767
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
1768
"shobj_description(oid, 'pg_database') AS description "
1773
appendStringLiteralAH(dbQry, datname, AH);
1775
else if (g_fout->remoteVersion >= 80200)
1777
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
1778
"(%s datdba) AS dba, "
1779
"pg_encoding_to_char(encoding) AS encoding, "
1780
"NULL AS datcollate, NULL AS datctype, datfrozenxid, "
1781
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
1782
"shobj_description(oid, 'pg_database') AS description "
1787
appendStringLiteralAH(dbQry, datname, AH);
1789
else if (g_fout->remoteVersion >= 80000)
1791
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
1792
"(%s datdba) AS dba, "
1793
"pg_encoding_to_char(encoding) AS encoding, "
1794
"NULL AS datcollate, NULL AS datctype, datfrozenxid, "
1795
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace "
1799
appendStringLiteralAH(dbQry, datname, AH);
1801
else if (g_fout->remoteVersion >= 70100)
1803
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
1804
"(%s datdba) AS dba, "
1805
"pg_encoding_to_char(encoding) AS encoding, "
1806
"NULL AS datcollate, NULL AS datctype, "
1807
"0 AS datfrozenxid, "
1808
"NULL AS tablespace "
1812
appendStringLiteralAH(dbQry, datname, AH);
1816
appendPQExpBuffer(dbQry, "SELECT "
1817
"(SELECT oid FROM pg_class WHERE relname = 'pg_database') AS tableoid, "
1819
"(%s datdba) AS dba, "
1820
"pg_encoding_to_char(encoding) AS encoding, "
1821
"NULL AS datcollate, NULL AS datctype, "
1822
"0 AS datfrozenxid, "
1823
"NULL AS tablespace "
1827
appendStringLiteralAH(dbQry, datname, AH);
1830
res = PQexec(g_conn, dbQry->data);
1831
check_sql_result(res, g_conn, dbQry->data, PGRES_TUPLES_OK);
1833
ntups = PQntuples(res);
1837
write_msg(NULL, "missing pg_database entry for database \"%s\"\n",
1844
write_msg(NULL, "query returned more than one (%d) pg_database entry for database \"%s\"\n",
1849
i_tableoid = PQfnumber(res, "tableoid");
1850
i_oid = PQfnumber(res, "oid");
1851
i_dba = PQfnumber(res, "dba");
1852
i_encoding = PQfnumber(res, "encoding");
1853
i_collate = PQfnumber(res, "datcollate");
1854
i_ctype = PQfnumber(res, "datctype");
1855
i_frozenxid = PQfnumber(res, "datfrozenxid");
1856
i_tablespace = PQfnumber(res, "tablespace");
1858
dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid));
1859
dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid));
1860
dba = PQgetvalue(res, 0, i_dba);
1861
encoding = PQgetvalue(res, 0, i_encoding);
1862
collate = PQgetvalue(res, 0, i_collate);
1863
ctype = PQgetvalue(res, 0, i_ctype);
1864
frozenxid = atooid(PQgetvalue(res, 0, i_frozenxid));
1865
tablespace = PQgetvalue(res, 0, i_tablespace);
1867
appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0",
1869
if (strlen(encoding) > 0)
1871
appendPQExpBuffer(creaQry, " ENCODING = ");
1872
appendStringLiteralAH(creaQry, encoding, AH);
1874
if (strlen(collate) > 0)
1876
appendPQExpBuffer(creaQry, " LC_COLLATE = ");
1877
appendStringLiteralAH(creaQry, collate, AH);
1879
if (strlen(ctype) > 0)
1881
appendPQExpBuffer(creaQry, " LC_CTYPE = ");
1882
appendStringLiteralAH(creaQry, ctype, AH);
1884
if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
1885
appendPQExpBuffer(creaQry, " TABLESPACE = %s",
1887
appendPQExpBuffer(creaQry, ";\n");
1891
appendPQExpBuffer(creaQry, "\n-- For binary upgrade, set datfrozenxid.\n");
1892
appendPQExpBuffer(creaQry, "UPDATE pg_catalog.pg_database\n"
1893
"SET datfrozenxid = '%u'\n"
1896
appendStringLiteralAH(creaQry, datname, AH);
1897
appendPQExpBuffer(creaQry, ";\n");
1901
appendPQExpBuffer(delQry, "DROP DATABASE %s;\n",
1904
dbDumpId = createDumpId();
1907
dbCatId, /* catalog ID */
1908
dbDumpId, /* dump ID */
1910
NULL, /* Namespace */
1911
NULL, /* Tablespace */
1913
false, /* with oids */
1914
"DATABASE", /* Desc */
1915
SECTION_PRE_DATA, /* Section */
1916
creaQry->data, /* Create */
1917
delQry->data, /* Del */
1922
NULL); /* Dumper Arg */
1925
* pg_largeobject and pg_largeobject_metadata come from the old system
1926
* intact, so set their relfrozenxids.
1931
PQExpBuffer loFrozenQry = createPQExpBuffer();
1932
PQExpBuffer loOutQry = createPQExpBuffer();
1938
appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid\n"
1939
"FROM pg_catalog.pg_class\n"
1940
"WHERE oid = %u;\n",
1941
LargeObjectRelationId);
1943
lo_res = PQexec(g_conn, loFrozenQry->data);
1944
check_sql_result(lo_res, g_conn, loFrozenQry->data, PGRES_TUPLES_OK);
1946
if (PQntuples(lo_res) != 1)
1948
write_msg(NULL, "dumpDatabase(): could not find pg_largeobject.relfrozenxid\n");
1952
i_relfrozenxid = PQfnumber(lo_res, "relfrozenxid");
1954
appendPQExpBuffer(loOutQry, "\n-- For binary upgrade, set pg_largeobject.relfrozenxid\n");
1955
appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n"
1956
"SET relfrozenxid = '%u'\n"
1957
"WHERE oid = %u;\n",
1958
atoi(PQgetvalue(lo_res, 0, i_relfrozenxid)),
1959
LargeObjectRelationId);
1960
ArchiveEntry(AH, nilCatalogId, createDumpId(),
1961
"pg_largeobject", NULL, NULL, "",
1962
false, "pg_largeobject", SECTION_PRE_DATA,
1963
loOutQry->data, "", NULL,
1970
* pg_largeobject_metadata
1972
if (g_fout->remoteVersion >= 90000)
1974
resetPQExpBuffer(loFrozenQry);
1975
resetPQExpBuffer(loOutQry);
1977
appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid\n"
1978
"FROM pg_catalog.pg_class\n"
1979
"WHERE oid = %u;\n",
1980
LargeObjectMetadataRelationId);
1982
lo_res = PQexec(g_conn, loFrozenQry->data);
1983
check_sql_result(lo_res, g_conn, loFrozenQry->data, PGRES_TUPLES_OK);
1985
if (PQntuples(lo_res) != 1)
1987
write_msg(NULL, "dumpDatabase(): could not find pg_largeobject_metadata.relfrozenxid\n");
1991
i_relfrozenxid = PQfnumber(lo_res, "relfrozenxid");
1993
appendPQExpBuffer(loOutQry, "\n-- For binary upgrade, set pg_largeobject_metadata.relfrozenxid\n");
1994
appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n"
1995
"SET relfrozenxid = '%u'\n"
1996
"WHERE oid = %u;\n",
1997
atoi(PQgetvalue(lo_res, 0, i_relfrozenxid)),
1998
LargeObjectMetadataRelationId);
1999
ArchiveEntry(AH, nilCatalogId, createDumpId(),
2000
"pg_largeobject_metadata", NULL, NULL, "",
2001
false, "pg_largeobject_metadata", SECTION_PRE_DATA,
2002
loOutQry->data, "", NULL,
2009
destroyPQExpBuffer(loFrozenQry);
2010
destroyPQExpBuffer(loOutQry);
2013
/* Dump DB comment if any */
2014
if (g_fout->remoteVersion >= 80200)
2017
* 8.2 keeps comments on shared objects in a shared table, so we
2018
* cannot use the dumpComment used for other database objects.
2020
char *comment = PQgetvalue(res, 0, PQfnumber(res, "description"));
2022
if (comment && strlen(comment))
2024
resetPQExpBuffer(dbQry);
2027
* Generates warning when loaded into a differently-named
2030
appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
2031
appendStringLiteralAH(dbQry, comment, AH);
2032
appendPQExpBuffer(dbQry, ";\n");
2034
ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
2035
dba, false, "COMMENT", SECTION_NONE,
2036
dbQry->data, "", NULL,
2037
&dbDumpId, 1, NULL, NULL);
2042
resetPQExpBuffer(dbQry);
2043
appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
2044
dumpComment(AH, dbQry->data, NULL, "",
2045
dbCatId, 0, dbDumpId);
2050
destroyPQExpBuffer(dbQry);
2051
destroyPQExpBuffer(delQry);
2052
destroyPQExpBuffer(creaQry);
2057
* dumpEncoding: put the correct encoding into the archive
2060
dumpEncoding(Archive *AH)
2062
const char *encname = pg_encoding_to_char(AH->encoding);
2063
PQExpBuffer qry = createPQExpBuffer();
2066
write_msg(NULL, "saving encoding = %s\n", encname);
2068
appendPQExpBuffer(qry, "SET client_encoding = ");
2069
appendStringLiteralAH(qry, encname, AH);
2070
appendPQExpBuffer(qry, ";\n");
2072
ArchiveEntry(AH, nilCatalogId, createDumpId(),
2073
"ENCODING", NULL, NULL, "",
2074
false, "ENCODING", SECTION_PRE_DATA,
2075
qry->data, "", NULL,
2079
destroyPQExpBuffer(qry);
2084
* dumpStdStrings: put the correct escape string behavior into the archive
2087
dumpStdStrings(Archive *AH)
2089
const char *stdstrings = AH->std_strings ? "on" : "off";
2090
PQExpBuffer qry = createPQExpBuffer();
2093
write_msg(NULL, "saving standard_conforming_strings = %s\n",
2096
appendPQExpBuffer(qry, "SET standard_conforming_strings = '%s';\n",
2099
ArchiveEntry(AH, nilCatalogId, createDumpId(),
2100
"STDSTRINGS", NULL, NULL, "",
2101
false, "STDSTRINGS", SECTION_PRE_DATA,
2102
qry->data, "", NULL,
2106
destroyPQExpBuffer(qry);
2112
* Collect schema-level data about large objects
2115
getBlobs(Archive *AH)
2117
PQExpBuffer blobQry = createPQExpBuffer();
2119
DumpableObject *bdata;
2124
/* Verbose message */
2126
write_msg(NULL, "reading large objects\n");
2128
/* Make sure we are in proper schema */
2129
selectSourceSchema("pg_catalog");
2131
/* Fetch BLOB OIDs, and owner/ACL data if >= 9.0 */
2132
if (AH->remoteVersion >= 90000)
2133
appendPQExpBuffer(blobQry,
2134
"SELECT oid, (%s lomowner) AS rolname, lomacl"
2135
" FROM pg_largeobject_metadata",
2137
else if (AH->remoteVersion >= 70100)
2138
appendPQExpBuffer(blobQry,
2139
"SELECT DISTINCT loid, NULL::oid, NULL::oid"
2140
" FROM pg_largeobject");
2142
appendPQExpBuffer(blobQry,
2143
"SELECT oid, NULL::oid, NULL::oid"
2144
" FROM pg_class WHERE relkind = 'l'");
2146
res = PQexec(g_conn, blobQry->data);
2147
check_sql_result(res, g_conn, blobQry->data, PGRES_TUPLES_OK);
2149
ntups = PQntuples(res);
2153
* Each large object has its own BLOB archive entry.
2155
binfo = (BlobInfo *) malloc(ntups * sizeof(BlobInfo));
2157
for (i = 0; i < ntups; i++)
2159
binfo[i].dobj.objType = DO_BLOB;
2160
binfo[i].dobj.catId.tableoid = LargeObjectRelationId;
2161
binfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, 0));
2162
AssignDumpId(&binfo[i].dobj);
2164
binfo[i].dobj.name = strdup(PQgetvalue(res, i, 0));
2165
if (!PQgetisnull(res, i, 1))
2166
binfo[i].rolname = strdup(PQgetvalue(res, i, 1));
2168
binfo[i].rolname = "";
2169
if (!PQgetisnull(res, i, 2))
2170
binfo[i].blobacl = strdup(PQgetvalue(res, i, 2));
2172
binfo[i].blobacl = NULL;
2176
* If we have any large objects, a "BLOBS" archive entry is needed.
2177
* This is just a placeholder for sorting; it carries no data now.
2179
bdata = (DumpableObject *) malloc(sizeof(DumpableObject));
2180
bdata->objType = DO_BLOB_DATA;
2181
bdata->catId = nilCatalogId;
2182
AssignDumpId(bdata);
2183
bdata->name = strdup("BLOBS");
2187
destroyPQExpBuffer(blobQry);
2193
* dump the definition (metadata) of the given large object
2196
dumpBlob(Archive *AH, BlobInfo *binfo)
2198
PQExpBuffer cquery = createPQExpBuffer();
2199
PQExpBuffer dquery = createPQExpBuffer();
2201
appendPQExpBuffer(cquery,
2202
"SELECT pg_catalog.lo_create('%s');\n",
2205
appendPQExpBuffer(dquery,
2206
"SELECT pg_catalog.lo_unlink('%s');\n",
2209
ArchiveEntry(AH, binfo->dobj.catId, binfo->dobj.dumpId,
2212
binfo->rolname, false,
2213
"BLOB", SECTION_PRE_DATA,
2214
cquery->data, dquery->data, NULL,
2215
binfo->dobj.dependencies, binfo->dobj.nDeps,
2218
/* set up tag for comment and/or ACL */
2219
resetPQExpBuffer(cquery);
2220
appendPQExpBuffer(cquery, "LARGE OBJECT %s", binfo->dobj.name);
2222
/* Dump comment if any */
2223
dumpComment(AH, cquery->data,
2224
NULL, binfo->rolname,
2225
binfo->dobj.catId, 0, binfo->dobj.dumpId);
2227
/* Dump security label if any */
2228
dumpSecLabel(AH, cquery->data,
2229
NULL, binfo->rolname,
2230
binfo->dobj.catId, 0, binfo->dobj.dumpId);
2232
/* Dump ACL if any */
2234
dumpACL(AH, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
2235
binfo->dobj.name, NULL, cquery->data,
2236
NULL, binfo->rolname, binfo->blobacl);
2238
destroyPQExpBuffer(cquery);
2239
destroyPQExpBuffer(dquery);
2244
* dump the data contents of all large objects
2247
dumpBlobs(Archive *AH, void *arg)
2249
const char *blobQry;
2250
const char *blobFetchQry;
2252
char buf[LOBBUFSIZE];
2258
write_msg(NULL, "saving large objects\n");
2260
/* Make sure we are in proper schema */
2261
selectSourceSchema("pg_catalog");
2264
* Currently, we re-fetch all BLOB OIDs using a cursor. Consider scanning
2265
* the already-in-memory dumpable objects instead...
2267
if (AH->remoteVersion >= 90000)
2268
blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_largeobject_metadata";
2269
else if (AH->remoteVersion >= 70100)
2270
blobQry = "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
2272
blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class WHERE relkind = 'l'";
2274
res = PQexec(g_conn, blobQry);
2275
check_sql_result(res, g_conn, blobQry, PGRES_COMMAND_OK);
2277
/* Command to fetch from cursor */
2278
blobFetchQry = "FETCH 1000 IN bloboid";
2285
res = PQexec(g_conn, blobFetchQry);
2286
check_sql_result(res, g_conn, blobFetchQry, PGRES_TUPLES_OK);
2288
/* Process the tuples, if any */
2289
ntups = PQntuples(res);
2290
for (i = 0; i < ntups; i++)
2295
blobOid = atooid(PQgetvalue(res, i, 0));
2297
loFd = lo_open(g_conn, blobOid, INV_READ);
2300
write_msg(NULL, "could not open large object %u: %s",
2301
blobOid, PQerrorMessage(g_conn));
2305
StartBlob(AH, blobOid);
2307
/* Now read it in chunks, sending data to archive */
2310
cnt = lo_read(g_conn, loFd, buf, LOBBUFSIZE);
2313
write_msg(NULL, "error reading large object %u: %s",
2314
blobOid, PQerrorMessage(g_conn));
2318
WriteData(AH, buf, cnt);
2321
lo_close(g_conn, loFd);
2323
EndBlob(AH, blobOid);
2325
} while (ntups > 0);
2333
binary_upgrade_set_type_oids_by_type_oid(PQExpBuffer upgrade_buffer,
2336
PQExpBuffer upgrade_query = createPQExpBuffer();
2338
PGresult *upgrade_res;
2339
Oid pg_type_array_oid;
2341
appendPQExpBuffer(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type oid\n");
2342
appendPQExpBuffer(upgrade_buffer,
2343
"SELECT binary_upgrade.set_next_pg_type_oid('%u'::pg_catalog.oid);\n\n",
2346
/* we only support old >= 8.3 for binary upgrades */
2347
appendPQExpBuffer(upgrade_query,
2349
"FROM pg_catalog.pg_type "
2350
"WHERE pg_type.oid = '%u'::pg_catalog.oid;",
2353
upgrade_res = PQexec(g_conn, upgrade_query->data);
2354
check_sql_result(upgrade_res, g_conn, upgrade_query->data, PGRES_TUPLES_OK);
2356
/* Expecting a single result only */
2357
ntups = PQntuples(upgrade_res);
2360
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
2361
"query returned %d rows instead of one: %s\n",
2363
ntups, upgrade_query->data);
2367
pg_type_array_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "typarray")));
2369
if (OidIsValid(pg_type_array_oid))
2371
appendPQExpBuffer(upgrade_buffer,
2372
"\n-- For binary upgrade, must preserve pg_type array oid\n");
2373
appendPQExpBuffer(upgrade_buffer,
2374
"SELECT binary_upgrade.set_next_array_pg_type_oid('%u'::pg_catalog.oid);\n\n",
2378
PQclear(upgrade_res);
2379
destroyPQExpBuffer(upgrade_query);
2383
binary_upgrade_set_type_oids_by_rel_oid(PQExpBuffer upgrade_buffer,
2386
PQExpBuffer upgrade_query = createPQExpBuffer();
2388
PGresult *upgrade_res;
2390
bool toast_set = false;
2392
/* we only support old >= 8.3 for binary upgrades */
2393
appendPQExpBuffer(upgrade_query,
2394
"SELECT c.reltype AS crel, t.reltype AS trel "
2395
"FROM pg_catalog.pg_class c "
2396
"LEFT JOIN pg_catalog.pg_class t ON "
2397
" (c.reltoastrelid = t.oid) "
2398
"WHERE c.oid = '%u'::pg_catalog.oid;",
2401
upgrade_res = PQexec(g_conn, upgrade_query->data);
2402
check_sql_result(upgrade_res, g_conn, upgrade_query->data, PGRES_TUPLES_OK);
2404
/* Expecting a single result only */
2405
ntups = PQntuples(upgrade_res);
2408
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
2409
"query returned %d rows instead of one: %s\n",
2411
ntups, upgrade_query->data);
2415
pg_type_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "crel")));
2417
binary_upgrade_set_type_oids_by_type_oid(upgrade_buffer, pg_type_oid);
2419
if (!PQgetisnull(upgrade_res, 0, PQfnumber(upgrade_res, "trel")))
2421
/* Toast tables do not have pg_type array rows */
2422
Oid pg_type_toast_oid = atooid(PQgetvalue(upgrade_res, 0,
2423
PQfnumber(upgrade_res, "trel")));
2425
appendPQExpBuffer(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type toast oid\n");
2426
appendPQExpBuffer(upgrade_buffer,
2427
"SELECT binary_upgrade.set_next_toast_pg_type_oid('%u'::pg_catalog.oid);\n\n",
2433
PQclear(upgrade_res);
2434
destroyPQExpBuffer(upgrade_query);
2440
binary_upgrade_set_pg_class_oids(PQExpBuffer upgrade_buffer, Oid pg_class_oid,
2443
PQExpBuffer upgrade_query = createPQExpBuffer();
2445
PGresult *upgrade_res;
2446
Oid pg_class_reltoastrelid;
2447
Oid pg_class_reltoastidxid;
2449
appendPQExpBuffer(upgrade_query,
2450
"SELECT c.reltoastrelid, t.reltoastidxid "
2451
"FROM pg_catalog.pg_class c LEFT JOIN "
2452
"pg_catalog.pg_class t ON (c.reltoastrelid = t.oid) "
2453
"WHERE c.oid = '%u'::pg_catalog.oid;",
2456
upgrade_res = PQexec(g_conn, upgrade_query->data);
2457
check_sql_result(upgrade_res, g_conn, upgrade_query->data, PGRES_TUPLES_OK);
2459
/* Expecting a single result only */
2460
ntups = PQntuples(upgrade_res);
2463
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
2464
"query returned %d rows instead of one: %s\n",
2466
ntups, upgrade_query->data);
2470
pg_class_reltoastrelid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "reltoastrelid")));
2471
pg_class_reltoastidxid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "reltoastidxid")));
2473
appendPQExpBuffer(upgrade_buffer,
2474
"\n-- For binary upgrade, must preserve pg_class oids\n");
2478
appendPQExpBuffer(upgrade_buffer,
2479
"SELECT binary_upgrade.set_next_heap_pg_class_oid('%u'::pg_catalog.oid);\n",
2481
/* only tables have toast tables, not indexes */
2482
if (OidIsValid(pg_class_reltoastrelid))
2485
* One complexity is that the table definition might not require
2486
* the creation of a TOAST table, and the TOAST table might have
2487
* been created long after table creation, when the table was
2488
* loaded with wide data. By setting the TOAST oid we force
2489
* creation of the TOAST heap and TOAST index by the backend so we
2490
* can cleanly copy the files during binary upgrade.
2493
appendPQExpBuffer(upgrade_buffer,
2494
"SELECT binary_upgrade.set_next_toast_pg_class_oid('%u'::pg_catalog.oid);\n",
2495
pg_class_reltoastrelid);
2497
/* every toast table has an index */
2498
appendPQExpBuffer(upgrade_buffer,
2499
"SELECT binary_upgrade.set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n",
2500
pg_class_reltoastidxid);
2504
appendPQExpBuffer(upgrade_buffer,
2505
"SELECT binary_upgrade.set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n",
2508
appendPQExpBuffer(upgrade_buffer, "\n");
2510
PQclear(upgrade_res);
2511
destroyPQExpBuffer(upgrade_query);
2515
* If the DumpableObject is a member of an extension, add a suitable
2516
* ALTER EXTENSION ADD command to the creation commands in upgrade_buffer.
2519
binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
2520
DumpableObject *dobj,
2521
const char *objlabel)
2523
DumpableObject *extobj = NULL;
2526
if (!dobj->ext_member)
2530
* Find the parent extension. We could avoid this search if we wanted to
2531
* add a link field to DumpableObject, but the space costs of that would
2532
* be considerable. We assume that member objects could only have a
2533
* direct dependency on their own extension, not any others.
2535
for (i = 0; i < dobj->nDeps; i++)
2537
extobj = findObjectByDumpId(dobj->dependencies[i]);
2538
if (extobj && extobj->objType == DO_EXTENSION)
2544
write_msg(NULL, "failed to find parent extension for %s", objlabel);
2548
appendPQExpBuffer(upgrade_buffer,
2549
"\n-- For binary upgrade, handle extension membership the hard way\n");
2550
appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s;\n",
2551
fmtId(extobj->name),
2557
* read all namespaces in the system catalogs and return them in the
2558
* NamespaceInfo* structure
2560
* numNamespaces is set to the number of namespaces read in
2563
getNamespaces(int *numNamespaces)
2569
NamespaceInfo *nsinfo;
2577
* Before 7.3, there are no real namespaces; create two dummy entries, one
2578
* for user stuff and one for system stuff.
2580
if (g_fout->remoteVersion < 70300)
2582
nsinfo = (NamespaceInfo *) malloc(2 * sizeof(NamespaceInfo));
2584
nsinfo[0].dobj.objType = DO_NAMESPACE;
2585
nsinfo[0].dobj.catId.tableoid = 0;
2586
nsinfo[0].dobj.catId.oid = 0;
2587
AssignDumpId(&nsinfo[0].dobj);
2588
nsinfo[0].dobj.name = strdup("public");
2589
nsinfo[0].rolname = strdup("");
2590
nsinfo[0].nspacl = strdup("");
2592
selectDumpableNamespace(&nsinfo[0]);
2594
nsinfo[1].dobj.objType = DO_NAMESPACE;
2595
nsinfo[1].dobj.catId.tableoid = 0;
2596
nsinfo[1].dobj.catId.oid = 1;
2597
AssignDumpId(&nsinfo[1].dobj);
2598
nsinfo[1].dobj.name = strdup("pg_catalog");
2599
nsinfo[1].rolname = strdup("");
2600
nsinfo[1].nspacl = strdup("");
2602
selectDumpableNamespace(&nsinfo[1]);
2604
g_namespaces = nsinfo;
2605
g_numNamespaces = *numNamespaces = 2;
2610
query = createPQExpBuffer();
2612
/* Make sure we are in proper schema */
2613
selectSourceSchema("pg_catalog");
2616
* we fetch all namespaces including system ones, so that every object we
2617
* read in can be linked to a containing namespace.
2619
appendPQExpBuffer(query, "SELECT tableoid, oid, nspname, "
2620
"(%s nspowner) AS rolname, "
2621
"nspacl FROM pg_namespace",
2624
res = PQexec(g_conn, query->data);
2625
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
2627
ntups = PQntuples(res);
2629
nsinfo = (NamespaceInfo *) malloc(ntups * sizeof(NamespaceInfo));
2631
i_tableoid = PQfnumber(res, "tableoid");
2632
i_oid = PQfnumber(res, "oid");
2633
i_nspname = PQfnumber(res, "nspname");
2634
i_rolname = PQfnumber(res, "rolname");
2635
i_nspacl = PQfnumber(res, "nspacl");
2637
for (i = 0; i < ntups; i++)
2639
nsinfo[i].dobj.objType = DO_NAMESPACE;
2640
nsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
2641
nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
2642
AssignDumpId(&nsinfo[i].dobj);
2643
nsinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_nspname));
2644
nsinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
2645
nsinfo[i].nspacl = strdup(PQgetvalue(res, i, i_nspacl));
2647
/* Decide whether to dump this namespace */
2648
selectDumpableNamespace(&nsinfo[i]);
2650
if (strlen(nsinfo[i].rolname) == 0)
2651
write_msg(NULL, "WARNING: owner of schema \"%s\" appears to be invalid\n",
2652
nsinfo[i].dobj.name);
2656
destroyPQExpBuffer(query);
2658
g_namespaces = nsinfo;
2659
g_numNamespaces = *numNamespaces = ntups;
2666
* given a namespace OID and an object OID, look up the info read by
2669
* NB: for pre-7.3 source database, we use object OID to guess whether it's
2670
* a system object or not. In 7.3 and later there is no guessing.
2672
static NamespaceInfo *
2673
findNamespace(Oid nsoid, Oid objoid)
2677
if (g_fout->remoteVersion >= 70300)
2679
for (i = 0; i < g_numNamespaces; i++)
2681
NamespaceInfo *nsinfo = &g_namespaces[i];
2683
if (nsoid == nsinfo->dobj.catId.oid)
2686
write_msg(NULL, "schema with OID %u does not exist\n", nsoid);
2691
/* This code depends on the layout set up by getNamespaces. */
2692
if (objoid > g_last_builtin_oid)
2693
i = 0; /* user object */
2695
i = 1; /* system object */
2696
return &g_namespaces[i];
2699
return NULL; /* keep compiler quiet */
2704
* read all extensions in the system catalogs and return them in the
2705
* ExtensionInfo* structure
2707
* numExtensions is set to the number of extensions read in
2710
getExtensions(int *numExtensions)
2716
ExtensionInfo *extinfo;
2721
int i_extrelocatable;
2727
* Before 9.1, there are no extensions.
2729
if (g_fout->remoteVersion < 90100)
2735
query = createPQExpBuffer();
2737
/* Make sure we are in proper schema */
2738
selectSourceSchema("pg_catalog");
2740
appendPQExpBuffer(query, "SELECT x.tableoid, x.oid, "
2741
"x.extname, n.nspname, x.extrelocatable, x.extversion, x.extconfig, x.extcondition "
2742
"FROM pg_extension x "
2743
"JOIN pg_namespace n ON n.oid = x.extnamespace");
2745
res = PQexec(g_conn, query->data);
2746
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
2748
ntups = PQntuples(res);
2750
extinfo = (ExtensionInfo *) malloc(ntups * sizeof(ExtensionInfo));
2752
i_tableoid = PQfnumber(res, "tableoid");
2753
i_oid = PQfnumber(res, "oid");
2754
i_extname = PQfnumber(res, "extname");
2755
i_nspname = PQfnumber(res, "nspname");
2756
i_extrelocatable = PQfnumber(res, "extrelocatable");
2757
i_extversion = PQfnumber(res, "extversion");
2758
i_extconfig = PQfnumber(res, "extconfig");
2759
i_extcondition = PQfnumber(res, "extcondition");
2761
for (i = 0; i < ntups; i++)
2763
extinfo[i].dobj.objType = DO_EXTENSION;
2764
extinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
2765
extinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
2766
AssignDumpId(&extinfo[i].dobj);
2767
extinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_extname));
2768
extinfo[i].namespace = strdup(PQgetvalue(res, i, i_nspname));
2769
extinfo[i].relocatable = *(PQgetvalue(res, i, i_extrelocatable)) == 't';
2770
extinfo[i].extversion = strdup(PQgetvalue(res, i, i_extversion));
2771
extinfo[i].extconfig = strdup(PQgetvalue(res, i, i_extconfig));
2772
extinfo[i].extcondition = strdup(PQgetvalue(res, i, i_extcondition));
2774
/* Decide whether we want to dump it */
2775
selectDumpableExtension(&(extinfo[i]));
2779
destroyPQExpBuffer(query);
2781
*numExtensions = ntups;
2788
* read all types in the system catalogs and return them in the
2789
* TypeInfo* structure
2791
* numTypes is set to the number of types read in
2793
* NB: this must run after getFuncs() because we assume we can do
2797
getTypes(int *numTypes)
2802
PQExpBuffer query = createPQExpBuffer();
2804
ShellTypeInfo *stinfo;
2820
* we include even the built-in types because those may be used as array
2821
* elements by user-defined types
2823
* we filter out the built-in types when we dump out the types
2825
* same approach for undefined (shell) types and array types
2827
* Note: as of 8.3 we can reliably detect whether a type is an
2828
* auto-generated array type by checking the element type's typarray.
2829
* (Before that the test is capable of generating false positives.) We
2830
* still check for name beginning with '_', though, so as to avoid the
2831
* cost of the subselect probe for all standard types. This would have to
2832
* be revisited if the backend ever allows renaming of array types.
2835
/* Make sure we are in proper schema */
2836
selectSourceSchema("pg_catalog");
2838
if (g_fout->remoteVersion >= 80300)
2840
appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
2842
"(%s typowner) AS rolname, "
2843
"typinput::oid AS typinput, "
2844
"typoutput::oid AS typoutput, typelem, typrelid, "
2845
"CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2846
"ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2847
"typtype, typisdefined, "
2848
"typname[0] = '_' AND typelem != 0 AND "
2849
"(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
2853
else if (g_fout->remoteVersion >= 70300)
2855
appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
2857
"(%s typowner) AS rolname, "
2858
"typinput::oid AS typinput, "
2859
"typoutput::oid AS typoutput, typelem, typrelid, "
2860
"CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2861
"ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2862
"typtype, typisdefined, "
2863
"typname[0] = '_' AND typelem != 0 AS isarray "
2867
else if (g_fout->remoteVersion >= 70100)
2869
appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
2870
"0::oid AS typnamespace, "
2871
"(%s typowner) AS rolname, "
2872
"typinput::oid AS typinput, "
2873
"typoutput::oid AS typoutput, typelem, typrelid, "
2874
"CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2875
"ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2876
"typtype, typisdefined, "
2877
"typname[0] = '_' AND typelem != 0 AS isarray "
2883
appendPQExpBuffer(query, "SELECT "
2884
"(SELECT oid FROM pg_class WHERE relname = 'pg_type') AS tableoid, "
2886
"0::oid AS typnamespace, "
2887
"(%s typowner) AS rolname, "
2888
"typinput::oid AS typinput, "
2889
"typoutput::oid AS typoutput, typelem, typrelid, "
2890
"CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2891
"ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2892
"typtype, typisdefined, "
2893
"typname[0] = '_' AND typelem != 0 AS isarray "
2898
res = PQexec(g_conn, query->data);
2899
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
2901
ntups = PQntuples(res);
2903
tyinfo = (TypeInfo *) malloc(ntups * sizeof(TypeInfo));
2905
i_tableoid = PQfnumber(res, "tableoid");
2906
i_oid = PQfnumber(res, "oid");
2907
i_typname = PQfnumber(res, "typname");
2908
i_typnamespace = PQfnumber(res, "typnamespace");
2909
i_rolname = PQfnumber(res, "rolname");
2910
i_typinput = PQfnumber(res, "typinput");
2911
i_typoutput = PQfnumber(res, "typoutput");
2912
i_typelem = PQfnumber(res, "typelem");
2913
i_typrelid = PQfnumber(res, "typrelid");
2914
i_typrelkind = PQfnumber(res, "typrelkind");
2915
i_typtype = PQfnumber(res, "typtype");
2916
i_typisdefined = PQfnumber(res, "typisdefined");
2917
i_isarray = PQfnumber(res, "isarray");
2919
for (i = 0; i < ntups; i++)
2921
tyinfo[i].dobj.objType = DO_TYPE;
2922
tyinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
2923
tyinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
2924
AssignDumpId(&tyinfo[i].dobj);
2925
tyinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_typname));
2926
tyinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_typnamespace)),
2927
tyinfo[i].dobj.catId.oid);
2928
tyinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
2929
tyinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem));
2930
tyinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid));
2931
tyinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
2932
tyinfo[i].typtype = *PQgetvalue(res, i, i_typtype);
2933
tyinfo[i].shellType = NULL;
2935
if (strcmp(PQgetvalue(res, i, i_typisdefined), "t") == 0)
2936
tyinfo[i].isDefined = true;
2938
tyinfo[i].isDefined = false;
2940
if (strcmp(PQgetvalue(res, i, i_isarray), "t") == 0)
2941
tyinfo[i].isArray = true;
2943
tyinfo[i].isArray = false;
2945
/* Decide whether we want to dump it */
2946
selectDumpableType(&tyinfo[i]);
2949
* If it's a domain, fetch info about its constraints, if any
2951
tyinfo[i].nDomChecks = 0;
2952
tyinfo[i].domChecks = NULL;
2953
if (tyinfo[i].dobj.dump && tyinfo[i].typtype == TYPTYPE_DOMAIN)
2954
getDomainConstraints(&(tyinfo[i]));
2957
* If it's a base type, make a DumpableObject representing a shell
2958
* definition of the type. We will need to dump that ahead of the I/O
2959
* functions for the type.
2961
* Note: the shell type doesn't have a catId. You might think it
2962
* should copy the base type's catId, but then it might capture the
2963
* pg_depend entries for the type, which we don't want.
2965
if (tyinfo[i].dobj.dump && tyinfo[i].typtype == TYPTYPE_BASE)
2967
stinfo = (ShellTypeInfo *) malloc(sizeof(ShellTypeInfo));
2968
stinfo->dobj.objType = DO_SHELL_TYPE;
2969
stinfo->dobj.catId = nilCatalogId;
2970
AssignDumpId(&stinfo->dobj);
2971
stinfo->dobj.name = strdup(tyinfo[i].dobj.name);
2972
stinfo->dobj.namespace = tyinfo[i].dobj.namespace;
2973
stinfo->baseType = &(tyinfo[i]);
2974
tyinfo[i].shellType = stinfo;
2977
* Initially mark the shell type as not to be dumped. We'll only
2978
* dump it if the I/O functions need to be dumped; this is taken
2979
* care of while sorting dependencies.
2981
stinfo->dobj.dump = false;
2984
* However, if dumping from pre-7.3, there will be no dependency
2985
* info so we have to fake it here. We only need to worry about
2986
* typinput and typoutput since the other functions only exist
2989
if (g_fout->remoteVersion < 70300)
2995
typinput = atooid(PQgetvalue(res, i, i_typinput));
2996
typoutput = atooid(PQgetvalue(res, i, i_typoutput));
2998
funcInfo = findFuncByOid(typinput);
2999
if (funcInfo && funcInfo->dobj.dump)
3001
/* base type depends on function */
3002
addObjectDependency(&tyinfo[i].dobj,
3003
funcInfo->dobj.dumpId);
3004
/* function depends on shell type */
3005
addObjectDependency(&funcInfo->dobj,
3006
stinfo->dobj.dumpId);
3007
/* mark shell type as to be dumped */
3008
stinfo->dobj.dump = true;
3011
funcInfo = findFuncByOid(typoutput);
3012
if (funcInfo && funcInfo->dobj.dump)
3014
/* base type depends on function */
3015
addObjectDependency(&tyinfo[i].dobj,
3016
funcInfo->dobj.dumpId);
3017
/* function depends on shell type */
3018
addObjectDependency(&funcInfo->dobj,
3019
stinfo->dobj.dumpId);
3020
/* mark shell type as to be dumped */
3021
stinfo->dobj.dump = true;
3026
if (strlen(tyinfo[i].rolname) == 0 && tyinfo[i].isDefined)
3027
write_msg(NULL, "WARNING: owner of data type \"%s\" appears to be invalid\n",
3028
tyinfo[i].dobj.name);
3035
destroyPQExpBuffer(query);
3042
* read all operators in the system catalogs and return them in the
3043
* OprInfo* structure
3045
* numOprs is set to the number of operators read in
3048
getOperators(int *numOprs)
3053
PQExpBuffer query = createPQExpBuffer();
3063
* find all operators, including builtin operators; we filter out
3064
* system-defined operators at dump-out time.
3067
/* Make sure we are in proper schema */
3068
selectSourceSchema("pg_catalog");
3070
if (g_fout->remoteVersion >= 70300)
3072
appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
3074
"(%s oprowner) AS rolname, "
3075
"oprcode::oid AS oprcode "
3079
else if (g_fout->remoteVersion >= 70100)
3081
appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
3082
"0::oid AS oprnamespace, "
3083
"(%s oprowner) AS rolname, "
3084
"oprcode::oid AS oprcode "
3090
appendPQExpBuffer(query, "SELECT "
3091
"(SELECT oid FROM pg_class WHERE relname = 'pg_operator') AS tableoid, "
3093
"0::oid AS oprnamespace, "
3094
"(%s oprowner) AS rolname, "
3095
"oprcode::oid AS oprcode "
3100
res = PQexec(g_conn, query->data);
3101
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3103
ntups = PQntuples(res);
3106
oprinfo = (OprInfo *) malloc(ntups * sizeof(OprInfo));
3108
i_tableoid = PQfnumber(res, "tableoid");
3109
i_oid = PQfnumber(res, "oid");
3110
i_oprname = PQfnumber(res, "oprname");
3111
i_oprnamespace = PQfnumber(res, "oprnamespace");
3112
i_rolname = PQfnumber(res, "rolname");
3113
i_oprcode = PQfnumber(res, "oprcode");
3115
for (i = 0; i < ntups; i++)
3117
oprinfo[i].dobj.objType = DO_OPERATOR;
3118
oprinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
3119
oprinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
3120
AssignDumpId(&oprinfo[i].dobj);
3121
oprinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_oprname));
3122
oprinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_oprnamespace)),
3123
oprinfo[i].dobj.catId.oid);
3124
oprinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
3125
oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
3127
/* Decide whether we want to dump it */
3128
selectDumpableObject(&(oprinfo[i].dobj));
3130
if (strlen(oprinfo[i].rolname) == 0)
3131
write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
3132
oprinfo[i].dobj.name);
3137
destroyPQExpBuffer(query);
3144
* read all collations in the system catalogs and return them in the
3145
* CollInfo* structure
3147
* numCollations is set to the number of collations read in
3150
getCollations(int *numCollations)
3155
PQExpBuffer query = createPQExpBuffer();
3160
int i_collnamespace;
3163
/* Collations didn't exist pre-9.1 */
3164
if (g_fout->remoteVersion < 90100)
3171
* find all collations, including builtin collations; we filter out
3172
* system-defined collations at dump-out time.
3175
/* Make sure we are in proper schema */
3176
selectSourceSchema("pg_catalog");
3178
appendPQExpBuffer(query, "SELECT tableoid, oid, collname, "
3180
"(%s collowner) AS rolname "
3181
"FROM pg_collation",
3184
res = PQexec(g_conn, query->data);
3185
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3187
ntups = PQntuples(res);
3188
*numCollations = ntups;
3190
collinfo = (CollInfo *) malloc(ntups * sizeof(CollInfo));
3192
i_tableoid = PQfnumber(res, "tableoid");
3193
i_oid = PQfnumber(res, "oid");
3194
i_collname = PQfnumber(res, "collname");
3195
i_collnamespace = PQfnumber(res, "collnamespace");
3196
i_rolname = PQfnumber(res, "rolname");
3198
for (i = 0; i < ntups; i++)
3200
collinfo[i].dobj.objType = DO_COLLATION;
3201
collinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
3202
collinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
3203
AssignDumpId(&collinfo[i].dobj);
3204
collinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_collname));
3205
collinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_collnamespace)),
3206
collinfo[i].dobj.catId.oid);
3207
collinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
3209
/* Decide whether we want to dump it */
3210
selectDumpableObject(&(collinfo[i].dobj));
3215
destroyPQExpBuffer(query);
3222
* read all conversions in the system catalogs and return them in the
3223
* ConvInfo* structure
3225
* numConversions is set to the number of conversions read in
3228
getConversions(int *numConversions)
3233
PQExpBuffer query = createPQExpBuffer();
3241
/* Conversions didn't exist pre-7.3 */
3242
if (g_fout->remoteVersion < 70300)
3244
*numConversions = 0;
3249
* find all conversions, including builtin conversions; we filter out
3250
* system-defined conversions at dump-out time.
3253
/* Make sure we are in proper schema */
3254
selectSourceSchema("pg_catalog");
3256
appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
3258
"(%s conowner) AS rolname "
3259
"FROM pg_conversion",
3262
res = PQexec(g_conn, query->data);
3263
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3265
ntups = PQntuples(res);
3266
*numConversions = ntups;
3268
convinfo = (ConvInfo *) malloc(ntups * sizeof(ConvInfo));
3270
i_tableoid = PQfnumber(res, "tableoid");
3271
i_oid = PQfnumber(res, "oid");
3272
i_conname = PQfnumber(res, "conname");
3273
i_connamespace = PQfnumber(res, "connamespace");
3274
i_rolname = PQfnumber(res, "rolname");
3276
for (i = 0; i < ntups; i++)
3278
convinfo[i].dobj.objType = DO_CONVERSION;
3279
convinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
3280
convinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
3281
AssignDumpId(&convinfo[i].dobj);
3282
convinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_conname));
3283
convinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_connamespace)),
3284
convinfo[i].dobj.catId.oid);
3285
convinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
3287
/* Decide whether we want to dump it */
3288
selectDumpableObject(&(convinfo[i].dobj));
3293
destroyPQExpBuffer(query);
3300
* read all opclasses in the system catalogs and return them in the
3301
* OpclassInfo* structure
3303
* numOpclasses is set to the number of opclasses read in
3306
getOpclasses(int *numOpclasses)
3311
PQExpBuffer query = createPQExpBuffer();
3312
OpclassInfo *opcinfo;
3320
* find all opclasses, including builtin opclasses; we filter out
3321
* system-defined opclasses at dump-out time.
3324
/* Make sure we are in proper schema */
3325
selectSourceSchema("pg_catalog");
3327
if (g_fout->remoteVersion >= 70300)
3329
appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
3331
"(%s opcowner) AS rolname "
3335
else if (g_fout->remoteVersion >= 70100)
3337
appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
3338
"0::oid AS opcnamespace, "
3339
"''::name AS rolname "
3344
appendPQExpBuffer(query, "SELECT "
3345
"(SELECT oid FROM pg_class WHERE relname = 'pg_opclass') AS tableoid, "
3347
"0::oid AS opcnamespace, "
3348
"''::name AS rolname "
3352
res = PQexec(g_conn, query->data);
3353
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3355
ntups = PQntuples(res);
3356
*numOpclasses = ntups;
3358
opcinfo = (OpclassInfo *) malloc(ntups * sizeof(OpclassInfo));
3360
i_tableoid = PQfnumber(res, "tableoid");
3361
i_oid = PQfnumber(res, "oid");
3362
i_opcname = PQfnumber(res, "opcname");
3363
i_opcnamespace = PQfnumber(res, "opcnamespace");
3364
i_rolname = PQfnumber(res, "rolname");
3366
for (i = 0; i < ntups; i++)
3368
opcinfo[i].dobj.objType = DO_OPCLASS;
3369
opcinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
3370
opcinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
3371
AssignDumpId(&opcinfo[i].dobj);
3372
opcinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_opcname));
3373
opcinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_opcnamespace)),
3374
opcinfo[i].dobj.catId.oid);
3375
opcinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
3377
/* Decide whether we want to dump it */
3378
selectDumpableObject(&(opcinfo[i].dobj));
3380
if (g_fout->remoteVersion >= 70300)
3382
if (strlen(opcinfo[i].rolname) == 0)
3383
write_msg(NULL, "WARNING: owner of operator class \"%s\" appears to be invalid\n",
3384
opcinfo[i].dobj.name);
3390
destroyPQExpBuffer(query);
3397
* read all opfamilies in the system catalogs and return them in the
3398
* OpfamilyInfo* structure
3400
* numOpfamilies is set to the number of opfamilies read in
3403
getOpfamilies(int *numOpfamilies)
3409
OpfamilyInfo *opfinfo;
3416
/* Before 8.3, there is no separate concept of opfamilies */
3417
if (g_fout->remoteVersion < 80300)
3423
query = createPQExpBuffer();
3426
* find all opfamilies, including builtin opfamilies; we filter out
3427
* system-defined opfamilies at dump-out time.
3430
/* Make sure we are in proper schema */
3431
selectSourceSchema("pg_catalog");
3433
appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, "
3435
"(%s opfowner) AS rolname "
3439
res = PQexec(g_conn, query->data);
3440
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3442
ntups = PQntuples(res);
3443
*numOpfamilies = ntups;
3445
opfinfo = (OpfamilyInfo *) malloc(ntups * sizeof(OpfamilyInfo));
3447
i_tableoid = PQfnumber(res, "tableoid");
3448
i_oid = PQfnumber(res, "oid");
3449
i_opfname = PQfnumber(res, "opfname");
3450
i_opfnamespace = PQfnumber(res, "opfnamespace");
3451
i_rolname = PQfnumber(res, "rolname");
3453
for (i = 0; i < ntups; i++)
3455
opfinfo[i].dobj.objType = DO_OPFAMILY;
3456
opfinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
3457
opfinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
3458
AssignDumpId(&opfinfo[i].dobj);
3459
opfinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_opfname));
3460
opfinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_opfnamespace)),
3461
opfinfo[i].dobj.catId.oid);
3462
opfinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
3464
/* Decide whether we want to dump it */
3465
selectDumpableObject(&(opfinfo[i].dobj));
3467
if (g_fout->remoteVersion >= 70300)
3469
if (strlen(opfinfo[i].rolname) == 0)
3470
write_msg(NULL, "WARNING: owner of operator family \"%s\" appears to be invalid\n",
3471
opfinfo[i].dobj.name);
3477
destroyPQExpBuffer(query);
3484
* read all the user-defined aggregates in the system catalogs and
3485
* return them in the AggInfo* structure
3487
* numAggs is set to the number of aggregates read in
3490
getAggregates(int *numAggs)
3495
PQExpBuffer query = createPQExpBuffer();
3506
/* Make sure we are in proper schema */
3507
selectSourceSchema("pg_catalog");
3510
* Find all user-defined aggregates. See comment in getFuncs() for the
3511
* rationale behind the filtering logic.
3514
if (g_fout->remoteVersion >= 80200)
3516
appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
3517
"pronamespace AS aggnamespace, "
3518
"pronargs, proargtypes, "
3519
"(%s proowner) AS rolname, "
3522
"WHERE proisagg AND ("
3524
"(SELECT oid FROM pg_namespace "
3525
"WHERE nspname = 'pg_catalog')",
3527
if (binary_upgrade && g_fout->remoteVersion >= 90100)
3528
appendPQExpBuffer(query,
3529
" OR EXISTS(SELECT 1 FROM pg_depend WHERE "
3530
"classid = 'pg_proc'::regclass AND "
3531
"objid = p.oid AND "
3532
"refclassid = 'pg_extension'::regclass AND "
3534
appendPQExpBuffer(query, ")");
3536
else if (g_fout->remoteVersion >= 70300)
3538
appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
3539
"pronamespace AS aggnamespace, "
3540
"CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, "
3542
"(%s proowner) AS rolname, "
3546
"AND pronamespace != "
3547
"(SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog')",
3550
else if (g_fout->remoteVersion >= 70100)
3552
appendPQExpBuffer(query, "SELECT tableoid, oid, aggname, "
3553
"0::oid AS aggnamespace, "
3554
"CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
3555
"aggbasetype AS proargtypes, "
3556
"(%s aggowner) AS rolname, "
3558
"FROM pg_aggregate "
3559
"where oid > '%u'::oid",
3561
g_last_builtin_oid);
3565
appendPQExpBuffer(query, "SELECT "
3566
"(SELECT oid FROM pg_class WHERE relname = 'pg_aggregate') AS tableoid, "
3568
"0::oid AS aggnamespace, "
3569
"CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
3570
"aggbasetype AS proargtypes, "
3571
"(%s aggowner) AS rolname, "
3573
"FROM pg_aggregate "
3574
"where oid > '%u'::oid",
3576
g_last_builtin_oid);
3579
res = PQexec(g_conn, query->data);
3580
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3582
ntups = PQntuples(res);
3585
agginfo = (AggInfo *) malloc(ntups * sizeof(AggInfo));
3587
i_tableoid = PQfnumber(res, "tableoid");
3588
i_oid = PQfnumber(res, "oid");
3589
i_aggname = PQfnumber(res, "aggname");
3590
i_aggnamespace = PQfnumber(res, "aggnamespace");
3591
i_pronargs = PQfnumber(res, "pronargs");
3592
i_proargtypes = PQfnumber(res, "proargtypes");
3593
i_rolname = PQfnumber(res, "rolname");
3594
i_aggacl = PQfnumber(res, "aggacl");
3596
for (i = 0; i < ntups; i++)
3598
agginfo[i].aggfn.dobj.objType = DO_AGG;
3599
agginfo[i].aggfn.dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
3600
agginfo[i].aggfn.dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
3601
AssignDumpId(&agginfo[i].aggfn.dobj);
3602
agginfo[i].aggfn.dobj.name = strdup(PQgetvalue(res, i, i_aggname));
3603
agginfo[i].aggfn.dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_aggnamespace)),
3604
agginfo[i].aggfn.dobj.catId.oid);
3605
agginfo[i].aggfn.rolname = strdup(PQgetvalue(res, i, i_rolname));
3606
if (strlen(agginfo[i].aggfn.rolname) == 0)
3607
write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
3608
agginfo[i].aggfn.dobj.name);
3609
agginfo[i].aggfn.lang = InvalidOid; /* not currently interesting */
3610
agginfo[i].aggfn.prorettype = InvalidOid; /* not saved */
3611
agginfo[i].aggfn.proacl = strdup(PQgetvalue(res, i, i_aggacl));
3612
agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs));
3613
if (agginfo[i].aggfn.nargs == 0)
3614
agginfo[i].aggfn.argtypes = NULL;
3617
agginfo[i].aggfn.argtypes = (Oid *) malloc(agginfo[i].aggfn.nargs * sizeof(Oid));
3618
if (g_fout->remoteVersion >= 70300)
3619
parseOidArray(PQgetvalue(res, i, i_proargtypes),
3620
agginfo[i].aggfn.argtypes,
3621
agginfo[i].aggfn.nargs);
3623
/* it's just aggbasetype */
3624
agginfo[i].aggfn.argtypes[0] = atooid(PQgetvalue(res, i, i_proargtypes));
3627
/* Decide whether we want to dump it */
3628
selectDumpableObject(&(agginfo[i].aggfn.dobj));
3633
destroyPQExpBuffer(query);
3640
* read all the user-defined functions in the system catalogs and
3641
* return them in the FuncInfo* structure
3643
* numFuncs is set to the number of functions read in
3646
getFuncs(int *numFuncs)
3651
PQExpBuffer query = createPQExpBuffer();
3664
/* Make sure we are in proper schema */
3665
selectSourceSchema("pg_catalog");
3668
* Find all user-defined functions. Normally we can exclude functions in
3669
* pg_catalog, which is worth doing since there are several thousand of
3670
* 'em. However, there are some extensions that create functions in
3671
* pg_catalog. In normal dumps we can still ignore those --- but in
3672
* binary-upgrade mode, we must dump the member objects of the extension,
3673
* so be sure to fetch any such functions.
3676
if (g_fout->remoteVersion >= 70300)
3678
appendPQExpBuffer(query,
3679
"SELECT tableoid, oid, proname, prolang, "
3680
"pronargs, proargtypes, prorettype, proacl, "
3682
"(%s proowner) AS rolname "
3684
"WHERE NOT proisagg AND ("
3686
"(SELECT oid FROM pg_namespace "
3687
"WHERE nspname = 'pg_catalog')",
3689
if (binary_upgrade && g_fout->remoteVersion >= 90100)
3690
appendPQExpBuffer(query,
3691
" OR EXISTS(SELECT 1 FROM pg_depend WHERE "
3692
"classid = 'pg_proc'::regclass AND "
3693
"objid = p.oid AND "
3694
"refclassid = 'pg_extension'::regclass AND "
3696
appendPQExpBuffer(query, ")");
3698
else if (g_fout->remoteVersion >= 70100)
3700
appendPQExpBuffer(query,
3701
"SELECT tableoid, oid, proname, prolang, "
3702
"pronargs, proargtypes, prorettype, "
3703
"'{=X}' AS proacl, "
3704
"0::oid AS pronamespace, "
3705
"(%s proowner) AS rolname "
3707
"WHERE pg_proc.oid > '%u'::oid",
3709
g_last_builtin_oid);
3713
appendPQExpBuffer(query,
3715
"(SELECT oid FROM pg_class "
3716
" WHERE relname = 'pg_proc') AS tableoid, "
3717
"oid, proname, prolang, "
3718
"pronargs, proargtypes, prorettype, "
3719
"'{=X}' AS proacl, "
3720
"0::oid AS pronamespace, "
3721
"(%s proowner) AS rolname "
3723
"where pg_proc.oid > '%u'::oid",
3725
g_last_builtin_oid);
3728
res = PQexec(g_conn, query->data);
3729
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3731
ntups = PQntuples(res);
3735
finfo = (FuncInfo *) calloc(ntups, sizeof(FuncInfo));
3737
i_tableoid = PQfnumber(res, "tableoid");
3738
i_oid = PQfnumber(res, "oid");
3739
i_proname = PQfnumber(res, "proname");
3740
i_pronamespace = PQfnumber(res, "pronamespace");
3741
i_rolname = PQfnumber(res, "rolname");
3742
i_prolang = PQfnumber(res, "prolang");
3743
i_pronargs = PQfnumber(res, "pronargs");
3744
i_proargtypes = PQfnumber(res, "proargtypes");
3745
i_prorettype = PQfnumber(res, "prorettype");
3746
i_proacl = PQfnumber(res, "proacl");
3748
for (i = 0; i < ntups; i++)
3750
finfo[i].dobj.objType = DO_FUNC;
3751
finfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
3752
finfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
3753
AssignDumpId(&finfo[i].dobj);
3754
finfo[i].dobj.name = strdup(PQgetvalue(res, i, i_proname));
3755
finfo[i].dobj.namespace =
3756
findNamespace(atooid(PQgetvalue(res, i, i_pronamespace)),
3757
finfo[i].dobj.catId.oid);
3758
finfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
3759
finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
3760
finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
3761
finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl));
3762
finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
3763
if (finfo[i].nargs == 0)
3764
finfo[i].argtypes = NULL;
3767
finfo[i].argtypes = (Oid *) malloc(finfo[i].nargs * sizeof(Oid));
3768
parseOidArray(PQgetvalue(res, i, i_proargtypes),
3769
finfo[i].argtypes, finfo[i].nargs);
3772
/* Decide whether we want to dump it */
3773
selectDumpableObject(&(finfo[i].dobj));
3775
if (strlen(finfo[i].rolname) == 0)
3777
"WARNING: owner of function \"%s\" appears to be invalid\n",
3778
finfo[i].dobj.name);
3783
destroyPQExpBuffer(query);
3790
* read all the user-defined tables (no indexes, no catalogs)
3791
* in the system catalogs return them in the TableInfo* structure
3793
* numTables is set to the number of tables read in
3796
getTables(int *numTables)
3801
PQExpBuffer query = createPQExpBuffer();
3811
int i_relhastriggers;
3817
int i_toastfrozenxid;
3818
int i_relpersistence;
3821
int i_reltablespace;
3823
int i_toastreloptions;
3826
/* Make sure we are in proper schema */
3827
selectSourceSchema("pg_catalog");
3830
* Find all the tables (including views and sequences).
3832
* We include system catalogs, so that we can work if a user table is
3833
* defined to inherit from a system catalog (pretty weird, but...)
3835
* We ignore tables that are not type 'r' (ordinary relation), 'S'
3836
* (sequence), 'v' (view), or 'c' (composite type).
3838
* Composite-type table entries won't be dumped as such, but we have to
3839
* make a DumpableObject for them so that we can track dependencies of the
3840
* composite type (pg_depend entries for columns of the composite type
3841
* link to the pg_class entry not the pg_type entry).
3843
* Note: in this phase we should collect only a minimal amount of
3844
* information about each table, basically just enough to decide if it is
3845
* interesting. We must fetch all tables in this phase because otherwise
3846
* we cannot correctly identify inherited columns, owned sequences, etc.
3849
if (g_fout->remoteVersion >= 90100)
3852
* Left join to pick up dependency info linking sequences to their
3853
* owning column, if any (note this dependency is AUTO as of 8.2)
3855
appendPQExpBuffer(query,
3856
"SELECT c.tableoid, c.oid, c.relname, "
3857
"c.relacl, c.relkind, c.relnamespace, "
3858
"(%s c.relowner) AS rolname, "
3859
"c.relchecks, c.relhastriggers, "
3860
"c.relhasindex, c.relhasrules, c.relhasoids, "
3861
"c.relfrozenxid, tc.oid AS toid, "
3862
"tc.relfrozenxid AS tfrozenxid, "
3863
"c.relpersistence, "
3864
"CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
3865
"d.refobjid AS owning_tab, "
3866
"d.refobjsubid AS owning_col, "
3867
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3868
"array_to_string(c.reloptions, ', ') AS reloptions, "
3869
"array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions "
3871
"LEFT JOIN pg_depend d ON "
3872
"(c.relkind = '%c' AND "
3873
"d.classid = c.tableoid AND d.objid = c.oid AND "
3874
"d.objsubid = 0 AND "
3875
"d.refclassid = c.tableoid AND d.deptype = 'a') "
3876
"LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
3877
"WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c') "
3881
RELKIND_RELATION, RELKIND_SEQUENCE,
3882
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
3883
RELKIND_FOREIGN_TABLE);
3885
else if (g_fout->remoteVersion >= 90000)
3888
* Left join to pick up dependency info linking sequences to their
3889
* owning column, if any (note this dependency is AUTO as of 8.2)
3891
appendPQExpBuffer(query,
3892
"SELECT c.tableoid, c.oid, c.relname, "
3893
"c.relacl, c.relkind, c.relnamespace, "
3894
"(%s c.relowner) AS rolname, "
3895
"c.relchecks, c.relhastriggers, "
3896
"c.relhasindex, c.relhasrules, c.relhasoids, "
3897
"c.relfrozenxid, tc.oid AS toid, "
3898
"tc.relfrozenxid AS tfrozenxid, "
3899
"'p' AS relpersistence, "
3900
"CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
3901
"d.refobjid AS owning_tab, "
3902
"d.refobjsubid AS owning_col, "
3903
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3904
"array_to_string(c.reloptions, ', ') AS reloptions, "
3905
"array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions "
3907
"LEFT JOIN pg_depend d ON "
3908
"(c.relkind = '%c' AND "
3909
"d.classid = c.tableoid AND d.objid = c.oid AND "
3910
"d.objsubid = 0 AND "
3911
"d.refclassid = c.tableoid AND d.deptype = 'a') "
3912
"LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
3913
"WHERE c.relkind in ('%c', '%c', '%c', '%c') "
3917
RELKIND_RELATION, RELKIND_SEQUENCE,
3918
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
3920
else if (g_fout->remoteVersion >= 80400)
3923
* Left join to pick up dependency info linking sequences to their
3924
* owning column, if any (note this dependency is AUTO as of 8.2)
3926
appendPQExpBuffer(query,
3927
"SELECT c.tableoid, c.oid, c.relname, "
3928
"c.relacl, c.relkind, c.relnamespace, "
3929
"(%s c.relowner) AS rolname, "
3930
"c.relchecks, c.relhastriggers, "
3931
"c.relhasindex, c.relhasrules, c.relhasoids, "
3932
"c.relfrozenxid, tc.oid AS toid, "
3933
"tc.relfrozenxid AS tfrozenxid, "
3934
"'p' AS relpersistence, "
3935
"NULL AS reloftype, "
3936
"d.refobjid AS owning_tab, "
3937
"d.refobjsubid AS owning_col, "
3938
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3939
"array_to_string(c.reloptions, ', ') AS reloptions, "
3940
"array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions "
3942
"LEFT JOIN pg_depend d ON "
3943
"(c.relkind = '%c' AND "
3944
"d.classid = c.tableoid AND d.objid = c.oid AND "
3945
"d.objsubid = 0 AND "
3946
"d.refclassid = c.tableoid AND d.deptype = 'a') "
3947
"LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
3948
"WHERE c.relkind in ('%c', '%c', '%c', '%c') "
3952
RELKIND_RELATION, RELKIND_SEQUENCE,
3953
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
3955
else if (g_fout->remoteVersion >= 80200)
3958
* Left join to pick up dependency info linking sequences to their
3959
* owning column, if any (note this dependency is AUTO as of 8.2)
3961
appendPQExpBuffer(query,
3962
"SELECT c.tableoid, c.oid, relname, "
3963
"relacl, relkind, relnamespace, "
3964
"(%s relowner) AS rolname, "
3965
"relchecks, (reltriggers <> 0) AS relhastriggers, "
3966
"relhasindex, relhasrules, relhasoids, "
3970
"'p' AS relpersistence, "
3971
"NULL AS reloftype, "
3972
"d.refobjid AS owning_tab, "
3973
"d.refobjsubid AS owning_col, "
3974
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3975
"array_to_string(c.reloptions, ', ') AS reloptions, "
3976
"NULL AS toast_reloptions "
3978
"LEFT JOIN pg_depend d ON "
3979
"(c.relkind = '%c' AND "
3980
"d.classid = c.tableoid AND d.objid = c.oid AND "
3981
"d.objsubid = 0 AND "
3982
"d.refclassid = c.tableoid AND d.deptype = 'a') "
3983
"WHERE relkind in ('%c', '%c', '%c', '%c') "
3987
RELKIND_RELATION, RELKIND_SEQUENCE,
3988
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
3990
else if (g_fout->remoteVersion >= 80000)
3993
* Left join to pick up dependency info linking sequences to their
3994
* owning column, if any
3996
appendPQExpBuffer(query,
3997
"SELECT c.tableoid, c.oid, relname, "
3998
"relacl, relkind, relnamespace, "
3999
"(%s relowner) AS rolname, "
4000
"relchecks, (reltriggers <> 0) AS relhastriggers, "
4001
"relhasindex, relhasrules, relhasoids, "
4002
"0 AS relfrozenxid, "
4005
"'p' AS relpersistence, "
4006
"NULL AS reloftype, "
4007
"d.refobjid AS owning_tab, "
4008
"d.refobjsubid AS owning_col, "
4009
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
4010
"NULL AS reloptions, "
4011
"NULL AS toast_reloptions "
4013
"LEFT JOIN pg_depend d ON "
4014
"(c.relkind = '%c' AND "
4015
"d.classid = c.tableoid AND d.objid = c.oid AND "
4016
"d.objsubid = 0 AND "
4017
"d.refclassid = c.tableoid AND d.deptype = 'i') "
4018
"WHERE relkind in ('%c', '%c', '%c', '%c') "
4022
RELKIND_RELATION, RELKIND_SEQUENCE,
4023
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
4025
else if (g_fout->remoteVersion >= 70300)
4028
* Left join to pick up dependency info linking sequences to their
4029
* owning column, if any
4031
appendPQExpBuffer(query,
4032
"SELECT c.tableoid, c.oid, relname, "
4033
"relacl, relkind, relnamespace, "
4034
"(%s relowner) AS rolname, "
4035
"relchecks, (reltriggers <> 0) AS relhastriggers, "
4036
"relhasindex, relhasrules, relhasoids, "
4037
"0 AS relfrozenxid, "
4040
"'p' AS relpersistence, "
4041
"NULL AS reloftype, "
4042
"d.refobjid AS owning_tab, "
4043
"d.refobjsubid AS owning_col, "
4044
"NULL AS reltablespace, "
4045
"NULL AS reloptions, "
4046
"NULL AS toast_reloptions "
4048
"LEFT JOIN pg_depend d ON "
4049
"(c.relkind = '%c' AND "
4050
"d.classid = c.tableoid AND d.objid = c.oid AND "
4051
"d.objsubid = 0 AND "
4052
"d.refclassid = c.tableoid AND d.deptype = 'i') "
4053
"WHERE relkind IN ('%c', '%c', '%c', '%c') "
4057
RELKIND_RELATION, RELKIND_SEQUENCE,
4058
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
4060
else if (g_fout->remoteVersion >= 70200)
4062
appendPQExpBuffer(query,
4063
"SELECT tableoid, oid, relname, relacl, relkind, "
4064
"0::oid AS relnamespace, "
4065
"(%s relowner) AS rolname, "
4066
"relchecks, (reltriggers <> 0) AS relhastriggers, "
4067
"relhasindex, relhasrules, relhasoids, "
4068
"0 AS relfrozenxid, "
4071
"'p' AS relpersistence, "
4072
"NULL AS reloftype, "
4073
"NULL::oid AS owning_tab, "
4074
"NULL::int4 AS owning_col, "
4075
"NULL AS reltablespace, "
4076
"NULL AS reloptions, "
4077
"NULL AS toast_reloptions "
4079
"WHERE relkind IN ('%c', '%c', '%c') "
4082
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
4084
else if (g_fout->remoteVersion >= 70100)
4086
/* all tables have oids in 7.1 */
4087
appendPQExpBuffer(query,
4088
"SELECT tableoid, oid, relname, relacl, relkind, "
4089
"0::oid AS relnamespace, "
4090
"(%s relowner) AS rolname, "
4091
"relchecks, (reltriggers <> 0) AS relhastriggers, "
4092
"relhasindex, relhasrules, "
4093
"'t'::bool AS relhasoids, "
4094
"0 AS relfrozenxid, "
4097
"'p' AS relpersistence, "
4098
"NULL AS reloftype, "
4099
"NULL::oid AS owning_tab, "
4100
"NULL::int4 AS owning_col, "
4101
"NULL AS reltablespace, "
4102
"NULL AS reloptions, "
4103
"NULL AS toast_reloptions "
4105
"WHERE relkind IN ('%c', '%c', '%c') "
4108
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
4113
* Before 7.1, view relkind was not set to 'v', so we must check if we
4114
* have a view by looking for a rule in pg_rewrite.
4116
appendPQExpBuffer(query,
4118
"(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
4119
"oid, relname, relacl, "
4120
"CASE WHEN relhasrules and relkind = 'r' "
4121
" and EXISTS(SELECT rulename FROM pg_rewrite r WHERE "
4122
" r.ev_class = c.oid AND r.ev_type = '1') "
4123
"THEN '%c'::\"char\" "
4124
"ELSE relkind END AS relkind,"
4125
"0::oid AS relnamespace, "
4126
"(%s relowner) AS rolname, "
4127
"relchecks, (reltriggers <> 0) AS relhastriggers, "
4128
"relhasindex, relhasrules, "
4129
"'t'::bool AS relhasoids, "
4130
"0 as relfrozenxid, "
4133
"'p' AS relpersistence, "
4134
"NULL AS reloftype, "
4135
"NULL::oid AS owning_tab, "
4136
"NULL::int4 AS owning_col, "
4137
"NULL AS reltablespace, "
4138
"NULL AS reloptions, "
4139
"NULL AS toast_reloptions "
4141
"WHERE relkind IN ('%c', '%c') "
4145
RELKIND_RELATION, RELKIND_SEQUENCE);
4148
res = PQexec(g_conn, query->data);
4149
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4151
ntups = PQntuples(res);
4156
* Extract data from result and lock dumpable tables. We do the locking
4157
* before anything else, to minimize the window wherein a table could
4158
* disappear under us.
4160
* Note that we have to save info about all tables here, even when dumping
4161
* only one, because we don't yet know which tables might be inheritance
4162
* ancestors of the target table.
4164
tblinfo = (TableInfo *) calloc(ntups, sizeof(TableInfo));
4166
i_reltableoid = PQfnumber(res, "tableoid");
4167
i_reloid = PQfnumber(res, "oid");
4168
i_relname = PQfnumber(res, "relname");
4169
i_relnamespace = PQfnumber(res, "relnamespace");
4170
i_relacl = PQfnumber(res, "relacl");
4171
i_relkind = PQfnumber(res, "relkind");
4172
i_rolname = PQfnumber(res, "rolname");
4173
i_relchecks = PQfnumber(res, "relchecks");
4174
i_relhastriggers = PQfnumber(res, "relhastriggers");
4175
i_relhasindex = PQfnumber(res, "relhasindex");
4176
i_relhasrules = PQfnumber(res, "relhasrules");
4177
i_relhasoids = PQfnumber(res, "relhasoids");
4178
i_relfrozenxid = PQfnumber(res, "relfrozenxid");
4179
i_toastoid = PQfnumber(res, "toid");
4180
i_toastfrozenxid = PQfnumber(res, "tfrozenxid");
4181
i_relpersistence = PQfnumber(res, "relpersistence");
4182
i_owning_tab = PQfnumber(res, "owning_tab");
4183
i_owning_col = PQfnumber(res, "owning_col");
4184
i_reltablespace = PQfnumber(res, "reltablespace");
4185
i_reloptions = PQfnumber(res, "reloptions");
4186
i_toastreloptions = PQfnumber(res, "toast_reloptions");
4187
i_reloftype = PQfnumber(res, "reloftype");
4189
if (lockWaitTimeout && g_fout->remoteVersion >= 70300)
4192
* Arrange to fail instead of waiting forever for a table lock.
4194
* NB: this coding assumes that the only queries issued within the
4195
* following loop are LOCK TABLEs; else the timeout may be undesirably
4196
* applied to other things too.
4198
resetPQExpBuffer(query);
4199
appendPQExpBuffer(query, "SET statement_timeout = ");
4200
appendStringLiteralConn(query, lockWaitTimeout, g_conn);
4201
do_sql_command(g_conn, query->data);
4204
for (i = 0; i < ntups; i++)
4206
tblinfo[i].dobj.objType = DO_TABLE;
4207
tblinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_reltableoid));
4208
tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid));
4209
AssignDumpId(&tblinfo[i].dobj);
4210
tblinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_relname));
4211
tblinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_relnamespace)),
4212
tblinfo[i].dobj.catId.oid);
4213
tblinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
4214
tblinfo[i].relacl = strdup(PQgetvalue(res, i, i_relacl));
4215
tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
4216
tblinfo[i].relpersistence = *(PQgetvalue(res, i, i_relpersistence));
4217
tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
4218
tblinfo[i].hasrules = (strcmp(PQgetvalue(res, i, i_relhasrules), "t") == 0);
4219
tblinfo[i].hastriggers = (strcmp(PQgetvalue(res, i, i_relhastriggers), "t") == 0);
4220
tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
4221
tblinfo[i].frozenxid = atooid(PQgetvalue(res, i, i_relfrozenxid));
4222
tblinfo[i].toast_oid = atooid(PQgetvalue(res, i, i_toastoid));
4223
tblinfo[i].toast_frozenxid = atooid(PQgetvalue(res, i, i_toastfrozenxid));
4224
if (PQgetisnull(res, i, i_reloftype))
4225
tblinfo[i].reloftype = NULL;
4227
tblinfo[i].reloftype = strdup(PQgetvalue(res, i, i_reloftype));
4228
tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
4229
if (PQgetisnull(res, i, i_owning_tab))
4231
tblinfo[i].owning_tab = InvalidOid;
4232
tblinfo[i].owning_col = 0;
4236
tblinfo[i].owning_tab = atooid(PQgetvalue(res, i, i_owning_tab));
4237
tblinfo[i].owning_col = atoi(PQgetvalue(res, i, i_owning_col));
4239
tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace));
4240
tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions));
4241
tblinfo[i].toast_reloptions = strdup(PQgetvalue(res, i, i_toastreloptions));
4243
/* other fields were zeroed above */
4246
* Decide whether we want to dump this table.
4248
if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
4249
tblinfo[i].dobj.dump = false;
4251
selectDumpableTable(&tblinfo[i]);
4252
tblinfo[i].interesting = tblinfo[i].dobj.dump;
4255
* Read-lock target tables to make sure they aren't DROPPED or altered
4256
* in schema before we get around to dumping them.
4258
* Note that we don't explicitly lock parents of the target tables; we
4259
* assume our lock on the child is enough to prevent schema
4260
* alterations to parent tables.
4262
* NOTE: it'd be kinda nice to lock other relations too, not only
4263
* plain tables, but the backend doesn't presently allow that.
4265
if (tblinfo[i].dobj.dump && tblinfo[i].relkind == RELKIND_RELATION)
4267
resetPQExpBuffer(query);
4268
appendPQExpBuffer(query,
4269
"LOCK TABLE %s IN ACCESS SHARE MODE",
4270
fmtQualifiedId(tblinfo[i].dobj.namespace->dobj.name,
4271
tblinfo[i].dobj.name));
4272
do_sql_command(g_conn, query->data);
4275
/* Emit notice if join for owner failed */
4276
if (strlen(tblinfo[i].rolname) == 0)
4277
write_msg(NULL, "WARNING: owner of table \"%s\" appears to be invalid\n",
4278
tblinfo[i].dobj.name);
4281
if (lockWaitTimeout && g_fout->remoteVersion >= 70300)
4283
do_sql_command(g_conn, "SET statement_timeout = 0");
4289
* Force sequences that are "owned" by table columns to be dumped whenever
4290
* their owning table is being dumped.
4292
for (i = 0; i < ntups; i++)
4294
TableInfo *seqinfo = &tblinfo[i];
4297
if (!OidIsValid(seqinfo->owning_tab))
4298
continue; /* not an owned sequence */
4299
if (seqinfo->dobj.dump)
4300
continue; /* no need to search */
4302
/* can't use findTableByOid yet, unfortunately */
4303
for (j = 0; j < ntups; j++)
4305
if (tblinfo[j].dobj.catId.oid == seqinfo->owning_tab)
4307
if (tblinfo[j].dobj.dump)
4309
seqinfo->interesting = true;
4310
seqinfo->dobj.dump = true;
4317
destroyPQExpBuffer(query);
4324
* read all the inheritance information
4325
* from the system catalogs return them in the InhInfo* structure
4327
* numInherits is set to the number of pairs read in
4330
getInherits(int *numInherits)
4335
PQExpBuffer query = createPQExpBuffer();
4341
/* Make sure we are in proper schema */
4342
selectSourceSchema("pg_catalog");
4344
/* find all the inheritance information */
4346
appendPQExpBuffer(query, "SELECT inhrelid, inhparent FROM pg_inherits");
4348
res = PQexec(g_conn, query->data);
4349
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4351
ntups = PQntuples(res);
4353
*numInherits = ntups;
4355
inhinfo = (InhInfo *) malloc(ntups * sizeof(InhInfo));
4357
i_inhrelid = PQfnumber(res, "inhrelid");
4358
i_inhparent = PQfnumber(res, "inhparent");
4360
for (i = 0; i < ntups; i++)
4362
inhinfo[i].inhrelid = atooid(PQgetvalue(res, i, i_inhrelid));
4363
inhinfo[i].inhparent = atooid(PQgetvalue(res, i, i_inhparent));
4368
destroyPQExpBuffer(query);
4375
* get information about every index on a dumpable table
4377
* Note: index data is not returned directly to the caller, but it
4378
* does get entered into the DumpableObject tables.
4381
getIndexes(TableInfo tblinfo[], int numTables)
4385
PQExpBuffer query = createPQExpBuffer();
4388
ConstraintInfo *constrinfo;
4407
for (i = 0; i < numTables; i++)
4409
TableInfo *tbinfo = &tblinfo[i];
4411
/* Only plain tables have indexes */
4412
if (tbinfo->relkind != RELKIND_RELATION || !tbinfo->hasindex)
4415
/* Ignore indexes of tables not to be dumped */
4416
if (!tbinfo->dobj.dump)
4420
write_msg(NULL, "reading indexes for table \"%s\"\n",
4423
/* Make sure we are in proper schema so indexdef is right */
4424
selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
4427
* The point of the messy-looking outer join is to find a constraint
4428
* that is related by an internal dependency link to the index. If we
4429
* find one, create a CONSTRAINT entry linked to the INDEX entry. We
4430
* assume an index won't have more than one internal dependency.
4432
* As of 9.0 we don't need to look at pg_depend but can check for a
4433
* match to pg_constraint.conindid. The check on conrelid is
4434
* redundant but useful because that column is indexed while conindid
4437
resetPQExpBuffer(query);
4438
if (g_fout->remoteVersion >= 90000)
4440
appendPQExpBuffer(query,
4441
"SELECT t.tableoid, t.oid, "
4442
"t.relname AS indexname, "
4443
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
4444
"t.relnatts AS indnkeys, "
4445
"i.indkey, i.indisclustered, "
4446
"c.contype, c.conname, "
4447
"c.condeferrable, c.condeferred, "
4448
"c.tableoid AS contableoid, "
4450
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
4451
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
4452
"array_to_string(t.reloptions, ', ') AS options "
4453
"FROM pg_catalog.pg_index i "
4454
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
4455
"LEFT JOIN pg_catalog.pg_constraint c "
4456
"ON (i.indrelid = c.conrelid AND "
4457
"i.indexrelid = c.conindid AND "
4458
"c.contype IN ('p','u','x')) "
4459
"WHERE i.indrelid = '%u'::pg_catalog.oid "
4460
"ORDER BY indexname",
4461
tbinfo->dobj.catId.oid);
4463
else if (g_fout->remoteVersion >= 80200)
4465
appendPQExpBuffer(query,
4466
"SELECT t.tableoid, t.oid, "
4467
"t.relname AS indexname, "
4468
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
4469
"t.relnatts AS indnkeys, "
4470
"i.indkey, i.indisclustered, "
4471
"c.contype, c.conname, "
4472
"c.condeferrable, c.condeferred, "
4473
"c.tableoid AS contableoid, "
4476
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
4477
"array_to_string(t.reloptions, ', ') AS options "
4478
"FROM pg_catalog.pg_index i "
4479
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
4480
"LEFT JOIN pg_catalog.pg_depend d "
4481
"ON (d.classid = t.tableoid "
4482
"AND d.objid = t.oid "
4483
"AND d.deptype = 'i') "
4484
"LEFT JOIN pg_catalog.pg_constraint c "
4485
"ON (d.refclassid = c.tableoid "
4486
"AND d.refobjid = c.oid) "
4487
"WHERE i.indrelid = '%u'::pg_catalog.oid "
4488
"ORDER BY indexname",
4489
tbinfo->dobj.catId.oid);
4491
else if (g_fout->remoteVersion >= 80000)
4493
appendPQExpBuffer(query,
4494
"SELECT t.tableoid, t.oid, "
4495
"t.relname AS indexname, "
4496
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
4497
"t.relnatts AS indnkeys, "
4498
"i.indkey, i.indisclustered, "
4499
"c.contype, c.conname, "
4500
"c.condeferrable, c.condeferred, "
4501
"c.tableoid AS contableoid, "
4504
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
4506
"FROM pg_catalog.pg_index i "
4507
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
4508
"LEFT JOIN pg_catalog.pg_depend d "
4509
"ON (d.classid = t.tableoid "
4510
"AND d.objid = t.oid "
4511
"AND d.deptype = 'i') "
4512
"LEFT JOIN pg_catalog.pg_constraint c "
4513
"ON (d.refclassid = c.tableoid "
4514
"AND d.refobjid = c.oid) "
4515
"WHERE i.indrelid = '%u'::pg_catalog.oid "
4516
"ORDER BY indexname",
4517
tbinfo->dobj.catId.oid);
4519
else if (g_fout->remoteVersion >= 70300)
4521
appendPQExpBuffer(query,
4522
"SELECT t.tableoid, t.oid, "
4523
"t.relname AS indexname, "
4524
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
4525
"t.relnatts AS indnkeys, "
4526
"i.indkey, i.indisclustered, "
4527
"c.contype, c.conname, "
4528
"c.condeferrable, c.condeferred, "
4529
"c.tableoid AS contableoid, "
4532
"NULL AS tablespace, "
4534
"FROM pg_catalog.pg_index i "
4535
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
4536
"LEFT JOIN pg_catalog.pg_depend d "
4537
"ON (d.classid = t.tableoid "
4538
"AND d.objid = t.oid "
4539
"AND d.deptype = 'i') "
4540
"LEFT JOIN pg_catalog.pg_constraint c "
4541
"ON (d.refclassid = c.tableoid "
4542
"AND d.refobjid = c.oid) "
4543
"WHERE i.indrelid = '%u'::pg_catalog.oid "
4544
"ORDER BY indexname",
4545
tbinfo->dobj.catId.oid);
4547
else if (g_fout->remoteVersion >= 70100)
4549
appendPQExpBuffer(query,
4550
"SELECT t.tableoid, t.oid, "
4551
"t.relname AS indexname, "
4552
"pg_get_indexdef(i.indexrelid) AS indexdef, "
4553
"t.relnatts AS indnkeys, "
4554
"i.indkey, false AS indisclustered, "
4555
"CASE WHEN i.indisprimary THEN 'p'::char "
4556
"ELSE '0'::char END AS contype, "
4557
"t.relname AS conname, "
4558
"false AS condeferrable, "
4559
"false AS condeferred, "
4560
"0::oid AS contableoid, "
4563
"NULL AS tablespace, "
4565
"FROM pg_index i, pg_class t "
4566
"WHERE t.oid = i.indexrelid "
4567
"AND i.indrelid = '%u'::oid "
4568
"ORDER BY indexname",
4569
tbinfo->dobj.catId.oid);
4573
appendPQExpBuffer(query,
4575
"(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
4577
"t.relname AS indexname, "
4578
"pg_get_indexdef(i.indexrelid) AS indexdef, "
4579
"t.relnatts AS indnkeys, "
4580
"i.indkey, false AS indisclustered, "
4581
"CASE WHEN i.indisprimary THEN 'p'::char "
4582
"ELSE '0'::char END AS contype, "
4583
"t.relname AS conname, "
4584
"false AS condeferrable, "
4585
"false AS condeferred, "
4586
"0::oid AS contableoid, "
4589
"NULL AS tablespace, "
4591
"FROM pg_index i, pg_class t "
4592
"WHERE t.oid = i.indexrelid "
4593
"AND i.indrelid = '%u'::oid "
4594
"ORDER BY indexname",
4595
tbinfo->dobj.catId.oid);
4598
res = PQexec(g_conn, query->data);
4599
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4601
ntups = PQntuples(res);
4603
i_tableoid = PQfnumber(res, "tableoid");
4604
i_oid = PQfnumber(res, "oid");
4605
i_indexname = PQfnumber(res, "indexname");
4606
i_indexdef = PQfnumber(res, "indexdef");
4607
i_indnkeys = PQfnumber(res, "indnkeys");
4608
i_indkey = PQfnumber(res, "indkey");
4609
i_indisclustered = PQfnumber(res, "indisclustered");
4610
i_contype = PQfnumber(res, "contype");
4611
i_conname = PQfnumber(res, "conname");
4612
i_condeferrable = PQfnumber(res, "condeferrable");
4613
i_condeferred = PQfnumber(res, "condeferred");
4614
i_contableoid = PQfnumber(res, "contableoid");
4615
i_conoid = PQfnumber(res, "conoid");
4616
i_condef = PQfnumber(res, "condef");
4617
i_tablespace = PQfnumber(res, "tablespace");
4618
i_options = PQfnumber(res, "options");
4620
indxinfo = (IndxInfo *) malloc(ntups * sizeof(IndxInfo));
4621
constrinfo = (ConstraintInfo *) malloc(ntups * sizeof(ConstraintInfo));
4623
for (j = 0; j < ntups; j++)
4627
indxinfo[j].dobj.objType = DO_INDEX;
4628
indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
4629
indxinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
4630
AssignDumpId(&indxinfo[j].dobj);
4631
indxinfo[j].dobj.name = strdup(PQgetvalue(res, j, i_indexname));
4632
indxinfo[j].dobj.namespace = tbinfo->dobj.namespace;
4633
indxinfo[j].indextable = tbinfo;
4634
indxinfo[j].indexdef = strdup(PQgetvalue(res, j, i_indexdef));
4635
indxinfo[j].indnkeys = atoi(PQgetvalue(res, j, i_indnkeys));
4636
indxinfo[j].tablespace = strdup(PQgetvalue(res, j, i_tablespace));
4637
indxinfo[j].options = strdup(PQgetvalue(res, j, i_options));
4640
* In pre-7.4 releases, indkeys may contain more entries than
4641
* indnkeys says (since indnkeys will be 1 for a functional
4642
* index). We don't actually care about this case since we don't
4643
* examine indkeys except for indexes associated with PRIMARY and
4644
* UNIQUE constraints, which are never functional indexes. But we
4645
* have to allocate enough space to keep parseOidArray from
4648
indxinfo[j].indkeys = (Oid *) malloc(INDEX_MAX_KEYS * sizeof(Oid));
4649
parseOidArray(PQgetvalue(res, j, i_indkey),
4650
indxinfo[j].indkeys, INDEX_MAX_KEYS);
4651
indxinfo[j].indisclustered = (PQgetvalue(res, j, i_indisclustered)[0] == 't');
4652
contype = *(PQgetvalue(res, j, i_contype));
4654
if (contype == 'p' || contype == 'u' || contype == 'x')
4657
* If we found a constraint matching the index, create an
4660
* In a pre-7.3 database, we take this path iff the index was
4661
* marked indisprimary.
4663
constrinfo[j].dobj.objType = DO_CONSTRAINT;
4664
constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
4665
constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
4666
AssignDumpId(&constrinfo[j].dobj);
4667
constrinfo[j].dobj.name = strdup(PQgetvalue(res, j, i_conname));
4668
constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
4669
constrinfo[j].contable = tbinfo;
4670
constrinfo[j].condomain = NULL;
4671
constrinfo[j].contype = contype;
4673
constrinfo[j].condef = strdup(PQgetvalue(res, j, i_condef));
4675
constrinfo[j].condef = NULL;
4676
constrinfo[j].confrelid = InvalidOid;
4677
constrinfo[j].conindex = indxinfo[j].dobj.dumpId;
4678
constrinfo[j].condeferrable = *(PQgetvalue(res, j, i_condeferrable)) == 't';
4679
constrinfo[j].condeferred = *(PQgetvalue(res, j, i_condeferred)) == 't';
4680
constrinfo[j].conislocal = true;
4681
constrinfo[j].separate = true;
4683
indxinfo[j].indexconstraint = constrinfo[j].dobj.dumpId;
4685
/* If pre-7.3 DB, better make sure table comes first */
4686
addObjectDependency(&constrinfo[j].dobj,
4687
tbinfo->dobj.dumpId);
4691
/* Plain secondary index */
4692
indxinfo[j].indexconstraint = 0;
4699
destroyPQExpBuffer(query);
4705
* Get info about constraints on dumpable tables.
4707
* Currently handles foreign keys only.
4708
* Unique and primary key constraints are handled with indexes,
4709
* while check constraints are processed in getTableAttrs().
4712
getConstraints(TableInfo tblinfo[], int numTables)
4716
ConstraintInfo *constrinfo;
4726
/* pg_constraint was created in 7.3, so nothing to do if older */
4727
if (g_fout->remoteVersion < 70300)
4730
query = createPQExpBuffer();
4732
for (i = 0; i < numTables; i++)
4734
TableInfo *tbinfo = &tblinfo[i];
4736
if (!tbinfo->hastriggers || !tbinfo->dobj.dump)
4740
write_msg(NULL, "reading foreign key constraints for table \"%s\"\n",
4744
* select table schema to ensure constraint expr is qualified if
4747
selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
4749
resetPQExpBuffer(query);
4750
appendPQExpBuffer(query,
4751
"SELECT tableoid, oid, conname, confrelid, "
4752
"pg_catalog.pg_get_constraintdef(oid) AS condef "
4753
"FROM pg_catalog.pg_constraint "
4754
"WHERE conrelid = '%u'::pg_catalog.oid "
4755
"AND contype = 'f'",
4756
tbinfo->dobj.catId.oid);
4757
res = PQexec(g_conn, query->data);
4758
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4760
ntups = PQntuples(res);
4762
i_contableoid = PQfnumber(res, "tableoid");
4763
i_conoid = PQfnumber(res, "oid");
4764
i_conname = PQfnumber(res, "conname");
4765
i_confrelid = PQfnumber(res, "confrelid");
4766
i_condef = PQfnumber(res, "condef");
4768
constrinfo = (ConstraintInfo *) malloc(ntups * sizeof(ConstraintInfo));
4770
for (j = 0; j < ntups; j++)
4772
constrinfo[j].dobj.objType = DO_FK_CONSTRAINT;
4773
constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
4774
constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
4775
AssignDumpId(&constrinfo[j].dobj);
4776
constrinfo[j].dobj.name = strdup(PQgetvalue(res, j, i_conname));
4777
constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
4778
constrinfo[j].contable = tbinfo;
4779
constrinfo[j].condomain = NULL;
4780
constrinfo[j].contype = 'f';
4781
constrinfo[j].condef = strdup(PQgetvalue(res, j, i_condef));
4782
constrinfo[j].confrelid = atooid(PQgetvalue(res, j, i_confrelid));
4783
constrinfo[j].conindex = 0;
4784
constrinfo[j].condeferrable = false;
4785
constrinfo[j].condeferred = false;
4786
constrinfo[j].conislocal = true;
4787
constrinfo[j].separate = true;
4793
destroyPQExpBuffer(query);
4797
* getDomainConstraints
4799
* Get info about constraints on a domain.
4802
getDomainConstraints(TypeInfo *tyinfo)
4805
ConstraintInfo *constrinfo;
4814
/* pg_constraint was created in 7.3, so nothing to do if older */
4815
if (g_fout->remoteVersion < 70300)
4819
* select appropriate schema to ensure names in constraint are properly
4822
selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
4824
query = createPQExpBuffer();
4826
if (g_fout->remoteVersion >= 70400)
4827
appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
4828
"pg_catalog.pg_get_constraintdef(oid) AS consrc "
4829
"FROM pg_catalog.pg_constraint "
4830
"WHERE contypid = '%u'::pg_catalog.oid "
4832
tyinfo->dobj.catId.oid);
4834
appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
4835
"'CHECK (' || consrc || ')' AS consrc "
4836
"FROM pg_catalog.pg_constraint "
4837
"WHERE contypid = '%u'::pg_catalog.oid "
4839
tyinfo->dobj.catId.oid);
4841
res = PQexec(g_conn, query->data);
4842
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4844
ntups = PQntuples(res);
4846
i_tableoid = PQfnumber(res, "tableoid");
4847
i_oid = PQfnumber(res, "oid");
4848
i_conname = PQfnumber(res, "conname");
4849
i_consrc = PQfnumber(res, "consrc");
4851
constrinfo = (ConstraintInfo *) malloc(ntups * sizeof(ConstraintInfo));
4853
tyinfo->nDomChecks = ntups;
4854
tyinfo->domChecks = constrinfo;
4856
for (i = 0; i < ntups; i++)
4858
constrinfo[i].dobj.objType = DO_CONSTRAINT;
4859
constrinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
4860
constrinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
4861
AssignDumpId(&constrinfo[i].dobj);
4862
constrinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_conname));
4863
constrinfo[i].dobj.namespace = tyinfo->dobj.namespace;
4864
constrinfo[i].contable = NULL;
4865
constrinfo[i].condomain = tyinfo;
4866
constrinfo[i].contype = 'c';
4867
constrinfo[i].condef = strdup(PQgetvalue(res, i, i_consrc));
4868
constrinfo[i].confrelid = InvalidOid;
4869
constrinfo[i].conindex = 0;
4870
constrinfo[i].condeferrable = false;
4871
constrinfo[i].condeferred = false;
4872
constrinfo[i].conislocal = true;
4873
constrinfo[i].separate = false;
4876
* Make the domain depend on the constraint, ensuring it won't be
4877
* output till any constraint dependencies are OK.
4879
addObjectDependency(&tyinfo->dobj,
4880
constrinfo[i].dobj.dumpId);
4885
destroyPQExpBuffer(query);
4890
* get basic information about every rule in the system
4892
* numRules is set to the number of rules read in
4895
getRules(int *numRules)
4900
PQExpBuffer query = createPQExpBuffer();
4910
/* Make sure we are in proper schema */
4911
selectSourceSchema("pg_catalog");
4913
if (g_fout->remoteVersion >= 80300)
4915
appendPQExpBuffer(query, "SELECT "
4916
"tableoid, oid, rulename, "
4917
"ev_class AS ruletable, ev_type, is_instead, "
4922
else if (g_fout->remoteVersion >= 70100)
4924
appendPQExpBuffer(query, "SELECT "
4925
"tableoid, oid, rulename, "
4926
"ev_class AS ruletable, ev_type, is_instead, "
4927
"'O'::char AS ev_enabled "
4933
appendPQExpBuffer(query, "SELECT "
4934
"(SELECT oid FROM pg_class WHERE relname = 'pg_rewrite') AS tableoid, "
4936
"ev_class AS ruletable, ev_type, is_instead, "
4937
"'O'::char AS ev_enabled "
4942
res = PQexec(g_conn, query->data);
4943
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4945
ntups = PQntuples(res);
4949
ruleinfo = (RuleInfo *) malloc(ntups * sizeof(RuleInfo));
4951
i_tableoid = PQfnumber(res, "tableoid");
4952
i_oid = PQfnumber(res, "oid");
4953
i_rulename = PQfnumber(res, "rulename");
4954
i_ruletable = PQfnumber(res, "ruletable");
4955
i_ev_type = PQfnumber(res, "ev_type");
4956
i_is_instead = PQfnumber(res, "is_instead");
4957
i_ev_enabled = PQfnumber(res, "ev_enabled");
4959
for (i = 0; i < ntups; i++)
4963
ruleinfo[i].dobj.objType = DO_RULE;
4964
ruleinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
4965
ruleinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
4966
AssignDumpId(&ruleinfo[i].dobj);
4967
ruleinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_rulename));
4968
ruletableoid = atooid(PQgetvalue(res, i, i_ruletable));
4969
ruleinfo[i].ruletable = findTableByOid(ruletableoid);
4970
if (ruleinfo[i].ruletable == NULL)
4972
write_msg(NULL, "failed sanity check, parent table OID %u of pg_rewrite entry OID %u not found\n",
4974
ruleinfo[i].dobj.catId.oid);
4977
ruleinfo[i].dobj.namespace = ruleinfo[i].ruletable->dobj.namespace;
4978
ruleinfo[i].dobj.dump = ruleinfo[i].ruletable->dobj.dump;
4979
ruleinfo[i].ev_type = *(PQgetvalue(res, i, i_ev_type));
4980
ruleinfo[i].is_instead = *(PQgetvalue(res, i, i_is_instead)) == 't';
4981
ruleinfo[i].ev_enabled = *(PQgetvalue(res, i, i_ev_enabled));
4982
if (ruleinfo[i].ruletable)
4985
* If the table is a view, force its ON SELECT rule to be sorted
4986
* before the view itself --- this ensures that any dependencies
4987
* for the rule affect the table's positioning. Other rules are
4988
* forced to appear after their table.
4990
if (ruleinfo[i].ruletable->relkind == RELKIND_VIEW &&
4991
ruleinfo[i].ev_type == '1' && ruleinfo[i].is_instead)
4993
addObjectDependency(&ruleinfo[i].ruletable->dobj,
4994
ruleinfo[i].dobj.dumpId);
4995
/* We'll merge the rule into CREATE VIEW, if possible */
4996
ruleinfo[i].separate = false;
5000
addObjectDependency(&ruleinfo[i].dobj,
5001
ruleinfo[i].ruletable->dobj.dumpId);
5002
ruleinfo[i].separate = true;
5006
ruleinfo[i].separate = true;
5011
destroyPQExpBuffer(query);
5018
* get information about every trigger on a dumpable table
5020
* Note: trigger data is not returned directly to the caller, but it
5021
* does get entered into the DumpableObject tables.
5024
getTriggers(TableInfo tblinfo[], int numTables)
5028
PQExpBuffer query = createPQExpBuffer();
5030
TriggerInfo *tginfo;
5048
for (i = 0; i < numTables; i++)
5050
TableInfo *tbinfo = &tblinfo[i];
5052
if (!tbinfo->hastriggers || !tbinfo->dobj.dump)
5056
write_msg(NULL, "reading triggers for table \"%s\"\n",
5060
* select table schema to ensure regproc name is qualified if needed
5062
selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
5064
resetPQExpBuffer(query);
5065
if (g_fout->remoteVersion >= 90000)
5068
* NB: think not to use pretty=true in pg_get_triggerdef. It
5069
* could result in non-forward-compatible dumps of WHEN clauses
5070
* due to under-parenthesization.
5072
appendPQExpBuffer(query,
5074
"tgfoid::pg_catalog.regproc AS tgfname, "
5075
"pg_catalog.pg_get_triggerdef(oid, false) AS tgdef, "
5076
"tgenabled, tableoid, oid "
5077
"FROM pg_catalog.pg_trigger t "
5078
"WHERE tgrelid = '%u'::pg_catalog.oid "
5079
"AND NOT tgisinternal",
5080
tbinfo->dobj.catId.oid);
5082
else if (g_fout->remoteVersion >= 80300)
5085
* We ignore triggers that are tied to a foreign-key constraint
5087
appendPQExpBuffer(query,
5089
"tgfoid::pg_catalog.regproc AS tgfname, "
5090
"tgtype, tgnargs, tgargs, tgenabled, "
5091
"tgisconstraint, tgconstrname, tgdeferrable, "
5092
"tgconstrrelid, tginitdeferred, tableoid, oid, "
5093
"tgconstrrelid::pg_catalog.regclass AS tgconstrrelname "
5094
"FROM pg_catalog.pg_trigger t "
5095
"WHERE tgrelid = '%u'::pg_catalog.oid "
5096
"AND tgconstraint = 0",
5097
tbinfo->dobj.catId.oid);
5099
else if (g_fout->remoteVersion >= 70300)
5102
* We ignore triggers that are tied to a foreign-key constraint,
5103
* but in these versions we have to grovel through pg_constraint
5106
appendPQExpBuffer(query,
5108
"tgfoid::pg_catalog.regproc AS tgfname, "
5109
"tgtype, tgnargs, tgargs, tgenabled, "
5110
"tgisconstraint, tgconstrname, tgdeferrable, "
5111
"tgconstrrelid, tginitdeferred, tableoid, oid, "
5112
"tgconstrrelid::pg_catalog.regclass AS tgconstrrelname "
5113
"FROM pg_catalog.pg_trigger t "
5114
"WHERE tgrelid = '%u'::pg_catalog.oid "
5115
"AND (NOT tgisconstraint "
5117
" (SELECT 1 FROM pg_catalog.pg_depend d "
5118
" JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
5119
" WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))",
5120
tbinfo->dobj.catId.oid);
5122
else if (g_fout->remoteVersion >= 70100)
5124
appendPQExpBuffer(query,
5125
"SELECT tgname, tgfoid::regproc AS tgfname, "
5126
"tgtype, tgnargs, tgargs, tgenabled, "
5127
"tgisconstraint, tgconstrname, tgdeferrable, "
5128
"tgconstrrelid, tginitdeferred, tableoid, oid, "
5129
"(SELECT relname FROM pg_class WHERE oid = tgconstrrelid) "
5130
" AS tgconstrrelname "
5132
"WHERE tgrelid = '%u'::oid",
5133
tbinfo->dobj.catId.oid);
5137
appendPQExpBuffer(query,
5138
"SELECT tgname, tgfoid::regproc AS tgfname, "
5139
"tgtype, tgnargs, tgargs, tgenabled, "
5140
"tgisconstraint, tgconstrname, tgdeferrable, "
5141
"tgconstrrelid, tginitdeferred, "
5142
"(SELECT oid FROM pg_class WHERE relname = 'pg_trigger') AS tableoid, "
5144
"(SELECT relname FROM pg_class WHERE oid = tgconstrrelid) "
5145
" AS tgconstrrelname "
5147
"WHERE tgrelid = '%u'::oid",
5148
tbinfo->dobj.catId.oid);
5150
res = PQexec(g_conn, query->data);
5151
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
5153
ntups = PQntuples(res);
5155
i_tableoid = PQfnumber(res, "tableoid");
5156
i_oid = PQfnumber(res, "oid");
5157
i_tgname = PQfnumber(res, "tgname");
5158
i_tgfname = PQfnumber(res, "tgfname");
5159
i_tgtype = PQfnumber(res, "tgtype");
5160
i_tgnargs = PQfnumber(res, "tgnargs");
5161
i_tgargs = PQfnumber(res, "tgargs");
5162
i_tgisconstraint = PQfnumber(res, "tgisconstraint");
5163
i_tgconstrname = PQfnumber(res, "tgconstrname");
5164
i_tgconstrrelid = PQfnumber(res, "tgconstrrelid");
5165
i_tgconstrrelname = PQfnumber(res, "tgconstrrelname");
5166
i_tgenabled = PQfnumber(res, "tgenabled");
5167
i_tgdeferrable = PQfnumber(res, "tgdeferrable");
5168
i_tginitdeferred = PQfnumber(res, "tginitdeferred");
5169
i_tgdef = PQfnumber(res, "tgdef");
5171
tginfo = (TriggerInfo *) malloc(ntups * sizeof(TriggerInfo));
5173
for (j = 0; j < ntups; j++)
5175
tginfo[j].dobj.objType = DO_TRIGGER;
5176
tginfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
5177
tginfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
5178
AssignDumpId(&tginfo[j].dobj);
5179
tginfo[j].dobj.name = strdup(PQgetvalue(res, j, i_tgname));
5180
tginfo[j].dobj.namespace = tbinfo->dobj.namespace;
5181
tginfo[j].tgtable = tbinfo;
5182
tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled));
5185
tginfo[j].tgdef = strdup(PQgetvalue(res, j, i_tgdef));
5187
/* remaining fields are not valid if we have tgdef */
5188
tginfo[j].tgfname = NULL;
5189
tginfo[j].tgtype = 0;
5190
tginfo[j].tgnargs = 0;
5191
tginfo[j].tgargs = NULL;
5192
tginfo[j].tgisconstraint = false;
5193
tginfo[j].tgdeferrable = false;
5194
tginfo[j].tginitdeferred = false;
5195
tginfo[j].tgconstrname = NULL;
5196
tginfo[j].tgconstrrelid = InvalidOid;
5197
tginfo[j].tgconstrrelname = NULL;
5201
tginfo[j].tgdef = NULL;
5203
tginfo[j].tgfname = strdup(PQgetvalue(res, j, i_tgfname));
5204
tginfo[j].tgtype = atoi(PQgetvalue(res, j, i_tgtype));
5205
tginfo[j].tgnargs = atoi(PQgetvalue(res, j, i_tgnargs));
5206
tginfo[j].tgargs = strdup(PQgetvalue(res, j, i_tgargs));
5207
tginfo[j].tgisconstraint = *(PQgetvalue(res, j, i_tgisconstraint)) == 't';
5208
tginfo[j].tgdeferrable = *(PQgetvalue(res, j, i_tgdeferrable)) == 't';
5209
tginfo[j].tginitdeferred = *(PQgetvalue(res, j, i_tginitdeferred)) == 't';
5211
if (tginfo[j].tgisconstraint)
5213
tginfo[j].tgconstrname = strdup(PQgetvalue(res, j, i_tgconstrname));
5214
tginfo[j].tgconstrrelid = atooid(PQgetvalue(res, j, i_tgconstrrelid));
5215
if (OidIsValid(tginfo[j].tgconstrrelid))
5217
if (PQgetisnull(res, j, i_tgconstrrelname))
5219
write_msg(NULL, "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)\n",
5220
tginfo[j].dobj.name, tbinfo->dobj.name,
5221
tginfo[j].tgconstrrelid);
5224
tginfo[j].tgconstrrelname = strdup(PQgetvalue(res, j, i_tgconstrrelname));
5227
tginfo[j].tgconstrrelname = NULL;
5231
tginfo[j].tgconstrname = NULL;
5232
tginfo[j].tgconstrrelid = InvalidOid;
5233
tginfo[j].tgconstrrelname = NULL;
5241
destroyPQExpBuffer(query);
5246
* get basic information about every procedural language in the system
5248
* numProcLangs is set to the number of langs read in
5250
* NB: this must run after getFuncs() because we assume we can do
5254
getProcLangs(int *numProcLangs)
5259
PQExpBuffer query = createPQExpBuffer();
5260
ProcLangInfo *planginfo;
5265
int i_lanplcallfoid;
5271
/* Make sure we are in proper schema */
5272
selectSourceSchema("pg_catalog");
5274
if (g_fout->remoteVersion >= 90000)
5276
/* pg_language has a laninline column */
5277
appendPQExpBuffer(query, "SELECT tableoid, oid, "
5278
"lanname, lanpltrusted, lanplcallfoid, "
5279
"laninline, lanvalidator, lanacl, "
5280
"(%s lanowner) AS lanowner "
5286
else if (g_fout->remoteVersion >= 80300)
5288
/* pg_language has a lanowner column */
5289
appendPQExpBuffer(query, "SELECT tableoid, oid, "
5290
"lanname, lanpltrusted, lanplcallfoid, "
5291
"lanvalidator, lanacl, "
5292
"(%s lanowner) AS lanowner "
5298
else if (g_fout->remoteVersion >= 80100)
5300
/* Languages are owned by the bootstrap superuser, OID 10 */
5301
appendPQExpBuffer(query, "SELECT tableoid, oid, *, "
5302
"(%s '10') AS lanowner "
5308
else if (g_fout->remoteVersion >= 70400)
5310
/* Languages are owned by the bootstrap superuser, sysid 1 */
5311
appendPQExpBuffer(query, "SELECT tableoid, oid, *, "
5312
"(%s '1') AS lanowner "
5318
else if (g_fout->remoteVersion >= 70100)
5320
/* No clear notion of an owner at all before 7.4 ... */
5321
appendPQExpBuffer(query, "SELECT tableoid, oid, * FROM pg_language "
5327
appendPQExpBuffer(query, "SELECT "
5328
"(SELECT oid FROM pg_class WHERE relname = 'pg_language') AS tableoid, "
5329
"oid, * FROM pg_language "
5334
res = PQexec(g_conn, query->data);
5335
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
5337
ntups = PQntuples(res);
5339
*numProcLangs = ntups;
5341
planginfo = (ProcLangInfo *) malloc(ntups * sizeof(ProcLangInfo));
5343
i_tableoid = PQfnumber(res, "tableoid");
5344
i_oid = PQfnumber(res, "oid");
5345
i_lanname = PQfnumber(res, "lanname");
5346
i_lanpltrusted = PQfnumber(res, "lanpltrusted");
5347
i_lanplcallfoid = PQfnumber(res, "lanplcallfoid");
5348
/* these may fail and return -1: */
5349
i_laninline = PQfnumber(res, "laninline");
5350
i_lanvalidator = PQfnumber(res, "lanvalidator");
5351
i_lanacl = PQfnumber(res, "lanacl");
5352
i_lanowner = PQfnumber(res, "lanowner");
5354
for (i = 0; i < ntups; i++)
5356
planginfo[i].dobj.objType = DO_PROCLANG;
5357
planginfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
5358
planginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
5359
AssignDumpId(&planginfo[i].dobj);
5361
planginfo[i].dobj.name = strdup(PQgetvalue(res, i, i_lanname));
5362
planginfo[i].lanpltrusted = *(PQgetvalue(res, i, i_lanpltrusted)) == 't';
5363
planginfo[i].lanplcallfoid = atooid(PQgetvalue(res, i, i_lanplcallfoid));
5364
if (i_laninline >= 0)
5365
planginfo[i].laninline = atooid(PQgetvalue(res, i, i_laninline));
5367
planginfo[i].laninline = InvalidOid;
5368
if (i_lanvalidator >= 0)
5369
planginfo[i].lanvalidator = atooid(PQgetvalue(res, i, i_lanvalidator));
5371
planginfo[i].lanvalidator = InvalidOid;
5373
planginfo[i].lanacl = strdup(PQgetvalue(res, i, i_lanacl));
5375
planginfo[i].lanacl = strdup("{=U}");
5376
if (i_lanowner >= 0)
5377
planginfo[i].lanowner = strdup(PQgetvalue(res, i, i_lanowner));
5379
planginfo[i].lanowner = strdup("");
5381
if (g_fout->remoteVersion < 70300)
5384
* We need to make a dependency to ensure the function will be
5385
* dumped first. (In 7.3 and later the regular dependency
5386
* mechanism will handle this for us.)
5388
FuncInfo *funcInfo = findFuncByOid(planginfo[i].lanplcallfoid);
5391
addObjectDependency(&planginfo[i].dobj,
5392
funcInfo->dobj.dumpId);
5398
destroyPQExpBuffer(query);
5405
* get basic information about every cast in the system
5407
* numCasts is set to the number of casts read in
5410
getCasts(int *numCasts)
5415
PQExpBuffer query = createPQExpBuffer();
5425
/* Make sure we are in proper schema */
5426
selectSourceSchema("pg_catalog");
5428
if (g_fout->remoteVersion >= 80400)
5430
appendPQExpBuffer(query, "SELECT tableoid, oid, "
5431
"castsource, casttarget, castfunc, castcontext, "
5433
"FROM pg_cast ORDER BY 3,4");
5435
else if (g_fout->remoteVersion >= 70300)
5437
appendPQExpBuffer(query, "SELECT tableoid, oid, "
5438
"castsource, casttarget, castfunc, castcontext, "
5439
"CASE WHEN castfunc = 0 THEN 'b' ELSE 'f' END AS castmethod "
5440
"FROM pg_cast ORDER BY 3,4");
5444
appendPQExpBuffer(query, "SELECT 0 AS tableoid, p.oid, "
5445
"t1.oid AS castsource, t2.oid AS casttarget, "
5446
"p.oid AS castfunc, 'e' AS castcontext, "
5447
"'f' AS castmethod "
5448
"FROM pg_type t1, pg_type t2, pg_proc p "
5449
"WHERE p.pronargs = 1 AND "
5450
"p.proargtypes[0] = t1.oid AND "
5451
"p.prorettype = t2.oid AND p.proname = t2.typname "
5455
res = PQexec(g_conn, query->data);
5456
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
5458
ntups = PQntuples(res);
5462
castinfo = (CastInfo *) malloc(ntups * sizeof(CastInfo));
5464
i_tableoid = PQfnumber(res, "tableoid");
5465
i_oid = PQfnumber(res, "oid");
5466
i_castsource = PQfnumber(res, "castsource");
5467
i_casttarget = PQfnumber(res, "casttarget");
5468
i_castfunc = PQfnumber(res, "castfunc");
5469
i_castcontext = PQfnumber(res, "castcontext");
5470
i_castmethod = PQfnumber(res, "castmethod");
5472
for (i = 0; i < ntups; i++)
5474
PQExpBufferData namebuf;
5475
TypeInfo *sTypeInfo;
5476
TypeInfo *tTypeInfo;
5478
castinfo[i].dobj.objType = DO_CAST;
5479
castinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
5480
castinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
5481
AssignDumpId(&castinfo[i].dobj);
5482
castinfo[i].castsource = atooid(PQgetvalue(res, i, i_castsource));
5483
castinfo[i].casttarget = atooid(PQgetvalue(res, i, i_casttarget));
5484
castinfo[i].castfunc = atooid(PQgetvalue(res, i, i_castfunc));
5485
castinfo[i].castcontext = *(PQgetvalue(res, i, i_castcontext));
5486
castinfo[i].castmethod = *(PQgetvalue(res, i, i_castmethod));
5489
* Try to name cast as concatenation of typnames. This is only used
5490
* for purposes of sorting. If we fail to find either type, the name
5491
* will be an empty string.
5493
initPQExpBuffer(&namebuf);
5494
sTypeInfo = findTypeByOid(castinfo[i].castsource);
5495
tTypeInfo = findTypeByOid(castinfo[i].casttarget);
5496
if (sTypeInfo && tTypeInfo)
5497
appendPQExpBuffer(&namebuf, "%s %s",
5498
sTypeInfo->dobj.name, tTypeInfo->dobj.name);
5499
castinfo[i].dobj.name = namebuf.data;
5501
if (OidIsValid(castinfo[i].castfunc))
5504
* We need to make a dependency to ensure the function will be
5505
* dumped first. (In 7.3 and later the regular dependency
5506
* mechanism will handle this for us.)
5510
funcInfo = findFuncByOid(castinfo[i].castfunc);
5512
addObjectDependency(&castinfo[i].dobj,
5513
funcInfo->dobj.dumpId);
5519
destroyPQExpBuffer(query);
5526
* for each interesting table, read info about its attributes
5527
* (names, types, default values, CHECK constraints, etc)
5529
* This is implemented in a very inefficient way right now, looping
5530
* through the tblinfo and doing a join per table to find the attrs and their
5531
* types. However, because we want type names and so forth to be named
5532
* relative to the schema of each table, we couldn't do it in just one
5533
* query. (Maybe one query per schema?)
5538
getTableAttrs(TableInfo *tblinfo, int numTables)
5542
PQExpBuffer q = createPQExpBuffer();
5547
int i_attstattarget;
5562
for (i = 0; i < numTables; i++)
5564
TableInfo *tbinfo = &tblinfo[i];
5566
/* Don't bother to collect info for sequences */
5567
if (tbinfo->relkind == RELKIND_SEQUENCE)
5570
/* Don't bother with uninteresting tables, either */
5571
if (!tbinfo->interesting)
5575
* Make sure we are in proper schema for this table; this allows
5576
* correct retrieval of formatted type names and default exprs
5578
selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
5580
/* find all the user attributes and their types */
5583
* we must read the attribute names in attribute number order! because
5584
* we will use the attnum to index into the attnames array later. We
5585
* actually ask to order by "attrelid, attnum" because (at least up to
5586
* 7.3) the planner is not smart enough to realize it needn't re-sort
5587
* the output of an indexscan on pg_attribute_relid_attnum_index.
5590
write_msg(NULL, "finding the columns and types of table \"%s\"\n",
5593
resetPQExpBuffer(q);
5595
if (g_fout->remoteVersion >= 90100)
5598
* attcollation is new in 9.1. Since we only want to dump COLLATE
5599
* clauses for attributes whose collation is different from their
5600
* type's default, we use a CASE here to suppress uninteresting
5601
* attcollations cheaply.
5603
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
5604
"a.attstattarget, a.attstorage, t.typstorage, "
5605
"a.attnotnull, a.atthasdef, a.attisdropped, "
5606
"a.attlen, a.attalign, a.attislocal, "
5607
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
5608
"array_to_string(a.attoptions, ', ') AS attoptions, "
5609
"CASE WHEN a.attcollation <> t.typcollation "
5610
"THEN a.attcollation ELSE 0 END AS attcollation "
5611
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
5612
"ON a.atttypid = t.oid "
5613
"WHERE a.attrelid = '%u'::pg_catalog.oid "
5614
"AND a.attnum > 0::pg_catalog.int2 "
5615
"ORDER BY a.attrelid, a.attnum",
5616
tbinfo->dobj.catId.oid);
5618
else if (g_fout->remoteVersion >= 90000)
5620
/* attoptions is new in 9.0 */
5621
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
5622
"a.attstattarget, a.attstorage, t.typstorage, "
5623
"a.attnotnull, a.atthasdef, a.attisdropped, "
5624
"a.attlen, a.attalign, a.attislocal, "
5625
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
5626
"array_to_string(a.attoptions, ', ') AS attoptions, "
5627
"0 AS attcollation "
5628
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
5629
"ON a.atttypid = t.oid "
5630
"WHERE a.attrelid = '%u'::pg_catalog.oid "
5631
"AND a.attnum > 0::pg_catalog.int2 "
5632
"ORDER BY a.attrelid, a.attnum",
5633
tbinfo->dobj.catId.oid);
5635
else if (g_fout->remoteVersion >= 70300)
5637
/* need left join here to not fail on dropped columns ... */
5638
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
5639
"a.attstattarget, a.attstorage, t.typstorage, "
5640
"a.attnotnull, a.atthasdef, a.attisdropped, "
5641
"a.attlen, a.attalign, a.attislocal, "
5642
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
5643
"'' AS attoptions, 0 AS attcollation "
5644
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
5645
"ON a.atttypid = t.oid "
5646
"WHERE a.attrelid = '%u'::pg_catalog.oid "
5647
"AND a.attnum > 0::pg_catalog.int2 "
5648
"ORDER BY a.attrelid, a.attnum",
5649
tbinfo->dobj.catId.oid);
5651
else if (g_fout->remoteVersion >= 70100)
5654
* attstattarget doesn't exist in 7.1. It does exist in 7.2, but
5655
* we don't dump it because we can't tell whether it's been
5656
* explicitly set or was just a default.
5658
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
5659
"-1 AS attstattarget, a.attstorage, "
5660
"t.typstorage, a.attnotnull, a.atthasdef, "
5661
"false AS attisdropped, a.attlen, "
5662
"a.attalign, false AS attislocal, "
5663
"format_type(t.oid,a.atttypmod) AS atttypname, "
5664
"'' AS attoptions, 0 AS attcollation "
5665
"FROM pg_attribute a LEFT JOIN pg_type t "
5666
"ON a.atttypid = t.oid "
5667
"WHERE a.attrelid = '%u'::oid "
5668
"AND a.attnum > 0::int2 "
5669
"ORDER BY a.attrelid, a.attnum",
5670
tbinfo->dobj.catId.oid);
5674
/* format_type not available before 7.1 */
5675
appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, "
5676
"-1 AS attstattarget, "
5677
"attstorage, attstorage AS typstorage, "
5678
"attnotnull, atthasdef, false AS attisdropped, "
5679
"attlen, attalign, "
5680
"false AS attislocal, "
5681
"(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname, "
5682
"'' AS attoptions, 0 AS attcollation "
5683
"FROM pg_attribute a "
5684
"WHERE attrelid = '%u'::oid "
5685
"AND attnum > 0::int2 "
5686
"ORDER BY attrelid, attnum",
5687
tbinfo->dobj.catId.oid);
5690
res = PQexec(g_conn, q->data);
5691
check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
5693
ntups = PQntuples(res);
5695
i_attnum = PQfnumber(res, "attnum");
5696
i_attname = PQfnumber(res, "attname");
5697
i_atttypname = PQfnumber(res, "atttypname");
5698
i_atttypmod = PQfnumber(res, "atttypmod");
5699
i_attstattarget = PQfnumber(res, "attstattarget");
5700
i_attstorage = PQfnumber(res, "attstorage");
5701
i_typstorage = PQfnumber(res, "typstorage");
5702
i_attnotnull = PQfnumber(res, "attnotnull");
5703
i_atthasdef = PQfnumber(res, "atthasdef");
5704
i_attisdropped = PQfnumber(res, "attisdropped");
5705
i_attlen = PQfnumber(res, "attlen");
5706
i_attalign = PQfnumber(res, "attalign");
5707
i_attislocal = PQfnumber(res, "attislocal");
5708
i_attoptions = PQfnumber(res, "attoptions");
5709
i_attcollation = PQfnumber(res, "attcollation");
5711
tbinfo->numatts = ntups;
5712
tbinfo->attnames = (char **) malloc(ntups * sizeof(char *));
5713
tbinfo->atttypnames = (char **) malloc(ntups * sizeof(char *));
5714
tbinfo->atttypmod = (int *) malloc(ntups * sizeof(int));
5715
tbinfo->attstattarget = (int *) malloc(ntups * sizeof(int));
5716
tbinfo->attstorage = (char *) malloc(ntups * sizeof(char));
5717
tbinfo->typstorage = (char *) malloc(ntups * sizeof(char));
5718
tbinfo->attisdropped = (bool *) malloc(ntups * sizeof(bool));
5719
tbinfo->attlen = (int *) malloc(ntups * sizeof(int));
5720
tbinfo->attalign = (char *) malloc(ntups * sizeof(char));
5721
tbinfo->attislocal = (bool *) malloc(ntups * sizeof(bool));
5722
tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool));
5723
tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
5724
tbinfo->attoptions = (char **) malloc(ntups * sizeof(char *));
5725
tbinfo->attcollation = (Oid *) malloc(ntups * sizeof(Oid));
5726
tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
5727
tbinfo->inhAttrDef = (bool *) malloc(ntups * sizeof(bool));
5728
tbinfo->inhNotNull = (bool *) malloc(ntups * sizeof(bool));
5729
hasdefaults = false;
5731
for (j = 0; j < ntups; j++)
5733
if (j + 1 != atoi(PQgetvalue(res, j, i_attnum)))
5735
write_msg(NULL, "invalid column numbering in table \"%s\"\n",
5739
tbinfo->attnames[j] = strdup(PQgetvalue(res, j, i_attname));
5740
tbinfo->atttypnames[j] = strdup(PQgetvalue(res, j, i_atttypname));
5741
tbinfo->atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod));
5742
tbinfo->attstattarget[j] = atoi(PQgetvalue(res, j, i_attstattarget));
5743
tbinfo->attstorage[j] = *(PQgetvalue(res, j, i_attstorage));
5744
tbinfo->typstorage[j] = *(PQgetvalue(res, j, i_typstorage));
5745
tbinfo->attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't');
5746
tbinfo->attlen[j] = atoi(PQgetvalue(res, j, i_attlen));
5747
tbinfo->attalign[j] = *(PQgetvalue(res, j, i_attalign));
5748
tbinfo->attislocal[j] = (PQgetvalue(res, j, i_attislocal)[0] == 't');
5749
tbinfo->notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
5750
tbinfo->attoptions[j] = strdup(PQgetvalue(res, j, i_attoptions));
5751
tbinfo->attcollation[j] = atooid(PQgetvalue(res, j, i_attcollation));
5752
tbinfo->attrdefs[j] = NULL; /* fix below */
5753
if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
5755
/* these flags will be set in flagInhAttrs() */
5756
tbinfo->inhAttrs[j] = false;
5757
tbinfo->inhAttrDef[j] = false;
5758
tbinfo->inhNotNull[j] = false;
5764
* Get info about column defaults
5768
AttrDefInfo *attrdefs;
5772
write_msg(NULL, "finding default expressions of table \"%s\"\n",
5775
resetPQExpBuffer(q);
5776
if (g_fout->remoteVersion >= 70300)
5778
appendPQExpBuffer(q, "SELECT tableoid, oid, adnum, "
5779
"pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
5780
"FROM pg_catalog.pg_attrdef "
5781
"WHERE adrelid = '%u'::pg_catalog.oid",
5782
tbinfo->dobj.catId.oid);
5784
else if (g_fout->remoteVersion >= 70200)
5786
/* 7.2 did not have OIDs in pg_attrdef */
5787
appendPQExpBuffer(q, "SELECT tableoid, 0 AS oid, adnum, "
5788
"pg_get_expr(adbin, adrelid) AS adsrc "
5790
"WHERE adrelid = '%u'::oid",
5791
tbinfo->dobj.catId.oid);
5793
else if (g_fout->remoteVersion >= 70100)
5795
/* no pg_get_expr, so must rely on adsrc */
5796
appendPQExpBuffer(q, "SELECT tableoid, oid, adnum, adsrc "
5798
"WHERE adrelid = '%u'::oid",
5799
tbinfo->dobj.catId.oid);
5803
/* no pg_get_expr, no tableoid either */
5804
appendPQExpBuffer(q, "SELECT "
5805
"(SELECT oid FROM pg_class WHERE relname = 'pg_attrdef') AS tableoid, "
5806
"oid, adnum, adsrc "
5808
"WHERE adrelid = '%u'::oid",
5809
tbinfo->dobj.catId.oid);
5811
res = PQexec(g_conn, q->data);
5812
check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
5814
numDefaults = PQntuples(res);
5815
attrdefs = (AttrDefInfo *) malloc(numDefaults * sizeof(AttrDefInfo));
5817
for (j = 0; j < numDefaults; j++)
5821
attrdefs[j].dobj.objType = DO_ATTRDEF;
5822
attrdefs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
5823
attrdefs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
5824
AssignDumpId(&attrdefs[j].dobj);
5825
attrdefs[j].adtable = tbinfo;
5826
attrdefs[j].adnum = adnum = atoi(PQgetvalue(res, j, 2));
5827
attrdefs[j].adef_expr = strdup(PQgetvalue(res, j, 3));
5829
attrdefs[j].dobj.name = strdup(tbinfo->dobj.name);
5830
attrdefs[j].dobj.namespace = tbinfo->dobj.namespace;
5832
attrdefs[j].dobj.dump = tbinfo->dobj.dump;
5835
* Defaults on a VIEW must always be dumped as separate ALTER
5836
* TABLE commands. Defaults on regular tables are dumped as
5837
* part of the CREATE TABLE if possible. To check if it's
5838
* safe, we mark the default as needing to appear before the
5841
if (tbinfo->relkind == RELKIND_VIEW)
5843
attrdefs[j].separate = true;
5844
/* needed in case pre-7.3 DB: */
5845
addObjectDependency(&attrdefs[j].dobj,
5846
tbinfo->dobj.dumpId);
5850
attrdefs[j].separate = false;
5851
addObjectDependency(&tbinfo->dobj,
5852
attrdefs[j].dobj.dumpId);
5855
if (adnum <= 0 || adnum > ntups)
5857
write_msg(NULL, "invalid adnum value %d for table \"%s\"\n",
5858
adnum, tbinfo->dobj.name);
5861
tbinfo->attrdefs[adnum - 1] = &attrdefs[j];
5867
* Get info about table CHECK constraints
5869
if (tbinfo->ncheck > 0)
5871
ConstraintInfo *constrs;
5875
write_msg(NULL, "finding check constraints for table \"%s\"\n",
5878
resetPQExpBuffer(q);
5879
if (g_fout->remoteVersion >= 80400)
5881
appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
5882
"pg_catalog.pg_get_constraintdef(oid) AS consrc, "
5884
"FROM pg_catalog.pg_constraint "
5885
"WHERE conrelid = '%u'::pg_catalog.oid "
5886
" AND contype = 'c' "
5888
tbinfo->dobj.catId.oid);
5890
else if (g_fout->remoteVersion >= 70400)
5892
appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
5893
"pg_catalog.pg_get_constraintdef(oid) AS consrc, "
5894
"true AS conislocal "
5895
"FROM pg_catalog.pg_constraint "
5896
"WHERE conrelid = '%u'::pg_catalog.oid "
5897
" AND contype = 'c' "
5899
tbinfo->dobj.catId.oid);
5901
else if (g_fout->remoteVersion >= 70300)
5903
/* no pg_get_constraintdef, must use consrc */
5904
appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
5905
"'CHECK (' || consrc || ')' AS consrc, "
5906
"true AS conislocal "
5907
"FROM pg_catalog.pg_constraint "
5908
"WHERE conrelid = '%u'::pg_catalog.oid "
5909
" AND contype = 'c' "
5911
tbinfo->dobj.catId.oid);
5913
else if (g_fout->remoteVersion >= 70200)
5915
/* 7.2 did not have OIDs in pg_relcheck */
5916
appendPQExpBuffer(q, "SELECT tableoid, 0 AS oid, "
5917
"rcname AS conname, "
5918
"'CHECK (' || rcsrc || ')' AS consrc, "
5919
"true AS conislocal "
5921
"WHERE rcrelid = '%u'::oid "
5923
tbinfo->dobj.catId.oid);
5925
else if (g_fout->remoteVersion >= 70100)
5927
appendPQExpBuffer(q, "SELECT tableoid, oid, "
5928
"rcname AS conname, "
5929
"'CHECK (' || rcsrc || ')' AS consrc, "
5930
"true AS conislocal "
5932
"WHERE rcrelid = '%u'::oid "
5934
tbinfo->dobj.catId.oid);
5938
/* no tableoid in 7.0 */
5939
appendPQExpBuffer(q, "SELECT "
5940
"(SELECT oid FROM pg_class WHERE relname = 'pg_relcheck') AS tableoid, "
5941
"oid, rcname AS conname, "
5942
"'CHECK (' || rcsrc || ')' AS consrc, "
5943
"true AS conislocal "
5945
"WHERE rcrelid = '%u'::oid "
5947
tbinfo->dobj.catId.oid);
5949
res = PQexec(g_conn, q->data);
5950
check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
5952
numConstrs = PQntuples(res);
5953
if (numConstrs != tbinfo->ncheck)
5955
write_msg(NULL, ngettext("expected %d check constraint on table \"%s\" but found %d\n",
5956
"expected %d check constraints on table \"%s\" but found %d\n",
5958
tbinfo->ncheck, tbinfo->dobj.name, numConstrs);
5959
write_msg(NULL, "(The system catalogs might be corrupted.)\n");
5963
constrs = (ConstraintInfo *) malloc(numConstrs * sizeof(ConstraintInfo));
5964
tbinfo->checkexprs = constrs;
5966
for (j = 0; j < numConstrs; j++)
5968
constrs[j].dobj.objType = DO_CONSTRAINT;
5969
constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
5970
constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
5971
AssignDumpId(&constrs[j].dobj);
5972
constrs[j].dobj.name = strdup(PQgetvalue(res, j, 2));
5973
constrs[j].dobj.namespace = tbinfo->dobj.namespace;
5974
constrs[j].contable = tbinfo;
5975
constrs[j].condomain = NULL;
5976
constrs[j].contype = 'c';
5977
constrs[j].condef = strdup(PQgetvalue(res, j, 3));
5978
constrs[j].confrelid = InvalidOid;
5979
constrs[j].conindex = 0;
5980
constrs[j].condeferrable = false;
5981
constrs[j].condeferred = false;
5982
constrs[j].conislocal = (PQgetvalue(res, j, 4)[0] == 't');
5983
constrs[j].separate = false;
5985
constrs[j].dobj.dump = tbinfo->dobj.dump;
5988
* Mark the constraint as needing to appear before the table
5989
* --- this is so that any other dependencies of the
5990
* constraint will be emitted before we try to create the
5993
addObjectDependency(&tbinfo->dobj,
5994
constrs[j].dobj.dumpId);
5997
* If the constraint is inherited, this will be detected later
5998
* (in pre-8.4 databases). We also detect later if the
5999
* constraint must be split out from the table definition.
6006
destroyPQExpBuffer(q);
6012
* read all text search parsers in the system catalogs and return them
6013
* in the TSParserInfo* structure
6015
* numTSParsers is set to the number of parsers read in
6018
getTSParsers(int *numTSParsers)
6023
PQExpBuffer query = createPQExpBuffer();
6024
TSParserInfo *prsinfo;
6035
/* Before 8.3, there is no built-in text search support */
6036
if (g_fout->remoteVersion < 80300)
6043
* find all text search objects, including builtin ones; we filter out
6044
* system-defined objects at dump-out time.
6047
/* Make sure we are in proper schema */
6048
selectSourceSchema("pg_catalog");
6050
appendPQExpBuffer(query, "SELECT tableoid, oid, prsname, prsnamespace, "
6051
"prsstart::oid, prstoken::oid, "
6052
"prsend::oid, prsheadline::oid, prslextype::oid "
6053
"FROM pg_ts_parser");
6055
res = PQexec(g_conn, query->data);
6056
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6058
ntups = PQntuples(res);
6059
*numTSParsers = ntups;
6061
prsinfo = (TSParserInfo *) malloc(ntups * sizeof(TSParserInfo));
6063
i_tableoid = PQfnumber(res, "tableoid");
6064
i_oid = PQfnumber(res, "oid");
6065
i_prsname = PQfnumber(res, "prsname");
6066
i_prsnamespace = PQfnumber(res, "prsnamespace");
6067
i_prsstart = PQfnumber(res, "prsstart");
6068
i_prstoken = PQfnumber(res, "prstoken");
6069
i_prsend = PQfnumber(res, "prsend");
6070
i_prsheadline = PQfnumber(res, "prsheadline");
6071
i_prslextype = PQfnumber(res, "prslextype");
6073
for (i = 0; i < ntups; i++)
6075
prsinfo[i].dobj.objType = DO_TSPARSER;
6076
prsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
6077
prsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
6078
AssignDumpId(&prsinfo[i].dobj);
6079
prsinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_prsname));
6080
prsinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_prsnamespace)),
6081
prsinfo[i].dobj.catId.oid);
6082
prsinfo[i].prsstart = atooid(PQgetvalue(res, i, i_prsstart));
6083
prsinfo[i].prstoken = atooid(PQgetvalue(res, i, i_prstoken));
6084
prsinfo[i].prsend = atooid(PQgetvalue(res, i, i_prsend));
6085
prsinfo[i].prsheadline = atooid(PQgetvalue(res, i, i_prsheadline));
6086
prsinfo[i].prslextype = atooid(PQgetvalue(res, i, i_prslextype));
6088
/* Decide whether we want to dump it */
6089
selectDumpableObject(&(prsinfo[i].dobj));
6094
destroyPQExpBuffer(query);
6100
* getTSDictionaries:
6101
* read all text search dictionaries in the system catalogs and return them
6102
* in the TSDictInfo* structure
6104
* numTSDicts is set to the number of dictionaries read in
6107
getTSDictionaries(int *numTSDicts)
6112
PQExpBuffer query = createPQExpBuffer();
6113
TSDictInfo *dictinfo;
6117
int i_dictnamespace;
6120
int i_dictinitoption;
6122
/* Before 8.3, there is no built-in text search support */
6123
if (g_fout->remoteVersion < 80300)
6129
/* Make sure we are in proper schema */
6130
selectSourceSchema("pg_catalog");
6132
appendPQExpBuffer(query, "SELECT tableoid, oid, dictname, "
6133
"dictnamespace, (%s dictowner) AS rolname, "
6134
"dicttemplate, dictinitoption "
6138
res = PQexec(g_conn, query->data);
6139
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6141
ntups = PQntuples(res);
6142
*numTSDicts = ntups;
6144
dictinfo = (TSDictInfo *) malloc(ntups * sizeof(TSDictInfo));
6146
i_tableoid = PQfnumber(res, "tableoid");
6147
i_oid = PQfnumber(res, "oid");
6148
i_dictname = PQfnumber(res, "dictname");
6149
i_dictnamespace = PQfnumber(res, "dictnamespace");
6150
i_rolname = PQfnumber(res, "rolname");
6151
i_dictinitoption = PQfnumber(res, "dictinitoption");
6152
i_dicttemplate = PQfnumber(res, "dicttemplate");
6154
for (i = 0; i < ntups; i++)
6156
dictinfo[i].dobj.objType = DO_TSDICT;
6157
dictinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
6158
dictinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
6159
AssignDumpId(&dictinfo[i].dobj);
6160
dictinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_dictname));
6161
dictinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_dictnamespace)),
6162
dictinfo[i].dobj.catId.oid);
6163
dictinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
6164
dictinfo[i].dicttemplate = atooid(PQgetvalue(res, i, i_dicttemplate));
6165
if (PQgetisnull(res, i, i_dictinitoption))
6166
dictinfo[i].dictinitoption = NULL;
6168
dictinfo[i].dictinitoption = strdup(PQgetvalue(res, i, i_dictinitoption));
6170
/* Decide whether we want to dump it */
6171
selectDumpableObject(&(dictinfo[i].dobj));
6176
destroyPQExpBuffer(query);
6183
* read all text search templates in the system catalogs and return them
6184
* in the TSTemplateInfo* structure
6186
* numTSTemplates is set to the number of templates read in
6189
getTSTemplates(int *numTSTemplates)
6194
PQExpBuffer query = createPQExpBuffer();
6195
TSTemplateInfo *tmplinfo;
6199
int i_tmplnamespace;
6203
/* Before 8.3, there is no built-in text search support */
6204
if (g_fout->remoteVersion < 80300)
6206
*numTSTemplates = 0;
6210
/* Make sure we are in proper schema */
6211
selectSourceSchema("pg_catalog");
6213
appendPQExpBuffer(query, "SELECT tableoid, oid, tmplname, "
6214
"tmplnamespace, tmplinit::oid, tmpllexize::oid "
6215
"FROM pg_ts_template");
6217
res = PQexec(g_conn, query->data);
6218
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6220
ntups = PQntuples(res);
6221
*numTSTemplates = ntups;
6223
tmplinfo = (TSTemplateInfo *) malloc(ntups * sizeof(TSTemplateInfo));
6225
i_tableoid = PQfnumber(res, "tableoid");
6226
i_oid = PQfnumber(res, "oid");
6227
i_tmplname = PQfnumber(res, "tmplname");
6228
i_tmplnamespace = PQfnumber(res, "tmplnamespace");
6229
i_tmplinit = PQfnumber(res, "tmplinit");
6230
i_tmpllexize = PQfnumber(res, "tmpllexize");
6232
for (i = 0; i < ntups; i++)
6234
tmplinfo[i].dobj.objType = DO_TSTEMPLATE;
6235
tmplinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
6236
tmplinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
6237
AssignDumpId(&tmplinfo[i].dobj);
6238
tmplinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_tmplname));
6239
tmplinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_tmplnamespace)),
6240
tmplinfo[i].dobj.catId.oid);
6241
tmplinfo[i].tmplinit = atooid(PQgetvalue(res, i, i_tmplinit));
6242
tmplinfo[i].tmpllexize = atooid(PQgetvalue(res, i, i_tmpllexize));
6244
/* Decide whether we want to dump it */
6245
selectDumpableObject(&(tmplinfo[i].dobj));
6250
destroyPQExpBuffer(query);
6256
* getTSConfigurations:
6257
* read all text search configurations in the system catalogs and return
6258
* them in the TSConfigInfo* structure
6260
* numTSConfigs is set to the number of configurations read in
6263
getTSConfigurations(int *numTSConfigs)
6268
PQExpBuffer query = createPQExpBuffer();
6269
TSConfigInfo *cfginfo;
6277
/* Before 8.3, there is no built-in text search support */
6278
if (g_fout->remoteVersion < 80300)
6284
/* Make sure we are in proper schema */
6285
selectSourceSchema("pg_catalog");
6287
appendPQExpBuffer(query, "SELECT tableoid, oid, cfgname, "
6288
"cfgnamespace, (%s cfgowner) AS rolname, cfgparser "
6289
"FROM pg_ts_config",
6292
res = PQexec(g_conn, query->data);
6293
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6295
ntups = PQntuples(res);
6296
*numTSConfigs = ntups;
6298
cfginfo = (TSConfigInfo *) malloc(ntups * sizeof(TSConfigInfo));
6300
i_tableoid = PQfnumber(res, "tableoid");
6301
i_oid = PQfnumber(res, "oid");
6302
i_cfgname = PQfnumber(res, "cfgname");
6303
i_cfgnamespace = PQfnumber(res, "cfgnamespace");
6304
i_rolname = PQfnumber(res, "rolname");
6305
i_cfgparser = PQfnumber(res, "cfgparser");
6307
for (i = 0; i < ntups; i++)
6309
cfginfo[i].dobj.objType = DO_TSCONFIG;
6310
cfginfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
6311
cfginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
6312
AssignDumpId(&cfginfo[i].dobj);
6313
cfginfo[i].dobj.name = strdup(PQgetvalue(res, i, i_cfgname));
6314
cfginfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_cfgnamespace)),
6315
cfginfo[i].dobj.catId.oid);
6316
cfginfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
6317
cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));
6319
/* Decide whether we want to dump it */
6320
selectDumpableObject(&(cfginfo[i].dobj));
6325
destroyPQExpBuffer(query);
6331
* getForeignDataWrappers:
6332
* read all foreign-data wrappers in the system catalogs and return
6333
* them in the FdwInfo* structure
6335
* numForeignDataWrappers is set to the number of fdws read in
6338
getForeignDataWrappers(int *numForeignDataWrappers)
6343
PQExpBuffer query = createPQExpBuffer();
6354
/* Before 8.4, there are no foreign-data wrappers */
6355
if (g_fout->remoteVersion < 80400)
6357
*numForeignDataWrappers = 0;
6361
/* Make sure we are in proper schema */
6362
selectSourceSchema("pg_catalog");
6364
if (g_fout->remoteVersion >= 90100)
6366
appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
6367
"(%s fdwowner) AS rolname, "
6368
"fdwhandler::pg_catalog.regproc, "
6369
"fdwvalidator::pg_catalog.regproc, fdwacl, "
6370
"array_to_string(ARRAY("
6371
" SELECT option_name || ' ' || quote_literal(option_value) "
6372
" FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
6373
"FROM pg_foreign_data_wrapper",
6378
appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
6379
"(%s fdwowner) AS rolname, "
6380
"'-' AS fdwhandler, "
6381
"fdwvalidator::pg_catalog.regproc, fdwacl, "
6382
"array_to_string(ARRAY("
6383
" SELECT option_name || ' ' || quote_literal(option_value) "
6384
" FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
6385
"FROM pg_foreign_data_wrapper",
6389
res = PQexec(g_conn, query->data);
6390
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6392
ntups = PQntuples(res);
6393
*numForeignDataWrappers = ntups;
6395
fdwinfo = (FdwInfo *) malloc(ntups * sizeof(FdwInfo));
6397
i_tableoid = PQfnumber(res, "tableoid");
6398
i_oid = PQfnumber(res, "oid");
6399
i_fdwname = PQfnumber(res, "fdwname");
6400
i_rolname = PQfnumber(res, "rolname");
6401
i_fdwhandler = PQfnumber(res, "fdwhandler");
6402
i_fdwvalidator = PQfnumber(res, "fdwvalidator");
6403
i_fdwacl = PQfnumber(res, "fdwacl");
6404
i_fdwoptions = PQfnumber(res, "fdwoptions");
6406
for (i = 0; i < ntups; i++)
6408
fdwinfo[i].dobj.objType = DO_FDW;
6409
fdwinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
6410
fdwinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
6411
AssignDumpId(&fdwinfo[i].dobj);
6412
fdwinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_fdwname));
6413
fdwinfo[i].dobj.namespace = NULL;
6414
fdwinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
6415
fdwinfo[i].fdwhandler = strdup(PQgetvalue(res, i, i_fdwhandler));
6416
fdwinfo[i].fdwvalidator = strdup(PQgetvalue(res, i, i_fdwvalidator));
6417
fdwinfo[i].fdwoptions = strdup(PQgetvalue(res, i, i_fdwoptions));
6418
fdwinfo[i].fdwacl = strdup(PQgetvalue(res, i, i_fdwacl));
6420
/* Decide whether we want to dump it */
6421
selectDumpableObject(&(fdwinfo[i].dobj));
6426
destroyPQExpBuffer(query);
6432
* getForeignServers:
6433
* read all foreign servers in the system catalogs and return
6434
* them in the ForeignServerInfo * structure
6436
* numForeignServers is set to the number of servers read in
6439
getForeignServers(int *numForeignServers)
6444
PQExpBuffer query = createPQExpBuffer();
6445
ForeignServerInfo *srvinfo;
6456
/* Before 8.4, there are no foreign servers */
6457
if (g_fout->remoteVersion < 80400)
6459
*numForeignServers = 0;
6463
/* Make sure we are in proper schema */
6464
selectSourceSchema("pg_catalog");
6466
appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, "
6467
"(%s srvowner) AS rolname, "
6468
"srvfdw, srvtype, srvversion, srvacl,"
6469
"array_to_string(ARRAY("
6470
" SELECT option_name || ' ' || quote_literal(option_value) "
6471
" FROM pg_options_to_table(srvoptions)), ', ') AS srvoptions "
6472
"FROM pg_foreign_server",
6475
res = PQexec(g_conn, query->data);
6476
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6478
ntups = PQntuples(res);
6479
*numForeignServers = ntups;
6481
srvinfo = (ForeignServerInfo *) malloc(ntups * sizeof(ForeignServerInfo));
6483
i_tableoid = PQfnumber(res, "tableoid");
6484
i_oid = PQfnumber(res, "oid");
6485
i_srvname = PQfnumber(res, "srvname");
6486
i_rolname = PQfnumber(res, "rolname");
6487
i_srvfdw = PQfnumber(res, "srvfdw");
6488
i_srvtype = PQfnumber(res, "srvtype");
6489
i_srvversion = PQfnumber(res, "srvversion");
6490
i_srvacl = PQfnumber(res, "srvacl");
6491
i_srvoptions = PQfnumber(res, "srvoptions");
6493
for (i = 0; i < ntups; i++)
6495
srvinfo[i].dobj.objType = DO_FOREIGN_SERVER;
6496
srvinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
6497
srvinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
6498
AssignDumpId(&srvinfo[i].dobj);
6499
srvinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_srvname));
6500
srvinfo[i].dobj.namespace = NULL;
6501
srvinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
6502
srvinfo[i].srvfdw = atooid(PQgetvalue(res, i, i_srvfdw));
6503
srvinfo[i].srvtype = strdup(PQgetvalue(res, i, i_srvtype));
6504
srvinfo[i].srvversion = strdup(PQgetvalue(res, i, i_srvversion));
6505
srvinfo[i].srvoptions = strdup(PQgetvalue(res, i, i_srvoptions));
6506
srvinfo[i].srvacl = strdup(PQgetvalue(res, i, i_srvacl));
6508
/* Decide whether we want to dump it */
6509
selectDumpableObject(&(srvinfo[i].dobj));
6514
destroyPQExpBuffer(query);
6521
* read all default ACL information in the system catalogs and return
6522
* them in the DefaultACLInfo structure
6524
* numDefaultACLs is set to the number of ACLs read in
6527
getDefaultACLs(int *numDefaultACLs)
6529
DefaultACLInfo *daclinfo;
6535
int i_defaclnamespace;
6536
int i_defaclobjtype;
6541
if (g_fout->remoteVersion < 90000)
6543
*numDefaultACLs = 0;
6547
query = createPQExpBuffer();
6549
/* Make sure we are in proper schema */
6550
selectSourceSchema("pg_catalog");
6552
appendPQExpBuffer(query, "SELECT oid, tableoid, "
6553
"(%s defaclrole) AS defaclrole, "
6557
"FROM pg_default_acl",
6560
res = PQexec(g_conn, query->data);
6561
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6563
ntups = PQntuples(res);
6564
*numDefaultACLs = ntups;
6566
daclinfo = (DefaultACLInfo *) malloc(ntups * sizeof(DefaultACLInfo));
6568
i_oid = PQfnumber(res, "oid");
6569
i_tableoid = PQfnumber(res, "tableoid");
6570
i_defaclrole = PQfnumber(res, "defaclrole");
6571
i_defaclnamespace = PQfnumber(res, "defaclnamespace");
6572
i_defaclobjtype = PQfnumber(res, "defaclobjtype");
6573
i_defaclacl = PQfnumber(res, "defaclacl");
6575
for (i = 0; i < ntups; i++)
6577
Oid nspid = atooid(PQgetvalue(res, i, i_defaclnamespace));
6579
daclinfo[i].dobj.objType = DO_DEFAULT_ACL;
6580
daclinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
6581
daclinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
6582
AssignDumpId(&daclinfo[i].dobj);
6583
/* cheesy ... is it worth coming up with a better object name? */
6584
daclinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_defaclobjtype));
6586
if (nspid != InvalidOid)
6587
daclinfo[i].dobj.namespace = findNamespace(nspid,
6588
daclinfo[i].dobj.catId.oid);
6590
daclinfo[i].dobj.namespace = NULL;
6592
daclinfo[i].defaclrole = strdup(PQgetvalue(res, i, i_defaclrole));
6593
daclinfo[i].defaclobjtype = *(PQgetvalue(res, i, i_defaclobjtype));
6594
daclinfo[i].defaclacl = strdup(PQgetvalue(res, i, i_defaclacl));
6596
/* Decide whether we want to dump it */
6597
selectDumpableDefaultACL(&(daclinfo[i]));
6602
destroyPQExpBuffer(query);
6610
* This routine is used to dump any comments associated with the
6611
* object handed to this routine. The routine takes a constant character
6612
* string for the target part of the comment-creation command, plus
6613
* the namespace and owner of the object (for labeling the ArchiveEntry),
6614
* plus catalog ID and subid which are the lookup key for pg_description,
6615
* plus the dump ID for the object (for setting a dependency).
6616
* If a matching pg_description entry is found, it is dumped.
6618
* Note: although this routine takes a dumpId for dependency purposes,
6619
* that purpose is just to mark the dependency in the emitted dump file
6620
* for possible future use by pg_restore. We do NOT use it for determining
6621
* ordering of the comment in the dump file, because this routine is called
6622
* after dependency sorting occurs. This routine should be called just after
6623
* calling ArchiveEntry() for the specified object.
6626
dumpComment(Archive *fout, const char *target,
6627
const char *namespace, const char *owner,
6628
CatalogId catalogId, int subid, DumpId dumpId)
6630
CommentItem *comments;
6633
/* Comments are schema not data ... except blob comments are data */
6634
if (strncmp(target, "LARGE OBJECT ", 13) != 0)
6645
/* Search for comments associated with catalogId, using table */
6646
ncomments = findComments(fout, catalogId.tableoid, catalogId.oid,
6649
/* Is there one matching the subid? */
6650
while (ncomments > 0)
6652
if (comments->objsubid == subid)
6658
/* If a comment exists, build COMMENT ON statement */
6661
PQExpBuffer query = createPQExpBuffer();
6663
appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
6664
appendStringLiteralAH(query, comments->descr, fout);
6665
appendPQExpBuffer(query, ";\n");
6668
* We mark comments as SECTION_NONE because they really belong in the
6669
* same section as their parent, whether that is pre-data or
6672
ArchiveEntry(fout, nilCatalogId, createDumpId(),
6673
target, namespace, NULL, owner,
6674
false, "COMMENT", SECTION_NONE,
6675
query->data, "", NULL,
6679
destroyPQExpBuffer(query);
6684
* dumpTableComment --
6686
* As above, but dump comments for both the specified table (or view)
6690
dumpTableComment(Archive *fout, TableInfo *tbinfo,
6691
const char *reltypename)
6693
CommentItem *comments;
6698
/* Comments are SCHEMA not data */
6702
/* Search for comments associated with relation, using table */
6703
ncomments = findComments(fout,
6704
tbinfo->dobj.catId.tableoid,
6705
tbinfo->dobj.catId.oid,
6708
/* If comments exist, build COMMENT ON statements */
6712
query = createPQExpBuffer();
6713
target = createPQExpBuffer();
6715
while (ncomments > 0)
6717
const char *descr = comments->descr;
6718
int objsubid = comments->objsubid;
6722
resetPQExpBuffer(target);
6723
appendPQExpBuffer(target, "%s %s", reltypename,
6724
fmtId(tbinfo->dobj.name));
6726
resetPQExpBuffer(query);
6727
appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
6728
appendStringLiteralAH(query, descr, fout);
6729
appendPQExpBuffer(query, ";\n");
6731
ArchiveEntry(fout, nilCatalogId, createDumpId(),
6733
tbinfo->dobj.namespace->dobj.name,
6734
NULL, tbinfo->rolname,
6735
false, "COMMENT", SECTION_NONE,
6736
query->data, "", NULL,
6737
&(tbinfo->dobj.dumpId), 1,
6740
else if (objsubid > 0 && objsubid <= tbinfo->numatts)
6742
resetPQExpBuffer(target);
6743
appendPQExpBuffer(target, "COLUMN %s.",
6744
fmtId(tbinfo->dobj.name));
6745
appendPQExpBuffer(target, "%s",
6746
fmtId(tbinfo->attnames[objsubid - 1]));
6748
resetPQExpBuffer(query);
6749
appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
6750
appendStringLiteralAH(query, descr, fout);
6751
appendPQExpBuffer(query, ";\n");
6753
ArchiveEntry(fout, nilCatalogId, createDumpId(),
6755
tbinfo->dobj.namespace->dobj.name,
6756
NULL, tbinfo->rolname,
6757
false, "COMMENT", SECTION_NONE,
6758
query->data, "", NULL,
6759
&(tbinfo->dobj.dumpId), 1,
6767
destroyPQExpBuffer(query);
6768
destroyPQExpBuffer(target);
6774
* Find the comment(s), if any, associated with the given object. All the
6775
* objsubid values associated with the given classoid/objoid are found with
6779
findComments(Archive *fout, Oid classoid, Oid objoid,
6780
CommentItem **items)
6782
/* static storage for table of comments */
6783
static CommentItem *comments = NULL;
6784
static int ncomments = -1;
6786
CommentItem *middle = NULL;
6791
/* Get comments if we didn't already */
6793
ncomments = collectComments(fout, &comments);
6796
* Pre-7.2, pg_description does not contain classoid, so collectComments
6797
* just stores a zero. If there's a collision on object OID, well, you
6798
* get duplicate comments.
6800
if (fout->remoteVersion < 70200)
6804
* Do binary search to find some item matching the object.
6807
high = &comments[ncomments - 1];
6810
middle = low + (high - low) / 2;
6812
if (classoid < middle->classoid)
6814
else if (classoid > middle->classoid)
6816
else if (objoid < middle->objoid)
6818
else if (objoid > middle->objoid)
6821
break; /* found a match */
6824
if (low > high) /* no matches */
6831
* Now determine how many items match the object. The search loop
6832
* invariant still holds: only items between low and high inclusive could
6836
while (middle > low)
6838
if (classoid != middle[-1].classoid ||
6839
objoid != middle[-1].objoid)
6848
while (middle <= high)
6850
if (classoid != middle->classoid ||
6851
objoid != middle->objoid)
6861
* collectComments --
6863
* Construct a table of all comments available for database objects.
6864
* We used to do per-object queries for the comments, but it's much faster
6865
* to pull them all over at once, and on most databases the memory cost
6868
* The table is sorted by classoid/objid/objsubid for speed in lookup.
6871
collectComments(Archive *fout, CommentItem **items)
6881
CommentItem *comments;
6884
* Note we do NOT change source schema here; preserve the caller's
6888
query = createPQExpBuffer();
6890
if (fout->remoteVersion >= 70300)
6892
appendPQExpBuffer(query, "SELECT description, classoid, objoid, objsubid "
6893
"FROM pg_catalog.pg_description "
6894
"ORDER BY classoid, objoid, objsubid");
6896
else if (fout->remoteVersion >= 70200)
6898
appendPQExpBuffer(query, "SELECT description, classoid, objoid, objsubid "
6899
"FROM pg_description "
6900
"ORDER BY classoid, objoid, objsubid");
6904
/* Note: this will fail to find attribute comments in pre-7.2... */
6905
appendPQExpBuffer(query, "SELECT description, 0 AS classoid, objoid, 0 AS objsubid "
6906
"FROM pg_description "
6910
res = PQexec(g_conn, query->data);
6911
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6913
/* Construct lookup table containing OIDs in numeric form */
6915
i_description = PQfnumber(res, "description");
6916
i_classoid = PQfnumber(res, "classoid");
6917
i_objoid = PQfnumber(res, "objoid");
6918
i_objsubid = PQfnumber(res, "objsubid");
6920
ntups = PQntuples(res);
6922
comments = (CommentItem *) malloc(ntups * sizeof(CommentItem));
6924
for (i = 0; i < ntups; i++)
6926
comments[i].descr = PQgetvalue(res, i, i_description);
6927
comments[i].classoid = atooid(PQgetvalue(res, i, i_classoid));
6928
comments[i].objoid = atooid(PQgetvalue(res, i, i_objoid));
6929
comments[i].objsubid = atoi(PQgetvalue(res, i, i_objsubid));
6932
/* Do NOT free the PGresult since we are keeping pointers into it */
6933
destroyPQExpBuffer(query);
6940
* dumpDumpableObject
6942
* This routine and its subsidiaries are responsible for creating
6943
* ArchiveEntries (TOC objects) for each object to be dumped.
6946
dumpDumpableObject(Archive *fout, DumpableObject *dobj)
6948
switch (dobj->objType)
6951
dumpNamespace(fout, (NamespaceInfo *) dobj);
6954
dumpExtension(fout, (ExtensionInfo *) dobj);
6957
dumpType(fout, (TypeInfo *) dobj);
6960
dumpShellType(fout, (ShellTypeInfo *) dobj);
6963
dumpFunc(fout, (FuncInfo *) dobj);
6966
dumpAgg(fout, (AggInfo *) dobj);
6969
dumpOpr(fout, (OprInfo *) dobj);
6972
dumpOpclass(fout, (OpclassInfo *) dobj);
6975
dumpOpfamily(fout, (OpfamilyInfo *) dobj);
6978
dumpCollation(fout, (CollInfo *) dobj);
6981
dumpConversion(fout, (ConvInfo *) dobj);
6984
dumpTable(fout, (TableInfo *) dobj);
6987
dumpAttrDef(fout, (AttrDefInfo *) dobj);
6990
dumpIndex(fout, (IndxInfo *) dobj);
6993
dumpRule(fout, (RuleInfo *) dobj);
6996
dumpTrigger(fout, (TriggerInfo *) dobj);
6999
dumpConstraint(fout, (ConstraintInfo *) dobj);
7001
case DO_FK_CONSTRAINT:
7002
dumpConstraint(fout, (ConstraintInfo *) dobj);
7005
dumpProcLang(fout, (ProcLangInfo *) dobj);
7008
dumpCast(fout, (CastInfo *) dobj);
7011
dumpTableData(fout, (TableDataInfo *) dobj);
7014
/* table rowtypes and array types are never dumped separately */
7017
dumpTSParser(fout, (TSParserInfo *) dobj);
7020
dumpTSDictionary(fout, (TSDictInfo *) dobj);
7023
dumpTSTemplate(fout, (TSTemplateInfo *) dobj);
7026
dumpTSConfig(fout, (TSConfigInfo *) dobj);
7029
dumpForeignDataWrapper(fout, (FdwInfo *) dobj);
7031
case DO_FOREIGN_SERVER:
7032
dumpForeignServer(fout, (ForeignServerInfo *) dobj);
7034
case DO_DEFAULT_ACL:
7035
dumpDefaultACL(fout, (DefaultACLInfo *) dobj);
7038
dumpBlob(fout, (BlobInfo *) dobj);
7041
ArchiveEntry(fout, dobj->catId, dobj->dumpId,
7042
dobj->name, NULL, NULL, "",
7043
false, "BLOBS", SECTION_DATA,
7045
dobj->dependencies, dobj->nDeps,
7053
* writes out to fout the queries to recreate a user-defined namespace
7056
dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
7063
/* Skip if not to be dumped */
7064
if (!nspinfo->dobj.dump || dataOnly)
7067
/* don't dump dummy namespace from pre-7.3 source */
7068
if (strlen(nspinfo->dobj.name) == 0)
7071
q = createPQExpBuffer();
7072
delq = createPQExpBuffer();
7073
labelq = createPQExpBuffer();
7075
qnspname = strdup(fmtId(nspinfo->dobj.name));
7077
appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
7079
appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
7081
appendPQExpBuffer(labelq, "SCHEMA %s", qnspname);
7084
binary_upgrade_extension_member(q, &nspinfo->dobj, labelq->data);
7086
ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
7090
false, "SCHEMA", SECTION_PRE_DATA,
7091
q->data, delq->data, NULL,
7092
nspinfo->dobj.dependencies, nspinfo->dobj.nDeps,
7095
/* Dump Schema Comments and Security Labels */
7096
dumpComment(fout, labelq->data,
7097
NULL, nspinfo->rolname,
7098
nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
7099
dumpSecLabel(fout, labelq->data,
7100
NULL, nspinfo->rolname,
7101
nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
7103
dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
7104
qnspname, NULL, nspinfo->dobj.name, NULL,
7105
nspinfo->rolname, nspinfo->nspacl);
7109
destroyPQExpBuffer(q);
7110
destroyPQExpBuffer(delq);
7111
destroyPQExpBuffer(labelq);
7116
* writes out to fout the queries to recreate an extension
7119
dumpExtension(Archive *fout, ExtensionInfo *extinfo)
7126
/* Skip if not to be dumped */
7127
if (!extinfo->dobj.dump || dataOnly)
7130
q = createPQExpBuffer();
7131
delq = createPQExpBuffer();
7132
labelq = createPQExpBuffer();
7134
qextname = strdup(fmtId(extinfo->dobj.name));
7136
appendPQExpBuffer(delq, "DROP EXTENSION %s;\n", qextname);
7138
if (!binary_upgrade)
7141
* In a regular dump, we use IF NOT EXISTS so that there isn't a
7142
* problem if the extension already exists in the target database;
7143
* this is essential for installed-by-default extensions such as
7146
* In binary-upgrade mode, that doesn't work well, so instead we skip
7147
* built-in extensions based on their OIDs; see
7148
* selectDumpableExtension.
7150
appendPQExpBuffer(q, "CREATE EXTENSION IF NOT EXISTS %s WITH SCHEMA %s;\n",
7151
qextname, fmtId(extinfo->namespace));
7158
appendPQExpBuffer(q, "-- For binary upgrade, create an empty extension and insert objects into it\n");
7159
appendPQExpBuffer(q,
7160
"SELECT binary_upgrade.create_empty_extension(");
7161
appendStringLiteralAH(q, extinfo->dobj.name, fout);
7162
appendPQExpBuffer(q, ", ");
7163
appendStringLiteralAH(q, extinfo->namespace, fout);
7164
appendPQExpBuffer(q, ", ");
7165
appendPQExpBuffer(q, "%s, ", extinfo->relocatable ? "true" : "false");
7166
appendStringLiteralAH(q, extinfo->extversion, fout);
7167
appendPQExpBuffer(q, ", ");
7170
* Note that we're pushing extconfig (an OID array) back into
7171
* pg_extension exactly as-is. This is OK because pg_class OIDs are
7172
* preserved in binary upgrade.
7174
if (strlen(extinfo->extconfig) > 2)
7175
appendStringLiteralAH(q, extinfo->extconfig, fout);
7177
appendPQExpBuffer(q, "NULL");
7178
appendPQExpBuffer(q, ", ");
7179
if (strlen(extinfo->extcondition) > 2)
7180
appendStringLiteralAH(q, extinfo->extcondition, fout);
7182
appendPQExpBuffer(q, "NULL");
7183
appendPQExpBuffer(q, ", ");
7184
appendPQExpBuffer(q, "ARRAY[");
7186
for (i = 0; i < extinfo->dobj.nDeps; i++)
7188
DumpableObject *extobj;
7190
extobj = findObjectByDumpId(extinfo->dobj.dependencies[i]);
7191
if (extobj && extobj->objType == DO_EXTENSION)
7194
appendPQExpBuffer(q, ",");
7195
appendStringLiteralAH(q, extobj->name, fout);
7198
appendPQExpBuffer(q, "]::pg_catalog.text[]");
7199
appendPQExpBuffer(q, ");\n");
7202
appendPQExpBuffer(labelq, "EXTENSION %s", qextname);
7204
ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId,
7208
false, "EXTENSION", SECTION_PRE_DATA,
7209
q->data, delq->data, NULL,
7210
extinfo->dobj.dependencies, extinfo->dobj.nDeps,
7213
/* Dump Extension Comments and Security Labels */
7214
dumpComment(fout, labelq->data,
7216
extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
7217
dumpSecLabel(fout, labelq->data,
7219
extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
7223
destroyPQExpBuffer(q);
7224
destroyPQExpBuffer(delq);
7225
destroyPQExpBuffer(labelq);
7230
* writes out to fout the queries to recreate a user-defined type
7233
dumpType(Archive *fout, TypeInfo *tyinfo)
7235
/* Skip if not to be dumped */
7236
if (!tyinfo->dobj.dump || dataOnly)
7239
/* Dump out in proper style */
7240
if (tyinfo->typtype == TYPTYPE_BASE)
7241
dumpBaseType(fout, tyinfo);
7242
else if (tyinfo->typtype == TYPTYPE_DOMAIN)
7243
dumpDomain(fout, tyinfo);
7244
else if (tyinfo->typtype == TYPTYPE_COMPOSITE)
7245
dumpCompositeType(fout, tyinfo);
7246
else if (tyinfo->typtype == TYPTYPE_ENUM)
7247
dumpEnumType(fout, tyinfo);
7252
* writes out to fout the queries to recreate a user-defined enum type
7255
dumpEnumType(Archive *fout, TypeInfo *tyinfo)
7257
PQExpBuffer q = createPQExpBuffer();
7258
PQExpBuffer delq = createPQExpBuffer();
7259
PQExpBuffer labelq = createPQExpBuffer();
7260
PQExpBuffer query = createPQExpBuffer();
7267
/* Set proper schema search path */
7268
selectSourceSchema("pg_catalog");
7270
if (fout->remoteVersion >= 90100)
7271
appendPQExpBuffer(query, "SELECT oid, enumlabel "
7272
"FROM pg_catalog.pg_enum "
7273
"WHERE enumtypid = '%u'"
7274
"ORDER BY enumsortorder",
7275
tyinfo->dobj.catId.oid);
7277
appendPQExpBuffer(query, "SELECT oid, enumlabel "
7278
"FROM pg_catalog.pg_enum "
7279
"WHERE enumtypid = '%u'"
7281
tyinfo->dobj.catId.oid);
7283
res = PQexec(g_conn, query->data);
7284
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
7286
num = PQntuples(res);
7289
* DROP must be fully qualified in case same name appears in pg_catalog.
7290
* CASCADE shouldn't be required here as for normal types since the I/O
7291
* functions are generic and do not get dropped.
7293
appendPQExpBuffer(delq, "DROP TYPE %s.",
7294
fmtId(tyinfo->dobj.namespace->dobj.name));
7295
appendPQExpBuffer(delq, "%s;\n",
7296
fmtId(tyinfo->dobj.name));
7299
binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
7301
appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (",
7302
fmtId(tyinfo->dobj.name));
7304
if (!binary_upgrade)
7306
/* Labels with server-assigned oids */
7307
for (i = 0; i < num; i++)
7309
label = PQgetvalue(res, i, PQfnumber(res, "enumlabel"));
7311
appendPQExpBuffer(q, ",");
7312
appendPQExpBuffer(q, "\n ");
7313
appendStringLiteralAH(q, label, fout);
7317
appendPQExpBuffer(q, "\n);\n");
7321
/* Labels with dump-assigned (preserved) oids */
7322
for (i = 0; i < num; i++)
7324
enum_oid = atooid(PQgetvalue(res, i, PQfnumber(res, "oid")));
7325
label = PQgetvalue(res, i, PQfnumber(res, "enumlabel"));
7328
appendPQExpBuffer(q, "\n-- For binary upgrade, must preserve pg_enum oids\n");
7329
appendPQExpBuffer(q,
7330
"SELECT binary_upgrade.set_next_pg_enum_oid('%u'::pg_catalog.oid);\n",
7332
appendPQExpBuffer(q, "ALTER TYPE %s.",
7333
fmtId(tyinfo->dobj.namespace->dobj.name));
7334
appendPQExpBuffer(q, "%s ADD VALUE ",
7335
fmtId(tyinfo->dobj.name));
7336
appendStringLiteralAH(q, label, fout);
7337
appendPQExpBuffer(q, ";\n\n");
7341
appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
7344
binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
7346
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
7348
tyinfo->dobj.namespace->dobj.name,
7350
tyinfo->rolname, false,
7351
"TYPE", SECTION_PRE_DATA,
7352
q->data, delq->data, NULL,
7353
tyinfo->dobj.dependencies, tyinfo->dobj.nDeps,
7356
/* Dump Type Comments and Security Labels */
7357
dumpComment(fout, labelq->data,
7358
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
7359
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
7360
dumpSecLabel(fout, labelq->data,
7361
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
7362
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
7365
destroyPQExpBuffer(q);
7366
destroyPQExpBuffer(delq);
7367
destroyPQExpBuffer(labelq);
7368
destroyPQExpBuffer(query);
7373
* writes out to fout the queries to recreate a user-defined base type
7376
dumpBaseType(Archive *fout, TypeInfo *tyinfo)
7378
PQExpBuffer q = createPQExpBuffer();
7379
PQExpBuffer delq = createPQExpBuffer();
7380
PQExpBuffer labelq = createPQExpBuffer();
7381
PQExpBuffer query = createPQExpBuffer();
7398
char *typispreferred;
7403
char *typcollatable;
7405
bool typdefault_is_literal = false;
7407
/* Set proper schema search path so regproc references list correctly */
7408
selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
7410
/* Fetch type-specific details */
7411
if (fout->remoteVersion >= 90100)
7413
appendPQExpBuffer(query, "SELECT typlen, "
7414
"typinput, typoutput, typreceive, typsend, "
7415
"typmodin, typmodout, typanalyze, "
7416
"typreceive::pg_catalog.oid AS typreceiveoid, "
7417
"typsend::pg_catalog.oid AS typsendoid, "
7418
"typmodin::pg_catalog.oid AS typmodinoid, "
7419
"typmodout::pg_catalog.oid AS typmodoutoid, "
7420
"typanalyze::pg_catalog.oid AS typanalyzeoid, "
7421
"typcategory, typispreferred, "
7422
"typdelim, typbyval, typalign, typstorage, "
7423
"(typcollation <> 0) AS typcollatable, "
7424
"pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault "
7425
"FROM pg_catalog.pg_type "
7426
"WHERE oid = '%u'::pg_catalog.oid",
7427
tyinfo->dobj.catId.oid);
7429
else if (fout->remoteVersion >= 80400)
7431
appendPQExpBuffer(query, "SELECT typlen, "
7432
"typinput, typoutput, typreceive, typsend, "
7433
"typmodin, typmodout, typanalyze, "
7434
"typreceive::pg_catalog.oid AS typreceiveoid, "
7435
"typsend::pg_catalog.oid AS typsendoid, "
7436
"typmodin::pg_catalog.oid AS typmodinoid, "
7437
"typmodout::pg_catalog.oid AS typmodoutoid, "
7438
"typanalyze::pg_catalog.oid AS typanalyzeoid, "
7439
"typcategory, typispreferred, "
7440
"typdelim, typbyval, typalign, typstorage, "
7441
"false AS typcollatable, "
7442
"pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault "
7443
"FROM pg_catalog.pg_type "
7444
"WHERE oid = '%u'::pg_catalog.oid",
7445
tyinfo->dobj.catId.oid);
7447
else if (fout->remoteVersion >= 80300)
7449
/* Before 8.4, pg_get_expr does not allow 0 for its second arg */
7450
appendPQExpBuffer(query, "SELECT typlen, "
7451
"typinput, typoutput, typreceive, typsend, "
7452
"typmodin, typmodout, typanalyze, "
7453
"typreceive::pg_catalog.oid AS typreceiveoid, "
7454
"typsend::pg_catalog.oid AS typsendoid, "
7455
"typmodin::pg_catalog.oid AS typmodinoid, "
7456
"typmodout::pg_catalog.oid AS typmodoutoid, "
7457
"typanalyze::pg_catalog.oid AS typanalyzeoid, "
7458
"'U' AS typcategory, false AS typispreferred, "
7459
"typdelim, typbyval, typalign, typstorage, "
7460
"false AS typcollatable, "
7461
"pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
7462
"FROM pg_catalog.pg_type "
7463
"WHERE oid = '%u'::pg_catalog.oid",
7464
tyinfo->dobj.catId.oid);
7466
else if (fout->remoteVersion >= 80000)
7468
appendPQExpBuffer(query, "SELECT typlen, "
7469
"typinput, typoutput, typreceive, typsend, "
7470
"'-' AS typmodin, '-' AS typmodout, "
7472
"typreceive::pg_catalog.oid AS typreceiveoid, "
7473
"typsend::pg_catalog.oid AS typsendoid, "
7474
"0 AS typmodinoid, 0 AS typmodoutoid, "
7475
"typanalyze::pg_catalog.oid AS typanalyzeoid, "
7476
"'U' AS typcategory, false AS typispreferred, "
7477
"typdelim, typbyval, typalign, typstorage, "
7478
"false AS typcollatable, "
7479
"pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
7480
"FROM pg_catalog.pg_type "
7481
"WHERE oid = '%u'::pg_catalog.oid",
7482
tyinfo->dobj.catId.oid);
7484
else if (fout->remoteVersion >= 70400)
7486
appendPQExpBuffer(query, "SELECT typlen, "
7487
"typinput, typoutput, typreceive, typsend, "
7488
"'-' AS typmodin, '-' AS typmodout, "
7489
"'-' AS typanalyze, "
7490
"typreceive::pg_catalog.oid AS typreceiveoid, "
7491
"typsend::pg_catalog.oid AS typsendoid, "
7492
"0 AS typmodinoid, 0 AS typmodoutoid, "
7493
"0 AS typanalyzeoid, "
7494
"'U' AS typcategory, false AS typispreferred, "
7495
"typdelim, typbyval, typalign, typstorage, "
7496
"false AS typcollatable, "
7497
"pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
7498
"FROM pg_catalog.pg_type "
7499
"WHERE oid = '%u'::pg_catalog.oid",
7500
tyinfo->dobj.catId.oid);
7502
else if (fout->remoteVersion >= 70300)
7504
appendPQExpBuffer(query, "SELECT typlen, "
7505
"typinput, typoutput, "
7506
"'-' AS typreceive, '-' AS typsend, "
7507
"'-' AS typmodin, '-' AS typmodout, "
7508
"'-' AS typanalyze, "
7509
"0 AS typreceiveoid, 0 AS typsendoid, "
7510
"0 AS typmodinoid, 0 AS typmodoutoid, "
7511
"0 AS typanalyzeoid, "
7512
"'U' AS typcategory, false AS typispreferred, "
7513
"typdelim, typbyval, typalign, typstorage, "
7514
"false AS typcollatable, "
7515
"pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
7516
"FROM pg_catalog.pg_type "
7517
"WHERE oid = '%u'::pg_catalog.oid",
7518
tyinfo->dobj.catId.oid);
7520
else if (fout->remoteVersion >= 70200)
7523
* Note: although pre-7.3 catalogs contain typreceive and typsend,
7524
* ignore them because they are not right.
7526
appendPQExpBuffer(query, "SELECT typlen, "
7527
"typinput, typoutput, "
7528
"'-' AS typreceive, '-' AS typsend, "
7529
"'-' AS typmodin, '-' AS typmodout, "
7530
"'-' AS typanalyze, "
7531
"0 AS typreceiveoid, 0 AS typsendoid, "
7532
"0 AS typmodinoid, 0 AS typmodoutoid, "
7533
"0 AS typanalyzeoid, "
7534
"'U' AS typcategory, false AS typispreferred, "
7535
"typdelim, typbyval, typalign, typstorage, "
7536
"false AS typcollatable, "
7537
"NULL AS typdefaultbin, typdefault "
7539
"WHERE oid = '%u'::oid",
7540
tyinfo->dobj.catId.oid);
7542
else if (fout->remoteVersion >= 70100)
7545
* Ignore pre-7.2 typdefault; the field exists but has an unusable
7548
appendPQExpBuffer(query, "SELECT typlen, "
7549
"typinput, typoutput, "
7550
"'-' AS typreceive, '-' AS typsend, "
7551
"'-' AS typmodin, '-' AS typmodout, "
7552
"'-' AS typanalyze, "
7553
"0 AS typreceiveoid, 0 AS typsendoid, "
7554
"0 AS typmodinoid, 0 AS typmodoutoid, "
7555
"0 AS typanalyzeoid, "
7556
"'U' AS typcategory, false AS typispreferred, "
7557
"typdelim, typbyval, typalign, typstorage, "
7558
"false AS typcollatable, "
7559
"NULL AS typdefaultbin, NULL AS typdefault "
7561
"WHERE oid = '%u'::oid",
7562
tyinfo->dobj.catId.oid);
7566
appendPQExpBuffer(query, "SELECT typlen, "
7567
"typinput, typoutput, "
7568
"'-' AS typreceive, '-' AS typsend, "
7569
"'-' AS typmodin, '-' AS typmodout, "
7570
"'-' AS typanalyze, "
7571
"0 AS typreceiveoid, 0 AS typsendoid, "
7572
"0 AS typmodinoid, 0 AS typmodoutoid, "
7573
"0 AS typanalyzeoid, "
7574
"'U' AS typcategory, false AS typispreferred, "
7575
"typdelim, typbyval, typalign, "
7576
"'p'::char AS typstorage, "
7577
"false AS typcollatable, "
7578
"NULL AS typdefaultbin, NULL AS typdefault "
7580
"WHERE oid = '%u'::oid",
7581
tyinfo->dobj.catId.oid);
7584
res = PQexec(g_conn, query->data);
7585
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
7587
/* Expecting a single result only */
7588
ntups = PQntuples(res);
7591
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
7592
"query returned %d rows instead of one: %s\n",
7594
ntups, query->data);
7598
typlen = PQgetvalue(res, 0, PQfnumber(res, "typlen"));
7599
typinput = PQgetvalue(res, 0, PQfnumber(res, "typinput"));
7600
typoutput = PQgetvalue(res, 0, PQfnumber(res, "typoutput"));
7601
typreceive = PQgetvalue(res, 0, PQfnumber(res, "typreceive"));
7602
typsend = PQgetvalue(res, 0, PQfnumber(res, "typsend"));
7603
typmodin = PQgetvalue(res, 0, PQfnumber(res, "typmodin"));
7604
typmodout = PQgetvalue(res, 0, PQfnumber(res, "typmodout"));
7605
typanalyze = PQgetvalue(res, 0, PQfnumber(res, "typanalyze"));
7606
typreceiveoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typreceiveoid")));
7607
typsendoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typsendoid")));
7608
typmodinoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodinoid")));
7609
typmodoutoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodoutoid")));
7610
typanalyzeoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typanalyzeoid")));
7611
typcategory = PQgetvalue(res, 0, PQfnumber(res, "typcategory"));
7612
typispreferred = PQgetvalue(res, 0, PQfnumber(res, "typispreferred"));
7613
typdelim = PQgetvalue(res, 0, PQfnumber(res, "typdelim"));
7614
typbyval = PQgetvalue(res, 0, PQfnumber(res, "typbyval"));
7615
typalign = PQgetvalue(res, 0, PQfnumber(res, "typalign"));
7616
typstorage = PQgetvalue(res, 0, PQfnumber(res, "typstorage"));
7617
typcollatable = PQgetvalue(res, 0, PQfnumber(res, "typcollatable"));
7618
if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin")))
7619
typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin"));
7620
else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
7622
typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
7623
typdefault_is_literal = true; /* it needs quotes */
7629
* DROP must be fully qualified in case same name appears in pg_catalog.
7630
* The reason we include CASCADE is that the circular dependency between
7631
* the type and its I/O functions makes it impossible to drop the type any
7634
appendPQExpBuffer(delq, "DROP TYPE %s.",
7635
fmtId(tyinfo->dobj.namespace->dobj.name));
7636
appendPQExpBuffer(delq, "%s CASCADE;\n",
7637
fmtId(tyinfo->dobj.name));
7639
/* We might already have a shell type, but setting pg_type_oid is harmless */
7641
binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
7643
appendPQExpBuffer(q,
7644
"CREATE TYPE %s (\n"
7645
" INTERNALLENGTH = %s",
7646
fmtId(tyinfo->dobj.name),
7647
(strcmp(typlen, "-1") == 0) ? "variable" : typlen);
7649
if (fout->remoteVersion >= 70300)
7651
/* regproc result is correctly quoted as of 7.3 */
7652
appendPQExpBuffer(q, ",\n INPUT = %s", typinput);
7653
appendPQExpBuffer(q, ",\n OUTPUT = %s", typoutput);
7654
if (OidIsValid(typreceiveoid))
7655
appendPQExpBuffer(q, ",\n RECEIVE = %s", typreceive);
7656
if (OidIsValid(typsendoid))
7657
appendPQExpBuffer(q, ",\n SEND = %s", typsend);
7658
if (OidIsValid(typmodinoid))
7659
appendPQExpBuffer(q, ",\n TYPMOD_IN = %s", typmodin);
7660
if (OidIsValid(typmodoutoid))
7661
appendPQExpBuffer(q, ",\n TYPMOD_OUT = %s", typmodout);
7662
if (OidIsValid(typanalyzeoid))
7663
appendPQExpBuffer(q, ",\n ANALYZE = %s", typanalyze);
7667
/* regproc delivers an unquoted name before 7.3 */
7668
/* cannot combine these because fmtId uses static result area */
7669
appendPQExpBuffer(q, ",\n INPUT = %s", fmtId(typinput));
7670
appendPQExpBuffer(q, ",\n OUTPUT = %s", fmtId(typoutput));
7671
/* receive/send/typmodin/typmodout/analyze need not be printed */
7674
if (strcmp(typcollatable, "t") == 0)
7675
appendPQExpBuffer(q, ",\n COLLATABLE = true");
7677
if (typdefault != NULL)
7679
appendPQExpBuffer(q, ",\n DEFAULT = ");
7680
if (typdefault_is_literal)
7681
appendStringLiteralAH(q, typdefault, fout);
7683
appendPQExpBufferStr(q, typdefault);
7686
if (OidIsValid(tyinfo->typelem))
7690
/* reselect schema in case changed by function dump */
7691
selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
7692
elemType = getFormattedTypeName(tyinfo->typelem, zeroAsOpaque);
7693
appendPQExpBuffer(q, ",\n ELEMENT = %s", elemType);
7697
if (strcmp(typcategory, "U") != 0)
7699
appendPQExpBuffer(q, ",\n CATEGORY = ");
7700
appendStringLiteralAH(q, typcategory, fout);
7703
if (strcmp(typispreferred, "t") == 0)
7704
appendPQExpBuffer(q, ",\n PREFERRED = true");
7706
if (typdelim && strcmp(typdelim, ",") != 0)
7708
appendPQExpBuffer(q, ",\n DELIMITER = ");
7709
appendStringLiteralAH(q, typdelim, fout);
7712
if (strcmp(typalign, "c") == 0)
7713
appendPQExpBuffer(q, ",\n ALIGNMENT = char");
7714
else if (strcmp(typalign, "s") == 0)
7715
appendPQExpBuffer(q, ",\n ALIGNMENT = int2");
7716
else if (strcmp(typalign, "i") == 0)
7717
appendPQExpBuffer(q, ",\n ALIGNMENT = int4");
7718
else if (strcmp(typalign, "d") == 0)
7719
appendPQExpBuffer(q, ",\n ALIGNMENT = double");
7721
if (strcmp(typstorage, "p") == 0)
7722
appendPQExpBuffer(q, ",\n STORAGE = plain");
7723
else if (strcmp(typstorage, "e") == 0)
7724
appendPQExpBuffer(q, ",\n STORAGE = external");
7725
else if (strcmp(typstorage, "x") == 0)
7726
appendPQExpBuffer(q, ",\n STORAGE = extended");
7727
else if (strcmp(typstorage, "m") == 0)
7728
appendPQExpBuffer(q, ",\n STORAGE = main");
7730
if (strcmp(typbyval, "t") == 0)
7731
appendPQExpBuffer(q, ",\n PASSEDBYVALUE");
7733
appendPQExpBuffer(q, "\n);\n");
7735
appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
7738
binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
7740
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
7742
tyinfo->dobj.namespace->dobj.name,
7744
tyinfo->rolname, false,
7745
"TYPE", SECTION_PRE_DATA,
7746
q->data, delq->data, NULL,
7747
tyinfo->dobj.dependencies, tyinfo->dobj.nDeps,
7750
/* Dump Type Comments and Security Labels */
7751
dumpComment(fout, labelq->data,
7752
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
7753
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
7754
dumpSecLabel(fout, labelq->data,
7755
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
7756
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
7759
destroyPQExpBuffer(q);
7760
destroyPQExpBuffer(delq);
7761
destroyPQExpBuffer(labelq);
7762
destroyPQExpBuffer(query);
7767
* writes out to fout the queries to recreate a user-defined domain
7770
dumpDomain(Archive *fout, TypeInfo *tyinfo)
7772
PQExpBuffer q = createPQExpBuffer();
7773
PQExpBuffer delq = createPQExpBuffer();
7774
PQExpBuffer labelq = createPQExpBuffer();
7775
PQExpBuffer query = createPQExpBuffer();
7783
bool typdefault_is_literal = false;
7785
/* Set proper schema search path so type references list correctly */
7786
selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
7788
/* Fetch domain specific details */
7789
if (g_fout->remoteVersion >= 90100)
7791
/* typcollation is new in 9.1 */
7792
appendPQExpBuffer(query, "SELECT t.typnotnull, "
7793
"pg_catalog.format_type(t.typbasetype, t.typtypmod) AS typdefn, "
7794
"pg_catalog.pg_get_expr(t.typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
7796
"CASE WHEN t.typcollation <> u.typcollation "
7797
"THEN t.typcollation ELSE 0 END AS typcollation "
7798
"FROM pg_catalog.pg_type t "
7799
"LEFT JOIN pg_catalog.pg_type u ON (t.typbasetype = u.oid) "
7800
"WHERE t.oid = '%u'::pg_catalog.oid",
7801
tyinfo->dobj.catId.oid);
7805
/* We assume here that remoteVersion must be at least 70300 */
7806
appendPQExpBuffer(query, "SELECT typnotnull, "
7807
"pg_catalog.format_type(typbasetype, typtypmod) AS typdefn, "
7808
"pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
7809
"typdefault, 0 AS typcollation "
7810
"FROM pg_catalog.pg_type "
7811
"WHERE oid = '%u'::pg_catalog.oid",
7812
tyinfo->dobj.catId.oid);
7815
res = PQexec(g_conn, query->data);
7816
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
7818
/* Expecting a single result only */
7819
ntups = PQntuples(res);
7822
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
7823
"query returned %d rows instead of one: %s\n",
7825
ntups, query->data);
7829
typnotnull = PQgetvalue(res, 0, PQfnumber(res, "typnotnull"));
7830
typdefn = PQgetvalue(res, 0, PQfnumber(res, "typdefn"));
7831
if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin")))
7832
typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin"));
7833
else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
7835
typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
7836
typdefault_is_literal = true; /* it needs quotes */
7840
typcollation = atooid(PQgetvalue(res, 0, PQfnumber(res, "typcollation")));
7843
binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
7845
appendPQExpBuffer(q,
7846
"CREATE DOMAIN %s AS %s",
7847
fmtId(tyinfo->dobj.name),
7850
/* Print collation only if different from base type's collation */
7851
if (OidIsValid(typcollation))
7855
coll = findCollationByOid(typcollation);
7858
/* always schema-qualify, don't try to be smart */
7859
appendPQExpBuffer(q, " COLLATE %s.",
7860
fmtId(coll->dobj.namespace->dobj.name));
7861
appendPQExpBuffer(q, "%s",
7862
fmtId(coll->dobj.name));
7866
if (typnotnull[0] == 't')
7867
appendPQExpBuffer(q, " NOT NULL");
7869
if (typdefault != NULL)
7871
appendPQExpBuffer(q, " DEFAULT ");
7872
if (typdefault_is_literal)
7873
appendStringLiteralAH(q, typdefault, fout);
7875
appendPQExpBufferStr(q, typdefault);
7881
* Add any CHECK constraints for the domain
7883
for (i = 0; i < tyinfo->nDomChecks; i++)
7885
ConstraintInfo *domcheck = &(tyinfo->domChecks[i]);
7887
if (!domcheck->separate)
7888
appendPQExpBuffer(q, "\n\tCONSTRAINT %s %s",
7889
fmtId(domcheck->dobj.name), domcheck->condef);
7892
appendPQExpBuffer(q, ";\n");
7895
* DROP must be fully qualified in case same name appears in pg_catalog
7897
appendPQExpBuffer(delq, "DROP DOMAIN %s.",
7898
fmtId(tyinfo->dobj.namespace->dobj.name));
7899
appendPQExpBuffer(delq, "%s;\n",
7900
fmtId(tyinfo->dobj.name));
7902
appendPQExpBuffer(labelq, "DOMAIN %s", fmtId(tyinfo->dobj.name));
7905
binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
7907
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
7909
tyinfo->dobj.namespace->dobj.name,
7911
tyinfo->rolname, false,
7912
"DOMAIN", SECTION_PRE_DATA,
7913
q->data, delq->data, NULL,
7914
tyinfo->dobj.dependencies, tyinfo->dobj.nDeps,
7917
/* Dump Domain Comments and Security Labels */
7918
dumpComment(fout, labelq->data,
7919
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
7920
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
7921
dumpSecLabel(fout, labelq->data,
7922
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
7923
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
7925
destroyPQExpBuffer(q);
7926
destroyPQExpBuffer(delq);
7927
destroyPQExpBuffer(labelq);
7928
destroyPQExpBuffer(query);
7933
* writes out to fout the queries to recreate a user-defined stand-alone
7937
dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
7939
PQExpBuffer q = createPQExpBuffer();
7940
PQExpBuffer delq = createPQExpBuffer();
7941
PQExpBuffer labelq = createPQExpBuffer();
7942
PQExpBuffer query = createPQExpBuffer();
7951
/* Set proper schema search path so type references list correctly */
7952
selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
7954
/* Fetch type specific details */
7955
if (fout->remoteVersion >= 90100)
7958
* attcollation is new in 9.1. Since we only want to dump COLLATE
7959
* clauses for attributes whose collation is different from their
7960
* type's default, we use a CASE here to suppress uninteresting
7961
* attcollations cheaply.
7963
appendPQExpBuffer(query, "SELECT a.attname, "
7964
"pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, "
7965
"CASE WHEN a.attcollation <> at.typcollation "
7966
"THEN a.attcollation ELSE 0 END AS attcollation, "
7968
"FROM pg_catalog.pg_type ct, pg_catalog.pg_attribute a, "
7969
"pg_catalog.pg_type at "
7970
"WHERE ct.oid = '%u'::pg_catalog.oid "
7971
"AND a.attrelid = ct.typrelid "
7972
"AND a.atttypid = at.oid "
7973
"AND NOT a.attisdropped "
7974
"ORDER BY a.attnum ",
7975
tyinfo->dobj.catId.oid);
7979
/* We assume here that remoteVersion must be at least 70300 */
7980
appendPQExpBuffer(query, "SELECT a.attname, "
7981
"pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, "
7982
"0 AS attcollation, "
7984
"FROM pg_catalog.pg_type ct, pg_catalog.pg_attribute a "
7985
"WHERE ct.oid = '%u'::pg_catalog.oid "
7986
"AND a.attrelid = ct.typrelid "
7987
"AND NOT a.attisdropped "
7988
"ORDER BY a.attnum ",
7989
tyinfo->dobj.catId.oid);
7992
res = PQexec(g_conn, query->data);
7993
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
7995
ntups = PQntuples(res);
7997
i_attname = PQfnumber(res, "attname");
7998
i_atttypdefn = PQfnumber(res, "atttypdefn");
7999
i_attcollation = PQfnumber(res, "attcollation");
8000
i_typrelid = PQfnumber(res, "typrelid");
8004
Oid typrelid = atooid(PQgetvalue(res, 0, i_typrelid));
8006
binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
8007
binary_upgrade_set_pg_class_oids(q, typrelid, false);
8010
appendPQExpBuffer(q, "CREATE TYPE %s AS (",
8011
fmtId(tyinfo->dobj.name));
8013
for (i = 0; i < ntups; i++)
8019
attname = PQgetvalue(res, i, i_attname);
8020
atttypdefn = PQgetvalue(res, i, i_atttypdefn);
8021
attcollation = atooid(PQgetvalue(res, i, i_attcollation));
8023
appendPQExpBuffer(q, "\n\t%s %s", fmtId(attname), atttypdefn);
8025
/* Add collation if not default for the column type */
8026
if (OidIsValid(attcollation))
8030
coll = findCollationByOid(attcollation);
8033
/* always schema-qualify, don't try to be smart */
8034
appendPQExpBuffer(q, " COLLATE %s.",
8035
fmtId(coll->dobj.namespace->dobj.name));
8036
appendPQExpBuffer(q, "%s",
8037
fmtId(coll->dobj.name));
8042
appendPQExpBuffer(q, ",");
8044
appendPQExpBuffer(q, "\n);\n");
8047
* DROP must be fully qualified in case same name appears in pg_catalog
8049
appendPQExpBuffer(delq, "DROP TYPE %s.",
8050
fmtId(tyinfo->dobj.namespace->dobj.name));
8051
appendPQExpBuffer(delq, "%s;\n",
8052
fmtId(tyinfo->dobj.name));
8054
appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
8057
binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
8059
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
8061
tyinfo->dobj.namespace->dobj.name,
8063
tyinfo->rolname, false,
8064
"TYPE", SECTION_PRE_DATA,
8065
q->data, delq->data, NULL,
8066
tyinfo->dobj.dependencies, tyinfo->dobj.nDeps,
8070
/* Dump Type Comments and Security Labels */
8071
dumpComment(fout, labelq->data,
8072
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
8073
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
8074
dumpSecLabel(fout, labelq->data,
8075
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
8076
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
8079
destroyPQExpBuffer(q);
8080
destroyPQExpBuffer(delq);
8081
destroyPQExpBuffer(labelq);
8082
destroyPQExpBuffer(query);
8084
/* Dump any per-column comments */
8085
dumpCompositeTypeColComments(fout, tyinfo);
8089
* dumpCompositeTypeColComments
8090
* writes out to fout the queries to recreate comments on the columns of
8091
* a user-defined stand-alone composite type
8094
dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo)
8096
CommentItem *comments;
8107
query = createPQExpBuffer();
8109
/* We assume here that remoteVersion must be at least 70300 */
8110
appendPQExpBuffer(query,
8111
"SELECT c.tableoid, a.attname, a.attnum "
8112
"FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a "
8113
"WHERE c.oid = '%u' AND c.oid = a.attrelid "
8114
" AND NOT a.attisdropped "
8115
"ORDER BY a.attnum ",
8118
/* Fetch column attnames */
8119
res = PQexec(g_conn, query->data);
8120
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
8122
ntups = PQntuples(res);
8126
destroyPQExpBuffer(query);
8130
pgClassOid = atooid(PQgetvalue(res, 0, PQfnumber(res, "tableoid")));
8132
/* Search for comments associated with type's pg_class OID */
8133
ncomments = findComments(fout,
8138
/* If no comments exist, we're done */
8142
destroyPQExpBuffer(query);
8146
/* Build COMMENT ON statements */
8147
target = createPQExpBuffer();
8149
i_attnum = PQfnumber(res, "attnum");
8150
i_attname = PQfnumber(res, "attname");
8151
while (ncomments > 0)
8153
const char *attname;
8156
for (i = 0; i < ntups; i++)
8158
if (atoi(PQgetvalue(res, i, i_attnum)) == comments->objsubid)
8160
attname = PQgetvalue(res, i, i_attname);
8164
if (attname) /* just in case we don't find it */
8166
const char *descr = comments->descr;
8168
resetPQExpBuffer(target);
8169
appendPQExpBuffer(target, "COLUMN %s.",
8170
fmtId(tyinfo->dobj.name));
8171
appendPQExpBuffer(target, "%s",
8174
resetPQExpBuffer(query);
8175
appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
8176
appendStringLiteralAH(query, descr, fout);
8177
appendPQExpBuffer(query, ";\n");
8179
ArchiveEntry(fout, nilCatalogId, createDumpId(),
8181
tyinfo->dobj.namespace->dobj.name,
8182
NULL, tyinfo->rolname,
8183
false, "COMMENT", SECTION_NONE,
8184
query->data, "", NULL,
8185
&(tyinfo->dobj.dumpId), 1,
8194
destroyPQExpBuffer(query);
8195
destroyPQExpBuffer(target);
8200
* writes out to fout the queries to create a shell type
8202
* We dump a shell definition in advance of the I/O functions for the type.
8205
dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
8209
/* Skip if not to be dumped */
8210
if (!stinfo->dobj.dump || dataOnly)
8213
q = createPQExpBuffer();
8216
* Note the lack of a DROP command for the shell type; any required DROP
8217
* is driven off the base type entry, instead. This interacts with
8218
* _printTocEntry()'s use of the presence of a DROP command to decide
8219
* whether an entry needs an ALTER OWNER command. We don't want to alter
8220
* the shell type's owner immediately on creation; that should happen only
8221
* after it's filled in, otherwise the backend complains.
8225
binary_upgrade_set_type_oids_by_type_oid(q,
8226
stinfo->baseType->dobj.catId.oid);
8228
appendPQExpBuffer(q, "CREATE TYPE %s;\n",
8229
fmtId(stinfo->dobj.name));
8231
ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
8233
stinfo->dobj.namespace->dobj.name,
8235
stinfo->baseType->rolname, false,
8236
"SHELL TYPE", SECTION_PRE_DATA,
8238
stinfo->dobj.dependencies, stinfo->dobj.nDeps,
8241
destroyPQExpBuffer(q);
8245
* Determine whether we want to dump definitions for procedural languages.
8246
* Since the languages themselves don't have schemas, we can't rely on
8247
* the normal schema-based selection mechanism. We choose to dump them
8248
* whenever neither --schema nor --table was given. (Before 8.1, we used
8249
* the dump flag of the PL's call handler function, but in 8.1 this will
8250
* probably always be false since call handlers are created in pg_catalog.)
8252
* For some backwards compatibility with the older behavior, we forcibly
8253
* dump a PL if its handler function (and validator if any) are in a
8254
* dumpable namespace. That case is not checked here.
8257
shouldDumpProcLangs(void)
8259
if (!include_everything)
8261
/* And they're schema not data */
8269
* writes out to fout the queries to recreate a user-defined
8270
* procedural language
8273
dumpProcLang(Archive *fout, ProcLangInfo *plang)
8282
FuncInfo *inlineInfo = NULL;
8283
FuncInfo *validatorInfo = NULL;
8285
/* Skip if not to be dumped */
8286
if (!plang->dobj.dump || dataOnly)
8290
* Try to find the support function(s). It is not an error if we don't
8291
* find them --- if the functions are in the pg_catalog schema, as is
8292
* standard in 8.1 and up, then we won't have loaded them. (In this case
8293
* we will emit a parameterless CREATE LANGUAGE command, which will
8294
* require PL template knowledge in the backend to reload.)
8297
funcInfo = findFuncByOid(plang->lanplcallfoid);
8298
if (funcInfo != NULL && !funcInfo->dobj.dump)
8299
funcInfo = NULL; /* treat not-dumped same as not-found */
8301
if (OidIsValid(plang->laninline))
8303
inlineInfo = findFuncByOid(plang->laninline);
8304
if (inlineInfo != NULL && !inlineInfo->dobj.dump)
8308
if (OidIsValid(plang->lanvalidator))
8310
validatorInfo = findFuncByOid(plang->lanvalidator);
8311
if (validatorInfo != NULL && !validatorInfo->dobj.dump)
8312
validatorInfo = NULL;
8316
* If the functions are dumpable then emit a traditional CREATE LANGUAGE
8317
* with parameters. Otherwise, dump only if shouldDumpProcLangs() says to
8320
useParams = (funcInfo != NULL &&
8321
(inlineInfo != NULL || !OidIsValid(plang->laninline)) &&
8322
(validatorInfo != NULL || !OidIsValid(plang->lanvalidator)));
8324
if (!useParams && !shouldDumpProcLangs())
8327
defqry = createPQExpBuffer();
8328
delqry = createPQExpBuffer();
8329
labelq = createPQExpBuffer();
8331
qlanname = strdup(fmtId(plang->dobj.name));
8334
* If dumping a HANDLER clause, treat the language as being in the handler
8335
* function's schema; this avoids cluttering the HANDLER clause. Otherwise
8336
* it doesn't really have a schema.
8339
lanschema = funcInfo->dobj.namespace->dobj.name;
8343
appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n",
8348
appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s",
8349
plang->lanpltrusted ? "TRUSTED " : "",
8351
appendPQExpBuffer(defqry, " HANDLER %s",
8352
fmtId(funcInfo->dobj.name));
8353
if (OidIsValid(plang->laninline))
8355
appendPQExpBuffer(defqry, " INLINE ");
8356
/* Cope with possibility that inline is in different schema */
8357
if (inlineInfo->dobj.namespace != funcInfo->dobj.namespace)
8358
appendPQExpBuffer(defqry, "%s.",
8359
fmtId(inlineInfo->dobj.namespace->dobj.name));
8360
appendPQExpBuffer(defqry, "%s",
8361
fmtId(inlineInfo->dobj.name));
8363
if (OidIsValid(plang->lanvalidator))
8365
appendPQExpBuffer(defqry, " VALIDATOR ");
8366
/* Cope with possibility that validator is in different schema */
8367
if (validatorInfo->dobj.namespace != funcInfo->dobj.namespace)
8368
appendPQExpBuffer(defqry, "%s.",
8369
fmtId(validatorInfo->dobj.namespace->dobj.name));
8370
appendPQExpBuffer(defqry, "%s",
8371
fmtId(validatorInfo->dobj.name));
8377
* If not dumping parameters, then use CREATE OR REPLACE so that the
8378
* command will not fail if the language is preinstalled in the target
8379
* database. We restrict the use of REPLACE to this case so as to
8380
* eliminate the risk of replacing a language with incompatible
8381
* parameter settings: this command will only succeed at all if there
8382
* is a pg_pltemplate entry, and if there is one, the existing entry
8383
* must match it too.
8385
appendPQExpBuffer(defqry, "CREATE OR REPLACE PROCEDURAL LANGUAGE %s",
8388
appendPQExpBuffer(defqry, ";\n");
8390
appendPQExpBuffer(labelq, "LANGUAGE %s", qlanname);
8393
binary_upgrade_extension_member(defqry, &plang->dobj, labelq->data);
8395
ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
8397
lanschema, NULL, plang->lanowner,
8398
false, "PROCEDURAL LANGUAGE", SECTION_PRE_DATA,
8399
defqry->data, delqry->data, NULL,
8400
plang->dobj.dependencies, plang->dobj.nDeps,
8403
/* Dump Proc Lang Comments and Security Labels */
8404
dumpComment(fout, labelq->data,
8406
plang->dobj.catId, 0, plang->dobj.dumpId);
8407
dumpSecLabel(fout, labelq->data,
8409
plang->dobj.catId, 0, plang->dobj.dumpId);
8411
if (plang->lanpltrusted)
8412
dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
8413
qlanname, NULL, plang->dobj.name,
8415
plang->lanowner, plang->lanacl);
8419
destroyPQExpBuffer(defqry);
8420
destroyPQExpBuffer(delqry);
8421
destroyPQExpBuffer(labelq);
8425
* format_function_arguments: generate function name and argument list
8427
* This is used when we can rely on pg_get_function_arguments to format
8428
* the argument list.
8431
format_function_arguments(FuncInfo *finfo, char *funcargs)
8435
initPQExpBuffer(&fn);
8436
appendPQExpBuffer(&fn, "%s(%s)", fmtId(finfo->dobj.name), funcargs);
8441
* format_function_arguments_old: generate function name and argument list
8443
* The argument type names are qualified if needed. The function name
8444
* is never qualified.
8446
* This is used only with pre-8.4 servers, so we aren't expecting to see
8447
* VARIADIC or TABLE arguments, nor are there any defaults for arguments.
8449
* Any or all of allargtypes, argmodes, argnames may be NULL.
8452
format_function_arguments_old(FuncInfo *finfo, int nallargs,
8460
initPQExpBuffer(&fn);
8461
appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
8462
for (j = 0; j < nallargs; j++)
8466
const char *argmode;
8467
const char *argname;
8469
typid = allargtypes ? atooid(allargtypes[j]) : finfo->argtypes[j];
8470
typname = getFormattedTypeName(typid, zeroAsOpaque);
8474
switch (argmodes[j][0])
8479
case PROARGMODE_OUT:
8482
case PROARGMODE_INOUT:
8486
write_msg(NULL, "WARNING: bogus value in proargmodes array\n");
8494
argname = argnames ? argnames[j] : (char *) NULL;
8495
if (argname && argname[0] == '\0')
8498
appendPQExpBuffer(&fn, "%s%s%s%s%s",
8499
(j > 0) ? ", " : "",
8501
argname ? fmtId(argname) : "",
8506
appendPQExpBuffer(&fn, ")");
8511
* format_function_signature: generate function name and argument list
8513
* This is like format_function_arguments_old except that only a minimal
8514
* list of input argument types is generated; this is sufficient to
8515
* reference the function, but not to define it.
8517
* If honor_quotes is false then the function name is never quoted.
8518
* This is appropriate for use in TOC tags, but not in SQL commands.
8521
format_function_signature(FuncInfo *finfo, bool honor_quotes)
8526
initPQExpBuffer(&fn);
8528
appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
8530
appendPQExpBuffer(&fn, "%s(", finfo->dobj.name);
8531
for (j = 0; j < finfo->nargs; j++)
8535
typname = getFormattedTypeName(finfo->argtypes[j], zeroAsOpaque);
8537
appendPQExpBuffer(&fn, "%s%s",
8538
(j > 0) ? ", " : "",
8542
appendPQExpBuffer(&fn, ")");
8549
* dump out one function
8552
dumpFunc(Archive *fout, FuncInfo *finfo)
8560
char *funcsig; /* identity signature */
8561
char *funcfullsig; /* full signature */
8570
char *proallargtypes;
8583
char **allargtypes = NULL;
8584
char **argmodes = NULL;
8585
char **argnames = NULL;
8586
char **configitems = NULL;
8587
int nconfigitems = 0;
8590
/* Skip if not to be dumped */
8591
if (!finfo->dobj.dump || dataOnly)
8594
query = createPQExpBuffer();
8595
q = createPQExpBuffer();
8596
delqry = createPQExpBuffer();
8597
labelq = createPQExpBuffer();
8598
asPart = createPQExpBuffer();
8600
/* Set proper schema search path so type references list correctly */
8601
selectSourceSchema(finfo->dobj.namespace->dobj.name);
8603
/* Fetch function-specific details */
8604
if (g_fout->remoteVersion >= 80400)
8607
* In 8.4 and up we rely on pg_get_function_arguments and
8608
* pg_get_function_result instead of examining proallargtypes etc.
8610
appendPQExpBuffer(query,
8611
"SELECT proretset, prosrc, probin, "
8612
"pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
8613
"pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
8614
"pg_catalog.pg_get_function_result(oid) AS funcresult, "
8615
"proiswindow, provolatile, proisstrict, prosecdef, "
8616
"proconfig, procost, prorows, "
8617
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
8618
"FROM pg_catalog.pg_proc "
8619
"WHERE oid = '%u'::pg_catalog.oid",
8620
finfo->dobj.catId.oid);
8622
else if (g_fout->remoteVersion >= 80300)
8624
appendPQExpBuffer(query,
8625
"SELECT proretset, prosrc, probin, "
8626
"proallargtypes, proargmodes, proargnames, "
8627
"false AS proiswindow, "
8628
"provolatile, proisstrict, prosecdef, "
8629
"proconfig, procost, prorows, "
8630
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
8631
"FROM pg_catalog.pg_proc "
8632
"WHERE oid = '%u'::pg_catalog.oid",
8633
finfo->dobj.catId.oid);
8635
else if (g_fout->remoteVersion >= 80100)
8637
appendPQExpBuffer(query,
8638
"SELECT proretset, prosrc, probin, "
8639
"proallargtypes, proargmodes, proargnames, "
8640
"false AS proiswindow, "
8641
"provolatile, proisstrict, prosecdef, "
8642
"null AS proconfig, 0 AS procost, 0 AS prorows, "
8643
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
8644
"FROM pg_catalog.pg_proc "
8645
"WHERE oid = '%u'::pg_catalog.oid",
8646
finfo->dobj.catId.oid);
8648
else if (g_fout->remoteVersion >= 80000)
8650
appendPQExpBuffer(query,
8651
"SELECT proretset, prosrc, probin, "
8652
"null AS proallargtypes, "
8653
"null AS proargmodes, "
8655
"false AS proiswindow, "
8656
"provolatile, proisstrict, prosecdef, "
8657
"null AS proconfig, 0 AS procost, 0 AS prorows, "
8658
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
8659
"FROM pg_catalog.pg_proc "
8660
"WHERE oid = '%u'::pg_catalog.oid",
8661
finfo->dobj.catId.oid);
8663
else if (g_fout->remoteVersion >= 70300)
8665
appendPQExpBuffer(query,
8666
"SELECT proretset, prosrc, probin, "
8667
"null AS proallargtypes, "
8668
"null AS proargmodes, "
8669
"null AS proargnames, "
8670
"false AS proiswindow, "
8671
"provolatile, proisstrict, prosecdef, "
8672
"null AS proconfig, 0 AS procost, 0 AS prorows, "
8673
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
8674
"FROM pg_catalog.pg_proc "
8675
"WHERE oid = '%u'::pg_catalog.oid",
8676
finfo->dobj.catId.oid);
8678
else if (g_fout->remoteVersion >= 70100)
8680
appendPQExpBuffer(query,
8681
"SELECT proretset, prosrc, probin, "
8682
"null AS proallargtypes, "
8683
"null AS proargmodes, "
8684
"null AS proargnames, "
8685
"false AS proiswindow, "
8686
"case when proiscachable then 'i' else 'v' end AS provolatile, "
8688
"false AS prosecdef, "
8689
"null AS proconfig, 0 AS procost, 0 AS prorows, "
8690
"(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname "
8692
"WHERE oid = '%u'::oid",
8693
finfo->dobj.catId.oid);
8697
appendPQExpBuffer(query,
8698
"SELECT proretset, prosrc, probin, "
8699
"null AS proallargtypes, "
8700
"null AS proargmodes, "
8701
"null AS proargnames, "
8702
"false AS proiswindow, "
8703
"CASE WHEN proiscachable THEN 'i' ELSE 'v' END AS provolatile, "
8704
"false AS proisstrict, "
8705
"false AS prosecdef, "
8706
"NULL AS proconfig, 0 AS procost, 0 AS prorows, "
8707
"(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname "
8709
"WHERE oid = '%u'::oid",
8710
finfo->dobj.catId.oid);
8713
res = PQexec(g_conn, query->data);
8714
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
8716
/* Expecting a single result only */
8717
ntups = PQntuples(res);
8720
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
8721
"query returned %d rows instead of one: %s\n",
8723
ntups, query->data);
8727
proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset"));
8728
prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
8729
probin = PQgetvalue(res, 0, PQfnumber(res, "probin"));
8730
if (g_fout->remoteVersion >= 80400)
8732
funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs"));
8733
funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs"));
8734
funcresult = PQgetvalue(res, 0, PQfnumber(res, "funcresult"));
8735
proallargtypes = proargmodes = proargnames = NULL;
8739
proallargtypes = PQgetvalue(res, 0, PQfnumber(res, "proallargtypes"));
8740
proargmodes = PQgetvalue(res, 0, PQfnumber(res, "proargmodes"));
8741
proargnames = PQgetvalue(res, 0, PQfnumber(res, "proargnames"));
8742
funcargs = funciargs = funcresult = NULL;
8744
proiswindow = PQgetvalue(res, 0, PQfnumber(res, "proiswindow"));
8745
provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
8746
proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
8747
prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
8748
proconfig = PQgetvalue(res, 0, PQfnumber(res, "proconfig"));
8749
procost = PQgetvalue(res, 0, PQfnumber(res, "procost"));
8750
prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
8751
lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
8754
* See backend/commands/functioncmds.c for details of how the 'AS' clause
8755
* is used. In 8.4 and up, an unused probin is NULL (here ""); previous
8756
* versions would set it to "-". There are no known cases in which prosrc
8757
* is unused, so the tests below for "-" are probably useless.
8759
if (probin[0] != '\0' && strcmp(probin, "-") != 0)
8761
appendPQExpBuffer(asPart, "AS ");
8762
appendStringLiteralAH(asPart, probin, fout);
8763
if (strcmp(prosrc, "-") != 0)
8765
appendPQExpBuffer(asPart, ", ");
8768
* where we have bin, use dollar quoting if allowed and src
8769
* contains quote or backslash; else use regular quoting.
8771
if (disable_dollar_quoting ||
8772
(strchr(prosrc, '\'') == NULL && strchr(prosrc, '\\') == NULL))
8773
appendStringLiteralAH(asPart, prosrc, fout);
8775
appendStringLiteralDQ(asPart, prosrc, NULL);
8780
if (strcmp(prosrc, "-") != 0)
8782
appendPQExpBuffer(asPart, "AS ");
8783
/* with no bin, dollar quote src unconditionally if allowed */
8784
if (disable_dollar_quoting)
8785
appendStringLiteralAH(asPart, prosrc, fout);
8787
appendStringLiteralDQ(asPart, prosrc, NULL);
8791
nallargs = finfo->nargs; /* unless we learn different from allargs */
8793
if (proallargtypes && *proallargtypes)
8797
if (!parsePGArray(proallargtypes, &allargtypes, &nitems) ||
8798
nitems < finfo->nargs)
8800
write_msg(NULL, "WARNING: could not parse proallargtypes array\n");
8809
if (proargmodes && *proargmodes)
8813
if (!parsePGArray(proargmodes, &argmodes, &nitems) ||
8816
write_msg(NULL, "WARNING: could not parse proargmodes array\n");
8823
if (proargnames && *proargnames)
8827
if (!parsePGArray(proargnames, &argnames, &nitems) ||
8830
write_msg(NULL, "WARNING: could not parse proargnames array\n");
8837
if (proconfig && *proconfig)
8839
if (!parsePGArray(proconfig, &configitems, &nconfigitems))
8841
write_msg(NULL, "WARNING: could not parse proconfig array\n");
8851
/* 8.4 or later; we rely on server-side code for most of the work */
8852
funcfullsig = format_function_arguments(finfo, funcargs);
8853
funcsig = format_function_arguments(finfo, funciargs);
8857
/* pre-8.4, do it ourselves */
8858
funcsig = format_function_arguments_old(finfo, nallargs, allargtypes,
8859
argmodes, argnames);
8860
funcfullsig = funcsig;
8863
funcsig_tag = format_function_signature(finfo, false);
8866
* DROP must be fully qualified in case same name appears in pg_catalog
8868
appendPQExpBuffer(delqry, "DROP FUNCTION %s.%s;\n",
8869
fmtId(finfo->dobj.namespace->dobj.name),
8872
appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcfullsig);
8874
appendPQExpBuffer(q, "RETURNS %s", funcresult);
8877
rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque);
8878
appendPQExpBuffer(q, "RETURNS %s%s",
8879
(proretset[0] == 't') ? "SETOF " : "",
8884
appendPQExpBuffer(q, "\n LANGUAGE %s", fmtId(lanname));
8886
if (proiswindow[0] == 't')
8887
appendPQExpBuffer(q, " WINDOW");
8889
if (provolatile[0] != PROVOLATILE_VOLATILE)
8891
if (provolatile[0] == PROVOLATILE_IMMUTABLE)
8892
appendPQExpBuffer(q, " IMMUTABLE");
8893
else if (provolatile[0] == PROVOLATILE_STABLE)
8894
appendPQExpBuffer(q, " STABLE");
8895
else if (provolatile[0] != PROVOLATILE_VOLATILE)
8897
write_msg(NULL, "unrecognized provolatile value for function \"%s\"\n",
8903
if (proisstrict[0] == 't')
8904
appendPQExpBuffer(q, " STRICT");
8906
if (prosecdef[0] == 't')
8907
appendPQExpBuffer(q, " SECURITY DEFINER");
8910
* COST and ROWS are emitted only if present and not default, so as not to
8911
* break backwards-compatibility of the dump without need. Keep this code
8912
* in sync with the defaults in functioncmds.c.
8914
if (strcmp(procost, "0") != 0)
8916
if (strcmp(lanname, "internal") == 0 || strcmp(lanname, "c") == 0)
8918
/* default cost is 1 */
8919
if (strcmp(procost, "1") != 0)
8920
appendPQExpBuffer(q, " COST %s", procost);
8924
/* default cost is 100 */
8925
if (strcmp(procost, "100") != 0)
8926
appendPQExpBuffer(q, " COST %s", procost);
8929
if (proretset[0] == 't' &&
8930
strcmp(prorows, "0") != 0 && strcmp(prorows, "1000") != 0)
8931
appendPQExpBuffer(q, " ROWS %s", prorows);
8933
for (i = 0; i < nconfigitems; i++)
8935
/* we feel free to scribble on configitems[] here */
8936
char *configitem = configitems[i];
8939
pos = strchr(configitem, '=');
8943
appendPQExpBuffer(q, "\n SET %s TO ", fmtId(configitem));
8946
* Some GUC variable names are 'LIST' type and hence must not be
8949
if (pg_strcasecmp(configitem, "DateStyle") == 0
8950
|| pg_strcasecmp(configitem, "search_path") == 0)
8951
appendPQExpBuffer(q, "%s", pos);
8953
appendStringLiteralAH(q, pos, fout);
8956
appendPQExpBuffer(q, "\n %s;\n", asPart->data);
8958
appendPQExpBuffer(labelq, "FUNCTION %s", funcsig);
8961
binary_upgrade_extension_member(q, &finfo->dobj, labelq->data);
8963
ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
8965
finfo->dobj.namespace->dobj.name,
8967
finfo->rolname, false,
8968
"FUNCTION", SECTION_PRE_DATA,
8969
q->data, delqry->data, NULL,
8970
finfo->dobj.dependencies, finfo->dobj.nDeps,
8973
/* Dump Function Comments and Security Labels */
8974
dumpComment(fout, labelq->data,
8975
finfo->dobj.namespace->dobj.name, finfo->rolname,
8976
finfo->dobj.catId, 0, finfo->dobj.dumpId);
8977
dumpSecLabel(fout, labelq->data,
8978
finfo->dobj.namespace->dobj.name, finfo->rolname,
8979
finfo->dobj.catId, 0, finfo->dobj.dumpId);
8981
dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, "FUNCTION",
8982
funcsig, NULL, funcsig_tag,
8983
finfo->dobj.namespace->dobj.name,
8984
finfo->rolname, finfo->proacl);
8988
destroyPQExpBuffer(query);
8989
destroyPQExpBuffer(q);
8990
destroyPQExpBuffer(delqry);
8991
destroyPQExpBuffer(labelq);
8992
destroyPQExpBuffer(asPart);
9007
* Dump a user-defined cast
9010
dumpCast(Archive *fout, CastInfo *cast)
9015
FuncInfo *funcInfo = NULL;
9016
TypeInfo *sourceInfo;
9017
TypeInfo *targetInfo;
9019
/* Skip if not to be dumped */
9020
if (!cast->dobj.dump || dataOnly)
9023
if (OidIsValid(cast->castfunc))
9025
funcInfo = findFuncByOid(cast->castfunc);
9026
if (funcInfo == NULL)
9031
* As per discussion we dump casts if one or more of the underlying
9032
* objects (the conversion function and the two data types) are not
9033
* builtin AND if all of the non-builtin objects are included in the dump.
9034
* Builtin meaning, the namespace name does not start with "pg_".
9036
sourceInfo = findTypeByOid(cast->castsource);
9037
targetInfo = findTypeByOid(cast->casttarget);
9039
if (sourceInfo == NULL || targetInfo == NULL)
9043
* Skip this cast if all objects are from pg_
9045
if ((funcInfo == NULL ||
9046
strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) == 0) &&
9047
strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) == 0 &&
9048
strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) == 0)
9052
* Skip cast if function isn't from pg_ and is not to be dumped.
9055
strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
9056
!funcInfo->dobj.dump)
9060
* Same for the source type
9062
if (strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
9063
!sourceInfo->dobj.dump)
9067
* and the target type.
9069
if (strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
9070
!targetInfo->dobj.dump)
9073
/* Make sure we are in proper schema (needed for getFormattedTypeName) */
9074
selectSourceSchema("pg_catalog");
9076
defqry = createPQExpBuffer();
9077
delqry = createPQExpBuffer();
9078
labelq = createPQExpBuffer();
9080
appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n",
9081
getFormattedTypeName(cast->castsource, zeroAsNone),
9082
getFormattedTypeName(cast->casttarget, zeroAsNone));
9084
appendPQExpBuffer(defqry, "CREATE CAST (%s AS %s) ",
9085
getFormattedTypeName(cast->castsource, zeroAsNone),
9086
getFormattedTypeName(cast->casttarget, zeroAsNone));
9088
switch (cast->castmethod)
9090
case COERCION_METHOD_BINARY:
9091
appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
9093
case COERCION_METHOD_INOUT:
9094
appendPQExpBuffer(defqry, "WITH INOUT");
9096
case COERCION_METHOD_FUNCTION:
9099
* Always qualify the function name, in case it is not in
9100
* pg_catalog schema (format_function_signature won't qualify it).
9102
appendPQExpBuffer(defqry, "WITH FUNCTION %s.",
9103
fmtId(funcInfo->dobj.namespace->dobj.name));
9104
appendPQExpBuffer(defqry, "%s",
9105
format_function_signature(funcInfo, true));
9108
write_msg(NULL, "WARNING: bogus value in pg_cast.castmethod field\n");
9111
if (cast->castcontext == 'a')
9112
appendPQExpBuffer(defqry, " AS ASSIGNMENT");
9113
else if (cast->castcontext == 'i')
9114
appendPQExpBuffer(defqry, " AS IMPLICIT");
9115
appendPQExpBuffer(defqry, ";\n");
9117
appendPQExpBuffer(labelq, "CAST (%s AS %s)",
9118
getFormattedTypeName(cast->castsource, zeroAsNone),
9119
getFormattedTypeName(cast->casttarget, zeroAsNone));
9122
binary_upgrade_extension_member(defqry, &cast->dobj, labelq->data);
9124
ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
9126
"pg_catalog", NULL, "",
9127
false, "CAST", SECTION_PRE_DATA,
9128
defqry->data, delqry->data, NULL,
9129
cast->dobj.dependencies, cast->dobj.nDeps,
9132
/* Dump Cast Comments */
9133
dumpComment(fout, labelq->data,
9135
cast->dobj.catId, 0, cast->dobj.dumpId);
9137
destroyPQExpBuffer(defqry);
9138
destroyPQExpBuffer(delqry);
9139
destroyPQExpBuffer(labelq);
9144
* write out a single operator definition
9147
dumpOpr(Archive *fout, OprInfo *oprinfo)
9154
PQExpBuffer details;
9179
/* Skip if not to be dumped */
9180
if (!oprinfo->dobj.dump || dataOnly)
9184
* some operators are invalid because they were the result of user
9185
* defining operators before commutators exist
9187
if (!OidIsValid(oprinfo->oprcode))
9190
query = createPQExpBuffer();
9191
q = createPQExpBuffer();
9192
delq = createPQExpBuffer();
9193
labelq = createPQExpBuffer();
9194
oprid = createPQExpBuffer();
9195
details = createPQExpBuffer();
9197
/* Make sure we are in proper schema so regoperator works correctly */
9198
selectSourceSchema(oprinfo->dobj.namespace->dobj.name);
9200
if (g_fout->remoteVersion >= 80300)
9202
appendPQExpBuffer(query, "SELECT oprkind, "
9203
"oprcode::pg_catalog.regprocedure, "
9204
"oprleft::pg_catalog.regtype, "
9205
"oprright::pg_catalog.regtype, "
9206
"oprcom::pg_catalog.regoperator, "
9207
"oprnegate::pg_catalog.regoperator, "
9208
"oprrest::pg_catalog.regprocedure, "
9209
"oprjoin::pg_catalog.regprocedure, "
9210
"oprcanmerge, oprcanhash "
9211
"FROM pg_catalog.pg_operator "
9212
"WHERE oid = '%u'::pg_catalog.oid",
9213
oprinfo->dobj.catId.oid);
9215
else if (g_fout->remoteVersion >= 70300)
9217
appendPQExpBuffer(query, "SELECT oprkind, "
9218
"oprcode::pg_catalog.regprocedure, "
9219
"oprleft::pg_catalog.regtype, "
9220
"oprright::pg_catalog.regtype, "
9221
"oprcom::pg_catalog.regoperator, "
9222
"oprnegate::pg_catalog.regoperator, "
9223
"oprrest::pg_catalog.regprocedure, "
9224
"oprjoin::pg_catalog.regprocedure, "
9225
"(oprlsortop != 0) AS oprcanmerge, "
9227
"FROM pg_catalog.pg_operator "
9228
"WHERE oid = '%u'::pg_catalog.oid",
9229
oprinfo->dobj.catId.oid);
9231
else if (g_fout->remoteVersion >= 70100)
9233
appendPQExpBuffer(query, "SELECT oprkind, oprcode, "
9234
"CASE WHEN oprleft = 0 THEN '-' "
9235
"ELSE format_type(oprleft, NULL) END AS oprleft, "
9236
"CASE WHEN oprright = 0 THEN '-' "
9237
"ELSE format_type(oprright, NULL) END AS oprright, "
9238
"oprcom, oprnegate, oprrest, oprjoin, "
9239
"(oprlsortop != 0) AS oprcanmerge, "
9242
"WHERE oid = '%u'::oid",
9243
oprinfo->dobj.catId.oid);
9247
appendPQExpBuffer(query, "SELECT oprkind, oprcode, "
9248
"CASE WHEN oprleft = 0 THEN '-'::name "
9249
"ELSE (SELECT typname FROM pg_type WHERE oid = oprleft) END AS oprleft, "
9250
"CASE WHEN oprright = 0 THEN '-'::name "
9251
"ELSE (SELECT typname FROM pg_type WHERE oid = oprright) END AS oprright, "
9252
"oprcom, oprnegate, oprrest, oprjoin, "
9253
"(oprlsortop != 0) AS oprcanmerge, "
9256
"WHERE oid = '%u'::oid",
9257
oprinfo->dobj.catId.oid);
9260
res = PQexec(g_conn, query->data);
9261
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9263
/* Expecting a single result only */
9264
ntups = PQntuples(res);
9267
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
9268
"query returned %d rows instead of one: %s\n",
9270
ntups, query->data);
9274
i_oprkind = PQfnumber(res, "oprkind");
9275
i_oprcode = PQfnumber(res, "oprcode");
9276
i_oprleft = PQfnumber(res, "oprleft");
9277
i_oprright = PQfnumber(res, "oprright");
9278
i_oprcom = PQfnumber(res, "oprcom");
9279
i_oprnegate = PQfnumber(res, "oprnegate");
9280
i_oprrest = PQfnumber(res, "oprrest");
9281
i_oprjoin = PQfnumber(res, "oprjoin");
9282
i_oprcanmerge = PQfnumber(res, "oprcanmerge");
9283
i_oprcanhash = PQfnumber(res, "oprcanhash");
9285
oprkind = PQgetvalue(res, 0, i_oprkind);
9286
oprcode = PQgetvalue(res, 0, i_oprcode);
9287
oprleft = PQgetvalue(res, 0, i_oprleft);
9288
oprright = PQgetvalue(res, 0, i_oprright);
9289
oprcom = PQgetvalue(res, 0, i_oprcom);
9290
oprnegate = PQgetvalue(res, 0, i_oprnegate);
9291
oprrest = PQgetvalue(res, 0, i_oprrest);
9292
oprjoin = PQgetvalue(res, 0, i_oprjoin);
9293
oprcanmerge = PQgetvalue(res, 0, i_oprcanmerge);
9294
oprcanhash = PQgetvalue(res, 0, i_oprcanhash);
9296
appendPQExpBuffer(details, " PROCEDURE = %s",
9297
convertRegProcReference(oprcode));
9299
appendPQExpBuffer(oprid, "%s (",
9300
oprinfo->dobj.name);
9303
* right unary means there's a left arg and left unary means there's a
9306
if (strcmp(oprkind, "r") == 0 ||
9307
strcmp(oprkind, "b") == 0)
9309
if (g_fout->remoteVersion >= 70100)
9312
name = fmtId(oprleft);
9313
appendPQExpBuffer(details, ",\n LEFTARG = %s", name);
9314
appendPQExpBuffer(oprid, "%s", name);
9317
appendPQExpBuffer(oprid, "NONE");
9319
if (strcmp(oprkind, "l") == 0 ||
9320
strcmp(oprkind, "b") == 0)
9322
if (g_fout->remoteVersion >= 70100)
9325
name = fmtId(oprright);
9326
appendPQExpBuffer(details, ",\n RIGHTARG = %s", name);
9327
appendPQExpBuffer(oprid, ", %s)", name);
9330
appendPQExpBuffer(oprid, ", NONE)");
9332
name = convertOperatorReference(oprcom);
9334
appendPQExpBuffer(details, ",\n COMMUTATOR = %s", name);
9336
name = convertOperatorReference(oprnegate);
9338
appendPQExpBuffer(details, ",\n NEGATOR = %s", name);
9340
if (strcmp(oprcanmerge, "t") == 0)
9341
appendPQExpBuffer(details, ",\n MERGES");
9343
if (strcmp(oprcanhash, "t") == 0)
9344
appendPQExpBuffer(details, ",\n HASHES");
9346
name = convertRegProcReference(oprrest);
9348
appendPQExpBuffer(details, ",\n RESTRICT = %s", name);
9350
name = convertRegProcReference(oprjoin);
9352
appendPQExpBuffer(details, ",\n JOIN = %s", name);
9355
* DROP must be fully qualified in case same name appears in pg_catalog
9357
appendPQExpBuffer(delq, "DROP OPERATOR %s.%s;\n",
9358
fmtId(oprinfo->dobj.namespace->dobj.name),
9361
appendPQExpBuffer(q, "CREATE OPERATOR %s (\n%s\n);\n",
9362
oprinfo->dobj.name, details->data);
9364
appendPQExpBuffer(labelq, "OPERATOR %s", oprid->data);
9367
binary_upgrade_extension_member(q, &oprinfo->dobj, labelq->data);
9369
ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId,
9371
oprinfo->dobj.namespace->dobj.name,
9374
false, "OPERATOR", SECTION_PRE_DATA,
9375
q->data, delq->data, NULL,
9376
oprinfo->dobj.dependencies, oprinfo->dobj.nDeps,
9379
/* Dump Operator Comments */
9380
dumpComment(fout, labelq->data,
9381
oprinfo->dobj.namespace->dobj.name, oprinfo->rolname,
9382
oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId);
9386
destroyPQExpBuffer(query);
9387
destroyPQExpBuffer(q);
9388
destroyPQExpBuffer(delq);
9389
destroyPQExpBuffer(labelq);
9390
destroyPQExpBuffer(oprid);
9391
destroyPQExpBuffer(details);
9395
* Convert a function reference obtained from pg_operator
9397
* Returns what to print, or NULL if function references is InvalidOid
9399
* In 7.3 the input is a REGPROCEDURE display; we have to strip the
9400
* argument-types part. In prior versions, the input is a REGPROC display.
9403
convertRegProcReference(const char *proc)
9405
/* In all cases "-" means a null reference */
9406
if (strcmp(proc, "-") == 0)
9409
if (g_fout->remoteVersion >= 70300)
9415
name = strdup(proc);
9416
/* find non-double-quoted left paren */
9418
for (paren = name; *paren; paren++)
9420
if (*paren == '(' && !inquote)
9431
/* REGPROC before 7.3 does not quote its result */
9436
* Convert an operator cross-reference obtained from pg_operator
9438
* Returns what to print, or NULL to print nothing
9440
* In 7.3 and up the input is a REGOPERATOR display; we have to strip the
9441
* argument-types part, and add OPERATOR() decoration if the name is
9442
* schema-qualified. In older versions, the input is just a numeric OID,
9443
* which we search our operator list for.
9446
convertOperatorReference(const char *opr)
9450
/* In all cases "0" means a null reference */
9451
if (strcmp(opr, "0") == 0)
9454
if (g_fout->remoteVersion >= 70300)
9463
/* find non-double-quoted left paren, and check for non-quoted dot */
9466
for (ptr = name; *ptr; ptr++)
9470
else if (*ptr == '.' && !inquote)
9472
else if (*ptr == '(' && !inquote)
9478
/* If not schema-qualified, don't need to add OPERATOR() */
9481
oname = malloc(strlen(name) + 11);
9482
sprintf(oname, "OPERATOR(%s)", name);
9487
oprInfo = findOprByOid(atooid(opr));
9488
if (oprInfo == NULL)
9490
write_msg(NULL, "WARNING: could not find operator with OID %s\n",
9494
return oprInfo->dobj.name;
9498
* Convert a function OID obtained from pg_ts_parser or pg_ts_template
9500
* It is sufficient to use REGPROC rather than REGPROCEDURE, since the
9501
* argument lists of these functions are predetermined. Note that the
9502
* caller should ensure we are in the proper schema, because the results
9503
* are search path dependent!
9506
convertTSFunction(Oid funcOid)
9513
snprintf(query, sizeof(query),
9514
"SELECT '%u'::pg_catalog.regproc", funcOid);
9515
res = PQexec(g_conn, query);
9516
check_sql_result(res, g_conn, query, PGRES_TUPLES_OK);
9518
ntups = PQntuples(res);
9521
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
9522
"query returned %d rows instead of one: %s\n",
9528
result = strdup(PQgetvalue(res, 0, 0));
9538
* write out a single operator class definition
9541
dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
9553
int i_opcfamilyname;
9560
int i_sortfamilynsp;
9567
char *opcfamilyname;
9574
char *sortfamilynsp;
9580
/* Skip if not to be dumped */
9581
if (!opcinfo->dobj.dump || dataOnly)
9585
* XXX currently we do not implement dumping of operator classes from
9586
* pre-7.3 databases. This could be done but it seems not worth the
9589
if (g_fout->remoteVersion < 70300)
9592
query = createPQExpBuffer();
9593
q = createPQExpBuffer();
9594
delq = createPQExpBuffer();
9595
labelq = createPQExpBuffer();
9597
/* Make sure we are in proper schema so regoperator works correctly */
9598
selectSourceSchema(opcinfo->dobj.namespace->dobj.name);
9600
/* Get additional fields from the pg_opclass row */
9601
if (g_fout->remoteVersion >= 80300)
9603
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
9604
"opckeytype::pg_catalog.regtype, "
9605
"opcdefault, opcfamily, "
9606
"opfname AS opcfamilyname, "
9607
"nspname AS opcfamilynsp, "
9608
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
9609
"FROM pg_catalog.pg_opclass c "
9610
"LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
9611
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
9612
"WHERE c.oid = '%u'::pg_catalog.oid",
9613
opcinfo->dobj.catId.oid);
9617
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
9618
"opckeytype::pg_catalog.regtype, "
9619
"opcdefault, NULL AS opcfamily, "
9620
"NULL AS opcfamilyname, "
9621
"NULL AS opcfamilynsp, "
9622
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
9623
"FROM pg_catalog.pg_opclass "
9624
"WHERE oid = '%u'::pg_catalog.oid",
9625
opcinfo->dobj.catId.oid);
9628
res = PQexec(g_conn, query->data);
9629
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9631
/* Expecting a single result only */
9632
ntups = PQntuples(res);
9635
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
9636
"query returned %d rows instead of one: %s\n",
9638
ntups, query->data);
9642
i_opcintype = PQfnumber(res, "opcintype");
9643
i_opckeytype = PQfnumber(res, "opckeytype");
9644
i_opcdefault = PQfnumber(res, "opcdefault");
9645
i_opcfamily = PQfnumber(res, "opcfamily");
9646
i_opcfamilyname = PQfnumber(res, "opcfamilyname");
9647
i_opcfamilynsp = PQfnumber(res, "opcfamilynsp");
9648
i_amname = PQfnumber(res, "amname");
9650
opcintype = PQgetvalue(res, 0, i_opcintype);
9651
opckeytype = PQgetvalue(res, 0, i_opckeytype);
9652
opcdefault = PQgetvalue(res, 0, i_opcdefault);
9653
/* opcfamily will still be needed after we PQclear res */
9654
opcfamily = strdup(PQgetvalue(res, 0, i_opcfamily));
9655
opcfamilyname = PQgetvalue(res, 0, i_opcfamilyname);
9656
opcfamilynsp = PQgetvalue(res, 0, i_opcfamilynsp);
9657
/* amname will still be needed after we PQclear res */
9658
amname = strdup(PQgetvalue(res, 0, i_amname));
9661
* DROP must be fully qualified in case same name appears in pg_catalog
9663
appendPQExpBuffer(delq, "DROP OPERATOR CLASS %s",
9664
fmtId(opcinfo->dobj.namespace->dobj.name));
9665
appendPQExpBuffer(delq, ".%s",
9666
fmtId(opcinfo->dobj.name));
9667
appendPQExpBuffer(delq, " USING %s;\n",
9670
/* Build the fixed portion of the CREATE command */
9671
appendPQExpBuffer(q, "CREATE OPERATOR CLASS %s\n ",
9672
fmtId(opcinfo->dobj.name));
9673
if (strcmp(opcdefault, "t") == 0)
9674
appendPQExpBuffer(q, "DEFAULT ");
9675
appendPQExpBuffer(q, "FOR TYPE %s USING %s",
9678
if (strlen(opcfamilyname) > 0 &&
9679
(strcmp(opcfamilyname, opcinfo->dobj.name) != 0 ||
9680
strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0))
9682
appendPQExpBuffer(q, " FAMILY ");
9683
if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
9684
appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
9685
appendPQExpBuffer(q, "%s", fmtId(opcfamilyname));
9687
appendPQExpBuffer(q, " AS\n ");
9691
if (strcmp(opckeytype, "-") != 0)
9693
appendPQExpBuffer(q, "STORAGE %s",
9701
* Now fetch and print the OPERATOR entries (pg_amop rows).
9703
* Print only those opfamily members that are tied to the opclass by
9704
* pg_depend entries.
9706
* XXX RECHECK is gone as of 8.4, but we'll still print it if dumping an
9707
* older server's opclass in which it is used. This is to avoid
9708
* hard-to-detect breakage if a newer pg_dump is used to dump from an
9709
* older server and then reload into that old version. This can go away
9710
* once 8.3 is so old as to not be of interest to anyone.
9712
resetPQExpBuffer(query);
9714
if (g_fout->remoteVersion >= 90100)
9716
appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
9717
"amopopr::pg_catalog.regoperator, "
9718
"opfname AS sortfamily, "
9719
"nspname AS sortfamilynsp "
9720
"FROM pg_catalog.pg_amop ao JOIN pg_catalog.pg_depend ON "
9721
"(classid = 'pg_catalog.pg_amop'::pg_catalog.regclass AND objid = ao.oid) "
9722
"LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = amopsortfamily "
9723
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
9724
"WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
9725
"AND refobjid = '%u'::pg_catalog.oid "
9726
"AND amopfamily = '%s'::pg_catalog.oid "
9727
"ORDER BY amopstrategy",
9728
opcinfo->dobj.catId.oid,
9731
else if (g_fout->remoteVersion >= 80400)
9733
appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
9734
"amopopr::pg_catalog.regoperator, "
9735
"NULL AS sortfamily, "
9736
"NULL AS sortfamilynsp "
9737
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
9738
"WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
9739
"AND refobjid = '%u'::pg_catalog.oid "
9740
"AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
9741
"AND objid = ao.oid "
9742
"ORDER BY amopstrategy",
9743
opcinfo->dobj.catId.oid);
9745
else if (g_fout->remoteVersion >= 80300)
9747
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
9748
"amopopr::pg_catalog.regoperator, "
9749
"NULL AS sortfamily, "
9750
"NULL AS sortfamilynsp "
9751
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
9752
"WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
9753
"AND refobjid = '%u'::pg_catalog.oid "
9754
"AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
9755
"AND objid = ao.oid "
9756
"ORDER BY amopstrategy",
9757
opcinfo->dobj.catId.oid);
9762
* Here, we print all entries since there are no opfamilies and hence
9763
* no loose operators to worry about.
9765
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
9766
"amopopr::pg_catalog.regoperator, "
9767
"NULL AS sortfamily, "
9768
"NULL AS sortfamilynsp "
9769
"FROM pg_catalog.pg_amop "
9770
"WHERE amopclaid = '%u'::pg_catalog.oid "
9771
"ORDER BY amopstrategy",
9772
opcinfo->dobj.catId.oid);
9775
res = PQexec(g_conn, query->data);
9776
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9778
ntups = PQntuples(res);
9780
i_amopstrategy = PQfnumber(res, "amopstrategy");
9781
i_amopreqcheck = PQfnumber(res, "amopreqcheck");
9782
i_amopopr = PQfnumber(res, "amopopr");
9783
i_sortfamily = PQfnumber(res, "sortfamily");
9784
i_sortfamilynsp = PQfnumber(res, "sortfamilynsp");
9786
for (i = 0; i < ntups; i++)
9788
amopstrategy = PQgetvalue(res, i, i_amopstrategy);
9789
amopreqcheck = PQgetvalue(res, i, i_amopreqcheck);
9790
amopopr = PQgetvalue(res, i, i_amopopr);
9791
sortfamily = PQgetvalue(res, i, i_sortfamily);
9792
sortfamilynsp = PQgetvalue(res, i, i_sortfamilynsp);
9795
appendPQExpBuffer(q, " ,\n ");
9797
appendPQExpBuffer(q, "OPERATOR %s %s",
9798
amopstrategy, amopopr);
9800
if (strlen(sortfamily) > 0)
9802
appendPQExpBuffer(q, " FOR ORDER BY ");
9803
if (strcmp(sortfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
9804
appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
9805
appendPQExpBuffer(q, "%s", fmtId(sortfamily));
9808
if (strcmp(amopreqcheck, "t") == 0)
9809
appendPQExpBuffer(q, " RECHECK");
9817
* Now fetch and print the FUNCTION entries (pg_amproc rows).
9819
* Print only those opfamily members that are tied to the opclass by
9820
* pg_depend entries.
9822
resetPQExpBuffer(query);
9824
if (g_fout->remoteVersion >= 80300)
9826
appendPQExpBuffer(query, "SELECT amprocnum, "
9827
"amproc::pg_catalog.regprocedure "
9828
"FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
9829
"WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
9830
"AND refobjid = '%u'::pg_catalog.oid "
9831
"AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
9832
"AND objid = ap.oid "
9833
"ORDER BY amprocnum",
9834
opcinfo->dobj.catId.oid);
9838
appendPQExpBuffer(query, "SELECT amprocnum, "
9839
"amproc::pg_catalog.regprocedure "
9840
"FROM pg_catalog.pg_amproc "
9841
"WHERE amopclaid = '%u'::pg_catalog.oid "
9842
"ORDER BY amprocnum",
9843
opcinfo->dobj.catId.oid);
9846
res = PQexec(g_conn, query->data);
9847
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9849
ntups = PQntuples(res);
9851
i_amprocnum = PQfnumber(res, "amprocnum");
9852
i_amproc = PQfnumber(res, "amproc");
9854
for (i = 0; i < ntups; i++)
9856
amprocnum = PQgetvalue(res, i, i_amprocnum);
9857
amproc = PQgetvalue(res, i, i_amproc);
9860
appendPQExpBuffer(q, " ,\n ");
9862
appendPQExpBuffer(q, "FUNCTION %s %s",
9870
appendPQExpBuffer(q, ";\n");
9872
appendPQExpBuffer(labelq, "OPERATOR CLASS %s",
9873
fmtId(opcinfo->dobj.name));
9874
appendPQExpBuffer(labelq, " USING %s",
9878
binary_upgrade_extension_member(q, &opcinfo->dobj, labelq->data);
9880
ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
9882
opcinfo->dobj.namespace->dobj.name,
9885
false, "OPERATOR CLASS", SECTION_PRE_DATA,
9886
q->data, delq->data, NULL,
9887
opcinfo->dobj.dependencies, opcinfo->dobj.nDeps,
9890
/* Dump Operator Class Comments */
9891
dumpComment(fout, labelq->data,
9892
NULL, opcinfo->rolname,
9893
opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId);
9896
destroyPQExpBuffer(query);
9897
destroyPQExpBuffer(q);
9898
destroyPQExpBuffer(delq);
9899
destroyPQExpBuffer(labelq);
9904
* write out a single operator family definition
9906
* Note: this also dumps any "loose" operator members that aren't bound to a
9907
* specific opclass within the opfamily.
9910
dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
9918
PGresult *res_procs;
9925
int i_sortfamilynsp;
9928
int i_amproclefttype;
9929
int i_amprocrighttype;
9935
char *sortfamilynsp;
9938
char *amproclefttype;
9939
char *amprocrighttype;
9943
/* Skip if not to be dumped */
9944
if (!opfinfo->dobj.dump || dataOnly)
9948
* We want to dump the opfamily only if (1) it contains "loose" operators
9949
* or functions, or (2) it contains an opclass with a different name or
9950
* owner. Otherwise it's sufficient to let it be created during creation
9951
* of the contained opclass, and not dumping it improves portability of
9952
* the dump. Since we have to fetch the loose operators/funcs anyway, do
9956
query = createPQExpBuffer();
9957
q = createPQExpBuffer();
9958
delq = createPQExpBuffer();
9959
labelq = createPQExpBuffer();
9961
/* Make sure we are in proper schema so regoperator works correctly */
9962
selectSourceSchema(opfinfo->dobj.namespace->dobj.name);
9965
* Fetch only those opfamily members that are tied directly to the
9966
* opfamily by pg_depend entries.
9968
* XXX RECHECK is gone as of 8.4, but we'll still print it if dumping an
9969
* older server's opclass in which it is used. This is to avoid
9970
* hard-to-detect breakage if a newer pg_dump is used to dump from an
9971
* older server and then reload into that old version. This can go away
9972
* once 8.3 is so old as to not be of interest to anyone.
9974
if (g_fout->remoteVersion >= 90100)
9976
appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
9977
"amopopr::pg_catalog.regoperator, "
9978
"opfname AS sortfamily, "
9979
"nspname AS sortfamilynsp "
9980
"FROM pg_catalog.pg_amop ao JOIN pg_catalog.pg_depend ON "
9981
"(classid = 'pg_catalog.pg_amop'::pg_catalog.regclass AND objid = ao.oid) "
9982
"LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = amopsortfamily "
9983
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
9984
"WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
9985
"AND refobjid = '%u'::pg_catalog.oid "
9986
"AND amopfamily = '%u'::pg_catalog.oid "
9987
"ORDER BY amopstrategy",
9988
opfinfo->dobj.catId.oid,
9989
opfinfo->dobj.catId.oid);
9991
else if (g_fout->remoteVersion >= 80400)
9993
appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
9994
"amopopr::pg_catalog.regoperator, "
9995
"NULL AS sortfamily, "
9996
"NULL AS sortfamilynsp "
9997
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
9998
"WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
9999
"AND refobjid = '%u'::pg_catalog.oid "
10000
"AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
10001
"AND objid = ao.oid "
10002
"ORDER BY amopstrategy",
10003
opfinfo->dobj.catId.oid);
10007
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
10008
"amopopr::pg_catalog.regoperator, "
10009
"NULL AS sortfamily, "
10010
"NULL AS sortfamilynsp "
10011
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
10012
"WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
10013
"AND refobjid = '%u'::pg_catalog.oid "
10014
"AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
10015
"AND objid = ao.oid "
10016
"ORDER BY amopstrategy",
10017
opfinfo->dobj.catId.oid);
10020
res_ops = PQexec(g_conn, query->data);
10021
check_sql_result(res_ops, g_conn, query->data, PGRES_TUPLES_OK);
10023
resetPQExpBuffer(query);
10025
appendPQExpBuffer(query, "SELECT amprocnum, "
10026
"amproc::pg_catalog.regprocedure, "
10027
"amproclefttype::pg_catalog.regtype, "
10028
"amprocrighttype::pg_catalog.regtype "
10029
"FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
10030
"WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
10031
"AND refobjid = '%u'::pg_catalog.oid "
10032
"AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
10033
"AND objid = ap.oid "
10034
"ORDER BY amprocnum",
10035
opfinfo->dobj.catId.oid);
10037
res_procs = PQexec(g_conn, query->data);
10038
check_sql_result(res_procs, g_conn, query->data, PGRES_TUPLES_OK);
10040
if (PQntuples(res_ops) == 0 && PQntuples(res_procs) == 0)
10042
/* No loose members, so check contained opclasses */
10043
resetPQExpBuffer(query);
10045
appendPQExpBuffer(query, "SELECT 1 "
10046
"FROM pg_catalog.pg_opclass c, pg_catalog.pg_opfamily f, pg_catalog.pg_depend "
10047
"WHERE f.oid = '%u'::pg_catalog.oid "
10048
"AND refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
10049
"AND refobjid = f.oid "
10050
"AND classid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
10051
"AND objid = c.oid "
10052
"AND (opcname != opfname OR opcnamespace != opfnamespace OR opcowner != opfowner) "
10054
opfinfo->dobj.catId.oid);
10056
res = PQexec(g_conn, query->data);
10057
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
10059
if (PQntuples(res) == 0)
10061
/* no need to dump it, so bail out */
10064
PQclear(res_procs);
10065
destroyPQExpBuffer(query);
10066
destroyPQExpBuffer(q);
10067
destroyPQExpBuffer(delq);
10068
destroyPQExpBuffer(labelq);
10075
/* Get additional fields from the pg_opfamily row */
10076
resetPQExpBuffer(query);
10078
appendPQExpBuffer(query, "SELECT "
10079
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opfmethod) AS amname "
10080
"FROM pg_catalog.pg_opfamily "
10081
"WHERE oid = '%u'::pg_catalog.oid",
10082
opfinfo->dobj.catId.oid);
10084
res = PQexec(g_conn, query->data);
10085
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
10087
/* Expecting a single result only */
10088
ntups = PQntuples(res);
10091
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
10092
"query returned %d rows instead of one: %s\n",
10094
ntups, query->data);
10098
i_amname = PQfnumber(res, "amname");
10100
/* amname will still be needed after we PQclear res */
10101
amname = strdup(PQgetvalue(res, 0, i_amname));
10104
* DROP must be fully qualified in case same name appears in pg_catalog
10106
appendPQExpBuffer(delq, "DROP OPERATOR FAMILY %s",
10107
fmtId(opfinfo->dobj.namespace->dobj.name));
10108
appendPQExpBuffer(delq, ".%s",
10109
fmtId(opfinfo->dobj.name));
10110
appendPQExpBuffer(delq, " USING %s;\n",
10113
/* Build the fixed portion of the CREATE command */
10114
appendPQExpBuffer(q, "CREATE OPERATOR FAMILY %s",
10115
fmtId(opfinfo->dobj.name));
10116
appendPQExpBuffer(q, " USING %s;\n",
10121
/* Do we need an ALTER to add loose members? */
10122
if (PQntuples(res_ops) > 0 || PQntuples(res_procs) > 0)
10124
appendPQExpBuffer(q, "ALTER OPERATOR FAMILY %s",
10125
fmtId(opfinfo->dobj.name));
10126
appendPQExpBuffer(q, " USING %s ADD\n ",
10132
* Now fetch and print the OPERATOR entries (pg_amop rows).
10134
ntups = PQntuples(res_ops);
10136
i_amopstrategy = PQfnumber(res_ops, "amopstrategy");
10137
i_amopreqcheck = PQfnumber(res_ops, "amopreqcheck");
10138
i_amopopr = PQfnumber(res_ops, "amopopr");
10139
i_sortfamily = PQfnumber(res_ops, "sortfamily");
10140
i_sortfamilynsp = PQfnumber(res_ops, "sortfamilynsp");
10142
for (i = 0; i < ntups; i++)
10144
amopstrategy = PQgetvalue(res_ops, i, i_amopstrategy);
10145
amopreqcheck = PQgetvalue(res_ops, i, i_amopreqcheck);
10146
amopopr = PQgetvalue(res_ops, i, i_amopopr);
10147
sortfamily = PQgetvalue(res_ops, i, i_sortfamily);
10148
sortfamilynsp = PQgetvalue(res_ops, i, i_sortfamilynsp);
10151
appendPQExpBuffer(q, " ,\n ");
10153
appendPQExpBuffer(q, "OPERATOR %s %s",
10154
amopstrategy, amopopr);
10156
if (strlen(sortfamily) > 0)
10158
appendPQExpBuffer(q, " FOR ORDER BY ");
10159
if (strcmp(sortfamilynsp, opfinfo->dobj.namespace->dobj.name) != 0)
10160
appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
10161
appendPQExpBuffer(q, "%s", fmtId(sortfamily));
10164
if (strcmp(amopreqcheck, "t") == 0)
10165
appendPQExpBuffer(q, " RECHECK");
10171
* Now fetch and print the FUNCTION entries (pg_amproc rows).
10173
ntups = PQntuples(res_procs);
10175
i_amprocnum = PQfnumber(res_procs, "amprocnum");
10176
i_amproc = PQfnumber(res_procs, "amproc");
10177
i_amproclefttype = PQfnumber(res_procs, "amproclefttype");
10178
i_amprocrighttype = PQfnumber(res_procs, "amprocrighttype");
10180
for (i = 0; i < ntups; i++)
10182
amprocnum = PQgetvalue(res_procs, i, i_amprocnum);
10183
amproc = PQgetvalue(res_procs, i, i_amproc);
10184
amproclefttype = PQgetvalue(res_procs, i, i_amproclefttype);
10185
amprocrighttype = PQgetvalue(res_procs, i, i_amprocrighttype);
10188
appendPQExpBuffer(q, " ,\n ");
10190
appendPQExpBuffer(q, "FUNCTION %s (%s, %s) %s",
10191
amprocnum, amproclefttype, amprocrighttype,
10197
appendPQExpBuffer(q, ";\n");
10200
appendPQExpBuffer(labelq, "OPERATOR FAMILY %s",
10201
fmtId(opfinfo->dobj.name));
10202
appendPQExpBuffer(labelq, " USING %s",
10205
if (binary_upgrade)
10206
binary_upgrade_extension_member(q, &opfinfo->dobj, labelq->data);
10208
ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
10209
opfinfo->dobj.name,
10210
opfinfo->dobj.namespace->dobj.name,
10213
false, "OPERATOR FAMILY", SECTION_PRE_DATA,
10214
q->data, delq->data, NULL,
10215
opfinfo->dobj.dependencies, opfinfo->dobj.nDeps,
10218
/* Dump Operator Family Comments */
10219
dumpComment(fout, labelq->data,
10220
NULL, opfinfo->rolname,
10221
opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId);
10225
PQclear(res_procs);
10226
destroyPQExpBuffer(query);
10227
destroyPQExpBuffer(q);
10228
destroyPQExpBuffer(delq);
10229
destroyPQExpBuffer(labelq);
10234
* write out a single collation definition
10237
dumpCollation(Archive *fout, CollInfo *collinfo)
10242
PQExpBuffer labelq;
10247
const char *collcollate;
10248
const char *collctype;
10250
/* Skip if not to be dumped */
10251
if (!collinfo->dobj.dump || dataOnly)
10254
query = createPQExpBuffer();
10255
q = createPQExpBuffer();
10256
delq = createPQExpBuffer();
10257
labelq = createPQExpBuffer();
10259
/* Make sure we are in proper schema */
10260
selectSourceSchema(collinfo->dobj.namespace->dobj.name);
10262
/* Get conversion-specific details */
10263
appendPQExpBuffer(query, "SELECT "
10266
"FROM pg_catalog.pg_collation c "
10267
"WHERE c.oid = '%u'::pg_catalog.oid",
10268
collinfo->dobj.catId.oid);
10270
res = PQexec(g_conn, query->data);
10271
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
10273
/* Expecting a single result only */
10274
ntups = PQntuples(res);
10277
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
10278
"query returned %d rows instead of one: %s\n",
10280
ntups, query->data);
10284
i_collcollate = PQfnumber(res, "collcollate");
10285
i_collctype = PQfnumber(res, "collctype");
10287
collcollate = PQgetvalue(res, 0, i_collcollate);
10288
collctype = PQgetvalue(res, 0, i_collctype);
10291
* DROP must be fully qualified in case same name appears in pg_catalog
10293
appendPQExpBuffer(delq, "DROP COLLATION %s",
10294
fmtId(collinfo->dobj.namespace->dobj.name));
10295
appendPQExpBuffer(delq, ".%s;\n",
10296
fmtId(collinfo->dobj.name));
10298
appendPQExpBuffer(q, "CREATE COLLATION %s (lc_collate = ",
10299
fmtId(collinfo->dobj.name));
10300
appendStringLiteralAH(q, collcollate, fout);
10301
appendPQExpBuffer(q, ", lc_ctype = ");
10302
appendStringLiteralAH(q, collctype, fout);
10303
appendPQExpBuffer(q, ");\n");
10305
appendPQExpBuffer(labelq, "COLLATION %s", fmtId(collinfo->dobj.name));
10307
if (binary_upgrade)
10308
binary_upgrade_extension_member(q, &collinfo->dobj, labelq->data);
10310
ArchiveEntry(fout, collinfo->dobj.catId, collinfo->dobj.dumpId,
10311
collinfo->dobj.name,
10312
collinfo->dobj.namespace->dobj.name,
10315
false, "COLLATION", SECTION_PRE_DATA,
10316
q->data, delq->data, NULL,
10317
collinfo->dobj.dependencies, collinfo->dobj.nDeps,
10320
/* Dump Collation Comments */
10321
dumpComment(fout, labelq->data,
10322
collinfo->dobj.namespace->dobj.name, collinfo->rolname,
10323
collinfo->dobj.catId, 0, collinfo->dobj.dumpId);
10327
destroyPQExpBuffer(query);
10328
destroyPQExpBuffer(q);
10329
destroyPQExpBuffer(delq);
10330
destroyPQExpBuffer(labelq);
10335
* write out a single conversion definition
10338
dumpConversion(Archive *fout, ConvInfo *convinfo)
10343
PQExpBuffer labelq;
10346
int i_conforencoding;
10347
int i_contoencoding;
10350
const char *conforencoding;
10351
const char *contoencoding;
10352
const char *conproc;
10355
/* Skip if not to be dumped */
10356
if (!convinfo->dobj.dump || dataOnly)
10359
query = createPQExpBuffer();
10360
q = createPQExpBuffer();
10361
delq = createPQExpBuffer();
10362
labelq = createPQExpBuffer();
10364
/* Make sure we are in proper schema */
10365
selectSourceSchema(convinfo->dobj.namespace->dobj.name);
10367
/* Get conversion-specific details */
10368
appendPQExpBuffer(query, "SELECT "
10369
"pg_catalog.pg_encoding_to_char(conforencoding) AS conforencoding, "
10370
"pg_catalog.pg_encoding_to_char(contoencoding) AS contoencoding, "
10371
"conproc, condefault "
10372
"FROM pg_catalog.pg_conversion c "
10373
"WHERE c.oid = '%u'::pg_catalog.oid",
10374
convinfo->dobj.catId.oid);
10376
res = PQexec(g_conn, query->data);
10377
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
10379
/* Expecting a single result only */
10380
ntups = PQntuples(res);
10383
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
10384
"query returned %d rows instead of one: %s\n",
10386
ntups, query->data);
10390
i_conforencoding = PQfnumber(res, "conforencoding");
10391
i_contoencoding = PQfnumber(res, "contoencoding");
10392
i_conproc = PQfnumber(res, "conproc");
10393
i_condefault = PQfnumber(res, "condefault");
10395
conforencoding = PQgetvalue(res, 0, i_conforencoding);
10396
contoencoding = PQgetvalue(res, 0, i_contoencoding);
10397
conproc = PQgetvalue(res, 0, i_conproc);
10398
condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't');
10401
* DROP must be fully qualified in case same name appears in pg_catalog
10403
appendPQExpBuffer(delq, "DROP CONVERSION %s",
10404
fmtId(convinfo->dobj.namespace->dobj.name));
10405
appendPQExpBuffer(delq, ".%s;\n",
10406
fmtId(convinfo->dobj.name));
10408
appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
10409
(condefault) ? "DEFAULT " : "",
10410
fmtId(convinfo->dobj.name));
10411
appendStringLiteralAH(q, conforencoding, fout);
10412
appendPQExpBuffer(q, " TO ");
10413
appendStringLiteralAH(q, contoencoding, fout);
10414
/* regproc is automatically quoted in 7.3 and above */
10415
appendPQExpBuffer(q, " FROM %s;\n", conproc);
10417
appendPQExpBuffer(labelq, "CONVERSION %s", fmtId(convinfo->dobj.name));
10419
if (binary_upgrade)
10420
binary_upgrade_extension_member(q, &convinfo->dobj, labelq->data);
10422
ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId,
10423
convinfo->dobj.name,
10424
convinfo->dobj.namespace->dobj.name,
10427
false, "CONVERSION", SECTION_PRE_DATA,
10428
q->data, delq->data, NULL,
10429
convinfo->dobj.dependencies, convinfo->dobj.nDeps,
10432
/* Dump Conversion Comments */
10433
dumpComment(fout, labelq->data,
10434
convinfo->dobj.namespace->dobj.name, convinfo->rolname,
10435
convinfo->dobj.catId, 0, convinfo->dobj.dumpId);
10439
destroyPQExpBuffer(query);
10440
destroyPQExpBuffer(q);
10441
destroyPQExpBuffer(delq);
10442
destroyPQExpBuffer(labelq);
10446
* format_aggregate_signature: generate aggregate name and argument list
10448
* The argument type names are qualified if needed. The aggregate name
10449
* is never qualified.
10452
format_aggregate_signature(AggInfo *agginfo, Archive *fout, bool honor_quotes)
10454
PQExpBufferData buf;
10457
initPQExpBuffer(&buf);
10459
appendPQExpBuffer(&buf, "%s",
10460
fmtId(agginfo->aggfn.dobj.name));
10462
appendPQExpBuffer(&buf, "%s", agginfo->aggfn.dobj.name);
10464
if (agginfo->aggfn.nargs == 0)
10465
appendPQExpBuffer(&buf, "(*)");
10468
appendPQExpBuffer(&buf, "(");
10469
for (j = 0; j < agginfo->aggfn.nargs; j++)
10473
typname = getFormattedTypeName(agginfo->aggfn.argtypes[j], zeroAsOpaque);
10475
appendPQExpBuffer(&buf, "%s%s",
10476
(j > 0) ? ", " : "",
10480
appendPQExpBuffer(&buf, ")");
10487
* write out a single aggregate definition
10490
dumpAgg(Archive *fout, AggInfo *agginfo)
10495
PQExpBuffer labelq;
10496
PQExpBuffer details;
10504
int i_aggtranstype;
10507
const char *aggtransfn;
10508
const char *aggfinalfn;
10509
const char *aggsortop;
10510
const char *aggtranstype;
10511
const char *agginitval;
10514
/* Skip if not to be dumped */
10515
if (!agginfo->aggfn.dobj.dump || dataOnly)
10518
query = createPQExpBuffer();
10519
q = createPQExpBuffer();
10520
delq = createPQExpBuffer();
10521
labelq = createPQExpBuffer();
10522
details = createPQExpBuffer();
10524
/* Make sure we are in proper schema */
10525
selectSourceSchema(agginfo->aggfn.dobj.namespace->dobj.name);
10527
/* Get aggregate-specific details */
10528
if (g_fout->remoteVersion >= 80100)
10530
appendPQExpBuffer(query, "SELECT aggtransfn, "
10531
"aggfinalfn, aggtranstype::pg_catalog.regtype, "
10532
"aggsortop::pg_catalog.regoperator, "
10534
"'t'::boolean AS convertok "
10535
"FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
10536
"WHERE a.aggfnoid = p.oid "
10537
"AND p.oid = '%u'::pg_catalog.oid",
10538
agginfo->aggfn.dobj.catId.oid);
10540
else if (g_fout->remoteVersion >= 70300)
10542
appendPQExpBuffer(query, "SELECT aggtransfn, "
10543
"aggfinalfn, aggtranstype::pg_catalog.regtype, "
10546
"'t'::boolean AS convertok "
10547
"FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
10548
"WHERE a.aggfnoid = p.oid "
10549
"AND p.oid = '%u'::pg_catalog.oid",
10550
agginfo->aggfn.dobj.catId.oid);
10552
else if (g_fout->remoteVersion >= 70100)
10554
appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
10555
"format_type(aggtranstype, NULL) AS aggtranstype, "
10558
"'t'::boolean AS convertok "
10559
"FROM pg_aggregate "
10560
"WHERE oid = '%u'::oid",
10561
agginfo->aggfn.dobj.catId.oid);
10565
appendPQExpBuffer(query, "SELECT aggtransfn1 AS aggtransfn, "
10567
"(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, "
10569
"agginitval1 AS agginitval, "
10570
"(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) AS convertok "
10571
"FROM pg_aggregate "
10572
"WHERE oid = '%u'::oid",
10573
agginfo->aggfn.dobj.catId.oid);
10576
res = PQexec(g_conn, query->data);
10577
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
10579
/* Expecting a single result only */
10580
ntups = PQntuples(res);
10583
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
10584
"query returned %d rows instead of one: %s\n",
10586
ntups, query->data);
10590
i_aggtransfn = PQfnumber(res, "aggtransfn");
10591
i_aggfinalfn = PQfnumber(res, "aggfinalfn");
10592
i_aggsortop = PQfnumber(res, "aggsortop");
10593
i_aggtranstype = PQfnumber(res, "aggtranstype");
10594
i_agginitval = PQfnumber(res, "agginitval");
10595
i_convertok = PQfnumber(res, "convertok");
10597
aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
10598
aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
10599
aggsortop = PQgetvalue(res, 0, i_aggsortop);
10600
aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
10601
agginitval = PQgetvalue(res, 0, i_agginitval);
10602
convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
10604
aggsig = format_aggregate_signature(agginfo, fout, true);
10605
aggsig_tag = format_aggregate_signature(agginfo, fout, false);
10609
write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
10614
if (g_fout->remoteVersion >= 70300)
10616
/* If using 7.3's regproc or regtype, data is already quoted */
10617
appendPQExpBuffer(details, " SFUNC = %s,\n STYPE = %s",
10621
else if (g_fout->remoteVersion >= 70100)
10623
/* format_type quotes, regproc does not */
10624
appendPQExpBuffer(details, " SFUNC = %s,\n STYPE = %s",
10630
/* need quotes all around */
10631
appendPQExpBuffer(details, " SFUNC = %s,\n",
10632
fmtId(aggtransfn));
10633
appendPQExpBuffer(details, " STYPE = %s",
10634
fmtId(aggtranstype));
10637
if (!PQgetisnull(res, 0, i_agginitval))
10639
appendPQExpBuffer(details, ",\n INITCOND = ");
10640
appendStringLiteralAH(details, agginitval, fout);
10643
if (strcmp(aggfinalfn, "-") != 0)
10645
appendPQExpBuffer(details, ",\n FINALFUNC = %s",
10649
aggsortop = convertOperatorReference(aggsortop);
10652
appendPQExpBuffer(details, ",\n SORTOP = %s",
10657
* DROP must be fully qualified in case same name appears in pg_catalog
10659
appendPQExpBuffer(delq, "DROP AGGREGATE %s.%s;\n",
10660
fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
10663
appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n",
10664
aggsig, details->data);
10666
appendPQExpBuffer(labelq, "AGGREGATE %s", aggsig);
10668
if (binary_upgrade)
10669
binary_upgrade_extension_member(q, &agginfo->aggfn.dobj, labelq->data);
10671
ArchiveEntry(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
10673
agginfo->aggfn.dobj.namespace->dobj.name,
10675
agginfo->aggfn.rolname,
10676
false, "AGGREGATE", SECTION_PRE_DATA,
10677
q->data, delq->data, NULL,
10678
agginfo->aggfn.dobj.dependencies, agginfo->aggfn.dobj.nDeps,
10681
/* Dump Aggregate Comments */
10682
dumpComment(fout, labelq->data,
10683
agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
10684
agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
10685
dumpSecLabel(fout, labelq->data,
10686
agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
10687
agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
10690
* Since there is no GRANT ON AGGREGATE syntax, we have to make the ACL
10691
* command look like a function's GRANT; in particular this affects the
10692
* syntax for zero-argument aggregates.
10697
aggsig = format_function_signature(&agginfo->aggfn, true);
10698
aggsig_tag = format_function_signature(&agginfo->aggfn, false);
10700
dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
10702
aggsig, NULL, aggsig_tag,
10703
agginfo->aggfn.dobj.namespace->dobj.name,
10704
agginfo->aggfn.rolname, agginfo->aggfn.proacl);
10711
destroyPQExpBuffer(query);
10712
destroyPQExpBuffer(q);
10713
destroyPQExpBuffer(delq);
10714
destroyPQExpBuffer(labelq);
10715
destroyPQExpBuffer(details);
10720
* write out a single text search parser
10723
dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
10727
PQExpBuffer labelq;
10729
/* Skip if not to be dumped */
10730
if (!prsinfo->dobj.dump || dataOnly)
10733
q = createPQExpBuffer();
10734
delq = createPQExpBuffer();
10735
labelq = createPQExpBuffer();
10737
/* Make sure we are in proper schema */
10738
selectSourceSchema(prsinfo->dobj.namespace->dobj.name);
10740
appendPQExpBuffer(q, "CREATE TEXT SEARCH PARSER %s (\n",
10741
fmtId(prsinfo->dobj.name));
10743
appendPQExpBuffer(q, " START = %s,\n",
10744
convertTSFunction(prsinfo->prsstart));
10745
appendPQExpBuffer(q, " GETTOKEN = %s,\n",
10746
convertTSFunction(prsinfo->prstoken));
10747
appendPQExpBuffer(q, " END = %s,\n",
10748
convertTSFunction(prsinfo->prsend));
10749
if (prsinfo->prsheadline != InvalidOid)
10750
appendPQExpBuffer(q, " HEADLINE = %s,\n",
10751
convertTSFunction(prsinfo->prsheadline));
10752
appendPQExpBuffer(q, " LEXTYPES = %s );\n",
10753
convertTSFunction(prsinfo->prslextype));
10756
* DROP must be fully qualified in case same name appears in pg_catalog
10758
appendPQExpBuffer(delq, "DROP TEXT SEARCH PARSER %s",
10759
fmtId(prsinfo->dobj.namespace->dobj.name));
10760
appendPQExpBuffer(delq, ".%s;\n",
10761
fmtId(prsinfo->dobj.name));
10763
appendPQExpBuffer(labelq, "TEXT SEARCH PARSER %s",
10764
fmtId(prsinfo->dobj.name));
10766
if (binary_upgrade)
10767
binary_upgrade_extension_member(q, &prsinfo->dobj, labelq->data);
10769
ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId,
10770
prsinfo->dobj.name,
10771
prsinfo->dobj.namespace->dobj.name,
10774
false, "TEXT SEARCH PARSER", SECTION_PRE_DATA,
10775
q->data, delq->data, NULL,
10776
prsinfo->dobj.dependencies, prsinfo->dobj.nDeps,
10779
/* Dump Parser Comments */
10780
dumpComment(fout, labelq->data,
10782
prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId);
10784
destroyPQExpBuffer(q);
10785
destroyPQExpBuffer(delq);
10786
destroyPQExpBuffer(labelq);
10791
* write out a single text search dictionary
10794
dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
10798
PQExpBuffer labelq;
10805
/* Skip if not to be dumped */
10806
if (!dictinfo->dobj.dump || dataOnly)
10809
q = createPQExpBuffer();
10810
delq = createPQExpBuffer();
10811
labelq = createPQExpBuffer();
10812
query = createPQExpBuffer();
10814
/* Fetch name and namespace of the dictionary's template */
10815
selectSourceSchema("pg_catalog");
10816
appendPQExpBuffer(query, "SELECT nspname, tmplname "
10817
"FROM pg_ts_template p, pg_namespace n "
10818
"WHERE p.oid = '%u' AND n.oid = tmplnamespace",
10819
dictinfo->dicttemplate);
10820
res = PQexec(g_conn, query->data);
10821
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
10822
ntups = PQntuples(res);
10825
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
10826
"query returned %d rows instead of one: %s\n",
10828
ntups, query->data);
10831
nspname = PQgetvalue(res, 0, 0);
10832
tmplname = PQgetvalue(res, 0, 1);
10834
/* Make sure we are in proper schema */
10835
selectSourceSchema(dictinfo->dobj.namespace->dobj.name);
10837
appendPQExpBuffer(q, "CREATE TEXT SEARCH DICTIONARY %s (\n",
10838
fmtId(dictinfo->dobj.name));
10840
appendPQExpBuffer(q, " TEMPLATE = ");
10841
if (strcmp(nspname, dictinfo->dobj.namespace->dobj.name) != 0)
10842
appendPQExpBuffer(q, "%s.", fmtId(nspname));
10843
appendPQExpBuffer(q, "%s", fmtId(tmplname));
10847
/* the dictinitoption can be dumped straight into the command */
10848
if (dictinfo->dictinitoption)
10849
appendPQExpBuffer(q, ",\n %s", dictinfo->dictinitoption);
10851
appendPQExpBuffer(q, " );\n");
10854
* DROP must be fully qualified in case same name appears in pg_catalog
10856
appendPQExpBuffer(delq, "DROP TEXT SEARCH DICTIONARY %s",
10857
fmtId(dictinfo->dobj.namespace->dobj.name));
10858
appendPQExpBuffer(delq, ".%s;\n",
10859
fmtId(dictinfo->dobj.name));
10861
appendPQExpBuffer(labelq, "TEXT SEARCH DICTIONARY %s",
10862
fmtId(dictinfo->dobj.name));
10864
if (binary_upgrade)
10865
binary_upgrade_extension_member(q, &dictinfo->dobj, labelq->data);
10867
ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId,
10868
dictinfo->dobj.name,
10869
dictinfo->dobj.namespace->dobj.name,
10872
false, "TEXT SEARCH DICTIONARY", SECTION_PRE_DATA,
10873
q->data, delq->data, NULL,
10874
dictinfo->dobj.dependencies, dictinfo->dobj.nDeps,
10877
/* Dump Dictionary Comments */
10878
dumpComment(fout, labelq->data,
10879
NULL, dictinfo->rolname,
10880
dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId);
10882
destroyPQExpBuffer(q);
10883
destroyPQExpBuffer(delq);
10884
destroyPQExpBuffer(labelq);
10885
destroyPQExpBuffer(query);
10890
* write out a single text search template
10893
dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
10897
PQExpBuffer labelq;
10899
/* Skip if not to be dumped */
10900
if (!tmplinfo->dobj.dump || dataOnly)
10903
q = createPQExpBuffer();
10904
delq = createPQExpBuffer();
10905
labelq = createPQExpBuffer();
10907
/* Make sure we are in proper schema */
10908
selectSourceSchema(tmplinfo->dobj.namespace->dobj.name);
10910
appendPQExpBuffer(q, "CREATE TEXT SEARCH TEMPLATE %s (\n",
10911
fmtId(tmplinfo->dobj.name));
10913
if (tmplinfo->tmplinit != InvalidOid)
10914
appendPQExpBuffer(q, " INIT = %s,\n",
10915
convertTSFunction(tmplinfo->tmplinit));
10916
appendPQExpBuffer(q, " LEXIZE = %s );\n",
10917
convertTSFunction(tmplinfo->tmpllexize));
10920
* DROP must be fully qualified in case same name appears in pg_catalog
10922
appendPQExpBuffer(delq, "DROP TEXT SEARCH TEMPLATE %s",
10923
fmtId(tmplinfo->dobj.namespace->dobj.name));
10924
appendPQExpBuffer(delq, ".%s;\n",
10925
fmtId(tmplinfo->dobj.name));
10927
appendPQExpBuffer(labelq, "TEXT SEARCH TEMPLATE %s",
10928
fmtId(tmplinfo->dobj.name));
10930
if (binary_upgrade)
10931
binary_upgrade_extension_member(q, &tmplinfo->dobj, labelq->data);
10933
ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId,
10934
tmplinfo->dobj.name,
10935
tmplinfo->dobj.namespace->dobj.name,
10938
false, "TEXT SEARCH TEMPLATE", SECTION_PRE_DATA,
10939
q->data, delq->data, NULL,
10940
tmplinfo->dobj.dependencies, tmplinfo->dobj.nDeps,
10943
/* Dump Template Comments */
10944
dumpComment(fout, labelq->data,
10946
tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId);
10948
destroyPQExpBuffer(q);
10949
destroyPQExpBuffer(delq);
10950
destroyPQExpBuffer(labelq);
10955
* write out a single text search configuration
10958
dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
10962
PQExpBuffer labelq;
10972
/* Skip if not to be dumped */
10973
if (!cfginfo->dobj.dump || dataOnly)
10976
q = createPQExpBuffer();
10977
delq = createPQExpBuffer();
10978
labelq = createPQExpBuffer();
10979
query = createPQExpBuffer();
10981
/* Fetch name and namespace of the config's parser */
10982
selectSourceSchema("pg_catalog");
10983
appendPQExpBuffer(query, "SELECT nspname, prsname "
10984
"FROM pg_ts_parser p, pg_namespace n "
10985
"WHERE p.oid = '%u' AND n.oid = prsnamespace",
10986
cfginfo->cfgparser);
10987
res = PQexec(g_conn, query->data);
10988
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
10989
ntups = PQntuples(res);
10992
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
10993
"query returned %d rows instead of one: %s\n",
10995
ntups, query->data);
10998
nspname = PQgetvalue(res, 0, 0);
10999
prsname = PQgetvalue(res, 0, 1);
11001
/* Make sure we are in proper schema */
11002
selectSourceSchema(cfginfo->dobj.namespace->dobj.name);
11004
appendPQExpBuffer(q, "CREATE TEXT SEARCH CONFIGURATION %s (\n",
11005
fmtId(cfginfo->dobj.name));
11007
appendPQExpBuffer(q, " PARSER = ");
11008
if (strcmp(nspname, cfginfo->dobj.namespace->dobj.name) != 0)
11009
appendPQExpBuffer(q, "%s.", fmtId(nspname));
11010
appendPQExpBuffer(q, "%s );\n", fmtId(prsname));
11014
resetPQExpBuffer(query);
11015
appendPQExpBuffer(query,
11017
" ( SELECT alias FROM pg_catalog.ts_token_type('%u'::pg_catalog.oid) AS t \n"
11018
" WHERE t.tokid = m.maptokentype ) AS tokenname, \n"
11019
" m.mapdict::pg_catalog.regdictionary AS dictname \n"
11020
"FROM pg_catalog.pg_ts_config_map AS m \n"
11021
"WHERE m.mapcfg = '%u' \n"
11022
"ORDER BY m.mapcfg, m.maptokentype, m.mapseqno",
11023
cfginfo->cfgparser, cfginfo->dobj.catId.oid);
11025
res = PQexec(g_conn, query->data);
11026
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11027
ntups = PQntuples(res);
11029
i_tokenname = PQfnumber(res, "tokenname");
11030
i_dictname = PQfnumber(res, "dictname");
11032
for (i = 0; i < ntups; i++)
11034
char *tokenname = PQgetvalue(res, i, i_tokenname);
11035
char *dictname = PQgetvalue(res, i, i_dictname);
11038
strcmp(tokenname, PQgetvalue(res, i - 1, i_tokenname)) != 0)
11040
/* starting a new token type, so start a new command */
11042
appendPQExpBuffer(q, ";\n");
11043
appendPQExpBuffer(q, "\nALTER TEXT SEARCH CONFIGURATION %s\n",
11044
fmtId(cfginfo->dobj.name));
11045
/* tokenname needs quoting, dictname does NOT */
11046
appendPQExpBuffer(q, " ADD MAPPING FOR %s WITH %s",
11047
fmtId(tokenname), dictname);
11050
appendPQExpBuffer(q, ", %s", dictname);
11054
appendPQExpBuffer(q, ";\n");
11059
* DROP must be fully qualified in case same name appears in pg_catalog
11061
appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s",
11062
fmtId(cfginfo->dobj.namespace->dobj.name));
11063
appendPQExpBuffer(delq, ".%s;\n",
11064
fmtId(cfginfo->dobj.name));
11066
appendPQExpBuffer(labelq, "TEXT SEARCH CONFIGURATION %s",
11067
fmtId(cfginfo->dobj.name));
11069
if (binary_upgrade)
11070
binary_upgrade_extension_member(q, &cfginfo->dobj, labelq->data);
11072
ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId,
11073
cfginfo->dobj.name,
11074
cfginfo->dobj.namespace->dobj.name,
11077
false, "TEXT SEARCH CONFIGURATION", SECTION_PRE_DATA,
11078
q->data, delq->data, NULL,
11079
cfginfo->dobj.dependencies, cfginfo->dobj.nDeps,
11082
/* Dump Configuration Comments */
11083
dumpComment(fout, labelq->data,
11084
NULL, cfginfo->rolname,
11085
cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId);
11087
destroyPQExpBuffer(q);
11088
destroyPQExpBuffer(delq);
11089
destroyPQExpBuffer(labelq);
11090
destroyPQExpBuffer(query);
11094
* dumpForeignDataWrapper
11095
* write out a single foreign-data wrapper definition
11098
dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
11102
PQExpBuffer labelq;
11105
/* Skip if not to be dumped */
11106
if (!fdwinfo->dobj.dump || dataOnly)
11109
q = createPQExpBuffer();
11110
delq = createPQExpBuffer();
11111
labelq = createPQExpBuffer();
11113
qfdwname = strdup(fmtId(fdwinfo->dobj.name));
11115
appendPQExpBuffer(q, "CREATE FOREIGN DATA WRAPPER %s",
11118
if (strcmp(fdwinfo->fdwhandler, "-") != 0)
11119
appendPQExpBuffer(q, " HANDLER %s", fdwinfo->fdwhandler);
11121
if (strcmp(fdwinfo->fdwvalidator, "-") != 0)
11122
appendPQExpBuffer(q, " VALIDATOR %s", fdwinfo->fdwvalidator);
11124
if (strlen(fdwinfo->fdwoptions) > 0)
11125
appendPQExpBuffer(q, " OPTIONS (%s)", fdwinfo->fdwoptions);
11127
appendPQExpBuffer(q, ";\n");
11129
appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n",
11132
appendPQExpBuffer(labelq, "FOREIGN DATA WRAPPER %s",
11135
if (binary_upgrade)
11136
binary_upgrade_extension_member(q, &fdwinfo->dobj, labelq->data);
11138
ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
11139
fdwinfo->dobj.name,
11143
false, "FOREIGN DATA WRAPPER", SECTION_PRE_DATA,
11144
q->data, delq->data, NULL,
11145
fdwinfo->dobj.dependencies, fdwinfo->dobj.nDeps,
11148
/* Handle the ACL */
11149
dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
11150
"FOREIGN DATA WRAPPER",
11151
qfdwname, NULL, fdwinfo->dobj.name,
11152
NULL, fdwinfo->rolname,
11155
/* Dump Foreign Data Wrapper Comments */
11156
dumpComment(fout, labelq->data,
11157
NULL, fdwinfo->rolname,
11158
fdwinfo->dobj.catId, 0, fdwinfo->dobj.dumpId);
11162
destroyPQExpBuffer(q);
11163
destroyPQExpBuffer(delq);
11164
destroyPQExpBuffer(labelq);
11168
* dumpForeignServer
11169
* write out a foreign server definition
11172
dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
11176
PQExpBuffer labelq;
11183
/* Skip if not to be dumped */
11184
if (!srvinfo->dobj.dump || dataOnly)
11187
q = createPQExpBuffer();
11188
delq = createPQExpBuffer();
11189
labelq = createPQExpBuffer();
11190
query = createPQExpBuffer();
11192
qsrvname = strdup(fmtId(srvinfo->dobj.name));
11194
/* look up the foreign-data wrapper */
11195
selectSourceSchema("pg_catalog");
11196
appendPQExpBuffer(query, "SELECT fdwname "
11197
"FROM pg_foreign_data_wrapper w "
11198
"WHERE w.oid = '%u'",
11200
res = PQexec(g_conn, query->data);
11201
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11202
ntups = PQntuples(res);
11205
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
11206
"query returned %d rows instead of one: %s\n",
11208
ntups, query->data);
11211
fdwname = PQgetvalue(res, 0, 0);
11213
appendPQExpBuffer(q, "CREATE SERVER %s", qsrvname);
11214
if (srvinfo->srvtype && strlen(srvinfo->srvtype) > 0)
11216
appendPQExpBuffer(q, " TYPE ");
11217
appendStringLiteralAH(q, srvinfo->srvtype, fout);
11219
if (srvinfo->srvversion && strlen(srvinfo->srvversion) > 0)
11221
appendPQExpBuffer(q, " VERSION ");
11222
appendStringLiteralAH(q, srvinfo->srvversion, fout);
11225
appendPQExpBuffer(q, " FOREIGN DATA WRAPPER ");
11226
appendPQExpBuffer(q, "%s", fmtId(fdwname));
11228
if (srvinfo->srvoptions && strlen(srvinfo->srvoptions) > 0)
11229
appendPQExpBuffer(q, " OPTIONS (%s)", srvinfo->srvoptions);
11231
appendPQExpBuffer(q, ";\n");
11233
appendPQExpBuffer(delq, "DROP SERVER %s;\n",
11236
appendPQExpBuffer(labelq, "SERVER %s", qsrvname);
11238
if (binary_upgrade)
11239
binary_upgrade_extension_member(q, &srvinfo->dobj, labelq->data);
11241
ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
11242
srvinfo->dobj.name,
11246
false, "SERVER", SECTION_PRE_DATA,
11247
q->data, delq->data, NULL,
11248
srvinfo->dobj.dependencies, srvinfo->dobj.nDeps,
11251
/* Handle the ACL */
11252
dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
11254
qsrvname, NULL, srvinfo->dobj.name,
11255
NULL, srvinfo->rolname,
11258
/* Dump user mappings */
11259
dumpUserMappings(fout,
11260
srvinfo->dobj.name, NULL,
11262
srvinfo->dobj.catId, srvinfo->dobj.dumpId);
11264
/* Dump Foreign Server Comments */
11265
dumpComment(fout, labelq->data,
11266
NULL, srvinfo->rolname,
11267
srvinfo->dobj.catId, 0, srvinfo->dobj.dumpId);
11271
destroyPQExpBuffer(q);
11272
destroyPQExpBuffer(delq);
11273
destroyPQExpBuffer(labelq);
11279
* This routine is used to dump any user mappings associated with the
11280
* server handed to this routine. Should be called after ArchiveEntry()
11284
dumpUserMappings(Archive *fout,
11285
const char *servername, const char *namespace,
11287
CatalogId catalogId, DumpId dumpId)
11299
q = createPQExpBuffer();
11300
tag = createPQExpBuffer();
11301
delq = createPQExpBuffer();
11302
query = createPQExpBuffer();
11305
* We read from the publicly accessible view pg_user_mappings, so as not
11306
* to fail if run by a non-superuser. Note that the view will show
11307
* umoptions as null if the user hasn't got privileges for the associated
11308
* server; this means that pg_dump will dump such a mapping, but with no
11309
* OPTIONS clause. A possible alternative is to skip such mappings
11310
* altogether, but it's not clear that that's an improvement.
11312
selectSourceSchema("pg_catalog");
11314
appendPQExpBuffer(query,
11316
"array_to_string(ARRAY(SELECT option_name || ' ' || quote_literal(option_value) FROM pg_options_to_table(umoptions)), ', ') AS umoptions\n"
11317
"FROM pg_user_mappings "
11318
"WHERE srvid = %u",
11321
res = PQexec(g_conn, query->data);
11322
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11324
ntups = PQntuples(res);
11325
i_usename = PQfnumber(res, "usename");
11326
i_umoptions = PQfnumber(res, "umoptions");
11328
for (i = 0; i < ntups; i++)
11333
usename = PQgetvalue(res, i, i_usename);
11334
umoptions = PQgetvalue(res, i, i_umoptions);
11336
resetPQExpBuffer(q);
11337
appendPQExpBuffer(q, "CREATE USER MAPPING FOR %s", fmtId(usename));
11338
appendPQExpBuffer(q, " SERVER %s", fmtId(servername));
11340
if (umoptions && strlen(umoptions) > 0)
11341
appendPQExpBuffer(q, " OPTIONS (%s)", umoptions);
11343
appendPQExpBuffer(q, ";\n");
11345
resetPQExpBuffer(delq);
11346
appendPQExpBuffer(delq, "DROP USER MAPPING FOR %s", fmtId(usename));
11347
appendPQExpBuffer(delq, " SERVER %s;\n", fmtId(servername));
11349
resetPQExpBuffer(tag);
11350
appendPQExpBuffer(tag, "USER MAPPING %s SERVER %s",
11351
usename, servername);
11353
ArchiveEntry(fout, nilCatalogId, createDumpId(),
11358
"USER MAPPING", SECTION_PRE_DATA,
11359
q->data, delq->data, NULL,
11366
destroyPQExpBuffer(query);
11367
destroyPQExpBuffer(delq);
11368
destroyPQExpBuffer(q);
11372
* Write out default privileges information
11375
dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
11381
/* Skip if not to be dumped */
11382
if (!daclinfo->dobj.dump || dataOnly || aclsSkip)
11385
q = createPQExpBuffer();
11386
tag = createPQExpBuffer();
11388
switch (daclinfo->defaclobjtype)
11390
case DEFACLOBJ_RELATION:
11393
case DEFACLOBJ_SEQUENCE:
11394
type = "SEQUENCES";
11396
case DEFACLOBJ_FUNCTION:
11397
type = "FUNCTIONS";
11400
/* shouldn't get here */
11401
write_msg(NULL, "unknown object type (%d) in default privileges\n",
11402
(int) daclinfo->defaclobjtype);
11404
type = ""; /* keep compiler quiet */
11407
appendPQExpBuffer(tag, "DEFAULT PRIVILEGES FOR %s", type);
11409
/* build the actual command(s) for this tuple */
11410
if (!buildDefaultACLCommands(type,
11411
daclinfo->dobj.namespace != NULL ?
11412
daclinfo->dobj.namespace->dobj.name : NULL,
11413
daclinfo->defaclacl,
11414
daclinfo->defaclrole,
11415
fout->remoteVersion,
11418
write_msg(NULL, "could not parse default ACL list (%s)\n",
11419
daclinfo->defaclacl);
11423
ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
11425
daclinfo->dobj.namespace ? daclinfo->dobj.namespace->dobj.name : NULL,
11427
daclinfo->defaclrole,
11428
false, "DEFAULT ACL", SECTION_NONE,
11430
daclinfo->dobj.dependencies, daclinfo->dobj.nDeps,
11433
destroyPQExpBuffer(tag);
11434
destroyPQExpBuffer(q);
11438
* Write out grant/revoke information
11440
* 'objCatId' is the catalog ID of the underlying object.
11441
* 'objDumpId' is the dump ID of the underlying object.
11442
* 'type' must be one of
11443
* TABLE, SEQUENCE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, TABLESPACE,
11444
* FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT.
11445
* 'name' is the formatted name of the object. Must be quoted etc. already.
11446
* 'subname' is the formatted name of the sub-object, if any. Must be quoted.
11447
* 'tag' is the tag for the archive entry (typ. unquoted name of object).
11448
* 'nspname' is the namespace the object is in (NULL if none).
11449
* 'owner' is the owner, NULL if there is no owner (for languages).
11450
* 'acls' is the string read out of the fooacl system catalog field;
11451
* it will be parsed here.
11455
dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
11456
const char *type, const char *name, const char *subname,
11457
const char *tag, const char *nspname, const char *owner,
11462
/* Do nothing if ACL dump is not enabled */
11466
/* --data-only skips ACLs *except* BLOB ACLs */
11467
if (dataOnly && strcmp(type, "LARGE OBJECT") != 0)
11470
sql = createPQExpBuffer();
11472
if (!buildACLCommands(name, subname, type, acls, owner,
11473
"", fout->remoteVersion, sql))
11475
write_msg(NULL, "could not parse ACL list (%s) for object \"%s\" (%s)\n",
11481
ArchiveEntry(fout, nilCatalogId, createDumpId(),
11484
owner ? owner : "",
11485
false, "ACL", SECTION_NONE,
11486
sql->data, "", NULL,
11490
destroyPQExpBuffer(sql);
11496
* This routine is used to dump any security labels associated with the
11497
* object handed to this routine. The routine takes a constant character
11498
* string for the target part of the security-label command, plus
11499
* the namespace and owner of the object (for labeling the ArchiveEntry),
11500
* plus catalog ID and subid which are the lookup key for pg_seclabel,
11501
* plus the dump ID for the object (for setting a dependency).
11502
* If a matching pg_seclabel entry is found, it is dumped.
11504
* Note: although this routine takes a dumpId for dependency purposes,
11505
* that purpose is just to mark the dependency in the emitted dump file
11506
* for possible future use by pg_restore. We do NOT use it for determining
11507
* ordering of the label in the dump file, because this routine is called
11508
* after dependency sorting occurs. This routine should be called just after
11509
* calling ArchiveEntry() for the specified object.
11512
dumpSecLabel(Archive *fout, const char *target,
11513
const char *namespace, const char *owner,
11514
CatalogId catalogId, int subid, DumpId dumpId)
11516
SecLabelItem *labels;
11521
/* do nothing, if --no-security-label is supplied */
11522
if (no_security_label)
11525
/* Comments are schema not data ... except blob comments are data */
11526
if (strncmp(target, "LARGE OBJECT ", 13) != 0)
11537
/* Search for security labels associated with catalogId, using table */
11538
nlabels = findSecLabels(fout, catalogId.tableoid, catalogId.oid, &labels);
11540
query = createPQExpBuffer();
11542
for (i = 0; i < nlabels; i++)
11545
* Ignore label entries for which the subid doesn't match.
11547
if (labels[i].objsubid != subid)
11550
appendPQExpBuffer(query,
11551
"SECURITY LABEL FOR %s ON %s IS ",
11552
fmtId(labels[i].provider), target);
11553
appendStringLiteralAH(query, labels[i].label, fout);
11554
appendPQExpBuffer(query, ";\n");
11557
if (query->len > 0)
11559
ArchiveEntry(fout, nilCatalogId, createDumpId(),
11560
target, namespace, NULL, owner,
11561
false, "SECURITY LABEL", SECTION_NONE,
11562
query->data, "", NULL,
11566
destroyPQExpBuffer(query);
11570
* dumpTableSecLabel
11572
* As above, but dump security label for both the specified table (or view)
11576
dumpTableSecLabel(Archive *fout, TableInfo *tbinfo, const char *reltypename)
11578
SecLabelItem *labels;
11582
PQExpBuffer target;
11584
/* do nothing, if --no-security-label is supplied */
11585
if (no_security_label)
11588
/* SecLabel are SCHEMA not data */
11592
/* Search for comments associated with relation, using table */
11593
nlabels = findSecLabels(fout,
11594
tbinfo->dobj.catId.tableoid,
11595
tbinfo->dobj.catId.oid,
11598
/* If security labels exist, build SECURITY LABEL statements */
11602
query = createPQExpBuffer();
11603
target = createPQExpBuffer();
11605
for (i = 0; i < nlabels; i++)
11607
const char *colname;
11608
const char *provider = labels[i].provider;
11609
const char *label = labels[i].label;
11610
int objsubid = labels[i].objsubid;
11612
resetPQExpBuffer(target);
11615
appendPQExpBuffer(target, "%s %s", reltypename,
11616
fmtId(tbinfo->dobj.name));
11620
colname = getAttrName(objsubid, tbinfo);
11621
/* first fmtId result must be consumed before calling it again */
11622
appendPQExpBuffer(target, "COLUMN %s", fmtId(tbinfo->dobj.name));
11623
appendPQExpBuffer(target, ".%s", fmtId(colname));
11625
appendPQExpBuffer(query, "SECURITY LABEL FOR %s ON %s IS ",
11626
fmtId(provider), target->data);
11627
appendStringLiteralAH(query, label, fout);
11628
appendPQExpBuffer(query, ";\n");
11630
if (query->len > 0)
11632
resetPQExpBuffer(target);
11633
appendPQExpBuffer(target, "%s %s", reltypename,
11634
fmtId(tbinfo->dobj.name));
11635
ArchiveEntry(fout, nilCatalogId, createDumpId(),
11637
tbinfo->dobj.namespace->dobj.name,
11638
NULL, tbinfo->rolname,
11639
false, "SECURITY LABEL", SECTION_NONE,
11640
query->data, "", NULL,
11641
&(tbinfo->dobj.dumpId), 1,
11644
destroyPQExpBuffer(query);
11645
destroyPQExpBuffer(target);
11651
* Find the security label(s), if any, associated with the given object.
11652
* All the objsubid values associated with the given classoid/objoid are
11653
* found with one search.
11656
findSecLabels(Archive *fout, Oid classoid, Oid objoid, SecLabelItem **items)
11658
/* static storage for table of security labels */
11659
static SecLabelItem *labels = NULL;
11660
static int nlabels = -1;
11662
SecLabelItem *middle = NULL;
11664
SecLabelItem *high;
11667
/* Get security labels if we didn't already */
11669
nlabels = collectSecLabels(fout, &labels);
11672
* Do binary search to find some item matching the object.
11675
high = &labels[nlabels - 1];
11676
while (low <= high)
11678
middle = low + (high - low) / 2;
11680
if (classoid < middle->classoid)
11682
else if (classoid > middle->classoid)
11684
else if (objoid < middle->objoid)
11686
else if (objoid > middle->objoid)
11689
break; /* found a match */
11692
if (low > high) /* no matches */
11699
* Now determine how many items match the object. The search loop
11700
* invariant still holds: only items between low and high inclusive could
11704
while (middle > low)
11706
if (classoid != middle[-1].classoid ||
11707
objoid != middle[-1].objoid)
11716
while (middle <= high)
11718
if (classoid != middle->classoid ||
11719
objoid != middle->objoid)
11731
* Construct a table of all security labels available for database objects.
11732
* It's much faster to pull them all at once.
11734
* The table is sorted by classoid/objid/objsubid for speed in lookup.
11737
collectSecLabels(Archive *fout, SecLabelItem **items)
11748
SecLabelItem *labels;
11750
query = createPQExpBuffer();
11752
appendPQExpBuffer(query,
11753
"SELECT label, provider, classoid, objoid, objsubid "
11754
"FROM pg_catalog.pg_seclabel "
11755
"ORDER BY classoid, objoid, objsubid");
11757
res = PQexec(g_conn, query->data);
11758
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11760
/* Construct lookup table containing OIDs in numeric form */
11761
i_label = PQfnumber(res, "label");
11762
i_provider = PQfnumber(res, "provider");
11763
i_classoid = PQfnumber(res, "classoid");
11764
i_objoid = PQfnumber(res, "objoid");
11765
i_objsubid = PQfnumber(res, "objsubid");
11767
ntups = PQntuples(res);
11769
labels = (SecLabelItem *) malloc(ntups * sizeof(SecLabelItem));
11771
for (i = 0; i < ntups; i++)
11773
labels[i].label = PQgetvalue(res, i, i_label);
11774
labels[i].provider = PQgetvalue(res, i, i_provider);
11775
labels[i].classoid = atooid(PQgetvalue(res, i, i_classoid));
11776
labels[i].objoid = atooid(PQgetvalue(res, i, i_objoid));
11777
labels[i].objsubid = atoi(PQgetvalue(res, i, i_objsubid));
11780
/* Do NOT free the PGresult since we are keeping pointers into it */
11781
destroyPQExpBuffer(query);
11789
* write out to fout the declarations (not data) of a user-defined table
11792
dumpTable(Archive *fout, TableInfo *tbinfo)
11794
if (tbinfo->dobj.dump)
11798
if (tbinfo->relkind == RELKIND_SEQUENCE)
11799
dumpSequence(fout, tbinfo);
11800
else if (!dataOnly)
11801
dumpTableSchema(fout, tbinfo);
11803
/* Handle the ACL here */
11804
namecopy = strdup(fmtId(tbinfo->dobj.name));
11805
dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
11806
(tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" :
11807
(tbinfo->relkind == RELKIND_FOREIGN_TABLE) ? "FOREIGN TABLE" :
11809
namecopy, NULL, tbinfo->dobj.name,
11810
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
11814
* Handle column ACLs, if any. Note: we pull these with a separate
11815
* query rather than trying to fetch them during getTableAttrs, so
11816
* that we won't miss ACLs on system columns.
11818
if (g_fout->remoteVersion >= 80400)
11820
PQExpBuffer query = createPQExpBuffer();
11824
appendPQExpBuffer(query,
11825
"SELECT attname, attacl FROM pg_catalog.pg_attribute "
11826
"WHERE attrelid = '%u' AND NOT attisdropped AND attacl IS NOT NULL "
11828
tbinfo->dobj.catId.oid);
11829
res = PQexec(g_conn, query->data);
11830
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11832
for (i = 0; i < PQntuples(res); i++)
11834
char *attname = PQgetvalue(res, i, 0);
11835
char *attacl = PQgetvalue(res, i, 1);
11839
attnamecopy = strdup(fmtId(attname));
11840
acltag = malloc(strlen(tbinfo->dobj.name) + strlen(attname) + 2);
11841
sprintf(acltag, "%s.%s", tbinfo->dobj.name, attname);
11842
/* Column's GRANT type is always TABLE */
11843
dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
11844
namecopy, attnamecopy, acltag,
11845
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
11851
destroyPQExpBuffer(query);
11860
* write the declaration (not data) of one user-defined table or view
11863
dumpTableSchema(Archive *fout, TableInfo *tbinfo)
11865
PQExpBuffer query = createPQExpBuffer();
11866
PQExpBuffer q = createPQExpBuffer();
11867
PQExpBuffer delq = createPQExpBuffer();
11868
PQExpBuffer labelq = createPQExpBuffer();
11871
TableInfo **parents;
11872
int actual_atts; /* number of attrs in this CREATE statment */
11878
char *ftoptions = NULL;
11880
/* Make sure we are in proper schema */
11881
selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
11883
if (binary_upgrade)
11884
binary_upgrade_set_type_oids_by_rel_oid(q,
11885
tbinfo->dobj.catId.oid);
11887
/* Is it a table or a view? */
11888
if (tbinfo->relkind == RELKIND_VIEW)
11892
reltypename = "VIEW";
11894
/* Fetch the view definition */
11895
if (g_fout->remoteVersion >= 70300)
11897
/* Beginning in 7.3, viewname is not unique; rely on OID */
11898
appendPQExpBuffer(query,
11899
"SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) AS viewdef",
11900
tbinfo->dobj.catId.oid);
11904
appendPQExpBuffer(query, "SELECT definition AS viewdef "
11905
"FROM pg_views WHERE viewname = ");
11906
appendStringLiteralAH(query, tbinfo->dobj.name, fout);
11907
appendPQExpBuffer(query, ";");
11910
res = PQexec(g_conn, query->data);
11911
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11913
if (PQntuples(res) != 1)
11915
if (PQntuples(res) < 1)
11916
write_msg(NULL, "query to obtain definition of view \"%s\" returned no data\n",
11917
tbinfo->dobj.name);
11919
write_msg(NULL, "query to obtain definition of view \"%s\" returned more than one definition\n",
11920
tbinfo->dobj.name);
11924
viewdef = PQgetvalue(res, 0, 0);
11926
if (strlen(viewdef) == 0)
11928
write_msg(NULL, "definition of view \"%s\" appears to be empty (length zero)\n",
11929
tbinfo->dobj.name);
11934
* DROP must be fully qualified in case same name appears in
11937
appendPQExpBuffer(delq, "DROP VIEW %s.",
11938
fmtId(tbinfo->dobj.namespace->dobj.name));
11939
appendPQExpBuffer(delq, "%s;\n",
11940
fmtId(tbinfo->dobj.name));
11942
if (binary_upgrade)
11943
binary_upgrade_set_pg_class_oids(q, tbinfo->dobj.catId.oid, false);
11945
appendPQExpBuffer(q, "CREATE VIEW %s AS\n %s\n",
11946
fmtId(tbinfo->dobj.name), viewdef);
11948
appendPQExpBuffer(labelq, "VIEW %s",
11949
fmtId(tbinfo->dobj.name));
11955
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
11960
reltypename = "FOREIGN TABLE";
11962
/* retrieve name of foreign server and generic options */
11963
appendPQExpBuffer(query,
11964
"SELECT fs.srvname, array_to_string(ARRAY("
11965
" SELECT option_name || ' ' || quote_literal(option_value)"
11966
" FROM pg_options_to_table(ftoptions)), ', ') AS ftoptions "
11967
"FROM pg_foreign_table ft JOIN pg_foreign_server fs "
11968
" ON (fs.oid = ft.ftserver) "
11969
"WHERE ft.ftrelid = %u", tbinfo->dobj.catId.oid);
11970
res = PQexec(g_conn, query->data);
11971
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11972
i_srvname = PQfnumber(res, "srvname");
11973
i_ftoptions = PQfnumber(res, "ftoptions");
11974
srvname = strdup(PQgetvalue(res, 0, i_srvname));
11975
ftoptions = strdup(PQgetvalue(res, 0, i_ftoptions));
11980
reltypename = "TABLE";
11984
numParents = tbinfo->numParents;
11985
parents = tbinfo->parents;
11988
* DROP must be fully qualified in case same name appears in
11991
appendPQExpBuffer(delq, "DROP %s %s.", reltypename,
11992
fmtId(tbinfo->dobj.namespace->dobj.name));
11993
appendPQExpBuffer(delq, "%s;\n",
11994
fmtId(tbinfo->dobj.name));
11996
appendPQExpBuffer(labelq, "%s %s", reltypename,
11997
fmtId(tbinfo->dobj.name));
11999
if (binary_upgrade)
12000
binary_upgrade_set_pg_class_oids(q, tbinfo->dobj.catId.oid, false);
12002
appendPQExpBuffer(q, "CREATE %s%s %s",
12003
tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ?
12006
fmtId(tbinfo->dobj.name));
12008
* In case of a binary upgrade, we dump the table normally and attach
12009
* it to the type afterward.
12011
if (tbinfo->reloftype && !binary_upgrade)
12012
appendPQExpBuffer(q, " OF %s", tbinfo->reloftype);
12014
for (j = 0; j < tbinfo->numatts; j++)
12017
* Normally, dump if it's one of the table's own attrs, and not
12018
* dropped. But for binary upgrade, dump all the columns.
12020
if ((!tbinfo->inhAttrs[j] && !tbinfo->attisdropped[j]) ||
12024
* Default value --- suppress if inherited (except in
12025
* binary-upgrade case, where we're not doing normal
12026
* inheritance) or if it's to be printed separately.
12028
bool has_default = (tbinfo->attrdefs[j] != NULL
12029
&& (!tbinfo->inhAttrDef[j] || binary_upgrade)
12030
&& !tbinfo->attrdefs[j]->separate);
12033
* Not Null constraint --- suppress if inherited, except in
12034
* binary-upgrade case.
12036
bool has_notnull = (tbinfo->notnull[j]
12037
&& (!tbinfo->inhNotNull[j] || binary_upgrade));
12039
if (tbinfo->reloftype && !has_default && !has_notnull && !binary_upgrade)
12042
/* Format properly if not first attr */
12043
if (actual_atts == 0)
12044
appendPQExpBuffer(q, " (");
12046
appendPQExpBuffer(q, ",");
12047
appendPQExpBuffer(q, "\n ");
12050
/* Attribute name */
12051
appendPQExpBuffer(q, "%s ",
12052
fmtId(tbinfo->attnames[j]));
12054
if (tbinfo->attisdropped[j])
12057
* ALTER TABLE DROP COLUMN clears pg_attribute.atttypid,
12058
* so we will not have gotten a valid type name; insert
12059
* INTEGER as a stopgap. We'll clean things up later.
12061
appendPQExpBuffer(q, "INTEGER /* dummy */");
12062
/* Skip all the rest, too */
12066
/* Attribute type */
12067
if (tbinfo->reloftype && !binary_upgrade)
12069
appendPQExpBuffer(q, "WITH OPTIONS");
12071
else if (g_fout->remoteVersion >= 70100)
12073
appendPQExpBuffer(q, "%s",
12074
tbinfo->atttypnames[j]);
12078
/* If no format_type, fake it */
12079
appendPQExpBuffer(q, "%s",
12080
myFormatType(tbinfo->atttypnames[j],
12081
tbinfo->atttypmod[j]));
12084
/* Add collation if not default for the type */
12085
if (OidIsValid(tbinfo->attcollation[j]))
12089
coll = findCollationByOid(tbinfo->attcollation[j]);
12092
/* always schema-qualify, don't try to be smart */
12093
appendPQExpBuffer(q, " COLLATE %s.",
12094
fmtId(coll->dobj.namespace->dobj.name));
12095
appendPQExpBuffer(q, "%s",
12096
fmtId(coll->dobj.name));
12101
appendPQExpBuffer(q, " DEFAULT %s",
12102
tbinfo->attrdefs[j]->adef_expr);
12105
appendPQExpBuffer(q, " NOT NULL");
12110
* Add non-inherited CHECK constraints, if any.
12112
for (j = 0; j < tbinfo->ncheck; j++)
12114
ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
12116
if (constr->separate || !constr->conislocal)
12119
if (actual_atts == 0)
12120
appendPQExpBuffer(q, " (\n ");
12122
appendPQExpBuffer(q, ",\n ");
12124
appendPQExpBuffer(q, "CONSTRAINT %s ",
12125
fmtId(constr->dobj.name));
12126
appendPQExpBuffer(q, "%s", constr->condef);
12132
appendPQExpBuffer(q, "\n)");
12133
else if (!(tbinfo->reloftype && !binary_upgrade))
12136
* We must have a parenthesized attribute list, even though empty,
12137
* when not using the OF TYPE syntax.
12139
appendPQExpBuffer(q, " (\n)");
12142
if (numParents > 0 && !binary_upgrade)
12144
appendPQExpBuffer(q, "\nINHERITS (");
12145
for (k = 0; k < numParents; k++)
12147
TableInfo *parentRel = parents[k];
12150
appendPQExpBuffer(q, ", ");
12151
if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
12152
appendPQExpBuffer(q, "%s.",
12153
fmtId(parentRel->dobj.namespace->dobj.name));
12154
appendPQExpBuffer(q, "%s",
12155
fmtId(parentRel->dobj.name));
12157
appendPQExpBuffer(q, ")");
12160
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
12161
appendPQExpBuffer(q, "\nSERVER %s", srvname);
12163
if ((tbinfo->reloptions && strlen(tbinfo->reloptions) > 0) ||
12164
(tbinfo->toast_reloptions && strlen(tbinfo->toast_reloptions) > 0))
12166
bool addcomma = false;
12168
appendPQExpBuffer(q, "\nWITH (");
12169
if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
12172
appendPQExpBuffer(q, "%s", tbinfo->reloptions);
12174
if (tbinfo->toast_reloptions && strlen(tbinfo->toast_reloptions) > 0)
12176
appendPQExpBuffer(q, "%s%s", addcomma ? ", " : "",
12177
tbinfo->toast_reloptions);
12179
appendPQExpBuffer(q, ")");
12182
/* Dump generic options if any */
12183
if (ftoptions && ftoptions[0])
12184
appendPQExpBuffer(q, "\nOPTIONS (%s)", ftoptions);
12186
appendPQExpBuffer(q, ";\n");
12189
* To create binary-compatible heap files, we have to ensure the same
12190
* physical column order, including dropped columns, as in the
12191
* original. Therefore, we create dropped columns above and drop them
12192
* here, also updating their attlen/attalign values so that the
12193
* dropped column can be skipped properly. (We do not bother with
12194
* restoring the original attbyval setting.) Also, inheritance
12195
* relationships are set up by doing ALTER INHERIT rather than using
12196
* an INHERITS clause --- the latter would possibly mess up the column
12197
* order. That also means we have to take care about setting
12198
* attislocal correctly, plus fix up any inherited CHECK constraints.
12199
* Analogously, we set up typed tables using ALTER TABLE / OF here.
12201
if (binary_upgrade && tbinfo->relkind == RELKIND_RELATION)
12203
for (j = 0; j < tbinfo->numatts; j++)
12205
if (tbinfo->attisdropped[j])
12207
appendPQExpBuffer(q, "\n-- For binary upgrade, recreate dropped column.\n");
12208
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_attribute\n"
12209
"SET attlen = %d, "
12210
"attalign = '%c', attbyval = false\n"
12211
"WHERE attname = ",
12213
tbinfo->attalign[j]);
12214
appendStringLiteralAH(q, tbinfo->attnames[j], fout);
12215
appendPQExpBuffer(q, "\n AND attrelid = ");
12216
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
12217
appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
12219
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
12220
fmtId(tbinfo->dobj.name));
12221
appendPQExpBuffer(q, "DROP COLUMN %s;\n",
12222
fmtId(tbinfo->attnames[j]));
12224
else if (!tbinfo->attislocal[j])
12226
appendPQExpBuffer(q, "\n-- For binary upgrade, recreate inherited column.\n");
12227
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_attribute\n"
12228
"SET attislocal = false\n"
12229
"WHERE attname = ");
12230
appendStringLiteralAH(q, tbinfo->attnames[j], fout);
12231
appendPQExpBuffer(q, "\n AND attrelid = ");
12232
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
12233
appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
12237
for (k = 0; k < tbinfo->ncheck; k++)
12239
ConstraintInfo *constr = &(tbinfo->checkexprs[k]);
12241
if (constr->separate || constr->conislocal)
12244
appendPQExpBuffer(q, "\n-- For binary upgrade, set up inherited constraint.\n");
12245
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
12246
fmtId(tbinfo->dobj.name));
12247
appendPQExpBuffer(q, " ADD CONSTRAINT %s ",
12248
fmtId(constr->dobj.name));
12249
appendPQExpBuffer(q, "%s;\n", constr->condef);
12250
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_constraint\n"
12251
"SET conislocal = false\n"
12252
"WHERE contype = 'c' AND conname = ");
12253
appendStringLiteralAH(q, constr->dobj.name, fout);
12254
appendPQExpBuffer(q, "\n AND conrelid = ");
12255
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
12256
appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
12259
if (numParents > 0)
12261
appendPQExpBuffer(q, "\n-- For binary upgrade, set up inheritance this way.\n");
12262
for (k = 0; k < numParents; k++)
12264
TableInfo *parentRel = parents[k];
12266
appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT ",
12267
fmtId(tbinfo->dobj.name));
12268
if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
12269
appendPQExpBuffer(q, "%s.",
12270
fmtId(parentRel->dobj.namespace->dobj.name));
12271
appendPQExpBuffer(q, "%s;\n",
12272
fmtId(parentRel->dobj.name));
12276
if (tbinfo->reloftype)
12278
appendPQExpBuffer(q, "\n-- For binary upgrade, set up typed tables this way.\n");
12279
appendPQExpBuffer(q, "ALTER TABLE ONLY %s OF %s;\n",
12280
fmtId(tbinfo->dobj.name),
12281
tbinfo->reloftype);
12284
appendPQExpBuffer(q, "\n-- For binary upgrade, set heap's relfrozenxid\n");
12285
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
12286
"SET relfrozenxid = '%u'\n"
12288
tbinfo->frozenxid);
12289
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
12290
appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
12292
if (tbinfo->toast_oid)
12294
/* We preserve the toast oids, so we can use it during restore */
12295
appendPQExpBuffer(q, "\n-- For binary upgrade, set toast's relfrozenxid\n");
12296
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
12297
"SET relfrozenxid = '%u'\n"
12298
"WHERE oid = '%u';\n",
12299
tbinfo->toast_frozenxid, tbinfo->toast_oid);
12303
/* Loop dumping statistics and storage statements */
12304
for (j = 0; j < tbinfo->numatts; j++)
12307
* Dump per-column statistics information. We only issue an ALTER
12308
* TABLE statement if the attstattarget entry for this column is
12309
* non-negative (i.e. it's not the default value)
12311
if (tbinfo->attstattarget[j] >= 0 &&
12312
!tbinfo->attisdropped[j])
12314
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
12315
fmtId(tbinfo->dobj.name));
12316
appendPQExpBuffer(q, "ALTER COLUMN %s ",
12317
fmtId(tbinfo->attnames[j]));
12318
appendPQExpBuffer(q, "SET STATISTICS %d;\n",
12319
tbinfo->attstattarget[j]);
12323
* Dump per-column storage information. The statement is only
12324
* dumped if the storage has been changed from the type's default.
12326
if (!tbinfo->attisdropped[j] && tbinfo->attstorage[j] != tbinfo->typstorage[j])
12328
switch (tbinfo->attstorage[j])
12334
storage = "EXTERNAL";
12340
storage = "EXTENDED";
12347
* Only dump the statement if it's a storage type we recognize
12349
if (storage != NULL)
12351
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
12352
fmtId(tbinfo->dobj.name));
12353
appendPQExpBuffer(q, "ALTER COLUMN %s ",
12354
fmtId(tbinfo->attnames[j]));
12355
appendPQExpBuffer(q, "SET STORAGE %s;\n",
12361
* Dump per-column attributes.
12363
if (tbinfo->attoptions[j] && tbinfo->attoptions[j][0] != '\0')
12365
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
12366
fmtId(tbinfo->dobj.name));
12367
appendPQExpBuffer(q, "ALTER COLUMN %s ",
12368
fmtId(tbinfo->attnames[j]));
12369
appendPQExpBuffer(q, "SET (%s);\n",
12370
tbinfo->attoptions[j]);
12375
if (binary_upgrade)
12376
binary_upgrade_extension_member(q, &tbinfo->dobj, labelq->data);
12378
ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
12380
tbinfo->dobj.namespace->dobj.name,
12381
(tbinfo->relkind == RELKIND_VIEW) ? NULL : tbinfo->reltablespace,
12383
(strcmp(reltypename, "TABLE") == 0) ? tbinfo->hasoids : false,
12384
reltypename, SECTION_PRE_DATA,
12385
q->data, delq->data, NULL,
12386
tbinfo->dobj.dependencies, tbinfo->dobj.nDeps,
12390
/* Dump Table Comments */
12391
dumpTableComment(fout, tbinfo, reltypename);
12393
/* Dump Table Security Labels */
12394
dumpTableSecLabel(fout, tbinfo, reltypename);
12396
/* Dump comments on inlined table constraints */
12397
for (j = 0; j < tbinfo->ncheck; j++)
12399
ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
12401
if (constr->separate || !constr->conislocal)
12404
dumpTableConstraintComment(fout, constr);
12407
destroyPQExpBuffer(query);
12408
destroyPQExpBuffer(q);
12409
destroyPQExpBuffer(delq);
12410
destroyPQExpBuffer(labelq);
12414
* dumpAttrDef --- dump an attribute's default-value declaration
12417
dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
12419
TableInfo *tbinfo = adinfo->adtable;
12420
int adnum = adinfo->adnum;
12424
/* Only print it if "separate" mode is selected */
12425
if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly)
12428
/* Don't print inherited defaults, either, except for binary upgrade */
12429
if (tbinfo->inhAttrDef[adnum - 1] && !binary_upgrade)
12432
q = createPQExpBuffer();
12433
delq = createPQExpBuffer();
12435
appendPQExpBuffer(q, "ALTER TABLE %s ",
12436
fmtId(tbinfo->dobj.name));
12437
appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
12438
fmtId(tbinfo->attnames[adnum - 1]),
12439
adinfo->adef_expr);
12442
* DROP must be fully qualified in case same name appears in pg_catalog
12444
appendPQExpBuffer(delq, "ALTER TABLE %s.",
12445
fmtId(tbinfo->dobj.namespace->dobj.name));
12446
appendPQExpBuffer(delq, "%s ",
12447
fmtId(tbinfo->dobj.name));
12448
appendPQExpBuffer(delq, "ALTER COLUMN %s DROP DEFAULT;\n",
12449
fmtId(tbinfo->attnames[adnum - 1]));
12451
ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId,
12452
tbinfo->attnames[adnum - 1],
12453
tbinfo->dobj.namespace->dobj.name,
12456
false, "DEFAULT", SECTION_PRE_DATA,
12457
q->data, delq->data, NULL,
12458
adinfo->dobj.dependencies, adinfo->dobj.nDeps,
12461
destroyPQExpBuffer(q);
12462
destroyPQExpBuffer(delq);
12466
* getAttrName: extract the correct name for an attribute
12468
* The array tblInfo->attnames[] only provides names of user attributes;
12469
* if a system attribute number is supplied, we have to fake it.
12470
* We also do a little bit of bounds checking for safety's sake.
12472
static const char *
12473
getAttrName(int attrnum, TableInfo *tblInfo)
12475
if (attrnum > 0 && attrnum <= tblInfo->numatts)
12476
return tblInfo->attnames[attrnum - 1];
12479
case SelfItemPointerAttributeNumber:
12481
case ObjectIdAttributeNumber:
12483
case MinTransactionIdAttributeNumber:
12485
case MinCommandIdAttributeNumber:
12487
case MaxTransactionIdAttributeNumber:
12489
case MaxCommandIdAttributeNumber:
12491
case TableOidAttributeNumber:
12494
write_msg(NULL, "invalid column number %d for table \"%s\"\n",
12495
attrnum, tblInfo->dobj.name);
12497
return NULL; /* keep compiler quiet */
12502
* write out to fout a user-defined index
12505
dumpIndex(Archive *fout, IndxInfo *indxinfo)
12507
TableInfo *tbinfo = indxinfo->indextable;
12510
PQExpBuffer labelq;
12515
q = createPQExpBuffer();
12516
delq = createPQExpBuffer();
12517
labelq = createPQExpBuffer();
12519
appendPQExpBuffer(labelq, "INDEX %s",
12520
fmtId(indxinfo->dobj.name));
12523
* If there's an associated constraint, don't dump the index per se, but
12524
* do dump any comment for it. (This is safe because dependency ordering
12525
* will have ensured the constraint is emitted first.)
12527
if (indxinfo->indexconstraint == 0)
12529
if (binary_upgrade)
12530
binary_upgrade_set_pg_class_oids(q, indxinfo->dobj.catId.oid, true);
12532
/* Plain secondary index */
12533
appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef);
12535
/* If the index is clustered, we need to record that. */
12536
if (indxinfo->indisclustered)
12538
appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
12539
fmtId(tbinfo->dobj.name));
12540
appendPQExpBuffer(q, " ON %s;\n",
12541
fmtId(indxinfo->dobj.name));
12545
* DROP must be fully qualified in case same name appears in
12548
appendPQExpBuffer(delq, "DROP INDEX %s.",
12549
fmtId(tbinfo->dobj.namespace->dobj.name));
12550
appendPQExpBuffer(delq, "%s;\n",
12551
fmtId(indxinfo->dobj.name));
12553
ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
12554
indxinfo->dobj.name,
12555
tbinfo->dobj.namespace->dobj.name,
12556
indxinfo->tablespace,
12557
tbinfo->rolname, false,
12558
"INDEX", SECTION_POST_DATA,
12559
q->data, delq->data, NULL,
12560
indxinfo->dobj.dependencies, indxinfo->dobj.nDeps,
12564
/* Dump Index Comments */
12565
dumpComment(fout, labelq->data,
12566
tbinfo->dobj.namespace->dobj.name,
12568
indxinfo->dobj.catId, 0, indxinfo->dobj.dumpId);
12570
destroyPQExpBuffer(q);
12571
destroyPQExpBuffer(delq);
12572
destroyPQExpBuffer(labelq);
12577
* write out to fout a user-defined constraint
12580
dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
12582
TableInfo *tbinfo = coninfo->contable;
12586
/* Skip if not to be dumped */
12587
if (!coninfo->dobj.dump || dataOnly)
12590
q = createPQExpBuffer();
12591
delq = createPQExpBuffer();
12593
if (coninfo->contype == 'p' ||
12594
coninfo->contype == 'u' ||
12595
coninfo->contype == 'x')
12597
/* Index-related constraint */
12598
IndxInfo *indxinfo;
12601
indxinfo = (IndxInfo *) findObjectByDumpId(coninfo->conindex);
12603
if (indxinfo == NULL)
12605
write_msg(NULL, "missing index for constraint \"%s\"\n",
12606
coninfo->dobj.name);
12610
if (binary_upgrade && !coninfo->condef)
12611
binary_upgrade_set_pg_class_oids(q, indxinfo->dobj.catId.oid, true);
12613
appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
12614
fmtId(tbinfo->dobj.name));
12615
appendPQExpBuffer(q, " ADD CONSTRAINT %s ",
12616
fmtId(coninfo->dobj.name));
12618
if (coninfo->condef)
12620
/* pg_get_constraintdef should have provided everything */
12621
appendPQExpBuffer(q, "%s;\n", coninfo->condef);
12625
appendPQExpBuffer(q, "%s (",
12626
coninfo->contype == 'p' ? "PRIMARY KEY" : "UNIQUE");
12627
for (k = 0; k < indxinfo->indnkeys; k++)
12629
int indkey = (int) indxinfo->indkeys[k];
12630
const char *attname;
12632
if (indkey == InvalidAttrNumber)
12634
attname = getAttrName(indkey, tbinfo);
12636
appendPQExpBuffer(q, "%s%s",
12637
(k == 0) ? "" : ", ",
12641
appendPQExpBuffer(q, ")");
12643
if (indxinfo->options && strlen(indxinfo->options) > 0)
12644
appendPQExpBuffer(q, " WITH (%s)", indxinfo->options);
12646
if (coninfo->condeferrable)
12648
appendPQExpBuffer(q, " DEFERRABLE");
12649
if (coninfo->condeferred)
12650
appendPQExpBuffer(q, " INITIALLY DEFERRED");
12653
appendPQExpBuffer(q, ";\n");
12656
/* If the index is clustered, we need to record that. */
12657
if (indxinfo->indisclustered)
12659
appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
12660
fmtId(tbinfo->dobj.name));
12661
appendPQExpBuffer(q, " ON %s;\n",
12662
fmtId(indxinfo->dobj.name));
12666
* DROP must be fully qualified in case same name appears in
12669
appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
12670
fmtId(tbinfo->dobj.namespace->dobj.name));
12671
appendPQExpBuffer(delq, "%s ",
12672
fmtId(tbinfo->dobj.name));
12673
appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
12674
fmtId(coninfo->dobj.name));
12676
ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
12677
coninfo->dobj.name,
12678
tbinfo->dobj.namespace->dobj.name,
12679
indxinfo->tablespace,
12680
tbinfo->rolname, false,
12681
"CONSTRAINT", SECTION_POST_DATA,
12682
q->data, delq->data, NULL,
12683
coninfo->dobj.dependencies, coninfo->dobj.nDeps,
12686
else if (coninfo->contype == 'f')
12689
* XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that the
12690
* current table data is not processed
12692
appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
12693
fmtId(tbinfo->dobj.name));
12694
appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
12695
fmtId(coninfo->dobj.name),
12699
* DROP must be fully qualified in case same name appears in
12702
appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
12703
fmtId(tbinfo->dobj.namespace->dobj.name));
12704
appendPQExpBuffer(delq, "%s ",
12705
fmtId(tbinfo->dobj.name));
12706
appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
12707
fmtId(coninfo->dobj.name));
12709
ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
12710
coninfo->dobj.name,
12711
tbinfo->dobj.namespace->dobj.name,
12713
tbinfo->rolname, false,
12714
"FK CONSTRAINT", SECTION_POST_DATA,
12715
q->data, delq->data, NULL,
12716
coninfo->dobj.dependencies, coninfo->dobj.nDeps,
12719
else if (coninfo->contype == 'c' && tbinfo)
12721
/* CHECK constraint on a table */
12723
/* Ignore if not to be dumped separately */
12724
if (coninfo->separate)
12726
/* not ONLY since we want it to propagate to children */
12727
appendPQExpBuffer(q, "ALTER TABLE %s\n",
12728
fmtId(tbinfo->dobj.name));
12729
appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
12730
fmtId(coninfo->dobj.name),
12734
* DROP must be fully qualified in case same name appears in
12737
appendPQExpBuffer(delq, "ALTER TABLE %s.",
12738
fmtId(tbinfo->dobj.namespace->dobj.name));
12739
appendPQExpBuffer(delq, "%s ",
12740
fmtId(tbinfo->dobj.name));
12741
appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
12742
fmtId(coninfo->dobj.name));
12744
ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
12745
coninfo->dobj.name,
12746
tbinfo->dobj.namespace->dobj.name,
12748
tbinfo->rolname, false,
12749
"CHECK CONSTRAINT", SECTION_POST_DATA,
12750
q->data, delq->data, NULL,
12751
coninfo->dobj.dependencies, coninfo->dobj.nDeps,
12755
else if (coninfo->contype == 'c' && tbinfo == NULL)
12757
/* CHECK constraint on a domain */
12758
TypeInfo *tyinfo = coninfo->condomain;
12760
/* Ignore if not to be dumped separately */
12761
if (coninfo->separate)
12763
appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
12764
fmtId(tyinfo->dobj.name));
12765
appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
12766
fmtId(coninfo->dobj.name),
12770
* DROP must be fully qualified in case same name appears in
12773
appendPQExpBuffer(delq, "ALTER DOMAIN %s.",
12774
fmtId(tyinfo->dobj.namespace->dobj.name));
12775
appendPQExpBuffer(delq, "%s ",
12776
fmtId(tyinfo->dobj.name));
12777
appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
12778
fmtId(coninfo->dobj.name));
12780
ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
12781
coninfo->dobj.name,
12782
tyinfo->dobj.namespace->dobj.name,
12784
tyinfo->rolname, false,
12785
"CHECK CONSTRAINT", SECTION_POST_DATA,
12786
q->data, delq->data, NULL,
12787
coninfo->dobj.dependencies, coninfo->dobj.nDeps,
12793
write_msg(NULL, "unrecognized constraint type: %c\n", coninfo->contype);
12797
/* Dump Constraint Comments --- only works for table constraints */
12798
if (tbinfo && coninfo->separate)
12799
dumpTableConstraintComment(fout, coninfo);
12801
destroyPQExpBuffer(q);
12802
destroyPQExpBuffer(delq);
12806
* dumpTableConstraintComment --- dump a constraint's comment if any
12808
* This is split out because we need the function in two different places
12809
* depending on whether the constraint is dumped as part of CREATE TABLE
12810
* or as a separate ALTER command.
12813
dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo)
12815
TableInfo *tbinfo = coninfo->contable;
12816
PQExpBuffer labelq = createPQExpBuffer();
12818
appendPQExpBuffer(labelq, "CONSTRAINT %s ",
12819
fmtId(coninfo->dobj.name));
12820
appendPQExpBuffer(labelq, "ON %s",
12821
fmtId(tbinfo->dobj.name));
12822
dumpComment(fout, labelq->data,
12823
tbinfo->dobj.namespace->dobj.name,
12825
coninfo->dobj.catId, 0,
12826
coninfo->separate ? coninfo->dobj.dumpId : tbinfo->dobj.dumpId);
12828
destroyPQExpBuffer(labelq);
12832
* findLastBuiltInOid -
12833
* find the last built in oid
12835
* For 7.1 and 7.2, we do this by retrieving datlastsysoid from the
12836
* pg_database entry for the current database
12839
findLastBuiltinOid_V71(const char *dbname)
12844
PQExpBuffer query = createPQExpBuffer();
12846
resetPQExpBuffer(query);
12847
appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = ");
12848
appendStringLiteralAH(query, dbname, g_fout);
12850
res = PQexec(g_conn, query->data);
12851
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
12853
ntups = PQntuples(res);
12856
write_msg(NULL, "missing pg_database entry for this database\n");
12861
write_msg(NULL, "found more than one pg_database entry for this database\n");
12864
last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "datlastsysoid")));
12866
destroyPQExpBuffer(query);
12871
* findLastBuiltInOid -
12872
* find the last built in oid
12874
* For 7.0, we do this by assuming that the last thing that initdb does is to
12875
* create the pg_indexes view. This sucks in general, but seeing that 7.0.x
12876
* initdb won't be changing anymore, it'll do.
12879
findLastBuiltinOid_V70(void)
12885
res = PQexec(g_conn,
12886
"SELECT oid FROM pg_class WHERE relname = 'pg_indexes'");
12887
check_sql_result(res, g_conn,
12888
"SELECT oid FROM pg_class WHERE relname = 'pg_indexes'",
12890
ntups = PQntuples(res);
12893
write_msg(NULL, "could not find entry for pg_indexes in pg_class\n");
12898
write_msg(NULL, "found more than one entry for pg_indexes in pg_class\n");
12901
last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "oid")));
12907
dumpSequence(Archive *fout, TableInfo *tbinfo)
12920
PQExpBuffer query = createPQExpBuffer();
12921
PQExpBuffer delqry = createPQExpBuffer();
12922
PQExpBuffer labelq = createPQExpBuffer();
12924
/* Make sure we are in proper schema */
12925
selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
12927
snprintf(bufm, sizeof(bufm), INT64_FORMAT, SEQ_MINVALUE);
12928
snprintf(bufx, sizeof(bufx), INT64_FORMAT, SEQ_MAXVALUE);
12930
if (g_fout->remoteVersion >= 80400)
12932
appendPQExpBuffer(query,
12933
"SELECT sequence_name, "
12934
"start_value, last_value, increment_by, "
12935
"CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
12936
" WHEN increment_by < 0 AND max_value = -1 THEN NULL "
12938
"END AS max_value, "
12939
"CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
12940
" WHEN increment_by < 0 AND min_value = %s THEN NULL "
12942
"END AS min_value, "
12943
"cache_value, is_cycled, is_called from %s",
12945
fmtId(tbinfo->dobj.name));
12949
appendPQExpBuffer(query,
12950
"SELECT sequence_name, "
12951
"0 AS start_value, last_value, increment_by, "
12952
"CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
12953
" WHEN increment_by < 0 AND max_value = -1 THEN NULL "
12955
"END AS max_value, "
12956
"CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
12957
" WHEN increment_by < 0 AND min_value = %s THEN NULL "
12959
"END AS min_value, "
12960
"cache_value, is_cycled, is_called from %s",
12962
fmtId(tbinfo->dobj.name));
12965
res = PQexec(g_conn, query->data);
12966
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
12968
if (PQntuples(res) != 1)
12970
write_msg(NULL, ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)\n",
12971
"query to get data of sequence \"%s\" returned %d rows (expected 1)\n",
12973
tbinfo->dobj.name, PQntuples(res));
12977
/* Disable this check: it fails if sequence has been renamed */
12979
if (strcmp(PQgetvalue(res, 0, 0), tbinfo->dobj.name) != 0)
12981
write_msg(NULL, "query to get data of sequence \"%s\" returned name \"%s\"\n",
12982
tbinfo->dobj.name, PQgetvalue(res, 0, 0));
12987
startv = PQgetvalue(res, 0, 1);
12988
last = PQgetvalue(res, 0, 2);
12989
incby = PQgetvalue(res, 0, 3);
12990
if (!PQgetisnull(res, 0, 4))
12991
maxv = PQgetvalue(res, 0, 4);
12992
if (!PQgetisnull(res, 0, 5))
12993
minv = PQgetvalue(res, 0, 5);
12994
cache = PQgetvalue(res, 0, 6);
12995
cycled = (strcmp(PQgetvalue(res, 0, 7), "t") == 0);
12996
called = (strcmp(PQgetvalue(res, 0, 8), "t") == 0);
12999
* The logic we use for restoring sequences is as follows:
13001
* Add a CREATE SEQUENCE statement as part of a "schema" dump (use
13002
* last_val for start if called is false, else use min_val for start_val).
13003
* Also, if the sequence is owned by a column, add an ALTER SEQUENCE OWNED
13004
* BY command for it.
13006
* Add a 'SETVAL(seq, last_val, iscalled)' as part of a "data" dump.
13011
* DROP must be fully qualified in case same name appears in
13014
appendPQExpBuffer(delqry, "DROP SEQUENCE %s.",
13015
fmtId(tbinfo->dobj.namespace->dobj.name));
13016
appendPQExpBuffer(delqry, "%s;\n",
13017
fmtId(tbinfo->dobj.name));
13019
resetPQExpBuffer(query);
13021
if (binary_upgrade)
13023
binary_upgrade_set_pg_class_oids(query, tbinfo->dobj.catId.oid, false);
13024
binary_upgrade_set_type_oids_by_rel_oid(query, tbinfo->dobj.catId.oid);
13027
appendPQExpBuffer(query,
13028
"CREATE SEQUENCE %s\n",
13029
fmtId(tbinfo->dobj.name));
13031
if (g_fout->remoteVersion >= 80400)
13032
appendPQExpBuffer(query, " START WITH %s\n", startv);
13036
* Versions before 8.4 did not remember the true start value. If
13037
* is_called is false then the sequence has never been incremented
13038
* so we can use last_val. Otherwise punt and let it default.
13041
appendPQExpBuffer(query, " START WITH %s\n", last);
13044
appendPQExpBuffer(query, " INCREMENT BY %s\n", incby);
13047
appendPQExpBuffer(query, " MINVALUE %s\n", minv);
13049
appendPQExpBuffer(query, " NO MINVALUE\n");
13052
appendPQExpBuffer(query, " MAXVALUE %s\n", maxv);
13054
appendPQExpBuffer(query, " NO MAXVALUE\n");
13056
appendPQExpBuffer(query,
13058
cache, (cycled ? "\n CYCLE" : ""));
13060
appendPQExpBuffer(query, ";\n");
13062
appendPQExpBuffer(labelq, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
13064
/* binary_upgrade: no need to clear TOAST table oid */
13066
if (binary_upgrade)
13067
binary_upgrade_extension_member(query, &tbinfo->dobj,
13070
ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
13072
tbinfo->dobj.namespace->dobj.name,
13075
false, "SEQUENCE", SECTION_PRE_DATA,
13076
query->data, delqry->data, NULL,
13077
tbinfo->dobj.dependencies, tbinfo->dobj.nDeps,
13081
* If the sequence is owned by a table column, emit the ALTER for it
13082
* as a separate TOC entry immediately following the sequence's own
13083
* entry. It's OK to do this rather than using full sorting logic,
13084
* because the dependency that tells us it's owned will have forced
13085
* the table to be created first. We can't just include the ALTER in
13086
* the TOC entry because it will fail if we haven't reassigned the
13087
* sequence owner to match the table's owner.
13089
* We need not schema-qualify the table reference because both
13090
* sequence and table must be in the same schema.
13092
if (OidIsValid(tbinfo->owning_tab))
13094
TableInfo *owning_tab = findTableByOid(tbinfo->owning_tab);
13096
if (owning_tab && owning_tab->dobj.dump)
13098
resetPQExpBuffer(query);
13099
appendPQExpBuffer(query, "ALTER SEQUENCE %s",
13100
fmtId(tbinfo->dobj.name));
13101
appendPQExpBuffer(query, " OWNED BY %s",
13102
fmtId(owning_tab->dobj.name));
13103
appendPQExpBuffer(query, ".%s;\n",
13104
fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
13106
ArchiveEntry(fout, nilCatalogId, createDumpId(),
13108
tbinfo->dobj.namespace->dobj.name,
13111
false, "SEQUENCE OWNED BY", SECTION_PRE_DATA,
13112
query->data, "", NULL,
13113
&(tbinfo->dobj.dumpId), 1,
13118
/* Dump Sequence Comments and Security Labels */
13119
dumpComment(fout, labelq->data,
13120
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
13121
tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
13122
dumpSecLabel(fout, labelq->data,
13123
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
13124
tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
13129
resetPQExpBuffer(query);
13130
appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
13131
appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
13132
appendPQExpBuffer(query, ", %s, %s);\n",
13133
last, (called ? "true" : "false"));
13135
ArchiveEntry(fout, nilCatalogId, createDumpId(),
13137
tbinfo->dobj.namespace->dobj.name,
13140
false, "SEQUENCE SET", SECTION_PRE_DATA,
13141
query->data, "", NULL,
13142
&(tbinfo->dobj.dumpId), 1,
13148
destroyPQExpBuffer(query);
13149
destroyPQExpBuffer(delqry);
13150
destroyPQExpBuffer(labelq);
13154
dumpTrigger(Archive *fout, TriggerInfo *tginfo)
13156
TableInfo *tbinfo = tginfo->tgtable;
13158
PQExpBuffer delqry;
13159
PQExpBuffer labelq;
13168
query = createPQExpBuffer();
13169
delqry = createPQExpBuffer();
13170
labelq = createPQExpBuffer();
13173
* DROP must be fully qualified in case same name appears in pg_catalog
13175
appendPQExpBuffer(delqry, "DROP TRIGGER %s ",
13176
fmtId(tginfo->dobj.name));
13177
appendPQExpBuffer(delqry, "ON %s.",
13178
fmtId(tbinfo->dobj.namespace->dobj.name));
13179
appendPQExpBuffer(delqry, "%s;\n",
13180
fmtId(tbinfo->dobj.name));
13184
appendPQExpBuffer(query, "%s;\n", tginfo->tgdef);
13188
if (tginfo->tgisconstraint)
13190
appendPQExpBuffer(query, "CREATE CONSTRAINT TRIGGER ");
13191
appendPQExpBufferStr(query, fmtId(tginfo->tgconstrname));
13195
appendPQExpBuffer(query, "CREATE TRIGGER ");
13196
appendPQExpBufferStr(query, fmtId(tginfo->dobj.name));
13198
appendPQExpBuffer(query, "\n ");
13201
if (TRIGGER_FOR_BEFORE(tginfo->tgtype))
13202
appendPQExpBuffer(query, "BEFORE");
13203
else if (TRIGGER_FOR_AFTER(tginfo->tgtype))
13204
appendPQExpBuffer(query, "AFTER");
13205
else if (TRIGGER_FOR_INSTEAD(tginfo->tgtype))
13206
appendPQExpBuffer(query, "INSTEAD OF");
13209
write_msg(NULL, "unexpected tgtype value: %d\n", tginfo->tgtype);
13214
if (TRIGGER_FOR_INSERT(tginfo->tgtype))
13216
appendPQExpBuffer(query, " INSERT");
13219
if (TRIGGER_FOR_DELETE(tginfo->tgtype))
13222
appendPQExpBuffer(query, " OR DELETE");
13224
appendPQExpBuffer(query, " DELETE");
13227
if (TRIGGER_FOR_UPDATE(tginfo->tgtype))
13230
appendPQExpBuffer(query, " OR UPDATE");
13232
appendPQExpBuffer(query, " UPDATE");
13235
if (TRIGGER_FOR_TRUNCATE(tginfo->tgtype))
13238
appendPQExpBuffer(query, " OR TRUNCATE");
13240
appendPQExpBuffer(query, " TRUNCATE");
13243
appendPQExpBuffer(query, " ON %s\n",
13244
fmtId(tbinfo->dobj.name));
13246
if (tginfo->tgisconstraint)
13248
if (OidIsValid(tginfo->tgconstrrelid))
13250
/* If we are using regclass, name is already quoted */
13251
if (g_fout->remoteVersion >= 70300)
13252
appendPQExpBuffer(query, " FROM %s\n ",
13253
tginfo->tgconstrrelname);
13255
appendPQExpBuffer(query, " FROM %s\n ",
13256
fmtId(tginfo->tgconstrrelname));
13258
if (!tginfo->tgdeferrable)
13259
appendPQExpBuffer(query, "NOT ");
13260
appendPQExpBuffer(query, "DEFERRABLE INITIALLY ");
13261
if (tginfo->tginitdeferred)
13262
appendPQExpBuffer(query, "DEFERRED\n");
13264
appendPQExpBuffer(query, "IMMEDIATE\n");
13267
if (TRIGGER_FOR_ROW(tginfo->tgtype))
13268
appendPQExpBuffer(query, " FOR EACH ROW\n ");
13270
appendPQExpBuffer(query, " FOR EACH STATEMENT\n ");
13272
/* In 7.3, result of regproc is already quoted */
13273
if (g_fout->remoteVersion >= 70300)
13274
appendPQExpBuffer(query, "EXECUTE PROCEDURE %s(",
13277
appendPQExpBuffer(query, "EXECUTE PROCEDURE %s(",
13278
fmtId(tginfo->tgfname));
13280
tgargs = (char *) PQunescapeBytea((unsigned char *) tginfo->tgargs,
13283
for (findx = 0; findx < tginfo->tgnargs; findx++)
13285
/* find the embedded null that terminates this trigger argument */
13286
size_t tlen = strlen(p);
13288
if (p + tlen >= tgargs + lentgargs)
13290
/* hm, not found before end of bytea value... */
13291
write_msg(NULL, "invalid argument string (%s) for trigger \"%s\" on table \"%s\"\n",
13294
tbinfo->dobj.name);
13299
appendPQExpBuffer(query, ", ");
13300
appendStringLiteralAH(query, p, fout);
13304
appendPQExpBuffer(query, ");\n");
13307
if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
13309
appendPQExpBuffer(query, "\nALTER TABLE %s ",
13310
fmtId(tbinfo->dobj.name));
13311
switch (tginfo->tgenabled)
13315
appendPQExpBuffer(query, "DISABLE");
13318
appendPQExpBuffer(query, "ENABLE ALWAYS");
13321
appendPQExpBuffer(query, "ENABLE REPLICA");
13324
appendPQExpBuffer(query, "ENABLE");
13327
appendPQExpBuffer(query, " TRIGGER %s;\n",
13328
fmtId(tginfo->dobj.name));
13331
appendPQExpBuffer(labelq, "TRIGGER %s ",
13332
fmtId(tginfo->dobj.name));
13333
appendPQExpBuffer(labelq, "ON %s",
13334
fmtId(tbinfo->dobj.name));
13336
ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
13338
tbinfo->dobj.namespace->dobj.name,
13340
tbinfo->rolname, false,
13341
"TRIGGER", SECTION_POST_DATA,
13342
query->data, delqry->data, NULL,
13343
tginfo->dobj.dependencies, tginfo->dobj.nDeps,
13346
dumpComment(fout, labelq->data,
13347
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
13348
tginfo->dobj.catId, 0, tginfo->dobj.dumpId);
13350
destroyPQExpBuffer(query);
13351
destroyPQExpBuffer(delqry);
13352
destroyPQExpBuffer(labelq);
13360
dumpRule(Archive *fout, RuleInfo *rinfo)
13362
TableInfo *tbinfo = rinfo->ruletable;
13365
PQExpBuffer delcmd;
13366
PQExpBuffer labelq;
13369
/* Skip if not to be dumped */
13370
if (!rinfo->dobj.dump || dataOnly)
13374
* If it is an ON SELECT rule that is created implicitly by CREATE VIEW,
13375
* we do not want to dump it as a separate object.
13377
if (!rinfo->separate)
13381
* Make sure we are in proper schema.
13383
selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
13385
query = createPQExpBuffer();
13386
cmd = createPQExpBuffer();
13387
delcmd = createPQExpBuffer();
13388
labelq = createPQExpBuffer();
13390
if (g_fout->remoteVersion >= 70300)
13392
appendPQExpBuffer(query,
13393
"SELECT pg_catalog.pg_get_ruledef('%u'::pg_catalog.oid) AS definition",
13394
rinfo->dobj.catId.oid);
13398
/* Rule name was unique before 7.3 ... */
13399
appendPQExpBuffer(query,
13400
"SELECT pg_get_ruledef('%s') AS definition",
13404
res = PQexec(g_conn, query->data);
13405
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
13407
if (PQntuples(res) != 1)
13409
write_msg(NULL, "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned\n",
13410
rinfo->dobj.name, tbinfo->dobj.name);
13414
printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, 0, 0));
13417
* Add the command to alter the rules replication firing semantics if it
13418
* differs from the default.
13420
if (rinfo->ev_enabled != 'O')
13422
appendPQExpBuffer(cmd, "ALTER TABLE %s.",
13423
fmtId(tbinfo->dobj.namespace->dobj.name));
13424
appendPQExpBuffer(cmd, "%s ",
13425
fmtId(tbinfo->dobj.name));
13426
switch (rinfo->ev_enabled)
13429
appendPQExpBuffer(cmd, "ENABLE ALWAYS RULE %s;\n",
13430
fmtId(rinfo->dobj.name));
13433
appendPQExpBuffer(cmd, "ENABLE REPLICA RULE %s;\n",
13434
fmtId(rinfo->dobj.name));
13437
appendPQExpBuffer(cmd, "DISABLE RULE %s;\n",
13438
fmtId(rinfo->dobj.name));
13444
* DROP must be fully qualified in case same name appears in pg_catalog
13446
appendPQExpBuffer(delcmd, "DROP RULE %s ",
13447
fmtId(rinfo->dobj.name));
13448
appendPQExpBuffer(delcmd, "ON %s.",
13449
fmtId(tbinfo->dobj.namespace->dobj.name));
13450
appendPQExpBuffer(delcmd, "%s;\n",
13451
fmtId(tbinfo->dobj.name));
13453
appendPQExpBuffer(labelq, "RULE %s",
13454
fmtId(rinfo->dobj.name));
13455
appendPQExpBuffer(labelq, " ON %s",
13456
fmtId(tbinfo->dobj.name));
13458
ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
13460
tbinfo->dobj.namespace->dobj.name,
13462
tbinfo->rolname, false,
13463
"RULE", SECTION_POST_DATA,
13464
cmd->data, delcmd->data, NULL,
13465
rinfo->dobj.dependencies, rinfo->dobj.nDeps,
13468
/* Dump rule comments */
13469
dumpComment(fout, labelq->data,
13470
tbinfo->dobj.namespace->dobj.name,
13472
rinfo->dobj.catId, 0, rinfo->dobj.dumpId);
13476
destroyPQExpBuffer(query);
13477
destroyPQExpBuffer(cmd);
13478
destroyPQExpBuffer(delcmd);
13479
destroyPQExpBuffer(labelq);
13483
* getExtensionMembership --- obtain extension membership data
13486
getExtensionMembership(ExtensionInfo extinfo[], int numExtensions)
13496
DumpableObject *dobj,
13499
/* Nothing to do if no extensions */
13500
if (numExtensions == 0)
13503
/* Make sure we are in proper schema */
13504
selectSourceSchema("pg_catalog");
13506
query = createPQExpBuffer();
13508
/* refclassid constraint is redundant but may speed the search */
13509
appendPQExpBuffer(query, "SELECT "
13510
"classid, objid, refclassid, refobjid "
13512
"WHERE refclassid = 'pg_extension'::regclass "
13513
"AND deptype = 'e' "
13516
res = PQexec(g_conn, query->data);
13517
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
13519
ntups = PQntuples(res);
13521
i_classid = PQfnumber(res, "classid");
13522
i_objid = PQfnumber(res, "objid");
13523
i_refclassid = PQfnumber(res, "refclassid");
13524
i_refobjid = PQfnumber(res, "refobjid");
13527
* Since we ordered the SELECT by referenced ID, we can expect that
13528
* multiple entries for the same extension will appear together; this
13529
* saves on searches.
13533
for (i = 0; i < ntups; i++)
13536
CatalogId refobjId;
13538
objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
13539
objId.oid = atooid(PQgetvalue(res, i, i_objid));
13540
refobjId.tableoid = atooid(PQgetvalue(res, i, i_refclassid));
13541
refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid));
13543
if (refdobj == NULL ||
13544
refdobj->catId.tableoid != refobjId.tableoid ||
13545
refdobj->catId.oid != refobjId.oid)
13546
refdobj = findObjectByCatalogId(refobjId);
13549
* Failure to find objects mentioned in pg_depend is not unexpected,
13550
* since for example we don't collect info about TOAST tables.
13552
if (refdobj == NULL)
13555
fprintf(stderr, "no referenced object %u %u\n",
13556
refobjId.tableoid, refobjId.oid);
13561
dobj = findObjectByCatalogId(objId);
13566
fprintf(stderr, "no referencing object %u %u\n",
13567
objId.tableoid, objId.oid);
13572
/* Record dependency so that getDependencies needn't repeat this */
13573
addObjectDependency(dobj, refdobj->dumpId);
13575
dobj->ext_member = true;
13578
* Normally, mark the member object as not to be dumped. But in
13579
* binary upgrades, we still dump the members individually, since the
13580
* idea is to exactly reproduce the database contents rather than
13581
* replace the extension contents with something different.
13583
if (!binary_upgrade)
13584
dobj->dump = false;
13586
dobj->dump = refdobj->dump;
13592
* Now identify extension configuration tables and create TableDataInfo
13593
* objects for them, ensuring their data will be dumped even though the
13594
* tables themselves won't be.
13596
* Note that we create TableDataInfo objects even in schemaOnly mode, ie,
13597
* user data in a configuration table is treated like schema data. This
13598
* seems appropriate since system data in a config table would get
13599
* reloaded by CREATE EXTENSION.
13601
for (i = 0; i < numExtensions; i++)
13603
char *extconfig = extinfo[i].extconfig;
13604
char *extcondition = extinfo[i].extcondition;
13605
char **extconfigarray = NULL;
13606
char **extconditionarray = NULL;
13608
int nconditionitems;
13610
if (parsePGArray(extconfig, &extconfigarray, &nconfigitems) &&
13611
parsePGArray(extcondition, &extconditionarray, &nconditionitems) &&
13612
nconfigitems == nconditionitems)
13616
for (j = 0; j < nconfigitems; j++)
13618
TableInfo *configtbl;
13620
configtbl = findTableByOid(atooid(extconfigarray[j]));
13621
if (configtbl && configtbl->dataObj == NULL)
13624
* Note: config tables are dumped without OIDs regardless
13625
* of the --oids setting. This is because row filtering
13626
* conditions aren't compatible with dumping OIDs.
13628
makeTableDataInfo(configtbl, false);
13629
if (strlen(extconditionarray[j]) > 0)
13630
configtbl->dataObj->filtercond = strdup(extconditionarray[j]);
13634
if (extconfigarray)
13635
free(extconfigarray);
13636
if (extconditionarray)
13637
free(extconditionarray);
13640
destroyPQExpBuffer(query);
13644
* getDependencies --- obtain available dependency data
13647
getDependencies(void)
13658
DumpableObject *dobj,
13661
/* No dependency info available before 7.3 */
13662
if (g_fout->remoteVersion < 70300)
13666
write_msg(NULL, "reading dependency data\n");
13668
/* Make sure we are in proper schema */
13669
selectSourceSchema("pg_catalog");
13671
query = createPQExpBuffer();
13674
* PIN dependencies aren't interesting, and EXTENSION dependencies were
13675
* already processed by getExtensionMembership.
13677
appendPQExpBuffer(query, "SELECT "
13678
"classid, objid, refclassid, refobjid, deptype "
13680
"WHERE deptype != 'p' AND deptype != 'e' "
13683
res = PQexec(g_conn, query->data);
13684
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
13686
ntups = PQntuples(res);
13688
i_classid = PQfnumber(res, "classid");
13689
i_objid = PQfnumber(res, "objid");
13690
i_refclassid = PQfnumber(res, "refclassid");
13691
i_refobjid = PQfnumber(res, "refobjid");
13692
i_deptype = PQfnumber(res, "deptype");
13695
* Since we ordered the SELECT by referencing ID, we can expect that
13696
* multiple entries for the same object will appear together; this saves
13701
for (i = 0; i < ntups; i++)
13704
CatalogId refobjId;
13707
objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
13708
objId.oid = atooid(PQgetvalue(res, i, i_objid));
13709
refobjId.tableoid = atooid(PQgetvalue(res, i, i_refclassid));
13710
refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid));
13711
deptype = *(PQgetvalue(res, i, i_deptype));
13713
if (dobj == NULL ||
13714
dobj->catId.tableoid != objId.tableoid ||
13715
dobj->catId.oid != objId.oid)
13716
dobj = findObjectByCatalogId(objId);
13719
* Failure to find objects mentioned in pg_depend is not unexpected,
13720
* since for example we don't collect info about TOAST tables.
13725
fprintf(stderr, "no referencing object %u %u\n",
13726
objId.tableoid, objId.oid);
13731
refdobj = findObjectByCatalogId(refobjId);
13733
if (refdobj == NULL)
13736
fprintf(stderr, "no referenced object %u %u\n",
13737
refobjId.tableoid, refobjId.oid);
13743
* Ordinarily, table rowtypes have implicit dependencies on their
13744
* tables. However, for a composite type the implicit dependency goes
13745
* the other way in pg_depend; which is the right thing for DROP but
13746
* it doesn't produce the dependency ordering we need. So in that one
13747
* case, we reverse the direction of the dependency.
13749
if (deptype == 'i' &&
13750
dobj->objType == DO_TABLE &&
13751
refdobj->objType == DO_TYPE)
13752
addObjectDependency(refdobj, dobj->dumpId);
13755
addObjectDependency(dobj, refdobj->dumpId);
13760
destroyPQExpBuffer(query);
13765
* selectSourceSchema - make the specified schema the active search path
13766
* in the source database.
13768
* NB: pg_catalog is explicitly searched after the specified schema;
13769
* so user names are only qualified if they are cross-schema references,
13770
* and system names are only qualified if they conflict with a user name
13771
* in the current schema.
13773
* Whenever the selected schema is not pg_catalog, be careful to qualify
13774
* references to system catalogs and types in our emitted commands!
13777
selectSourceSchema(const char *schemaName)
13779
static char *curSchemaName = NULL;
13782
/* Not relevant if fetching from pre-7.3 DB */
13783
if (g_fout->remoteVersion < 70300)
13785
/* Ignore null schema names */
13786
if (schemaName == NULL || *schemaName == '\0')
13788
/* Optimize away repeated selection of same schema */
13789
if (curSchemaName && strcmp(curSchemaName, schemaName) == 0)
13792
query = createPQExpBuffer();
13793
appendPQExpBuffer(query, "SET search_path = %s",
13794
fmtId(schemaName));
13795
if (strcmp(schemaName, "pg_catalog") != 0)
13796
appendPQExpBuffer(query, ", pg_catalog");
13798
do_sql_command(g_conn, query->data);
13800
destroyPQExpBuffer(query);
13802
free(curSchemaName);
13803
curSchemaName = strdup(schemaName);
13807
* getFormattedTypeName - retrieve a nicely-formatted type name for the
13810
* NB: in 7.3 and up the result may depend on the currently-selected
13811
* schema; this is why we don't try to cache the names.
13814
getFormattedTypeName(Oid oid, OidOptions opts)
13823
if ((opts & zeroAsOpaque) != 0)
13824
return strdup(g_opaque_type);
13825
else if ((opts & zeroAsAny) != 0)
13826
return strdup("'any'");
13827
else if ((opts & zeroAsStar) != 0)
13828
return strdup("*");
13829
else if ((opts & zeroAsNone) != 0)
13830
return strdup("NONE");
13833
query = createPQExpBuffer();
13834
if (g_fout->remoteVersion >= 70300)
13836
appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)",
13839
else if (g_fout->remoteVersion >= 70100)
13841
appendPQExpBuffer(query, "SELECT format_type('%u'::oid, NULL)",
13846
appendPQExpBuffer(query, "SELECT typname "
13848
"WHERE oid = '%u'::oid",
13852
res = PQexec(g_conn, query->data);
13853
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
13855
/* Expecting a single result only */
13856
ntups = PQntuples(res);
13859
write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
13860
"query returned %d rows instead of one: %s\n",
13862
ntups, query->data);
13866
if (g_fout->remoteVersion >= 70100)
13868
/* already quoted */
13869
result = strdup(PQgetvalue(res, 0, 0));
13873
/* may need to quote it */
13874
result = strdup(fmtId(PQgetvalue(res, 0, 0)));
13878
destroyPQExpBuffer(query);
13884
* myFormatType --- local implementation of format_type for use with 7.0.
13887
myFormatType(const char *typname, int32 typmod)
13890
bool isarray = false;
13891
PQExpBuffer buf = createPQExpBuffer();
13893
/* Handle array types */
13894
if (typname[0] == '_')
13900
/* Show lengths on bpchar and varchar */
13901
if (!strcmp(typname, "bpchar"))
13903
int len = (typmod - VARHDRSZ);
13905
appendPQExpBuffer(buf, "character");
13907
appendPQExpBuffer(buf, "(%d)",
13908
typmod - VARHDRSZ);
13910
else if (!strcmp(typname, "varchar"))
13912
appendPQExpBuffer(buf, "character varying");
13914
appendPQExpBuffer(buf, "(%d)",
13915
typmod - VARHDRSZ);
13917
else if (!strcmp(typname, "numeric"))
13919
appendPQExpBuffer(buf, "numeric");
13926
tmp_typmod = typmod - VARHDRSZ;
13927
precision = (tmp_typmod >> 16) & 0xffff;
13928
scale = tmp_typmod & 0xffff;
13929
appendPQExpBuffer(buf, "(%d,%d)",
13935
* char is an internal single-byte data type; Let's make sure we force it
13936
* through with quotes. - thomas 1998-12-13
13938
else if (strcmp(typname, "char") == 0)
13939
appendPQExpBuffer(buf, "\"char\"");
13941
appendPQExpBuffer(buf, "%s", fmtId(typname));
13943
/* Append array qualifier for array types */
13945
appendPQExpBuffer(buf, "[]");
13947
result = strdup(buf->data);
13948
destroyPQExpBuffer(buf);
13954
* fmtQualifiedId - convert a qualified name to the proper format for
13955
* the source database.
13957
* Like fmtId, use the result before calling again.
13959
static const char *
13960
fmtQualifiedId(const char *schema, const char *id)
13962
static PQExpBuffer id_return = NULL;
13964
if (id_return) /* first time through? */
13965
resetPQExpBuffer(id_return);
13967
id_return = createPQExpBuffer();
13969
/* Suppress schema name if fetching from pre-7.3 DB */
13970
if (g_fout->remoteVersion >= 70300 && schema && *schema)
13972
appendPQExpBuffer(id_return, "%s.",
13975
appendPQExpBuffer(id_return, "%s",
13978
return id_return->data;
13982
* Return a column list clause for the given relation.
13984
* Special case: if there are no undropped columns in the relation, return
13985
* "", not an invalid "()" column list.
13987
static const char *
13988
fmtCopyColumnList(const TableInfo *ti)
13990
static PQExpBuffer q = NULL;
13991
int numatts = ti->numatts;
13992
char **attnames = ti->attnames;
13993
bool *attisdropped = ti->attisdropped;
13997
if (q) /* first time through? */
13998
resetPQExpBuffer(q);
14000
q = createPQExpBuffer();
14002
appendPQExpBuffer(q, "(");
14004
for (i = 0; i < numatts; i++)
14006
if (attisdropped[i])
14009
appendPQExpBuffer(q, ", ");
14010
appendPQExpBuffer(q, "%s", fmtId(attnames[i]));
14015
return ""; /* no undropped columns */
14017
appendPQExpBuffer(q, ")");
14022
* Convenience subroutine to execute a SQL command and check for
14023
* COMMAND_OK status.
14026
do_sql_command(PGconn *conn, const char *query)
14030
res = PQexec(conn, query);
14031
check_sql_result(res, conn, query, PGRES_COMMAND_OK);
14036
* Convenience subroutine to verify a SQL command succeeded,
14037
* and exit with a useful error message if not.
14040
check_sql_result(PGresult *res, PGconn *conn, const char *query,
14041
ExecStatusType expected)
14045
if (res && PQresultStatus(res) == expected)
14048
write_msg(NULL, "SQL command failed\n");
14050
err = PQresultErrorMessage(res);
14052
err = PQerrorMessage(conn);
14053
write_msg(NULL, "Error message from server: %s", err);
14054
write_msg(NULL, "The command was: %s\n", query);