1 /*-------------------------------------------------------------------------
4 * pg_dump is a utility for dumping out a postgres database
7 * Portions Copyright (c) 1996-2009, 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
15 * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.559 2009/12/22 23:27:41 petere Exp $
17 *-------------------------------------------------------------------------
20 #include "postgres_fe.h"
31 #include "getopt_long.h"
33 #include "access/attnum.h"
34 #include "access/sysattr.h"
35 #include "access/transam.h"
36 #include "catalog/pg_cast.h"
37 #include "catalog/pg_class.h"
38 #include "catalog/pg_default_acl.h"
39 #include "catalog/pg_largeobject.h"
40 #include "catalog/pg_proc.h"
41 #include "catalog/pg_trigger.h"
42 #include "catalog/pg_type.h"
43 #include "libpq/libpq-fs.h"
45 #include "pg_backup_archiver.h"
46 #include "dumputils.h"
55 const char *descr; /* comment for an object */
56 Oid classoid; /* object class (catalog OID) */
57 Oid objoid; /* object OID */
58 int objsubid; /* subobject (table column #) */
63 bool g_verbose; /* User wants verbose narration of our
65 Archive *g_fout; /* the script file */
66 PGconn *g_conn; /* the database connection */
68 /* various user-settable parameters */
72 const char *lockWaitTimeout;
74 /* subquery used to convert user ID (eg, datdba) to user name */
75 static const char *username_subquery;
77 /* obsolete as of 7.3: */
78 static Oid g_last_builtin_oid; /* value of the last builtin oid */
81 * Object inclusion/exclusion lists
83 * The string lists record the patterns given by command-line switches,
84 * which we then convert to lists of OIDs of matching objects.
86 static SimpleStringList schema_include_patterns = {NULL, NULL};
87 static SimpleOidList schema_include_oids = {NULL, NULL};
88 static SimpleStringList schema_exclude_patterns = {NULL, NULL};
89 static SimpleOidList schema_exclude_oids = {NULL, NULL};
91 static SimpleStringList table_include_patterns = {NULL, NULL};
92 static SimpleOidList table_include_oids = {NULL, NULL};
93 static SimpleStringList table_exclude_patterns = {NULL, NULL};
94 static SimpleOidList table_exclude_oids = {NULL, NULL};
96 /* default, if no "inclusion" switches appear, is to dump everything */
97 static bool include_everything = true;
99 char g_opaque_type[10]; /* name for the opaque type */
101 /* placeholders for the delimiters for comments */
102 char g_comment_start[10];
103 char g_comment_end[10];
105 static const CatalogId nilCatalogId = {0, 0};
107 /* these are to avoid passing around info for findNamespace() */
108 static NamespaceInfo *g_namespaces;
109 static int g_numNamespaces;
111 /* flags for various command-line long options */
112 static int binary_upgrade = 0;
113 static int disable_dollar_quoting = 0;
114 static int dump_inserts = 0;
115 static int column_inserts = 0;
118 static void help(const char *progname);
119 static void expand_schema_name_patterns(SimpleStringList *patterns,
120 SimpleOidList *oids);
121 static void expand_table_name_patterns(SimpleStringList *patterns,
122 SimpleOidList *oids);
123 static NamespaceInfo *findNamespace(Oid nsoid, Oid objoid);
124 static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
125 static void guessConstraintInheritance(TableInfo *tblinfo, int numTables);
126 static void dumpComment(Archive *fout, const char *target,
127 const char *namespace, const char *owner,
128 CatalogId catalogId, int subid, DumpId dumpId);
129 static int findComments(Archive *fout, Oid classoid, Oid objoid,
130 CommentItem **items);
131 static int collectComments(Archive *fout, CommentItem **items);
132 static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
133 static void dumpNamespace(Archive *fout, NamespaceInfo *nspinfo);
134 static void dumpType(Archive *fout, TypeInfo *tinfo);
135 static void dumpBaseType(Archive *fout, TypeInfo *tinfo);
136 static void dumpEnumType(Archive *fout, TypeInfo *tinfo);
137 static void dumpDomain(Archive *fout, TypeInfo *tinfo);
138 static void dumpCompositeType(Archive *fout, TypeInfo *tinfo);
139 static void dumpCompositeTypeColComments(Archive *fout, TypeInfo *tinfo);
140 static void dumpShellType(Archive *fout, ShellTypeInfo *stinfo);
141 static void dumpProcLang(Archive *fout, ProcLangInfo *plang);
142 static void dumpFunc(Archive *fout, FuncInfo *finfo);
143 static void dumpCast(Archive *fout, CastInfo *cast);
144 static void dumpOpr(Archive *fout, OprInfo *oprinfo);
145 static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo);
146 static void dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo);
147 static void dumpConversion(Archive *fout, ConvInfo *convinfo);
148 static void dumpRule(Archive *fout, RuleInfo *rinfo);
149 static void dumpAgg(Archive *fout, AggInfo *agginfo);
150 static void dumpTrigger(Archive *fout, TriggerInfo *tginfo);
151 static void dumpTable(Archive *fout, TableInfo *tbinfo);
152 static void dumpTableSchema(Archive *fout, TableInfo *tbinfo);
153 static void dumpAttrDef(Archive *fout, AttrDefInfo *adinfo);
154 static void dumpSequence(Archive *fout, TableInfo *tbinfo);
155 static void dumpIndex(Archive *fout, IndxInfo *indxinfo);
156 static void dumpConstraint(Archive *fout, ConstraintInfo *coninfo);
157 static void dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo);
158 static void dumpTSParser(Archive *fout, TSParserInfo *prsinfo);
159 static void dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo);
160 static void dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo);
161 static void dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo);
162 static void dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo);
163 static void dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo);
164 static void dumpUserMappings(Archive *fout, const char *target,
165 const char *servername, const char *namespace,
166 const char *owner, CatalogId catalogId, DumpId dumpId);
167 static void dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo);
169 static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
170 const char *type, const char *name, const char *subname,
171 const char *tag, const char *nspname, const char *owner,
174 static void getDependencies(void);
175 static void getDomainConstraints(TypeInfo *tinfo);
176 static void getTableData(TableInfo *tblinfo, int numTables, bool oids);
177 static void getTableDataFKConstraints(void);
178 static char *format_function_arguments(FuncInfo *finfo, char *funcargs);
179 static char *format_function_arguments_old(FuncInfo *finfo, int nallargs,
183 static char *format_function_signature(FuncInfo *finfo, bool honor_quotes);
184 static const char *convertRegProcReference(const char *proc);
185 static const char *convertOperatorReference(const char *opr);
186 static const char *convertTSFunction(Oid funcOid);
187 static Oid findLastBuiltinOid_V71(const char *);
188 static Oid findLastBuiltinOid_V70(void);
189 static void selectSourceSchema(const char *schemaName);
190 static char *getFormattedTypeName(Oid oid, OidOptions opts);
191 static char *myFormatType(const char *typname, int32 typmod);
192 static const char *fmtQualifiedId(const char *schema, const char *id);
193 static bool hasBlobs(Archive *AH);
194 static int dumpBlobs(Archive *AH, void *arg);
195 static int dumpBlobComments(Archive *AH, void *arg);
196 static void dumpDatabase(Archive *AH);
197 static void dumpEncoding(Archive *AH);
198 static void dumpStdStrings(Archive *AH);
199 static const char *getAttrName(int attrnum, TableInfo *tblInfo);
200 static const char *fmtCopyColumnList(const TableInfo *ti);
201 static void do_sql_command(PGconn *conn, const char *query);
202 static void check_sql_result(PGresult *res, PGconn *conn, const char *query,
203 ExecStatusType expected);
207 main(int argc, char **argv)
210 const char *filename = NULL;
211 const char *format = "p";
212 const char *dbname = NULL;
213 const char *pghost = NULL;
214 const char *pgport = NULL;
215 const char *username = NULL;
216 const char *dumpencoding = NULL;
217 const char *std_strings;
221 DumpableObject **dobjs;
224 enum trivalue prompt_password = TRI_DEFAULT;
225 int compressLevel = -1;
228 int outputCreate = 0;
229 bool outputBlobs = false;
230 int outputNoOwner = 0;
231 char *outputSuperuser = NULL;
232 char *use_role = NULL;
235 RestoreOptions *ropt;
237 static int disable_triggers = 0;
238 static int outputNoTablespaces = 0;
239 static int use_setsessauth = 0;
241 static struct option long_options[] = {
242 {"data-only", no_argument, NULL, 'a'},
243 {"blobs", no_argument, NULL, 'b'},
244 {"clean", no_argument, NULL, 'c'},
245 {"create", no_argument, NULL, 'C'},
246 {"file", required_argument, NULL, 'f'},
247 {"format", required_argument, NULL, 'F'},
248 {"host", required_argument, NULL, 'h'},
249 {"ignore-version", no_argument, NULL, 'i'},
250 {"no-reconnect", no_argument, NULL, 'R'},
251 {"oids", no_argument, NULL, 'o'},
252 {"no-owner", no_argument, NULL, 'O'},
253 {"port", required_argument, NULL, 'p'},
254 {"schema", required_argument, NULL, 'n'},
255 {"exclude-schema", required_argument, NULL, 'N'},
256 {"schema-only", no_argument, NULL, 's'},
257 {"superuser", required_argument, NULL, 'S'},
258 {"table", required_argument, NULL, 't'},
259 {"exclude-table", required_argument, NULL, 'T'},
260 {"no-password", no_argument, NULL, 'w'},
261 {"password", no_argument, NULL, 'W'},
262 {"username", required_argument, NULL, 'U'},
263 {"verbose", no_argument, NULL, 'v'},
264 {"no-privileges", no_argument, NULL, 'x'},
265 {"no-acl", no_argument, NULL, 'x'},
266 {"compress", required_argument, NULL, 'Z'},
267 {"encoding", required_argument, NULL, 'E'},
268 {"help", no_argument, NULL, '?'},
269 {"version", no_argument, NULL, 'V'},
272 * the following options don't have an equivalent short option letter
274 {"attribute-inserts", no_argument, &column_inserts, 1},
275 {"binary-upgrade", no_argument, &binary_upgrade, 1},
276 {"column-inserts", no_argument, &column_inserts, 1},
277 {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
278 {"disable-triggers", no_argument, &disable_triggers, 1},
279 {"inserts", no_argument, &dump_inserts, 1},
280 {"lock-wait-timeout", required_argument, NULL, 2},
281 {"no-tablespaces", no_argument, &outputNoTablespaces, 1},
282 {"role", required_argument, NULL, 3},
283 {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
288 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
292 strcpy(g_comment_start, "-- ");
293 g_comment_end[0] = '\0';
294 strcpy(g_opaque_type, "opaque");
296 dataOnly = schemaOnly = false;
297 lockWaitTimeout = NULL;
299 progname = get_progname(argv[0]);
301 /* Set default options based on progname */
302 if (strcmp(progname, "pg_backup") == 0)
307 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
312 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
314 puts("pg_dump (PostgreSQL) " PG_VERSION);
319 while ((c = getopt_long(argc, argv, "abcCE:f:F:h:in:N:oOp:RsS:t:T:U:vwWxX:Z:",
320 long_options, &optindex)) != -1)
324 case 'a': /* Dump data only */
328 case 'b': /* Dump blobs */
332 case 'c': /* clean (i.e., drop) schema prior to create */
336 case 'C': /* Create DB */
340 case 'E': /* Dump encoding */
341 dumpencoding = optarg;
352 case 'h': /* server host */
357 /* ignored, deprecated option */
360 case 'n': /* include schema(s) */
361 simple_string_list_append(&schema_include_patterns, optarg);
362 include_everything = false;
365 case 'N': /* exclude schema(s) */
366 simple_string_list_append(&schema_exclude_patterns, optarg);
369 case 'o': /* Dump oids */
373 case 'O': /* Don't reconnect to match owner */
377 case 'p': /* server port */
382 /* no-op, still accepted for backwards compatibility */
385 case 's': /* dump schema only */
389 case 'S': /* Username for superuser in plain text output */
390 outputSuperuser = strdup(optarg);
393 case 't': /* include table(s) */
394 simple_string_list_append(&table_include_patterns, optarg);
395 include_everything = false;
398 case 'T': /* exclude table(s) */
399 simple_string_list_append(&table_exclude_patterns, optarg);
406 case 'v': /* verbose */
411 prompt_password = TRI_NO;
415 prompt_password = TRI_YES;
418 case 'x': /* skip ACL dump */
423 /* -X is a deprecated alternative to long options */
424 if (strcmp(optarg, "disable-dollar-quoting") == 0)
425 disable_dollar_quoting = 1;
426 else if (strcmp(optarg, "disable-triggers") == 0)
427 disable_triggers = 1;
428 else if (strcmp(optarg, "no-tablespaces") == 0)
429 outputNoTablespaces = 1;
430 else if (strcmp(optarg, "use-set-session-authorization") == 0)
435 _("%s: invalid -X option -- %s\n"),
437 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
442 case 'Z': /* Compression Level */
443 compressLevel = atoi(optarg);
447 /* This covers the long options equivalent to -X xxx. */
450 case 2: /* lock-wait-timeout */
451 lockWaitTimeout = optarg;
454 case 3: /* SET ROLE */
459 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
464 if (optind < (argc - 1))
466 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
467 progname, argv[optind + 1]);
468 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
473 /* Get database name from command line */
475 dbname = argv[optind];
477 /* --column-inserts implies --inserts */
481 if (dataOnly && schemaOnly)
483 write_msg(NULL, "options -s/--schema-only and -a/--data-only cannot be used together\n");
487 if (dataOnly && outputClean)
489 write_msg(NULL, "options -c/--clean and -a/--data-only cannot be used together\n");
493 if (dump_inserts && oids)
495 write_msg(NULL, "options --inserts/--column-inserts and -o/--oids cannot be used together\n");
496 write_msg(NULL, "(The INSERT command cannot set OIDs.)\n");
500 /* open the output file */
501 if (pg_strcasecmp(format, "a") == 0 || pg_strcasecmp(format, "append") == 0)
503 /* This is used by pg_dumpall, and is not documented */
505 g_fout = CreateArchive(filename, archNull, 0, archModeAppend);
507 else if (pg_strcasecmp(format, "c") == 0 || pg_strcasecmp(format, "custom") == 0)
508 g_fout = CreateArchive(filename, archCustom, compressLevel, archModeWrite);
509 else if (pg_strcasecmp(format, "f") == 0 || pg_strcasecmp(format, "file") == 0)
512 * Dump files into the current directory; for demonstration only, not
515 g_fout = CreateArchive(filename, archFiles, compressLevel, archModeWrite);
517 else if (pg_strcasecmp(format, "p") == 0 || pg_strcasecmp(format, "plain") == 0)
520 g_fout = CreateArchive(filename, archNull, 0, archModeWrite);
522 else if (pg_strcasecmp(format, "t") == 0 || pg_strcasecmp(format, "tar") == 0)
523 g_fout = CreateArchive(filename, archTar, compressLevel, archModeWrite);
526 write_msg(NULL, "invalid output format \"%s\" specified\n", format);
532 write_msg(NULL, "could not open output file \"%s\" for writing\n", filename);
536 /* Let the archiver know how noisy to be */
537 g_fout->verbose = g_verbose;
539 my_version = parse_version(PG_VERSION);
542 write_msg(NULL, "could not parse version string \"%s\"\n", PG_VERSION);
547 * We allow the server to be back to 7.0, and up to any minor release of
548 * our own major version. (See also version check in pg_dumpall.c.)
550 g_fout->minRemoteVersion = 70000;
551 g_fout->maxRemoteVersion = (my_version / 100) * 100 + 99;
554 * Open the database using the Archiver, so it knows about it. Errors mean
557 g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport,
558 username, prompt_password);
560 /* Set the client encoding if requested */
563 if (PQsetClientEncoding(g_conn, dumpencoding) < 0)
565 write_msg(NULL, "invalid client encoding \"%s\" specified\n",
572 * Get the active encoding and the standard_conforming_strings setting, so
573 * we know how to escape strings.
575 g_fout->encoding = PQclientEncoding(g_conn);
577 std_strings = PQparameterStatus(g_conn, "standard_conforming_strings");
578 g_fout->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
580 /* Set the role if requested */
581 if (use_role && g_fout->remoteVersion >= 80100)
583 PQExpBuffer query = createPQExpBuffer();
585 appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
586 do_sql_command(g_conn, query->data);
587 destroyPQExpBuffer(query);
590 /* Set the datestyle to ISO to ensure the dump's portability */
591 do_sql_command(g_conn, "SET DATESTYLE = ISO");
593 /* Likewise, avoid using sql_standard intervalstyle */
594 if (g_fout->remoteVersion >= 80400)
595 do_sql_command(g_conn, "SET INTERVALSTYLE = POSTGRES");
598 * If supported, set extra_float_digits so that we can dump float data
599 * exactly (given correctly implemented float I/O code, anyway)
601 if (g_fout->remoteVersion >= 80500)
602 do_sql_command(g_conn, "SET extra_float_digits TO 3");
603 else if (g_fout->remoteVersion >= 70400)
604 do_sql_command(g_conn, "SET extra_float_digits TO 2");
607 * If synchronized scanning is supported, disable it, to prevent
608 * unpredictable changes in row ordering across a dump and reload.
610 if (g_fout->remoteVersion >= 80300)
611 do_sql_command(g_conn, "SET synchronize_seqscans TO off");
614 * Disable timeouts if supported.
616 if (g_fout->remoteVersion >= 70300)
617 do_sql_command(g_conn, "SET statement_timeout = 0");
620 * Start serializable transaction to dump consistent data.
622 do_sql_command(g_conn, "BEGIN");
624 do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
626 /* Select the appropriate subquery to convert user IDs to names */
627 if (g_fout->remoteVersion >= 80100)
628 username_subquery = "SELECT rolname FROM pg_catalog.pg_roles WHERE oid =";
629 else if (g_fout->remoteVersion >= 70300)
630 username_subquery = "SELECT usename FROM pg_catalog.pg_user WHERE usesysid =";
632 username_subquery = "SELECT usename FROM pg_user WHERE usesysid =";
634 /* Find the last built-in OID, if needed */
635 if (g_fout->remoteVersion < 70300)
637 if (g_fout->remoteVersion >= 70100)
638 g_last_builtin_oid = findLastBuiltinOid_V71(PQdb(g_conn));
640 g_last_builtin_oid = findLastBuiltinOid_V70();
642 write_msg(NULL, "last built-in OID is %u\n", g_last_builtin_oid);
645 /* Expand schema selection patterns into OID lists */
646 if (schema_include_patterns.head != NULL)
648 expand_schema_name_patterns(&schema_include_patterns,
649 &schema_include_oids);
650 if (schema_include_oids.head == NULL)
652 write_msg(NULL, "No matching schemas were found\n");
656 expand_schema_name_patterns(&schema_exclude_patterns,
657 &schema_exclude_oids);
658 /* non-matching exclusion patterns aren't an error */
660 /* Expand table selection patterns into OID lists */
661 if (table_include_patterns.head != NULL)
663 expand_table_name_patterns(&table_include_patterns,
664 &table_include_oids);
665 if (table_include_oids.head == NULL)
667 write_msg(NULL, "No matching tables were found\n");
671 expand_table_name_patterns(&table_exclude_patterns,
672 &table_exclude_oids);
673 /* non-matching exclusion patterns aren't an error */
676 * Dumping blobs is now default unless we saw an inclusion switch or -s
677 * ... but even if we did see one of these, -b turns it back on.
679 if (include_everything && !schemaOnly)
683 * Now scan the database and create DumpableObject structs for all the
684 * objects we intend to dump.
686 tblinfo = getSchemaData(&numTables);
688 if (g_fout->remoteVersion < 80400)
689 guessConstraintInheritance(tblinfo, numTables);
693 getTableData(tblinfo, numTables, oids);
695 getTableDataFKConstraints();
698 if (outputBlobs && hasBlobs(g_fout))
700 /* Add placeholders to allow correct sorting of blobs */
701 DumpableObject *blobobj;
702 DumpableObject *blobcobj;
704 blobobj = (DumpableObject *) malloc(sizeof(DumpableObject));
705 blobobj->objType = DO_BLOBS;
706 blobobj->catId = nilCatalogId;
707 AssignDumpId(blobobj);
708 blobobj->name = strdup("BLOBS");
710 blobcobj = (DumpableObject *) malloc(sizeof(DumpableObject));
711 blobcobj->objType = DO_BLOB_COMMENTS;
712 blobcobj->catId = nilCatalogId;
713 AssignDumpId(blobcobj);
714 blobcobj->name = strdup("BLOB COMMENTS");
715 addObjectDependency(blobcobj, blobobj->dumpId);
719 * Collect dependency data to assist in ordering the objects.
724 * Sort the objects into a safe dump order (no forward references).
726 * In 7.3 or later, we can rely on dependency information to help us
727 * determine a safe order, so the initial sort is mostly for cosmetic
728 * purposes: we sort by name to ensure that logically identical schemas
729 * will dump identically. Before 7.3 we don't have dependencies and we
730 * use OID ordering as an (unreliable) guide to creation order.
732 getDumpableObjects(&dobjs, &numObjs);
734 if (g_fout->remoteVersion >= 70300)
735 sortDumpableObjectsByTypeName(dobjs, numObjs);
737 sortDumpableObjectsByTypeOid(dobjs, numObjs);
739 sortDumpableObjects(dobjs, numObjs);
742 * Create archive TOC entries for all the objects to be dumped, in a safe
746 /* First the special ENCODING and STDSTRINGS entries. */
747 dumpEncoding(g_fout);
748 dumpStdStrings(g_fout);
750 /* The database item is always next, unless we don't want it at all */
751 if (include_everything && !dataOnly)
752 dumpDatabase(g_fout);
754 /* Now the rearrangeable objects. */
755 for (i = 0; i < numObjs; i++)
756 dumpDumpableObject(g_fout, dobjs[i]);
759 * And finally we can do the actual output.
763 ropt = NewRestoreOptions();
764 ropt->filename = (char *) filename;
765 ropt->dropSchema = outputClean;
766 ropt->aclsSkip = aclsSkip;
767 ropt->superuser = outputSuperuser;
768 ropt->create = outputCreate;
769 ropt->noOwner = outputNoOwner;
770 ropt->noTablespace = outputNoTablespaces;
771 ropt->disable_triggers = disable_triggers;
772 ropt->use_setsessauth = use_setsessauth;
773 ropt->dataOnly = dataOnly;
775 if (compressLevel == -1)
776 ropt->compression = 0;
778 ropt->compression = compressLevel;
780 ropt->suppressDumpWarnings = true; /* We've already shown them */
782 RestoreArchive(g_fout, ropt);
785 CloseArchive(g_fout);
794 help(const char *progname)
796 printf(_("%s dumps a database as a text file or to other formats.\n\n"), progname);
797 printf(_("Usage:\n"));
798 printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
800 printf(_("\nGeneral options:\n"));
801 printf(_(" -f, --file=FILENAME output file name\n"));
802 printf(_(" -F, --format=c|t|p output file format (custom, tar, plain text)\n"));
803 printf(_(" -v, --verbose verbose mode\n"));
804 printf(_(" -Z, --compress=0-9 compression level for compressed formats\n"));
805 printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
806 printf(_(" --help show this help, then exit\n"));
807 printf(_(" --version output version information, then exit\n"));
809 printf(_("\nOptions controlling the output content:\n"));
810 printf(_(" -a, --data-only dump only the data, not the schema\n"));
811 printf(_(" -b, --blobs include large objects in dump\n"));
812 printf(_(" -c, --clean clean (drop) database objects before recreating\n"));
813 printf(_(" -C, --create include commands to create database in dump\n"));
814 printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
815 printf(_(" -n, --schema=SCHEMA dump the named schema(s) only\n"));
816 printf(_(" -N, --exclude-schema=SCHEMA do NOT dump the named schema(s)\n"));
817 printf(_(" -o, --oids include OIDs in dump\n"));
818 printf(_(" -O, --no-owner skip restoration of object ownership in\n"
819 " plain-text format\n"));
820 printf(_(" -s, --schema-only dump only the schema, no data\n"));
821 printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n"));
822 printf(_(" -t, --table=TABLE dump the named table(s) only\n"));
823 printf(_(" -T, --exclude-table=TABLE do NOT dump the named table(s)\n"));
824 printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
825 printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
826 printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
827 printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
828 printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
829 printf(_(" --disable-triggers disable triggers during data-only restore\n"));
830 printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
831 printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
832 printf(_(" --use-set-session-authorization\n"
833 " use SET SESSION AUTHORIZATION commands instead of\n"
834 " ALTER OWNER commands to set ownership\n"));
836 printf(_("\nConnection options:\n"));
837 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
838 printf(_(" -p, --port=PORT database server port number\n"));
839 printf(_(" -U, --username=NAME connect as specified database user\n"));
840 printf(_(" -w, --no-password never prompt for password\n"));
841 printf(_(" -W, --password force password prompt (should happen automatically)\n"));
843 printf(_("\nIf no database name is supplied, then the PGDATABASE environment\n"
844 "variable value is used.\n\n"));
845 printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
853 write_msg(NULL, "*** aborted because of error\n");
858 * Find the OIDs of all schemas matching the given list of patterns,
859 * and append them to the given OID list.
862 expand_schema_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
866 SimpleStringListCell *cell;
869 if (patterns->head == NULL)
870 return; /* nothing to do */
872 if (g_fout->remoteVersion < 70300)
874 write_msg(NULL, "server version must be at least 7.3 to use schema selection switches\n");
878 query = createPQExpBuffer();
881 * We use UNION ALL rather than UNION; this might sometimes result in
882 * duplicate entries in the OID list, but we don't care.
885 for (cell = patterns->head; cell; cell = cell->next)
887 if (cell != patterns->head)
888 appendPQExpBuffer(query, "UNION ALL\n");
889 appendPQExpBuffer(query,
890 "SELECT oid FROM pg_catalog.pg_namespace n\n");
891 processSQLNamePattern(g_conn, query, cell->val, false, false,
892 NULL, "n.nspname", NULL,
896 res = PQexec(g_conn, query->data);
897 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
899 for (i = 0; i < PQntuples(res); i++)
901 simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
905 destroyPQExpBuffer(query);
909 * Find the OIDs of all tables matching the given list of patterns,
910 * and append them to the given OID list.
913 expand_table_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
917 SimpleStringListCell *cell;
920 if (patterns->head == NULL)
921 return; /* nothing to do */
923 query = createPQExpBuffer();
926 * We use UNION ALL rather than UNION; this might sometimes result in
927 * duplicate entries in the OID list, but we don't care.
930 for (cell = patterns->head; cell; cell = cell->next)
932 if (cell != patterns->head)
933 appendPQExpBuffer(query, "UNION ALL\n");
934 appendPQExpBuffer(query,
936 "\nFROM pg_catalog.pg_class c"
937 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
938 "\nWHERE c.relkind in ('%c', '%c', '%c')\n",
939 RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
940 processSQLNamePattern(g_conn, query, cell->val, true, false,
941 "n.nspname", "c.relname", NULL,
942 "pg_catalog.pg_table_is_visible(c.oid)");
945 res = PQexec(g_conn, query->data);
946 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
948 for (i = 0; i < PQntuples(res); i++)
950 simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
954 destroyPQExpBuffer(query);
958 * selectDumpableNamespace: policy-setting subroutine
959 * Mark a namespace as to be dumped or not
962 selectDumpableNamespace(NamespaceInfo *nsinfo)
965 * If specific tables are being dumped, do not dump any complete
966 * namespaces. If specific namespaces are being dumped, dump just those
967 * namespaces. Otherwise, dump all non-system namespaces.
969 if (table_include_oids.head != NULL)
970 nsinfo->dobj.dump = false;
971 else if (schema_include_oids.head != NULL)
972 nsinfo->dobj.dump = simple_oid_list_member(&schema_include_oids,
973 nsinfo->dobj.catId.oid);
974 else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 ||
975 strcmp(nsinfo->dobj.name, "information_schema") == 0)
976 nsinfo->dobj.dump = false;
978 nsinfo->dobj.dump = true;
981 * In any case, a namespace can be excluded by an exclusion switch
983 if (nsinfo->dobj.dump &&
984 simple_oid_list_member(&schema_exclude_oids,
985 nsinfo->dobj.catId.oid))
986 nsinfo->dobj.dump = false;
990 * selectDumpableTable: policy-setting subroutine
991 * Mark a table as to be dumped or not
994 selectDumpableTable(TableInfo *tbinfo)
997 * If specific tables are being dumped, dump just those tables; else, dump
998 * according to the parent namespace's dump flag.
1000 if (table_include_oids.head != NULL)
1001 tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids,
1002 tbinfo->dobj.catId.oid);
1004 tbinfo->dobj.dump = tbinfo->dobj.namespace->dobj.dump;
1007 * In any case, a table can be excluded by an exclusion switch
1009 if (tbinfo->dobj.dump &&
1010 simple_oid_list_member(&table_exclude_oids,
1011 tbinfo->dobj.catId.oid))
1012 tbinfo->dobj.dump = false;
1016 * selectDumpableType: policy-setting subroutine
1017 * Mark a type as to be dumped or not
1019 * If it's a table's rowtype or an autogenerated array type, we also apply a
1020 * special type code to facilitate sorting into the desired order. (We don't
1021 * want to consider those to be ordinary types because that would bring tables
1022 * up into the datatype part of the dump order.) Those tests should be made
1023 * first to ensure the objType change is applied regardless of namespace etc.
1026 selectDumpableType(TypeInfo *tinfo)
1028 /* skip complex types, except for standalone composite types */
1029 if (OidIsValid(tinfo->typrelid) &&
1030 tinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
1032 tinfo->dobj.dump = false;
1033 tinfo->dobj.objType = DO_DUMMY_TYPE;
1036 /* skip auto-generated array types */
1037 else if (tinfo->isArray)
1039 tinfo->dobj.dump = false;
1040 tinfo->dobj.objType = DO_DUMMY_TYPE;
1043 /* dump only types in dumpable namespaces */
1044 else if (!tinfo->dobj.namespace->dobj.dump)
1045 tinfo->dobj.dump = false;
1047 /* skip undefined placeholder types */
1048 else if (!tinfo->isDefined)
1049 tinfo->dobj.dump = false;
1052 tinfo->dobj.dump = true;
1056 * selectDumpableDefaultACL: policy-setting subroutine
1057 * Mark a default ACL as to be dumped or not
1059 * For per-schema default ACLs, dump if the schema is to be dumped.
1060 * Otherwise dump if we are dumping "everything". Note that dataOnly
1061 * and aclsSkip are checked separately.
1064 selectDumpableDefaultACL(DefaultACLInfo *dinfo)
1066 if (dinfo->dobj.namespace)
1067 dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump;
1069 dinfo->dobj.dump = include_everything;
1073 * selectDumpableObject: policy-setting subroutine
1074 * Mark a generic dumpable object as to be dumped or not
1076 * Use this only for object types without a special-case routine above.
1079 selectDumpableObject(DumpableObject *dobj)
1082 * Default policy is to dump if parent namespace is dumpable, or always
1083 * for non-namespace-associated items.
1085 if (dobj->namespace)
1086 dobj->dump = dobj->namespace->dobj.dump;
1092 * Dump a table's contents for loading using the COPY command
1093 * - this routine is called by the Archiver when it wants the table
1098 dumpTableData_copy(Archive *fout, void *dcontext)
1100 TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
1101 TableInfo *tbinfo = tdinfo->tdtable;
1102 const char *classname = tbinfo->dobj.name;
1103 const bool hasoids = tbinfo->hasoids;
1104 const bool oids = tdinfo->oids;
1105 PQExpBuffer q = createPQExpBuffer();
1109 const char *column_list;
1112 write_msg(NULL, "dumping contents of table %s\n", classname);
1115 * Make sure we are in proper schema. We will qualify the table name
1116 * below anyway (in case its name conflicts with a pg_catalog table); but
1117 * this ensures reproducible results in case the table contains regproc,
1118 * regclass, etc columns.
1120 selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
1123 * If possible, specify the column list explicitly so that we have no
1124 * possibility of retrieving data in the wrong column order. (The default
1125 * column ordering of COPY will not be what we want in certain corner
1126 * cases involving ADD COLUMN and inheritance.)
1128 if (g_fout->remoteVersion >= 70300)
1129 column_list = fmtCopyColumnList(tbinfo);
1131 column_list = ""; /* can't select columns in COPY */
1133 if (oids && hasoids)
1135 appendPQExpBuffer(q, "COPY %s %s WITH OIDS TO stdout;",
1136 fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
1142 appendPQExpBuffer(q, "COPY %s %s TO stdout;",
1143 fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
1147 res = PQexec(g_conn, q->data);
1148 check_sql_result(res, g_conn, q->data, PGRES_COPY_OUT);
1153 ret = PQgetCopyData(g_conn, ©buf, 0);
1156 break; /* done or error */
1160 WriteData(fout, copybuf, ret);
1167 * There was considerable discussion in late July, 2000 regarding
1168 * slowing down pg_dump when backing up large tables. Users with both
1169 * slow & fast (multi-processor) machines experienced performance
1170 * degradation when doing a backup.
1172 * Initial attempts based on sleeping for a number of ms for each ms
1173 * of work were deemed too complex, then a simple 'sleep in each loop'
1174 * implementation was suggested. The latter failed because the loop
1175 * was too tight. Finally, the following was implemented:
1177 * If throttle is non-zero, then
1178 * See how long since the last sleep.
1179 * Work out how long to sleep (based on ratio).
1180 * If sleep is more than 100ms, then
1186 * where the throttle value was the number of ms to sleep per ms of
1187 * work. The calculation was done in each loop.
1189 * Most of the hard work is done in the backend, and this solution
1190 * still did not work particularly well: on slow machines, the ratio
1191 * was 50:1, and on medium paced machines, 1:1, and on fast
1192 * multi-processor machines, it had little or no effect, for reasons
1193 * that were unclear.
1195 * Further discussion ensued, and the proposal was dropped.
1197 * For those people who want this feature, it can be implemented using
1198 * gettimeofday in each loop, calculating the time since last sleep,
1199 * multiplying that by the sleep ratio, then if the result is more
1200 * than a preset 'minimum sleep time' (say 100ms), call the 'select'
1201 * function to sleep for a subsecond period ie.
1203 * select(0, NULL, NULL, NULL, &tvi);
1205 * This will return after the interval specified in the structure tvi.
1206 * Finally, call gettimeofday again to save the 'last sleep time'.
1210 archprintf(fout, "\\.\n\n\n");
1214 /* copy data transfer failed */
1215 write_msg(NULL, "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed.\n", classname);
1216 write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
1217 write_msg(NULL, "The command was: %s\n", q->data);
1221 /* Check command status and return to normal libpq state */
1222 res = PQgetResult(g_conn);
1223 check_sql_result(res, g_conn, q->data, PGRES_COMMAND_OK);
1226 destroyPQExpBuffer(q);
1231 dumpTableData_insert(Archive *fout, void *dcontext)
1233 TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
1234 TableInfo *tbinfo = tdinfo->tdtable;
1235 const char *classname = tbinfo->dobj.name;
1236 PQExpBuffer q = createPQExpBuffer();
1243 * Make sure we are in proper schema. We will qualify the table name
1244 * below anyway (in case its name conflicts with a pg_catalog table); but
1245 * this ensures reproducible results in case the table contains regproc,
1246 * regclass, etc columns.
1248 selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
1250 if (fout->remoteVersion >= 70100)
1252 appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
1253 "SELECT * FROM ONLY %s",
1254 fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
1259 appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
1261 fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
1265 res = PQexec(g_conn, q->data);
1266 check_sql_result(res, g_conn, q->data, PGRES_COMMAND_OK);
1272 res = PQexec(g_conn, "FETCH 100 FROM _pg_dump_cursor");
1273 check_sql_result(res, g_conn, "FETCH 100 FROM _pg_dump_cursor",
1275 nfields = PQnfields(res);
1276 for (tuple = 0; tuple < PQntuples(res); tuple++)
1278 archprintf(fout, "INSERT INTO %s ", fmtId(classname));
1281 /* corner case for zero-column table */
1282 archprintf(fout, "DEFAULT VALUES;\n");
1287 resetPQExpBuffer(q);
1288 appendPQExpBuffer(q, "(");
1289 for (field = 0; field < nfields; field++)
1292 appendPQExpBuffer(q, ", ");
1293 appendPQExpBufferStr(q, fmtId(PQfname(res, field)));
1295 appendPQExpBuffer(q, ") ");
1296 archputs(q->data, fout);
1298 archprintf(fout, "VALUES (");
1299 for (field = 0; field < nfields; field++)
1302 archprintf(fout, ", ");
1303 if (PQgetisnull(res, tuple, field))
1305 archprintf(fout, "NULL");
1309 /* XXX This code is partially duplicated in ruleutils.c */
1310 switch (PQftype(res, field))
1321 * These types are printed without quotes unless
1322 * they contain values that aren't accepted by the
1323 * scanner unquoted (e.g., 'NaN'). Note that
1324 * strtod() and friends might accept NaN, so we
1325 * can't use that to test.
1327 * In reality we only need to defend against
1328 * infinity and NaN, so we need not get too crazy
1329 * about pattern matching here.
1331 const char *s = PQgetvalue(res, tuple, field);
1333 if (strspn(s, "0123456789 +-eE.") == strlen(s))
1334 archprintf(fout, "%s", s);
1336 archprintf(fout, "'%s'", s);
1342 archprintf(fout, "B'%s'",
1343 PQgetvalue(res, tuple, field));
1347 if (strcmp(PQgetvalue(res, tuple, field), "t") == 0)
1348 archprintf(fout, "true");
1350 archprintf(fout, "false");
1354 /* All other types are printed as string literals. */
1355 resetPQExpBuffer(q);
1356 appendStringLiteralAH(q,
1357 PQgetvalue(res, tuple, field),
1359 archputs(q->data, fout);
1363 archprintf(fout, ");\n");
1365 } while (PQntuples(res) > 0);
1369 archprintf(fout, "\n\n");
1371 do_sql_command(g_conn, "CLOSE _pg_dump_cursor");
1373 destroyPQExpBuffer(q);
1380 * dump the contents of a single table
1382 * Actually, this just makes an ArchiveEntry for the table contents.
1385 dumpTableData(Archive *fout, TableDataInfo *tdinfo)
1387 TableInfo *tbinfo = tdinfo->tdtable;
1388 PQExpBuffer copyBuf = createPQExpBuffer();
1389 DataDumperPtr dumpFn;
1394 /* Dump/restore using COPY */
1395 dumpFn = dumpTableData_copy;
1396 /* must use 2 steps here 'cause fmtId is nonreentrant */
1397 appendPQExpBuffer(copyBuf, "COPY %s ",
1398 fmtId(tbinfo->dobj.name));
1399 appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n",
1400 fmtCopyColumnList(tbinfo),
1401 (tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "");
1402 copyStmt = copyBuf->data;
1406 /* Restore using INSERT */
1407 dumpFn = dumpTableData_insert;
1411 ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
1412 tbinfo->dobj.name, tbinfo->dobj.namespace->dobj.name,
1413 NULL, tbinfo->rolname,
1414 false, "TABLE DATA", SECTION_DATA,
1416 tdinfo->dobj.dependencies, tdinfo->dobj.nDeps,
1419 destroyPQExpBuffer(copyBuf);
1424 * set up dumpable objects representing the contents of tables
1427 getTableData(TableInfo *tblinfo, int numTables, bool oids)
1431 for (i = 0; i < numTables; i++)
1433 /* Skip VIEWs (no data to dump) */
1434 if (tblinfo[i].relkind == RELKIND_VIEW)
1436 /* Skip SEQUENCEs (handled elsewhere) */
1437 if (tblinfo[i].relkind == RELKIND_SEQUENCE)
1440 if (tblinfo[i].dobj.dump)
1442 TableDataInfo *tdinfo;
1444 tdinfo = (TableDataInfo *) malloc(sizeof(TableDataInfo));
1446 tdinfo->dobj.objType = DO_TABLE_DATA;
1449 * Note: use tableoid 0 so that this object won't be mistaken for
1450 * something that pg_depend entries apply to.
1452 tdinfo->dobj.catId.tableoid = 0;
1453 tdinfo->dobj.catId.oid = tblinfo[i].dobj.catId.oid;
1454 AssignDumpId(&tdinfo->dobj);
1455 tdinfo->dobj.name = tblinfo[i].dobj.name;
1456 tdinfo->dobj.namespace = tblinfo[i].dobj.namespace;
1457 tdinfo->tdtable = &(tblinfo[i]);
1458 tdinfo->oids = oids;
1459 addObjectDependency(&tdinfo->dobj, tblinfo[i].dobj.dumpId);
1461 tblinfo[i].dataObj = tdinfo;
1467 * getTableDataFKConstraints -
1468 * add dump-order dependencies reflecting foreign key constraints
1470 * This code is executed only in a data-only dump --- in schema+data dumps
1471 * we handle foreign key issues by not creating the FK constraints until
1472 * after the data is loaded. In a data-only dump, however, we want to
1473 * order the table data objects in such a way that a table's referenced
1474 * tables are restored first. (In the presence of circular references or
1475 * self-references this may be impossible; we'll detect and complain about
1476 * that during the dependency sorting step.)
1479 getTableDataFKConstraints(void)
1481 DumpableObject **dobjs;
1485 /* Search through all the dumpable objects for FK constraints */
1486 getDumpableObjects(&dobjs, &numObjs);
1487 for (i = 0; i < numObjs; i++)
1489 if (dobjs[i]->objType == DO_FK_CONSTRAINT)
1491 ConstraintInfo *cinfo = (ConstraintInfo *) dobjs[i];
1494 /* Not interesting unless both tables are to be dumped */
1495 if (cinfo->contable == NULL ||
1496 cinfo->contable->dataObj == NULL)
1498 ftable = findTableByOid(cinfo->confrelid);
1499 if (ftable == NULL ||
1500 ftable->dataObj == NULL)
1504 * Okay, make referencing table's TABLE_DATA object depend on the
1505 * referenced table's TABLE_DATA object.
1507 addObjectDependency(&cinfo->contable->dataObj->dobj,
1508 ftable->dataObj->dobj.dumpId);
1516 * guessConstraintInheritance:
1517 * In pre-8.4 databases, we can't tell for certain which constraints
1518 * are inherited. We assume a CHECK constraint is inherited if its name
1519 * matches the name of any constraint in the parent. Originally this code
1520 * tried to compare the expression texts, but that can fail for various
1521 * reasons --- for example, if the parent and child tables are in different
1522 * schemas, reverse-listing of function calls may produce different text
1523 * (schema-qualified or not) depending on search path.
1525 * In 8.4 and up we can rely on the conislocal field to decide which
1526 * constraints must be dumped; much safer.
1528 * This function assumes all conislocal flags were initialized to TRUE.
1529 * It clears the flag on anything that seems to be inherited.
1532 guessConstraintInheritance(TableInfo *tblinfo, int numTables)
1538 for (i = 0; i < numTables; i++)
1540 TableInfo *tbinfo = &(tblinfo[i]);
1542 TableInfo **parents;
1545 /* Sequences and views never have parents */
1546 if (tbinfo->relkind == RELKIND_SEQUENCE ||
1547 tbinfo->relkind == RELKIND_VIEW)
1550 /* Don't bother computing anything for non-target tables, either */
1551 if (!tbinfo->dobj.dump)
1554 numParents = tbinfo->numParents;
1555 parents = tbinfo->parents;
1557 if (numParents == 0)
1558 continue; /* nothing to see here, move along */
1560 /* scan for inherited CHECK constraints */
1561 for (j = 0; j < tbinfo->ncheck; j++)
1563 ConstraintInfo *constr;
1565 constr = &(tbinfo->checkexprs[j]);
1567 for (k = 0; k < numParents; k++)
1571 parent = parents[k];
1572 for (l = 0; l < parent->ncheck; l++)
1574 ConstraintInfo *pconstr = &(parent->checkexprs[l]);
1576 if (strcmp(pconstr->dobj.name, constr->dobj.name) == 0)
1578 constr->conislocal = false;
1582 if (!constr->conislocal)
1592 * dump the database definition
1595 dumpDatabase(Archive *AH)
1597 PQExpBuffer dbQry = createPQExpBuffer();
1598 PQExpBuffer delQry = createPQExpBuffer();
1599 PQExpBuffer creaQry = createPQExpBuffer();
1612 const char *datname,
1620 datname = PQdb(g_conn);
1623 write_msg(NULL, "saving database definition\n");
1625 /* Make sure we are in proper schema */
1626 selectSourceSchema("pg_catalog");
1628 /* Get the database owner and parameters from pg_database */
1629 if (g_fout->remoteVersion >= 80400)
1631 appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
1632 "(%s datdba) AS dba, "
1633 "pg_encoding_to_char(encoding) AS encoding, "
1634 "datcollate, datctype, datfrozenxid, "
1635 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
1636 "shobj_description(oid, 'pg_database') AS description "
1641 appendStringLiteralAH(dbQry, datname, AH);
1643 else if (g_fout->remoteVersion >= 80200)
1645 appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
1646 "(%s datdba) AS dba, "
1647 "pg_encoding_to_char(encoding) AS encoding, "
1648 "NULL AS datcollate, NULL AS datctype, datfrozenxid, "
1649 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
1650 "shobj_description(oid, 'pg_database') AS description "
1655 appendStringLiteralAH(dbQry, datname, AH);
1657 else if (g_fout->remoteVersion >= 80000)
1659 appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
1660 "(%s datdba) AS dba, "
1661 "pg_encoding_to_char(encoding) AS encoding, "
1662 "NULL AS datcollate, NULL AS datctype, datfrozenxid, "
1663 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace "
1667 appendStringLiteralAH(dbQry, datname, AH);
1669 else if (g_fout->remoteVersion >= 70100)
1671 appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
1672 "(%s datdba) AS dba, "
1673 "pg_encoding_to_char(encoding) AS encoding, "
1674 "NULL AS datcollate, NULL AS datctype, "
1675 "0 AS datfrozenxid, "
1676 "NULL AS tablespace "
1680 appendStringLiteralAH(dbQry, datname, AH);
1684 appendPQExpBuffer(dbQry, "SELECT "
1685 "(SELECT oid FROM pg_class WHERE relname = 'pg_database') AS tableoid, "
1687 "(%s datdba) AS dba, "
1688 "pg_encoding_to_char(encoding) AS encoding, "
1689 "NULL AS datcollate, NULL AS datctype, "
1690 "0 AS datfrozenxid, "
1691 "NULL AS tablespace "
1695 appendStringLiteralAH(dbQry, datname, AH);
1698 res = PQexec(g_conn, dbQry->data);
1699 check_sql_result(res, g_conn, dbQry->data, PGRES_TUPLES_OK);
1701 ntups = PQntuples(res);
1705 write_msg(NULL, "missing pg_database entry for database \"%s\"\n",
1712 write_msg(NULL, "query returned more than one (%d) pg_database entry for database \"%s\"\n",
1717 i_tableoid = PQfnumber(res, "tableoid");
1718 i_oid = PQfnumber(res, "oid");
1719 i_dba = PQfnumber(res, "dba");
1720 i_encoding = PQfnumber(res, "encoding");
1721 i_collate = PQfnumber(res, "datcollate");
1722 i_ctype = PQfnumber(res, "datctype");
1723 i_frozenxid = PQfnumber(res, "datfrozenxid");
1724 i_tablespace = PQfnumber(res, "tablespace");
1726 dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid));
1727 dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid));
1728 dba = PQgetvalue(res, 0, i_dba);
1729 encoding = PQgetvalue(res, 0, i_encoding);
1730 collate = PQgetvalue(res, 0, i_collate);
1731 ctype = PQgetvalue(res, 0, i_ctype);
1732 frozenxid = atooid(PQgetvalue(res, 0, i_frozenxid));
1733 tablespace = PQgetvalue(res, 0, i_tablespace);
1735 appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0",
1737 if (strlen(encoding) > 0)
1739 appendPQExpBuffer(creaQry, " ENCODING = ");
1740 appendStringLiteralAH(creaQry, encoding, AH);
1742 if (strlen(collate) > 0)
1744 appendPQExpBuffer(creaQry, " LC_COLLATE = ");
1745 appendStringLiteralAH(creaQry, collate, AH);
1747 if (strlen(ctype) > 0)
1749 appendPQExpBuffer(creaQry, " LC_CTYPE = ");
1750 appendStringLiteralAH(creaQry, ctype, AH);
1752 if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
1753 appendPQExpBuffer(creaQry, " TABLESPACE = %s",
1755 appendPQExpBuffer(creaQry, ";\n");
1759 appendPQExpBuffer(creaQry, "\n-- For binary upgrade, set datfrozenxid.\n");
1760 appendPQExpBuffer(creaQry, "UPDATE pg_catalog.pg_database\n"
1761 "SET datfrozenxid = '%u'\n"
1764 appendStringLiteralAH(creaQry, datname, AH);
1765 appendPQExpBuffer(creaQry, ";\n");
1769 appendPQExpBuffer(delQry, "DROP DATABASE %s;\n",
1772 dbDumpId = createDumpId();
1775 dbCatId, /* catalog ID */
1776 dbDumpId, /* dump ID */
1778 NULL, /* Namespace */
1779 NULL, /* Tablespace */
1781 false, /* with oids */
1782 "DATABASE", /* Desc */
1783 SECTION_PRE_DATA, /* Section */
1784 creaQry->data, /* Create */
1785 delQry->data, /* Del */
1790 NULL); /* Dumper Arg */
1793 * pg_largeobject comes from the old system intact, so set
1799 PQExpBuffer loFrozenQry = createPQExpBuffer();
1800 PQExpBuffer loOutQry = createPQExpBuffer();
1803 appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid\n"
1804 "FROM pg_catalog.pg_class\n"
1805 "WHERE oid = %d;\n",
1806 LargeObjectRelationId);
1808 lo_res = PQexec(g_conn, loFrozenQry->data);
1809 check_sql_result(lo_res, g_conn, loFrozenQry->data, PGRES_TUPLES_OK);
1811 if (PQntuples(lo_res) != 1)
1813 write_msg(NULL, "dumpDatabase(): could not find pg_largeobject.relfrozenxid\n");
1817 i_relfrozenxid = PQfnumber(lo_res, "relfrozenxid");
1819 appendPQExpBuffer(loOutQry, "\n-- For binary upgrade, set pg_largeobject relfrozenxid.\n");
1820 appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n"
1821 "SET relfrozenxid = '%u'\n"
1822 "WHERE oid = %d;\n",
1823 atoi(PQgetvalue(lo_res, 0, i_relfrozenxid)),
1824 LargeObjectRelationId);
1825 ArchiveEntry(AH, nilCatalogId, createDumpId(),
1826 "pg_largeobject", NULL, NULL, "",
1827 false, "pg_largeobject", SECTION_PRE_DATA,
1828 loOutQry->data, "", NULL,
1833 destroyPQExpBuffer(loFrozenQry);
1834 destroyPQExpBuffer(loOutQry);
1837 /* Dump DB comment if any */
1838 if (g_fout->remoteVersion >= 80200)
1841 * 8.2 keeps comments on shared objects in a shared table, so we
1842 * cannot use the dumpComment used for other database objects.
1844 char *comment = PQgetvalue(res, 0, PQfnumber(res, "description"));
1846 if (comment && strlen(comment))
1848 resetPQExpBuffer(dbQry);
1851 * Generates warning when loaded into a differently-named
1854 appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
1855 appendStringLiteralAH(dbQry, comment, AH);
1856 appendPQExpBuffer(dbQry, ";\n");
1858 ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
1859 dba, false, "COMMENT", SECTION_NONE,
1860 dbQry->data, "", NULL,
1861 &dbDumpId, 1, NULL, NULL);
1866 resetPQExpBuffer(dbQry);
1867 appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
1868 dumpComment(AH, dbQry->data, NULL, "",
1869 dbCatId, 0, dbDumpId);
1874 destroyPQExpBuffer(dbQry);
1875 destroyPQExpBuffer(delQry);
1876 destroyPQExpBuffer(creaQry);
1881 * dumpEncoding: put the correct encoding into the archive
1884 dumpEncoding(Archive *AH)
1886 const char *encname = pg_encoding_to_char(AH->encoding);
1887 PQExpBuffer qry = createPQExpBuffer();
1890 write_msg(NULL, "saving encoding = %s\n", encname);
1892 appendPQExpBuffer(qry, "SET client_encoding = ");
1893 appendStringLiteralAH(qry, encname, AH);
1894 appendPQExpBuffer(qry, ";\n");
1896 ArchiveEntry(AH, nilCatalogId, createDumpId(),
1897 "ENCODING", NULL, NULL, "",
1898 false, "ENCODING", SECTION_PRE_DATA,
1899 qry->data, "", NULL,
1903 destroyPQExpBuffer(qry);
1908 * dumpStdStrings: put the correct escape string behavior into the archive
1911 dumpStdStrings(Archive *AH)
1913 const char *stdstrings = AH->std_strings ? "on" : "off";
1914 PQExpBuffer qry = createPQExpBuffer();
1917 write_msg(NULL, "saving standard_conforming_strings = %s\n",
1920 appendPQExpBuffer(qry, "SET standard_conforming_strings = '%s';\n",
1923 ArchiveEntry(AH, nilCatalogId, createDumpId(),
1924 "STDSTRINGS", NULL, NULL, "",
1925 false, "STDSTRINGS", SECTION_PRE_DATA,
1926 qry->data, "", NULL,
1930 destroyPQExpBuffer(qry);
1936 * Test whether database contains any large objects
1939 hasBlobs(Archive *AH)
1942 const char *blobQry;
1945 /* Make sure we are in proper schema */
1946 selectSourceSchema("pg_catalog");
1948 /* Check for BLOB OIDs */
1949 if (AH->remoteVersion >= 80500)
1950 blobQry = "SELECT oid FROM pg_largeobject_metadata LIMIT 1";
1951 else if (AH->remoteVersion >= 70100)
1952 blobQry = "SELECT loid FROM pg_largeobject LIMIT 1";
1954 blobQry = "SELECT oid FROM pg_class WHERE relkind = 'l' LIMIT 1";
1956 res = PQexec(g_conn, blobQry);
1957 check_sql_result(res, g_conn, blobQry, PGRES_TUPLES_OK);
1959 result = PQntuples(res) > 0;
1971 dumpBlobs(Archive *AH, void *arg)
1973 const char *blobQry;
1974 const char *blobFetchQry;
1976 char buf[LOBBUFSIZE];
1981 write_msg(NULL, "saving large objects\n");
1983 /* Make sure we are in proper schema */
1984 selectSourceSchema("pg_catalog");
1986 /* Cursor to get all BLOB OIDs */
1987 if (AH->remoteVersion >= 80500)
1988 blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_largeobject_metadata";
1989 else if (AH->remoteVersion >= 70100)
1990 blobQry = "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
1992 blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class WHERE relkind = 'l'";
1994 res = PQexec(g_conn, blobQry);
1995 check_sql_result(res, g_conn, blobQry, PGRES_COMMAND_OK);
1997 /* Command to fetch from cursor */
1998 blobFetchQry = "FETCH 1000 IN bloboid";
2005 res = PQexec(g_conn, blobFetchQry);
2006 check_sql_result(res, g_conn, blobFetchQry, PGRES_TUPLES_OK);
2008 /* Process the tuples, if any */
2009 for (i = 0; i < PQntuples(res); i++)
2014 blobOid = atooid(PQgetvalue(res, i, 0));
2016 loFd = lo_open(g_conn, blobOid, INV_READ);
2019 write_msg(NULL, "dumpBlobs(): could not open large object: %s",
2020 PQerrorMessage(g_conn));
2024 StartBlob(AH, blobOid);
2026 /* Now read it in chunks, sending data to archive */
2029 cnt = lo_read(g_conn, loFd, buf, LOBBUFSIZE);
2032 write_msg(NULL, "dumpBlobs(): error reading large object: %s",
2033 PQerrorMessage(g_conn));
2037 WriteData(AH, buf, cnt);
2040 lo_close(g_conn, loFd);
2042 EndBlob(AH, blobOid);
2044 } while (PQntuples(res) > 0);
2053 * dump all blob properties.
2054 * It has "BLOB COMMENTS" tag due to the historical reason, but note
2055 * that it is the routine to dump all the properties of blobs.
2057 * Since we don't provide any way to be selective about dumping blobs,
2058 * there's no need to be selective about their comments either. We put
2059 * all the comments into one big TOC entry.
2062 dumpBlobComments(Archive *AH, void *arg)
2064 const char *blobQry;
2065 const char *blobFetchQry;
2066 PQExpBuffer cmdQry = createPQExpBuffer();
2071 write_msg(NULL, "saving large object properties\n");
2073 /* Make sure we are in proper schema */
2074 selectSourceSchema("pg_catalog");
2076 /* Cursor to get all BLOB comments */
2077 if (AH->remoteVersion >= 80500)
2078 blobQry = "DECLARE blobcmt CURSOR FOR SELECT oid, "
2079 "obj_description(oid, 'pg_largeobject'), "
2080 "pg_get_userbyid(lomowner), lomacl "
2081 "FROM pg_largeobject_metadata";
2082 else if (AH->remoteVersion >= 70300)
2083 blobQry = "DECLARE blobcmt CURSOR FOR SELECT loid, "
2084 "obj_description(loid, 'pg_largeobject'), NULL, NULL "
2085 "FROM (SELECT DISTINCT loid FROM "
2086 "pg_description d JOIN pg_largeobject l ON (objoid = loid) "
2087 "WHERE classoid = 'pg_largeobject'::regclass) ss";
2088 else if (AH->remoteVersion >= 70200)
2089 blobQry = "DECLARE blobcmt CURSOR FOR SELECT loid, "
2090 "obj_description(loid, 'pg_largeobject'), NULL, NULL "
2091 "FROM (SELECT DISTINCT loid FROM pg_largeobject) ss";
2092 else if (AH->remoteVersion >= 70100)
2093 blobQry = "DECLARE blobcmt CURSOR FOR SELECT loid, "
2094 "obj_description(loid), NULL, NULL "
2095 "FROM (SELECT DISTINCT loid FROM pg_largeobject) ss";
2097 blobQry = "DECLARE blobcmt CURSOR FOR SELECT oid, "
2099 " SELECT description "
2100 " FROM pg_description pd "
2101 " WHERE pd.objoid=pc.oid "
2103 "FROM pg_class pc WHERE relkind = 'l'";
2105 res = PQexec(g_conn, blobQry);
2106 check_sql_result(res, g_conn, blobQry, PGRES_COMMAND_OK);
2108 /* Command to fetch from cursor */
2109 blobFetchQry = "FETCH 100 IN blobcmt";
2116 res = PQexec(g_conn, blobFetchQry);
2117 check_sql_result(res, g_conn, blobFetchQry, PGRES_TUPLES_OK);
2119 /* Process the tuples, if any */
2120 for (i = 0; i < PQntuples(res); i++)
2122 Oid blobOid = atooid(PQgetvalue(res, i, 0));
2123 char *lo_comment = PQgetvalue(res, i, 1);
2124 char *lo_owner = PQgetvalue(res, i, 2);
2125 char *lo_acl = PQgetvalue(res, i, 3);
2128 resetPQExpBuffer(cmdQry);
2130 /* comment on the blob */
2131 if (!PQgetisnull(res, i, 1))
2133 appendPQExpBuffer(cmdQry,
2134 "COMMENT ON LARGE OBJECT %u IS ", blobOid);
2135 appendStringLiteralAH(cmdQry, lo_comment, AH);
2136 appendPQExpBuffer(cmdQry, ";\n");
2139 /* dump blob ownership, if necessary */
2140 if (!PQgetisnull(res, i, 2))
2142 appendPQExpBuffer(cmdQry,
2143 "ALTER LARGE OBJECT %u OWNER TO %s;\n",
2147 /* dump blob privileges, if necessary */
2148 if (!PQgetisnull(res, i, 3) &&
2149 !dataOnly && !aclsSkip)
2151 snprintf(lo_name, sizeof(lo_name), "%u", blobOid);
2152 if (!buildACLCommands(lo_name, NULL, "LARGE OBJECT",
2153 lo_acl, lo_owner, "",
2154 AH->remoteVersion, cmdQry))
2156 write_msg(NULL, "could not parse ACL (%s) for "
2157 "large object %u", lo_acl, blobOid);
2162 if (cmdQry->len > 0)
2164 appendPQExpBuffer(cmdQry, "\n");
2165 archputs(cmdQry->data, AH);
2168 } while (PQntuples(res) > 0);
2174 destroyPQExpBuffer(cmdQry);
2181 * read all namespaces in the system catalogs and return them in the
2182 * NamespaceInfo* structure
2184 * numNamespaces is set to the number of namespaces read in
2187 getNamespaces(int *numNamespaces)
2193 NamespaceInfo *nsinfo;
2201 * Before 7.3, there are no real namespaces; create two dummy entries, one
2202 * for user stuff and one for system stuff.
2204 if (g_fout->remoteVersion < 70300)
2206 nsinfo = (NamespaceInfo *) malloc(2 * sizeof(NamespaceInfo));
2208 nsinfo[0].dobj.objType = DO_NAMESPACE;
2209 nsinfo[0].dobj.catId.tableoid = 0;
2210 nsinfo[0].dobj.catId.oid = 0;
2211 AssignDumpId(&nsinfo[0].dobj);
2212 nsinfo[0].dobj.name = strdup("public");
2213 nsinfo[0].rolname = strdup("");
2214 nsinfo[0].nspacl = strdup("");
2216 selectDumpableNamespace(&nsinfo[0]);
2218 nsinfo[1].dobj.objType = DO_NAMESPACE;
2219 nsinfo[1].dobj.catId.tableoid = 0;
2220 nsinfo[1].dobj.catId.oid = 1;
2221 AssignDumpId(&nsinfo[1].dobj);
2222 nsinfo[1].dobj.name = strdup("pg_catalog");
2223 nsinfo[1].rolname = strdup("");
2224 nsinfo[1].nspacl = strdup("");
2226 selectDumpableNamespace(&nsinfo[1]);
2228 g_namespaces = nsinfo;
2229 g_numNamespaces = *numNamespaces = 2;
2234 query = createPQExpBuffer();
2236 /* Make sure we are in proper schema */
2237 selectSourceSchema("pg_catalog");
2240 * we fetch all namespaces including system ones, so that every object we
2241 * read in can be linked to a containing namespace.
2243 appendPQExpBuffer(query, "SELECT tableoid, oid, nspname, "
2244 "(%s nspowner) AS rolname, "
2245 "nspacl FROM pg_namespace",
2248 res = PQexec(g_conn, query->data);
2249 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
2251 ntups = PQntuples(res);
2253 nsinfo = (NamespaceInfo *) malloc(ntups * sizeof(NamespaceInfo));
2255 i_tableoid = PQfnumber(res, "tableoid");
2256 i_oid = PQfnumber(res, "oid");
2257 i_nspname = PQfnumber(res, "nspname");
2258 i_rolname = PQfnumber(res, "rolname");
2259 i_nspacl = PQfnumber(res, "nspacl");
2261 for (i = 0; i < ntups; i++)
2263 nsinfo[i].dobj.objType = DO_NAMESPACE;
2264 nsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
2265 nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
2266 AssignDumpId(&nsinfo[i].dobj);
2267 nsinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_nspname));
2268 nsinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
2269 nsinfo[i].nspacl = strdup(PQgetvalue(res, i, i_nspacl));
2271 /* Decide whether to dump this namespace */
2272 selectDumpableNamespace(&nsinfo[i]);
2274 if (strlen(nsinfo[i].rolname) == 0)
2275 write_msg(NULL, "WARNING: owner of schema \"%s\" appears to be invalid\n",
2276 nsinfo[i].dobj.name);
2280 destroyPQExpBuffer(query);
2282 g_namespaces = nsinfo;
2283 g_numNamespaces = *numNamespaces = ntups;
2290 * given a namespace OID and an object OID, look up the info read by
2293 * NB: for pre-7.3 source database, we use object OID to guess whether it's
2294 * a system object or not. In 7.3 and later there is no guessing.
2296 static NamespaceInfo *
2297 findNamespace(Oid nsoid, Oid objoid)
2301 if (g_fout->remoteVersion >= 70300)
2303 for (i = 0; i < g_numNamespaces; i++)
2305 NamespaceInfo *nsinfo = &g_namespaces[i];
2307 if (nsoid == nsinfo->dobj.catId.oid)
2310 write_msg(NULL, "schema with OID %u does not exist\n", nsoid);
2315 /* This code depends on the layout set up by getNamespaces. */
2316 if (objoid > g_last_builtin_oid)
2317 i = 0; /* user object */
2319 i = 1; /* system object */
2320 return &g_namespaces[i];
2323 return NULL; /* keep compiler quiet */
2328 * read all types in the system catalogs and return them in the
2329 * TypeInfo* structure
2331 * numTypes is set to the number of types read in
2333 * NB: this must run after getFuncs() because we assume we can do
2337 getTypes(int *numTypes)
2342 PQExpBuffer query = createPQExpBuffer();
2344 ShellTypeInfo *stinfo;
2360 * we include even the built-in types because those may be used as array
2361 * elements by user-defined types
2363 * we filter out the built-in types when we dump out the types
2365 * same approach for undefined (shell) types and array types
2367 * Note: as of 8.3 we can reliably detect whether a type is an
2368 * auto-generated array type by checking the element type's typarray.
2369 * (Before that the test is capable of generating false positives.) We
2370 * still check for name beginning with '_', though, so as to avoid the
2371 * cost of the subselect probe for all standard types. This would have to
2372 * be revisited if the backend ever allows renaming of array types.
2375 /* Make sure we are in proper schema */
2376 selectSourceSchema("pg_catalog");
2378 if (g_fout->remoteVersion >= 80300)
2380 appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
2382 "(%s typowner) AS rolname, "
2383 "typinput::oid AS typinput, "
2384 "typoutput::oid AS typoutput, typelem, typrelid, "
2385 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2386 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2387 "typtype, typisdefined, "
2388 "typname[0] = '_' AND typelem != 0 AND "
2389 "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
2393 else if (g_fout->remoteVersion >= 70300)
2395 appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
2397 "(%s typowner) AS rolname, "
2398 "typinput::oid AS typinput, "
2399 "typoutput::oid AS typoutput, typelem, typrelid, "
2400 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2401 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2402 "typtype, typisdefined, "
2403 "typname[0] = '_' AND typelem != 0 AS isarray "
2407 else if (g_fout->remoteVersion >= 70100)
2409 appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
2410 "0::oid AS typnamespace, "
2411 "(%s typowner) AS rolname, "
2412 "typinput::oid AS typinput, "
2413 "typoutput::oid AS typoutput, typelem, typrelid, "
2414 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2415 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2416 "typtype, typisdefined, "
2417 "typname[0] = '_' AND typelem != 0 AS isarray "
2423 appendPQExpBuffer(query, "SELECT "
2424 "(SELECT oid FROM pg_class WHERE relname = 'pg_type') AS tableoid, "
2426 "0::oid AS typnamespace, "
2427 "(%s typowner) AS rolname, "
2428 "typinput::oid AS typinput, "
2429 "typoutput::oid AS typoutput, typelem, typrelid, "
2430 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2431 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2432 "typtype, typisdefined, "
2433 "typname[0] = '_' AND typelem != 0 AS isarray "
2438 res = PQexec(g_conn, query->data);
2439 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
2441 ntups = PQntuples(res);
2443 tinfo = (TypeInfo *) malloc(ntups * sizeof(TypeInfo));
2445 i_tableoid = PQfnumber(res, "tableoid");
2446 i_oid = PQfnumber(res, "oid");
2447 i_typname = PQfnumber(res, "typname");
2448 i_typnamespace = PQfnumber(res, "typnamespace");
2449 i_rolname = PQfnumber(res, "rolname");
2450 i_typinput = PQfnumber(res, "typinput");
2451 i_typoutput = PQfnumber(res, "typoutput");
2452 i_typelem = PQfnumber(res, "typelem");
2453 i_typrelid = PQfnumber(res, "typrelid");
2454 i_typrelkind = PQfnumber(res, "typrelkind");
2455 i_typtype = PQfnumber(res, "typtype");
2456 i_typisdefined = PQfnumber(res, "typisdefined");
2457 i_isarray = PQfnumber(res, "isarray");
2459 for (i = 0; i < ntups; i++)
2461 tinfo[i].dobj.objType = DO_TYPE;
2462 tinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
2463 tinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
2464 AssignDumpId(&tinfo[i].dobj);
2465 tinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_typname));
2466 tinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_typnamespace)),
2467 tinfo[i].dobj.catId.oid);
2468 tinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
2469 tinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem));
2470 tinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid));
2471 tinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
2472 tinfo[i].typtype = *PQgetvalue(res, i, i_typtype);
2473 tinfo[i].shellType = NULL;
2475 if (strcmp(PQgetvalue(res, i, i_typisdefined), "t") == 0)
2476 tinfo[i].isDefined = true;
2478 tinfo[i].isDefined = false;
2480 if (strcmp(PQgetvalue(res, i, i_isarray), "t") == 0)
2481 tinfo[i].isArray = true;
2483 tinfo[i].isArray = false;
2485 /* Decide whether we want to dump it */
2486 selectDumpableType(&tinfo[i]);
2489 * If it's a domain, fetch info about its constraints, if any
2491 tinfo[i].nDomChecks = 0;
2492 tinfo[i].domChecks = NULL;
2493 if (tinfo[i].dobj.dump && tinfo[i].typtype == TYPTYPE_DOMAIN)
2494 getDomainConstraints(&(tinfo[i]));
2497 * If it's a base type, make a DumpableObject representing a shell
2498 * definition of the type. We will need to dump that ahead of the I/O
2499 * functions for the type.
2501 * Note: the shell type doesn't have a catId. You might think it
2502 * should copy the base type's catId, but then it might capture the
2503 * pg_depend entries for the type, which we don't want.
2505 if (tinfo[i].dobj.dump && tinfo[i].typtype == TYPTYPE_BASE)
2507 stinfo = (ShellTypeInfo *) malloc(sizeof(ShellTypeInfo));
2508 stinfo->dobj.objType = DO_SHELL_TYPE;
2509 stinfo->dobj.catId = nilCatalogId;
2510 AssignDumpId(&stinfo->dobj);
2511 stinfo->dobj.name = strdup(tinfo[i].dobj.name);
2512 stinfo->dobj.namespace = tinfo[i].dobj.namespace;
2513 stinfo->baseType = &(tinfo[i]);
2514 tinfo[i].shellType = stinfo;
2517 * Initially mark the shell type as not to be dumped. We'll only
2518 * dump it if the I/O functions need to be dumped; this is taken
2519 * care of while sorting dependencies.
2521 stinfo->dobj.dump = false;
2524 * However, if dumping from pre-7.3, there will be no dependency
2525 * info so we have to fake it here. We only need to worry about
2526 * typinput and typoutput since the other functions only exist
2529 if (g_fout->remoteVersion < 70300)
2535 typinput = atooid(PQgetvalue(res, i, i_typinput));
2536 typoutput = atooid(PQgetvalue(res, i, i_typoutput));
2538 funcInfo = findFuncByOid(typinput);
2539 if (funcInfo && funcInfo->dobj.dump)
2541 /* base type depends on function */
2542 addObjectDependency(&tinfo[i].dobj,
2543 funcInfo->dobj.dumpId);
2544 /* function depends on shell type */
2545 addObjectDependency(&funcInfo->dobj,
2546 stinfo->dobj.dumpId);
2547 /* mark shell type as to be dumped */
2548 stinfo->dobj.dump = true;
2551 funcInfo = findFuncByOid(typoutput);
2552 if (funcInfo && funcInfo->dobj.dump)
2554 /* base type depends on function */
2555 addObjectDependency(&tinfo[i].dobj,
2556 funcInfo->dobj.dumpId);
2557 /* function depends on shell type */
2558 addObjectDependency(&funcInfo->dobj,
2559 stinfo->dobj.dumpId);
2560 /* mark shell type as to be dumped */
2561 stinfo->dobj.dump = true;
2566 if (strlen(tinfo[i].rolname) == 0 && tinfo[i].isDefined)
2567 write_msg(NULL, "WARNING: owner of data type \"%s\" appears to be invalid\n",
2568 tinfo[i].dobj.name);
2575 destroyPQExpBuffer(query);
2582 * read all operators in the system catalogs and return them in the
2583 * OprInfo* structure
2585 * numOprs is set to the number of operators read in
2588 getOperators(int *numOprs)
2593 PQExpBuffer query = createPQExpBuffer();
2603 * find all operators, including builtin operators; we filter out
2604 * system-defined operators at dump-out time.
2607 /* Make sure we are in proper schema */
2608 selectSourceSchema("pg_catalog");
2610 if (g_fout->remoteVersion >= 70300)
2612 appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
2614 "(%s oprowner) AS rolname, "
2615 "oprcode::oid AS oprcode "
2619 else if (g_fout->remoteVersion >= 70100)
2621 appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
2622 "0::oid AS oprnamespace, "
2623 "(%s oprowner) AS rolname, "
2624 "oprcode::oid AS oprcode "
2630 appendPQExpBuffer(query, "SELECT "
2631 "(SELECT oid FROM pg_class WHERE relname = 'pg_operator') AS tableoid, "
2633 "0::oid AS oprnamespace, "
2634 "(%s oprowner) AS rolname, "
2635 "oprcode::oid AS oprcode "
2640 res = PQexec(g_conn, query->data);
2641 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
2643 ntups = PQntuples(res);
2646 oprinfo = (OprInfo *) malloc(ntups * sizeof(OprInfo));
2648 i_tableoid = PQfnumber(res, "tableoid");
2649 i_oid = PQfnumber(res, "oid");
2650 i_oprname = PQfnumber(res, "oprname");
2651 i_oprnamespace = PQfnumber(res, "oprnamespace");
2652 i_rolname = PQfnumber(res, "rolname");
2653 i_oprcode = PQfnumber(res, "oprcode");
2655 for (i = 0; i < ntups; i++)
2657 oprinfo[i].dobj.objType = DO_OPERATOR;
2658 oprinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
2659 oprinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
2660 AssignDumpId(&oprinfo[i].dobj);
2661 oprinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_oprname));
2662 oprinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_oprnamespace)),
2663 oprinfo[i].dobj.catId.oid);
2664 oprinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
2665 oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
2667 /* Decide whether we want to dump it */
2668 selectDumpableObject(&(oprinfo[i].dobj));
2670 if (strlen(oprinfo[i].rolname) == 0)
2671 write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
2672 oprinfo[i].dobj.name);
2677 destroyPQExpBuffer(query);
2684 * read all conversions in the system catalogs and return them in the
2685 * ConvInfo* structure
2687 * numConversions is set to the number of conversions read in
2690 getConversions(int *numConversions)
2695 PQExpBuffer query = createPQExpBuffer();
2703 /* Conversions didn't exist pre-7.3 */
2704 if (g_fout->remoteVersion < 70300)
2706 *numConversions = 0;
2711 * find all conversions, including builtin conversions; we filter out
2712 * system-defined conversions at dump-out time.
2715 /* Make sure we are in proper schema */
2716 selectSourceSchema("pg_catalog");
2718 appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
2720 "(%s conowner) AS rolname "
2721 "FROM pg_conversion",
2724 res = PQexec(g_conn, query->data);
2725 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
2727 ntups = PQntuples(res);
2728 *numConversions = ntups;
2730 convinfo = (ConvInfo *) malloc(ntups * sizeof(ConvInfo));
2732 i_tableoid = PQfnumber(res, "tableoid");
2733 i_oid = PQfnumber(res, "oid");
2734 i_conname = PQfnumber(res, "conname");
2735 i_connamespace = PQfnumber(res, "connamespace");
2736 i_rolname = PQfnumber(res, "rolname");
2738 for (i = 0; i < ntups; i++)
2740 convinfo[i].dobj.objType = DO_CONVERSION;
2741 convinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
2742 convinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
2743 AssignDumpId(&convinfo[i].dobj);
2744 convinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_conname));
2745 convinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_connamespace)),
2746 convinfo[i].dobj.catId.oid);
2747 convinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
2749 /* Decide whether we want to dump it */
2750 selectDumpableObject(&(convinfo[i].dobj));
2755 destroyPQExpBuffer(query);
2762 * read all opclasses in the system catalogs and return them in the
2763 * OpclassInfo* structure
2765 * numOpclasses is set to the number of opclasses read in
2768 getOpclasses(int *numOpclasses)
2773 PQExpBuffer query = createPQExpBuffer();
2774 OpclassInfo *opcinfo;
2782 * find all opclasses, including builtin opclasses; we filter out
2783 * system-defined opclasses at dump-out time.
2786 /* Make sure we are in proper schema */
2787 selectSourceSchema("pg_catalog");
2789 if (g_fout->remoteVersion >= 70300)
2791 appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
2793 "(%s opcowner) AS rolname "
2797 else if (g_fout->remoteVersion >= 70100)
2799 appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
2800 "0::oid AS opcnamespace, "
2801 "''::name AS rolname "
2806 appendPQExpBuffer(query, "SELECT "
2807 "(SELECT oid FROM pg_class WHERE relname = 'pg_opclass') AS tableoid, "
2809 "0::oid AS opcnamespace, "
2810 "''::name AS rolname "
2814 res = PQexec(g_conn, query->data);
2815 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
2817 ntups = PQntuples(res);
2818 *numOpclasses = ntups;
2820 opcinfo = (OpclassInfo *) malloc(ntups * sizeof(OpclassInfo));
2822 i_tableoid = PQfnumber(res, "tableoid");
2823 i_oid = PQfnumber(res, "oid");
2824 i_opcname = PQfnumber(res, "opcname");
2825 i_opcnamespace = PQfnumber(res, "opcnamespace");
2826 i_rolname = PQfnumber(res, "rolname");
2828 for (i = 0; i < ntups; i++)
2830 opcinfo[i].dobj.objType = DO_OPCLASS;
2831 opcinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
2832 opcinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
2833 AssignDumpId(&opcinfo[i].dobj);
2834 opcinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_opcname));
2835 opcinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_opcnamespace)),
2836 opcinfo[i].dobj.catId.oid);
2837 opcinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
2839 /* Decide whether we want to dump it */
2840 selectDumpableObject(&(opcinfo[i].dobj));
2842 if (g_fout->remoteVersion >= 70300)
2844 if (strlen(opcinfo[i].rolname) == 0)
2845 write_msg(NULL, "WARNING: owner of operator class \"%s\" appears to be invalid\n",
2846 opcinfo[i].dobj.name);
2852 destroyPQExpBuffer(query);
2859 * read all opfamilies in the system catalogs and return them in the
2860 * OpfamilyInfo* structure
2862 * numOpfamilies is set to the number of opfamilies read in
2865 getOpfamilies(int *numOpfamilies)
2871 OpfamilyInfo *opfinfo;
2878 /* Before 8.3, there is no separate concept of opfamilies */
2879 if (g_fout->remoteVersion < 80300)
2885 query = createPQExpBuffer();
2888 * find all opfamilies, including builtin opfamilies; we filter out
2889 * system-defined opfamilies at dump-out time.
2892 /* Make sure we are in proper schema */
2893 selectSourceSchema("pg_catalog");
2895 appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, "
2897 "(%s opfowner) AS rolname "
2901 res = PQexec(g_conn, query->data);
2902 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
2904 ntups = PQntuples(res);
2905 *numOpfamilies = ntups;
2907 opfinfo = (OpfamilyInfo *) malloc(ntups * sizeof(OpfamilyInfo));
2909 i_tableoid = PQfnumber(res, "tableoid");
2910 i_oid = PQfnumber(res, "oid");
2911 i_opfname = PQfnumber(res, "opfname");
2912 i_opfnamespace = PQfnumber(res, "opfnamespace");
2913 i_rolname = PQfnumber(res, "rolname");
2915 for (i = 0; i < ntups; i++)
2917 opfinfo[i].dobj.objType = DO_OPFAMILY;
2918 opfinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
2919 opfinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
2920 AssignDumpId(&opfinfo[i].dobj);
2921 opfinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_opfname));
2922 opfinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_opfnamespace)),
2923 opfinfo[i].dobj.catId.oid);
2924 opfinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
2926 /* Decide whether we want to dump it */
2927 selectDumpableObject(&(opfinfo[i].dobj));
2929 if (g_fout->remoteVersion >= 70300)
2931 if (strlen(opfinfo[i].rolname) == 0)
2932 write_msg(NULL, "WARNING: owner of operator family \"%s\" appears to be invalid\n",
2933 opfinfo[i].dobj.name);
2939 destroyPQExpBuffer(query);
2946 * read all the user-defined aggregates in the system catalogs and
2947 * return them in the AggInfo* structure
2949 * numAggs is set to the number of aggregates read in
2952 getAggregates(int *numAggs)
2957 PQExpBuffer query = createPQExpBuffer();
2968 /* Make sure we are in proper schema */
2969 selectSourceSchema("pg_catalog");
2971 /* find all user-defined aggregates */
2973 if (g_fout->remoteVersion >= 80200)
2975 appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
2976 "pronamespace AS aggnamespace, "
2977 "pronargs, proargtypes, "
2978 "(%s proowner) AS rolname, "
2982 "AND pronamespace != "
2983 "(SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog')",
2986 else if (g_fout->remoteVersion >= 70300)
2988 appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
2989 "pronamespace AS aggnamespace, "
2990 "CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, "
2992 "(%s proowner) AS rolname, "
2996 "AND pronamespace != "
2997 "(SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog')",
3000 else if (g_fout->remoteVersion >= 70100)
3002 appendPQExpBuffer(query, "SELECT tableoid, oid, aggname, "
3003 "0::oid AS aggnamespace, "
3004 "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
3005 "aggbasetype AS proargtypes, "
3006 "(%s aggowner) AS rolname, "
3008 "FROM pg_aggregate "
3009 "where oid > '%u'::oid",
3011 g_last_builtin_oid);
3015 appendPQExpBuffer(query, "SELECT "
3016 "(SELECT oid FROM pg_class WHERE relname = 'pg_aggregate') AS tableoid, "
3018 "0::oid AS aggnamespace, "
3019 "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
3020 "aggbasetype AS proargtypes, "
3021 "(%s aggowner) AS rolname, "
3023 "FROM pg_aggregate "
3024 "where oid > '%u'::oid",
3026 g_last_builtin_oid);
3029 res = PQexec(g_conn, query->data);
3030 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3032 ntups = PQntuples(res);
3035 agginfo = (AggInfo *) malloc(ntups * sizeof(AggInfo));
3037 i_tableoid = PQfnumber(res, "tableoid");
3038 i_oid = PQfnumber(res, "oid");
3039 i_aggname = PQfnumber(res, "aggname");
3040 i_aggnamespace = PQfnumber(res, "aggnamespace");
3041 i_pronargs = PQfnumber(res, "pronargs");
3042 i_proargtypes = PQfnumber(res, "proargtypes");
3043 i_rolname = PQfnumber(res, "rolname");
3044 i_aggacl = PQfnumber(res, "aggacl");
3046 for (i = 0; i < ntups; i++)
3048 agginfo[i].aggfn.dobj.objType = DO_AGG;
3049 agginfo[i].aggfn.dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
3050 agginfo[i].aggfn.dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
3051 AssignDumpId(&agginfo[i].aggfn.dobj);
3052 agginfo[i].aggfn.dobj.name = strdup(PQgetvalue(res, i, i_aggname));
3053 agginfo[i].aggfn.dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_aggnamespace)),
3054 agginfo[i].aggfn.dobj.catId.oid);
3055 agginfo[i].aggfn.rolname = strdup(PQgetvalue(res, i, i_rolname));
3056 if (strlen(agginfo[i].aggfn.rolname) == 0)
3057 write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
3058 agginfo[i].aggfn.dobj.name);
3059 agginfo[i].aggfn.lang = InvalidOid; /* not currently interesting */
3060 agginfo[i].aggfn.prorettype = InvalidOid; /* not saved */
3061 agginfo[i].aggfn.proacl = strdup(PQgetvalue(res, i, i_aggacl));
3062 agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs));
3063 if (agginfo[i].aggfn.nargs == 0)
3064 agginfo[i].aggfn.argtypes = NULL;
3067 agginfo[i].aggfn.argtypes = (Oid *) malloc(agginfo[i].aggfn.nargs * sizeof(Oid));
3068 if (g_fout->remoteVersion >= 70300)
3069 parseOidArray(PQgetvalue(res, i, i_proargtypes),
3070 agginfo[i].aggfn.argtypes,
3071 agginfo[i].aggfn.nargs);
3073 /* it's just aggbasetype */
3074 agginfo[i].aggfn.argtypes[0] = atooid(PQgetvalue(res, i, i_proargtypes));
3077 /* Decide whether we want to dump it */
3078 selectDumpableObject(&(agginfo[i].aggfn.dobj));
3083 destroyPQExpBuffer(query);
3090 * read all the user-defined functions in the system catalogs and
3091 * return them in the FuncInfo* structure
3093 * numFuncs is set to the number of functions read in
3096 getFuncs(int *numFuncs)
3101 PQExpBuffer query = createPQExpBuffer();
3114 /* Make sure we are in proper schema */
3115 selectSourceSchema("pg_catalog");
3117 /* find all user-defined funcs */
3119 if (g_fout->remoteVersion >= 70300)
3121 appendPQExpBuffer(query,
3122 "SELECT tableoid, oid, proname, prolang, "
3123 "pronargs, proargtypes, prorettype, proacl, "
3125 "(%s proowner) AS rolname "
3127 "WHERE NOT proisagg "
3128 "AND pronamespace != "
3129 "(SELECT oid FROM pg_namespace "
3130 "WHERE nspname = 'pg_catalog')",
3133 else if (g_fout->remoteVersion >= 70100)
3135 appendPQExpBuffer(query,
3136 "SELECT tableoid, oid, proname, prolang, "
3137 "pronargs, proargtypes, prorettype, "
3138 "'{=X}' AS proacl, "
3139 "0::oid AS pronamespace, "
3140 "(%s proowner) AS rolname "
3142 "WHERE pg_proc.oid > '%u'::oid",
3144 g_last_builtin_oid);
3148 appendPQExpBuffer(query,
3150 "(SELECT oid FROM pg_class "
3151 " WHERE relname = 'pg_proc') AS tableoid, "
3152 "oid, proname, prolang, "
3153 "pronargs, proargtypes, prorettype, "
3154 "'{=X}' AS proacl, "
3155 "0::oid AS pronamespace, "
3156 "(%s proowner) AS rolname "
3158 "where pg_proc.oid > '%u'::oid",
3160 g_last_builtin_oid);
3163 res = PQexec(g_conn, query->data);
3164 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3166 ntups = PQntuples(res);
3170 finfo = (FuncInfo *) calloc(ntups, sizeof(FuncInfo));
3172 i_tableoid = PQfnumber(res, "tableoid");
3173 i_oid = PQfnumber(res, "oid");
3174 i_proname = PQfnumber(res, "proname");
3175 i_pronamespace = PQfnumber(res, "pronamespace");
3176 i_rolname = PQfnumber(res, "rolname");
3177 i_prolang = PQfnumber(res, "prolang");
3178 i_pronargs = PQfnumber(res, "pronargs");
3179 i_proargtypes = PQfnumber(res, "proargtypes");
3180 i_prorettype = PQfnumber(res, "prorettype");
3181 i_proacl = PQfnumber(res, "proacl");
3183 for (i = 0; i < ntups; i++)
3185 finfo[i].dobj.objType = DO_FUNC;
3186 finfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
3187 finfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
3188 AssignDumpId(&finfo[i].dobj);
3189 finfo[i].dobj.name = strdup(PQgetvalue(res, i, i_proname));
3190 finfo[i].dobj.namespace =
3191 findNamespace(atooid(PQgetvalue(res, i, i_pronamespace)),
3192 finfo[i].dobj.catId.oid);
3193 finfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
3194 finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
3195 finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
3196 finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl));
3197 finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
3198 if (finfo[i].nargs == 0)
3199 finfo[i].argtypes = NULL;
3202 finfo[i].argtypes = (Oid *) malloc(finfo[i].nargs * sizeof(Oid));
3203 parseOidArray(PQgetvalue(res, i, i_proargtypes),
3204 finfo[i].argtypes, finfo[i].nargs);
3207 /* Decide whether we want to dump it */
3208 selectDumpableObject(&(finfo[i].dobj));
3210 if (strlen(finfo[i].rolname) == 0)
3212 "WARNING: owner of function \"%s\" appears to be invalid\n",
3213 finfo[i].dobj.name);
3218 destroyPQExpBuffer(query);
3225 * read all the user-defined tables (no indexes, no catalogs)
3226 * in the system catalogs return them in the TableInfo* structure
3228 * numTables is set to the number of tables read in
3231 getTables(int *numTables)
3236 PQExpBuffer query = createPQExpBuffer();
3246 int i_relhastriggers;
3253 int i_reltablespace;
3255 int i_toastreloptions;
3257 /* Make sure we are in proper schema */
3258 selectSourceSchema("pg_catalog");
3261 * Find all the tables (including views and sequences).
3263 * We include system catalogs, so that we can work if a user table is
3264 * defined to inherit from a system catalog (pretty weird, but...)
3266 * We ignore tables that are not type 'r' (ordinary relation), 'S'
3267 * (sequence), 'v' (view), or 'c' (composite type).
3269 * Composite-type table entries won't be dumped as such, but we have to
3270 * make a DumpableObject for them so that we can track dependencies of the
3271 * composite type (pg_depend entries for columns of the composite type
3272 * link to the pg_class entry not the pg_type entry).
3274 * Note: in this phase we should collect only a minimal amount of
3275 * information about each table, basically just enough to decide if it is
3276 * interesting. We must fetch all tables in this phase because otherwise
3277 * we cannot correctly identify inherited columns, owned sequences, etc.
3280 if (g_fout->remoteVersion >= 80400)
3283 * Left join to pick up dependency info linking sequences to their
3284 * owning column, if any (note this dependency is AUTO as of 8.2)
3286 appendPQExpBuffer(query,
3287 "SELECT c.tableoid, c.oid, c.relname, "
3288 "c.relacl, c.relkind, c.relnamespace, "
3289 "(%s c.relowner) AS rolname, "
3290 "c.relchecks, c.relhastriggers, "
3291 "c.relhasindex, c.relhasrules, c.relhasoids, "
3293 "d.refobjid AS owning_tab, "
3294 "d.refobjsubid AS owning_col, "
3295 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3296 "array_to_string(c.reloptions, ', ') AS reloptions, "
3297 "array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions "
3299 "LEFT JOIN pg_depend d ON "
3300 "(c.relkind = '%c' AND "
3301 "d.classid = c.tableoid AND d.objid = c.oid AND "
3302 "d.objsubid = 0 AND "
3303 "d.refclassid = c.tableoid AND d.deptype = 'a') "
3304 "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
3305 "WHERE c.relkind in ('%c', '%c', '%c', '%c') "
3309 RELKIND_RELATION, RELKIND_SEQUENCE,
3310 RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
3312 else if (g_fout->remoteVersion >= 80200)
3315 * Left join to pick up dependency info linking sequences to their
3316 * owning column, if any (note this dependency is AUTO as of 8.2)
3318 appendPQExpBuffer(query,
3319 "SELECT c.tableoid, c.oid, relname, "
3320 "relacl, relkind, relnamespace, "
3321 "(%s relowner) AS rolname, "
3322 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3323 "relhasindex, relhasrules, relhasoids, "
3325 "d.refobjid AS owning_tab, "
3326 "d.refobjsubid AS owning_col, "
3327 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3328 "array_to_string(c.reloptions, ', ') AS reloptions, "
3329 "NULL AS toast_reloptions "
3331 "LEFT JOIN pg_depend d ON "
3332 "(c.relkind = '%c' AND "
3333 "d.classid = c.tableoid AND d.objid = c.oid AND "
3334 "d.objsubid = 0 AND "
3335 "d.refclassid = c.tableoid AND d.deptype = 'a') "
3336 "WHERE relkind in ('%c', '%c', '%c', '%c') "
3340 RELKIND_RELATION, RELKIND_SEQUENCE,
3341 RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
3343 else if (g_fout->remoteVersion >= 80000)
3346 * Left join to pick up dependency info linking sequences to their
3347 * owning column, if any
3349 appendPQExpBuffer(query,
3350 "SELECT c.tableoid, c.oid, relname, "
3351 "relacl, relkind, relnamespace, "
3352 "(%s relowner) AS rolname, "
3353 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3354 "relhasindex, relhasrules, relhasoids, "
3355 "0 AS relfrozenxid, "
3356 "d.refobjid AS owning_tab, "
3357 "d.refobjsubid AS owning_col, "
3358 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3359 "NULL AS reloptions, "
3360 "NULL AS toast_reloptions "
3362 "LEFT JOIN pg_depend d ON "
3363 "(c.relkind = '%c' AND "
3364 "d.classid = c.tableoid AND d.objid = c.oid AND "
3365 "d.objsubid = 0 AND "
3366 "d.refclassid = c.tableoid AND d.deptype = 'i') "
3367 "WHERE relkind in ('%c', '%c', '%c', '%c') "
3371 RELKIND_RELATION, RELKIND_SEQUENCE,
3372 RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
3374 else if (g_fout->remoteVersion >= 70300)
3377 * Left join to pick up dependency info linking sequences to their
3378 * owning column, if any
3380 appendPQExpBuffer(query,
3381 "SELECT c.tableoid, c.oid, relname, "
3382 "relacl, relkind, relnamespace, "
3383 "(%s relowner) AS rolname, "
3384 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3385 "relhasindex, relhasrules, relhasoids, "
3386 "0 AS relfrozenxid, "
3387 "d.refobjid AS owning_tab, "
3388 "d.refobjsubid AS owning_col, "
3389 "NULL AS reltablespace, "
3390 "NULL AS reloptions, "
3391 "NULL AS toast_reloptions "
3393 "LEFT JOIN pg_depend d ON "
3394 "(c.relkind = '%c' AND "
3395 "d.classid = c.tableoid AND d.objid = c.oid AND "
3396 "d.objsubid = 0 AND "
3397 "d.refclassid = c.tableoid AND d.deptype = 'i') "
3398 "WHERE relkind IN ('%c', '%c', '%c', '%c') "
3402 RELKIND_RELATION, RELKIND_SEQUENCE,
3403 RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
3405 else if (g_fout->remoteVersion >= 70200)
3407 appendPQExpBuffer(query,
3408 "SELECT tableoid, oid, relname, relacl, relkind, "
3409 "0::oid AS relnamespace, "
3410 "(%s relowner) AS rolname, "
3411 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3412 "relhasindex, relhasrules, relhasoids, "
3413 "0 AS relfrozenxid, "
3414 "NULL::oid AS owning_tab, "
3415 "NULL::int4 AS owning_col, "
3416 "NULL AS reltablespace, "
3417 "NULL AS reloptions, "
3418 "NULL AS toast_reloptions "
3420 "WHERE relkind IN ('%c', '%c', '%c') "
3423 RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
3425 else if (g_fout->remoteVersion >= 70100)
3427 /* all tables have oids in 7.1 */
3428 appendPQExpBuffer(query,
3429 "SELECT tableoid, oid, relname, relacl, relkind, "
3430 "0::oid AS relnamespace, "
3431 "(%s relowner) AS rolname, "
3432 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3433 "relhasindex, relhasrules, "
3434 "'t'::bool AS relhasoids, "
3435 "0 AS relfrozenxid, "
3436 "NULL::oid AS owning_tab, "
3437 "NULL::int4 AS owning_col, "
3438 "NULL AS reltablespace, "
3439 "NULL AS reloptions, "
3440 "NULL AS toast_reloptions "
3442 "WHERE relkind IN ('%c', '%c', '%c') "
3445 RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
3450 * Before 7.1, view relkind was not set to 'v', so we must check if we
3451 * have a view by looking for a rule in pg_rewrite.
3453 appendPQExpBuffer(query,
3455 "(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
3456 "oid, relname, relacl, "
3457 "CASE WHEN relhasrules and relkind = 'r' "
3458 " and EXISTS(SELECT rulename FROM pg_rewrite r WHERE "
3459 " r.ev_class = c.oid AND r.ev_type = '1') "
3460 "THEN '%c'::\"char\" "
3461 "ELSE relkind END AS relkind,"
3462 "0::oid AS relnamespace, "
3463 "(%s relowner) AS rolname, "
3464 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3465 "relhasindex, relhasrules, "
3466 "'t'::bool AS relhasoids, "
3467 "0 as relfrozenxid, "
3468 "NULL::oid AS owning_tab, "
3469 "NULL::int4 AS owning_col, "
3470 "NULL AS reltablespace, "
3471 "NULL AS reloptions, "
3472 "NULL AS toast_reloptions "
3474 "WHERE relkind IN ('%c', '%c') "
3478 RELKIND_RELATION, RELKIND_SEQUENCE);
3481 res = PQexec(g_conn, query->data);
3482 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3484 ntups = PQntuples(res);
3489 * Extract data from result and lock dumpable tables. We do the locking
3490 * before anything else, to minimize the window wherein a table could
3491 * disappear under us.
3493 * Note that we have to save info about all tables here, even when dumping
3494 * only one, because we don't yet know which tables might be inheritance
3495 * ancestors of the target table.
3497 tblinfo = (TableInfo *) calloc(ntups, sizeof(TableInfo));
3499 i_reltableoid = PQfnumber(res, "tableoid");
3500 i_reloid = PQfnumber(res, "oid");
3501 i_relname = PQfnumber(res, "relname");
3502 i_relnamespace = PQfnumber(res, "relnamespace");
3503 i_relacl = PQfnumber(res, "relacl");
3504 i_relkind = PQfnumber(res, "relkind");
3505 i_rolname = PQfnumber(res, "rolname");
3506 i_relchecks = PQfnumber(res, "relchecks");
3507 i_relhastriggers = PQfnumber(res, "relhastriggers");
3508 i_relhasindex = PQfnumber(res, "relhasindex");
3509 i_relhasrules = PQfnumber(res, "relhasrules");
3510 i_relhasoids = PQfnumber(res, "relhasoids");
3511 i_relfrozenxid = PQfnumber(res, "relfrozenxid");
3512 i_owning_tab = PQfnumber(res, "owning_tab");
3513 i_owning_col = PQfnumber(res, "owning_col");
3514 i_reltablespace = PQfnumber(res, "reltablespace");
3515 i_reloptions = PQfnumber(res, "reloptions");
3516 i_toastreloptions = PQfnumber(res, "toast_reloptions");
3518 if (lockWaitTimeout && g_fout->remoteVersion >= 70300)
3521 * Arrange to fail instead of waiting forever for a table lock.
3523 * NB: this coding assumes that the only queries issued within the
3524 * following loop are LOCK TABLEs; else the timeout may be undesirably
3525 * applied to other things too.
3527 resetPQExpBuffer(query);
3528 appendPQExpBuffer(query, "SET statement_timeout = ");
3529 appendStringLiteralConn(query, lockWaitTimeout, g_conn);
3530 do_sql_command(g_conn, query->data);
3533 for (i = 0; i < ntups; i++)
3535 tblinfo[i].dobj.objType = DO_TABLE;
3536 tblinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_reltableoid));
3537 tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid));
3538 AssignDumpId(&tblinfo[i].dobj);
3539 tblinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_relname));
3540 tblinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_relnamespace)),
3541 tblinfo[i].dobj.catId.oid);
3542 tblinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
3543 tblinfo[i].relacl = strdup(PQgetvalue(res, i, i_relacl));
3544 tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
3545 tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
3546 tblinfo[i].hasrules = (strcmp(PQgetvalue(res, i, i_relhasrules), "t") == 0);
3547 tblinfo[i].hastriggers = (strcmp(PQgetvalue(res, i, i_relhastriggers), "t") == 0);
3548 tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
3549 tblinfo[i].frozenxid = atooid(PQgetvalue(res, i, i_relfrozenxid));
3550 tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
3551 if (PQgetisnull(res, i, i_owning_tab))
3553 tblinfo[i].owning_tab = InvalidOid;
3554 tblinfo[i].owning_col = 0;
3558 tblinfo[i].owning_tab = atooid(PQgetvalue(res, i, i_owning_tab));
3559 tblinfo[i].owning_col = atoi(PQgetvalue(res, i, i_owning_col));
3561 tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace));
3562 tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions));
3563 tblinfo[i].toast_reloptions = strdup(PQgetvalue(res, i, i_toastreloptions));
3565 /* other fields were zeroed above */
3568 * Decide whether we want to dump this table.
3570 if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
3571 tblinfo[i].dobj.dump = false;
3573 selectDumpableTable(&tblinfo[i]);
3574 tblinfo[i].interesting = tblinfo[i].dobj.dump;
3577 * Read-lock target tables to make sure they aren't DROPPED or altered
3578 * in schema before we get around to dumping them.
3580 * Note that we don't explicitly lock parents of the target tables; we
3581 * assume our lock on the child is enough to prevent schema
3582 * alterations to parent tables.
3584 * NOTE: it'd be kinda nice to lock views and sequences too, not only
3585 * plain tables, but the backend doesn't presently allow that.
3587 if (tblinfo[i].dobj.dump && tblinfo[i].relkind == RELKIND_RELATION)
3589 resetPQExpBuffer(query);
3590 appendPQExpBuffer(query,
3591 "LOCK TABLE %s IN ACCESS SHARE MODE",
3592 fmtQualifiedId(tblinfo[i].dobj.namespace->dobj.name,
3593 tblinfo[i].dobj.name));
3594 do_sql_command(g_conn, query->data);
3597 /* Emit notice if join for owner failed */
3598 if (strlen(tblinfo[i].rolname) == 0)
3599 write_msg(NULL, "WARNING: owner of table \"%s\" appears to be invalid\n",
3600 tblinfo[i].dobj.name);
3603 if (lockWaitTimeout && g_fout->remoteVersion >= 70300)
3605 do_sql_command(g_conn, "SET statement_timeout = 0");
3611 * Force sequences that are "owned" by table columns to be dumped whenever
3612 * their owning table is being dumped.
3614 for (i = 0; i < ntups; i++)
3616 TableInfo *seqinfo = &tblinfo[i];
3619 if (!OidIsValid(seqinfo->owning_tab))
3620 continue; /* not an owned sequence */
3621 if (seqinfo->dobj.dump)
3622 continue; /* no need to search */
3624 /* can't use findTableByOid yet, unfortunately */
3625 for (j = 0; j < ntups; j++)
3627 if (tblinfo[j].dobj.catId.oid == seqinfo->owning_tab)
3629 if (tblinfo[j].dobj.dump)
3631 seqinfo->interesting = true;
3632 seqinfo->dobj.dump = true;
3639 destroyPQExpBuffer(query);
3646 * read all the inheritance information
3647 * from the system catalogs return them in the InhInfo* structure
3649 * numInherits is set to the number of pairs read in
3652 getInherits(int *numInherits)
3657 PQExpBuffer query = createPQExpBuffer();
3663 /* Make sure we are in proper schema */
3664 selectSourceSchema("pg_catalog");
3666 /* find all the inheritance information */
3668 appendPQExpBuffer(query, "SELECT inhrelid, inhparent FROM pg_inherits");
3670 res = PQexec(g_conn, query->data);
3671 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3673 ntups = PQntuples(res);
3675 *numInherits = ntups;
3677 inhinfo = (InhInfo *) malloc(ntups * sizeof(InhInfo));
3679 i_inhrelid = PQfnumber(res, "inhrelid");
3680 i_inhparent = PQfnumber(res, "inhparent");
3682 for (i = 0; i < ntups; i++)
3684 inhinfo[i].inhrelid = atooid(PQgetvalue(res, i, i_inhrelid));
3685 inhinfo[i].inhparent = atooid(PQgetvalue(res, i, i_inhparent));
3690 destroyPQExpBuffer(query);
3697 * get information about every index on a dumpable table
3699 * Note: index data is not returned directly to the caller, but it
3700 * does get entered into the DumpableObject tables.
3703 getIndexes(TableInfo tblinfo[], int numTables)
3707 PQExpBuffer query = createPQExpBuffer();
3710 ConstraintInfo *constrinfo;
3729 for (i = 0; i < numTables; i++)
3731 TableInfo *tbinfo = &tblinfo[i];
3733 /* Only plain tables have indexes */
3734 if (tbinfo->relkind != RELKIND_RELATION || !tbinfo->hasindex)
3737 /* Ignore indexes of tables not to be dumped */
3738 if (!tbinfo->dobj.dump)
3742 write_msg(NULL, "reading indexes for table \"%s\"\n",
3745 /* Make sure we are in proper schema so indexdef is right */
3746 selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
3749 * The point of the messy-looking outer join is to find a constraint
3750 * that is related by an internal dependency link to the index. If we
3751 * find one, create a CONSTRAINT entry linked to the INDEX entry. We
3752 * assume an index won't have more than one internal dependency.
3754 resetPQExpBuffer(query);
3755 if (g_fout->remoteVersion >= 80500)
3757 appendPQExpBuffer(query,
3758 "SELECT t.tableoid, t.oid, "
3759 "t.relname AS indexname, "
3760 "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
3761 "t.relnatts AS indnkeys, "
3762 "i.indkey, i.indisclustered, "
3763 "c.contype, c.conname, "
3764 "c.condeferrable, c.condeferred, "
3765 "c.tableoid AS contableoid, "
3767 "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
3768 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
3769 "array_to_string(t.reloptions, ', ') AS options "
3770 "FROM pg_catalog.pg_index i "
3771 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
3772 "LEFT JOIN pg_catalog.pg_depend d "
3773 "ON (d.classid = t.tableoid "
3774 "AND d.objid = t.oid "
3775 "AND d.deptype = 'i') "
3776 "LEFT JOIN pg_catalog.pg_constraint c "
3777 "ON (d.refclassid = c.tableoid "
3778 "AND d.refobjid = c.oid) "
3779 "WHERE i.indrelid = '%u'::pg_catalog.oid "
3780 "ORDER BY indexname",
3781 tbinfo->dobj.catId.oid);
3783 else if (g_fout->remoteVersion >= 80200)
3785 appendPQExpBuffer(query,
3786 "SELECT t.tableoid, t.oid, "
3787 "t.relname AS indexname, "
3788 "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
3789 "t.relnatts AS indnkeys, "
3790 "i.indkey, i.indisclustered, "
3791 "c.contype, c.conname, "
3792 "c.condeferrable, c.condeferred, "
3793 "c.tableoid AS contableoid, "
3796 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
3797 "array_to_string(t.reloptions, ', ') AS options "
3798 "FROM pg_catalog.pg_index i "
3799 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
3800 "LEFT JOIN pg_catalog.pg_depend d "
3801 "ON (d.classid = t.tableoid "
3802 "AND d.objid = t.oid "
3803 "AND d.deptype = 'i') "
3804 "LEFT JOIN pg_catalog.pg_constraint c "
3805 "ON (d.refclassid = c.tableoid "
3806 "AND d.refobjid = c.oid) "
3807 "WHERE i.indrelid = '%u'::pg_catalog.oid "
3808 "ORDER BY indexname",
3809 tbinfo->dobj.catId.oid);
3811 else if (g_fout->remoteVersion >= 80000)
3813 appendPQExpBuffer(query,
3814 "SELECT t.tableoid, t.oid, "
3815 "t.relname AS indexname, "
3816 "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
3817 "t.relnatts AS indnkeys, "
3818 "i.indkey, i.indisclustered, "
3819 "c.contype, c.conname, "
3820 "c.condeferrable, c.condeferred, "
3821 "c.tableoid AS contableoid, "
3824 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
3826 "FROM pg_catalog.pg_index i "
3827 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
3828 "LEFT JOIN pg_catalog.pg_depend d "
3829 "ON (d.classid = t.tableoid "
3830 "AND d.objid = t.oid "
3831 "AND d.deptype = 'i') "
3832 "LEFT JOIN pg_catalog.pg_constraint c "
3833 "ON (d.refclassid = c.tableoid "
3834 "AND d.refobjid = c.oid) "
3835 "WHERE i.indrelid = '%u'::pg_catalog.oid "
3836 "ORDER BY indexname",
3837 tbinfo->dobj.catId.oid);
3839 else if (g_fout->remoteVersion >= 70300)
3841 appendPQExpBuffer(query,
3842 "SELECT t.tableoid, t.oid, "
3843 "t.relname AS indexname, "
3844 "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
3845 "t.relnatts AS indnkeys, "
3846 "i.indkey, i.indisclustered, "
3847 "c.contype, c.conname, "
3848 "c.condeferrable, c.condeferred, "
3849 "c.tableoid AS contableoid, "
3852 "NULL AS tablespace, "
3854 "FROM pg_catalog.pg_index i "
3855 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
3856 "LEFT JOIN pg_catalog.pg_depend d "
3857 "ON (d.classid = t.tableoid "
3858 "AND d.objid = t.oid "
3859 "AND d.deptype = 'i') "
3860 "LEFT JOIN pg_catalog.pg_constraint c "
3861 "ON (d.refclassid = c.tableoid "
3862 "AND d.refobjid = c.oid) "
3863 "WHERE i.indrelid = '%u'::pg_catalog.oid "
3864 "ORDER BY indexname",
3865 tbinfo->dobj.catId.oid);
3867 else if (g_fout->remoteVersion >= 70100)
3869 appendPQExpBuffer(query,
3870 "SELECT t.tableoid, t.oid, "
3871 "t.relname AS indexname, "
3872 "pg_get_indexdef(i.indexrelid) AS indexdef, "
3873 "t.relnatts AS indnkeys, "
3874 "i.indkey, false AS indisclustered, "
3875 "CASE WHEN i.indisprimary THEN 'p'::char "
3876 "ELSE '0'::char END AS contype, "
3877 "t.relname AS conname, "
3878 "false AS condeferrable, "
3879 "false AS condeferred, "
3880 "0::oid AS contableoid, "
3883 "NULL AS tablespace, "
3885 "FROM pg_index i, pg_class t "
3886 "WHERE t.oid = i.indexrelid "
3887 "AND i.indrelid = '%u'::oid "
3888 "ORDER BY indexname",
3889 tbinfo->dobj.catId.oid);
3893 appendPQExpBuffer(query,
3895 "(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
3897 "t.relname AS indexname, "
3898 "pg_get_indexdef(i.indexrelid) AS indexdef, "
3899 "t.relnatts AS indnkeys, "
3900 "i.indkey, false AS indisclustered, "
3901 "CASE WHEN i.indisprimary THEN 'p'::char "
3902 "ELSE '0'::char END AS contype, "
3903 "t.relname AS conname, "
3904 "false AS condeferrable, "
3905 "false AS condeferred, "
3906 "0::oid AS contableoid, "
3909 "NULL AS tablespace, "
3911 "FROM pg_index i, pg_class t "
3912 "WHERE t.oid = i.indexrelid "
3913 "AND i.indrelid = '%u'::oid "
3914 "ORDER BY indexname",
3915 tbinfo->dobj.catId.oid);
3918 res = PQexec(g_conn, query->data);
3919 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
3921 ntups = PQntuples(res);
3923 i_tableoid = PQfnumber(res, "tableoid");
3924 i_oid = PQfnumber(res, "oid");
3925 i_indexname = PQfnumber(res, "indexname");
3926 i_indexdef = PQfnumber(res, "indexdef");
3927 i_indnkeys = PQfnumber(res, "indnkeys");
3928 i_indkey = PQfnumber(res, "indkey");
3929 i_indisclustered = PQfnumber(res, "indisclustered");
3930 i_contype = PQfnumber(res, "contype");
3931 i_conname = PQfnumber(res, "conname");
3932 i_condeferrable = PQfnumber(res, "condeferrable");
3933 i_condeferred = PQfnumber(res, "condeferred");
3934 i_contableoid = PQfnumber(res, "contableoid");
3935 i_conoid = PQfnumber(res, "conoid");
3936 i_condef = PQfnumber(res, "condef");
3937 i_tablespace = PQfnumber(res, "tablespace");
3938 i_options = PQfnumber(res, "options");
3940 indxinfo = (IndxInfo *) malloc(ntups * sizeof(IndxInfo));
3941 constrinfo = (ConstraintInfo *) malloc(ntups * sizeof(ConstraintInfo));
3943 for (j = 0; j < ntups; j++)
3947 indxinfo[j].dobj.objType = DO_INDEX;
3948 indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
3949 indxinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
3950 AssignDumpId(&indxinfo[j].dobj);
3951 indxinfo[j].dobj.name = strdup(PQgetvalue(res, j, i_indexname));
3952 indxinfo[j].dobj.namespace = tbinfo->dobj.namespace;
3953 indxinfo[j].indextable = tbinfo;
3954 indxinfo[j].indexdef = strdup(PQgetvalue(res, j, i_indexdef));
3955 indxinfo[j].indnkeys = atoi(PQgetvalue(res, j, i_indnkeys));
3956 indxinfo[j].tablespace = strdup(PQgetvalue(res, j, i_tablespace));
3957 indxinfo[j].options = strdup(PQgetvalue(res, j, i_options));
3960 * In pre-7.4 releases, indkeys may contain more entries than
3961 * indnkeys says (since indnkeys will be 1 for a functional
3962 * index). We don't actually care about this case since we don't
3963 * examine indkeys except for indexes associated with PRIMARY and
3964 * UNIQUE constraints, which are never functional indexes. But we
3965 * have to allocate enough space to keep parseOidArray from
3968 indxinfo[j].indkeys = (Oid *) malloc(INDEX_MAX_KEYS * sizeof(Oid));
3969 parseOidArray(PQgetvalue(res, j, i_indkey),
3970 indxinfo[j].indkeys, INDEX_MAX_KEYS);
3971 indxinfo[j].indisclustered = (PQgetvalue(res, j, i_indisclustered)[0] == 't');
3972 contype = *(PQgetvalue(res, j, i_contype));
3974 if (contype == 'p' || contype == 'u' || contype == 'x')
3977 * If we found a constraint matching the index, create an
3980 * In a pre-7.3 database, we take this path iff the index was
3981 * marked indisprimary.
3983 constrinfo[j].dobj.objType = DO_CONSTRAINT;
3984 constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
3985 constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
3986 AssignDumpId(&constrinfo[j].dobj);
3987 constrinfo[j].dobj.name = strdup(PQgetvalue(res, j, i_conname));
3988 constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
3989 constrinfo[j].contable = tbinfo;
3990 constrinfo[j].condomain = NULL;
3991 constrinfo[j].contype = contype;
3993 constrinfo[j].condef = strdup(PQgetvalue(res, j, i_condef));
3995 constrinfo[j].condef = NULL;
3996 constrinfo[j].confrelid = InvalidOid;
3997 constrinfo[j].conindex = indxinfo[j].dobj.dumpId;
3998 constrinfo[j].condeferrable = *(PQgetvalue(res, j, i_condeferrable)) == 't';
3999 constrinfo[j].condeferred = *(PQgetvalue(res, j, i_condeferred)) == 't';
4000 constrinfo[j].conislocal = true;
4001 constrinfo[j].separate = true;
4003 indxinfo[j].indexconstraint = constrinfo[j].dobj.dumpId;
4005 /* If pre-7.3 DB, better make sure table comes first */
4006 addObjectDependency(&constrinfo[j].dobj,
4007 tbinfo->dobj.dumpId);
4011 /* Plain secondary index */
4012 indxinfo[j].indexconstraint = 0;
4019 destroyPQExpBuffer(query);
4025 * Get info about constraints on dumpable tables.
4027 * Currently handles foreign keys only.
4028 * Unique and primary key constraints are handled with indexes,
4029 * while check constraints are processed in getTableAttrs().
4032 getConstraints(TableInfo tblinfo[], int numTables)
4036 ConstraintInfo *constrinfo;
4046 /* pg_constraint was created in 7.3, so nothing to do if older */
4047 if (g_fout->remoteVersion < 70300)
4050 query = createPQExpBuffer();
4052 for (i = 0; i < numTables; i++)
4054 TableInfo *tbinfo = &tblinfo[i];
4056 if (!tbinfo->hastriggers || !tbinfo->dobj.dump)
4060 write_msg(NULL, "reading foreign key constraints for table \"%s\"\n",
4064 * select table schema to ensure constraint expr is qualified if
4067 selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
4069 resetPQExpBuffer(query);
4070 appendPQExpBuffer(query,
4071 "SELECT tableoid, oid, conname, confrelid, "
4072 "pg_catalog.pg_get_constraintdef(oid) AS condef "
4073 "FROM pg_catalog.pg_constraint "
4074 "WHERE conrelid = '%u'::pg_catalog.oid "
4075 "AND contype = 'f'",
4076 tbinfo->dobj.catId.oid);
4077 res = PQexec(g_conn, query->data);
4078 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4080 ntups = PQntuples(res);
4082 i_contableoid = PQfnumber(res, "tableoid");
4083 i_conoid = PQfnumber(res, "oid");
4084 i_conname = PQfnumber(res, "conname");
4085 i_confrelid = PQfnumber(res, "confrelid");
4086 i_condef = PQfnumber(res, "condef");
4088 constrinfo = (ConstraintInfo *) malloc(ntups * sizeof(ConstraintInfo));
4090 for (j = 0; j < ntups; j++)
4092 constrinfo[j].dobj.objType = DO_FK_CONSTRAINT;
4093 constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
4094 constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
4095 AssignDumpId(&constrinfo[j].dobj);
4096 constrinfo[j].dobj.name = strdup(PQgetvalue(res, j, i_conname));
4097 constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
4098 constrinfo[j].contable = tbinfo;
4099 constrinfo[j].condomain = NULL;
4100 constrinfo[j].contype = 'f';
4101 constrinfo[j].condef = strdup(PQgetvalue(res, j, i_condef));
4102 constrinfo[j].confrelid = atooid(PQgetvalue(res, j, i_confrelid));
4103 constrinfo[j].conindex = 0;
4104 constrinfo[j].condeferrable = false;
4105 constrinfo[j].condeferred = false;
4106 constrinfo[j].conislocal = true;
4107 constrinfo[j].separate = true;
4113 destroyPQExpBuffer(query);
4117 * getDomainConstraints
4119 * Get info about constraints on a domain.
4122 getDomainConstraints(TypeInfo *tinfo)
4125 ConstraintInfo *constrinfo;
4134 /* pg_constraint was created in 7.3, so nothing to do if older */
4135 if (g_fout->remoteVersion < 70300)
4139 * select appropriate schema to ensure names in constraint are properly
4142 selectSourceSchema(tinfo->dobj.namespace->dobj.name);
4144 query = createPQExpBuffer();
4146 if (g_fout->remoteVersion >= 70400)
4147 appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
4148 "pg_catalog.pg_get_constraintdef(oid) AS consrc "
4149 "FROM pg_catalog.pg_constraint "
4150 "WHERE contypid = '%u'::pg_catalog.oid "
4152 tinfo->dobj.catId.oid);
4154 appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
4155 "'CHECK (' || consrc || ')' AS consrc "
4156 "FROM pg_catalog.pg_constraint "
4157 "WHERE contypid = '%u'::pg_catalog.oid "
4159 tinfo->dobj.catId.oid);
4161 res = PQexec(g_conn, query->data);
4162 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4164 ntups = PQntuples(res);
4166 i_tableoid = PQfnumber(res, "tableoid");
4167 i_oid = PQfnumber(res, "oid");
4168 i_conname = PQfnumber(res, "conname");
4169 i_consrc = PQfnumber(res, "consrc");
4171 constrinfo = (ConstraintInfo *) malloc(ntups * sizeof(ConstraintInfo));
4173 tinfo->nDomChecks = ntups;
4174 tinfo->domChecks = constrinfo;
4176 for (i = 0; i < ntups; i++)
4178 constrinfo[i].dobj.objType = DO_CONSTRAINT;
4179 constrinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
4180 constrinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
4181 AssignDumpId(&constrinfo[i].dobj);
4182 constrinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_conname));
4183 constrinfo[i].dobj.namespace = tinfo->dobj.namespace;
4184 constrinfo[i].contable = NULL;
4185 constrinfo[i].condomain = tinfo;
4186 constrinfo[i].contype = 'c';
4187 constrinfo[i].condef = strdup(PQgetvalue(res, i, i_consrc));
4188 constrinfo[i].confrelid = InvalidOid;
4189 constrinfo[i].conindex = 0;
4190 constrinfo[i].condeferrable = false;
4191 constrinfo[i].condeferred = false;
4192 constrinfo[i].conislocal = true;
4193 constrinfo[i].separate = false;
4196 * Make the domain depend on the constraint, ensuring it won't be
4197 * output till any constraint dependencies are OK.
4199 addObjectDependency(&tinfo->dobj,
4200 constrinfo[i].dobj.dumpId);
4205 destroyPQExpBuffer(query);
4210 * get basic information about every rule in the system
4212 * numRules is set to the number of rules read in
4215 getRules(int *numRules)
4220 PQExpBuffer query = createPQExpBuffer();
4230 /* Make sure we are in proper schema */
4231 selectSourceSchema("pg_catalog");
4233 if (g_fout->remoteVersion >= 80300)
4235 appendPQExpBuffer(query, "SELECT "
4236 "tableoid, oid, rulename, "
4237 "ev_class AS ruletable, ev_type, is_instead, "
4242 else if (g_fout->remoteVersion >= 70100)
4244 appendPQExpBuffer(query, "SELECT "
4245 "tableoid, oid, rulename, "
4246 "ev_class AS ruletable, ev_type, is_instead, "
4247 "'O'::char AS ev_enabled "
4253 appendPQExpBuffer(query, "SELECT "
4254 "(SELECT oid FROM pg_class WHERE relname = 'pg_rewrite') AS tableoid, "
4256 "ev_class AS ruletable, ev_type, is_instead, "
4257 "'O'::char AS ev_enabled "
4262 res = PQexec(g_conn, query->data);
4263 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4265 ntups = PQntuples(res);
4269 ruleinfo = (RuleInfo *) malloc(ntups * sizeof(RuleInfo));
4271 i_tableoid = PQfnumber(res, "tableoid");
4272 i_oid = PQfnumber(res, "oid");
4273 i_rulename = PQfnumber(res, "rulename");
4274 i_ruletable = PQfnumber(res, "ruletable");
4275 i_ev_type = PQfnumber(res, "ev_type");
4276 i_is_instead = PQfnumber(res, "is_instead");
4277 i_ev_enabled = PQfnumber(res, "ev_enabled");
4279 for (i = 0; i < ntups; i++)
4283 ruleinfo[i].dobj.objType = DO_RULE;
4284 ruleinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
4285 ruleinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
4286 AssignDumpId(&ruleinfo[i].dobj);
4287 ruleinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_rulename));
4288 ruletableoid = atooid(PQgetvalue(res, i, i_ruletable));
4289 ruleinfo[i].ruletable = findTableByOid(ruletableoid);
4290 if (ruleinfo[i].ruletable == NULL)
4292 write_msg(NULL, "failed sanity check, parent table OID %u of pg_rewrite entry OID %u not found\n",
4294 ruleinfo[i].dobj.catId.oid);
4297 ruleinfo[i].dobj.namespace = ruleinfo[i].ruletable->dobj.namespace;
4298 ruleinfo[i].dobj.dump = ruleinfo[i].ruletable->dobj.dump;
4299 ruleinfo[i].ev_type = *(PQgetvalue(res, i, i_ev_type));
4300 ruleinfo[i].is_instead = *(PQgetvalue(res, i, i_is_instead)) == 't';
4301 ruleinfo[i].ev_enabled = *(PQgetvalue(res, i, i_ev_enabled));
4302 if (ruleinfo[i].ruletable)
4305 * If the table is a view, force its ON SELECT rule to be sorted
4306 * before the view itself --- this ensures that any dependencies
4307 * for the rule affect the table's positioning. Other rules are
4308 * forced to appear after their table.
4310 if (ruleinfo[i].ruletable->relkind == RELKIND_VIEW &&
4311 ruleinfo[i].ev_type == '1' && ruleinfo[i].is_instead)
4313 addObjectDependency(&ruleinfo[i].ruletable->dobj,
4314 ruleinfo[i].dobj.dumpId);
4315 /* We'll merge the rule into CREATE VIEW, if possible */
4316 ruleinfo[i].separate = false;
4320 addObjectDependency(&ruleinfo[i].dobj,
4321 ruleinfo[i].ruletable->dobj.dumpId);
4322 ruleinfo[i].separate = true;
4326 ruleinfo[i].separate = true;
4331 destroyPQExpBuffer(query);
4338 * get information about every trigger on a dumpable table
4340 * Note: trigger data is not returned directly to the caller, but it
4341 * does get entered into the DumpableObject tables.
4344 getTriggers(TableInfo tblinfo[], int numTables)
4348 PQExpBuffer query = createPQExpBuffer();
4350 TriggerInfo *tginfo;
4368 for (i = 0; i < numTables; i++)
4370 TableInfo *tbinfo = &tblinfo[i];
4372 if (!tbinfo->hastriggers || !tbinfo->dobj.dump)
4376 write_msg(NULL, "reading triggers for table \"%s\"\n",
4380 * select table schema to ensure regproc name is qualified if needed
4382 selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
4384 resetPQExpBuffer(query);
4385 if (g_fout->remoteVersion >= 80500)
4388 * NB: think not to use pretty=true in pg_get_triggerdef. It
4389 * could result in non-forward-compatible dumps of WHEN clauses
4390 * due to under-parenthesization.
4392 appendPQExpBuffer(query,
4394 "tgfoid::pg_catalog.regproc AS tgfname, "
4395 "pg_catalog.pg_get_triggerdef(oid, false) AS tgdef, "
4396 "tgenabled, tableoid, oid "
4397 "FROM pg_catalog.pg_trigger t "
4398 "WHERE tgrelid = '%u'::pg_catalog.oid "
4399 "AND tgconstraint = 0",
4400 tbinfo->dobj.catId.oid);
4402 else if (g_fout->remoteVersion >= 80300)
4405 * We ignore triggers that are tied to a foreign-key constraint
4407 appendPQExpBuffer(query,
4409 "tgfoid::pg_catalog.regproc AS tgfname, "
4410 "tgtype, tgnargs, tgargs, tgenabled, "
4411 "tgisconstraint, tgconstrname, tgdeferrable, "
4412 "tgconstrrelid, tginitdeferred, tableoid, oid, "
4413 "tgconstrrelid::pg_catalog.regclass AS tgconstrrelname "
4414 "FROM pg_catalog.pg_trigger t "
4415 "WHERE tgrelid = '%u'::pg_catalog.oid "
4416 "AND tgconstraint = 0",
4417 tbinfo->dobj.catId.oid);
4419 else if (g_fout->remoteVersion >= 70300)
4422 * We ignore triggers that are tied to a foreign-key constraint,
4423 * but in these versions we have to grovel through pg_constraint
4426 appendPQExpBuffer(query,
4428 "tgfoid::pg_catalog.regproc AS tgfname, "
4429 "tgtype, tgnargs, tgargs, tgenabled, "
4430 "tgisconstraint, tgconstrname, tgdeferrable, "
4431 "tgconstrrelid, tginitdeferred, tableoid, oid, "
4432 "tgconstrrelid::pg_catalog.regclass AS tgconstrrelname "
4433 "FROM pg_catalog.pg_trigger t "
4434 "WHERE tgrelid = '%u'::pg_catalog.oid "
4435 "AND (NOT tgisconstraint "
4437 " (SELECT 1 FROM pg_catalog.pg_depend d "
4438 " JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
4439 " WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))",
4440 tbinfo->dobj.catId.oid);
4442 else if (g_fout->remoteVersion >= 70100)
4444 appendPQExpBuffer(query,
4445 "SELECT tgname, tgfoid::regproc AS tgfname, "
4446 "tgtype, tgnargs, tgargs, tgenabled, "
4447 "tgisconstraint, tgconstrname, tgdeferrable, "
4448 "tgconstrrelid, tginitdeferred, tableoid, oid, "
4449 "(SELECT relname FROM pg_class WHERE oid = tgconstrrelid) "
4450 " AS tgconstrrelname "
4452 "WHERE tgrelid = '%u'::oid",
4453 tbinfo->dobj.catId.oid);
4457 appendPQExpBuffer(query,
4458 "SELECT tgname, tgfoid::regproc AS tgfname, "
4459 "tgtype, tgnargs, tgargs, tgenabled, "
4460 "tgisconstraint, tgconstrname, tgdeferrable, "
4461 "tgconstrrelid, tginitdeferred, "
4462 "(SELECT oid FROM pg_class WHERE relname = 'pg_trigger') AS tableoid, "
4464 "(SELECT relname FROM pg_class WHERE oid = tgconstrrelid) "
4465 " AS tgconstrrelname "
4467 "WHERE tgrelid = '%u'::oid",
4468 tbinfo->dobj.catId.oid);
4470 res = PQexec(g_conn, query->data);
4471 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4473 ntups = PQntuples(res);
4475 i_tableoid = PQfnumber(res, "tableoid");
4476 i_oid = PQfnumber(res, "oid");
4477 i_tgname = PQfnumber(res, "tgname");
4478 i_tgfname = PQfnumber(res, "tgfname");
4479 i_tgtype = PQfnumber(res, "tgtype");
4480 i_tgnargs = PQfnumber(res, "tgnargs");
4481 i_tgargs = PQfnumber(res, "tgargs");
4482 i_tgisconstraint = PQfnumber(res, "tgisconstraint");
4483 i_tgconstrname = PQfnumber(res, "tgconstrname");
4484 i_tgconstrrelid = PQfnumber(res, "tgconstrrelid");
4485 i_tgconstrrelname = PQfnumber(res, "tgconstrrelname");
4486 i_tgenabled = PQfnumber(res, "tgenabled");
4487 i_tgdeferrable = PQfnumber(res, "tgdeferrable");
4488 i_tginitdeferred = PQfnumber(res, "tginitdeferred");
4489 i_tgdef = PQfnumber(res, "tgdef");
4491 tginfo = (TriggerInfo *) malloc(ntups * sizeof(TriggerInfo));
4493 for (j = 0; j < ntups; j++)
4495 tginfo[j].dobj.objType = DO_TRIGGER;
4496 tginfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
4497 tginfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
4498 AssignDumpId(&tginfo[j].dobj);
4499 tginfo[j].dobj.name = strdup(PQgetvalue(res, j, i_tgname));
4500 tginfo[j].dobj.namespace = tbinfo->dobj.namespace;
4501 tginfo[j].tgtable = tbinfo;
4502 tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled));
4505 tginfo[j].tgdef = strdup(PQgetvalue(res, j, i_tgdef));
4507 /* remaining fields are not valid if we have tgdef */
4508 tginfo[j].tgfname = NULL;
4509 tginfo[j].tgtype = 0;
4510 tginfo[j].tgnargs = 0;
4511 tginfo[j].tgargs = NULL;
4512 tginfo[j].tgisconstraint = false;
4513 tginfo[j].tgdeferrable = false;
4514 tginfo[j].tginitdeferred = false;
4515 tginfo[j].tgconstrname = NULL;
4516 tginfo[j].tgconstrrelid = InvalidOid;
4517 tginfo[j].tgconstrrelname = NULL;
4521 tginfo[j].tgdef = NULL;
4523 tginfo[j].tgfname = strdup(PQgetvalue(res, j, i_tgfname));
4524 tginfo[j].tgtype = atoi(PQgetvalue(res, j, i_tgtype));
4525 tginfo[j].tgnargs = atoi(PQgetvalue(res, j, i_tgnargs));
4526 tginfo[j].tgargs = strdup(PQgetvalue(res, j, i_tgargs));
4527 tginfo[j].tgisconstraint = *(PQgetvalue(res, j, i_tgisconstraint)) == 't';
4528 tginfo[j].tgdeferrable = *(PQgetvalue(res, j, i_tgdeferrable)) == 't';
4529 tginfo[j].tginitdeferred = *(PQgetvalue(res, j, i_tginitdeferred)) == 't';
4531 if (tginfo[j].tgisconstraint)
4533 tginfo[j].tgconstrname = strdup(PQgetvalue(res, j, i_tgconstrname));
4534 tginfo[j].tgconstrrelid = atooid(PQgetvalue(res, j, i_tgconstrrelid));
4535 if (OidIsValid(tginfo[j].tgconstrrelid))
4537 if (PQgetisnull(res, j, i_tgconstrrelname))
4539 write_msg(NULL, "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)\n",
4540 tginfo[j].dobj.name, tbinfo->dobj.name,
4541 tginfo[j].tgconstrrelid);
4544 tginfo[j].tgconstrrelname = strdup(PQgetvalue(res, j, i_tgconstrrelname));
4547 tginfo[j].tgconstrrelname = NULL;
4551 tginfo[j].tgconstrname = NULL;
4552 tginfo[j].tgconstrrelid = InvalidOid;
4553 tginfo[j].tgconstrrelname = NULL;
4561 destroyPQExpBuffer(query);
4566 * get basic information about every procedural language in the system
4568 * numProcLangs is set to the number of langs read in
4570 * NB: this must run after getFuncs() because we assume we can do
4574 getProcLangs(int *numProcLangs)
4579 PQExpBuffer query = createPQExpBuffer();
4580 ProcLangInfo *planginfo;
4585 int i_lanplcallfoid;
4591 /* Make sure we are in proper schema */
4592 selectSourceSchema("pg_catalog");
4594 if (g_fout->remoteVersion >= 80500)
4596 /* pg_language has a laninline column */
4597 appendPQExpBuffer(query, "SELECT tableoid, oid, "
4598 "lanname, lanpltrusted, lanplcallfoid, "
4599 "laninline, lanvalidator, lanacl, "
4600 "(%s lanowner) AS lanowner "
4603 /* do not dump initdb-installed languages */
4606 username_subquery, FirstNormalObjectId);
4608 else if (g_fout->remoteVersion >= 80300)
4610 /* pg_language has a lanowner column */
4611 appendPQExpBuffer(query, "SELECT tableoid, oid, "
4612 "lanname, lanpltrusted, lanplcallfoid, "
4613 "lanvalidator, lanacl, "
4614 "(%s lanowner) AS lanowner "
4619 binary_upgrade ? "\nAND lanname != 'plpgsql'" : "");
4621 else if (g_fout->remoteVersion >= 80100)
4623 /* Languages are owned by the bootstrap superuser, OID 10 */
4624 appendPQExpBuffer(query, "SELECT tableoid, oid, *, "
4625 "(%s '10') AS lanowner "
4631 else if (g_fout->remoteVersion >= 70400)
4633 /* Languages are owned by the bootstrap superuser, sysid 1 */
4634 appendPQExpBuffer(query, "SELECT tableoid, oid, *, "
4635 "(%s '1') AS lanowner "
4641 else if (g_fout->remoteVersion >= 70100)
4643 /* No clear notion of an owner at all before 7.4 ... */
4644 appendPQExpBuffer(query, "SELECT tableoid, oid, * FROM pg_language "
4650 appendPQExpBuffer(query, "SELECT "
4651 "(SELECT oid FROM pg_class WHERE relname = 'pg_language') AS tableoid, "
4652 "oid, * FROM pg_language "
4657 res = PQexec(g_conn, query->data);
4658 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4660 ntups = PQntuples(res);
4662 *numProcLangs = ntups;
4664 planginfo = (ProcLangInfo *) malloc(ntups * sizeof(ProcLangInfo));
4666 i_tableoid = PQfnumber(res, "tableoid");
4667 i_oid = PQfnumber(res, "oid");
4668 i_lanname = PQfnumber(res, "lanname");
4669 i_lanpltrusted = PQfnumber(res, "lanpltrusted");
4670 i_lanplcallfoid = PQfnumber(res, "lanplcallfoid");
4671 /* these may fail and return -1: */
4672 i_laninline = PQfnumber(res, "laninline");
4673 i_lanvalidator = PQfnumber(res, "lanvalidator");
4674 i_lanacl = PQfnumber(res, "lanacl");
4675 i_lanowner = PQfnumber(res, "lanowner");
4677 for (i = 0; i < ntups; i++)
4679 planginfo[i].dobj.objType = DO_PROCLANG;
4680 planginfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
4681 planginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
4682 AssignDumpId(&planginfo[i].dobj);
4684 planginfo[i].dobj.name = strdup(PQgetvalue(res, i, i_lanname));
4685 planginfo[i].lanpltrusted = *(PQgetvalue(res, i, i_lanpltrusted)) == 't';
4686 planginfo[i].lanplcallfoid = atooid(PQgetvalue(res, i, i_lanplcallfoid));
4687 if (i_laninline >= 0)
4688 planginfo[i].laninline = atooid(PQgetvalue(res, i, i_laninline));
4690 planginfo[i].laninline = InvalidOid;
4691 if (i_lanvalidator >= 0)
4692 planginfo[i].lanvalidator = atooid(PQgetvalue(res, i, i_lanvalidator));
4694 planginfo[i].lanvalidator = InvalidOid;
4696 planginfo[i].lanacl = strdup(PQgetvalue(res, i, i_lanacl));
4698 planginfo[i].lanacl = strdup("{=U}");
4699 if (i_lanowner >= 0)
4700 planginfo[i].lanowner = strdup(PQgetvalue(res, i, i_lanowner));
4702 planginfo[i].lanowner = strdup("");
4704 if (g_fout->remoteVersion < 70300)
4707 * We need to make a dependency to ensure the function will be
4708 * dumped first. (In 7.3 and later the regular dependency
4709 * mechanism will handle this for us.)
4711 FuncInfo *funcInfo = findFuncByOid(planginfo[i].lanplcallfoid);
4714 addObjectDependency(&planginfo[i].dobj,
4715 funcInfo->dobj.dumpId);
4721 destroyPQExpBuffer(query);
4728 * get basic information about every cast in the system
4730 * numCasts is set to the number of casts read in
4733 getCasts(int *numCasts)
4738 PQExpBuffer query = createPQExpBuffer();
4748 /* Make sure we are in proper schema */
4749 selectSourceSchema("pg_catalog");
4751 if (g_fout->remoteVersion >= 80400)
4753 appendPQExpBuffer(query, "SELECT tableoid, oid, "
4754 "castsource, casttarget, castfunc, castcontext, "
4756 "FROM pg_cast ORDER BY 3,4");
4758 else if (g_fout->remoteVersion >= 70300)
4760 appendPQExpBuffer(query, "SELECT tableoid, oid, "
4761 "castsource, casttarget, castfunc, castcontext, "
4762 "CASE WHEN castfunc = 0 THEN 'b' ELSE 'f' END AS castmethod "
4763 "FROM pg_cast ORDER BY 3,4");
4767 appendPQExpBuffer(query, "SELECT 0 AS tableoid, p.oid, "
4768 "t1.oid AS castsource, t2.oid AS casttarget, "
4769 "p.oid AS castfunc, 'e' AS castcontext, "
4770 "'f' AS castmethod "
4771 "FROM pg_type t1, pg_type t2, pg_proc p "
4772 "WHERE p.pronargs = 1 AND "
4773 "p.proargtypes[0] = t1.oid AND "
4774 "p.prorettype = t2.oid AND p.proname = t2.typname "
4778 res = PQexec(g_conn, query->data);
4779 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
4781 ntups = PQntuples(res);
4785 castinfo = (CastInfo *) malloc(ntups * sizeof(CastInfo));
4787 i_tableoid = PQfnumber(res, "tableoid");
4788 i_oid = PQfnumber(res, "oid");
4789 i_castsource = PQfnumber(res, "castsource");
4790 i_casttarget = PQfnumber(res, "casttarget");
4791 i_castfunc = PQfnumber(res, "castfunc");
4792 i_castcontext = PQfnumber(res, "castcontext");
4793 i_castmethod = PQfnumber(res, "castmethod");
4795 for (i = 0; i < ntups; i++)
4797 PQExpBufferData namebuf;
4798 TypeInfo *sTypeInfo;
4799 TypeInfo *tTypeInfo;
4801 castinfo[i].dobj.objType = DO_CAST;
4802 castinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
4803 castinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
4804 AssignDumpId(&castinfo[i].dobj);
4805 castinfo[i].castsource = atooid(PQgetvalue(res, i, i_castsource));
4806 castinfo[i].casttarget = atooid(PQgetvalue(res, i, i_casttarget));
4807 castinfo[i].castfunc = atooid(PQgetvalue(res, i, i_castfunc));
4808 castinfo[i].castcontext = *(PQgetvalue(res, i, i_castcontext));
4809 castinfo[i].castmethod = *(PQgetvalue(res, i, i_castmethod));
4812 * Try to name cast as concatenation of typnames. This is only used
4813 * for purposes of sorting. If we fail to find either type, the name
4814 * will be an empty string.
4816 initPQExpBuffer(&namebuf);
4817 sTypeInfo = findTypeByOid(castinfo[i].castsource);
4818 tTypeInfo = findTypeByOid(castinfo[i].casttarget);
4819 if (sTypeInfo && tTypeInfo)
4820 appendPQExpBuffer(&namebuf, "%s %s",
4821 sTypeInfo->dobj.name, tTypeInfo->dobj.name);
4822 castinfo[i].dobj.name = namebuf.data;
4824 if (OidIsValid(castinfo[i].castfunc))
4827 * We need to make a dependency to ensure the function will be
4828 * dumped first. (In 7.3 and later the regular dependency
4829 * mechanism will handle this for us.)
4833 funcInfo = findFuncByOid(castinfo[i].castfunc);
4835 addObjectDependency(&castinfo[i].dobj,
4836 funcInfo->dobj.dumpId);
4842 destroyPQExpBuffer(query);
4849 * for each interesting table, read info about its attributes
4850 * (names, types, default values, CHECK constraints, etc)
4852 * This is implemented in a very inefficient way right now, looping
4853 * through the tblinfo and doing a join per table to find the attrs and their
4854 * types. However, because we want type names and so forth to be named
4855 * relative to the schema of each table, we couldn't do it in just one
4856 * query. (Maybe one query per schema?)
4861 getTableAttrs(TableInfo *tblinfo, int numTables)
4865 PQExpBuffer q = createPQExpBuffer();
4870 int i_attstattarget;
4884 for (i = 0; i < numTables; i++)
4886 TableInfo *tbinfo = &tblinfo[i];
4888 /* Don't bother to collect info for sequences */
4889 if (tbinfo->relkind == RELKIND_SEQUENCE)
4892 /* Don't bother with uninteresting tables, either */
4893 if (!tbinfo->interesting)
4897 * Make sure we are in proper schema for this table; this allows
4898 * correct retrieval of formatted type names and default exprs
4900 selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
4902 /* find all the user attributes and their types */
4905 * we must read the attribute names in attribute number order! because
4906 * we will use the attnum to index into the attnames array later. We
4907 * actually ask to order by "attrelid, attnum" because (at least up to
4908 * 7.3) the planner is not smart enough to realize it needn't re-sort
4909 * the output of an indexscan on pg_attribute_relid_attnum_index.
4912 write_msg(NULL, "finding the columns and types of table \"%s\"\n",
4915 resetPQExpBuffer(q);
4917 if (g_fout->remoteVersion >= 80500)
4919 /* attdistinct is new in 8.5 */
4920 appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
4921 "a.attstattarget, a.attdistinct, "
4922 "a.attstorage, t.typstorage, "
4923 "a.attnotnull, a.atthasdef, a.attisdropped, "
4924 "a.attlen, a.attalign, a.attislocal, "
4925 "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname "
4926 "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
4927 "ON a.atttypid = t.oid "
4928 "WHERE a.attrelid = '%u'::pg_catalog.oid "
4929 "AND a.attnum > 0::pg_catalog.int2 "
4930 "ORDER BY a.attrelid, a.attnum",
4931 tbinfo->dobj.catId.oid);
4933 else if (g_fout->remoteVersion >= 70300)
4935 /* need left join here to not fail on dropped columns ... */
4936 appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
4937 "a.attstattarget, 0 AS attdistinct, "
4938 "a.attstorage, t.typstorage, "
4939 "a.attnotnull, a.atthasdef, a.attisdropped, "
4940 "a.attlen, a.attalign, a.attislocal, "
4941 "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname "
4942 "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
4943 "ON a.atttypid = t.oid "
4944 "WHERE a.attrelid = '%u'::pg_catalog.oid "
4945 "AND a.attnum > 0::pg_catalog.int2 "
4946 "ORDER BY a.attrelid, a.attnum",
4947 tbinfo->dobj.catId.oid);
4949 else if (g_fout->remoteVersion >= 70100)
4952 * attstattarget doesn't exist in 7.1. It does exist in 7.2, but
4953 * we don't dump it because we can't tell whether it's been
4954 * explicitly set or was just a default.
4956 appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
4957 "-1 AS attstattarget, 0 AS attdistinct, "
4959 "t.typstorage, a.attnotnull, a.atthasdef, "
4960 "false AS attisdropped, a.attlen, "
4961 "a.attalign, false AS attislocal, "
4962 "format_type(t.oid,a.atttypmod) AS atttypname "
4963 "FROM pg_attribute a LEFT JOIN pg_type t "
4964 "ON a.atttypid = t.oid "
4965 "WHERE a.attrelid = '%u'::oid "
4966 "AND a.attnum > 0::int2 "
4967 "ORDER BY a.attrelid, a.attnum",
4968 tbinfo->dobj.catId.oid);
4972 /* format_type not available before 7.1 */
4973 appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, "
4974 "-1 AS attstattarget, 0 AS attdistinct, "
4975 "attstorage, attstorage AS typstorage, "
4976 "attnotnull, atthasdef, false AS attisdropped, "
4977 "attlen, attalign, "
4978 "false AS attislocal, "
4979 "(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname "
4980 "FROM pg_attribute a "
4981 "WHERE attrelid = '%u'::oid "
4982 "AND attnum > 0::int2 "
4983 "ORDER BY attrelid, attnum",
4984 tbinfo->dobj.catId.oid);
4987 res = PQexec(g_conn, q->data);
4988 check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
4990 ntups = PQntuples(res);
4992 i_attnum = PQfnumber(res, "attnum");
4993 i_attname = PQfnumber(res, "attname");
4994 i_atttypname = PQfnumber(res, "atttypname");
4995 i_atttypmod = PQfnumber(res, "atttypmod");
4996 i_attstattarget = PQfnumber(res, "attstattarget");
4997 i_attdistinct = PQfnumber(res, "attdistinct");
4998 i_attstorage = PQfnumber(res, "attstorage");
4999 i_typstorage = PQfnumber(res, "typstorage");
5000 i_attnotnull = PQfnumber(res, "attnotnull");
5001 i_atthasdef = PQfnumber(res, "atthasdef");
5002 i_attisdropped = PQfnumber(res, "attisdropped");
5003 i_attlen = PQfnumber(res, "attlen");
5004 i_attalign = PQfnumber(res, "attalign");
5005 i_attislocal = PQfnumber(res, "attislocal");
5007 tbinfo->numatts = ntups;
5008 tbinfo->attnames = (char **) malloc(ntups * sizeof(char *));
5009 tbinfo->atttypnames = (char **) malloc(ntups * sizeof(char *));
5010 tbinfo->atttypmod = (int *) malloc(ntups * sizeof(int));
5011 tbinfo->attstattarget = (int *) malloc(ntups * sizeof(int));
5012 tbinfo->attdistinct = (float4 *) malloc(ntups * sizeof(float4));
5013 tbinfo->attstorage = (char *) malloc(ntups * sizeof(char));
5014 tbinfo->typstorage = (char *) malloc(ntups * sizeof(char));
5015 tbinfo->attisdropped = (bool *) malloc(ntups * sizeof(bool));
5016 tbinfo->attlen = (int *) malloc(ntups * sizeof(int));
5017 tbinfo->attalign = (char *) malloc(ntups * sizeof(char));
5018 tbinfo->attislocal = (bool *) malloc(ntups * sizeof(bool));
5019 tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool));
5020 tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
5021 tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
5022 tbinfo->inhAttrDef = (bool *) malloc(ntups * sizeof(bool));
5023 tbinfo->inhNotNull = (bool *) malloc(ntups * sizeof(bool));
5024 hasdefaults = false;
5026 for (j = 0; j < ntups; j++)
5028 if (j + 1 != atoi(PQgetvalue(res, j, i_attnum)))
5030 write_msg(NULL, "invalid column numbering in table \"%s\"\n",
5034 tbinfo->attnames[j] = strdup(PQgetvalue(res, j, i_attname));
5035 tbinfo->atttypnames[j] = strdup(PQgetvalue(res, j, i_atttypname));
5036 tbinfo->atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod));
5037 tbinfo->attstattarget[j] = atoi(PQgetvalue(res, j, i_attstattarget));
5038 tbinfo->attdistinct[j] = strtod(PQgetvalue(res, j, i_attdistinct),
5040 tbinfo->attstorage[j] = *(PQgetvalue(res, j, i_attstorage));
5041 tbinfo->typstorage[j] = *(PQgetvalue(res, j, i_typstorage));
5042 tbinfo->attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't');
5043 tbinfo->attlen[j] = atoi(PQgetvalue(res, j, i_attlen));
5044 tbinfo->attalign[j] = *(PQgetvalue(res, j, i_attalign));
5045 tbinfo->attislocal[j] = (PQgetvalue(res, j, i_attislocal)[0] == 't');
5046 tbinfo->notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
5047 tbinfo->attrdefs[j] = NULL; /* fix below */
5048 if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
5050 /* these flags will be set in flagInhAttrs() */
5051 tbinfo->inhAttrs[j] = false;
5052 tbinfo->inhAttrDef[j] = false;
5053 tbinfo->inhNotNull[j] = false;
5059 * Get info about column defaults
5063 AttrDefInfo *attrdefs;
5067 write_msg(NULL, "finding default expressions of table \"%s\"\n",
5070 resetPQExpBuffer(q);
5071 if (g_fout->remoteVersion >= 70300)
5073 appendPQExpBuffer(q, "SELECT tableoid, oid, adnum, "
5074 "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
5075 "FROM pg_catalog.pg_attrdef "
5076 "WHERE adrelid = '%u'::pg_catalog.oid",
5077 tbinfo->dobj.catId.oid);
5079 else if (g_fout->remoteVersion >= 70200)
5081 /* 7.2 did not have OIDs in pg_attrdef */
5082 appendPQExpBuffer(q, "SELECT tableoid, 0 AS oid, adnum, "
5083 "pg_get_expr(adbin, adrelid) AS adsrc "
5085 "WHERE adrelid = '%u'::oid",
5086 tbinfo->dobj.catId.oid);
5088 else if (g_fout->remoteVersion >= 70100)
5090 /* no pg_get_expr, so must rely on adsrc */
5091 appendPQExpBuffer(q, "SELECT tableoid, oid, adnum, adsrc "
5093 "WHERE adrelid = '%u'::oid",
5094 tbinfo->dobj.catId.oid);
5098 /* no pg_get_expr, no tableoid either */
5099 appendPQExpBuffer(q, "SELECT "
5100 "(SELECT oid FROM pg_class WHERE relname = 'pg_attrdef') AS tableoid, "
5101 "oid, adnum, adsrc "
5103 "WHERE adrelid = '%u'::oid",
5104 tbinfo->dobj.catId.oid);
5106 res = PQexec(g_conn, q->data);
5107 check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
5109 numDefaults = PQntuples(res);
5110 attrdefs = (AttrDefInfo *) malloc(numDefaults * sizeof(AttrDefInfo));
5112 for (j = 0; j < numDefaults; j++)
5116 attrdefs[j].dobj.objType = DO_ATTRDEF;
5117 attrdefs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
5118 attrdefs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
5119 AssignDumpId(&attrdefs[j].dobj);
5120 attrdefs[j].adtable = tbinfo;
5121 attrdefs[j].adnum = adnum = atoi(PQgetvalue(res, j, 2));
5122 attrdefs[j].adef_expr = strdup(PQgetvalue(res, j, 3));
5124 attrdefs[j].dobj.name = strdup(tbinfo->dobj.name);
5125 attrdefs[j].dobj.namespace = tbinfo->dobj.namespace;
5127 attrdefs[j].dobj.dump = tbinfo->dobj.dump;
5130 * Defaults on a VIEW must always be dumped as separate ALTER
5131 * TABLE commands. Defaults on regular tables are dumped as
5132 * part of the CREATE TABLE if possible. To check if it's
5133 * safe, we mark the default as needing to appear before the
5136 if (tbinfo->relkind == RELKIND_VIEW)
5138 attrdefs[j].separate = true;
5139 /* needed in case pre-7.3 DB: */
5140 addObjectDependency(&attrdefs[j].dobj,
5141 tbinfo->dobj.dumpId);
5145 attrdefs[j].separate = false;
5146 addObjectDependency(&tbinfo->dobj,
5147 attrdefs[j].dobj.dumpId);
5150 if (adnum <= 0 || adnum > ntups)
5152 write_msg(NULL, "invalid adnum value %d for table \"%s\"\n",
5153 adnum, tbinfo->dobj.name);
5156 tbinfo->attrdefs[adnum - 1] = &attrdefs[j];
5162 * Get info about table CHECK constraints
5164 if (tbinfo->ncheck > 0)
5166 ConstraintInfo *constrs;
5170 write_msg(NULL, "finding check constraints for table \"%s\"\n",
5173 resetPQExpBuffer(q);
5174 if (g_fout->remoteVersion >= 80400)
5176 appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
5177 "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
5179 "FROM pg_catalog.pg_constraint "
5180 "WHERE conrelid = '%u'::pg_catalog.oid "
5181 " AND contype = 'c' "
5183 tbinfo->dobj.catId.oid);
5185 else if (g_fout->remoteVersion >= 70400)
5187 appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
5188 "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
5189 "true AS conislocal "
5190 "FROM pg_catalog.pg_constraint "
5191 "WHERE conrelid = '%u'::pg_catalog.oid "
5192 " AND contype = 'c' "
5194 tbinfo->dobj.catId.oid);
5196 else if (g_fout->remoteVersion >= 70300)
5198 /* no pg_get_constraintdef, must use consrc */
5199 appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
5200 "'CHECK (' || consrc || ')' AS consrc, "
5201 "true AS conislocal "
5202 "FROM pg_catalog.pg_constraint "
5203 "WHERE conrelid = '%u'::pg_catalog.oid "
5204 " AND contype = 'c' "
5206 tbinfo->dobj.catId.oid);
5208 else if (g_fout->remoteVersion >= 70200)
5210 /* 7.2 did not have OIDs in pg_relcheck */
5211 appendPQExpBuffer(q, "SELECT tableoid, 0 AS oid, "
5212 "rcname AS conname, "
5213 "'CHECK (' || rcsrc || ')' AS consrc, "
5214 "true AS conislocal "
5216 "WHERE rcrelid = '%u'::oid "
5218 tbinfo->dobj.catId.oid);
5220 else if (g_fout->remoteVersion >= 70100)
5222 appendPQExpBuffer(q, "SELECT tableoid, oid, "
5223 "rcname AS conname, "
5224 "'CHECK (' || rcsrc || ')' AS consrc, "
5225 "true AS conislocal "
5227 "WHERE rcrelid = '%u'::oid "
5229 tbinfo->dobj.catId.oid);
5233 /* no tableoid in 7.0 */
5234 appendPQExpBuffer(q, "SELECT "
5235 "(SELECT oid FROM pg_class WHERE relname = 'pg_relcheck') AS tableoid, "
5236 "oid, rcname AS conname, "
5237 "'CHECK (' || rcsrc || ')' AS consrc, "
5238 "true AS conislocal "
5240 "WHERE rcrelid = '%u'::oid "
5242 tbinfo->dobj.catId.oid);
5244 res = PQexec(g_conn, q->data);
5245 check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
5247 numConstrs = PQntuples(res);
5248 if (numConstrs != tbinfo->ncheck)
5250 write_msg(NULL, ngettext("expected %d check constraint on table \"%s\" but found %d\n",
5251 "expected %d check constraints on table \"%s\" but found %d\n",
5253 tbinfo->ncheck, tbinfo->dobj.name, numConstrs);
5254 write_msg(NULL, "(The system catalogs might be corrupted.)\n");
5258 constrs = (ConstraintInfo *) malloc(numConstrs * sizeof(ConstraintInfo));
5259 tbinfo->checkexprs = constrs;
5261 for (j = 0; j < numConstrs; j++)
5263 constrs[j].dobj.objType = DO_CONSTRAINT;
5264 constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
5265 constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
5266 AssignDumpId(&constrs[j].dobj);
5267 constrs[j].dobj.name = strdup(PQgetvalue(res, j, 2));
5268 constrs[j].dobj.namespace = tbinfo->dobj.namespace;
5269 constrs[j].contable = tbinfo;
5270 constrs[j].condomain = NULL;
5271 constrs[j].contype = 'c';
5272 constrs[j].condef = strdup(PQgetvalue(res, j, 3));
5273 constrs[j].confrelid = InvalidOid;
5274 constrs[j].conindex = 0;
5275 constrs[j].condeferrable = false;
5276 constrs[j].condeferred = false;
5277 constrs[j].conislocal = (PQgetvalue(res, j, 4)[0] == 't');
5278 constrs[j].separate = false;
5280 constrs[j].dobj.dump = tbinfo->dobj.dump;
5283 * Mark the constraint as needing to appear before the table
5284 * --- this is so that any other dependencies of the
5285 * constraint will be emitted before we try to create the
5288 addObjectDependency(&tbinfo->dobj,
5289 constrs[j].dobj.dumpId);
5292 * If the constraint is inherited, this will be detected later
5293 * (in pre-8.4 databases). We also detect later if the
5294 * constraint must be split out from the table definition.
5301 destroyPQExpBuffer(q);
5307 * read all text search parsers in the system catalogs and return them
5308 * in the TSParserInfo* structure
5310 * numTSParsers is set to the number of parsers read in
5313 getTSParsers(int *numTSParsers)
5318 PQExpBuffer query = createPQExpBuffer();
5319 TSParserInfo *prsinfo;
5330 /* Before 8.3, there is no built-in text search support */
5331 if (g_fout->remoteVersion < 80300)
5338 * find all text search objects, including builtin ones; we filter out
5339 * system-defined objects at dump-out time.
5342 /* Make sure we are in proper schema */
5343 selectSourceSchema("pg_catalog");
5345 appendPQExpBuffer(query, "SELECT tableoid, oid, prsname, prsnamespace, "
5346 "prsstart::oid, prstoken::oid, "
5347 "prsend::oid, prsheadline::oid, prslextype::oid "
5348 "FROM pg_ts_parser");
5350 res = PQexec(g_conn, query->data);
5351 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
5353 ntups = PQntuples(res);
5354 *numTSParsers = ntups;
5356 prsinfo = (TSParserInfo *) malloc(ntups * sizeof(TSParserInfo));
5358 i_tableoid = PQfnumber(res, "tableoid");
5359 i_oid = PQfnumber(res, "oid");
5360 i_prsname = PQfnumber(res, "prsname");
5361 i_prsnamespace = PQfnumber(res, "prsnamespace");
5362 i_prsstart = PQfnumber(res, "prsstart");
5363 i_prstoken = PQfnumber(res, "prstoken");
5364 i_prsend = PQfnumber(res, "prsend");
5365 i_prsheadline = PQfnumber(res, "prsheadline");
5366 i_prslextype = PQfnumber(res, "prslextype");
5368 for (i = 0; i < ntups; i++)
5370 prsinfo[i].dobj.objType = DO_TSPARSER;
5371 prsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
5372 prsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
5373 AssignDumpId(&prsinfo[i].dobj);
5374 prsinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_prsname));
5375 prsinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_prsnamespace)),
5376 prsinfo[i].dobj.catId.oid);
5377 prsinfo[i].prsstart = atooid(PQgetvalue(res, i, i_prsstart));
5378 prsinfo[i].prstoken = atooid(PQgetvalue(res, i, i_prstoken));
5379 prsinfo[i].prsend = atooid(PQgetvalue(res, i, i_prsend));
5380 prsinfo[i].prsheadline = atooid(PQgetvalue(res, i, i_prsheadline));
5381 prsinfo[i].prslextype = atooid(PQgetvalue(res, i, i_prslextype));
5383 /* Decide whether we want to dump it */
5384 selectDumpableObject(&(prsinfo[i].dobj));
5389 destroyPQExpBuffer(query);
5395 * getTSDictionaries:
5396 * read all text search dictionaries in the system catalogs and return them
5397 * in the TSDictInfo* structure
5399 * numTSDicts is set to the number of dictionaries read in
5402 getTSDictionaries(int *numTSDicts)
5407 PQExpBuffer query = createPQExpBuffer();
5408 TSDictInfo *dictinfo;
5412 int i_dictnamespace;
5415 int i_dictinitoption;
5417 /* Before 8.3, there is no built-in text search support */
5418 if (g_fout->remoteVersion < 80300)
5424 /* Make sure we are in proper schema */
5425 selectSourceSchema("pg_catalog");
5427 appendPQExpBuffer(query, "SELECT tableoid, oid, dictname, "
5428 "dictnamespace, (%s dictowner) AS rolname, "
5429 "dicttemplate, dictinitoption "
5433 res = PQexec(g_conn, query->data);
5434 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
5436 ntups = PQntuples(res);
5437 *numTSDicts = ntups;
5439 dictinfo = (TSDictInfo *) malloc(ntups * sizeof(TSDictInfo));
5441 i_tableoid = PQfnumber(res, "tableoid");
5442 i_oid = PQfnumber(res, "oid");
5443 i_dictname = PQfnumber(res, "dictname");
5444 i_dictnamespace = PQfnumber(res, "dictnamespace");
5445 i_rolname = PQfnumber(res, "rolname");
5446 i_dictinitoption = PQfnumber(res, "dictinitoption");
5447 i_dicttemplate = PQfnumber(res, "dicttemplate");
5449 for (i = 0; i < ntups; i++)
5451 dictinfo[i].dobj.objType = DO_TSDICT;
5452 dictinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
5453 dictinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
5454 AssignDumpId(&dictinfo[i].dobj);
5455 dictinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_dictname));
5456 dictinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_dictnamespace)),
5457 dictinfo[i].dobj.catId.oid);
5458 dictinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
5459 dictinfo[i].dicttemplate = atooid(PQgetvalue(res, i, i_dicttemplate));
5460 if (PQgetisnull(res, i, i_dictinitoption))
5461 dictinfo[i].dictinitoption = NULL;
5463 dictinfo[i].dictinitoption = strdup(PQgetvalue(res, i, i_dictinitoption));
5465 /* Decide whether we want to dump it */
5466 selectDumpableObject(&(dictinfo[i].dobj));
5471 destroyPQExpBuffer(query);
5478 * read all text search templates in the system catalogs and return them
5479 * in the TSTemplateInfo* structure
5481 * numTSTemplates is set to the number of templates read in
5484 getTSTemplates(int *numTSTemplates)
5489 PQExpBuffer query = createPQExpBuffer();
5490 TSTemplateInfo *tmplinfo;
5494 int i_tmplnamespace;
5498 /* Before 8.3, there is no built-in text search support */
5499 if (g_fout->remoteVersion < 80300)
5501 *numTSTemplates = 0;
5505 /* Make sure we are in proper schema */
5506 selectSourceSchema("pg_catalog");
5508 appendPQExpBuffer(query, "SELECT tableoid, oid, tmplname, "
5509 "tmplnamespace, tmplinit::oid, tmpllexize::oid "
5510 "FROM pg_ts_template");
5512 res = PQexec(g_conn, query->data);
5513 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
5515 ntups = PQntuples(res);
5516 *numTSTemplates = ntups;
5518 tmplinfo = (TSTemplateInfo *) malloc(ntups * sizeof(TSTemplateInfo));
5520 i_tableoid = PQfnumber(res, "tableoid");
5521 i_oid = PQfnumber(res, "oid");
5522 i_tmplname = PQfnumber(res, "tmplname");
5523 i_tmplnamespace = PQfnumber(res, "tmplnamespace");
5524 i_tmplinit = PQfnumber(res, "tmplinit");
5525 i_tmpllexize = PQfnumber(res, "tmpllexize");
5527 for (i = 0; i < ntups; i++)
5529 tmplinfo[i].dobj.objType = DO_TSTEMPLATE;
5530 tmplinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
5531 tmplinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
5532 AssignDumpId(&tmplinfo[i].dobj);
5533 tmplinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_tmplname));
5534 tmplinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_tmplnamespace)),
5535 tmplinfo[i].dobj.catId.oid);
5536 tmplinfo[i].tmplinit = atooid(PQgetvalue(res, i, i_tmplinit));
5537 tmplinfo[i].tmpllexize = atooid(PQgetvalue(res, i, i_tmpllexize));
5539 /* Decide whether we want to dump it */
5540 selectDumpableObject(&(tmplinfo[i].dobj));
5545 destroyPQExpBuffer(query);
5551 * getTSConfigurations:
5552 * read all text search configurations in the system catalogs and return
5553 * them in the TSConfigInfo* structure
5555 * numTSConfigs is set to the number of configurations read in
5558 getTSConfigurations(int *numTSConfigs)
5563 PQExpBuffer query = createPQExpBuffer();
5564 TSConfigInfo *cfginfo;
5572 /* Before 8.3, there is no built-in text search support */
5573 if (g_fout->remoteVersion < 80300)
5579 /* Make sure we are in proper schema */
5580 selectSourceSchema("pg_catalog");
5582 appendPQExpBuffer(query, "SELECT tableoid, oid, cfgname, "
5583 "cfgnamespace, (%s cfgowner) AS rolname, cfgparser "
5584 "FROM pg_ts_config",
5587 res = PQexec(g_conn, query->data);
5588 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
5590 ntups = PQntuples(res);
5591 *numTSConfigs = ntups;
5593 cfginfo = (TSConfigInfo *) malloc(ntups * sizeof(TSConfigInfo));
5595 i_tableoid = PQfnumber(res, "tableoid");
5596 i_oid = PQfnumber(res, "oid");
5597 i_cfgname = PQfnumber(res, "cfgname");
5598 i_cfgnamespace = PQfnumber(res, "cfgnamespace");
5599 i_rolname = PQfnumber(res, "rolname");
5600 i_cfgparser = PQfnumber(res, "cfgparser");
5602 for (i = 0; i < ntups; i++)
5604 cfginfo[i].dobj.objType = DO_TSCONFIG;
5605 cfginfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
5606 cfginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
5607 AssignDumpId(&cfginfo[i].dobj);
5608 cfginfo[i].dobj.name = strdup(PQgetvalue(res, i, i_cfgname));
5609 cfginfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_cfgnamespace)),
5610 cfginfo[i].dobj.catId.oid);
5611 cfginfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
5612 cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));
5614 /* Decide whether we want to dump it */
5615 selectDumpableObject(&(cfginfo[i].dobj));
5620 destroyPQExpBuffer(query);
5626 * getForeignDataWrappers:
5627 * read all foreign-data wrappers in the system catalogs and return
5628 * them in the FdwInfo* structure
5630 * numForeignDataWrappers is set to the number of fdws read in
5633 getForeignDataWrappers(int *numForeignDataWrappers)
5638 PQExpBuffer query = createPQExpBuffer();
5647 /* Before 8.4, there are no foreign-data wrappers */
5648 if (g_fout->remoteVersion < 80400)
5650 *numForeignDataWrappers = 0;
5654 /* Make sure we are in proper schema */
5655 selectSourceSchema("pg_catalog");
5657 appendPQExpBuffer(query, "SELECT oid, fdwname, "
5658 "(%s fdwowner) AS rolname, fdwvalidator::pg_catalog.regproc, fdwacl,"
5659 "array_to_string(ARRAY("
5660 " SELECT option_name || ' ' || quote_literal(option_value) "
5661 " FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
5662 "FROM pg_foreign_data_wrapper",
5665 res = PQexec(g_conn, query->data);
5666 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
5668 ntups = PQntuples(res);
5669 *numForeignDataWrappers = ntups;
5671 fdwinfo = (FdwInfo *) malloc(ntups * sizeof(FdwInfo));
5673 i_oid = PQfnumber(res, "oid");
5674 i_fdwname = PQfnumber(res, "fdwname");
5675 i_rolname = PQfnumber(res, "rolname");
5676 i_fdwvalidator = PQfnumber(res, "fdwvalidator");
5677 i_fdwacl = PQfnumber(res, "fdwacl");
5678 i_fdwoptions = PQfnumber(res, "fdwoptions");
5680 for (i = 0; i < ntups; i++)
5682 fdwinfo[i].dobj.objType = DO_FDW;
5683 fdwinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
5684 AssignDumpId(&fdwinfo[i].dobj);
5685 fdwinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_fdwname));
5686 fdwinfo[i].dobj.namespace = NULL;
5687 fdwinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
5688 fdwinfo[i].fdwvalidator = strdup(PQgetvalue(res, i, i_fdwvalidator));
5689 fdwinfo[i].fdwoptions = strdup(PQgetvalue(res, i, i_fdwoptions));
5690 fdwinfo[i].fdwacl = strdup(PQgetvalue(res, i, i_fdwacl));
5693 /* Decide whether we want to dump it */
5694 selectDumpableObject(&(fdwinfo[i].dobj));
5699 destroyPQExpBuffer(query);
5705 * getForeignServers:
5706 * read all foreign servers in the system catalogs and return
5707 * them in the ForeignServerInfo * structure
5709 * numForeignServers is set to the number of servers read in
5712 getForeignServers(int *numForeignServers)
5717 PQExpBuffer query = createPQExpBuffer();
5718 ForeignServerInfo *srvinfo;
5728 /* Before 8.4, there are no foreign servers */
5729 if (g_fout->remoteVersion < 80400)
5731 *numForeignServers = 0;
5735 /* Make sure we are in proper schema */
5736 selectSourceSchema("pg_catalog");
5738 appendPQExpBuffer(query, "SELECT oid, srvname, "
5739 "(%s srvowner) AS rolname, "
5740 "srvfdw, srvtype, srvversion, srvacl,"
5741 "array_to_string(ARRAY("
5742 " SELECT option_name || ' ' || quote_literal(option_value) "
5743 " FROM pg_options_to_table(srvoptions)), ', ') AS srvoptions "
5744 "FROM pg_foreign_server",
5747 res = PQexec(g_conn, query->data);
5748 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
5750 ntups = PQntuples(res);
5751 *numForeignServers = ntups;
5753 srvinfo = (ForeignServerInfo *) malloc(ntups * sizeof(ForeignServerInfo));
5755 i_oid = PQfnumber(res, "oid");
5756 i_srvname = PQfnumber(res, "srvname");
5757 i_rolname = PQfnumber(res, "rolname");
5758 i_srvfdw = PQfnumber(res, "srvfdw");
5759 i_srvtype = PQfnumber(res, "srvtype");
5760 i_srvversion = PQfnumber(res, "srvversion");
5761 i_srvacl = PQfnumber(res, "srvacl");
5762 i_srvoptions = PQfnumber(res, "srvoptions");
5764 for (i = 0; i < ntups; i++)
5766 srvinfo[i].dobj.objType = DO_FOREIGN_SERVER;
5767 srvinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
5768 AssignDumpId(&srvinfo[i].dobj);
5769 srvinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_srvname));
5770 srvinfo[i].dobj.namespace = NULL;
5771 srvinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
5772 srvinfo[i].srvfdw = atooid(PQgetvalue(res, i, i_srvfdw));
5773 srvinfo[i].srvtype = strdup(PQgetvalue(res, i, i_srvtype));
5774 srvinfo[i].srvversion = strdup(PQgetvalue(res, i, i_srvversion));
5775 srvinfo[i].srvoptions = strdup(PQgetvalue(res, i, i_srvoptions));
5776 srvinfo[i].srvacl = strdup(PQgetvalue(res, i, i_srvacl));
5778 /* Decide whether we want to dump it */
5779 selectDumpableObject(&(srvinfo[i].dobj));
5784 destroyPQExpBuffer(query);
5791 * read all default ACL information in the system catalogs and return
5792 * them in the DefaultACLInfo structure
5794 * numDefaultACLs is set to the number of ACLs read in
5797 getDefaultACLs(int *numDefaultACLs)
5799 DefaultACLInfo *daclinfo;
5805 int i_defaclnamespace;
5806 int i_defaclobjtype;
5811 if (g_fout->remoteVersion < 80500)
5813 *numDefaultACLs = 0;
5817 query = createPQExpBuffer();
5819 /* Make sure we are in proper schema */
5820 selectSourceSchema("pg_catalog");
5822 appendPQExpBuffer(query, "SELECT oid, tableoid, "
5823 "(%s defaclrole) AS defaclrole, "
5827 "FROM pg_default_acl",
5830 res = PQexec(g_conn, query->data);
5831 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
5833 ntups = PQntuples(res);
5834 *numDefaultACLs = ntups;
5836 daclinfo = (DefaultACLInfo *) malloc(ntups * sizeof(DefaultACLInfo));
5838 i_oid = PQfnumber(res, "oid");
5839 i_tableoid = PQfnumber(res, "tableoid");
5840 i_defaclrole = PQfnumber(res, "defaclrole");
5841 i_defaclnamespace = PQfnumber(res, "defaclnamespace");
5842 i_defaclobjtype = PQfnumber(res, "defaclobjtype");
5843 i_defaclacl = PQfnumber(res, "defaclacl");
5845 for (i = 0; i < ntups; i++)
5847 Oid nspid = atooid(PQgetvalue(res, i, i_defaclnamespace));
5849 daclinfo[i].dobj.objType = DO_DEFAULT_ACL;
5850 daclinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
5851 daclinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
5852 AssignDumpId(&daclinfo[i].dobj);
5853 /* cheesy ... is it worth coming up with a better object name? */
5854 daclinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_defaclobjtype));
5856 if (nspid != InvalidOid)
5857 daclinfo[i].dobj.namespace = findNamespace(nspid,
5858 daclinfo[i].dobj.catId.oid);
5860 daclinfo[i].dobj.namespace = NULL;
5862 daclinfo[i].defaclrole = strdup(PQgetvalue(res, i, i_defaclrole));
5863 daclinfo[i].defaclobjtype = *(PQgetvalue(res, i, i_defaclobjtype));
5864 daclinfo[i].defaclacl = strdup(PQgetvalue(res, i, i_defaclacl));
5866 /* Decide whether we want to dump it */
5867 selectDumpableDefaultACL(&(daclinfo[i]));
5872 destroyPQExpBuffer(query);
5880 * This routine is used to dump any comments associated with the
5881 * object handed to this routine. The routine takes a constant character
5882 * string for the target part of the comment-creation command, plus
5883 * the namespace and owner of the object (for labeling the ArchiveEntry),
5884 * plus catalog ID and subid which are the lookup key for pg_description,
5885 * plus the dump ID for the object (for setting a dependency).
5886 * If a matching pg_description entry is found, it is dumped.
5888 * Note: although this routine takes a dumpId for dependency purposes,
5889 * that purpose is just to mark the dependency in the emitted dump file
5890 * for possible future use by pg_restore. We do NOT use it for determining
5891 * ordering of the comment in the dump file, because this routine is called
5892 * after dependency sorting occurs. This routine should be called just after
5893 * calling ArchiveEntry() for the specified object.
5896 dumpComment(Archive *fout, const char *target,
5897 const char *namespace, const char *owner,
5898 CatalogId catalogId, int subid, DumpId dumpId)
5900 CommentItem *comments;
5903 /* Comments are SCHEMA not data */
5907 /* Search for comments associated with catalogId, using table */
5908 ncomments = findComments(fout, catalogId.tableoid, catalogId.oid,
5911 /* Is there one matching the subid? */
5912 while (ncomments > 0)
5914 if (comments->objsubid == subid)
5920 /* If a comment exists, build COMMENT ON statement */
5923 PQExpBuffer query = createPQExpBuffer();
5925 appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
5926 appendStringLiteralAH(query, comments->descr, fout);
5927 appendPQExpBuffer(query, ";\n");
5930 * We mark comments as SECTION_NONE because they really belong in the
5931 * same section as their parent, whether that is pre-data or
5934 ArchiveEntry(fout, nilCatalogId, createDumpId(),
5935 target, namespace, NULL, owner,
5936 false, "COMMENT", SECTION_NONE,
5937 query->data, "", NULL,
5941 destroyPQExpBuffer(query);
5946 * dumpTableComment --
5948 * As above, but dump comments for both the specified table (or view)
5952 dumpTableComment(Archive *fout, TableInfo *tbinfo,
5953 const char *reltypename)
5955 CommentItem *comments;
5960 /* Comments are SCHEMA not data */
5964 /* Search for comments associated with relation, using table */
5965 ncomments = findComments(fout,
5966 tbinfo->dobj.catId.tableoid,
5967 tbinfo->dobj.catId.oid,
5970 /* If comments exist, build COMMENT ON statements */
5974 query = createPQExpBuffer();
5975 target = createPQExpBuffer();
5977 while (ncomments > 0)
5979 const char *descr = comments->descr;
5980 int objsubid = comments->objsubid;
5984 resetPQExpBuffer(target);
5985 appendPQExpBuffer(target, "%s %s", reltypename,
5986 fmtId(tbinfo->dobj.name));
5988 resetPQExpBuffer(query);
5989 appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
5990 appendStringLiteralAH(query, descr, fout);
5991 appendPQExpBuffer(query, ";\n");
5993 ArchiveEntry(fout, nilCatalogId, createDumpId(),
5995 tbinfo->dobj.namespace->dobj.name,
5996 NULL, tbinfo->rolname,
5997 false, "COMMENT", SECTION_NONE,
5998 query->data, "", NULL,
5999 &(tbinfo->dobj.dumpId), 1,
6002 else if (objsubid > 0 && objsubid <= tbinfo->numatts)
6004 resetPQExpBuffer(target);
6005 appendPQExpBuffer(target, "COLUMN %s.",
6006 fmtId(tbinfo->dobj.name));
6007 appendPQExpBuffer(target, "%s",
6008 fmtId(tbinfo->attnames[objsubid - 1]));
6010 resetPQExpBuffer(query);
6011 appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
6012 appendStringLiteralAH(query, descr, fout);
6013 appendPQExpBuffer(query, ";\n");
6015 ArchiveEntry(fout, nilCatalogId, createDumpId(),
6017 tbinfo->dobj.namespace->dobj.name,
6018 NULL, tbinfo->rolname,
6019 false, "COMMENT", SECTION_NONE,
6020 query->data, "", NULL,
6021 &(tbinfo->dobj.dumpId), 1,
6029 destroyPQExpBuffer(query);
6030 destroyPQExpBuffer(target);
6036 * Find the comment(s), if any, associated with the given object. All the
6037 * objsubid values associated with the given classoid/objoid are found with
6041 findComments(Archive *fout, Oid classoid, Oid objoid,
6042 CommentItem **items)
6044 /* static storage for table of comments */
6045 static CommentItem *comments = NULL;
6046 static int ncomments = -1;
6048 CommentItem *middle = NULL;
6053 /* Get comments if we didn't already */
6055 ncomments = collectComments(fout, &comments);
6058 * Pre-7.2, pg_description does not contain classoid, so collectComments
6059 * just stores a zero. If there's a collision on object OID, well, you
6060 * get duplicate comments.
6062 if (fout->remoteVersion < 70200)
6066 * Do binary search to find some item matching the object.
6069 high = &comments[ncomments - 1];
6072 middle = low + (high - low) / 2;
6074 if (classoid < middle->classoid)
6076 else if (classoid > middle->classoid)
6078 else if (objoid < middle->objoid)
6080 else if (objoid > middle->objoid)
6083 break; /* found a match */
6086 if (low > high) /* no matches */
6093 * Now determine how many items match the object. The search loop
6094 * invariant still holds: only items between low and high inclusive could
6098 while (middle > low)
6100 if (classoid != middle[-1].classoid ||
6101 objoid != middle[-1].objoid)
6110 while (middle <= high)
6112 if (classoid != middle->classoid ||
6113 objoid != middle->objoid)
6123 * collectComments --
6125 * Construct a table of all comments available for database objects.
6126 * We used to do per-object queries for the comments, but it's much faster
6127 * to pull them all over at once, and on most databases the memory cost
6130 * The table is sorted by classoid/objid/objsubid for speed in lookup.
6133 collectComments(Archive *fout, CommentItem **items)
6143 CommentItem *comments;
6146 * Note we do NOT change source schema here; preserve the caller's
6150 query = createPQExpBuffer();
6152 if (fout->remoteVersion >= 70300)
6154 appendPQExpBuffer(query, "SELECT description, classoid, objoid, objsubid "
6155 "FROM pg_catalog.pg_description "
6156 "ORDER BY classoid, objoid, objsubid");
6158 else if (fout->remoteVersion >= 70200)
6160 appendPQExpBuffer(query, "SELECT description, classoid, objoid, objsubid "
6161 "FROM pg_description "
6162 "ORDER BY classoid, objoid, objsubid");
6166 /* Note: this will fail to find attribute comments in pre-7.2... */
6167 appendPQExpBuffer(query, "SELECT description, 0 AS classoid, objoid, 0 AS objsubid "
6168 "FROM pg_description "
6172 res = PQexec(g_conn, query->data);
6173 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6175 /* Construct lookup table containing OIDs in numeric form */
6177 i_description = PQfnumber(res, "description");
6178 i_classoid = PQfnumber(res, "classoid");
6179 i_objoid = PQfnumber(res, "objoid");
6180 i_objsubid = PQfnumber(res, "objsubid");
6182 ntups = PQntuples(res);
6184 comments = (CommentItem *) malloc(ntups * sizeof(CommentItem));
6186 for (i = 0; i < ntups; i++)
6188 comments[i].descr = PQgetvalue(res, i, i_description);
6189 comments[i].classoid = atooid(PQgetvalue(res, i, i_classoid));
6190 comments[i].objoid = atooid(PQgetvalue(res, i, i_objoid));
6191 comments[i].objsubid = atoi(PQgetvalue(res, i, i_objsubid));
6194 /* Do NOT free the PGresult since we are keeping pointers into it */
6195 destroyPQExpBuffer(query);
6202 * dumpDumpableObject
6204 * This routine and its subsidiaries are responsible for creating
6205 * ArchiveEntries (TOC objects) for each object to be dumped.
6208 dumpDumpableObject(Archive *fout, DumpableObject *dobj)
6210 switch (dobj->objType)
6213 dumpNamespace(fout, (NamespaceInfo *) dobj);
6216 dumpType(fout, (TypeInfo *) dobj);
6219 dumpShellType(fout, (ShellTypeInfo *) dobj);
6222 dumpFunc(fout, (FuncInfo *) dobj);
6225 dumpAgg(fout, (AggInfo *) dobj);
6228 dumpOpr(fout, (OprInfo *) dobj);
6231 dumpOpclass(fout, (OpclassInfo *) dobj);
6234 dumpOpfamily(fout, (OpfamilyInfo *) dobj);
6237 dumpConversion(fout, (ConvInfo *) dobj);
6240 dumpTable(fout, (TableInfo *) dobj);
6243 dumpAttrDef(fout, (AttrDefInfo *) dobj);
6246 dumpIndex(fout, (IndxInfo *) dobj);
6249 dumpRule(fout, (RuleInfo *) dobj);
6252 dumpTrigger(fout, (TriggerInfo *) dobj);
6255 dumpConstraint(fout, (ConstraintInfo *) dobj);
6257 case DO_FK_CONSTRAINT:
6258 dumpConstraint(fout, (ConstraintInfo *) dobj);
6261 dumpProcLang(fout, (ProcLangInfo *) dobj);
6264 dumpCast(fout, (CastInfo *) dobj);
6267 dumpTableData(fout, (TableDataInfo *) dobj);
6270 /* table rowtypes and array types are never dumped separately */
6273 dumpTSParser(fout, (TSParserInfo *) dobj);
6276 dumpTSDictionary(fout, (TSDictInfo *) dobj);
6279 dumpTSTemplate(fout, (TSTemplateInfo *) dobj);
6282 dumpTSConfig(fout, (TSConfigInfo *) dobj);
6285 dumpForeignDataWrapper(fout, (FdwInfo *) dobj);
6287 case DO_FOREIGN_SERVER:
6288 dumpForeignServer(fout, (ForeignServerInfo *) dobj);
6290 case DO_DEFAULT_ACL:
6291 dumpDefaultACL(fout, (DefaultACLInfo *) dobj);
6294 ArchiveEntry(fout, dobj->catId, dobj->dumpId,
6295 dobj->name, NULL, NULL, "",
6296 false, "BLOBS", SECTION_DATA,
6298 dobj->dependencies, dobj->nDeps,
6301 case DO_BLOB_COMMENTS:
6302 ArchiveEntry(fout, dobj->catId, dobj->dumpId,
6303 dobj->name, NULL, NULL, "",
6304 false, "BLOB COMMENTS", SECTION_DATA,
6306 dobj->dependencies, dobj->nDeps,
6307 dumpBlobComments, NULL);
6314 * writes out to fout the queries to recreate a user-defined namespace
6317 dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
6323 /* Skip if not to be dumped */
6324 if (!nspinfo->dobj.dump || dataOnly)
6327 /* don't dump dummy namespace from pre-7.3 source */
6328 if (strlen(nspinfo->dobj.name) == 0)
6331 q = createPQExpBuffer();
6332 delq = createPQExpBuffer();
6334 qnspname = strdup(fmtId(nspinfo->dobj.name));
6336 appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
6338 appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
6340 ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
6344 false, "SCHEMA", SECTION_PRE_DATA,
6345 q->data, delq->data, NULL,
6346 nspinfo->dobj.dependencies, nspinfo->dobj.nDeps,
6349 /* Dump Schema Comments */
6350 resetPQExpBuffer(q);
6351 appendPQExpBuffer(q, "SCHEMA %s", qnspname);
6352 dumpComment(fout, q->data,
6353 NULL, nspinfo->rolname,
6354 nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
6356 dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
6357 qnspname, NULL, nspinfo->dobj.name, NULL,
6358 nspinfo->rolname, nspinfo->nspacl);
6362 destroyPQExpBuffer(q);
6363 destroyPQExpBuffer(delq);
6368 * writes out to fout the queries to recreate a user-defined type
6371 dumpType(Archive *fout, TypeInfo *tinfo)
6373 /* Skip if not to be dumped */
6374 if (!tinfo->dobj.dump || dataOnly)
6377 /* Dump out in proper style */
6378 if (tinfo->typtype == TYPTYPE_BASE)
6379 dumpBaseType(fout, tinfo);
6380 else if (tinfo->typtype == TYPTYPE_DOMAIN)
6381 dumpDomain(fout, tinfo);
6382 else if (tinfo->typtype == TYPTYPE_COMPOSITE)
6383 dumpCompositeType(fout, tinfo);
6384 else if (tinfo->typtype == TYPTYPE_ENUM)
6385 dumpEnumType(fout, tinfo);
6390 * writes out to fout the queries to recreate a user-defined enum type
6393 dumpEnumType(Archive *fout, TypeInfo *tinfo)
6395 PQExpBuffer q = createPQExpBuffer();
6396 PQExpBuffer delq = createPQExpBuffer();
6397 PQExpBuffer query = createPQExpBuffer();
6403 /* Set proper schema search path so regproc references list correctly */
6404 selectSourceSchema(tinfo->dobj.namespace->dobj.name);
6406 appendPQExpBuffer(query, "SELECT enumlabel FROM pg_catalog.pg_enum "
6407 "WHERE enumtypid = '%u'"
6409 tinfo->dobj.catId.oid);
6411 res = PQexec(g_conn, query->data);
6412 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6414 num = PQntuples(res);
6415 /* should be at least 1 value */
6418 write_msg(NULL, "no label definitions found for enum ID %u\n", tinfo->dobj.catId.oid);
6423 * DROP must be fully qualified in case same name appears in pg_catalog.
6424 * CASCADE shouldn't be required here as for normal types since the I/O
6425 * functions are generic and do not get dropped.
6427 appendPQExpBuffer(delq, "DROP TYPE %s.",
6428 fmtId(tinfo->dobj.namespace->dobj.name));
6429 appendPQExpBuffer(delq, "%s;\n",
6430 fmtId(tinfo->dobj.name));
6431 appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (\n",
6432 fmtId(tinfo->dobj.name));
6433 for (i = 0; i < num; i++)
6435 label = PQgetvalue(res, i, 0);
6437 appendPQExpBuffer(q, ",\n");
6438 appendPQExpBuffer(q, " ");
6439 appendStringLiteralAH(q, label, fout);
6441 appendPQExpBuffer(q, "\n);\n");
6443 ArchiveEntry(fout, tinfo->dobj.catId, tinfo->dobj.dumpId,
6445 tinfo->dobj.namespace->dobj.name,
6447 tinfo->rolname, false,
6448 "TYPE", SECTION_PRE_DATA,
6449 q->data, delq->data, NULL,
6450 tinfo->dobj.dependencies, tinfo->dobj.nDeps,
6453 /* Dump Type Comments */
6454 resetPQExpBuffer(q);
6456 appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->dobj.name));
6457 dumpComment(fout, q->data,
6458 tinfo->dobj.namespace->dobj.name, tinfo->rolname,
6459 tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
6462 destroyPQExpBuffer(q);
6463 destroyPQExpBuffer(delq);
6464 destroyPQExpBuffer(query);
6469 * writes out to fout the queries to recreate a user-defined base type
6472 dumpBaseType(Archive *fout, TypeInfo *tinfo)
6474 PQExpBuffer q = createPQExpBuffer();
6475 PQExpBuffer delq = createPQExpBuffer();
6476 PQExpBuffer query = createPQExpBuffer();
6495 char *typispreferred;
6501 bool typdefault_is_literal = false;
6503 /* Set proper schema search path so regproc references list correctly */
6504 selectSourceSchema(tinfo->dobj.namespace->dobj.name);
6506 /* Fetch type-specific details */
6507 if (fout->remoteVersion >= 80400)
6509 appendPQExpBuffer(query, "SELECT typlen, "
6510 "typinput, typoutput, typreceive, typsend, "
6511 "typmodin, typmodout, typanalyze, "
6512 "typinput::pg_catalog.oid AS typinputoid, "
6513 "typoutput::pg_catalog.oid AS typoutputoid, "
6514 "typreceive::pg_catalog.oid AS typreceiveoid, "
6515 "typsend::pg_catalog.oid AS typsendoid, "
6516 "typmodin::pg_catalog.oid AS typmodinoid, "
6517 "typmodout::pg_catalog.oid AS typmodoutoid, "
6518 "typanalyze::pg_catalog.oid AS typanalyzeoid, "
6519 "typcategory, typispreferred, "
6520 "typdelim, typbyval, typalign, typstorage, "
6521 "pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault "
6522 "FROM pg_catalog.pg_type "
6523 "WHERE oid = '%u'::pg_catalog.oid",
6524 tinfo->dobj.catId.oid);
6526 else if (fout->remoteVersion >= 80300)
6528 /* Before 8.4, pg_get_expr does not allow 0 for its second arg */
6529 appendPQExpBuffer(query, "SELECT typlen, "
6530 "typinput, typoutput, typreceive, typsend, "
6531 "typmodin, typmodout, typanalyze, "
6532 "typinput::pg_catalog.oid AS typinputoid, "
6533 "typoutput::pg_catalog.oid AS typoutputoid, "
6534 "typreceive::pg_catalog.oid AS typreceiveoid, "
6535 "typsend::pg_catalog.oid AS typsendoid, "
6536 "typmodin::pg_catalog.oid AS typmodinoid, "
6537 "typmodout::pg_catalog.oid AS typmodoutoid, "
6538 "typanalyze::pg_catalog.oid AS typanalyzeoid, "
6539 "'U' AS typcategory, false AS typispreferred, "
6540 "typdelim, typbyval, typalign, typstorage, "
6541 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
6542 "FROM pg_catalog.pg_type "
6543 "WHERE oid = '%u'::pg_catalog.oid",
6544 tinfo->dobj.catId.oid);
6546 else if (fout->remoteVersion >= 80000)
6548 appendPQExpBuffer(query, "SELECT typlen, "
6549 "typinput, typoutput, typreceive, typsend, "
6550 "'-' AS typmodin, '-' AS typmodout, "
6552 "typinput::pg_catalog.oid AS typinputoid, "
6553 "typoutput::pg_catalog.oid AS typoutputoid, "
6554 "typreceive::pg_catalog.oid AS typreceiveoid, "
6555 "typsend::pg_catalog.oid AS typsendoid, "
6556 "0 AS typmodinoid, 0 AS typmodoutoid, "
6557 "typanalyze::pg_catalog.oid AS typanalyzeoid, "
6558 "'U' AS typcategory, false AS typispreferred, "
6559 "typdelim, typbyval, typalign, typstorage, "
6560 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
6561 "FROM pg_catalog.pg_type "
6562 "WHERE oid = '%u'::pg_catalog.oid",
6563 tinfo->dobj.catId.oid);
6565 else if (fout->remoteVersion >= 70400)
6567 appendPQExpBuffer(query, "SELECT typlen, "
6568 "typinput, typoutput, typreceive, typsend, "
6569 "'-' AS typmodin, '-' AS typmodout, "
6570 "'-' AS typanalyze, "
6571 "typinput::pg_catalog.oid AS typinputoid, "
6572 "typoutput::pg_catalog.oid AS typoutputoid, "
6573 "typreceive::pg_catalog.oid AS typreceiveoid, "
6574 "typsend::pg_catalog.oid AS typsendoid, "
6575 "0 AS typmodinoid, 0 AS typmodoutoid, "
6576 "0 AS typanalyzeoid, "
6577 "'U' AS typcategory, false AS typispreferred, "
6578 "typdelim, typbyval, typalign, typstorage, "
6579 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
6580 "FROM pg_catalog.pg_type "
6581 "WHERE oid = '%u'::pg_catalog.oid",
6582 tinfo->dobj.catId.oid);
6584 else if (fout->remoteVersion >= 70300)
6586 appendPQExpBuffer(query, "SELECT typlen, "
6587 "typinput, typoutput, "
6588 "'-' AS typreceive, '-' AS typsend, "
6589 "'-' AS typmodin, '-' AS typmodout, "
6590 "'-' AS typanalyze, "
6591 "typinput::pg_catalog.oid AS typinputoid, "
6592 "typoutput::pg_catalog.oid AS typoutputoid, "
6593 "0 AS typreceiveoid, 0 AS typsendoid, "
6594 "0 AS typmodinoid, 0 AS typmodoutoid, "
6595 "0 AS typanalyzeoid, "
6596 "'U' AS typcategory, false AS typispreferred, "
6597 "typdelim, typbyval, typalign, typstorage, "
6598 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
6599 "FROM pg_catalog.pg_type "
6600 "WHERE oid = '%u'::pg_catalog.oid",
6601 tinfo->dobj.catId.oid);
6603 else if (fout->remoteVersion >= 70200)
6606 * Note: although pre-7.3 catalogs contain typreceive and typsend,
6607 * ignore them because they are not right.
6609 appendPQExpBuffer(query, "SELECT typlen, "
6610 "typinput, typoutput, "
6611 "'-' AS typreceive, '-' AS typsend, "
6612 "'-' AS typmodin, '-' AS typmodout, "
6613 "'-' AS typanalyze, "
6614 "typinput::oid AS typinputoid, "
6615 "typoutput::oid AS typoutputoid, "
6616 "0 AS typreceiveoid, 0 AS typsendoid, "
6617 "0 AS typmodinoid, 0 AS typmodoutoid, "
6618 "0 AS typanalyzeoid, "
6619 "'U' AS typcategory, false AS typispreferred, "
6620 "typdelim, typbyval, typalign, typstorage, "
6621 "NULL AS typdefaultbin, typdefault "
6623 "WHERE oid = '%u'::oid",
6624 tinfo->dobj.catId.oid);
6626 else if (fout->remoteVersion >= 70100)
6629 * Ignore pre-7.2 typdefault; the field exists but has an unusable
6632 appendPQExpBuffer(query, "SELECT typlen, "
6633 "typinput, typoutput, "
6634 "'-' AS typreceive, '-' AS typsend, "
6635 "'-' AS typmodin, '-' AS typmodout, "
6636 "'-' AS typanalyze, "
6637 "typinput::oid AS typinputoid, "
6638 "typoutput::oid AS typoutputoid, "
6639 "0 AS typreceiveoid, 0 AS typsendoid, "
6640 "0 AS typmodinoid, 0 AS typmodoutoid, "
6641 "0 AS typanalyzeoid, "
6642 "'U' AS typcategory, false AS typispreferred, "
6643 "typdelim, typbyval, typalign, typstorage, "
6644 "NULL AS typdefaultbin, NULL AS typdefault "
6646 "WHERE oid = '%u'::oid",
6647 tinfo->dobj.catId.oid);
6651 appendPQExpBuffer(query, "SELECT typlen, "
6652 "typinput, typoutput, "
6653 "'-' AS typreceive, '-' AS typsend, "
6654 "'-' AS typmodin, '-' AS typmodout, "
6655 "'-' AS typanalyze, "
6656 "typinput::oid AS typinputoid, "
6657 "typoutput::oid AS typoutputoid, "
6658 "0 AS typreceiveoid, 0 AS typsendoid, "
6659 "0 AS typmodinoid, 0 AS typmodoutoid, "
6660 "0 AS typanalyzeoid, "
6661 "'U' AS typcategory, false AS typispreferred, "
6662 "typdelim, typbyval, typalign, "
6663 "'p'::char AS typstorage, "
6664 "NULL AS typdefaultbin, NULL AS typdefault "
6666 "WHERE oid = '%u'::oid",
6667 tinfo->dobj.catId.oid);
6670 res = PQexec(g_conn, query->data);
6671 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6673 /* Expecting a single result only */
6674 ntups = PQntuples(res);
6677 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
6678 "query returned %d rows instead of one: %s\n",
6680 ntups, query->data);
6684 typlen = PQgetvalue(res, 0, PQfnumber(res, "typlen"));
6685 typinput = PQgetvalue(res, 0, PQfnumber(res, "typinput"));
6686 typoutput = PQgetvalue(res, 0, PQfnumber(res, "typoutput"));
6687 typreceive = PQgetvalue(res, 0, PQfnumber(res, "typreceive"));
6688 typsend = PQgetvalue(res, 0, PQfnumber(res, "typsend"));
6689 typmodin = PQgetvalue(res, 0, PQfnumber(res, "typmodin"));
6690 typmodout = PQgetvalue(res, 0, PQfnumber(res, "typmodout"));
6691 typanalyze = PQgetvalue(res, 0, PQfnumber(res, "typanalyze"));
6692 typinputoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typinputoid")));
6693 typoutputoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typoutputoid")));
6694 typreceiveoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typreceiveoid")));
6695 typsendoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typsendoid")));
6696 typmodinoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodinoid")));
6697 typmodoutoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodoutoid")));
6698 typanalyzeoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typanalyzeoid")));
6699 typcategory = PQgetvalue(res, 0, PQfnumber(res, "typcategory"));
6700 typispreferred = PQgetvalue(res, 0, PQfnumber(res, "typispreferred"));
6701 typdelim = PQgetvalue(res, 0, PQfnumber(res, "typdelim"));
6702 typbyval = PQgetvalue(res, 0, PQfnumber(res, "typbyval"));
6703 typalign = PQgetvalue(res, 0, PQfnumber(res, "typalign"));
6704 typstorage = PQgetvalue(res, 0, PQfnumber(res, "typstorage"));
6705 if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin")))
6706 typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin"));
6707 else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
6709 typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
6710 typdefault_is_literal = true; /* it needs quotes */
6716 * DROP must be fully qualified in case same name appears in pg_catalog.
6717 * The reason we include CASCADE is that the circular dependency between
6718 * the type and its I/O functions makes it impossible to drop the type any
6721 appendPQExpBuffer(delq, "DROP TYPE %s.",
6722 fmtId(tinfo->dobj.namespace->dobj.name));
6723 appendPQExpBuffer(delq, "%s CASCADE;\n",
6724 fmtId(tinfo->dobj.name));
6726 appendPQExpBuffer(q,
6727 "CREATE TYPE %s (\n"
6728 " INTERNALLENGTH = %s",
6729 fmtId(tinfo->dobj.name),
6730 (strcmp(typlen, "-1") == 0) ? "variable" : typlen);
6732 if (fout->remoteVersion >= 70300)
6734 /* regproc result is correctly quoted as of 7.3 */
6735 appendPQExpBuffer(q, ",\n INPUT = %s", typinput);
6736 appendPQExpBuffer(q, ",\n OUTPUT = %s", typoutput);
6737 if (OidIsValid(typreceiveoid))
6738 appendPQExpBuffer(q, ",\n RECEIVE = %s", typreceive);
6739 if (OidIsValid(typsendoid))
6740 appendPQExpBuffer(q, ",\n SEND = %s", typsend);
6741 if (OidIsValid(typmodinoid))
6742 appendPQExpBuffer(q, ",\n TYPMOD_IN = %s", typmodin);
6743 if (OidIsValid(typmodoutoid))
6744 appendPQExpBuffer(q, ",\n TYPMOD_OUT = %s", typmodout);
6745 if (OidIsValid(typanalyzeoid))
6746 appendPQExpBuffer(q, ",\n ANALYZE = %s", typanalyze);
6750 /* regproc delivers an unquoted name before 7.3 */
6751 /* cannot combine these because fmtId uses static result area */
6752 appendPQExpBuffer(q, ",\n INPUT = %s", fmtId(typinput));
6753 appendPQExpBuffer(q, ",\n OUTPUT = %s", fmtId(typoutput));
6754 /* receive/send/typmodin/typmodout/analyze need not be printed */
6757 if (typdefault != NULL)
6759 appendPQExpBuffer(q, ",\n DEFAULT = ");
6760 if (typdefault_is_literal)
6761 appendStringLiteralAH(q, typdefault, fout);
6763 appendPQExpBufferStr(q, typdefault);
6766 if (OidIsValid(tinfo->typelem))
6770 /* reselect schema in case changed by function dump */
6771 selectSourceSchema(tinfo->dobj.namespace->dobj.name);
6772 elemType = getFormattedTypeName(tinfo->typelem, zeroAsOpaque);
6773 appendPQExpBuffer(q, ",\n ELEMENT = %s", elemType);
6777 if (strcmp(typcategory, "U") != 0)
6779 appendPQExpBuffer(q, ",\n CATEGORY = ");
6780 appendStringLiteralAH(q, typcategory, fout);
6783 if (strcmp(typispreferred, "t") == 0)
6784 appendPQExpBuffer(q, ",\n PREFERRED = true");
6786 if (typdelim && strcmp(typdelim, ",") != 0)
6788 appendPQExpBuffer(q, ",\n DELIMITER = ");
6789 appendStringLiteralAH(q, typdelim, fout);
6792 if (strcmp(typalign, "c") == 0)
6793 appendPQExpBuffer(q, ",\n ALIGNMENT = char");
6794 else if (strcmp(typalign, "s") == 0)
6795 appendPQExpBuffer(q, ",\n ALIGNMENT = int2");
6796 else if (strcmp(typalign, "i") == 0)
6797 appendPQExpBuffer(q, ",\n ALIGNMENT = int4");
6798 else if (strcmp(typalign, "d") == 0)
6799 appendPQExpBuffer(q, ",\n ALIGNMENT = double");
6801 if (strcmp(typstorage, "p") == 0)
6802 appendPQExpBuffer(q, ",\n STORAGE = plain");
6803 else if (strcmp(typstorage, "e") == 0)
6804 appendPQExpBuffer(q, ",\n STORAGE = external");
6805 else if (strcmp(typstorage, "x") == 0)
6806 appendPQExpBuffer(q, ",\n STORAGE = extended");
6807 else if (strcmp(typstorage, "m") == 0)
6808 appendPQExpBuffer(q, ",\n STORAGE = main");
6810 if (strcmp(typbyval, "t") == 0)
6811 appendPQExpBuffer(q, ",\n PASSEDBYVALUE");
6813 appendPQExpBuffer(q, "\n);\n");
6815 ArchiveEntry(fout, tinfo->dobj.catId, tinfo->dobj.dumpId,
6817 tinfo->dobj.namespace->dobj.name,
6819 tinfo->rolname, false,
6820 "TYPE", SECTION_PRE_DATA,
6821 q->data, delq->data, NULL,
6822 tinfo->dobj.dependencies, tinfo->dobj.nDeps,
6825 /* Dump Type Comments */
6826 resetPQExpBuffer(q);
6828 appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->dobj.name));
6829 dumpComment(fout, q->data,
6830 tinfo->dobj.namespace->dobj.name, tinfo->rolname,
6831 tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
6834 destroyPQExpBuffer(q);
6835 destroyPQExpBuffer(delq);
6836 destroyPQExpBuffer(query);
6841 * writes out to fout the queries to recreate a user-defined domain
6844 dumpDomain(Archive *fout, TypeInfo *tinfo)
6846 PQExpBuffer q = createPQExpBuffer();
6847 PQExpBuffer delq = createPQExpBuffer();
6848 PQExpBuffer query = createPQExpBuffer();
6855 bool typdefault_is_literal = false;
6857 /* Set proper schema search path so type references list correctly */
6858 selectSourceSchema(tinfo->dobj.namespace->dobj.name);
6860 /* Fetch domain specific details */
6861 /* We assume here that remoteVersion must be at least 70300 */
6862 appendPQExpBuffer(query, "SELECT typnotnull, "
6863 "pg_catalog.format_type(typbasetype, typtypmod) AS typdefn, "
6864 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
6865 "FROM pg_catalog.pg_type "
6866 "WHERE oid = '%u'::pg_catalog.oid",
6867 tinfo->dobj.catId.oid);
6869 res = PQexec(g_conn, query->data);
6870 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6872 /* Expecting a single result only */
6873 ntups = PQntuples(res);
6876 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
6877 "query returned %d rows instead of one: %s\n",
6879 ntups, query->data);
6883 typnotnull = PQgetvalue(res, 0, PQfnumber(res, "typnotnull"));
6884 typdefn = PQgetvalue(res, 0, PQfnumber(res, "typdefn"));
6885 if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin")))
6886 typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin"));
6887 else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
6889 typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
6890 typdefault_is_literal = true; /* it needs quotes */
6895 appendPQExpBuffer(q,
6896 "CREATE DOMAIN %s AS %s",
6897 fmtId(tinfo->dobj.name),
6900 if (typnotnull[0] == 't')
6901 appendPQExpBuffer(q, " NOT NULL");
6903 if (typdefault != NULL)
6905 appendPQExpBuffer(q, " DEFAULT ");
6906 if (typdefault_is_literal)
6907 appendStringLiteralAH(q, typdefault, fout);
6909 appendPQExpBufferStr(q, typdefault);
6915 * Add any CHECK constraints for the domain
6917 for (i = 0; i < tinfo->nDomChecks; i++)
6919 ConstraintInfo *domcheck = &(tinfo->domChecks[i]);
6921 if (!domcheck->separate)
6922 appendPQExpBuffer(q, "\n\tCONSTRAINT %s %s",
6923 fmtId(domcheck->dobj.name), domcheck->condef);
6926 appendPQExpBuffer(q, ";\n");
6929 * DROP must be fully qualified in case same name appears in pg_catalog
6931 appendPQExpBuffer(delq, "DROP DOMAIN %s.",
6932 fmtId(tinfo->dobj.namespace->dobj.name));
6933 appendPQExpBuffer(delq, "%s;\n",
6934 fmtId(tinfo->dobj.name));
6936 ArchiveEntry(fout, tinfo->dobj.catId, tinfo->dobj.dumpId,
6938 tinfo->dobj.namespace->dobj.name,
6940 tinfo->rolname, false,
6941 "DOMAIN", SECTION_PRE_DATA,
6942 q->data, delq->data, NULL,
6943 tinfo->dobj.dependencies, tinfo->dobj.nDeps,
6946 /* Dump Domain Comments */
6947 resetPQExpBuffer(q);
6949 appendPQExpBuffer(q, "DOMAIN %s", fmtId(tinfo->dobj.name));
6950 dumpComment(fout, q->data,
6951 tinfo->dobj.namespace->dobj.name, tinfo->rolname,
6952 tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
6954 destroyPQExpBuffer(q);
6955 destroyPQExpBuffer(delq);
6956 destroyPQExpBuffer(query);
6961 * writes out to fout the queries to recreate a user-defined stand-alone
6965 dumpCompositeType(Archive *fout, TypeInfo *tinfo)
6967 PQExpBuffer q = createPQExpBuffer();
6968 PQExpBuffer delq = createPQExpBuffer();
6969 PQExpBuffer query = createPQExpBuffer();
6976 /* Set proper schema search path so type references list correctly */
6977 selectSourceSchema(tinfo->dobj.namespace->dobj.name);
6979 /* Fetch type specific details */
6980 /* We assume here that remoteVersion must be at least 70300 */
6982 appendPQExpBuffer(query, "SELECT a.attname, "
6983 "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn "
6984 "FROM pg_catalog.pg_type t, pg_catalog.pg_attribute a "
6985 "WHERE t.oid = '%u'::pg_catalog.oid "
6986 "AND a.attrelid = t.typrelid "
6987 "AND NOT a.attisdropped "
6988 "ORDER BY a.attnum ",
6989 tinfo->dobj.catId.oid);
6991 res = PQexec(g_conn, query->data);
6992 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
6994 /* Expecting at least a single result */
6995 ntups = PQntuples(res);
6998 write_msg(NULL, "query returned no rows: %s\n", query->data);
7002 i_attname = PQfnumber(res, "attname");
7003 i_atttypdefn = PQfnumber(res, "atttypdefn");
7005 appendPQExpBuffer(q, "CREATE TYPE %s AS (",
7006 fmtId(tinfo->dobj.name));
7008 for (i = 0; i < ntups; i++)
7013 attname = PQgetvalue(res, i, i_attname);
7014 atttypdefn = PQgetvalue(res, i, i_atttypdefn);
7016 appendPQExpBuffer(q, "\n\t%s %s", fmtId(attname), atttypdefn);
7018 appendPQExpBuffer(q, ",");
7020 appendPQExpBuffer(q, "\n);\n");
7023 * DROP must be fully qualified in case same name appears in pg_catalog
7025 appendPQExpBuffer(delq, "DROP TYPE %s.",
7026 fmtId(tinfo->dobj.namespace->dobj.name));
7027 appendPQExpBuffer(delq, "%s;\n",
7028 fmtId(tinfo->dobj.name));
7030 ArchiveEntry(fout, tinfo->dobj.catId, tinfo->dobj.dumpId,
7032 tinfo->dobj.namespace->dobj.name,
7034 tinfo->rolname, false,
7035 "TYPE", SECTION_PRE_DATA,
7036 q->data, delq->data, NULL,
7037 tinfo->dobj.dependencies, tinfo->dobj.nDeps,
7041 /* Dump Type Comments */
7042 resetPQExpBuffer(q);
7044 appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->dobj.name));
7045 dumpComment(fout, q->data,
7046 tinfo->dobj.namespace->dobj.name, tinfo->rolname,
7047 tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
7050 destroyPQExpBuffer(q);
7051 destroyPQExpBuffer(delq);
7052 destroyPQExpBuffer(query);
7054 /* Dump any per-column comments */
7055 dumpCompositeTypeColComments(fout, tinfo);
7059 * dumpCompositeTypeColComments
7060 * writes out to fout the queries to recreate comments on the columns of
7061 * a user-defined stand-alone composite type
7064 dumpCompositeTypeColComments(Archive *fout, TypeInfo *tinfo)
7066 CommentItem *comments;
7077 query = createPQExpBuffer();
7079 /* We assume here that remoteVersion must be at least 70300 */
7080 appendPQExpBuffer(query,
7081 "SELECT c.tableoid, a.attname, a.attnum "
7082 "FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a "
7083 "WHERE c.oid = '%u' AND c.oid = a.attrelid "
7084 " AND NOT a.attisdropped "
7085 "ORDER BY a.attnum ",
7088 /* Fetch column attnames */
7089 res = PQexec(g_conn, query->data);
7090 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
7092 /* Expecting at least a single result */
7093 ntups = PQntuples(res);
7096 write_msg(NULL, "query returned no rows: %s\n", query->data);
7100 pgClassOid = atooid(PQgetvalue(res, 0, PQfnumber(res, "tableoid")));
7102 /* Search for comments associated with type's pg_class OID */
7103 ncomments = findComments(fout,
7108 /* If no comments exist, we're done */
7112 destroyPQExpBuffer(query);
7116 /* Build COMMENT ON statements */
7117 target = createPQExpBuffer();
7119 i_attnum = PQfnumber(res, "attnum");
7120 i_attname = PQfnumber(res, "attname");
7121 while (ncomments > 0)
7123 const char *attname;
7126 for (i = 0; i < ntups; i++)
7128 if (atoi(PQgetvalue(res, i, i_attnum)) == comments->objsubid)
7130 attname = PQgetvalue(res, i, i_attname);
7134 if (attname) /* just in case we don't find it */
7136 const char *descr = comments->descr;
7138 resetPQExpBuffer(target);
7139 appendPQExpBuffer(target, "COLUMN %s.",
7140 fmtId(tinfo->dobj.name));
7141 appendPQExpBuffer(target, "%s",
7144 resetPQExpBuffer(query);
7145 appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
7146 appendStringLiteralAH(query, descr, fout);
7147 appendPQExpBuffer(query, ";\n");
7149 ArchiveEntry(fout, nilCatalogId, createDumpId(),
7151 tinfo->dobj.namespace->dobj.name,
7152 NULL, tinfo->rolname,
7153 false, "COMMENT", SECTION_NONE,
7154 query->data, "", NULL,
7155 &(tinfo->dobj.dumpId), 1,
7164 destroyPQExpBuffer(query);
7165 destroyPQExpBuffer(target);
7170 * writes out to fout the queries to create a shell type
7172 * We dump a shell definition in advance of the I/O functions for the type.
7175 dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
7179 /* Skip if not to be dumped */
7180 if (!stinfo->dobj.dump || dataOnly)
7183 q = createPQExpBuffer();
7186 * Note the lack of a DROP command for the shell type; any required DROP
7187 * is driven off the base type entry, instead. This interacts with
7188 * _printTocEntry()'s use of the presence of a DROP command to decide
7189 * whether an entry needs an ALTER OWNER command. We don't want to alter
7190 * the shell type's owner immediately on creation; that should happen only
7191 * after it's filled in, otherwise the backend complains.
7194 appendPQExpBuffer(q, "CREATE TYPE %s;\n",
7195 fmtId(stinfo->dobj.name));
7197 ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
7199 stinfo->dobj.namespace->dobj.name,
7201 stinfo->baseType->rolname, false,
7202 "SHELL TYPE", SECTION_PRE_DATA,
7204 stinfo->dobj.dependencies, stinfo->dobj.nDeps,
7207 destroyPQExpBuffer(q);
7211 * Determine whether we want to dump definitions for procedural languages.
7212 * Since the languages themselves don't have schemas, we can't rely on
7213 * the normal schema-based selection mechanism. We choose to dump them
7214 * whenever neither --schema nor --table was given. (Before 8.1, we used
7215 * the dump flag of the PL's call handler function, but in 8.1 this will
7216 * probably always be false since call handlers are created in pg_catalog.)
7218 * For some backwards compatibility with the older behavior, we forcibly
7219 * dump a PL if its handler function (and validator if any) are in a
7220 * dumpable namespace. That case is not checked here.
7223 shouldDumpProcLangs(void)
7225 if (!include_everything)
7227 /* And they're schema not data */
7235 * writes out to fout the queries to recreate a user-defined
7236 * procedural language
7239 dumpProcLang(Archive *fout, ProcLangInfo *plang)
7247 FuncInfo *inlineInfo = NULL;
7248 FuncInfo *validatorInfo = NULL;
7254 * Try to find the support function(s). It is not an error if we don't
7255 * find them --- if the functions are in the pg_catalog schema, as is
7256 * standard in 8.1 and up, then we won't have loaded them. (In this case
7257 * we will emit a parameterless CREATE LANGUAGE command, which will
7258 * require PL template knowledge in the backend to reload.)
7261 funcInfo = findFuncByOid(plang->lanplcallfoid);
7262 if (funcInfo != NULL && !funcInfo->dobj.dump)
7263 funcInfo = NULL; /* treat not-dumped same as not-found */
7265 if (OidIsValid(plang->laninline))
7267 inlineInfo = findFuncByOid(plang->laninline);
7268 if (inlineInfo != NULL && !inlineInfo->dobj.dump)
7272 if (OidIsValid(plang->lanvalidator))
7274 validatorInfo = findFuncByOid(plang->lanvalidator);
7275 if (validatorInfo != NULL && !validatorInfo->dobj.dump)
7276 validatorInfo = NULL;
7280 * If the functions are dumpable then emit a traditional CREATE LANGUAGE
7281 * with parameters. Otherwise, dump only if shouldDumpProcLangs() says to
7284 useParams = (funcInfo != NULL &&
7285 (inlineInfo != NULL || !OidIsValid(plang->laninline)) &&
7286 (validatorInfo != NULL || !OidIsValid(plang->lanvalidator)));
7288 if (!useParams && !shouldDumpProcLangs())
7291 defqry = createPQExpBuffer();
7292 delqry = createPQExpBuffer();
7294 qlanname = strdup(fmtId(plang->dobj.name));
7297 * If dumping a HANDLER clause, treat the language as being in the handler
7298 * function's schema; this avoids cluttering the HANDLER clause. Otherwise
7299 * it doesn't really have a schema.
7302 lanschema = funcInfo->dobj.namespace->dobj.name;
7306 appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n",
7309 appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s",
7310 (useParams && plang->lanpltrusted) ? "TRUSTED " : "",
7314 appendPQExpBuffer(defqry, " HANDLER %s",
7315 fmtId(funcInfo->dobj.name));
7316 if (OidIsValid(plang->laninline))
7318 appendPQExpBuffer(defqry, " INLINE ");
7319 /* Cope with possibility that inline is in different schema */
7320 if (inlineInfo->dobj.namespace != funcInfo->dobj.namespace)
7321 appendPQExpBuffer(defqry, "%s.",
7322 fmtId(inlineInfo->dobj.namespace->dobj.name));
7323 appendPQExpBuffer(defqry, "%s",
7324 fmtId(inlineInfo->dobj.name));
7326 if (OidIsValid(plang->lanvalidator))
7328 appendPQExpBuffer(defqry, " VALIDATOR ");
7329 /* Cope with possibility that validator is in different schema */
7330 if (validatorInfo->dobj.namespace != funcInfo->dobj.namespace)
7331 appendPQExpBuffer(defqry, "%s.",
7332 fmtId(validatorInfo->dobj.namespace->dobj.name));
7333 appendPQExpBuffer(defqry, "%s",
7334 fmtId(validatorInfo->dobj.name));
7337 appendPQExpBuffer(defqry, ";\n");
7339 ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
7341 lanschema, NULL, plang->lanowner,
7342 false, "PROCEDURAL LANGUAGE", SECTION_PRE_DATA,
7343 defqry->data, delqry->data, NULL,
7344 plang->dobj.dependencies, plang->dobj.nDeps,
7347 /* Dump Proc Lang Comments */
7348 resetPQExpBuffer(defqry);
7349 appendPQExpBuffer(defqry, "LANGUAGE %s", qlanname);
7350 dumpComment(fout, defqry->data,
7352 plang->dobj.catId, 0, plang->dobj.dumpId);
7354 if (plang->lanpltrusted)
7355 dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
7356 qlanname, NULL, plang->dobj.name,
7358 plang->lanowner, plang->lanacl);
7362 destroyPQExpBuffer(defqry);
7363 destroyPQExpBuffer(delqry);
7367 * format_function_arguments: generate function name and argument list
7369 * This is used when we can rely on pg_get_function_arguments to format
7370 * the argument list.
7373 format_function_arguments(FuncInfo *finfo, char *funcargs)
7377 initPQExpBuffer(&fn);
7378 appendPQExpBuffer(&fn, "%s(%s)", fmtId(finfo->dobj.name), funcargs);
7383 * format_function_arguments_old: generate function name and argument list
7385 * The argument type names are qualified if needed. The function name
7386 * is never qualified.
7388 * This is used only with pre-8.4 servers, so we aren't expecting to see
7389 * VARIADIC or TABLE arguments, nor are there any defaults for arguments.
7391 * Any or all of allargtypes, argmodes, argnames may be NULL.
7394 format_function_arguments_old(FuncInfo *finfo, int nallargs,
7402 initPQExpBuffer(&fn);
7403 appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
7404 for (j = 0; j < nallargs; j++)
7408 const char *argmode;
7409 const char *argname;
7411 typid = allargtypes ? atooid(allargtypes[j]) : finfo->argtypes[j];
7412 typname = getFormattedTypeName(typid, zeroAsOpaque);
7416 switch (argmodes[j][0])
7421 case PROARGMODE_OUT:
7424 case PROARGMODE_INOUT:
7428 write_msg(NULL, "WARNING: bogus value in proargmodes array\n");
7436 argname = argnames ? argnames[j] : (char *) NULL;
7437 if (argname && argname[0] == '\0')
7440 appendPQExpBuffer(&fn, "%s%s%s%s%s",
7441 (j > 0) ? ", " : "",
7443 argname ? fmtId(argname) : "",
7448 appendPQExpBuffer(&fn, ")");
7453 * format_function_signature: generate function name and argument list
7455 * This is like format_function_arguments_old except that only a minimal
7456 * list of input argument types is generated; this is sufficient to
7457 * reference the function, but not to define it.
7459 * If honor_quotes is false then the function name is never quoted.
7460 * This is appropriate for use in TOC tags, but not in SQL commands.
7463 format_function_signature(FuncInfo *finfo, bool honor_quotes)
7468 initPQExpBuffer(&fn);
7470 appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
7472 appendPQExpBuffer(&fn, "%s(", finfo->dobj.name);
7473 for (j = 0; j < finfo->nargs; j++)
7477 typname = getFormattedTypeName(finfo->argtypes[j], zeroAsOpaque);
7479 appendPQExpBuffer(&fn, "%s%s",
7480 (j > 0) ? ", " : "",
7484 appendPQExpBuffer(&fn, ")");
7491 * dump out one function
7494 dumpFunc(Archive *fout, FuncInfo *finfo)
7501 char *funcsig; /* identity signature */
7502 char *funcfullsig; /* full signature */
7511 char *proallargtypes;
7524 char **allargtypes = NULL;
7525 char **argmodes = NULL;
7526 char **argnames = NULL;
7527 char **configitems = NULL;
7528 int nconfigitems = 0;
7531 /* Skip if not to be dumped */
7532 if (!finfo->dobj.dump || dataOnly)
7535 query = createPQExpBuffer();
7536 q = createPQExpBuffer();
7537 delqry = createPQExpBuffer();
7538 asPart = createPQExpBuffer();
7540 /* Set proper schema search path so type references list correctly */
7541 selectSourceSchema(finfo->dobj.namespace->dobj.name);
7543 /* Fetch function-specific details */
7544 if (g_fout->remoteVersion >= 80400)
7547 * In 8.4 and up we rely on pg_get_function_arguments and
7548 * pg_get_function_result instead of examining proallargtypes etc.
7550 appendPQExpBuffer(query,
7551 "SELECT proretset, prosrc, probin, "
7552 "pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
7553 "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
7554 "pg_catalog.pg_get_function_result(oid) AS funcresult, "
7555 "proiswindow, provolatile, proisstrict, prosecdef, "
7556 "proconfig, procost, prorows, "
7557 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
7558 "FROM pg_catalog.pg_proc "
7559 "WHERE oid = '%u'::pg_catalog.oid",
7560 finfo->dobj.catId.oid);
7562 else if (g_fout->remoteVersion >= 80300)
7564 appendPQExpBuffer(query,
7565 "SELECT proretset, prosrc, probin, "
7566 "proallargtypes, proargmodes, proargnames, "
7567 "false AS proiswindow, "
7568 "provolatile, proisstrict, prosecdef, "
7569 "proconfig, procost, prorows, "
7570 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
7571 "FROM pg_catalog.pg_proc "
7572 "WHERE oid = '%u'::pg_catalog.oid",
7573 finfo->dobj.catId.oid);
7575 else if (g_fout->remoteVersion >= 80100)
7577 appendPQExpBuffer(query,
7578 "SELECT proretset, prosrc, probin, "
7579 "proallargtypes, proargmodes, proargnames, "
7580 "false AS proiswindow, "
7581 "provolatile, proisstrict, prosecdef, "
7582 "null AS proconfig, 0 AS procost, 0 AS prorows, "
7583 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
7584 "FROM pg_catalog.pg_proc "
7585 "WHERE oid = '%u'::pg_catalog.oid",
7586 finfo->dobj.catId.oid);
7588 else if (g_fout->remoteVersion >= 80000)
7590 appendPQExpBuffer(query,
7591 "SELECT proretset, prosrc, probin, "
7592 "null AS proallargtypes, "
7593 "null AS proargmodes, "
7595 "false AS proiswindow, "
7596 "provolatile, proisstrict, prosecdef, "
7597 "null AS proconfig, 0 AS procost, 0 AS prorows, "
7598 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
7599 "FROM pg_catalog.pg_proc "
7600 "WHERE oid = '%u'::pg_catalog.oid",
7601 finfo->dobj.catId.oid);
7603 else if (g_fout->remoteVersion >= 70300)
7605 appendPQExpBuffer(query,
7606 "SELECT proretset, prosrc, probin, "
7607 "null AS proallargtypes, "
7608 "null AS proargmodes, "
7609 "null AS proargnames, "
7610 "false AS proiswindow, "
7611 "provolatile, proisstrict, prosecdef, "
7612 "null AS proconfig, 0 AS procost, 0 AS prorows, "
7613 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
7614 "FROM pg_catalog.pg_proc "
7615 "WHERE oid = '%u'::pg_catalog.oid",
7616 finfo->dobj.catId.oid);
7618 else if (g_fout->remoteVersion >= 70100)
7620 appendPQExpBuffer(query,
7621 "SELECT proretset, prosrc, probin, "
7622 "null AS proallargtypes, "
7623 "null AS proargmodes, "
7624 "null AS proargnames, "
7625 "false AS proiswindow, "
7626 "case when proiscachable then 'i' else 'v' end AS provolatile, "
7628 "false AS prosecdef, "
7629 "null AS proconfig, 0 AS procost, 0 AS prorows, "
7630 "(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname "
7632 "WHERE oid = '%u'::oid",
7633 finfo->dobj.catId.oid);
7637 appendPQExpBuffer(query,
7638 "SELECT proretset, prosrc, probin, "
7639 "null AS proallargtypes, "
7640 "null AS proargmodes, "
7641 "null AS proargnames, "
7642 "false AS proiswindow, "
7643 "CASE WHEN proiscachable THEN 'i' ELSE 'v' END AS provolatile, "
7644 "false AS proisstrict, "
7645 "false AS prosecdef, "
7646 "NULL AS proconfig, 0 AS procost, 0 AS prorows, "
7647 "(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname "
7649 "WHERE oid = '%u'::oid",
7650 finfo->dobj.catId.oid);
7653 res = PQexec(g_conn, query->data);
7654 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
7656 /* Expecting a single result only */
7657 ntups = PQntuples(res);
7660 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
7661 "query returned %d rows instead of one: %s\n",
7663 ntups, query->data);
7667 proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset"));
7668 prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
7669 probin = PQgetvalue(res, 0, PQfnumber(res, "probin"));
7670 if (g_fout->remoteVersion >= 80400)
7672 funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs"));
7673 funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs"));
7674 funcresult = PQgetvalue(res, 0, PQfnumber(res, "funcresult"));
7675 proallargtypes = proargmodes = proargnames = NULL;
7679 proallargtypes = PQgetvalue(res, 0, PQfnumber(res, "proallargtypes"));
7680 proargmodes = PQgetvalue(res, 0, PQfnumber(res, "proargmodes"));
7681 proargnames = PQgetvalue(res, 0, PQfnumber(res, "proargnames"));
7682 funcargs = funciargs = funcresult = NULL;
7684 proiswindow = PQgetvalue(res, 0, PQfnumber(res, "proiswindow"));
7685 provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
7686 proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
7687 prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
7688 proconfig = PQgetvalue(res, 0, PQfnumber(res, "proconfig"));
7689 procost = PQgetvalue(res, 0, PQfnumber(res, "procost"));
7690 prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
7691 lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
7694 * See backend/commands/functioncmds.c for details of how the 'AS' clause
7695 * is used. In 8.4 and up, an unused probin is NULL (here ""); previous
7696 * versions would set it to "-". There are no known cases in which prosrc
7697 * is unused, so the tests below for "-" are probably useless.
7699 if (probin[0] != '\0' && strcmp(probin, "-") != 0)
7701 appendPQExpBuffer(asPart, "AS ");
7702 appendStringLiteralAH(asPart, probin, fout);
7703 if (strcmp(prosrc, "-") != 0)
7705 appendPQExpBuffer(asPart, ", ");
7708 * where we have bin, use dollar quoting if allowed and src
7709 * contains quote or backslash; else use regular quoting.
7711 if (disable_dollar_quoting ||
7712 (strchr(prosrc, '\'') == NULL && strchr(prosrc, '\\') == NULL))
7713 appendStringLiteralAH(asPart, prosrc, fout);
7715 appendStringLiteralDQ(asPart, prosrc, NULL);
7720 if (strcmp(prosrc, "-") != 0)
7722 appendPQExpBuffer(asPart, "AS ");
7723 /* with no bin, dollar quote src unconditionally if allowed */
7724 if (disable_dollar_quoting)
7725 appendStringLiteralAH(asPart, prosrc, fout);
7727 appendStringLiteralDQ(asPart, prosrc, NULL);
7731 nallargs = finfo->nargs; /* unless we learn different from allargs */
7733 if (proallargtypes && *proallargtypes)
7737 if (!parsePGArray(proallargtypes, &allargtypes, &nitems) ||
7738 nitems < finfo->nargs)
7740 write_msg(NULL, "WARNING: could not parse proallargtypes array\n");
7749 if (proargmodes && *proargmodes)
7753 if (!parsePGArray(proargmodes, &argmodes, &nitems) ||
7756 write_msg(NULL, "WARNING: could not parse proargmodes array\n");
7763 if (proargnames && *proargnames)
7767 if (!parsePGArray(proargnames, &argnames, &nitems) ||
7770 write_msg(NULL, "WARNING: could not parse proargnames array\n");
7777 if (proconfig && *proconfig)
7779 if (!parsePGArray(proconfig, &configitems, &nconfigitems))
7781 write_msg(NULL, "WARNING: could not parse proconfig array\n");
7791 /* 8.4 or later; we rely on server-side code for most of the work */
7792 funcfullsig = format_function_arguments(finfo, funcargs);
7793 funcsig = format_function_arguments(finfo, funciargs);
7797 /* pre-8.4, do it ourselves */
7798 funcsig = format_function_arguments_old(finfo, nallargs, allargtypes,
7799 argmodes, argnames);
7800 funcfullsig = funcsig;
7803 funcsig_tag = format_function_signature(finfo, false);
7806 * DROP must be fully qualified in case same name appears in pg_catalog
7808 appendPQExpBuffer(delqry, "DROP FUNCTION %s.%s;\n",
7809 fmtId(finfo->dobj.namespace->dobj.name),
7812 appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcfullsig);
7814 appendPQExpBuffer(q, "RETURNS %s", funcresult);
7817 rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque);
7818 appendPQExpBuffer(q, "RETURNS %s%s",
7819 (proretset[0] == 't') ? "SETOF " : "",
7824 appendPQExpBuffer(q, "\n LANGUAGE %s", fmtId(lanname));
7826 if (proiswindow[0] == 't')
7827 appendPQExpBuffer(q, " WINDOW");
7829 if (provolatile[0] != PROVOLATILE_VOLATILE)
7831 if (provolatile[0] == PROVOLATILE_IMMUTABLE)
7832 appendPQExpBuffer(q, " IMMUTABLE");
7833 else if (provolatile[0] == PROVOLATILE_STABLE)
7834 appendPQExpBuffer(q, " STABLE");
7835 else if (provolatile[0] != PROVOLATILE_VOLATILE)
7837 write_msg(NULL, "unrecognized provolatile value for function \"%s\"\n",
7843 if (proisstrict[0] == 't')
7844 appendPQExpBuffer(q, " STRICT");
7846 if (prosecdef[0] == 't')
7847 appendPQExpBuffer(q, " SECURITY DEFINER");
7850 * COST and ROWS are emitted only if present and not default, so as not to
7851 * break backwards-compatibility of the dump without need. Keep this code
7852 * in sync with the defaults in functioncmds.c.
7854 if (strcmp(procost, "0") != 0)
7856 if (strcmp(lanname, "internal") == 0 || strcmp(lanname, "c") == 0)
7858 /* default cost is 1 */
7859 if (strcmp(procost, "1") != 0)
7860 appendPQExpBuffer(q, " COST %s", procost);
7864 /* default cost is 100 */
7865 if (strcmp(procost, "100") != 0)
7866 appendPQExpBuffer(q, " COST %s", procost);
7869 if (proretset[0] == 't' &&
7870 strcmp(prorows, "0") != 0 && strcmp(prorows, "1000") != 0)
7871 appendPQExpBuffer(q, " ROWS %s", prorows);
7873 for (i = 0; i < nconfigitems; i++)
7875 /* we feel free to scribble on configitems[] here */
7876 char *configitem = configitems[i];
7879 pos = strchr(configitem, '=');
7883 appendPQExpBuffer(q, "\n SET %s TO ", fmtId(configitem));
7886 * Some GUC variable names are 'LIST' type and hence must not be
7889 if (pg_strcasecmp(configitem, "DateStyle") == 0
7890 || pg_strcasecmp(configitem, "search_path") == 0)
7891 appendPQExpBuffer(q, "%s", pos);
7893 appendStringLiteralAH(q, pos, fout);
7896 appendPQExpBuffer(q, "\n %s;\n", asPart->data);
7898 ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
7900 finfo->dobj.namespace->dobj.name,
7902 finfo->rolname, false,
7903 "FUNCTION", SECTION_PRE_DATA,
7904 q->data, delqry->data, NULL,
7905 finfo->dobj.dependencies, finfo->dobj.nDeps,
7908 /* Dump Function Comments */
7909 resetPQExpBuffer(q);
7910 appendPQExpBuffer(q, "FUNCTION %s", funcsig);
7911 dumpComment(fout, q->data,
7912 finfo->dobj.namespace->dobj.name, finfo->rolname,
7913 finfo->dobj.catId, 0, finfo->dobj.dumpId);
7915 dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, "FUNCTION",
7916 funcsig, NULL, funcsig_tag,
7917 finfo->dobj.namespace->dobj.name,
7918 finfo->rolname, finfo->proacl);
7922 destroyPQExpBuffer(query);
7923 destroyPQExpBuffer(q);
7924 destroyPQExpBuffer(delqry);
7925 destroyPQExpBuffer(asPart);
7940 * Dump a user-defined cast
7943 dumpCast(Archive *fout, CastInfo *cast)
7947 PQExpBuffer castsig;
7948 FuncInfo *funcInfo = NULL;
7949 TypeInfo *sourceInfo;
7950 TypeInfo *targetInfo;
7955 if (OidIsValid(cast->castfunc))
7957 funcInfo = findFuncByOid(cast->castfunc);
7958 if (funcInfo == NULL)
7963 * As per discussion we dump casts if one or more of the underlying
7964 * objects (the conversion function and the two data types) are not
7965 * builtin AND if all of the non-builtin objects are included in the dump.
7966 * Builtin meaning, the namespace name does not start with "pg_".
7968 sourceInfo = findTypeByOid(cast->castsource);
7969 targetInfo = findTypeByOid(cast->casttarget);
7971 if (sourceInfo == NULL || targetInfo == NULL)
7975 * Skip this cast if all objects are from pg_
7977 if ((funcInfo == NULL ||
7978 strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) == 0) &&
7979 strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) == 0 &&
7980 strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) == 0)
7984 * Skip cast if function isn't from pg_ and is not to be dumped.
7987 strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
7988 !funcInfo->dobj.dump)
7992 * Same for the source type
7994 if (strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
7995 !sourceInfo->dobj.dump)
7999 * and the target type.
8001 if (strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
8002 !targetInfo->dobj.dump)
8005 /* Make sure we are in proper schema (needed for getFormattedTypeName) */
8006 selectSourceSchema("pg_catalog");
8008 defqry = createPQExpBuffer();
8009 delqry = createPQExpBuffer();
8010 castsig = createPQExpBuffer();
8012 appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n",
8013 getFormattedTypeName(cast->castsource, zeroAsNone),
8014 getFormattedTypeName(cast->casttarget, zeroAsNone));
8016 appendPQExpBuffer(defqry, "CREATE CAST (%s AS %s) ",
8017 getFormattedTypeName(cast->castsource, zeroAsNone),
8018 getFormattedTypeName(cast->casttarget, zeroAsNone));
8020 switch (cast->castmethod)
8022 case COERCION_METHOD_BINARY:
8023 appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
8025 case COERCION_METHOD_INOUT:
8026 appendPQExpBuffer(defqry, "WITH INOUT");
8028 case COERCION_METHOD_FUNCTION:
8031 * Always qualify the function name, in case it is not in
8032 * pg_catalog schema (format_function_signature won't qualify it).
8034 appendPQExpBuffer(defqry, "WITH FUNCTION %s.",
8035 fmtId(funcInfo->dobj.namespace->dobj.name));
8036 appendPQExpBuffer(defqry, "%s",
8037 format_function_signature(funcInfo, true));
8040 write_msg(NULL, "WARNING: bogus value in pg_cast.castmethod field\n");
8043 if (cast->castcontext == 'a')
8044 appendPQExpBuffer(defqry, " AS ASSIGNMENT");
8045 else if (cast->castcontext == 'i')
8046 appendPQExpBuffer(defqry, " AS IMPLICIT");
8047 appendPQExpBuffer(defqry, ";\n");
8049 appendPQExpBuffer(castsig, "CAST (%s AS %s)",
8050 getFormattedTypeName(cast->castsource, zeroAsNone),
8051 getFormattedTypeName(cast->casttarget, zeroAsNone));
8053 ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
8055 "pg_catalog", NULL, "",
8056 false, "CAST", SECTION_PRE_DATA,
8057 defqry->data, delqry->data, NULL,
8058 cast->dobj.dependencies, cast->dobj.nDeps,
8061 /* Dump Cast Comments */
8062 resetPQExpBuffer(defqry);
8063 appendPQExpBuffer(defqry, "CAST (%s AS %s)",
8064 getFormattedTypeName(cast->castsource, zeroAsNone),
8065 getFormattedTypeName(cast->casttarget, zeroAsNone));
8066 dumpComment(fout, defqry->data,
8068 cast->dobj.catId, 0, cast->dobj.dumpId);
8070 destroyPQExpBuffer(defqry);
8071 destroyPQExpBuffer(delqry);
8072 destroyPQExpBuffer(castsig);
8077 * write out a single operator definition
8080 dumpOpr(Archive *fout, OprInfo *oprinfo)
8086 PQExpBuffer details;
8111 /* Skip if not to be dumped */
8112 if (!oprinfo->dobj.dump || dataOnly)
8116 * some operators are invalid because they were the result of user
8117 * defining operators before commutators exist
8119 if (!OidIsValid(oprinfo->oprcode))
8122 query = createPQExpBuffer();
8123 q = createPQExpBuffer();
8124 delq = createPQExpBuffer();
8125 oprid = createPQExpBuffer();
8126 details = createPQExpBuffer();
8128 /* Make sure we are in proper schema so regoperator works correctly */
8129 selectSourceSchema(oprinfo->dobj.namespace->dobj.name);
8131 if (g_fout->remoteVersion >= 80300)
8133 appendPQExpBuffer(query, "SELECT oprkind, "
8134 "oprcode::pg_catalog.regprocedure, "
8135 "oprleft::pg_catalog.regtype, "
8136 "oprright::pg_catalog.regtype, "
8137 "oprcom::pg_catalog.regoperator, "
8138 "oprnegate::pg_catalog.regoperator, "
8139 "oprrest::pg_catalog.regprocedure, "
8140 "oprjoin::pg_catalog.regprocedure, "
8141 "oprcanmerge, oprcanhash "
8142 "FROM pg_catalog.pg_operator "
8143 "WHERE oid = '%u'::pg_catalog.oid",
8144 oprinfo->dobj.catId.oid);
8146 else if (g_fout->remoteVersion >= 70300)
8148 appendPQExpBuffer(query, "SELECT oprkind, "
8149 "oprcode::pg_catalog.regprocedure, "
8150 "oprleft::pg_catalog.regtype, "
8151 "oprright::pg_catalog.regtype, "
8152 "oprcom::pg_catalog.regoperator, "
8153 "oprnegate::pg_catalog.regoperator, "
8154 "oprrest::pg_catalog.regprocedure, "
8155 "oprjoin::pg_catalog.regprocedure, "
8156 "(oprlsortop != 0) AS oprcanmerge, "
8158 "FROM pg_catalog.pg_operator "
8159 "WHERE oid = '%u'::pg_catalog.oid",
8160 oprinfo->dobj.catId.oid);
8162 else if (g_fout->remoteVersion >= 70100)
8164 appendPQExpBuffer(query, "SELECT oprkind, oprcode, "
8165 "CASE WHEN oprleft = 0 THEN '-' "
8166 "ELSE format_type(oprleft, NULL) END AS oprleft, "
8167 "CASE WHEN oprright = 0 THEN '-' "
8168 "ELSE format_type(oprright, NULL) END AS oprright, "
8169 "oprcom, oprnegate, oprrest, oprjoin, "
8170 "(oprlsortop != 0) AS oprcanmerge, "
8173 "WHERE oid = '%u'::oid",
8174 oprinfo->dobj.catId.oid);
8178 appendPQExpBuffer(query, "SELECT oprkind, oprcode, "
8179 "CASE WHEN oprleft = 0 THEN '-'::name "
8180 "ELSE (SELECT typname FROM pg_type WHERE oid = oprleft) END AS oprleft, "
8181 "CASE WHEN oprright = 0 THEN '-'::name "
8182 "ELSE (SELECT typname FROM pg_type WHERE oid = oprright) END AS oprright, "
8183 "oprcom, oprnegate, oprrest, oprjoin, "
8184 "(oprlsortop != 0) AS oprcanmerge, "
8187 "WHERE oid = '%u'::oid",
8188 oprinfo->dobj.catId.oid);
8191 res = PQexec(g_conn, query->data);
8192 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
8194 /* Expecting a single result only */
8195 ntups = PQntuples(res);
8198 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
8199 "query returned %d rows instead of one: %s\n",
8201 ntups, query->data);
8205 i_oprkind = PQfnumber(res, "oprkind");
8206 i_oprcode = PQfnumber(res, "oprcode");
8207 i_oprleft = PQfnumber(res, "oprleft");
8208 i_oprright = PQfnumber(res, "oprright");
8209 i_oprcom = PQfnumber(res, "oprcom");
8210 i_oprnegate = PQfnumber(res, "oprnegate");
8211 i_oprrest = PQfnumber(res, "oprrest");
8212 i_oprjoin = PQfnumber(res, "oprjoin");
8213 i_oprcanmerge = PQfnumber(res, "oprcanmerge");
8214 i_oprcanhash = PQfnumber(res, "oprcanhash");
8216 oprkind = PQgetvalue(res, 0, i_oprkind);
8217 oprcode = PQgetvalue(res, 0, i_oprcode);
8218 oprleft = PQgetvalue(res, 0, i_oprleft);
8219 oprright = PQgetvalue(res, 0, i_oprright);
8220 oprcom = PQgetvalue(res, 0, i_oprcom);
8221 oprnegate = PQgetvalue(res, 0, i_oprnegate);
8222 oprrest = PQgetvalue(res, 0, i_oprrest);
8223 oprjoin = PQgetvalue(res, 0, i_oprjoin);
8224 oprcanmerge = PQgetvalue(res, 0, i_oprcanmerge);
8225 oprcanhash = PQgetvalue(res, 0, i_oprcanhash);
8227 appendPQExpBuffer(details, " PROCEDURE = %s",
8228 convertRegProcReference(oprcode));
8230 appendPQExpBuffer(oprid, "%s (",
8231 oprinfo->dobj.name);
8234 * right unary means there's a left arg and left unary means there's a
8237 if (strcmp(oprkind, "r") == 0 ||
8238 strcmp(oprkind, "b") == 0)
8240 if (g_fout->remoteVersion >= 70100)
8243 name = fmtId(oprleft);
8244 appendPQExpBuffer(details, ",\n LEFTARG = %s", name);
8245 appendPQExpBuffer(oprid, "%s", name);
8248 appendPQExpBuffer(oprid, "NONE");
8250 if (strcmp(oprkind, "l") == 0 ||
8251 strcmp(oprkind, "b") == 0)
8253 if (g_fout->remoteVersion >= 70100)
8256 name = fmtId(oprright);
8257 appendPQExpBuffer(details, ",\n RIGHTARG = %s", name);
8258 appendPQExpBuffer(oprid, ", %s)", name);
8261 appendPQExpBuffer(oprid, ", NONE)");
8263 name = convertOperatorReference(oprcom);
8265 appendPQExpBuffer(details, ",\n COMMUTATOR = %s", name);
8267 name = convertOperatorReference(oprnegate);
8269 appendPQExpBuffer(details, ",\n NEGATOR = %s", name);
8271 if (strcmp(oprcanmerge, "t") == 0)
8272 appendPQExpBuffer(details, ",\n MERGES");
8274 if (strcmp(oprcanhash, "t") == 0)
8275 appendPQExpBuffer(details, ",\n HASHES");
8277 name = convertRegProcReference(oprrest);
8279 appendPQExpBuffer(details, ",\n RESTRICT = %s", name);
8281 name = convertRegProcReference(oprjoin);
8283 appendPQExpBuffer(details, ",\n JOIN = %s", name);
8286 * DROP must be fully qualified in case same name appears in pg_catalog
8288 appendPQExpBuffer(delq, "DROP OPERATOR %s.%s;\n",
8289 fmtId(oprinfo->dobj.namespace->dobj.name),
8292 appendPQExpBuffer(q, "CREATE OPERATOR %s (\n%s\n);\n",
8293 oprinfo->dobj.name, details->data);
8295 ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId,
8297 oprinfo->dobj.namespace->dobj.name,
8300 false, "OPERATOR", SECTION_PRE_DATA,
8301 q->data, delq->data, NULL,
8302 oprinfo->dobj.dependencies, oprinfo->dobj.nDeps,
8305 /* Dump Operator Comments */
8306 resetPQExpBuffer(q);
8307 appendPQExpBuffer(q, "OPERATOR %s", oprid->data);
8308 dumpComment(fout, q->data,
8309 oprinfo->dobj.namespace->dobj.name, oprinfo->rolname,
8310 oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId);
8314 destroyPQExpBuffer(query);
8315 destroyPQExpBuffer(q);
8316 destroyPQExpBuffer(delq);
8317 destroyPQExpBuffer(oprid);
8318 destroyPQExpBuffer(details);
8322 * Convert a function reference obtained from pg_operator
8324 * Returns what to print, or NULL if function references is InvalidOid
8326 * In 7.3 the input is a REGPROCEDURE display; we have to strip the
8327 * argument-types part. In prior versions, the input is a REGPROC display.
8330 convertRegProcReference(const char *proc)
8332 /* In all cases "-" means a null reference */
8333 if (strcmp(proc, "-") == 0)
8336 if (g_fout->remoteVersion >= 70300)
8342 name = strdup(proc);
8343 /* find non-double-quoted left paren */
8345 for (paren = name; *paren; paren++)
8347 if (*paren == '(' && !inquote)
8358 /* REGPROC before 7.3 does not quote its result */
8363 * Convert an operator cross-reference obtained from pg_operator
8365 * Returns what to print, or NULL to print nothing
8367 * In 7.3 and up the input is a REGOPERATOR display; we have to strip the
8368 * argument-types part, and add OPERATOR() decoration if the name is
8369 * schema-qualified. In older versions, the input is just a numeric OID,
8370 * which we search our operator list for.
8373 convertOperatorReference(const char *opr)
8377 /* In all cases "0" means a null reference */
8378 if (strcmp(opr, "0") == 0)
8381 if (g_fout->remoteVersion >= 70300)
8390 /* find non-double-quoted left paren, and check for non-quoted dot */
8393 for (ptr = name; *ptr; ptr++)
8397 else if (*ptr == '.' && !inquote)
8399 else if (*ptr == '(' && !inquote)
8405 /* If not schema-qualified, don't need to add OPERATOR() */
8408 oname = malloc(strlen(name) + 11);
8409 sprintf(oname, "OPERATOR(%s)", name);
8414 oprInfo = findOprByOid(atooid(opr));
8415 if (oprInfo == NULL)
8417 write_msg(NULL, "WARNING: could not find operator with OID %s\n",
8421 return oprInfo->dobj.name;
8425 * Convert a function OID obtained from pg_ts_parser or pg_ts_template
8427 * It is sufficient to use REGPROC rather than REGPROCEDURE, since the
8428 * argument lists of these functions are predetermined. Note that the
8429 * caller should ensure we are in the proper schema, because the results
8430 * are search path dependent!
8433 convertTSFunction(Oid funcOid)
8440 snprintf(query, sizeof(query),
8441 "SELECT '%u'::pg_catalog.regproc", funcOid);
8442 res = PQexec(g_conn, query);
8443 check_sql_result(res, g_conn, query, PGRES_TUPLES_OK);
8445 ntups = PQntuples(res);
8448 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
8449 "query returned %d rows instead of one: %s\n",
8455 result = strdup(PQgetvalue(res, 0, 0));
8465 * write out a single operator class definition
8468 dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
8500 /* Skip if not to be dumped */
8501 if (!opcinfo->dobj.dump || dataOnly)
8505 * XXX currently we do not implement dumping of operator classes from
8506 * pre-7.3 databases. This could be done but it seems not worth the
8509 if (g_fout->remoteVersion < 70300)
8512 query = createPQExpBuffer();
8513 q = createPQExpBuffer();
8514 delq = createPQExpBuffer();
8516 /* Make sure we are in proper schema so regoperator works correctly */
8517 selectSourceSchema(opcinfo->dobj.namespace->dobj.name);
8519 /* Get additional fields from the pg_opclass row */
8520 if (g_fout->remoteVersion >= 80300)
8522 appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
8523 "opckeytype::pg_catalog.regtype, "
8525 "opfname AS opcfamily, "
8526 "nspname AS opcfamilynsp, "
8527 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
8528 "FROM pg_catalog.pg_opclass c "
8529 "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
8530 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
8531 "WHERE c.oid = '%u'::pg_catalog.oid",
8532 opcinfo->dobj.catId.oid);
8536 appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
8537 "opckeytype::pg_catalog.regtype, "
8539 "NULL AS opcfamily, "
8540 "NULL AS opcfamilynsp, "
8541 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
8542 "FROM pg_catalog.pg_opclass "
8543 "WHERE oid = '%u'::pg_catalog.oid",
8544 opcinfo->dobj.catId.oid);
8547 res = PQexec(g_conn, query->data);
8548 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
8550 /* Expecting a single result only */
8551 ntups = PQntuples(res);
8554 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
8555 "query returned %d rows instead of one: %s\n",
8557 ntups, query->data);
8561 i_opcintype = PQfnumber(res, "opcintype");
8562 i_opckeytype = PQfnumber(res, "opckeytype");
8563 i_opcdefault = PQfnumber(res, "opcdefault");
8564 i_opcfamily = PQfnumber(res, "opcfamily");
8565 i_opcfamilynsp = PQfnumber(res, "opcfamilynsp");
8566 i_amname = PQfnumber(res, "amname");
8568 opcintype = PQgetvalue(res, 0, i_opcintype);
8569 opckeytype = PQgetvalue(res, 0, i_opckeytype);
8570 opcdefault = PQgetvalue(res, 0, i_opcdefault);
8571 opcfamily = PQgetvalue(res, 0, i_opcfamily);
8572 opcfamilynsp = PQgetvalue(res, 0, i_opcfamilynsp);
8573 /* amname will still be needed after we PQclear res */
8574 amname = strdup(PQgetvalue(res, 0, i_amname));
8577 * DROP must be fully qualified in case same name appears in pg_catalog
8579 appendPQExpBuffer(delq, "DROP OPERATOR CLASS %s",
8580 fmtId(opcinfo->dobj.namespace->dobj.name));
8581 appendPQExpBuffer(delq, ".%s",
8582 fmtId(opcinfo->dobj.name));
8583 appendPQExpBuffer(delq, " USING %s;\n",
8586 /* Build the fixed portion of the CREATE command */
8587 appendPQExpBuffer(q, "CREATE OPERATOR CLASS %s\n ",
8588 fmtId(opcinfo->dobj.name));
8589 if (strcmp(opcdefault, "t") == 0)
8590 appendPQExpBuffer(q, "DEFAULT ");
8591 appendPQExpBuffer(q, "FOR TYPE %s USING %s",
8594 if (strlen(opcfamily) > 0 &&
8595 (strcmp(opcfamily, opcinfo->dobj.name) != 0 ||
8596 strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0))
8598 appendPQExpBuffer(q, " FAMILY ");
8599 if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
8600 appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
8601 appendPQExpBuffer(q, "%s", fmtId(opcfamily));
8603 appendPQExpBuffer(q, " AS\n ");
8607 if (strcmp(opckeytype, "-") != 0)
8609 appendPQExpBuffer(q, "STORAGE %s",
8617 * Now fetch and print the OPERATOR entries (pg_amop rows).
8619 resetPQExpBuffer(query);
8621 if (g_fout->remoteVersion >= 80400)
8624 * Print only those opfamily members that are tied to the opclass by
8625 * pg_depend entries.
8627 * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
8628 * an older server's opclass in which it is used. This is to avoid
8629 * hard-to-detect breakage if a newer pg_dump is used to dump from an
8630 * older server and then reload into that old version. This can go
8631 * away once 8.3 is so old as to not be of interest to anyone.
8633 appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
8634 "amopopr::pg_catalog.regoperator "
8635 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
8636 "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
8637 "AND refobjid = '%u'::pg_catalog.oid "
8638 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
8639 "AND objid = ao.oid "
8640 "ORDER BY amopstrategy",
8641 opcinfo->dobj.catId.oid);
8643 else if (g_fout->remoteVersion >= 80300)
8646 * Print only those opfamily members that are tied to the opclass by
8647 * pg_depend entries.
8649 appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
8650 "amopopr::pg_catalog.regoperator "
8651 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
8652 "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
8653 "AND refobjid = '%u'::pg_catalog.oid "
8654 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
8655 "AND objid = ao.oid "
8656 "ORDER BY amopstrategy",
8657 opcinfo->dobj.catId.oid);
8661 appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
8662 "amopopr::pg_catalog.regoperator "
8663 "FROM pg_catalog.pg_amop "
8664 "WHERE amopclaid = '%u'::pg_catalog.oid "
8665 "ORDER BY amopstrategy",
8666 opcinfo->dobj.catId.oid);
8669 res = PQexec(g_conn, query->data);
8670 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
8672 ntups = PQntuples(res);
8674 i_amopstrategy = PQfnumber(res, "amopstrategy");
8675 i_amopreqcheck = PQfnumber(res, "amopreqcheck");
8676 i_amopopr = PQfnumber(res, "amopopr");
8678 for (i = 0; i < ntups; i++)
8680 amopstrategy = PQgetvalue(res, i, i_amopstrategy);
8681 amopreqcheck = PQgetvalue(res, i, i_amopreqcheck);
8682 amopopr = PQgetvalue(res, i, i_amopopr);
8685 appendPQExpBuffer(q, " ,\n ");
8687 appendPQExpBuffer(q, "OPERATOR %s %s",
8688 amopstrategy, amopopr);
8689 if (strcmp(amopreqcheck, "t") == 0)
8690 appendPQExpBuffer(q, " RECHECK");
8698 * Now fetch and print the FUNCTION entries (pg_amproc rows).
8700 resetPQExpBuffer(query);
8702 if (g_fout->remoteVersion >= 80300)
8705 * Print only those opfamily members that are tied to the opclass by
8706 * pg_depend entries.
8708 appendPQExpBuffer(query, "SELECT amprocnum, "
8709 "amproc::pg_catalog.regprocedure "
8710 "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
8711 "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
8712 "AND refobjid = '%u'::pg_catalog.oid "
8713 "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
8714 "AND objid = ap.oid "
8715 "ORDER BY amprocnum",
8716 opcinfo->dobj.catId.oid);
8720 appendPQExpBuffer(query, "SELECT amprocnum, "
8721 "amproc::pg_catalog.regprocedure "
8722 "FROM pg_catalog.pg_amproc "
8723 "WHERE amopclaid = '%u'::pg_catalog.oid "
8724 "ORDER BY amprocnum",
8725 opcinfo->dobj.catId.oid);
8728 res = PQexec(g_conn, query->data);
8729 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
8731 ntups = PQntuples(res);
8733 i_amprocnum = PQfnumber(res, "amprocnum");
8734 i_amproc = PQfnumber(res, "amproc");
8736 for (i = 0; i < ntups; i++)
8738 amprocnum = PQgetvalue(res, i, i_amprocnum);
8739 amproc = PQgetvalue(res, i, i_amproc);
8742 appendPQExpBuffer(q, " ,\n ");
8744 appendPQExpBuffer(q, "FUNCTION %s %s",
8752 appendPQExpBuffer(q, ";\n");
8754 ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
8756 opcinfo->dobj.namespace->dobj.name,
8759 false, "OPERATOR CLASS", SECTION_PRE_DATA,
8760 q->data, delq->data, NULL,
8761 opcinfo->dobj.dependencies, opcinfo->dobj.nDeps,
8764 /* Dump Operator Class Comments */
8765 resetPQExpBuffer(q);
8766 appendPQExpBuffer(q, "OPERATOR CLASS %s",
8767 fmtId(opcinfo->dobj.name));
8768 appendPQExpBuffer(q, " USING %s",
8770 dumpComment(fout, q->data,
8771 NULL, opcinfo->rolname,
8772 opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId);
8775 destroyPQExpBuffer(query);
8776 destroyPQExpBuffer(q);
8777 destroyPQExpBuffer(delq);
8782 * write out a single operator family definition
8785 dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
8792 PGresult *res_procs;
8800 int i_amproclefttype;
8801 int i_amprocrighttype;
8808 char *amproclefttype;
8809 char *amprocrighttype;
8813 /* Skip if not to be dumped */
8814 if (!opfinfo->dobj.dump || dataOnly)
8818 * We want to dump the opfamily only if (1) it contains "loose" operators
8819 * or functions, or (2) it contains an opclass with a different name or
8820 * owner. Otherwise it's sufficient to let it be created during creation
8821 * of the contained opclass, and not dumping it improves portability of
8822 * the dump. Since we have to fetch the loose operators/funcs anyway, do
8826 query = createPQExpBuffer();
8827 q = createPQExpBuffer();
8828 delq = createPQExpBuffer();
8830 /* Make sure we are in proper schema so regoperator works correctly */
8831 selectSourceSchema(opfinfo->dobj.namespace->dobj.name);
8834 * Fetch only those opfamily members that are tied directly to the
8835 * opfamily by pg_depend entries.
8837 if (g_fout->remoteVersion >= 80400)
8840 * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
8841 * an older server's opclass in which it is used. This is to avoid
8842 * hard-to-detect breakage if a newer pg_dump is used to dump from an
8843 * older server and then reload into that old version. This can go
8844 * away once 8.3 is so old as to not be of interest to anyone.
8846 appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
8847 "amopopr::pg_catalog.regoperator "
8848 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
8849 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8850 "AND refobjid = '%u'::pg_catalog.oid "
8851 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
8852 "AND objid = ao.oid "
8853 "ORDER BY amopstrategy",
8854 opfinfo->dobj.catId.oid);
8858 appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
8859 "amopopr::pg_catalog.regoperator "
8860 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
8861 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8862 "AND refobjid = '%u'::pg_catalog.oid "
8863 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
8864 "AND objid = ao.oid "
8865 "ORDER BY amopstrategy",
8866 opfinfo->dobj.catId.oid);
8869 res_ops = PQexec(g_conn, query->data);
8870 check_sql_result(res_ops, g_conn, query->data, PGRES_TUPLES_OK);
8872 resetPQExpBuffer(query);
8874 appendPQExpBuffer(query, "SELECT amprocnum, "
8875 "amproc::pg_catalog.regprocedure, "
8876 "amproclefttype::pg_catalog.regtype, "
8877 "amprocrighttype::pg_catalog.regtype "
8878 "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
8879 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8880 "AND refobjid = '%u'::pg_catalog.oid "
8881 "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
8882 "AND objid = ap.oid "
8883 "ORDER BY amprocnum",
8884 opfinfo->dobj.catId.oid);
8886 res_procs = PQexec(g_conn, query->data);
8887 check_sql_result(res_procs, g_conn, query->data, PGRES_TUPLES_OK);
8889 if (PQntuples(res_ops) == 0 && PQntuples(res_procs) == 0)
8891 /* No loose members, so check contained opclasses */
8892 resetPQExpBuffer(query);
8894 appendPQExpBuffer(query, "SELECT 1 "
8895 "FROM pg_catalog.pg_opclass c, pg_catalog.pg_opfamily f, pg_catalog.pg_depend "
8896 "WHERE f.oid = '%u'::pg_catalog.oid "
8897 "AND refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8898 "AND refobjid = f.oid "
8899 "AND classid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
8900 "AND objid = c.oid "
8901 "AND (opcname != opfname OR opcnamespace != opfnamespace OR opcowner != opfowner) "
8903 opfinfo->dobj.catId.oid);
8905 res = PQexec(g_conn, query->data);
8906 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
8908 if (PQntuples(res) == 0)
8910 /* no need to dump it, so bail out */
8914 destroyPQExpBuffer(query);
8915 destroyPQExpBuffer(q);
8916 destroyPQExpBuffer(delq);
8923 /* Get additional fields from the pg_opfamily row */
8924 resetPQExpBuffer(query);
8926 appendPQExpBuffer(query, "SELECT "
8927 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opfmethod) AS amname "
8928 "FROM pg_catalog.pg_opfamily "
8929 "WHERE oid = '%u'::pg_catalog.oid",
8930 opfinfo->dobj.catId.oid);
8932 res = PQexec(g_conn, query->data);
8933 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
8935 /* Expecting a single result only */
8936 ntups = PQntuples(res);
8939 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
8940 "query returned %d rows instead of one: %s\n",
8942 ntups, query->data);
8946 i_amname = PQfnumber(res, "amname");
8948 /* amname will still be needed after we PQclear res */
8949 amname = strdup(PQgetvalue(res, 0, i_amname));
8952 * DROP must be fully qualified in case same name appears in pg_catalog
8954 appendPQExpBuffer(delq, "DROP OPERATOR FAMILY %s",
8955 fmtId(opfinfo->dobj.namespace->dobj.name));
8956 appendPQExpBuffer(delq, ".%s",
8957 fmtId(opfinfo->dobj.name));
8958 appendPQExpBuffer(delq, " USING %s;\n",
8961 /* Build the fixed portion of the CREATE command */
8962 appendPQExpBuffer(q, "CREATE OPERATOR FAMILY %s",
8963 fmtId(opfinfo->dobj.name));
8964 appendPQExpBuffer(q, " USING %s;\n",
8969 /* Do we need an ALTER to add loose members? */
8970 if (PQntuples(res_ops) > 0 || PQntuples(res_procs) > 0)
8972 appendPQExpBuffer(q, "ALTER OPERATOR FAMILY %s",
8973 fmtId(opfinfo->dobj.name));
8974 appendPQExpBuffer(q, " USING %s ADD\n ",
8980 * Now fetch and print the OPERATOR entries (pg_amop rows).
8982 ntups = PQntuples(res_ops);
8984 i_amopstrategy = PQfnumber(res_ops, "amopstrategy");
8985 i_amopreqcheck = PQfnumber(res_ops, "amopreqcheck");
8986 i_amopopr = PQfnumber(res_ops, "amopopr");
8988 for (i = 0; i < ntups; i++)
8990 amopstrategy = PQgetvalue(res_ops, i, i_amopstrategy);
8991 amopreqcheck = PQgetvalue(res_ops, i, i_amopreqcheck);
8992 amopopr = PQgetvalue(res_ops, i, i_amopopr);
8995 appendPQExpBuffer(q, " ,\n ");
8997 appendPQExpBuffer(q, "OPERATOR %s %s",
8998 amopstrategy, amopopr);
8999 if (strcmp(amopreqcheck, "t") == 0)
9000 appendPQExpBuffer(q, " RECHECK");
9006 * Now fetch and print the FUNCTION entries (pg_amproc rows).
9008 ntups = PQntuples(res_procs);
9010 i_amprocnum = PQfnumber(res_procs, "amprocnum");
9011 i_amproc = PQfnumber(res_procs, "amproc");
9012 i_amproclefttype = PQfnumber(res_procs, "amproclefttype");
9013 i_amprocrighttype = PQfnumber(res_procs, "amprocrighttype");
9015 for (i = 0; i < ntups; i++)
9017 amprocnum = PQgetvalue(res_procs, i, i_amprocnum);
9018 amproc = PQgetvalue(res_procs, i, i_amproc);
9019 amproclefttype = PQgetvalue(res_procs, i, i_amproclefttype);
9020 amprocrighttype = PQgetvalue(res_procs, i, i_amprocrighttype);
9023 appendPQExpBuffer(q, " ,\n ");
9025 appendPQExpBuffer(q, "FUNCTION %s (%s, %s) %s",
9026 amprocnum, amproclefttype, amprocrighttype,
9032 appendPQExpBuffer(q, ";\n");
9035 ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
9037 opfinfo->dobj.namespace->dobj.name,
9040 false, "OPERATOR FAMILY", SECTION_PRE_DATA,
9041 q->data, delq->data, NULL,
9042 opfinfo->dobj.dependencies, opfinfo->dobj.nDeps,
9045 /* Dump Operator Family Comments */
9046 resetPQExpBuffer(q);
9047 appendPQExpBuffer(q, "OPERATOR FAMILY %s",
9048 fmtId(opfinfo->dobj.name));
9049 appendPQExpBuffer(q, " USING %s",
9051 dumpComment(fout, q->data,
9052 NULL, opfinfo->rolname,
9053 opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId);
9058 destroyPQExpBuffer(query);
9059 destroyPQExpBuffer(q);
9060 destroyPQExpBuffer(delq);
9065 * write out a single conversion definition
9068 dumpConversion(Archive *fout, ConvInfo *convinfo)
9073 PQExpBuffer details;
9077 int i_conforencoding;
9078 int i_contoencoding;
9081 const char *conname;
9082 const char *conforencoding;
9083 const char *contoencoding;
9084 const char *conproc;
9087 /* Skip if not to be dumped */
9088 if (!convinfo->dobj.dump || dataOnly)
9091 query = createPQExpBuffer();
9092 q = createPQExpBuffer();
9093 delq = createPQExpBuffer();
9094 details = createPQExpBuffer();
9096 /* Make sure we are in proper schema */
9097 selectSourceSchema(convinfo->dobj.namespace->dobj.name);
9099 /* Get conversion-specific details */
9100 appendPQExpBuffer(query, "SELECT conname, "
9101 "pg_catalog.pg_encoding_to_char(conforencoding) AS conforencoding, "
9102 "pg_catalog.pg_encoding_to_char(contoencoding) AS contoencoding, "
9103 "conproc, condefault "
9104 "FROM pg_catalog.pg_conversion c "
9105 "WHERE c.oid = '%u'::pg_catalog.oid",
9106 convinfo->dobj.catId.oid);
9108 res = PQexec(g_conn, query->data);
9109 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9111 /* Expecting a single result only */
9112 ntups = PQntuples(res);
9115 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
9116 "query returned %d rows instead of one: %s\n",
9118 ntups, query->data);
9122 i_conname = PQfnumber(res, "conname");
9123 i_conforencoding = PQfnumber(res, "conforencoding");
9124 i_contoencoding = PQfnumber(res, "contoencoding");
9125 i_conproc = PQfnumber(res, "conproc");
9126 i_condefault = PQfnumber(res, "condefault");
9128 conname = PQgetvalue(res, 0, i_conname);
9129 conforencoding = PQgetvalue(res, 0, i_conforencoding);
9130 contoencoding = PQgetvalue(res, 0, i_contoencoding);
9131 conproc = PQgetvalue(res, 0, i_conproc);
9132 condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't');
9135 * DROP must be fully qualified in case same name appears in pg_catalog
9137 appendPQExpBuffer(delq, "DROP CONVERSION %s",
9138 fmtId(convinfo->dobj.namespace->dobj.name));
9139 appendPQExpBuffer(delq, ".%s;\n",
9140 fmtId(convinfo->dobj.name));
9142 appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
9143 (condefault) ? "DEFAULT " : "",
9144 fmtId(convinfo->dobj.name));
9145 appendStringLiteralAH(q, conforencoding, fout);
9146 appendPQExpBuffer(q, " TO ");
9147 appendStringLiteralAH(q, contoencoding, fout);
9148 /* regproc is automatically quoted in 7.3 and above */
9149 appendPQExpBuffer(q, " FROM %s;\n", conproc);
9151 ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId,
9152 convinfo->dobj.name,
9153 convinfo->dobj.namespace->dobj.name,
9156 false, "CONVERSION", SECTION_PRE_DATA,
9157 q->data, delq->data, NULL,
9158 convinfo->dobj.dependencies, convinfo->dobj.nDeps,
9161 /* Dump Conversion Comments */
9162 resetPQExpBuffer(q);
9163 appendPQExpBuffer(q, "CONVERSION %s", fmtId(convinfo->dobj.name));
9164 dumpComment(fout, q->data,
9165 convinfo->dobj.namespace->dobj.name, convinfo->rolname,
9166 convinfo->dobj.catId, 0, convinfo->dobj.dumpId);
9170 destroyPQExpBuffer(query);
9171 destroyPQExpBuffer(q);
9172 destroyPQExpBuffer(delq);
9173 destroyPQExpBuffer(details);
9177 * format_aggregate_signature: generate aggregate name and argument list
9179 * The argument type names are qualified if needed. The aggregate name
9180 * is never qualified.
9183 format_aggregate_signature(AggInfo *agginfo, Archive *fout, bool honor_quotes)
9185 PQExpBufferData buf;
9188 initPQExpBuffer(&buf);
9190 appendPQExpBuffer(&buf, "%s",
9191 fmtId(agginfo->aggfn.dobj.name));
9193 appendPQExpBuffer(&buf, "%s", agginfo->aggfn.dobj.name);
9195 if (agginfo->aggfn.nargs == 0)
9196 appendPQExpBuffer(&buf, "(*)");
9199 appendPQExpBuffer(&buf, "(");
9200 for (j = 0; j < agginfo->aggfn.nargs; j++)
9204 typname = getFormattedTypeName(agginfo->aggfn.argtypes[j], zeroAsOpaque);
9206 appendPQExpBuffer(&buf, "%s%s",
9207 (j > 0) ? ", " : "",
9211 appendPQExpBuffer(&buf, ")");
9218 * write out a single aggregate definition
9221 dumpAgg(Archive *fout, AggInfo *agginfo)
9226 PQExpBuffer details;
9237 const char *aggtransfn;
9238 const char *aggfinalfn;
9239 const char *aggsortop;
9240 const char *aggtranstype;
9241 const char *agginitval;
9244 /* Skip if not to be dumped */
9245 if (!agginfo->aggfn.dobj.dump || dataOnly)
9248 query = createPQExpBuffer();
9249 q = createPQExpBuffer();
9250 delq = createPQExpBuffer();
9251 details = createPQExpBuffer();
9253 /* Make sure we are in proper schema */
9254 selectSourceSchema(agginfo->aggfn.dobj.namespace->dobj.name);
9256 /* Get aggregate-specific details */
9257 if (g_fout->remoteVersion >= 80100)
9259 appendPQExpBuffer(query, "SELECT aggtransfn, "
9260 "aggfinalfn, aggtranstype::pg_catalog.regtype, "
9261 "aggsortop::pg_catalog.regoperator, "
9263 "'t'::boolean AS convertok "
9264 "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
9265 "WHERE a.aggfnoid = p.oid "
9266 "AND p.oid = '%u'::pg_catalog.oid",
9267 agginfo->aggfn.dobj.catId.oid);
9269 else if (g_fout->remoteVersion >= 70300)
9271 appendPQExpBuffer(query, "SELECT aggtransfn, "
9272 "aggfinalfn, aggtranstype::pg_catalog.regtype, "
9275 "'t'::boolean AS convertok "
9276 "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
9277 "WHERE a.aggfnoid = p.oid "
9278 "AND p.oid = '%u'::pg_catalog.oid",
9279 agginfo->aggfn.dobj.catId.oid);
9281 else if (g_fout->remoteVersion >= 70100)
9283 appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
9284 "format_type(aggtranstype, NULL) AS aggtranstype, "
9287 "'t'::boolean AS convertok "
9288 "FROM pg_aggregate "
9289 "WHERE oid = '%u'::oid",
9290 agginfo->aggfn.dobj.catId.oid);
9294 appendPQExpBuffer(query, "SELECT aggtransfn1 AS aggtransfn, "
9296 "(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, "
9298 "agginitval1 AS agginitval, "
9299 "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) AS convertok "
9300 "FROM pg_aggregate "
9301 "WHERE oid = '%u'::oid",
9302 agginfo->aggfn.dobj.catId.oid);
9305 res = PQexec(g_conn, query->data);
9306 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9308 /* Expecting a single result only */
9309 ntups = PQntuples(res);
9312 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
9313 "query returned %d rows instead of one: %s\n",
9315 ntups, query->data);
9319 i_aggtransfn = PQfnumber(res, "aggtransfn");
9320 i_aggfinalfn = PQfnumber(res, "aggfinalfn");
9321 i_aggsortop = PQfnumber(res, "aggsortop");
9322 i_aggtranstype = PQfnumber(res, "aggtranstype");
9323 i_agginitval = PQfnumber(res, "agginitval");
9324 i_convertok = PQfnumber(res, "convertok");
9326 aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
9327 aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
9328 aggsortop = PQgetvalue(res, 0, i_aggsortop);
9329 aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
9330 agginitval = PQgetvalue(res, 0, i_agginitval);
9331 convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
9333 aggsig = format_aggregate_signature(agginfo, fout, true);
9334 aggsig_tag = format_aggregate_signature(agginfo, fout, false);
9338 write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
9343 if (g_fout->remoteVersion >= 70300)
9345 /* If using 7.3's regproc or regtype, data is already quoted */
9346 appendPQExpBuffer(details, " SFUNC = %s,\n STYPE = %s",
9350 else if (g_fout->remoteVersion >= 70100)
9352 /* format_type quotes, regproc does not */
9353 appendPQExpBuffer(details, " SFUNC = %s,\n STYPE = %s",
9359 /* need quotes all around */
9360 appendPQExpBuffer(details, " SFUNC = %s,\n",
9362 appendPQExpBuffer(details, " STYPE = %s",
9363 fmtId(aggtranstype));
9366 if (!PQgetisnull(res, 0, i_agginitval))
9368 appendPQExpBuffer(details, ",\n INITCOND = ");
9369 appendStringLiteralAH(details, agginitval, fout);
9372 if (strcmp(aggfinalfn, "-") != 0)
9374 appendPQExpBuffer(details, ",\n FINALFUNC = %s",
9378 aggsortop = convertOperatorReference(aggsortop);
9381 appendPQExpBuffer(details, ",\n SORTOP = %s",
9386 * DROP must be fully qualified in case same name appears in pg_catalog
9388 appendPQExpBuffer(delq, "DROP AGGREGATE %s.%s;\n",
9389 fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
9392 appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n",
9393 aggsig, details->data);
9395 ArchiveEntry(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
9397 agginfo->aggfn.dobj.namespace->dobj.name,
9399 agginfo->aggfn.rolname,
9400 false, "AGGREGATE", SECTION_PRE_DATA,
9401 q->data, delq->data, NULL,
9402 agginfo->aggfn.dobj.dependencies, agginfo->aggfn.dobj.nDeps,
9405 /* Dump Aggregate Comments */
9406 resetPQExpBuffer(q);
9407 appendPQExpBuffer(q, "AGGREGATE %s", aggsig);
9408 dumpComment(fout, q->data,
9409 agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
9410 agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
9413 * Since there is no GRANT ON AGGREGATE syntax, we have to make the ACL
9414 * command look like a function's GRANT; in particular this affects the
9415 * syntax for zero-argument aggregates.
9420 aggsig = format_function_signature(&agginfo->aggfn, true);
9421 aggsig_tag = format_function_signature(&agginfo->aggfn, false);
9423 dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
9425 aggsig, NULL, aggsig_tag,
9426 agginfo->aggfn.dobj.namespace->dobj.name,
9427 agginfo->aggfn.rolname, agginfo->aggfn.proacl);
9434 destroyPQExpBuffer(query);
9435 destroyPQExpBuffer(q);
9436 destroyPQExpBuffer(delq);
9437 destroyPQExpBuffer(details);
9442 * write out a single text search parser
9445 dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
9450 /* Skip if not to be dumped */
9451 if (!prsinfo->dobj.dump || dataOnly)
9454 q = createPQExpBuffer();
9455 delq = createPQExpBuffer();
9457 /* Make sure we are in proper schema */
9458 selectSourceSchema(prsinfo->dobj.namespace->dobj.name);
9460 appendPQExpBuffer(q, "CREATE TEXT SEARCH PARSER %s (\n",
9461 fmtId(prsinfo->dobj.name));
9463 appendPQExpBuffer(q, " START = %s,\n",
9464 convertTSFunction(prsinfo->prsstart));
9465 appendPQExpBuffer(q, " GETTOKEN = %s,\n",
9466 convertTSFunction(prsinfo->prstoken));
9467 appendPQExpBuffer(q, " END = %s,\n",
9468 convertTSFunction(prsinfo->prsend));
9469 if (prsinfo->prsheadline != InvalidOid)
9470 appendPQExpBuffer(q, " HEADLINE = %s,\n",
9471 convertTSFunction(prsinfo->prsheadline));
9472 appendPQExpBuffer(q, " LEXTYPES = %s );\n",
9473 convertTSFunction(prsinfo->prslextype));
9476 * DROP must be fully qualified in case same name appears in pg_catalog
9478 appendPQExpBuffer(delq, "DROP TEXT SEARCH PARSER %s",
9479 fmtId(prsinfo->dobj.namespace->dobj.name));
9480 appendPQExpBuffer(delq, ".%s;\n",
9481 fmtId(prsinfo->dobj.name));
9483 ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId,
9485 prsinfo->dobj.namespace->dobj.name,
9488 false, "TEXT SEARCH PARSER", SECTION_PRE_DATA,
9489 q->data, delq->data, NULL,
9490 prsinfo->dobj.dependencies, prsinfo->dobj.nDeps,
9493 /* Dump Parser Comments */
9494 resetPQExpBuffer(q);
9495 appendPQExpBuffer(q, "TEXT SEARCH PARSER %s",
9496 fmtId(prsinfo->dobj.name));
9497 dumpComment(fout, q->data,
9499 prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId);
9501 destroyPQExpBuffer(q);
9502 destroyPQExpBuffer(delq);
9507 * write out a single text search dictionary
9510 dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
9520 /* Skip if not to be dumped */
9521 if (!dictinfo->dobj.dump || dataOnly)
9524 q = createPQExpBuffer();
9525 delq = createPQExpBuffer();
9526 query = createPQExpBuffer();
9528 /* Fetch name and namespace of the dictionary's template */
9529 selectSourceSchema("pg_catalog");
9530 appendPQExpBuffer(query, "SELECT nspname, tmplname "
9531 "FROM pg_ts_template p, pg_namespace n "
9532 "WHERE p.oid = '%u' AND n.oid = tmplnamespace",
9533 dictinfo->dicttemplate);
9534 res = PQexec(g_conn, query->data);
9535 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9536 ntups = PQntuples(res);
9539 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
9540 "query returned %d rows instead of one: %s\n",
9542 ntups, query->data);
9545 nspname = PQgetvalue(res, 0, 0);
9546 tmplname = PQgetvalue(res, 0, 1);
9548 /* Make sure we are in proper schema */
9549 selectSourceSchema(dictinfo->dobj.namespace->dobj.name);
9551 appendPQExpBuffer(q, "CREATE TEXT SEARCH DICTIONARY %s (\n",
9552 fmtId(dictinfo->dobj.name));
9554 appendPQExpBuffer(q, " TEMPLATE = ");
9555 if (strcmp(nspname, dictinfo->dobj.namespace->dobj.name) != 0)
9556 appendPQExpBuffer(q, "%s.", fmtId(nspname));
9557 appendPQExpBuffer(q, "%s", fmtId(tmplname));
9561 /* the dictinitoption can be dumped straight into the command */
9562 if (dictinfo->dictinitoption)
9563 appendPQExpBuffer(q, ",\n %s", dictinfo->dictinitoption);
9565 appendPQExpBuffer(q, " );\n");
9568 * DROP must be fully qualified in case same name appears in pg_catalog
9570 appendPQExpBuffer(delq, "DROP TEXT SEARCH DICTIONARY %s",
9571 fmtId(dictinfo->dobj.namespace->dobj.name));
9572 appendPQExpBuffer(delq, ".%s;\n",
9573 fmtId(dictinfo->dobj.name));
9575 ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId,
9576 dictinfo->dobj.name,
9577 dictinfo->dobj.namespace->dobj.name,
9580 false, "TEXT SEARCH DICTIONARY", SECTION_PRE_DATA,
9581 q->data, delq->data, NULL,
9582 dictinfo->dobj.dependencies, dictinfo->dobj.nDeps,
9585 /* Dump Dictionary Comments */
9586 resetPQExpBuffer(q);
9587 appendPQExpBuffer(q, "TEXT SEARCH DICTIONARY %s",
9588 fmtId(dictinfo->dobj.name));
9589 dumpComment(fout, q->data,
9590 NULL, dictinfo->rolname,
9591 dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId);
9593 destroyPQExpBuffer(q);
9594 destroyPQExpBuffer(delq);
9595 destroyPQExpBuffer(query);
9600 * write out a single text search template
9603 dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
9608 /* Skip if not to be dumped */
9609 if (!tmplinfo->dobj.dump || dataOnly)
9612 q = createPQExpBuffer();
9613 delq = createPQExpBuffer();
9615 /* Make sure we are in proper schema */
9616 selectSourceSchema(tmplinfo->dobj.namespace->dobj.name);
9618 appendPQExpBuffer(q, "CREATE TEXT SEARCH TEMPLATE %s (\n",
9619 fmtId(tmplinfo->dobj.name));
9621 if (tmplinfo->tmplinit != InvalidOid)
9622 appendPQExpBuffer(q, " INIT = %s,\n",
9623 convertTSFunction(tmplinfo->tmplinit));
9624 appendPQExpBuffer(q, " LEXIZE = %s );\n",
9625 convertTSFunction(tmplinfo->tmpllexize));
9628 * DROP must be fully qualified in case same name appears in pg_catalog
9630 appendPQExpBuffer(delq, "DROP TEXT SEARCH TEMPLATE %s",
9631 fmtId(tmplinfo->dobj.namespace->dobj.name));
9632 appendPQExpBuffer(delq, ".%s;\n",
9633 fmtId(tmplinfo->dobj.name));
9635 ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId,
9636 tmplinfo->dobj.name,
9637 tmplinfo->dobj.namespace->dobj.name,
9640 false, "TEXT SEARCH TEMPLATE", SECTION_PRE_DATA,
9641 q->data, delq->data, NULL,
9642 tmplinfo->dobj.dependencies, tmplinfo->dobj.nDeps,
9645 /* Dump Template Comments */
9646 resetPQExpBuffer(q);
9647 appendPQExpBuffer(q, "TEXT SEARCH TEMPLATE %s",
9648 fmtId(tmplinfo->dobj.name));
9649 dumpComment(fout, q->data,
9651 tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId);
9653 destroyPQExpBuffer(q);
9654 destroyPQExpBuffer(delq);
9659 * write out a single text search configuration
9662 dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
9675 /* Skip if not to be dumped */
9676 if (!cfginfo->dobj.dump || dataOnly)
9679 q = createPQExpBuffer();
9680 delq = createPQExpBuffer();
9681 query = createPQExpBuffer();
9683 /* Fetch name and namespace of the config's parser */
9684 selectSourceSchema("pg_catalog");
9685 appendPQExpBuffer(query, "SELECT nspname, prsname "
9686 "FROM pg_ts_parser p, pg_namespace n "
9687 "WHERE p.oid = '%u' AND n.oid = prsnamespace",
9688 cfginfo->cfgparser);
9689 res = PQexec(g_conn, query->data);
9690 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9691 ntups = PQntuples(res);
9694 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
9695 "query returned %d rows instead of one: %s\n",
9697 ntups, query->data);
9700 nspname = PQgetvalue(res, 0, 0);
9701 prsname = PQgetvalue(res, 0, 1);
9703 /* Make sure we are in proper schema */
9704 selectSourceSchema(cfginfo->dobj.namespace->dobj.name);
9706 appendPQExpBuffer(q, "CREATE TEXT SEARCH CONFIGURATION %s (\n",
9707 fmtId(cfginfo->dobj.name));
9709 appendPQExpBuffer(q, " PARSER = ");
9710 if (strcmp(nspname, cfginfo->dobj.namespace->dobj.name) != 0)
9711 appendPQExpBuffer(q, "%s.", fmtId(nspname));
9712 appendPQExpBuffer(q, "%s );\n", fmtId(prsname));
9716 resetPQExpBuffer(query);
9717 appendPQExpBuffer(query,
9719 " ( SELECT alias FROM pg_catalog.ts_token_type('%u'::pg_catalog.oid) AS t \n"
9720 " WHERE t.tokid = m.maptokentype ) AS tokenname, \n"
9721 " m.mapdict::pg_catalog.regdictionary AS dictname \n"
9722 "FROM pg_catalog.pg_ts_config_map AS m \n"
9723 "WHERE m.mapcfg = '%u' \n"
9724 "ORDER BY m.mapcfg, m.maptokentype, m.mapseqno",
9725 cfginfo->cfgparser, cfginfo->dobj.catId.oid);
9727 res = PQexec(g_conn, query->data);
9728 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9729 ntups = PQntuples(res);
9731 i_tokenname = PQfnumber(res, "tokenname");
9732 i_dictname = PQfnumber(res, "dictname");
9734 for (i = 0; i < ntups; i++)
9736 char *tokenname = PQgetvalue(res, i, i_tokenname);
9737 char *dictname = PQgetvalue(res, i, i_dictname);
9740 strcmp(tokenname, PQgetvalue(res, i - 1, i_tokenname)) != 0)
9742 /* starting a new token type, so start a new command */
9744 appendPQExpBuffer(q, ";\n");
9745 appendPQExpBuffer(q, "\nALTER TEXT SEARCH CONFIGURATION %s\n",
9746 fmtId(cfginfo->dobj.name));
9747 /* tokenname needs quoting, dictname does NOT */
9748 appendPQExpBuffer(q, " ADD MAPPING FOR %s WITH %s",
9749 fmtId(tokenname), dictname);
9752 appendPQExpBuffer(q, ", %s", dictname);
9756 appendPQExpBuffer(q, ";\n");
9761 * DROP must be fully qualified in case same name appears in pg_catalog
9763 appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s",
9764 fmtId(cfginfo->dobj.namespace->dobj.name));
9765 appendPQExpBuffer(delq, ".%s;\n",
9766 fmtId(cfginfo->dobj.name));
9768 ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId,
9770 cfginfo->dobj.namespace->dobj.name,
9773 false, "TEXT SEARCH CONFIGURATION", SECTION_PRE_DATA,
9774 q->data, delq->data, NULL,
9775 cfginfo->dobj.dependencies, cfginfo->dobj.nDeps,
9778 /* Dump Configuration Comments */
9779 resetPQExpBuffer(q);
9780 appendPQExpBuffer(q, "TEXT SEARCH CONFIGURATION %s",
9781 fmtId(cfginfo->dobj.name));
9782 dumpComment(fout, q->data,
9783 NULL, cfginfo->rolname,
9784 cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId);
9786 destroyPQExpBuffer(q);
9787 destroyPQExpBuffer(delq);
9788 destroyPQExpBuffer(query);
9792 * dumpForeignDataWrapper
9793 * write out a single foreign-data wrapper definition
9796 dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
9802 /* Skip if not to be dumped */
9803 if (!fdwinfo->dobj.dump || dataOnly)
9806 q = createPQExpBuffer();
9807 delq = createPQExpBuffer();
9809 appendPQExpBuffer(q, "CREATE FOREIGN DATA WRAPPER %s",
9810 fmtId(fdwinfo->dobj.name));
9812 if (fdwinfo->fdwvalidator && strcmp(fdwinfo->fdwvalidator, "-") != 0)
9813 appendPQExpBuffer(q, " VALIDATOR %s",
9814 fdwinfo->fdwvalidator);
9816 if (fdwinfo->fdwoptions && strlen(fdwinfo->fdwoptions) > 0)
9817 appendPQExpBuffer(q, " OPTIONS (%s)", fdwinfo->fdwoptions);
9819 appendPQExpBuffer(q, ";\n");
9821 appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n",
9822 fmtId(fdwinfo->dobj.name));
9824 ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
9829 false, "FOREIGN DATA WRAPPER", SECTION_PRE_DATA,
9830 q->data, delq->data, NULL,
9831 fdwinfo->dobj.dependencies, fdwinfo->dobj.nDeps,
9834 /* Handle the ACL */
9835 namecopy = strdup(fmtId(fdwinfo->dobj.name));
9836 dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
9837 "FOREIGN DATA WRAPPER",
9838 namecopy, NULL, fdwinfo->dobj.name,
9839 NULL, fdwinfo->rolname,
9843 destroyPQExpBuffer(q);
9844 destroyPQExpBuffer(delq);
9849 * write out a foreign server definition
9852 dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
9862 /* Skip if not to be dumped */
9863 if (!srvinfo->dobj.dump || dataOnly)
9866 q = createPQExpBuffer();
9867 delq = createPQExpBuffer();
9868 query = createPQExpBuffer();
9870 /* look up the foreign-data wrapper */
9871 appendPQExpBuffer(query, "SELECT fdwname "
9872 "FROM pg_foreign_data_wrapper w "
9873 "WHERE w.oid = '%u'",
9875 res = PQexec(g_conn, query->data);
9876 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9877 ntups = PQntuples(res);
9880 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
9881 "query returned %d rows instead of one: %s\n",
9883 ntups, query->data);
9886 fdwname = PQgetvalue(res, 0, 0);
9888 appendPQExpBuffer(q, "CREATE SERVER %s", fmtId(srvinfo->dobj.name));
9889 if (srvinfo->srvtype && strlen(srvinfo->srvtype) > 0)
9891 appendPQExpBuffer(q, " TYPE ");
9892 appendStringLiteralAH(q, srvinfo->srvtype, fout);
9894 if (srvinfo->srvversion && strlen(srvinfo->srvversion) > 0)
9896 appendPQExpBuffer(q, " VERSION ");
9897 appendStringLiteralAH(q, srvinfo->srvversion, fout);
9900 appendPQExpBuffer(q, " FOREIGN DATA WRAPPER ");
9901 appendPQExpBuffer(q, "%s", fmtId(fdwname));
9903 if (srvinfo->srvoptions && strlen(srvinfo->srvoptions) > 0)
9904 appendPQExpBuffer(q, " OPTIONS (%s)", srvinfo->srvoptions);
9906 appendPQExpBuffer(q, ";\n");
9908 appendPQExpBuffer(delq, "DROP SERVER %s;\n",
9909 fmtId(srvinfo->dobj.name));
9911 ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
9916 false, "SERVER", SECTION_PRE_DATA,
9917 q->data, delq->data, NULL,
9918 srvinfo->dobj.dependencies, srvinfo->dobj.nDeps,
9921 /* Handle the ACL */
9922 namecopy = strdup(fmtId(srvinfo->dobj.name));
9923 dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
9925 namecopy, NULL, srvinfo->dobj.name,
9926 NULL, srvinfo->rolname,
9930 /* Dump user mappings */
9931 resetPQExpBuffer(q);
9932 appendPQExpBuffer(q, "SERVER %s", fmtId(srvinfo->dobj.name));
9933 dumpUserMappings(fout, q->data,
9934 srvinfo->dobj.name, NULL,
9936 srvinfo->dobj.catId, srvinfo->dobj.dumpId);
9938 destroyPQExpBuffer(q);
9939 destroyPQExpBuffer(delq);
9945 * This routine is used to dump any user mappings associated with the
9946 * server handed to this routine. Should be called after ArchiveEntry()
9950 dumpUserMappings(Archive *fout, const char *target,
9951 const char *servername, const char *namespace,
9953 CatalogId catalogId, DumpId dumpId)
9965 q = createPQExpBuffer();
9966 tag = createPQExpBuffer();
9967 delq = createPQExpBuffer();
9968 query = createPQExpBuffer();
9970 appendPQExpBuffer(query,
9971 "SELECT (%s umuser) AS umuser, "
9972 "array_to_string(ARRAY(SELECT option_name || ' ' || quote_literal(option_value) FROM pg_options_to_table(umoptions)), ', ') AS umoptions\n"
9973 "FROM pg_user_mapping "
9974 "WHERE umserver=%u",
9978 res = PQexec(g_conn, query->data);
9979 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
9981 ntups = PQntuples(res);
9982 i_umuser = PQfnumber(res, "umuser");
9983 i_umoptions = PQfnumber(res, "umoptions");
9985 for (i = 0; i < ntups; i++)
9990 umuser = PQgetvalue(res, i, i_umuser);
9991 umoptions = PQgetvalue(res, i, i_umoptions);
9993 resetPQExpBuffer(q);
9994 appendPQExpBuffer(q, "CREATE USER MAPPING FOR %s", fmtId(umuser));
9995 appendPQExpBuffer(q, " SERVER %s", fmtId(servername));
9997 if (umoptions && strlen(umoptions) > 0)
9998 appendPQExpBuffer(q, " OPTIONS (%s)", umoptions);
10000 appendPQExpBuffer(q, ";\n");
10002 resetPQExpBuffer(delq);
10003 appendPQExpBuffer(delq, "DROP USER MAPPING FOR %s SERVER %s;\n", fmtId(umuser), fmtId(servername));
10005 resetPQExpBuffer(tag);
10006 appendPQExpBuffer(tag, "USER MAPPING %s %s", fmtId(umuser), target);
10008 ArchiveEntry(fout, nilCatalogId, createDumpId(),
10013 "USER MAPPING", SECTION_PRE_DATA,
10014 q->data, delq->data, NULL,
10021 destroyPQExpBuffer(query);
10022 destroyPQExpBuffer(delq);
10023 destroyPQExpBuffer(q);
10027 * Write out default privileges information
10030 dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
10036 /* Skip if not to be dumped */
10037 if (!daclinfo->dobj.dump || dataOnly || aclsSkip)
10040 q = createPQExpBuffer();
10041 tag = createPQExpBuffer();
10043 switch (daclinfo->defaclobjtype)
10045 case DEFACLOBJ_RELATION:
10048 case DEFACLOBJ_SEQUENCE:
10049 type = "SEQUENCES";
10051 case DEFACLOBJ_FUNCTION:
10052 type = "FUNCTIONS";
10055 /* shouldn't get here */
10056 write_msg(NULL, "unknown object type (%d) in default privileges\n",
10057 (int) daclinfo->defaclobjtype);
10059 type = ""; /* keep compiler quiet */
10062 appendPQExpBuffer(tag, "DEFAULT PRIVILEGES FOR %s", type);
10064 /* build the actual command(s) for this tuple */
10065 if (!buildDefaultACLCommands(type,
10066 daclinfo->dobj.namespace != NULL ?
10067 daclinfo->dobj.namespace->dobj.name : NULL,
10068 daclinfo->defaclacl,
10069 daclinfo->defaclrole,
10070 fout->remoteVersion,
10073 write_msg(NULL, "could not parse default ACL list (%s)\n",
10074 daclinfo->defaclacl);
10078 ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
10080 daclinfo->dobj.namespace ? daclinfo->dobj.namespace->dobj.name : NULL,
10082 daclinfo->defaclrole,
10083 false, "DEFAULT ACL", SECTION_NONE,
10085 daclinfo->dobj.dependencies, daclinfo->dobj.nDeps,
10088 destroyPQExpBuffer(tag);
10089 destroyPQExpBuffer(q);
10093 * Write out grant/revoke information
10095 * 'objCatId' is the catalog ID of the underlying object.
10096 * 'objDumpId' is the dump ID of the underlying object.
10097 * 'type' must be TABLE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, or TABLESPACE.
10098 * 'name' is the formatted name of the object. Must be quoted etc. already.
10099 * 'subname' is the formatted name of the sub-object, if any. Must be quoted.
10100 * 'tag' is the tag for the archive entry (typ. unquoted name of object).
10101 * 'nspname' is the namespace the object is in (NULL if none).
10102 * 'owner' is the owner, NULL if there is no owner (for languages).
10103 * 'acls' is the string read out of the fooacl system catalog field;
10104 * it will be parsed here.
10108 dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
10109 const char *type, const char *name, const char *subname,
10110 const char *tag, const char *nspname, const char *owner,
10115 /* Do nothing if ACL dump is not enabled */
10116 if (dataOnly || aclsSkip)
10119 sql = createPQExpBuffer();
10121 if (!buildACLCommands(name, subname, type, acls, owner,
10122 "", fout->remoteVersion, sql))
10124 write_msg(NULL, "could not parse ACL list (%s) for object \"%s\" (%s)\n",
10130 ArchiveEntry(fout, nilCatalogId, createDumpId(),
10133 owner ? owner : "",
10134 false, "ACL", SECTION_NONE,
10135 sql->data, "", NULL,
10139 destroyPQExpBuffer(sql);
10144 * write out to fout the declarations (not data) of a user-defined table
10147 dumpTable(Archive *fout, TableInfo *tbinfo)
10149 if (tbinfo->dobj.dump)
10153 if (tbinfo->relkind == RELKIND_SEQUENCE)
10154 dumpSequence(fout, tbinfo);
10155 else if (!dataOnly)
10156 dumpTableSchema(fout, tbinfo);
10158 /* Handle the ACL here */
10159 namecopy = strdup(fmtId(tbinfo->dobj.name));
10160 dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
10161 (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE",
10162 namecopy, NULL, tbinfo->dobj.name,
10163 tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
10167 * Handle column ACLs, if any. Note: we pull these with a separate
10168 * query rather than trying to fetch them during getTableAttrs, so
10169 * that we won't miss ACLs on system columns.
10171 if (g_fout->remoteVersion >= 80400)
10173 PQExpBuffer query = createPQExpBuffer();
10177 appendPQExpBuffer(query,
10178 "SELECT attname, attacl FROM pg_catalog.pg_attribute "
10179 "WHERE attrelid = '%u' AND NOT attisdropped AND attacl IS NOT NULL "
10181 tbinfo->dobj.catId.oid);
10182 res = PQexec(g_conn, query->data);
10183 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
10185 for (i = 0; i < PQntuples(res); i++)
10187 char *attname = PQgetvalue(res, i, 0);
10188 char *attacl = PQgetvalue(res, i, 1);
10192 attnamecopy = strdup(fmtId(attname));
10193 acltag = malloc(strlen(tbinfo->dobj.name) + strlen(attname) + 2);
10194 sprintf(acltag, "%s.%s", tbinfo->dobj.name, attname);
10195 /* Column's GRANT type is always TABLE */
10196 dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
10197 namecopy, attnamecopy, acltag,
10198 tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
10204 destroyPQExpBuffer(query);
10213 * write the declaration (not data) of one user-defined table or view
10216 dumpTableSchema(Archive *fout, TableInfo *tbinfo)
10218 PQExpBuffer query = createPQExpBuffer();
10219 PQExpBuffer q = createPQExpBuffer();
10220 PQExpBuffer delq = createPQExpBuffer();
10223 TableInfo **parents;
10224 int actual_atts; /* number of attrs in this CREATE statment */
10230 /* Make sure we are in proper schema */
10231 selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
10233 /* Is it a table or a view? */
10234 if (tbinfo->relkind == RELKIND_VIEW)
10238 reltypename = "VIEW";
10240 /* Fetch the view definition */
10241 if (g_fout->remoteVersion >= 70300)
10243 /* Beginning in 7.3, viewname is not unique; rely on OID */
10244 appendPQExpBuffer(query,
10245 "SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) AS viewdef",
10246 tbinfo->dobj.catId.oid);
10250 appendPQExpBuffer(query, "SELECT definition AS viewdef "
10251 "FROM pg_views WHERE viewname = ");
10252 appendStringLiteralAH(query, tbinfo->dobj.name, fout);
10253 appendPQExpBuffer(query, ";");
10256 res = PQexec(g_conn, query->data);
10257 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
10259 if (PQntuples(res) != 1)
10261 if (PQntuples(res) < 1)
10262 write_msg(NULL, "query to obtain definition of view \"%s\" returned no data\n",
10263 tbinfo->dobj.name);
10265 write_msg(NULL, "query to obtain definition of view \"%s\" returned more than one definition\n",
10266 tbinfo->dobj.name);
10270 viewdef = PQgetvalue(res, 0, 0);
10272 if (strlen(viewdef) == 0)
10274 write_msg(NULL, "definition of view \"%s\" appears to be empty (length zero)\n",
10275 tbinfo->dobj.name);
10280 * DROP must be fully qualified in case same name appears in
10283 appendPQExpBuffer(delq, "DROP VIEW %s.",
10284 fmtId(tbinfo->dobj.namespace->dobj.name));
10285 appendPQExpBuffer(delq, "%s;\n",
10286 fmtId(tbinfo->dobj.name));
10288 appendPQExpBuffer(q, "CREATE VIEW %s AS\n %s\n",
10289 fmtId(tbinfo->dobj.name), viewdef);
10295 reltypename = "TABLE";
10296 numParents = tbinfo->numParents;
10297 parents = tbinfo->parents;
10300 * DROP must be fully qualified in case same name appears in
10303 appendPQExpBuffer(delq, "DROP TABLE %s.",
10304 fmtId(tbinfo->dobj.namespace->dobj.name));
10305 appendPQExpBuffer(delq, "%s;\n",
10306 fmtId(tbinfo->dobj.name));
10308 appendPQExpBuffer(q, "CREATE TABLE %s (",
10309 fmtId(tbinfo->dobj.name));
10311 for (j = 0; j < tbinfo->numatts; j++)
10314 * Normally, dump if it's one of the table's own attrs, and not
10315 * dropped. But for binary upgrade, dump all the columns.
10317 if ((!tbinfo->inhAttrs[j] && !tbinfo->attisdropped[j]) ||
10320 /* Format properly if not first attr */
10321 if (actual_atts > 0)
10322 appendPQExpBuffer(q, ",");
10323 appendPQExpBuffer(q, "\n ");
10326 /* Attribute name */
10327 appendPQExpBuffer(q, "%s ",
10328 fmtId(tbinfo->attnames[j]));
10330 if (tbinfo->attisdropped[j])
10333 * ALTER TABLE DROP COLUMN clears pg_attribute.atttypid,
10334 * so we will not have gotten a valid type name; insert
10335 * INTEGER as a stopgap. We'll clean things up later.
10337 appendPQExpBuffer(q, "INTEGER /* dummy */");
10338 /* Skip all the rest, too */
10342 /* Attribute type */
10343 if (g_fout->remoteVersion >= 70100)
10345 appendPQExpBuffer(q, "%s",
10346 tbinfo->atttypnames[j]);
10350 /* If no format_type, fake it */
10351 appendPQExpBuffer(q, "%s",
10352 myFormatType(tbinfo->atttypnames[j],
10353 tbinfo->atttypmod[j]));
10357 * Default value --- suppress if inherited (except in
10358 * binary-upgrade case, where we're not doing normal
10359 * inheritance) or if it's to be printed separately.
10361 if (tbinfo->attrdefs[j] != NULL &&
10362 (!tbinfo->inhAttrDef[j] || binary_upgrade) &&
10363 !tbinfo->attrdefs[j]->separate)
10364 appendPQExpBuffer(q, " DEFAULT %s",
10365 tbinfo->attrdefs[j]->adef_expr);
10368 * Not Null constraint --- suppress if inherited, except
10369 * in binary-upgrade case.
10371 if (tbinfo->notnull[j] &&
10372 (!tbinfo->inhNotNull[j] || binary_upgrade))
10373 appendPQExpBuffer(q, " NOT NULL");
10378 * Add non-inherited CHECK constraints, if any.
10380 for (j = 0; j < tbinfo->ncheck; j++)
10382 ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
10384 if (constr->separate || !constr->conislocal)
10387 if (actual_atts > 0)
10388 appendPQExpBuffer(q, ",\n ");
10390 appendPQExpBuffer(q, "CONSTRAINT %s ",
10391 fmtId(constr->dobj.name));
10392 appendPQExpBuffer(q, "%s", constr->condef);
10397 appendPQExpBuffer(q, "\n)");
10399 if (numParents > 0 && !binary_upgrade)
10401 appendPQExpBuffer(q, "\nINHERITS (");
10402 for (k = 0; k < numParents; k++)
10404 TableInfo *parentRel = parents[k];
10407 appendPQExpBuffer(q, ", ");
10408 if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
10409 appendPQExpBuffer(q, "%s.",
10410 fmtId(parentRel->dobj.namespace->dobj.name));
10411 appendPQExpBuffer(q, "%s",
10412 fmtId(parentRel->dobj.name));
10414 appendPQExpBuffer(q, ")");
10417 if ((tbinfo->reloptions && strlen(tbinfo->reloptions) > 0) ||
10418 (tbinfo->toast_reloptions && strlen(tbinfo->toast_reloptions) > 0))
10420 bool addcomma = false;
10422 appendPQExpBuffer(q, "\nWITH (");
10423 if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
10426 appendPQExpBuffer(q, "%s", tbinfo->reloptions);
10428 if (tbinfo->toast_reloptions && strlen(tbinfo->toast_reloptions) > 0)
10430 appendPQExpBuffer(q, "%s%s", addcomma ? ", " : "",
10431 tbinfo->toast_reloptions);
10433 appendPQExpBuffer(q, ")");
10436 appendPQExpBuffer(q, ";\n");
10439 * To create binary-compatible heap files, we have to ensure the
10440 * same physical column order, including dropped columns, as in the
10441 * original. Therefore, we create dropped columns above and drop
10442 * them here, also updating their attlen/attalign values so that
10443 * the dropped column can be skipped properly. (We do not bother
10444 * with restoring the original attbyval setting.) Also, inheritance
10445 * relationships are set up by doing ALTER INHERIT rather than using
10446 * an INHERITS clause --- the latter would possibly mess up the
10447 * column order. That also means we have to take care about setting
10448 * attislocal correctly, plus fix up any inherited CHECK constraints.
10450 if (binary_upgrade)
10452 for (j = 0; j < tbinfo->numatts; j++)
10454 if (tbinfo->attisdropped[j])
10456 appendPQExpBuffer(q, "\n-- For binary upgrade, recreate dropped column.\n");
10457 appendPQExpBuffer(q, "UPDATE pg_catalog.pg_attribute\n"
10458 "SET attlen = %d, "
10459 "attalign = '%c', attbyval = false\n"
10460 "WHERE attname = ",
10462 tbinfo->attalign[j]);
10463 appendStringLiteralAH(q, tbinfo->attnames[j], fout);
10464 appendPQExpBuffer(q, "\n AND attrelid = ");
10465 appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
10466 appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
10468 appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
10469 fmtId(tbinfo->dobj.name));
10470 appendPQExpBuffer(q, "DROP COLUMN %s;\n",
10471 fmtId(tbinfo->attnames[j]));
10473 else if (!tbinfo->attislocal[j])
10475 appendPQExpBuffer(q, "\n-- For binary upgrade, recreate inherited column.\n");
10476 appendPQExpBuffer(q, "UPDATE pg_catalog.pg_attribute\n"
10477 "SET attislocal = false\n"
10478 "WHERE attname = ");
10479 appendStringLiteralAH(q, tbinfo->attnames[j], fout);
10480 appendPQExpBuffer(q, "\n AND attrelid = ");
10481 appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
10482 appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
10486 for (k = 0; k < tbinfo->ncheck; k++)
10488 ConstraintInfo *constr = &(tbinfo->checkexprs[k]);
10490 if (constr->separate || constr->conislocal)
10493 appendPQExpBuffer(q, "\n-- For binary upgrade, set up inherited constraint.\n");
10494 appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
10495 fmtId(tbinfo->dobj.name));
10496 appendPQExpBuffer(q, " ADD CONSTRAINT %s ",
10497 fmtId(constr->dobj.name));
10498 appendPQExpBuffer(q, "%s;\n", constr->condef);
10499 appendPQExpBuffer(q, "UPDATE pg_catalog.pg_constraint\n"
10500 "SET conislocal = false\n"
10501 "WHERE contype = 'c' AND conname = ");
10502 appendStringLiteralAH(q, constr->dobj.name, fout);
10503 appendPQExpBuffer(q, "\n AND conrelid = ");
10504 appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
10505 appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
10508 if (numParents > 0)
10510 appendPQExpBuffer(q, "\n-- For binary upgrade, set up inheritance this way.\n");
10511 for (k = 0; k < numParents; k++)
10513 TableInfo *parentRel = parents[k];
10515 appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT ",
10516 fmtId(tbinfo->dobj.name));
10517 if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
10518 appendPQExpBuffer(q, "%s.",
10519 fmtId(parentRel->dobj.namespace->dobj.name));
10520 appendPQExpBuffer(q, "%s;\n",
10521 fmtId(parentRel->dobj.name));
10525 appendPQExpBuffer(q, "\n-- For binary upgrade, set relfrozenxid.\n");
10526 appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
10527 "SET relfrozenxid = '%u'\n"
10529 tbinfo->frozenxid);
10530 appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
10531 appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
10534 /* Loop dumping statistics and storage statements */
10535 for (j = 0; j < tbinfo->numatts; j++)
10538 * Dump per-column statistics information. We only issue an ALTER
10539 * TABLE statement if the attstattarget entry for this column is
10540 * non-negative (i.e. it's not the default value)
10542 if (tbinfo->attstattarget[j] >= 0 &&
10543 !tbinfo->attisdropped[j])
10545 appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
10546 fmtId(tbinfo->dobj.name));
10547 appendPQExpBuffer(q, "ALTER COLUMN %s ",
10548 fmtId(tbinfo->attnames[j]));
10549 appendPQExpBuffer(q, "SET STATISTICS %d;\n",
10550 tbinfo->attstattarget[j]);
10554 * Dump per-column ndistinct information. We only issue an ALTER
10555 * TABLE statement if the attdistinct entry for this column is
10556 * non-zero (i.e. it's not the default value)
10558 if (tbinfo->attdistinct[j] != 0 &&
10559 !tbinfo->attisdropped[j])
10561 appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
10562 fmtId(tbinfo->dobj.name));
10563 appendPQExpBuffer(q, "ALTER COLUMN %s ",
10564 fmtId(tbinfo->attnames[j]));
10565 appendPQExpBuffer(q, "SET STATISTICS DISTINCT %g;\n",
10566 tbinfo->attdistinct[j]);
10570 * Dump per-column storage information. The statement is only
10571 * dumped if the storage has been changed from the type's default.
10573 if (!tbinfo->attisdropped[j] && tbinfo->attstorage[j] != tbinfo->typstorage[j])
10575 switch (tbinfo->attstorage[j])
10581 storage = "EXTERNAL";
10587 storage = "EXTENDED";
10594 * Only dump the statement if it's a storage type we recognize
10596 if (storage != NULL)
10598 appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
10599 fmtId(tbinfo->dobj.name));
10600 appendPQExpBuffer(q, "ALTER COLUMN %s ",
10601 fmtId(tbinfo->attnames[j]));
10602 appendPQExpBuffer(q, "SET STORAGE %s;\n",
10609 ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
10611 tbinfo->dobj.namespace->dobj.name,
10612 (tbinfo->relkind == RELKIND_VIEW) ? NULL : tbinfo->reltablespace,
10614 (strcmp(reltypename, "TABLE") == 0) ? tbinfo->hasoids : false,
10615 reltypename, SECTION_PRE_DATA,
10616 q->data, delq->data, NULL,
10617 tbinfo->dobj.dependencies, tbinfo->dobj.nDeps,
10620 /* Dump Table Comments */
10621 dumpTableComment(fout, tbinfo, reltypename);
10623 /* Dump comments on inlined table constraints */
10624 for (j = 0; j < tbinfo->ncheck; j++)
10626 ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
10628 if (constr->separate || !constr->conislocal)
10631 dumpTableConstraintComment(fout, constr);
10634 destroyPQExpBuffer(query);
10635 destroyPQExpBuffer(q);
10636 destroyPQExpBuffer(delq);
10640 * dumpAttrDef --- dump an attribute's default-value declaration
10643 dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
10645 TableInfo *tbinfo = adinfo->adtable;
10646 int adnum = adinfo->adnum;
10650 /* Only print it if "separate" mode is selected */
10651 if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly)
10654 /* Don't print inherited defaults, either, except for binary upgrade */
10655 if (tbinfo->inhAttrDef[adnum - 1] && !binary_upgrade)
10658 q = createPQExpBuffer();
10659 delq = createPQExpBuffer();
10661 appendPQExpBuffer(q, "ALTER TABLE %s ",
10662 fmtId(tbinfo->dobj.name));
10663 appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
10664 fmtId(tbinfo->attnames[adnum - 1]),
10665 adinfo->adef_expr);
10668 * DROP must be fully qualified in case same name appears in pg_catalog
10670 appendPQExpBuffer(delq, "ALTER TABLE %s.",
10671 fmtId(tbinfo->dobj.namespace->dobj.name));
10672 appendPQExpBuffer(delq, "%s ",
10673 fmtId(tbinfo->dobj.name));
10674 appendPQExpBuffer(delq, "ALTER COLUMN %s DROP DEFAULT;\n",
10675 fmtId(tbinfo->attnames[adnum - 1]));
10677 ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId,
10678 tbinfo->attnames[adnum - 1],
10679 tbinfo->dobj.namespace->dobj.name,
10682 false, "DEFAULT", SECTION_PRE_DATA,
10683 q->data, delq->data, NULL,
10684 adinfo->dobj.dependencies, adinfo->dobj.nDeps,
10687 destroyPQExpBuffer(q);
10688 destroyPQExpBuffer(delq);
10692 * getAttrName: extract the correct name for an attribute
10694 * The array tblInfo->attnames[] only provides names of user attributes;
10695 * if a system attribute number is supplied, we have to fake it.
10696 * We also do a little bit of bounds checking for safety's sake.
10698 static const char *
10699 getAttrName(int attrnum, TableInfo *tblInfo)
10701 if (attrnum > 0 && attrnum <= tblInfo->numatts)
10702 return tblInfo->attnames[attrnum - 1];
10705 case SelfItemPointerAttributeNumber:
10707 case ObjectIdAttributeNumber:
10709 case MinTransactionIdAttributeNumber:
10711 case MinCommandIdAttributeNumber:
10713 case MaxTransactionIdAttributeNumber:
10715 case MaxCommandIdAttributeNumber:
10717 case TableOidAttributeNumber:
10720 write_msg(NULL, "invalid column number %d for table \"%s\"\n",
10721 attrnum, tblInfo->dobj.name);
10723 return NULL; /* keep compiler quiet */
10728 * write out to fout a user-defined index
10731 dumpIndex(Archive *fout, IndxInfo *indxinfo)
10733 TableInfo *tbinfo = indxinfo->indextable;
10740 q = createPQExpBuffer();
10741 delq = createPQExpBuffer();
10744 * If there's an associated constraint, don't dump the index per se, but
10745 * do dump any comment for it. (This is safe because dependency ordering
10746 * will have ensured the constraint is emitted first.)
10748 if (indxinfo->indexconstraint == 0)
10750 /* Plain secondary index */
10751 appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef);
10753 /* If the index is clustered, we need to record that. */
10754 if (indxinfo->indisclustered)
10756 appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
10757 fmtId(tbinfo->dobj.name));
10758 appendPQExpBuffer(q, " ON %s;\n",
10759 fmtId(indxinfo->dobj.name));
10763 * DROP must be fully qualified in case same name appears in
10766 appendPQExpBuffer(delq, "DROP INDEX %s.",
10767 fmtId(tbinfo->dobj.namespace->dobj.name));
10768 appendPQExpBuffer(delq, "%s;\n",
10769 fmtId(indxinfo->dobj.name));
10771 ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
10772 indxinfo->dobj.name,
10773 tbinfo->dobj.namespace->dobj.name,
10774 indxinfo->tablespace,
10775 tbinfo->rolname, false,
10776 "INDEX", SECTION_POST_DATA,
10777 q->data, delq->data, NULL,
10778 indxinfo->dobj.dependencies, indxinfo->dobj.nDeps,
10782 /* Dump Index Comments */
10783 resetPQExpBuffer(q);
10784 appendPQExpBuffer(q, "INDEX %s",
10785 fmtId(indxinfo->dobj.name));
10786 dumpComment(fout, q->data,
10787 tbinfo->dobj.namespace->dobj.name,
10789 indxinfo->dobj.catId, 0, indxinfo->dobj.dumpId);
10791 destroyPQExpBuffer(q);
10792 destroyPQExpBuffer(delq);
10797 * write out to fout a user-defined constraint
10800 dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
10802 TableInfo *tbinfo = coninfo->contable;
10806 /* Skip if not to be dumped */
10807 if (!coninfo->dobj.dump || dataOnly)
10810 q = createPQExpBuffer();
10811 delq = createPQExpBuffer();
10813 if (coninfo->contype == 'p' ||
10814 coninfo->contype == 'u' ||
10815 coninfo->contype == 'x')
10817 /* Index-related constraint */
10818 IndxInfo *indxinfo;
10821 indxinfo = (IndxInfo *) findObjectByDumpId(coninfo->conindex);
10823 if (indxinfo == NULL)
10825 write_msg(NULL, "missing index for constraint \"%s\"\n",
10826 coninfo->dobj.name);
10830 appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
10831 fmtId(tbinfo->dobj.name));
10832 appendPQExpBuffer(q, " ADD CONSTRAINT %s ",
10833 fmtId(coninfo->dobj.name));
10835 if (coninfo->condef)
10837 /* pg_get_constraintdef should have provided everything */
10838 appendPQExpBuffer(q, "%s;\n", coninfo->condef);
10842 appendPQExpBuffer(q, "%s (",
10843 coninfo->contype == 'p' ? "PRIMARY KEY" : "UNIQUE");
10844 for (k = 0; k < indxinfo->indnkeys; k++)
10846 int indkey = (int) indxinfo->indkeys[k];
10847 const char *attname;
10849 if (indkey == InvalidAttrNumber)
10851 attname = getAttrName(indkey, tbinfo);
10853 appendPQExpBuffer(q, "%s%s",
10854 (k == 0) ? "" : ", ",
10858 appendPQExpBuffer(q, ")");
10860 if (indxinfo->options && strlen(indxinfo->options) > 0)
10861 appendPQExpBuffer(q, " WITH (%s)", indxinfo->options);
10863 if (coninfo->condeferrable)
10865 appendPQExpBuffer(q, " DEFERRABLE");
10866 if (coninfo->condeferred)
10867 appendPQExpBuffer(q, " INITIALLY DEFERRED");
10870 appendPQExpBuffer(q, ";\n");
10873 /* If the index is clustered, we need to record that. */
10874 if (indxinfo->indisclustered)
10876 appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
10877 fmtId(tbinfo->dobj.name));
10878 appendPQExpBuffer(q, " ON %s;\n",
10879 fmtId(indxinfo->dobj.name));
10883 * DROP must be fully qualified in case same name appears in
10886 appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
10887 fmtId(tbinfo->dobj.namespace->dobj.name));
10888 appendPQExpBuffer(delq, "%s ",
10889 fmtId(tbinfo->dobj.name));
10890 appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
10891 fmtId(coninfo->dobj.name));
10893 ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
10894 coninfo->dobj.name,
10895 tbinfo->dobj.namespace->dobj.name,
10896 indxinfo->tablespace,
10897 tbinfo->rolname, false,
10898 "CONSTRAINT", SECTION_POST_DATA,
10899 q->data, delq->data, NULL,
10900 coninfo->dobj.dependencies, coninfo->dobj.nDeps,
10903 else if (coninfo->contype == 'f')
10906 * XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that the
10907 * current table data is not processed
10909 appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
10910 fmtId(tbinfo->dobj.name));
10911 appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
10912 fmtId(coninfo->dobj.name),
10916 * DROP must be fully qualified in case same name appears in
10919 appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
10920 fmtId(tbinfo->dobj.namespace->dobj.name));
10921 appendPQExpBuffer(delq, "%s ",
10922 fmtId(tbinfo->dobj.name));
10923 appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
10924 fmtId(coninfo->dobj.name));
10926 ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
10927 coninfo->dobj.name,
10928 tbinfo->dobj.namespace->dobj.name,
10930 tbinfo->rolname, false,
10931 "FK CONSTRAINT", SECTION_POST_DATA,
10932 q->data, delq->data, NULL,
10933 coninfo->dobj.dependencies, coninfo->dobj.nDeps,
10936 else if (coninfo->contype == 'c' && tbinfo)
10938 /* CHECK constraint on a table */
10940 /* Ignore if not to be dumped separately */
10941 if (coninfo->separate)
10943 /* not ONLY since we want it to propagate to children */
10944 appendPQExpBuffer(q, "ALTER TABLE %s\n",
10945 fmtId(tbinfo->dobj.name));
10946 appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
10947 fmtId(coninfo->dobj.name),
10951 * DROP must be fully qualified in case same name appears in
10954 appendPQExpBuffer(delq, "ALTER TABLE %s.",
10955 fmtId(tbinfo->dobj.namespace->dobj.name));
10956 appendPQExpBuffer(delq, "%s ",
10957 fmtId(tbinfo->dobj.name));
10958 appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
10959 fmtId(coninfo->dobj.name));
10961 ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
10962 coninfo->dobj.name,
10963 tbinfo->dobj.namespace->dobj.name,
10965 tbinfo->rolname, false,
10966 "CHECK CONSTRAINT", SECTION_POST_DATA,
10967 q->data, delq->data, NULL,
10968 coninfo->dobj.dependencies, coninfo->dobj.nDeps,
10972 else if (coninfo->contype == 'c' && tbinfo == NULL)
10974 /* CHECK constraint on a domain */
10975 TypeInfo *tinfo = coninfo->condomain;
10977 /* Ignore if not to be dumped separately */
10978 if (coninfo->separate)
10980 appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
10981 fmtId(tinfo->dobj.name));
10982 appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
10983 fmtId(coninfo->dobj.name),
10987 * DROP must be fully qualified in case same name appears in
10990 appendPQExpBuffer(delq, "ALTER DOMAIN %s.",
10991 fmtId(tinfo->dobj.namespace->dobj.name));
10992 appendPQExpBuffer(delq, "%s ",
10993 fmtId(tinfo->dobj.name));
10994 appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
10995 fmtId(coninfo->dobj.name));
10997 ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
10998 coninfo->dobj.name,
10999 tinfo->dobj.namespace->dobj.name,
11001 tinfo->rolname, false,
11002 "CHECK CONSTRAINT", SECTION_POST_DATA,
11003 q->data, delq->data, NULL,
11004 coninfo->dobj.dependencies, coninfo->dobj.nDeps,
11010 write_msg(NULL, "unrecognized constraint type: %c\n", coninfo->contype);
11014 /* Dump Constraint Comments --- only works for table constraints */
11015 if (tbinfo && coninfo->separate)
11016 dumpTableConstraintComment(fout, coninfo);
11018 destroyPQExpBuffer(q);
11019 destroyPQExpBuffer(delq);
11023 * dumpTableConstraintComment --- dump a constraint's comment if any
11025 * This is split out because we need the function in two different places
11026 * depending on whether the constraint is dumped as part of CREATE TABLE
11027 * or as a separate ALTER command.
11030 dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo)
11032 TableInfo *tbinfo = coninfo->contable;
11033 PQExpBuffer q = createPQExpBuffer();
11035 appendPQExpBuffer(q, "CONSTRAINT %s ",
11036 fmtId(coninfo->dobj.name));
11037 appendPQExpBuffer(q, "ON %s",
11038 fmtId(tbinfo->dobj.name));
11039 dumpComment(fout, q->data,
11040 tbinfo->dobj.namespace->dobj.name,
11042 coninfo->dobj.catId, 0,
11043 coninfo->separate ? coninfo->dobj.dumpId : tbinfo->dobj.dumpId);
11045 destroyPQExpBuffer(q);
11049 * findLastBuiltInOid -
11050 * find the last built in oid
11052 * For 7.1 and 7.2, we do this by retrieving datlastsysoid from the
11053 * pg_database entry for the current database
11056 findLastBuiltinOid_V71(const char *dbname)
11061 PQExpBuffer query = createPQExpBuffer();
11063 resetPQExpBuffer(query);
11064 appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = ");
11065 appendStringLiteralAH(query, dbname, g_fout);
11067 res = PQexec(g_conn, query->data);
11068 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11070 ntups = PQntuples(res);
11073 write_msg(NULL, "missing pg_database entry for this database\n");
11078 write_msg(NULL, "found more than one pg_database entry for this database\n");
11081 last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "datlastsysoid")));
11083 destroyPQExpBuffer(query);
11088 * findLastBuiltInOid -
11089 * find the last built in oid
11091 * For 7.0, we do this by assuming that the last thing that initdb does is to
11092 * create the pg_indexes view. This sucks in general, but seeing that 7.0.x
11093 * initdb won't be changing anymore, it'll do.
11096 findLastBuiltinOid_V70(void)
11102 res = PQexec(g_conn,
11103 "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'");
11104 check_sql_result(res, g_conn,
11105 "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'",
11107 ntups = PQntuples(res);
11110 write_msg(NULL, "could not find entry for pg_indexes in pg_class\n");
11115 write_msg(NULL, "found more than one entry for pg_indexes in pg_class\n");
11118 last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "oid")));
11124 dumpSequence(Archive *fout, TableInfo *tbinfo)
11137 PQExpBuffer query = createPQExpBuffer();
11138 PQExpBuffer delqry = createPQExpBuffer();
11140 /* Make sure we are in proper schema */
11141 selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
11143 snprintf(bufm, sizeof(bufm), INT64_FORMAT, SEQ_MINVALUE);
11144 snprintf(bufx, sizeof(bufx), INT64_FORMAT, SEQ_MAXVALUE);
11146 if (g_fout->remoteVersion >= 80400)
11148 appendPQExpBuffer(query,
11149 "SELECT sequence_name, "
11150 "start_value, last_value, increment_by, "
11151 "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
11152 " WHEN increment_by < 0 AND max_value = -1 THEN NULL "
11154 "END AS max_value, "
11155 "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
11156 " WHEN increment_by < 0 AND min_value = %s THEN NULL "
11158 "END AS min_value, "
11159 "cache_value, is_cycled, is_called from %s",
11161 fmtId(tbinfo->dobj.name));
11165 appendPQExpBuffer(query,
11166 "SELECT sequence_name, "
11167 "0 AS start_value, last_value, increment_by, "
11168 "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
11169 " WHEN increment_by < 0 AND max_value = -1 THEN NULL "
11171 "END AS max_value, "
11172 "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
11173 " WHEN increment_by < 0 AND min_value = %s THEN NULL "
11175 "END AS min_value, "
11176 "cache_value, is_cycled, is_called from %s",
11178 fmtId(tbinfo->dobj.name));
11181 res = PQexec(g_conn, query->data);
11182 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11184 if (PQntuples(res) != 1)
11186 write_msg(NULL, ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)\n",
11187 "query to get data of sequence \"%s\" returned %d rows (expected 1)\n",
11189 tbinfo->dobj.name, PQntuples(res));
11193 /* Disable this check: it fails if sequence has been renamed */
11195 if (strcmp(PQgetvalue(res, 0, 0), tbinfo->dobj.name) != 0)
11197 write_msg(NULL, "query to get data of sequence \"%s\" returned name \"%s\"\n",
11198 tbinfo->dobj.name, PQgetvalue(res, 0, 0));
11203 startv = PQgetvalue(res, 0, 1);
11204 last = PQgetvalue(res, 0, 2);
11205 incby = PQgetvalue(res, 0, 3);
11206 if (!PQgetisnull(res, 0, 4))
11207 maxv = PQgetvalue(res, 0, 4);
11208 if (!PQgetisnull(res, 0, 5))
11209 minv = PQgetvalue(res, 0, 5);
11210 cache = PQgetvalue(res, 0, 6);
11211 cycled = (strcmp(PQgetvalue(res, 0, 7), "t") == 0);
11212 called = (strcmp(PQgetvalue(res, 0, 8), "t") == 0);
11215 * The logic we use for restoring sequences is as follows:
11217 * Add a CREATE SEQUENCE statement as part of a "schema" dump (use
11218 * last_val for start if called is false, else use min_val for start_val).
11219 * Also, if the sequence is owned by a column, add an ALTER SEQUENCE OWNED
11220 * BY command for it.
11222 * Add a 'SETVAL(seq, last_val, iscalled)' as part of a "data" dump.
11226 resetPQExpBuffer(delqry);
11229 * DROP must be fully qualified in case same name appears in
11232 appendPQExpBuffer(delqry, "DROP SEQUENCE %s.",
11233 fmtId(tbinfo->dobj.namespace->dobj.name));
11234 appendPQExpBuffer(delqry, "%s;\n",
11235 fmtId(tbinfo->dobj.name));
11237 resetPQExpBuffer(query);
11238 appendPQExpBuffer(query,
11239 "CREATE SEQUENCE %s\n",
11240 fmtId(tbinfo->dobj.name));
11242 if (g_fout->remoteVersion >= 80400)
11243 appendPQExpBuffer(query, " START WITH %s\n", startv);
11247 * Versions before 8.4 did not remember the true start value. If
11248 * is_called is false then the sequence has never been incremented
11249 * so we can use last_val. Otherwise punt and let it default.
11252 appendPQExpBuffer(query, " START WITH %s\n", last);
11255 appendPQExpBuffer(query, " INCREMENT BY %s\n", incby);
11258 appendPQExpBuffer(query, " MINVALUE %s\n", minv);
11260 appendPQExpBuffer(query, " NO MINVALUE\n");
11263 appendPQExpBuffer(query, " MAXVALUE %s\n", maxv);
11265 appendPQExpBuffer(query, " NO MAXVALUE\n");
11267 appendPQExpBuffer(query,
11269 cache, (cycled ? "\n CYCLE" : ""));
11271 appendPQExpBuffer(query, ";\n");
11273 ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
11275 tbinfo->dobj.namespace->dobj.name,
11278 false, "SEQUENCE", SECTION_PRE_DATA,
11279 query->data, delqry->data, NULL,
11280 tbinfo->dobj.dependencies, tbinfo->dobj.nDeps,
11284 * If the sequence is owned by a table column, emit the ALTER for it
11285 * as a separate TOC entry immediately following the sequence's own
11286 * entry. It's OK to do this rather than using full sorting logic,
11287 * because the dependency that tells us it's owned will have forced
11288 * the table to be created first. We can't just include the ALTER in
11289 * the TOC entry because it will fail if we haven't reassigned the
11290 * sequence owner to match the table's owner.
11292 * We need not schema-qualify the table reference because both
11293 * sequence and table must be in the same schema.
11295 if (OidIsValid(tbinfo->owning_tab))
11297 TableInfo *owning_tab = findTableByOid(tbinfo->owning_tab);
11299 if (owning_tab && owning_tab->dobj.dump)
11301 resetPQExpBuffer(query);
11302 appendPQExpBuffer(query, "ALTER SEQUENCE %s",
11303 fmtId(tbinfo->dobj.name));
11304 appendPQExpBuffer(query, " OWNED BY %s",
11305 fmtId(owning_tab->dobj.name));
11306 appendPQExpBuffer(query, ".%s;\n",
11307 fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
11309 ArchiveEntry(fout, nilCatalogId, createDumpId(),
11311 tbinfo->dobj.namespace->dobj.name,
11314 false, "SEQUENCE OWNED BY", SECTION_PRE_DATA,
11315 query->data, "", NULL,
11316 &(tbinfo->dobj.dumpId), 1,
11321 /* Dump Sequence Comments */
11322 resetPQExpBuffer(query);
11323 appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
11324 dumpComment(fout, query->data,
11325 tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
11326 tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
11331 resetPQExpBuffer(query);
11332 appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
11333 appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
11334 appendPQExpBuffer(query, ", %s, %s);\n",
11335 last, (called ? "true" : "false"));
11337 ArchiveEntry(fout, nilCatalogId, createDumpId(),
11339 tbinfo->dobj.namespace->dobj.name,
11342 false, "SEQUENCE SET", SECTION_PRE_DATA,
11343 query->data, "", NULL,
11344 &(tbinfo->dobj.dumpId), 1,
11350 destroyPQExpBuffer(query);
11351 destroyPQExpBuffer(delqry);
11355 dumpTrigger(Archive *fout, TriggerInfo *tginfo)
11357 TableInfo *tbinfo = tginfo->tgtable;
11359 PQExpBuffer delqry;
11368 query = createPQExpBuffer();
11369 delqry = createPQExpBuffer();
11372 * DROP must be fully qualified in case same name appears in pg_catalog
11374 appendPQExpBuffer(delqry, "DROP TRIGGER %s ",
11375 fmtId(tginfo->dobj.name));
11376 appendPQExpBuffer(delqry, "ON %s.",
11377 fmtId(tbinfo->dobj.namespace->dobj.name));
11378 appendPQExpBuffer(delqry, "%s;\n",
11379 fmtId(tbinfo->dobj.name));
11383 appendPQExpBuffer(query, "%s;\n", tginfo->tgdef);
11387 if (tginfo->tgisconstraint)
11389 appendPQExpBuffer(query, "CREATE CONSTRAINT TRIGGER ");
11390 appendPQExpBufferStr(query, fmtId(tginfo->tgconstrname));
11394 appendPQExpBuffer(query, "CREATE TRIGGER ");
11395 appendPQExpBufferStr(query, fmtId(tginfo->dobj.name));
11397 appendPQExpBuffer(query, "\n ");
11401 if (TRIGGER_FOR_BEFORE(tginfo->tgtype))
11402 appendPQExpBuffer(query, "BEFORE");
11404 appendPQExpBuffer(query, "AFTER");
11405 if (TRIGGER_FOR_INSERT(tginfo->tgtype))
11407 appendPQExpBuffer(query, " INSERT");
11410 if (TRIGGER_FOR_DELETE(tginfo->tgtype))
11413 appendPQExpBuffer(query, " OR DELETE");
11415 appendPQExpBuffer(query, " DELETE");
11418 if (TRIGGER_FOR_UPDATE(tginfo->tgtype))
11421 appendPQExpBuffer(query, " OR UPDATE");
11423 appendPQExpBuffer(query, " UPDATE");
11426 if (TRIGGER_FOR_TRUNCATE(tginfo->tgtype))
11429 appendPQExpBuffer(query, " OR TRUNCATE");
11431 appendPQExpBuffer(query, " TRUNCATE");
11434 appendPQExpBuffer(query, " ON %s\n",
11435 fmtId(tbinfo->dobj.name));
11437 if (tginfo->tgisconstraint)
11439 if (OidIsValid(tginfo->tgconstrrelid))
11441 /* If we are using regclass, name is already quoted */
11442 if (g_fout->remoteVersion >= 70300)
11443 appendPQExpBuffer(query, " FROM %s\n ",
11444 tginfo->tgconstrrelname);
11446 appendPQExpBuffer(query, " FROM %s\n ",
11447 fmtId(tginfo->tgconstrrelname));
11449 if (!tginfo->tgdeferrable)
11450 appendPQExpBuffer(query, "NOT ");
11451 appendPQExpBuffer(query, "DEFERRABLE INITIALLY ");
11452 if (tginfo->tginitdeferred)
11453 appendPQExpBuffer(query, "DEFERRED\n");
11455 appendPQExpBuffer(query, "IMMEDIATE\n");
11458 if (TRIGGER_FOR_ROW(tginfo->tgtype))
11459 appendPQExpBuffer(query, " FOR EACH ROW\n ");
11461 appendPQExpBuffer(query, " FOR EACH STATEMENT\n ");
11463 /* In 7.3, result of regproc is already quoted */
11464 if (g_fout->remoteVersion >= 70300)
11465 appendPQExpBuffer(query, "EXECUTE PROCEDURE %s(",
11468 appendPQExpBuffer(query, "EXECUTE PROCEDURE %s(",
11469 fmtId(tginfo->tgfname));
11471 tgargs = (char *) PQunescapeBytea((unsigned char *) tginfo->tgargs,
11474 for (findx = 0; findx < tginfo->tgnargs; findx++)
11476 /* find the embedded null that terminates this trigger argument */
11477 size_t tlen = strlen(p);
11479 if (p + tlen >= tgargs + lentgargs)
11481 /* hm, not found before end of bytea value... */
11482 write_msg(NULL, "invalid argument string (%s) for trigger \"%s\" on table \"%s\"\n",
11485 tbinfo->dobj.name);
11490 appendPQExpBuffer(query, ", ");
11491 appendStringLiteralAH(query, p, fout);
11495 appendPQExpBuffer(query, ");\n");
11498 if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
11500 appendPQExpBuffer(query, "\nALTER TABLE %s ",
11501 fmtId(tbinfo->dobj.name));
11502 switch (tginfo->tgenabled)
11506 appendPQExpBuffer(query, "DISABLE");
11509 appendPQExpBuffer(query, "ENABLE ALWAYS");
11512 appendPQExpBuffer(query, "ENABLE REPLICA");
11515 appendPQExpBuffer(query, "ENABLE");
11518 appendPQExpBuffer(query, " TRIGGER %s;\n",
11519 fmtId(tginfo->dobj.name));
11522 ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
11524 tbinfo->dobj.namespace->dobj.name,
11526 tbinfo->rolname, false,
11527 "TRIGGER", SECTION_POST_DATA,
11528 query->data, delqry->data, NULL,
11529 tginfo->dobj.dependencies, tginfo->dobj.nDeps,
11532 resetPQExpBuffer(query);
11533 appendPQExpBuffer(query, "TRIGGER %s ",
11534 fmtId(tginfo->dobj.name));
11535 appendPQExpBuffer(query, "ON %s",
11536 fmtId(tbinfo->dobj.name));
11538 dumpComment(fout, query->data,
11539 tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
11540 tginfo->dobj.catId, 0, tginfo->dobj.dumpId);
11542 destroyPQExpBuffer(query);
11543 destroyPQExpBuffer(delqry);
11551 dumpRule(Archive *fout, RuleInfo *rinfo)
11553 TableInfo *tbinfo = rinfo->ruletable;
11556 PQExpBuffer delcmd;
11559 /* Skip if not to be dumped */
11560 if (!rinfo->dobj.dump || dataOnly)
11564 * If it is an ON SELECT rule that is created implicitly by CREATE VIEW,
11565 * we do not want to dump it as a separate object.
11567 if (!rinfo->separate)
11571 * Make sure we are in proper schema.
11573 selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
11575 query = createPQExpBuffer();
11576 cmd = createPQExpBuffer();
11577 delcmd = createPQExpBuffer();
11579 if (g_fout->remoteVersion >= 70300)
11581 appendPQExpBuffer(query,
11582 "SELECT pg_catalog.pg_get_ruledef('%u'::pg_catalog.oid) AS definition",
11583 rinfo->dobj.catId.oid);
11587 /* Rule name was unique before 7.3 ... */
11588 appendPQExpBuffer(query,
11589 "SELECT pg_get_ruledef('%s') AS definition",
11593 res = PQexec(g_conn, query->data);
11594 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11596 if (PQntuples(res) != 1)
11598 write_msg(NULL, "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned\n",
11599 rinfo->dobj.name, tbinfo->dobj.name);
11603 printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, 0, 0));
11606 * Add the command to alter the rules replication firing semantics if it
11607 * differs from the default.
11609 if (rinfo->ev_enabled != 'O')
11611 appendPQExpBuffer(cmd, "ALTER TABLE %s.",
11612 fmtId(tbinfo->dobj.namespace->dobj.name));
11613 appendPQExpBuffer(cmd, "%s ",
11614 fmtId(tbinfo->dobj.name));
11615 switch (rinfo->ev_enabled)
11618 appendPQExpBuffer(cmd, "ENABLE ALWAYS RULE %s;\n",
11619 fmtId(rinfo->dobj.name));
11622 appendPQExpBuffer(cmd, "ENABLE REPLICA RULE %s;\n",
11623 fmtId(rinfo->dobj.name));
11626 appendPQExpBuffer(cmd, "DISABLE RULE %s;\n",
11627 fmtId(rinfo->dobj.name));
11633 * DROP must be fully qualified in case same name appears in pg_catalog
11635 appendPQExpBuffer(delcmd, "DROP RULE %s ",
11636 fmtId(rinfo->dobj.name));
11637 appendPQExpBuffer(delcmd, "ON %s.",
11638 fmtId(tbinfo->dobj.namespace->dobj.name));
11639 appendPQExpBuffer(delcmd, "%s;\n",
11640 fmtId(tbinfo->dobj.name));
11642 ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
11644 tbinfo->dobj.namespace->dobj.name,
11646 tbinfo->rolname, false,
11647 "RULE", SECTION_POST_DATA,
11648 cmd->data, delcmd->data, NULL,
11649 rinfo->dobj.dependencies, rinfo->dobj.nDeps,
11652 /* Dump rule comments */
11653 resetPQExpBuffer(query);
11654 appendPQExpBuffer(query, "RULE %s",
11655 fmtId(rinfo->dobj.name));
11656 appendPQExpBuffer(query, " ON %s",
11657 fmtId(tbinfo->dobj.name));
11658 dumpComment(fout, query->data,
11659 tbinfo->dobj.namespace->dobj.name,
11661 rinfo->dobj.catId, 0, rinfo->dobj.dumpId);
11665 destroyPQExpBuffer(query);
11666 destroyPQExpBuffer(cmd);
11667 destroyPQExpBuffer(delcmd);
11671 * getDependencies --- obtain available dependency data
11674 getDependencies(void)
11685 DumpableObject *dobj,
11688 /* No dependency info available before 7.3 */
11689 if (g_fout->remoteVersion < 70300)
11693 write_msg(NULL, "reading dependency data\n");
11695 /* Make sure we are in proper schema */
11696 selectSourceSchema("pg_catalog");
11698 query = createPQExpBuffer();
11700 appendPQExpBuffer(query, "SELECT "
11701 "classid, objid, refclassid, refobjid, deptype "
11703 "WHERE deptype != 'p' "
11706 res = PQexec(g_conn, query->data);
11707 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11709 ntups = PQntuples(res);
11711 i_classid = PQfnumber(res, "classid");
11712 i_objid = PQfnumber(res, "objid");
11713 i_refclassid = PQfnumber(res, "refclassid");
11714 i_refobjid = PQfnumber(res, "refobjid");
11715 i_deptype = PQfnumber(res, "deptype");
11718 * Since we ordered the SELECT by referencing ID, we can expect that
11719 * multiple entries for the same object will appear together; this saves
11724 for (i = 0; i < ntups; i++)
11727 CatalogId refobjId;
11730 objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
11731 objId.oid = atooid(PQgetvalue(res, i, i_objid));
11732 refobjId.tableoid = atooid(PQgetvalue(res, i, i_refclassid));
11733 refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid));
11734 deptype = *(PQgetvalue(res, i, i_deptype));
11736 if (dobj == NULL ||
11737 dobj->catId.tableoid != objId.tableoid ||
11738 dobj->catId.oid != objId.oid)
11739 dobj = findObjectByCatalogId(objId);
11742 * Failure to find objects mentioned in pg_depend is not unexpected,
11743 * since for example we don't collect info about TOAST tables.
11748 fprintf(stderr, "no referencing object %u %u\n",
11749 objId.tableoid, objId.oid);
11754 refdobj = findObjectByCatalogId(refobjId);
11756 if (refdobj == NULL)
11759 fprintf(stderr, "no referenced object %u %u\n",
11760 refobjId.tableoid, refobjId.oid);
11766 * Ordinarily, table rowtypes have implicit dependencies on their
11767 * tables. However, for a composite type the implicit dependency goes
11768 * the other way in pg_depend; which is the right thing for DROP but
11769 * it doesn't produce the dependency ordering we need. So in that one
11770 * case, we reverse the direction of the dependency.
11772 if (deptype == 'i' &&
11773 dobj->objType == DO_TABLE &&
11774 refdobj->objType == DO_TYPE)
11775 addObjectDependency(refdobj, dobj->dumpId);
11778 addObjectDependency(dobj, refdobj->dumpId);
11783 destroyPQExpBuffer(query);
11788 * selectSourceSchema - make the specified schema the active search path
11789 * in the source database.
11791 * NB: pg_catalog is explicitly searched after the specified schema;
11792 * so user names are only qualified if they are cross-schema references,
11793 * and system names are only qualified if they conflict with a user name
11794 * in the current schema.
11796 * Whenever the selected schema is not pg_catalog, be careful to qualify
11797 * references to system catalogs and types in our emitted commands!
11800 selectSourceSchema(const char *schemaName)
11802 static char *curSchemaName = NULL;
11805 /* Not relevant if fetching from pre-7.3 DB */
11806 if (g_fout->remoteVersion < 70300)
11808 /* Ignore null schema names */
11809 if (schemaName == NULL || *schemaName == '\0')
11811 /* Optimize away repeated selection of same schema */
11812 if (curSchemaName && strcmp(curSchemaName, schemaName) == 0)
11815 query = createPQExpBuffer();
11816 appendPQExpBuffer(query, "SET search_path = %s",
11817 fmtId(schemaName));
11818 if (strcmp(schemaName, "pg_catalog") != 0)
11819 appendPQExpBuffer(query, ", pg_catalog");
11821 do_sql_command(g_conn, query->data);
11823 destroyPQExpBuffer(query);
11825 free(curSchemaName);
11826 curSchemaName = strdup(schemaName);
11830 * getFormattedTypeName - retrieve a nicely-formatted type name for the
11833 * NB: in 7.3 and up the result may depend on the currently-selected
11834 * schema; this is why we don't try to cache the names.
11837 getFormattedTypeName(Oid oid, OidOptions opts)
11846 if ((opts & zeroAsOpaque) != 0)
11847 return strdup(g_opaque_type);
11848 else if ((opts & zeroAsAny) != 0)
11849 return strdup("'any'");
11850 else if ((opts & zeroAsStar) != 0)
11851 return strdup("*");
11852 else if ((opts & zeroAsNone) != 0)
11853 return strdup("NONE");
11856 query = createPQExpBuffer();
11857 if (g_fout->remoteVersion >= 70300)
11859 appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)",
11862 else if (g_fout->remoteVersion >= 70100)
11864 appendPQExpBuffer(query, "SELECT format_type('%u'::oid, NULL)",
11869 appendPQExpBuffer(query, "SELECT typname "
11871 "WHERE oid = '%u'::oid",
11875 res = PQexec(g_conn, query->data);
11876 check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
11878 /* Expecting a single result only */
11879 ntups = PQntuples(res);
11882 write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
11883 "query returned %d rows instead of one: %s\n",
11885 ntups, query->data);
11889 if (g_fout->remoteVersion >= 70100)
11891 /* already quoted */
11892 result = strdup(PQgetvalue(res, 0, 0));
11896 /* may need to quote it */
11897 result = strdup(fmtId(PQgetvalue(res, 0, 0)));
11901 destroyPQExpBuffer(query);
11907 * myFormatType --- local implementation of format_type for use with 7.0.
11910 myFormatType(const char *typname, int32 typmod)
11913 bool isarray = false;
11914 PQExpBuffer buf = createPQExpBuffer();
11916 /* Handle array types */
11917 if (typname[0] == '_')
11923 /* Show lengths on bpchar and varchar */
11924 if (!strcmp(typname, "bpchar"))
11926 int len = (typmod - VARHDRSZ);
11928 appendPQExpBuffer(buf, "character");
11930 appendPQExpBuffer(buf, "(%d)",
11931 typmod - VARHDRSZ);
11933 else if (!strcmp(typname, "varchar"))
11935 appendPQExpBuffer(buf, "character varying");
11937 appendPQExpBuffer(buf, "(%d)",
11938 typmod - VARHDRSZ);
11940 else if (!strcmp(typname, "numeric"))
11942 appendPQExpBuffer(buf, "numeric");
11949 tmp_typmod = typmod - VARHDRSZ;
11950 precision = (tmp_typmod >> 16) & 0xffff;
11951 scale = tmp_typmod & 0xffff;
11952 appendPQExpBuffer(buf, "(%d,%d)",
11958 * char is an internal single-byte data type; Let's make sure we force it
11959 * through with quotes. - thomas 1998-12-13
11961 else if (strcmp(typname, "char") == 0)
11962 appendPQExpBuffer(buf, "\"char\"");
11964 appendPQExpBuffer(buf, "%s", fmtId(typname));
11966 /* Append array qualifier for array types */
11968 appendPQExpBuffer(buf, "[]");
11970 result = strdup(buf->data);
11971 destroyPQExpBuffer(buf);
11977 * fmtQualifiedId - convert a qualified name to the proper format for
11978 * the source database.
11980 * Like fmtId, use the result before calling again.
11982 static const char *
11983 fmtQualifiedId(const char *schema, const char *id)
11985 static PQExpBuffer id_return = NULL;
11987 if (id_return) /* first time through? */
11988 resetPQExpBuffer(id_return);
11990 id_return = createPQExpBuffer();
11992 /* Suppress schema name if fetching from pre-7.3 DB */
11993 if (g_fout->remoteVersion >= 70300 && schema && *schema)
11995 appendPQExpBuffer(id_return, "%s.",
11998 appendPQExpBuffer(id_return, "%s",
12001 return id_return->data;
12005 * Return a column list clause for the given relation.
12007 * Special case: if there are no undropped columns in the relation, return
12008 * "", not an invalid "()" column list.
12010 static const char *
12011 fmtCopyColumnList(const TableInfo *ti)
12013 static PQExpBuffer q = NULL;
12014 int numatts = ti->numatts;
12015 char **attnames = ti->attnames;
12016 bool *attisdropped = ti->attisdropped;
12020 if (q) /* first time through? */
12021 resetPQExpBuffer(q);
12023 q = createPQExpBuffer();
12025 appendPQExpBuffer(q, "(");
12027 for (i = 0; i < numatts; i++)
12029 if (attisdropped[i])
12032 appendPQExpBuffer(q, ", ");
12033 appendPQExpBuffer(q, "%s", fmtId(attnames[i]));
12038 return ""; /* no undropped columns */
12040 appendPQExpBuffer(q, ")");
12045 * Convenience subroutine to execute a SQL command and check for
12046 * COMMAND_OK status.
12049 do_sql_command(PGconn *conn, const char *query)
12053 res = PQexec(conn, query);
12054 check_sql_result(res, conn, query, PGRES_COMMAND_OK);
12059 * Convenience subroutine to verify a SQL command succeeded,
12060 * and exit with a useful error message if not.
12063 check_sql_result(PGresult *res, PGconn *conn, const char *query,
12064 ExecStatusType expected)
12068 if (res && PQresultStatus(res) == expected)
12071 write_msg(NULL, "SQL command failed\n");
12073 err = PQresultErrorMessage(res);
12075 err = PQerrorMessage(conn);
12076 write_msg(NULL, "Error message from server: %s", err);
12077 write_msg(NULL, "The command was: %s\n", query);