1 /*-------------------------------------------------------------------------
4 * pg_dump is a utility for dumping out a postgres database
7 * Portions Copyright (c) 1996-2008, 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
17 *-------------------------------------------------------------------------
20 #include "postgres_fe.h"
31 #include "getopt_long.h"
33 #ifndef HAVE_INT_OPTRESET
37 #include "access/attnum.h"
38 #include "access/sysattr.h"
39 #include "catalog/pg_class.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 */
69 bool dumpInserts
; /* dump data using proper insert strings */
70 bool attrNames
; /* put attr names into insert strings */
74 const char *lockWaitTimeout
;
76 /* subquery used to convert user ID (eg, datdba) to user name */
77 static const char *username_subquery
;
79 /* obsolete as of 7.3: */
80 static Oid g_last_builtin_oid
; /* value of the last builtin oid */
83 * Object inclusion/exclusion lists
85 * The string lists record the patterns given by command-line switches,
86 * which we then convert to lists of OIDs of matching objects.
88 static SimpleStringList schema_include_patterns
= {NULL
, NULL
};
89 static SimpleOidList schema_include_oids
= {NULL
, NULL
};
90 static SimpleStringList schema_exclude_patterns
= {NULL
, NULL
};
91 static SimpleOidList schema_exclude_oids
= {NULL
, NULL
};
93 static SimpleStringList table_include_patterns
= {NULL
, NULL
};
94 static SimpleOidList table_include_oids
= {NULL
, NULL
};
95 static SimpleStringList table_exclude_patterns
= {NULL
, NULL
};
96 static SimpleOidList table_exclude_oids
= {NULL
, NULL
};
98 /* default, if no "inclusion" switches appear, is to dump everything */
99 static bool include_everything
= true;
101 char g_opaque_type
[10]; /* name for the opaque type */
103 /* placeholders for the delimiters for comments */
104 char g_comment_start
[10];
105 char g_comment_end
[10];
107 static const CatalogId nilCatalogId
= {0, 0};
109 /* these are to avoid passing around info for findNamespace() */
110 static NamespaceInfo
*g_namespaces
;
111 static int g_numNamespaces
;
113 /* flag to turn on/off dollar quoting */
114 static int disable_dollar_quoting
= 0;
117 static void help(const char *progname
);
118 static void expand_schema_name_patterns(SimpleStringList
*patterns
,
119 SimpleOidList
*oids
);
120 static void expand_table_name_patterns(SimpleStringList
*patterns
,
121 SimpleOidList
*oids
);
122 static NamespaceInfo
*findNamespace(Oid nsoid
, Oid objoid
);
123 static void dumpTableData(Archive
*fout
, TableDataInfo
*tdinfo
);
124 static void guessConstraintInheritance(TableInfo
*tblinfo
, int numTables
);
125 static void dumpComment(Archive
*fout
, const char *target
,
126 const char *namespace, const char *owner
,
127 CatalogId catalogId
, int subid
, DumpId dumpId
);
128 static int findComments(Archive
*fout
, Oid classoid
, Oid objoid
,
129 CommentItem
**items
);
130 static int collectComments(Archive
*fout
, CommentItem
**items
);
131 static void dumpDumpableObject(Archive
*fout
, DumpableObject
*dobj
);
132 static void dumpNamespace(Archive
*fout
, NamespaceInfo
*nspinfo
);
133 static void dumpType(Archive
*fout
, TypeInfo
*tinfo
);
134 static void dumpBaseType(Archive
*fout
, TypeInfo
*tinfo
);
135 static void dumpEnumType(Archive
*fout
, TypeInfo
*tinfo
);
136 static void dumpDomain(Archive
*fout
, TypeInfo
*tinfo
);
137 static void dumpCompositeType(Archive
*fout
, TypeInfo
*tinfo
);
138 static void dumpShellType(Archive
*fout
, ShellTypeInfo
*stinfo
);
139 static void dumpProcLang(Archive
*fout
, ProcLangInfo
*plang
);
140 static void dumpFunc(Archive
*fout
, FuncInfo
*finfo
);
141 static void dumpCast(Archive
*fout
, CastInfo
*cast
);
142 static void dumpOpr(Archive
*fout
, OprInfo
*oprinfo
);
143 static void dumpOpclass(Archive
*fout
, OpclassInfo
*opcinfo
);
144 static void dumpOpfamily(Archive
*fout
, OpfamilyInfo
*opfinfo
);
145 static void dumpConversion(Archive
*fout
, ConvInfo
*convinfo
);
146 static void dumpRule(Archive
*fout
, RuleInfo
*rinfo
);
147 static void dumpAgg(Archive
*fout
, AggInfo
*agginfo
);
148 static void dumpTrigger(Archive
*fout
, TriggerInfo
*tginfo
);
149 static void dumpTable(Archive
*fout
, TableInfo
*tbinfo
);
150 static void dumpTableSchema(Archive
*fout
, TableInfo
*tbinfo
);
151 static void dumpAttrDef(Archive
*fout
, AttrDefInfo
*adinfo
);
152 static void dumpSequence(Archive
*fout
, TableInfo
*tbinfo
);
153 static void dumpIndex(Archive
*fout
, IndxInfo
*indxinfo
);
154 static void dumpConstraint(Archive
*fout
, ConstraintInfo
*coninfo
);
155 static void dumpTableConstraintComment(Archive
*fout
, ConstraintInfo
*coninfo
);
156 static void dumpTSParser(Archive
*fout
, TSParserInfo
*prsinfo
);
157 static void dumpTSDictionary(Archive
*fout
, TSDictInfo
*dictinfo
);
158 static void dumpTSTemplate(Archive
*fout
, TSTemplateInfo
*tmplinfo
);
159 static void dumpTSConfig(Archive
*fout
, TSConfigInfo
*cfginfo
);
161 static void dumpACL(Archive
*fout
, CatalogId objCatId
, DumpId objDumpId
,
162 const char *type
, const char *name
,
163 const char *tag
, const char *nspname
, const char *owner
,
166 static void getDependencies(void);
167 static void getDomainConstraints(TypeInfo
*tinfo
);
168 static void getTableData(TableInfo
*tblinfo
, int numTables
, bool oids
);
169 static void getTableDataFKConstraints(void);
170 static char *format_function_arguments(FuncInfo
*finfo
, char *funcargs
);
171 static char *format_function_arguments_old(FuncInfo
*finfo
, int nallargs
,
175 static char *format_function_signature(FuncInfo
*finfo
, bool honor_quotes
);
176 static const char *convertRegProcReference(const char *proc
);
177 static const char *convertOperatorReference(const char *opr
);
178 static const char *convertTSFunction(Oid funcOid
);
179 static Oid
findLastBuiltinOid_V71(const char *);
180 static Oid
findLastBuiltinOid_V70(void);
181 static void selectSourceSchema(const char *schemaName
);
182 static char *getFormattedTypeName(Oid oid
, OidOptions opts
);
183 static char *myFormatType(const char *typname
, int32 typmod
);
184 static const char *fmtQualifiedId(const char *schema
, const char *id
);
185 static bool hasBlobs(Archive
*AH
);
186 static int dumpBlobs(Archive
*AH
, void *arg
);
187 static int dumpBlobComments(Archive
*AH
, void *arg
);
188 static void dumpDatabase(Archive
*AH
);
189 static void dumpEncoding(Archive
*AH
);
190 static void dumpStdStrings(Archive
*AH
);
191 static const char *getAttrName(int attrnum
, TableInfo
*tblInfo
);
192 static const char *fmtCopyColumnList(const TableInfo
*ti
);
193 static void do_sql_command(PGconn
*conn
, const char *query
);
194 static void check_sql_result(PGresult
*res
, PGconn
*conn
, const char *query
,
195 ExecStatusType expected
);
199 main(int argc
, char **argv
)
202 const char *filename
= NULL
;
203 const char *format
= "p";
204 const char *dbname
= NULL
;
205 const char *pghost
= NULL
;
206 const char *pgport
= NULL
;
207 const char *username
= NULL
;
208 const char *dumpencoding
= NULL
;
209 const char *std_strings
;
213 DumpableObject
**dobjs
;
216 bool force_password
= false;
217 int compressLevel
= -1;
220 int outputCreate
= 0;
221 bool outputBlobs
= false;
222 int outputNoOwner
= 0;
223 char *outputSuperuser
= NULL
;
226 RestoreOptions
*ropt
;
228 static int disable_triggers
= 0;
229 static int outputNoTablespaces
= 0;
230 static int use_setsessauth
= 0;
232 static struct option long_options
[] = {
233 {"data-only", no_argument
, NULL
, 'a'},
234 {"blobs", no_argument
, NULL
, 'b'},
235 {"clean", no_argument
, NULL
, 'c'},
236 {"create", no_argument
, NULL
, 'C'},
237 {"file", required_argument
, NULL
, 'f'},
238 {"format", required_argument
, NULL
, 'F'},
239 {"inserts", no_argument
, NULL
, 'd'},
240 {"attribute-inserts", no_argument
, NULL
, 'D'},
241 {"column-inserts", no_argument
, NULL
, 'D'},
242 {"host", required_argument
, NULL
, 'h'},
243 {"ignore-version", no_argument
, NULL
, 'i'},
244 {"no-reconnect", no_argument
, NULL
, 'R'},
245 {"oids", no_argument
, NULL
, 'o'},
246 {"no-owner", no_argument
, NULL
, 'O'},
247 {"port", required_argument
, NULL
, 'p'},
248 {"schema", required_argument
, NULL
, 'n'},
249 {"exclude-schema", required_argument
, NULL
, 'N'},
250 {"schema-only", no_argument
, NULL
, 's'},
251 {"superuser", required_argument
, NULL
, 'S'},
252 {"table", required_argument
, NULL
, 't'},
253 {"exclude-table", required_argument
, NULL
, 'T'},
254 {"password", no_argument
, NULL
, 'W'},
255 {"username", required_argument
, NULL
, 'U'},
256 {"verbose", no_argument
, NULL
, 'v'},
257 {"no-privileges", no_argument
, NULL
, 'x'},
258 {"no-acl", no_argument
, NULL
, 'x'},
259 {"compress", required_argument
, NULL
, 'Z'},
260 {"encoding", required_argument
, NULL
, 'E'},
261 {"help", no_argument
, NULL
, '?'},
262 {"version", no_argument
, NULL
, 'V'},
265 * the following options don't have an equivalent short option letter
267 {"disable-dollar-quoting", no_argument
, &disable_dollar_quoting
, 1},
268 {"disable-triggers", no_argument
, &disable_triggers
, 1},
269 {"lock-wait-timeout", required_argument
, NULL
, 2},
270 {"no-tablespaces", no_argument
, &outputNoTablespaces
, 1},
271 {"use-set-session-authorization", no_argument
, &use_setsessauth
, 1},
276 set_pglocale_pgservice(argv
[0], "pg_dump");
280 strcpy(g_comment_start
, "-- ");
281 g_comment_end
[0] = '\0';
282 strcpy(g_opaque_type
, "opaque");
284 dataOnly
= schemaOnly
= dumpInserts
= attrNames
= false;
285 lockWaitTimeout
= NULL
;
287 progname
= get_progname(argv
[0]);
289 /* Set default options based on progname */
290 if (strcmp(progname
, "pg_backup") == 0)
295 if (strcmp(argv
[1], "--help") == 0 || strcmp(argv
[1], "-?") == 0)
300 if (strcmp(argv
[1], "--version") == 0 || strcmp(argv
[1], "-V") == 0)
302 puts("pg_dump (PostgreSQL) " PG_VERSION
);
307 while ((c
= getopt_long(argc
, argv
, "abcCdDE:f:F:h:in:N:oOp:RsS:t:T:U:vWxX:Z:",
308 long_options
, &optindex
)) != -1)
312 case 'a': /* Dump data only */
316 case 'b': /* Dump blobs */
320 case 'c': /* clean (i.e., drop) schema prior to create */
324 case 'C': /* Create DB */
328 case 'd': /* dump data as proper insert strings */
332 case 'D': /* dump data as proper insert strings with
338 case 'E': /* Dump encoding */
339 dumpencoding
= optarg
;
350 case 'h': /* server host */
355 /* ignored, deprecated option */
358 case 'n': /* include schema(s) */
359 simple_string_list_append(&schema_include_patterns
, optarg
);
360 include_everything
= false;
363 case 'N': /* exclude schema(s) */
364 simple_string_list_append(&schema_exclude_patterns
, optarg
);
367 case 'o': /* Dump oids */
371 case 'O': /* Don't reconnect to match owner */
375 case 'p': /* server port */
380 /* no-op, still accepted for backwards compatibility */
383 case 's': /* dump schema only */
387 case 'S': /* Username for superuser in plain text output */
388 outputSuperuser
= strdup(optarg
);
391 case 't': /* include table(s) */
392 simple_string_list_append(&table_include_patterns
, optarg
);
393 include_everything
= false;
396 case 'T': /* exclude table(s) */
397 simple_string_list_append(&table_exclude_patterns
, optarg
);
404 case 'v': /* verbose */
409 force_password
= true;
412 case 'x': /* skip ACL dump */
417 /* -X is a deprecated alternative to long options */
418 if (strcmp(optarg
, "disable-dollar-quoting") == 0)
419 disable_dollar_quoting
= 1;
420 else if (strcmp(optarg
, "disable-triggers") == 0)
421 disable_triggers
= 1;
422 else if (strcmp(optarg
, "no-tablespaces") == 0)
423 outputNoTablespaces
= 1;
424 else if (strcmp(optarg
, "use-set-session-authorization") == 0)
429 _("%s: invalid -X option -- %s\n"),
431 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), progname
);
436 case 'Z': /* Compression Level */
437 compressLevel
= atoi(optarg
);
441 /* This covers the long options equivalent to -X xxx. */
445 /* lock-wait-timeout */
446 lockWaitTimeout
= optarg
;
450 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), progname
);
455 if (optind
< (argc
- 1))
457 fprintf(stderr
, _("%s: too many command-line arguments (first is \"%s\")\n"),
458 progname
, argv
[optind
+ 1]);
459 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
464 /* Get database name from command line */
466 dbname
= argv
[optind
];
468 if (dataOnly
&& schemaOnly
)
470 write_msg(NULL
, "options -s/--schema-only and -a/--data-only cannot be used together\n");
474 if (dataOnly
&& outputClean
)
476 write_msg(NULL
, "options -c/--clean and -a/--data-only cannot be used together\n");
480 if (dumpInserts
== true && oids
== true)
482 write_msg(NULL
, "options -d/-D/--inserts/--column-inserts and -o/--oids cannot be used together\n");
483 write_msg(NULL
, "(The INSERT command cannot set OIDs.)\n");
487 /* open the output file */
488 if (pg_strcasecmp(format
, "a") == 0 || pg_strcasecmp(format
, "append") == 0)
490 /* This is used by pg_dumpall, and is not documented */
492 g_fout
= CreateArchive(filename
, archNull
, 0, archModeAppend
);
494 else if (pg_strcasecmp(format
, "c") == 0 || pg_strcasecmp(format
, "custom") == 0)
495 g_fout
= CreateArchive(filename
, archCustom
, compressLevel
, archModeWrite
);
496 else if (pg_strcasecmp(format
, "f") == 0 || pg_strcasecmp(format
, "file") == 0)
499 * Dump files into the current directory; for demonstration only, not
502 g_fout
= CreateArchive(filename
, archFiles
, compressLevel
, archModeWrite
);
504 else if (pg_strcasecmp(format
, "p") == 0 || pg_strcasecmp(format
, "plain") == 0)
507 g_fout
= CreateArchive(filename
, archNull
, 0, archModeWrite
);
509 else if (pg_strcasecmp(format
, "t") == 0 || pg_strcasecmp(format
, "tar") == 0)
510 g_fout
= CreateArchive(filename
, archTar
, compressLevel
, archModeWrite
);
513 write_msg(NULL
, "invalid output format \"%s\" specified\n", format
);
519 write_msg(NULL
, "could not open output file \"%s\" for writing\n", filename
);
523 /* Let the archiver know how noisy to be */
524 g_fout
->verbose
= g_verbose
;
526 my_version
= parse_version(PG_VERSION
);
529 write_msg(NULL
, "could not parse version string \"%s\"\n", PG_VERSION
);
534 * We allow the server to be back to 7.0, and up to any minor release
535 * of our own major version. (See also version check in pg_dumpall.c.)
537 g_fout
->minRemoteVersion
= 70000;
538 g_fout
->maxRemoteVersion
= (my_version
/ 100) * 100 + 99;
541 * Open the database using the Archiver, so it knows about it. Errors mean
544 g_conn
= ConnectDatabase(g_fout
, dbname
, pghost
, pgport
,
545 username
, force_password
);
547 /* Set the client encoding if requested */
550 if (PQsetClientEncoding(g_conn
, dumpencoding
) < 0)
552 write_msg(NULL
, "invalid client encoding \"%s\" specified\n",
559 * Get the active encoding and the standard_conforming_strings setting, so
560 * we know how to escape strings.
562 g_fout
->encoding
= PQclientEncoding(g_conn
);
564 std_strings
= PQparameterStatus(g_conn
, "standard_conforming_strings");
565 g_fout
->std_strings
= (std_strings
&& strcmp(std_strings
, "on") == 0);
567 /* Set the datestyle to ISO to ensure the dump's portability */
568 do_sql_command(g_conn
, "SET DATESTYLE = ISO");
571 * If supported, set extra_float_digits so that we can dump float data
572 * exactly (given correctly implemented float I/O code, anyway)
574 if (g_fout
->remoteVersion
>= 70400)
575 do_sql_command(g_conn
, "SET extra_float_digits TO 2");
578 * If synchronized scanning is supported, disable it, to prevent
579 * unpredictable changes in row ordering across a dump and reload.
581 if (g_fout
->remoteVersion
>= 80300)
582 do_sql_command(g_conn
, "SET synchronize_seqscans TO off");
585 * Disable timeouts if supported.
587 if (g_fout
->remoteVersion
>= 70300)
588 do_sql_command(g_conn
, "SET statement_timeout = 0");
591 * Start serializable transaction to dump consistent data.
593 do_sql_command(g_conn
, "BEGIN");
595 do_sql_command(g_conn
, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
597 /* Select the appropriate subquery to convert user IDs to names */
598 if (g_fout
->remoteVersion
>= 80100)
599 username_subquery
= "SELECT rolname FROM pg_catalog.pg_roles WHERE oid =";
600 else if (g_fout
->remoteVersion
>= 70300)
601 username_subquery
= "SELECT usename FROM pg_catalog.pg_user WHERE usesysid =";
603 username_subquery
= "SELECT usename FROM pg_user WHERE usesysid =";
605 /* Find the last built-in OID, if needed */
606 if (g_fout
->remoteVersion
< 70300)
608 if (g_fout
->remoteVersion
>= 70100)
609 g_last_builtin_oid
= findLastBuiltinOid_V71(PQdb(g_conn
));
611 g_last_builtin_oid
= findLastBuiltinOid_V70();
613 write_msg(NULL
, "last built-in OID is %u\n", g_last_builtin_oid
);
616 /* Expand schema selection patterns into OID lists */
617 if (schema_include_patterns
.head
!= NULL
)
619 expand_schema_name_patterns(&schema_include_patterns
,
620 &schema_include_oids
);
621 if (schema_include_oids
.head
== NULL
)
623 write_msg(NULL
, "No matching schemas were found\n");
627 expand_schema_name_patterns(&schema_exclude_patterns
,
628 &schema_exclude_oids
);
629 /* non-matching exclusion patterns aren't an error */
631 /* Expand table selection patterns into OID lists */
632 if (table_include_patterns
.head
!= NULL
)
634 expand_table_name_patterns(&table_include_patterns
,
635 &table_include_oids
);
636 if (table_include_oids
.head
== NULL
)
638 write_msg(NULL
, "No matching tables were found\n");
642 expand_table_name_patterns(&table_exclude_patterns
,
643 &table_exclude_oids
);
644 /* non-matching exclusion patterns aren't an error */
647 * Dumping blobs is now default unless we saw an inclusion switch or -s
648 * ... but even if we did see one of these, -b turns it back on.
650 if (include_everything
&& !schemaOnly
)
654 * Now scan the database and create DumpableObject structs for all the
655 * objects we intend to dump.
657 tblinfo
= getSchemaData(&numTables
);
659 if (g_fout
->remoteVersion
< 80400)
660 guessConstraintInheritance(tblinfo
, numTables
);
664 getTableData(tblinfo
, numTables
, oids
);
666 getTableDataFKConstraints();
669 if (outputBlobs
&& hasBlobs(g_fout
))
671 /* Add placeholders to allow correct sorting of blobs */
672 DumpableObject
*blobobj
;
674 blobobj
= (DumpableObject
*) malloc(sizeof(DumpableObject
));
675 blobobj
->objType
= DO_BLOBS
;
676 blobobj
->catId
= nilCatalogId
;
677 AssignDumpId(blobobj
);
678 blobobj
->name
= strdup("BLOBS");
680 blobobj
= (DumpableObject
*) malloc(sizeof(DumpableObject
));
681 blobobj
->objType
= DO_BLOB_COMMENTS
;
682 blobobj
->catId
= nilCatalogId
;
683 AssignDumpId(blobobj
);
684 blobobj
->name
= strdup("BLOB COMMENTS");
688 * Collect dependency data to assist in ordering the objects.
693 * Sort the objects into a safe dump order (no forward references).
695 * In 7.3 or later, we can rely on dependency information to help us
696 * determine a safe order, so the initial sort is mostly for cosmetic
697 * purposes: we sort by name to ensure that logically identical schemas
698 * will dump identically. Before 7.3 we don't have dependencies and we
699 * use OID ordering as an (unreliable) guide to creation order.
701 getDumpableObjects(&dobjs
, &numObjs
);
703 if (g_fout
->remoteVersion
>= 70300)
704 sortDumpableObjectsByTypeName(dobjs
, numObjs
);
706 sortDumpableObjectsByTypeOid(dobjs
, numObjs
);
708 sortDumpableObjects(dobjs
, numObjs
);
711 * Create archive TOC entries for all the objects to be dumped, in a safe
715 /* First the special ENCODING and STDSTRINGS entries. */
716 dumpEncoding(g_fout
);
717 dumpStdStrings(g_fout
);
719 /* The database item is always next, unless we don't want it at all */
720 if (include_everything
&& !dataOnly
)
721 dumpDatabase(g_fout
);
723 /* Now the rearrangeable objects. */
724 for (i
= 0; i
< numObjs
; i
++)
725 dumpDumpableObject(g_fout
, dobjs
[i
]);
728 * And finally we can do the actual output.
732 ropt
= NewRestoreOptions();
733 ropt
->filename
= (char *) filename
;
734 ropt
->dropSchema
= outputClean
;
735 ropt
->aclsSkip
= aclsSkip
;
736 ropt
->superuser
= outputSuperuser
;
737 ropt
->create
= outputCreate
;
738 ropt
->noOwner
= outputNoOwner
;
739 ropt
->noTablespace
= outputNoTablespaces
;
740 ropt
->disable_triggers
= disable_triggers
;
741 ropt
->use_setsessauth
= use_setsessauth
;
742 ropt
->dataOnly
= dataOnly
;
744 if (compressLevel
== -1)
745 ropt
->compression
= 0;
747 ropt
->compression
= compressLevel
;
749 ropt
->suppressDumpWarnings
= true; /* We've already shown them */
751 RestoreArchive(g_fout
, ropt
);
754 CloseArchive(g_fout
);
763 help(const char *progname
)
765 printf(_("%s dumps a database as a text file or to other formats.\n\n"), progname
);
766 printf(_("Usage:\n"));
767 printf(_(" %s [OPTION]... [DBNAME]\n"), progname
);
769 printf(_("\nGeneral options:\n"));
770 printf(_(" -f, --file=FILENAME output file name\n"));
771 printf(_(" -F, --format=c|t|p output file format (custom, tar, plain text)\n"));
772 printf(_(" -v, --verbose verbose mode\n"));
773 printf(_(" -Z, --compress=0-9 compression level for compressed formats\n"));
774 printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
775 printf(_(" --help show this help, then exit\n"));
776 printf(_(" --version output version information, then exit\n"));
778 printf(_("\nOptions controlling the output content:\n"));
779 printf(_(" -a, --data-only dump only the data, not the schema\n"));
780 printf(_(" -b, --blobs include large objects in dump\n"));
781 printf(_(" -c, --clean clean (drop) schema prior to create\n"));
782 printf(_(" -C, --create include commands to create database in dump\n"));
783 printf(_(" -d, --inserts dump data as INSERT commands, rather than COPY\n"));
784 printf(_(" -D, --column-inserts dump data as INSERT commands with column names\n"));
785 printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
786 printf(_(" -n, --schema=SCHEMA dump the named schema(s) only\n"));
787 printf(_(" -N, --exclude-schema=SCHEMA do NOT dump the named schema(s)\n"));
788 printf(_(" -o, --oids include OIDs in dump\n"));
789 printf(_(" -O, --no-owner skip restoration of object ownership\n"
790 " in plain text format\n"));
791 printf(_(" -s, --schema-only dump only the schema, no data\n"));
792 printf(_(" -S, --superuser=NAME specify the superuser user name to use in\n"
793 " plain text format\n"));
794 printf(_(" -t, --table=TABLE dump the named table(s) only\n"));
795 printf(_(" -T, --exclude-table=TABLE do NOT dump the named table(s)\n"));
796 printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
797 printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
798 printf(_(" --disable-triggers disable triggers during data-only restore\n"));
799 printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
800 printf(_(" --use-set-session-authorization\n"
801 " use SESSION AUTHORIZATION commands instead of\n"
802 " ALTER OWNER commands to set ownership\n"));
804 printf(_("\nConnection options:\n"));
805 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
806 printf(_(" -p, --port=PORT database server port number\n"));
807 printf(_(" -U, --username=NAME connect as specified database user\n"));
808 printf(_(" -W, --password force password prompt (should happen automatically)\n"));
810 printf(_("\nIf no database name is supplied, then the PGDATABASE environment\n"
811 "variable value is used.\n\n"));
812 printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
820 write_msg(NULL
, "*** aborted because of error\n");
825 * Find the OIDs of all schemas matching the given list of patterns,
826 * and append them to the given OID list.
829 expand_schema_name_patterns(SimpleStringList
*patterns
, SimpleOidList
*oids
)
833 SimpleStringListCell
*cell
;
836 if (patterns
->head
== NULL
)
837 return; /* nothing to do */
839 if (g_fout
->remoteVersion
< 70300)
841 write_msg(NULL
, "server version must be at least 7.3 to use schema selection switches\n");
845 query
= createPQExpBuffer();
848 * We use UNION ALL rather than UNION; this might sometimes result in
849 * duplicate entries in the OID list, but we don't care.
852 for (cell
= patterns
->head
; cell
; cell
= cell
->next
)
854 if (cell
!= patterns
->head
)
855 appendPQExpBuffer(query
, "UNION ALL\n");
856 appendPQExpBuffer(query
,
857 "SELECT oid FROM pg_catalog.pg_namespace n\n");
858 processSQLNamePattern(g_conn
, query
, cell
->val
, false, false,
859 NULL
, "n.nspname", NULL
,
863 res
= PQexec(g_conn
, query
->data
);
864 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
866 for (i
= 0; i
< PQntuples(res
); i
++)
868 simple_oid_list_append(oids
, atooid(PQgetvalue(res
, i
, 0)));
872 destroyPQExpBuffer(query
);
876 * Find the OIDs of all tables matching the given list of patterns,
877 * and append them to the given OID list.
880 expand_table_name_patterns(SimpleStringList
*patterns
, SimpleOidList
*oids
)
884 SimpleStringListCell
*cell
;
887 if (patterns
->head
== NULL
)
888 return; /* nothing to do */
890 query
= createPQExpBuffer();
893 * We use UNION ALL rather than UNION; this might sometimes result in
894 * duplicate entries in the OID list, but we don't care.
897 for (cell
= patterns
->head
; cell
; cell
= cell
->next
)
899 if (cell
!= patterns
->head
)
900 appendPQExpBuffer(query
, "UNION ALL\n");
901 appendPQExpBuffer(query
,
903 "\nFROM pg_catalog.pg_class c"
904 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
905 "\nWHERE c.relkind in ('%c', '%c', '%c')\n",
906 RELKIND_RELATION
, RELKIND_SEQUENCE
, RELKIND_VIEW
);
907 processSQLNamePattern(g_conn
, query
, cell
->val
, true, false,
908 "n.nspname", "c.relname", NULL
,
909 "pg_catalog.pg_table_is_visible(c.oid)");
912 res
= PQexec(g_conn
, query
->data
);
913 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
915 for (i
= 0; i
< PQntuples(res
); i
++)
917 simple_oid_list_append(oids
, atooid(PQgetvalue(res
, i
, 0)));
921 destroyPQExpBuffer(query
);
925 * selectDumpableNamespace: policy-setting subroutine
926 * Mark a namespace as to be dumped or not
929 selectDumpableNamespace(NamespaceInfo
*nsinfo
)
932 * If specific tables are being dumped, do not dump any complete
933 * namespaces. If specific namespaces are being dumped, dump just those
934 * namespaces. Otherwise, dump all non-system namespaces.
936 if (table_include_oids
.head
!= NULL
)
937 nsinfo
->dobj
.dump
= false;
938 else if (schema_include_oids
.head
!= NULL
)
939 nsinfo
->dobj
.dump
= simple_oid_list_member(&schema_include_oids
,
940 nsinfo
->dobj
.catId
.oid
);
941 else if (strncmp(nsinfo
->dobj
.name
, "pg_", 3) == 0 ||
942 strcmp(nsinfo
->dobj
.name
, "information_schema") == 0)
943 nsinfo
->dobj
.dump
= false;
945 nsinfo
->dobj
.dump
= true;
948 * In any case, a namespace can be excluded by an exclusion switch
950 if (nsinfo
->dobj
.dump
&&
951 simple_oid_list_member(&schema_exclude_oids
,
952 nsinfo
->dobj
.catId
.oid
))
953 nsinfo
->dobj
.dump
= false;
957 * selectDumpableTable: policy-setting subroutine
958 * Mark a table as to be dumped or not
961 selectDumpableTable(TableInfo
*tbinfo
)
964 * If specific tables are being dumped, dump just those tables; else, dump
965 * according to the parent namespace's dump flag.
967 if (table_include_oids
.head
!= NULL
)
968 tbinfo
->dobj
.dump
= simple_oid_list_member(&table_include_oids
,
969 tbinfo
->dobj
.catId
.oid
);
971 tbinfo
->dobj
.dump
= tbinfo
->dobj
.namespace->dobj
.dump
;
974 * In any case, a table can be excluded by an exclusion switch
976 if (tbinfo
->dobj
.dump
&&
977 simple_oid_list_member(&table_exclude_oids
,
978 tbinfo
->dobj
.catId
.oid
))
979 tbinfo
->dobj
.dump
= false;
983 * selectDumpableType: policy-setting subroutine
984 * Mark a type as to be dumped or not
987 selectDumpableType(TypeInfo
*tinfo
)
989 /* Dump only types in dumpable namespaces */
990 if (!tinfo
->dobj
.namespace->dobj
.dump
)
991 tinfo
->dobj
.dump
= false;
993 /* skip complex types, except for standalone composite types */
994 /* (note: this test should now be unnecessary) */
995 else if (OidIsValid(tinfo
->typrelid
) &&
996 tinfo
->typrelkind
!= RELKIND_COMPOSITE_TYPE
)
997 tinfo
->dobj
.dump
= false;
999 /* skip undefined placeholder types */
1000 else if (!tinfo
->isDefined
)
1001 tinfo
->dobj
.dump
= false;
1003 /* skip auto-generated array types */
1004 else if (tinfo
->isArray
)
1005 tinfo
->dobj
.dump
= false;
1008 tinfo
->dobj
.dump
= true;
1012 * selectDumpableObject: policy-setting subroutine
1013 * Mark a generic dumpable object as to be dumped or not
1015 * Use this only for object types without a special-case routine above.
1018 selectDumpableObject(DumpableObject
*dobj
)
1021 * Default policy is to dump if parent namespace is dumpable, or always
1022 * for non-namespace-associated items.
1024 if (dobj
->namespace)
1025 dobj
->dump
= dobj
->namespace->dobj
.dump
;
1031 * Dump a table's contents for loading using the COPY command
1032 * - this routine is called by the Archiver when it wants the table
1037 dumpTableData_copy(Archive
*fout
, void *dcontext
)
1039 TableDataInfo
*tdinfo
= (TableDataInfo
*) dcontext
;
1040 TableInfo
*tbinfo
= tdinfo
->tdtable
;
1041 const char *classname
= tbinfo
->dobj
.name
;
1042 const bool hasoids
= tbinfo
->hasoids
;
1043 const bool oids
= tdinfo
->oids
;
1044 PQExpBuffer q
= createPQExpBuffer();
1048 const char *column_list
;
1051 write_msg(NULL
, "dumping contents of table %s\n", classname
);
1054 * Make sure we are in proper schema. We will qualify the table name
1055 * below anyway (in case its name conflicts with a pg_catalog table); but
1056 * this ensures reproducible results in case the table contains regproc,
1057 * regclass, etc columns.
1059 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
1062 * If possible, specify the column list explicitly so that we have no
1063 * possibility of retrieving data in the wrong column order. (The default
1064 * column ordering of COPY will not be what we want in certain corner
1065 * cases involving ADD COLUMN and inheritance.)
1067 if (g_fout
->remoteVersion
>= 70300)
1068 column_list
= fmtCopyColumnList(tbinfo
);
1070 column_list
= ""; /* can't select columns in COPY */
1072 if (oids
&& hasoids
)
1074 appendPQExpBuffer(q
, "COPY %s %s WITH OIDS TO stdout;",
1075 fmtQualifiedId(tbinfo
->dobj
.namespace->dobj
.name
,
1081 appendPQExpBuffer(q
, "COPY %s %s TO stdout;",
1082 fmtQualifiedId(tbinfo
->dobj
.namespace->dobj
.name
,
1086 res
= PQexec(g_conn
, q
->data
);
1087 check_sql_result(res
, g_conn
, q
->data
, PGRES_COPY_OUT
);
1092 ret
= PQgetCopyData(g_conn
, ©buf
, 0);
1095 break; /* done or error */
1099 WriteData(fout
, copybuf
, ret
);
1106 * There was considerable discussion in late July, 2000 regarding
1107 * slowing down pg_dump when backing up large tables. Users with both
1108 * slow & fast (multi-processor) machines experienced performance
1109 * degradation when doing a backup.
1111 * Initial attempts based on sleeping for a number of ms for each ms
1112 * of work were deemed too complex, then a simple 'sleep in each loop'
1113 * implementation was suggested. The latter failed because the loop
1114 * was too tight. Finally, the following was implemented:
1116 * If throttle is non-zero, then
1117 * See how long since the last sleep.
1118 * Work out how long to sleep (based on ratio).
1119 * If sleep is more than 100ms, then
1125 * where the throttle value was the number of ms to sleep per ms of
1126 * work. The calculation was done in each loop.
1128 * Most of the hard work is done in the backend, and this solution
1129 * still did not work particularly well: on slow machines, the ratio
1130 * was 50:1, and on medium paced machines, 1:1, and on fast
1131 * multi-processor machines, it had little or no effect, for reasons
1132 * that were unclear.
1134 * Further discussion ensued, and the proposal was dropped.
1136 * For those people who want this feature, it can be implemented using
1137 * gettimeofday in each loop, calculating the time since last sleep,
1138 * multiplying that by the sleep ratio, then if the result is more
1139 * than a preset 'minimum sleep time' (say 100ms), call the 'select'
1140 * function to sleep for a subsecond period ie.
1142 * select(0, NULL, NULL, NULL, &tvi);
1144 * This will return after the interval specified in the structure tvi.
1145 * Finally, call gettimeofday again to save the 'last sleep time'.
1149 archprintf(fout
, "\\.\n\n\n");
1153 /* copy data transfer failed */
1154 write_msg(NULL
, "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed.\n", classname
);
1155 write_msg(NULL
, "Error message from server: %s", PQerrorMessage(g_conn
));
1156 write_msg(NULL
, "The command was: %s\n", q
->data
);
1160 /* Check command status and return to normal libpq state */
1161 res
= PQgetResult(g_conn
);
1162 check_sql_result(res
, g_conn
, q
->data
, PGRES_COMMAND_OK
);
1165 destroyPQExpBuffer(q
);
1170 dumpTableData_insert(Archive
*fout
, void *dcontext
)
1172 TableDataInfo
*tdinfo
= (TableDataInfo
*) dcontext
;
1173 TableInfo
*tbinfo
= tdinfo
->tdtable
;
1174 const char *classname
= tbinfo
->dobj
.name
;
1175 PQExpBuffer q
= createPQExpBuffer();
1182 * Make sure we are in proper schema. We will qualify the table name
1183 * below anyway (in case its name conflicts with a pg_catalog table); but
1184 * this ensures reproducible results in case the table contains regproc,
1185 * regclass, etc columns.
1187 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
1189 if (fout
->remoteVersion
>= 70100)
1191 appendPQExpBuffer(q
, "DECLARE _pg_dump_cursor CURSOR FOR "
1192 "SELECT * FROM ONLY %s",
1193 fmtQualifiedId(tbinfo
->dobj
.namespace->dobj
.name
,
1198 appendPQExpBuffer(q
, "DECLARE _pg_dump_cursor CURSOR FOR "
1200 fmtQualifiedId(tbinfo
->dobj
.namespace->dobj
.name
,
1204 res
= PQexec(g_conn
, q
->data
);
1205 check_sql_result(res
, g_conn
, q
->data
, PGRES_COMMAND_OK
);
1211 res
= PQexec(g_conn
, "FETCH 100 FROM _pg_dump_cursor");
1212 check_sql_result(res
, g_conn
, "FETCH 100 FROM _pg_dump_cursor",
1214 nfields
= PQnfields(res
);
1215 for (tuple
= 0; tuple
< PQntuples(res
); tuple
++)
1217 archprintf(fout
, "INSERT INTO %s ", fmtId(classname
));
1220 /* corner case for zero-column table */
1221 archprintf(fout
, "DEFAULT VALUES;\n");
1224 if (attrNames
== true)
1226 resetPQExpBuffer(q
);
1227 appendPQExpBuffer(q
, "(");
1228 for (field
= 0; field
< nfields
; field
++)
1231 appendPQExpBuffer(q
, ", ");
1232 appendPQExpBufferStr(q
, fmtId(PQfname(res
, field
)));
1234 appendPQExpBuffer(q
, ") ");
1235 archputs(q
->data
, fout
);
1237 archprintf(fout
, "VALUES (");
1238 for (field
= 0; field
< nfields
; field
++)
1241 archprintf(fout
, ", ");
1242 if (PQgetisnull(res
, tuple
, field
))
1244 archprintf(fout
, "NULL");
1248 /* XXX This code is partially duplicated in ruleutils.c */
1249 switch (PQftype(res
, field
))
1260 * These types are printed without quotes unless
1261 * they contain values that aren't accepted by the
1262 * scanner unquoted (e.g., 'NaN'). Note that
1263 * strtod() and friends might accept NaN, so we
1264 * can't use that to test.
1266 * In reality we only need to defend against
1267 * infinity and NaN, so we need not get too crazy
1268 * about pattern matching here.
1270 const char *s
= PQgetvalue(res
, tuple
, field
);
1272 if (strspn(s
, "0123456789 +-eE.") == strlen(s
))
1273 archprintf(fout
, "%s", s
);
1275 archprintf(fout
, "'%s'", s
);
1281 archprintf(fout
, "B'%s'",
1282 PQgetvalue(res
, tuple
, field
));
1286 if (strcmp(PQgetvalue(res
, tuple
, field
), "t") == 0)
1287 archprintf(fout
, "true");
1289 archprintf(fout
, "false");
1293 /* All other types are printed as string literals. */
1294 resetPQExpBuffer(q
);
1295 appendStringLiteralAH(q
,
1296 PQgetvalue(res
, tuple
, field
),
1298 archputs(q
->data
, fout
);
1302 archprintf(fout
, ");\n");
1304 } while (PQntuples(res
) > 0);
1308 archprintf(fout
, "\n\n");
1310 do_sql_command(g_conn
, "CLOSE _pg_dump_cursor");
1312 destroyPQExpBuffer(q
);
1319 * dump the contents of a single table
1321 * Actually, this just makes an ArchiveEntry for the table contents.
1324 dumpTableData(Archive
*fout
, TableDataInfo
*tdinfo
)
1326 TableInfo
*tbinfo
= tdinfo
->tdtable
;
1327 PQExpBuffer copyBuf
= createPQExpBuffer();
1328 DataDumperPtr dumpFn
;
1333 /* Dump/restore using COPY */
1334 dumpFn
= dumpTableData_copy
;
1335 /* must use 2 steps here 'cause fmtId is nonreentrant */
1336 appendPQExpBuffer(copyBuf
, "COPY %s ",
1337 fmtId(tbinfo
->dobj
.name
));
1338 appendPQExpBuffer(copyBuf
, "%s %sFROM stdin;\n",
1339 fmtCopyColumnList(tbinfo
),
1340 (tdinfo
->oids
&& tbinfo
->hasoids
) ? "WITH OIDS " : "");
1341 copyStmt
= copyBuf
->data
;
1345 /* Restore using INSERT */
1346 dumpFn
= dumpTableData_insert
;
1350 ArchiveEntry(fout
, tdinfo
->dobj
.catId
, tdinfo
->dobj
.dumpId
,
1352 tbinfo
->dobj
.namespace->dobj
.name
,
1354 tbinfo
->rolname
, false,
1355 "TABLE DATA", "", "", copyStmt
,
1356 tdinfo
->dobj
.dependencies
, tdinfo
->dobj
.nDeps
,
1359 destroyPQExpBuffer(copyBuf
);
1364 * set up dumpable objects representing the contents of tables
1367 getTableData(TableInfo
*tblinfo
, int numTables
, bool oids
)
1371 for (i
= 0; i
< numTables
; i
++)
1373 /* Skip VIEWs (no data to dump) */
1374 if (tblinfo
[i
].relkind
== RELKIND_VIEW
)
1376 /* Skip SEQUENCEs (handled elsewhere) */
1377 if (tblinfo
[i
].relkind
== RELKIND_SEQUENCE
)
1380 if (tblinfo
[i
].dobj
.dump
)
1382 TableDataInfo
*tdinfo
;
1384 tdinfo
= (TableDataInfo
*) malloc(sizeof(TableDataInfo
));
1386 tdinfo
->dobj
.objType
= DO_TABLE_DATA
;
1389 * Note: use tableoid 0 so that this object won't be mistaken for
1390 * something that pg_depend entries apply to.
1392 tdinfo
->dobj
.catId
.tableoid
= 0;
1393 tdinfo
->dobj
.catId
.oid
= tblinfo
[i
].dobj
.catId
.oid
;
1394 AssignDumpId(&tdinfo
->dobj
);
1395 tdinfo
->dobj
.name
= tblinfo
[i
].dobj
.name
;
1396 tdinfo
->dobj
.namespace = tblinfo
[i
].dobj
.namespace;
1397 tdinfo
->tdtable
= &(tblinfo
[i
]);
1398 tdinfo
->oids
= oids
;
1399 addObjectDependency(&tdinfo
->dobj
, tblinfo
[i
].dobj
.dumpId
);
1401 tblinfo
[i
].dataObj
= tdinfo
;
1407 * getTableDataFKConstraints -
1408 * add dump-order dependencies reflecting foreign key constraints
1410 * This code is executed only in a data-only dump --- in schema+data dumps
1411 * we handle foreign key issues by not creating the FK constraints until
1412 * after the data is loaded. In a data-only dump, however, we want to
1413 * order the table data objects in such a way that a table's referenced
1414 * tables are restored first. (In the presence of circular references or
1415 * self-references this may be impossible; we'll detect and complain about
1416 * that during the dependency sorting step.)
1419 getTableDataFKConstraints(void)
1421 DumpableObject
**dobjs
;
1425 /* Search through all the dumpable objects for FK constraints */
1426 getDumpableObjects(&dobjs
, &numObjs
);
1427 for (i
= 0; i
< numObjs
; i
++)
1429 if (dobjs
[i
]->objType
== DO_FK_CONSTRAINT
)
1431 ConstraintInfo
*cinfo
= (ConstraintInfo
*) dobjs
[i
];
1434 /* Not interesting unless both tables are to be dumped */
1435 if (cinfo
->contable
== NULL
||
1436 cinfo
->contable
->dataObj
== NULL
)
1438 ftable
= findTableByOid(cinfo
->confrelid
);
1439 if (ftable
== NULL
||
1440 ftable
->dataObj
== NULL
)
1443 * Okay, make referencing table's TABLE_DATA object depend on
1444 * the referenced table's TABLE_DATA object.
1446 addObjectDependency(&cinfo
->contable
->dataObj
->dobj
,
1447 ftable
->dataObj
->dobj
.dumpId
);
1455 * guessConstraintInheritance:
1456 * In pre-8.4 databases, we can't tell for certain which constraints
1457 * are inherited. We assume a CHECK constraint is inherited if its name
1458 * matches the name of any constraint in the parent. Originally this code
1459 * tried to compare the expression texts, but that can fail for various
1460 * reasons --- for example, if the parent and child tables are in different
1461 * schemas, reverse-listing of function calls may produce different text
1462 * (schema-qualified or not) depending on search path.
1464 * In 8.4 and up we can rely on the conislocal field to decide which
1465 * constraints must be dumped; much safer.
1467 * This function assumes all conislocal flags were initialized to TRUE.
1468 * It clears the flag on anything that seems to be inherited.
1471 guessConstraintInheritance(TableInfo
*tblinfo
, int numTables
)
1477 for (i
= 0; i
< numTables
; i
++)
1479 TableInfo
*tbinfo
= &(tblinfo
[i
]);
1481 TableInfo
**parents
;
1484 /* Sequences and views never have parents */
1485 if (tbinfo
->relkind
== RELKIND_SEQUENCE
||
1486 tbinfo
->relkind
== RELKIND_VIEW
)
1489 /* Don't bother computing anything for non-target tables, either */
1490 if (!tbinfo
->dobj
.dump
)
1493 numParents
= tbinfo
->numParents
;
1494 parents
= tbinfo
->parents
;
1496 if (numParents
== 0)
1497 continue; /* nothing to see here, move along */
1499 /* scan for inherited CHECK constraints */
1500 for (j
= 0; j
< tbinfo
->ncheck
; j
++)
1502 ConstraintInfo
*constr
;
1504 constr
= &(tbinfo
->checkexprs
[j
]);
1506 for (k
= 0; k
< numParents
; k
++)
1510 parent
= parents
[k
];
1511 for (l
= 0; l
< parent
->ncheck
; l
++)
1513 ConstraintInfo
*pconstr
= &(parent
->checkexprs
[l
]);
1515 if (strcmp(pconstr
->dobj
.name
, constr
->dobj
.name
) == 0)
1517 constr
->conislocal
= false;
1521 if (!constr
->conislocal
)
1531 * dump the database definition
1534 dumpDatabase(Archive
*AH
)
1536 PQExpBuffer dbQry
= createPQExpBuffer();
1537 PQExpBuffer delQry
= createPQExpBuffer();
1538 PQExpBuffer creaQry
= createPQExpBuffer();
1550 const char *datname
,
1557 datname
= PQdb(g_conn
);
1560 write_msg(NULL
, "saving database definition\n");
1562 /* Make sure we are in proper schema */
1563 selectSourceSchema("pg_catalog");
1565 /* Get the database owner and parameters from pg_database */
1566 if (g_fout
->remoteVersion
>= 80400)
1568 appendPQExpBuffer(dbQry
, "SELECT tableoid, oid, "
1569 "(%s datdba) as dba, "
1570 "pg_encoding_to_char(encoding) as encoding, "
1571 "datcollate, datctype, "
1572 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) as tablespace, "
1573 "shobj_description(oid, 'pg_database') as description "
1578 appendStringLiteralAH(dbQry
, datname
, AH
);
1580 else if (g_fout
->remoteVersion
>= 80200)
1582 appendPQExpBuffer(dbQry
, "SELECT tableoid, oid, "
1583 "(%s datdba) as dba, "
1584 "pg_encoding_to_char(encoding) as encoding, "
1585 "NULL as datcollate, NULL as datctype, "
1586 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) as tablespace, "
1587 "shobj_description(oid, 'pg_database') as description "
1592 appendStringLiteralAH(dbQry
, datname
, AH
);
1594 else if (g_fout
->remoteVersion
>= 80000)
1596 appendPQExpBuffer(dbQry
, "SELECT tableoid, oid, "
1597 "(%s datdba) as dba, "
1598 "pg_encoding_to_char(encoding) as encoding, "
1599 "NULL as datcollate, NULL as datctype, "
1600 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) as tablespace "
1604 appendStringLiteralAH(dbQry
, datname
, AH
);
1606 else if (g_fout
->remoteVersion
>= 70100)
1608 appendPQExpBuffer(dbQry
, "SELECT tableoid, oid, "
1609 "(%s datdba) as dba, "
1610 "pg_encoding_to_char(encoding) as encoding, "
1611 "NULL as datcollate, NULL as datctype, "
1612 "NULL as tablespace "
1616 appendStringLiteralAH(dbQry
, datname
, AH
);
1620 appendPQExpBuffer(dbQry
, "SELECT "
1621 "(SELECT oid FROM pg_class WHERE relname = 'pg_database') AS tableoid, "
1623 "(%s datdba) as dba, "
1624 "pg_encoding_to_char(encoding) as encoding, "
1625 "NULL as datcollate, NULL as datctype, "
1626 "NULL as tablespace "
1630 appendStringLiteralAH(dbQry
, datname
, AH
);
1633 res
= PQexec(g_conn
, dbQry
->data
);
1634 check_sql_result(res
, g_conn
, dbQry
->data
, PGRES_TUPLES_OK
);
1636 ntups
= PQntuples(res
);
1640 write_msg(NULL
, "missing pg_database entry for database \"%s\"\n",
1647 write_msg(NULL
, "query returned more than one (%d) pg_database entry for database \"%s\"\n",
1652 i_tableoid
= PQfnumber(res
, "tableoid");
1653 i_oid
= PQfnumber(res
, "oid");
1654 i_dba
= PQfnumber(res
, "dba");
1655 i_encoding
= PQfnumber(res
, "encoding");
1656 i_collate
= PQfnumber(res
, "datcollate");
1657 i_ctype
= PQfnumber(res
, "datctype");
1658 i_tablespace
= PQfnumber(res
, "tablespace");
1660 dbCatId
.tableoid
= atooid(PQgetvalue(res
, 0, i_tableoid
));
1661 dbCatId
.oid
= atooid(PQgetvalue(res
, 0, i_oid
));
1662 dba
= PQgetvalue(res
, 0, i_dba
);
1663 encoding
= PQgetvalue(res
, 0, i_encoding
);
1664 collate
= PQgetvalue(res
, 0, i_collate
);
1665 ctype
= PQgetvalue(res
, 0, i_ctype
);
1666 tablespace
= PQgetvalue(res
, 0, i_tablespace
);
1668 appendPQExpBuffer(creaQry
, "CREATE DATABASE %s WITH TEMPLATE = template0",
1670 if (strlen(encoding
) > 0)
1672 appendPQExpBuffer(creaQry
, " ENCODING = ");
1673 appendStringLiteralAH(creaQry
, encoding
, AH
);
1675 if (strlen(collate
) > 0)
1677 appendPQExpBuffer(creaQry
, " COLLATE = ");
1678 appendStringLiteralAH(creaQry
, collate
, AH
);
1680 if (strlen(ctype
) > 0)
1682 appendPQExpBuffer(creaQry
, " CTYPE = ");
1683 appendStringLiteralAH(creaQry
, ctype
, AH
);
1685 if (strlen(tablespace
) > 0 && strcmp(tablespace
, "pg_default") != 0)
1686 appendPQExpBuffer(creaQry
, " TABLESPACE = %s",
1688 appendPQExpBuffer(creaQry
, ";\n");
1690 appendPQExpBuffer(delQry
, "DROP DATABASE %s;\n",
1693 dbDumpId
= createDumpId();
1696 dbCatId
, /* catalog ID */
1697 dbDumpId
, /* dump ID */
1699 NULL
, /* Namespace */
1700 NULL
, /* Tablespace */
1702 false, /* with oids */
1703 "DATABASE", /* Desc */
1704 creaQry
->data
, /* Create */
1705 delQry
->data
, /* Del */
1710 NULL
); /* Dumper Arg */
1712 /* Dump DB comment if any */
1713 if (g_fout
->remoteVersion
>= 80200)
1716 * 8.2 keeps comments on shared objects in a shared table, so we
1717 * cannot use the dumpComment used for other database objects.
1719 char *comment
= PQgetvalue(res
, 0, PQfnumber(res
, "description"));
1721 if (comment
&& strlen(comment
))
1723 resetPQExpBuffer(dbQry
);
1724 /* Generates warning when loaded into a differently-named database.*/
1725 appendPQExpBuffer(dbQry
, "COMMENT ON DATABASE %s IS ", fmtId(datname
));
1726 appendStringLiteralAH(dbQry
, comment
, AH
);
1727 appendPQExpBuffer(dbQry
, ";\n");
1729 ArchiveEntry(AH
, dbCatId
, createDumpId(), datname
, NULL
, NULL
,
1730 dba
, false, "COMMENT", dbQry
->data
, "", NULL
,
1731 &dbDumpId
, 1, NULL
, NULL
);
1736 resetPQExpBuffer(dbQry
);
1737 appendPQExpBuffer(dbQry
, "DATABASE %s", fmtId(datname
));
1738 dumpComment(AH
, dbQry
->data
, NULL
, "",
1739 dbCatId
, 0, dbDumpId
);
1744 destroyPQExpBuffer(dbQry
);
1745 destroyPQExpBuffer(delQry
);
1746 destroyPQExpBuffer(creaQry
);
1751 * dumpEncoding: put the correct encoding into the archive
1754 dumpEncoding(Archive
*AH
)
1756 const char *encname
= pg_encoding_to_char(AH
->encoding
);
1757 PQExpBuffer qry
= createPQExpBuffer();
1760 write_msg(NULL
, "saving encoding = %s\n", encname
);
1762 appendPQExpBuffer(qry
, "SET client_encoding = ");
1763 appendStringLiteralAH(qry
, encname
, AH
);
1764 appendPQExpBuffer(qry
, ";\n");
1766 ArchiveEntry(AH
, nilCatalogId
, createDumpId(),
1767 "ENCODING", NULL
, NULL
, "",
1768 false, "ENCODING", qry
->data
, "", NULL
,
1772 destroyPQExpBuffer(qry
);
1777 * dumpStdStrings: put the correct escape string behavior into the archive
1780 dumpStdStrings(Archive
*AH
)
1782 const char *stdstrings
= AH
->std_strings
? "on" : "off";
1783 PQExpBuffer qry
= createPQExpBuffer();
1786 write_msg(NULL
, "saving standard_conforming_strings = %s\n",
1789 appendPQExpBuffer(qry
, "SET standard_conforming_strings = '%s';\n",
1792 ArchiveEntry(AH
, nilCatalogId
, createDumpId(),
1793 "STDSTRINGS", NULL
, NULL
, "",
1794 false, "STDSTRINGS", qry
->data
, "", NULL
,
1798 destroyPQExpBuffer(qry
);
1804 * Test whether database contains any large objects
1807 hasBlobs(Archive
*AH
)
1810 const char *blobQry
;
1813 /* Make sure we are in proper schema */
1814 selectSourceSchema("pg_catalog");
1816 /* Check for BLOB OIDs */
1817 if (AH
->remoteVersion
>= 70100)
1818 blobQry
= "SELECT loid FROM pg_largeobject LIMIT 1";
1820 blobQry
= "SELECT oid FROM pg_class WHERE relkind = 'l' LIMIT 1";
1822 res
= PQexec(g_conn
, blobQry
);
1823 check_sql_result(res
, g_conn
, blobQry
, PGRES_TUPLES_OK
);
1825 result
= PQntuples(res
) > 0;
1837 dumpBlobs(Archive
*AH
, void *arg
)
1839 const char *blobQry
;
1840 const char *blobFetchQry
;
1842 char buf
[LOBBUFSIZE
];
1847 write_msg(NULL
, "saving large objects\n");
1849 /* Make sure we are in proper schema */
1850 selectSourceSchema("pg_catalog");
1852 /* Cursor to get all BLOB OIDs */
1853 if (AH
->remoteVersion
>= 70100)
1854 blobQry
= "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
1856 blobQry
= "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class WHERE relkind = 'l'";
1858 res
= PQexec(g_conn
, blobQry
);
1859 check_sql_result(res
, g_conn
, blobQry
, PGRES_COMMAND_OK
);
1861 /* Command to fetch from cursor */
1862 blobFetchQry
= "FETCH 1000 IN bloboid";
1869 res
= PQexec(g_conn
, blobFetchQry
);
1870 check_sql_result(res
, g_conn
, blobFetchQry
, PGRES_TUPLES_OK
);
1872 /* Process the tuples, if any */
1873 for (i
= 0; i
< PQntuples(res
); i
++)
1878 blobOid
= atooid(PQgetvalue(res
, i
, 0));
1880 loFd
= lo_open(g_conn
, blobOid
, INV_READ
);
1883 write_msg(NULL
, "dumpBlobs(): could not open large object: %s",
1884 PQerrorMessage(g_conn
));
1888 StartBlob(AH
, blobOid
);
1890 /* Now read it in chunks, sending data to archive */
1893 cnt
= lo_read(g_conn
, loFd
, buf
, LOBBUFSIZE
);
1896 write_msg(NULL
, "dumpBlobs(): error reading large object: %s",
1897 PQerrorMessage(g_conn
));
1901 WriteData(AH
, buf
, cnt
);
1904 lo_close(g_conn
, loFd
);
1906 EndBlob(AH
, blobOid
);
1908 } while (PQntuples(res
) > 0);
1917 * dump all blob comments
1919 * Since we don't provide any way to be selective about dumping blobs,
1920 * there's no need to be selective about their comments either. We put
1921 * all the comments into one big TOC entry.
1924 dumpBlobComments(Archive
*AH
, void *arg
)
1926 const char *blobQry
;
1927 const char *blobFetchQry
;
1928 PQExpBuffer commentcmd
= createPQExpBuffer();
1933 write_msg(NULL
, "saving large object comments\n");
1935 /* Make sure we are in proper schema */
1936 selectSourceSchema("pg_catalog");
1938 /* Cursor to get all BLOB comments */
1939 if (AH
->remoteVersion
>= 70200)
1940 blobQry
= "DECLARE blobcmt CURSOR FOR SELECT loid, obj_description(loid, 'pg_largeobject') FROM (SELECT DISTINCT loid FROM pg_largeobject) ss";
1941 else if (AH
->remoteVersion
>= 70100)
1942 blobQry
= "DECLARE blobcmt CURSOR FOR SELECT loid, obj_description(loid) FROM (SELECT DISTINCT loid FROM pg_largeobject) ss";
1944 blobQry
= "DECLARE blobcmt CURSOR FOR SELECT oid, (SELECT description FROM pg_description pd WHERE pd.objoid=pc.oid) FROM pg_class pc WHERE relkind = 'l'";
1946 res
= PQexec(g_conn
, blobQry
);
1947 check_sql_result(res
, g_conn
, blobQry
, PGRES_COMMAND_OK
);
1949 /* Command to fetch from cursor */
1950 blobFetchQry
= "FETCH 100 IN blobcmt";
1957 res
= PQexec(g_conn
, blobFetchQry
);
1958 check_sql_result(res
, g_conn
, blobFetchQry
, PGRES_TUPLES_OK
);
1960 /* Process the tuples, if any */
1961 for (i
= 0; i
< PQntuples(res
); i
++)
1966 /* ignore blobs without comments */
1967 if (PQgetisnull(res
, i
, 1))
1970 blobOid
= atooid(PQgetvalue(res
, i
, 0));
1971 comment
= PQgetvalue(res
, i
, 1);
1973 printfPQExpBuffer(commentcmd
, "COMMENT ON LARGE OBJECT %u IS ",
1975 appendStringLiteralAH(commentcmd
, comment
, AH
);
1976 appendPQExpBuffer(commentcmd
, ";\n");
1978 archputs(commentcmd
->data
, AH
);
1980 } while (PQntuples(res
) > 0);
1986 destroyPQExpBuffer(commentcmd
);
1993 * read all namespaces in the system catalogs and return them in the
1994 * NamespaceInfo* structure
1996 * numNamespaces is set to the number of namespaces read in
1999 getNamespaces(int *numNamespaces
)
2005 NamespaceInfo
*nsinfo
;
2013 * Before 7.3, there are no real namespaces; create two dummy entries, one
2014 * for user stuff and one for system stuff.
2016 if (g_fout
->remoteVersion
< 70300)
2018 nsinfo
= (NamespaceInfo
*) malloc(2 * sizeof(NamespaceInfo
));
2020 nsinfo
[0].dobj
.objType
= DO_NAMESPACE
;
2021 nsinfo
[0].dobj
.catId
.tableoid
= 0;
2022 nsinfo
[0].dobj
.catId
.oid
= 0;
2023 AssignDumpId(&nsinfo
[0].dobj
);
2024 nsinfo
[0].dobj
.name
= strdup("public");
2025 nsinfo
[0].rolname
= strdup("");
2026 nsinfo
[0].nspacl
= strdup("");
2028 selectDumpableNamespace(&nsinfo
[0]);
2030 nsinfo
[1].dobj
.objType
= DO_NAMESPACE
;
2031 nsinfo
[1].dobj
.catId
.tableoid
= 0;
2032 nsinfo
[1].dobj
.catId
.oid
= 1;
2033 AssignDumpId(&nsinfo
[1].dobj
);
2034 nsinfo
[1].dobj
.name
= strdup("pg_catalog");
2035 nsinfo
[1].rolname
= strdup("");
2036 nsinfo
[1].nspacl
= strdup("");
2038 selectDumpableNamespace(&nsinfo
[1]);
2040 g_namespaces
= nsinfo
;
2041 g_numNamespaces
= *numNamespaces
= 2;
2046 query
= createPQExpBuffer();
2048 /* Make sure we are in proper schema */
2049 selectSourceSchema("pg_catalog");
2052 * we fetch all namespaces including system ones, so that every object we
2053 * read in can be linked to a containing namespace.
2055 appendPQExpBuffer(query
, "SELECT tableoid, oid, nspname, "
2056 "(%s nspowner) as rolname, "
2057 "nspacl FROM pg_namespace",
2060 res
= PQexec(g_conn
, query
->data
);
2061 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2063 ntups
= PQntuples(res
);
2065 nsinfo
= (NamespaceInfo
*) malloc(ntups
* sizeof(NamespaceInfo
));
2067 i_tableoid
= PQfnumber(res
, "tableoid");
2068 i_oid
= PQfnumber(res
, "oid");
2069 i_nspname
= PQfnumber(res
, "nspname");
2070 i_rolname
= PQfnumber(res
, "rolname");
2071 i_nspacl
= PQfnumber(res
, "nspacl");
2073 for (i
= 0; i
< ntups
; i
++)
2075 nsinfo
[i
].dobj
.objType
= DO_NAMESPACE
;
2076 nsinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2077 nsinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2078 AssignDumpId(&nsinfo
[i
].dobj
);
2079 nsinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_nspname
));
2080 nsinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2081 nsinfo
[i
].nspacl
= strdup(PQgetvalue(res
, i
, i_nspacl
));
2083 /* Decide whether to dump this namespace */
2084 selectDumpableNamespace(&nsinfo
[i
]);
2086 if (strlen(nsinfo
[i
].rolname
) == 0)
2087 write_msg(NULL
, "WARNING: owner of schema \"%s\" appears to be invalid\n",
2088 nsinfo
[i
].dobj
.name
);
2092 destroyPQExpBuffer(query
);
2094 g_namespaces
= nsinfo
;
2095 g_numNamespaces
= *numNamespaces
= ntups
;
2102 * given a namespace OID and an object OID, look up the info read by
2105 * NB: for pre-7.3 source database, we use object OID to guess whether it's
2106 * a system object or not. In 7.3 and later there is no guessing.
2108 static NamespaceInfo
*
2109 findNamespace(Oid nsoid
, Oid objoid
)
2113 if (g_fout
->remoteVersion
>= 70300)
2115 for (i
= 0; i
< g_numNamespaces
; i
++)
2117 NamespaceInfo
*nsinfo
= &g_namespaces
[i
];
2119 if (nsoid
== nsinfo
->dobj
.catId
.oid
)
2122 write_msg(NULL
, "schema with OID %u does not exist\n", nsoid
);
2127 /* This code depends on the layout set up by getNamespaces. */
2128 if (objoid
> g_last_builtin_oid
)
2129 i
= 0; /* user object */
2131 i
= 1; /* system object */
2132 return &g_namespaces
[i
];
2135 return NULL
; /* keep compiler quiet */
2140 * read all types in the system catalogs and return them in the
2141 * TypeInfo* structure
2143 * numTypes is set to the number of types read in
2145 * NB: this must run after getFuncs() because we assume we can do
2149 getTypes(int *numTypes
)
2154 PQExpBuffer query
= createPQExpBuffer();
2156 ShellTypeInfo
*stinfo
;
2172 * we include even the built-in types because those may be used as array
2173 * elements by user-defined types
2175 * we filter out the built-in types when we dump out the types
2177 * same approach for undefined (shell) types and array types
2179 * Note: as of 8.3 we can reliably detect whether a type is an
2180 * auto-generated array type by checking the element type's typarray.
2181 * (Before that the test is capable of generating false positives.) We
2182 * still check for name beginning with '_', though, so as to avoid the
2183 * cost of the subselect probe for all standard types. This would have to
2184 * be revisited if the backend ever allows renaming of array types.
2187 /* Make sure we are in proper schema */
2188 selectSourceSchema("pg_catalog");
2190 if (g_fout
->remoteVersion
>= 80300)
2192 appendPQExpBuffer(query
, "SELECT tableoid, oid, typname, "
2194 "(%s typowner) as rolname, "
2195 "typinput::oid as typinput, "
2196 "typoutput::oid as typoutput, typelem, typrelid, "
2197 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2198 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
2199 "typtype, typisdefined, "
2200 "typname[0] = '_' AND typelem != 0 AND "
2201 "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
2205 else if (g_fout
->remoteVersion
>= 70300)
2207 appendPQExpBuffer(query
, "SELECT tableoid, oid, typname, "
2209 "(%s typowner) as rolname, "
2210 "typinput::oid as typinput, "
2211 "typoutput::oid as typoutput, typelem, typrelid, "
2212 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2213 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
2214 "typtype, typisdefined, "
2215 "typname[0] = '_' AND typelem != 0 AS isarray "
2219 else if (g_fout
->remoteVersion
>= 70100)
2221 appendPQExpBuffer(query
, "SELECT tableoid, oid, typname, "
2222 "0::oid as typnamespace, "
2223 "(%s typowner) as rolname, "
2224 "typinput::oid as typinput, "
2225 "typoutput::oid as typoutput, typelem, typrelid, "
2226 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2227 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
2228 "typtype, typisdefined, "
2229 "typname[0] = '_' AND typelem != 0 AS isarray "
2235 appendPQExpBuffer(query
, "SELECT "
2236 "(SELECT oid FROM pg_class WHERE relname = 'pg_type') AS tableoid, "
2238 "0::oid as typnamespace, "
2239 "(%s typowner) as rolname, "
2240 "typinput::oid as typinput, "
2241 "typoutput::oid as typoutput, typelem, typrelid, "
2242 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2243 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
2244 "typtype, typisdefined, "
2245 "typname[0] = '_' AND typelem != 0 AS isarray "
2250 res
= PQexec(g_conn
, query
->data
);
2251 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2253 ntups
= PQntuples(res
);
2255 tinfo
= (TypeInfo
*) malloc(ntups
* sizeof(TypeInfo
));
2257 i_tableoid
= PQfnumber(res
, "tableoid");
2258 i_oid
= PQfnumber(res
, "oid");
2259 i_typname
= PQfnumber(res
, "typname");
2260 i_typnamespace
= PQfnumber(res
, "typnamespace");
2261 i_rolname
= PQfnumber(res
, "rolname");
2262 i_typinput
= PQfnumber(res
, "typinput");
2263 i_typoutput
= PQfnumber(res
, "typoutput");
2264 i_typelem
= PQfnumber(res
, "typelem");
2265 i_typrelid
= PQfnumber(res
, "typrelid");
2266 i_typrelkind
= PQfnumber(res
, "typrelkind");
2267 i_typtype
= PQfnumber(res
, "typtype");
2268 i_typisdefined
= PQfnumber(res
, "typisdefined");
2269 i_isarray
= PQfnumber(res
, "isarray");
2271 for (i
= 0; i
< ntups
; i
++)
2273 tinfo
[i
].dobj
.objType
= DO_TYPE
;
2274 tinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2275 tinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2276 AssignDumpId(&tinfo
[i
].dobj
);
2277 tinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_typname
));
2278 tinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_typnamespace
)),
2279 tinfo
[i
].dobj
.catId
.oid
);
2280 tinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2281 tinfo
[i
].typelem
= atooid(PQgetvalue(res
, i
, i_typelem
));
2282 tinfo
[i
].typrelid
= atooid(PQgetvalue(res
, i
, i_typrelid
));
2283 tinfo
[i
].typrelkind
= *PQgetvalue(res
, i
, i_typrelkind
);
2284 tinfo
[i
].typtype
= *PQgetvalue(res
, i
, i_typtype
);
2285 tinfo
[i
].shellType
= NULL
;
2288 * If it's a table's rowtype, use special type code to facilitate
2289 * sorting into the desired order. (We don't want to consider it an
2290 * ordinary type because that would bring the table up into the
2291 * datatype part of the dump order.)
2293 if (OidIsValid(tinfo
[i
].typrelid
) &&
2294 tinfo
[i
].typrelkind
!= RELKIND_COMPOSITE_TYPE
)
2295 tinfo
[i
].dobj
.objType
= DO_TABLE_TYPE
;
2297 if (strcmp(PQgetvalue(res
, i
, i_typisdefined
), "t") == 0)
2298 tinfo
[i
].isDefined
= true;
2300 tinfo
[i
].isDefined
= false;
2302 if (strcmp(PQgetvalue(res
, i
, i_isarray
), "t") == 0)
2303 tinfo
[i
].isArray
= true;
2305 tinfo
[i
].isArray
= false;
2307 /* Decide whether we want to dump it */
2308 selectDumpableType(&tinfo
[i
]);
2311 * If it's a domain, fetch info about its constraints, if any
2313 tinfo
[i
].nDomChecks
= 0;
2314 tinfo
[i
].domChecks
= NULL
;
2315 if (tinfo
[i
].dobj
.dump
&& tinfo
[i
].typtype
== TYPTYPE_DOMAIN
)
2316 getDomainConstraints(&(tinfo
[i
]));
2319 * If it's a base type, make a DumpableObject representing a shell
2320 * definition of the type. We will need to dump that ahead of the I/O
2321 * functions for the type.
2323 * Note: the shell type doesn't have a catId. You might think it
2324 * should copy the base type's catId, but then it might capture the
2325 * pg_depend entries for the type, which we don't want.
2327 if (tinfo
[i
].dobj
.dump
&& tinfo
[i
].typtype
== TYPTYPE_BASE
)
2329 stinfo
= (ShellTypeInfo
*) malloc(sizeof(ShellTypeInfo
));
2330 stinfo
->dobj
.objType
= DO_SHELL_TYPE
;
2331 stinfo
->dobj
.catId
= nilCatalogId
;
2332 AssignDumpId(&stinfo
->dobj
);
2333 stinfo
->dobj
.name
= strdup(tinfo
[i
].dobj
.name
);
2334 stinfo
->dobj
.namespace = tinfo
[i
].dobj
.namespace;
2335 stinfo
->baseType
= &(tinfo
[i
]);
2336 tinfo
[i
].shellType
= stinfo
;
2339 * Initially mark the shell type as not to be dumped. We'll only
2340 * dump it if the I/O functions need to be dumped; this is taken
2341 * care of while sorting dependencies.
2343 stinfo
->dobj
.dump
= false;
2346 * However, if dumping from pre-7.3, there will be no dependency
2347 * info so we have to fake it here. We only need to worry about
2348 * typinput and typoutput since the other functions only exist
2351 if (g_fout
->remoteVersion
< 70300)
2357 typinput
= atooid(PQgetvalue(res
, i
, i_typinput
));
2358 typoutput
= atooid(PQgetvalue(res
, i
, i_typoutput
));
2360 funcInfo
= findFuncByOid(typinput
);
2361 if (funcInfo
&& funcInfo
->dobj
.dump
)
2363 /* base type depends on function */
2364 addObjectDependency(&tinfo
[i
].dobj
,
2365 funcInfo
->dobj
.dumpId
);
2366 /* function depends on shell type */
2367 addObjectDependency(&funcInfo
->dobj
,
2368 stinfo
->dobj
.dumpId
);
2369 /* mark shell type as to be dumped */
2370 stinfo
->dobj
.dump
= true;
2373 funcInfo
= findFuncByOid(typoutput
);
2374 if (funcInfo
&& funcInfo
->dobj
.dump
)
2376 /* base type depends on function */
2377 addObjectDependency(&tinfo
[i
].dobj
,
2378 funcInfo
->dobj
.dumpId
);
2379 /* function depends on shell type */
2380 addObjectDependency(&funcInfo
->dobj
,
2381 stinfo
->dobj
.dumpId
);
2382 /* mark shell type as to be dumped */
2383 stinfo
->dobj
.dump
= true;
2388 if (strlen(tinfo
[i
].rolname
) == 0 && tinfo
[i
].isDefined
)
2389 write_msg(NULL
, "WARNING: owner of data type \"%s\" appears to be invalid\n",
2390 tinfo
[i
].dobj
.name
);
2397 destroyPQExpBuffer(query
);
2404 * read all operators in the system catalogs and return them in the
2405 * OprInfo* structure
2407 * numOprs is set to the number of operators read in
2410 getOperators(int *numOprs
)
2415 PQExpBuffer query
= createPQExpBuffer();
2425 * find all operators, including builtin operators; we filter out
2426 * system-defined operators at dump-out time.
2429 /* Make sure we are in proper schema */
2430 selectSourceSchema("pg_catalog");
2432 if (g_fout
->remoteVersion
>= 70300)
2434 appendPQExpBuffer(query
, "SELECT tableoid, oid, oprname, "
2436 "(%s oprowner) as rolname, "
2437 "oprcode::oid as oprcode "
2441 else if (g_fout
->remoteVersion
>= 70100)
2443 appendPQExpBuffer(query
, "SELECT tableoid, oid, oprname, "
2444 "0::oid as oprnamespace, "
2445 "(%s oprowner) as rolname, "
2446 "oprcode::oid as oprcode "
2452 appendPQExpBuffer(query
, "SELECT "
2453 "(SELECT oid FROM pg_class WHERE relname = 'pg_operator') AS tableoid, "
2455 "0::oid as oprnamespace, "
2456 "(%s oprowner) as rolname, "
2457 "oprcode::oid as oprcode "
2462 res
= PQexec(g_conn
, query
->data
);
2463 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2465 ntups
= PQntuples(res
);
2468 oprinfo
= (OprInfo
*) malloc(ntups
* sizeof(OprInfo
));
2470 i_tableoid
= PQfnumber(res
, "tableoid");
2471 i_oid
= PQfnumber(res
, "oid");
2472 i_oprname
= PQfnumber(res
, "oprname");
2473 i_oprnamespace
= PQfnumber(res
, "oprnamespace");
2474 i_rolname
= PQfnumber(res
, "rolname");
2475 i_oprcode
= PQfnumber(res
, "oprcode");
2477 for (i
= 0; i
< ntups
; i
++)
2479 oprinfo
[i
].dobj
.objType
= DO_OPERATOR
;
2480 oprinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2481 oprinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2482 AssignDumpId(&oprinfo
[i
].dobj
);
2483 oprinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_oprname
));
2484 oprinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_oprnamespace
)),
2485 oprinfo
[i
].dobj
.catId
.oid
);
2486 oprinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2487 oprinfo
[i
].oprcode
= atooid(PQgetvalue(res
, i
, i_oprcode
));
2489 /* Decide whether we want to dump it */
2490 selectDumpableObject(&(oprinfo
[i
].dobj
));
2492 if (strlen(oprinfo
[i
].rolname
) == 0)
2493 write_msg(NULL
, "WARNING: owner of operator \"%s\" appears to be invalid\n",
2494 oprinfo
[i
].dobj
.name
);
2499 destroyPQExpBuffer(query
);
2506 * read all conversions in the system catalogs and return them in the
2507 * ConvInfo* structure
2509 * numConversions is set to the number of conversions read in
2512 getConversions(int *numConversions
)
2517 PQExpBuffer query
= createPQExpBuffer();
2525 /* Conversions didn't exist pre-7.3 */
2526 if (g_fout
->remoteVersion
< 70300)
2528 *numConversions
= 0;
2533 * find all conversions, including builtin conversions; we filter out
2534 * system-defined conversions at dump-out time.
2537 /* Make sure we are in proper schema */
2538 selectSourceSchema("pg_catalog");
2540 appendPQExpBuffer(query
, "SELECT tableoid, oid, conname, "
2542 "(%s conowner) as rolname "
2543 "FROM pg_conversion",
2546 res
= PQexec(g_conn
, query
->data
);
2547 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2549 ntups
= PQntuples(res
);
2550 *numConversions
= ntups
;
2552 convinfo
= (ConvInfo
*) malloc(ntups
* sizeof(ConvInfo
));
2554 i_tableoid
= PQfnumber(res
, "tableoid");
2555 i_oid
= PQfnumber(res
, "oid");
2556 i_conname
= PQfnumber(res
, "conname");
2557 i_connamespace
= PQfnumber(res
, "connamespace");
2558 i_rolname
= PQfnumber(res
, "rolname");
2560 for (i
= 0; i
< ntups
; i
++)
2562 convinfo
[i
].dobj
.objType
= DO_CONVERSION
;
2563 convinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2564 convinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2565 AssignDumpId(&convinfo
[i
].dobj
);
2566 convinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_conname
));
2567 convinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_connamespace
)),
2568 convinfo
[i
].dobj
.catId
.oid
);
2569 convinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2571 /* Decide whether we want to dump it */
2572 selectDumpableObject(&(convinfo
[i
].dobj
));
2577 destroyPQExpBuffer(query
);
2584 * read all opclasses in the system catalogs and return them in the
2585 * OpclassInfo* structure
2587 * numOpclasses is set to the number of opclasses read in
2590 getOpclasses(int *numOpclasses
)
2595 PQExpBuffer query
= createPQExpBuffer();
2596 OpclassInfo
*opcinfo
;
2604 * find all opclasses, including builtin opclasses; we filter out
2605 * system-defined opclasses at dump-out time.
2608 /* Make sure we are in proper schema */
2609 selectSourceSchema("pg_catalog");
2611 if (g_fout
->remoteVersion
>= 70300)
2613 appendPQExpBuffer(query
, "SELECT tableoid, oid, opcname, "
2615 "(%s opcowner) as rolname "
2619 else if (g_fout
->remoteVersion
>= 70100)
2621 appendPQExpBuffer(query
, "SELECT tableoid, oid, opcname, "
2622 "0::oid as opcnamespace, "
2623 "''::name as rolname "
2628 appendPQExpBuffer(query
, "SELECT "
2629 "(SELECT oid FROM pg_class WHERE relname = 'pg_opclass') AS tableoid, "
2631 "0::oid as opcnamespace, "
2632 "''::name as rolname "
2636 res
= PQexec(g_conn
, query
->data
);
2637 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2639 ntups
= PQntuples(res
);
2640 *numOpclasses
= ntups
;
2642 opcinfo
= (OpclassInfo
*) malloc(ntups
* sizeof(OpclassInfo
));
2644 i_tableoid
= PQfnumber(res
, "tableoid");
2645 i_oid
= PQfnumber(res
, "oid");
2646 i_opcname
= PQfnumber(res
, "opcname");
2647 i_opcnamespace
= PQfnumber(res
, "opcnamespace");
2648 i_rolname
= PQfnumber(res
, "rolname");
2650 for (i
= 0; i
< ntups
; i
++)
2652 opcinfo
[i
].dobj
.objType
= DO_OPCLASS
;
2653 opcinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2654 opcinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2655 AssignDumpId(&opcinfo
[i
].dobj
);
2656 opcinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_opcname
));
2657 opcinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_opcnamespace
)),
2658 opcinfo
[i
].dobj
.catId
.oid
);
2659 opcinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2661 /* Decide whether we want to dump it */
2662 selectDumpableObject(&(opcinfo
[i
].dobj
));
2664 if (g_fout
->remoteVersion
>= 70300)
2666 if (strlen(opcinfo
[i
].rolname
) == 0)
2667 write_msg(NULL
, "WARNING: owner of operator class \"%s\" appears to be invalid\n",
2668 opcinfo
[i
].dobj
.name
);
2674 destroyPQExpBuffer(query
);
2681 * read all opfamilies in the system catalogs and return them in the
2682 * OpfamilyInfo* structure
2684 * numOpfamilies is set to the number of opfamilies read in
2687 getOpfamilies(int *numOpfamilies
)
2693 OpfamilyInfo
*opfinfo
;
2700 /* Before 8.3, there is no separate concept of opfamilies */
2701 if (g_fout
->remoteVersion
< 80300)
2707 query
= createPQExpBuffer();
2710 * find all opfamilies, including builtin opfamilies; we filter out
2711 * system-defined opfamilies at dump-out time.
2714 /* Make sure we are in proper schema */
2715 selectSourceSchema("pg_catalog");
2717 appendPQExpBuffer(query
, "SELECT tableoid, oid, opfname, "
2719 "(%s opfowner) as rolname "
2723 res
= PQexec(g_conn
, query
->data
);
2724 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2726 ntups
= PQntuples(res
);
2727 *numOpfamilies
= ntups
;
2729 opfinfo
= (OpfamilyInfo
*) malloc(ntups
* sizeof(OpfamilyInfo
));
2731 i_tableoid
= PQfnumber(res
, "tableoid");
2732 i_oid
= PQfnumber(res
, "oid");
2733 i_opfname
= PQfnumber(res
, "opfname");
2734 i_opfnamespace
= PQfnumber(res
, "opfnamespace");
2735 i_rolname
= PQfnumber(res
, "rolname");
2737 for (i
= 0; i
< ntups
; i
++)
2739 opfinfo
[i
].dobj
.objType
= DO_OPFAMILY
;
2740 opfinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2741 opfinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2742 AssignDumpId(&opfinfo
[i
].dobj
);
2743 opfinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_opfname
));
2744 opfinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_opfnamespace
)),
2745 opfinfo
[i
].dobj
.catId
.oid
);
2746 opfinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2748 /* Decide whether we want to dump it */
2749 selectDumpableObject(&(opfinfo
[i
].dobj
));
2751 if (g_fout
->remoteVersion
>= 70300)
2753 if (strlen(opfinfo
[i
].rolname
) == 0)
2754 write_msg(NULL
, "WARNING: owner of operator family \"%s\" appears to be invalid\n",
2755 opfinfo
[i
].dobj
.name
);
2761 destroyPQExpBuffer(query
);
2768 * read all the user-defined aggregates in the system catalogs and
2769 * return them in the AggInfo* structure
2771 * numAggs is set to the number of aggregates read in
2774 getAggregates(int *numAggs
)
2779 PQExpBuffer query
= createPQExpBuffer();
2790 /* Make sure we are in proper schema */
2791 selectSourceSchema("pg_catalog");
2793 /* find all user-defined aggregates */
2795 if (g_fout
->remoteVersion
>= 80200)
2797 appendPQExpBuffer(query
, "SELECT tableoid, oid, proname as aggname, "
2798 "pronamespace as aggnamespace, "
2799 "pronargs, proargtypes, "
2800 "(%s proowner) as rolname, "
2804 "AND pronamespace != "
2805 "(select oid from pg_namespace where nspname = 'pg_catalog')",
2808 else if (g_fout
->remoteVersion
>= 70300)
2810 appendPQExpBuffer(query
, "SELECT tableoid, oid, proname as aggname, "
2811 "pronamespace as aggnamespace, "
2812 "CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END as pronargs, "
2814 "(%s proowner) as rolname, "
2818 "AND pronamespace != "
2819 "(select oid from pg_namespace where nspname = 'pg_catalog')",
2822 else if (g_fout
->remoteVersion
>= 70100)
2824 appendPQExpBuffer(query
, "SELECT tableoid, oid, aggname, "
2825 "0::oid as aggnamespace, "
2826 "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END as pronargs, "
2827 "aggbasetype as proargtypes, "
2828 "(%s aggowner) as rolname, "
2830 "FROM pg_aggregate "
2831 "where oid > '%u'::oid",
2833 g_last_builtin_oid
);
2837 appendPQExpBuffer(query
, "SELECT "
2838 "(SELECT oid FROM pg_class WHERE relname = 'pg_aggregate') AS tableoid, "
2840 "0::oid as aggnamespace, "
2841 "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END as pronargs, "
2842 "aggbasetype as proargtypes, "
2843 "(%s aggowner) as rolname, "
2845 "FROM pg_aggregate "
2846 "where oid > '%u'::oid",
2848 g_last_builtin_oid
);
2851 res
= PQexec(g_conn
, query
->data
);
2852 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2854 ntups
= PQntuples(res
);
2857 agginfo
= (AggInfo
*) malloc(ntups
* sizeof(AggInfo
));
2859 i_tableoid
= PQfnumber(res
, "tableoid");
2860 i_oid
= PQfnumber(res
, "oid");
2861 i_aggname
= PQfnumber(res
, "aggname");
2862 i_aggnamespace
= PQfnumber(res
, "aggnamespace");
2863 i_pronargs
= PQfnumber(res
, "pronargs");
2864 i_proargtypes
= PQfnumber(res
, "proargtypes");
2865 i_rolname
= PQfnumber(res
, "rolname");
2866 i_aggacl
= PQfnumber(res
, "aggacl");
2868 for (i
= 0; i
< ntups
; i
++)
2870 agginfo
[i
].aggfn
.dobj
.objType
= DO_AGG
;
2871 agginfo
[i
].aggfn
.dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2872 agginfo
[i
].aggfn
.dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2873 AssignDumpId(&agginfo
[i
].aggfn
.dobj
);
2874 agginfo
[i
].aggfn
.dobj
.name
= strdup(PQgetvalue(res
, i
, i_aggname
));
2875 agginfo
[i
].aggfn
.dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_aggnamespace
)),
2876 agginfo
[i
].aggfn
.dobj
.catId
.oid
);
2877 agginfo
[i
].aggfn
.rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2878 if (strlen(agginfo
[i
].aggfn
.rolname
) == 0)
2879 write_msg(NULL
, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
2880 agginfo
[i
].aggfn
.dobj
.name
);
2881 agginfo
[i
].aggfn
.lang
= InvalidOid
; /* not currently interesting */
2882 agginfo
[i
].aggfn
.prorettype
= InvalidOid
; /* not saved */
2883 agginfo
[i
].aggfn
.proacl
= strdup(PQgetvalue(res
, i
, i_aggacl
));
2884 agginfo
[i
].aggfn
.nargs
= atoi(PQgetvalue(res
, i
, i_pronargs
));
2885 if (agginfo
[i
].aggfn
.nargs
== 0)
2886 agginfo
[i
].aggfn
.argtypes
= NULL
;
2889 agginfo
[i
].aggfn
.argtypes
= (Oid
*) malloc(agginfo
[i
].aggfn
.nargs
* sizeof(Oid
));
2890 if (g_fout
->remoteVersion
>= 70300)
2891 parseOidArray(PQgetvalue(res
, i
, i_proargtypes
),
2892 agginfo
[i
].aggfn
.argtypes
,
2893 agginfo
[i
].aggfn
.nargs
);
2895 /* it's just aggbasetype */
2896 agginfo
[i
].aggfn
.argtypes
[0] = atooid(PQgetvalue(res
, i
, i_proargtypes
));
2899 /* Decide whether we want to dump it */
2900 selectDumpableObject(&(agginfo
[i
].aggfn
.dobj
));
2905 destroyPQExpBuffer(query
);
2912 * read all the user-defined functions in the system catalogs and
2913 * return them in the FuncInfo* structure
2915 * numFuncs is set to the number of functions read in
2918 getFuncs(int *numFuncs
)
2923 PQExpBuffer query
= createPQExpBuffer();
2936 /* Make sure we are in proper schema */
2937 selectSourceSchema("pg_catalog");
2939 /* find all user-defined funcs */
2941 if (g_fout
->remoteVersion
>= 70300)
2943 appendPQExpBuffer(query
,
2944 "SELECT tableoid, oid, proname, prolang, "
2945 "pronargs, proargtypes, prorettype, proacl, "
2947 "(%s proowner) as rolname "
2949 "WHERE NOT proisagg "
2950 "AND pronamespace != "
2951 "(select oid from pg_namespace"
2952 " where nspname = 'pg_catalog')",
2955 else if (g_fout
->remoteVersion
>= 70100)
2957 appendPQExpBuffer(query
,
2958 "SELECT tableoid, oid, proname, prolang, "
2959 "pronargs, proargtypes, prorettype, "
2960 "'{=X}' as proacl, "
2961 "0::oid as pronamespace, "
2962 "(%s proowner) as rolname "
2964 "where pg_proc.oid > '%u'::oid",
2966 g_last_builtin_oid
);
2970 appendPQExpBuffer(query
,
2972 "(SELECT oid FROM pg_class "
2973 " WHERE relname = 'pg_proc') AS tableoid, "
2974 "oid, proname, prolang, "
2975 "pronargs, proargtypes, prorettype, "
2976 "'{=X}' as proacl, "
2977 "0::oid as pronamespace, "
2978 "(%s proowner) as rolname "
2980 "where pg_proc.oid > '%u'::oid",
2982 g_last_builtin_oid
);
2985 res
= PQexec(g_conn
, query
->data
);
2986 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2988 ntups
= PQntuples(res
);
2992 finfo
= (FuncInfo
*) calloc(ntups
, sizeof(FuncInfo
));
2994 i_tableoid
= PQfnumber(res
, "tableoid");
2995 i_oid
= PQfnumber(res
, "oid");
2996 i_proname
= PQfnumber(res
, "proname");
2997 i_pronamespace
= PQfnumber(res
, "pronamespace");
2998 i_rolname
= PQfnumber(res
, "rolname");
2999 i_prolang
= PQfnumber(res
, "prolang");
3000 i_pronargs
= PQfnumber(res
, "pronargs");
3001 i_proargtypes
= PQfnumber(res
, "proargtypes");
3002 i_prorettype
= PQfnumber(res
, "prorettype");
3003 i_proacl
= PQfnumber(res
, "proacl");
3005 for (i
= 0; i
< ntups
; i
++)
3007 finfo
[i
].dobj
.objType
= DO_FUNC
;
3008 finfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
3009 finfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
3010 AssignDumpId(&finfo
[i
].dobj
);
3011 finfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_proname
));
3012 finfo
[i
].dobj
.namespace =
3013 findNamespace(atooid(PQgetvalue(res
, i
, i_pronamespace
)),
3014 finfo
[i
].dobj
.catId
.oid
);
3015 finfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
3016 finfo
[i
].lang
= atooid(PQgetvalue(res
, i
, i_prolang
));
3017 finfo
[i
].prorettype
= atooid(PQgetvalue(res
, i
, i_prorettype
));
3018 finfo
[i
].proacl
= strdup(PQgetvalue(res
, i
, i_proacl
));
3019 finfo
[i
].nargs
= atoi(PQgetvalue(res
, i
, i_pronargs
));
3020 if (finfo
[i
].nargs
== 0)
3021 finfo
[i
].argtypes
= NULL
;
3024 finfo
[i
].argtypes
= (Oid
*) malloc(finfo
[i
].nargs
* sizeof(Oid
));
3025 parseOidArray(PQgetvalue(res
, i
, i_proargtypes
),
3026 finfo
[i
].argtypes
, finfo
[i
].nargs
);
3029 /* Decide whether we want to dump it */
3030 selectDumpableObject(&(finfo
[i
].dobj
));
3032 if (strlen(finfo
[i
].rolname
) == 0)
3034 "WARNING: owner of function \"%s\" appears to be invalid\n",
3035 finfo
[i
].dobj
.name
);
3040 destroyPQExpBuffer(query
);
3047 * read all the user-defined tables (no indexes, no catalogs)
3048 * in the system catalogs return them in the TableInfo* structure
3050 * numTables is set to the number of tables read in
3053 getTables(int *numTables
)
3058 PQExpBuffer query
= createPQExpBuffer();
3074 int i_reltablespace
;
3077 /* Make sure we are in proper schema */
3078 selectSourceSchema("pg_catalog");
3081 * Find all the tables (including views and sequences).
3083 * We include system catalogs, so that we can work if a user table is
3084 * defined to inherit from a system catalog (pretty weird, but...)
3086 * We ignore tables that are not type 'r' (ordinary relation), 'S'
3087 * (sequence), 'v' (view), or 'c' (composite type).
3089 * Composite-type table entries won't be dumped as such, but we have to
3090 * make a DumpableObject for them so that we can track dependencies of the
3091 * composite type (pg_depend entries for columns of the composite type
3092 * link to the pg_class entry not the pg_type entry).
3094 * Note: in this phase we should collect only a minimal amount of
3095 * information about each table, basically just enough to decide if it is
3096 * interesting. We must fetch all tables in this phase because otherwise
3097 * we cannot correctly identify inherited columns, owned sequences, etc.
3100 if (g_fout
->remoteVersion
>= 80200)
3103 * Left join to pick up dependency info linking sequences to their
3104 * owning column, if any (note this dependency is AUTO as of 8.2)
3106 appendPQExpBuffer(query
,
3107 "SELECT c.tableoid, c.oid, relname, "
3108 "relacl, relkind, relnamespace, "
3109 "(%s relowner) as rolname, "
3110 "relchecks, reltriggers, "
3111 "relhasindex, relhasrules, relhasoids, "
3112 "d.refobjid as owning_tab, "
3113 "d.refobjsubid as owning_col, "
3114 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3115 "array_to_string(c.reloptions, ', ') as reloptions "
3117 "left join pg_depend d on "
3118 "(c.relkind = '%c' and "
3119 "d.classid = c.tableoid and d.objid = c.oid and "
3120 "d.objsubid = 0 and "
3121 "d.refclassid = c.tableoid and d.deptype = 'a') "
3122 "where relkind in ('%c', '%c', '%c', '%c') "
3126 RELKIND_RELATION
, RELKIND_SEQUENCE
,
3127 RELKIND_VIEW
, RELKIND_COMPOSITE_TYPE
);
3129 else if (g_fout
->remoteVersion
>= 80000)
3132 * Left join to pick up dependency info linking sequences to their
3133 * owning column, if any
3135 appendPQExpBuffer(query
,
3136 "SELECT c.tableoid, c.oid, relname, "
3137 "relacl, relkind, relnamespace, "
3138 "(%s relowner) as rolname, "
3139 "relchecks, reltriggers, "
3140 "relhasindex, relhasrules, relhasoids, "
3141 "d.refobjid as owning_tab, "
3142 "d.refobjsubid as owning_col, "
3143 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3144 "NULL as reloptions "
3146 "left join pg_depend d on "
3147 "(c.relkind = '%c' and "
3148 "d.classid = c.tableoid and d.objid = c.oid and "
3149 "d.objsubid = 0 and "
3150 "d.refclassid = c.tableoid and d.deptype = 'i') "
3151 "where relkind in ('%c', '%c', '%c', '%c') "
3155 RELKIND_RELATION
, RELKIND_SEQUENCE
,
3156 RELKIND_VIEW
, RELKIND_COMPOSITE_TYPE
);
3158 else if (g_fout
->remoteVersion
>= 70300)
3161 * Left join to pick up dependency info linking sequences to their
3162 * owning column, if any
3164 appendPQExpBuffer(query
,
3165 "SELECT c.tableoid, c.oid, relname, "
3166 "relacl, relkind, relnamespace, "
3167 "(%s relowner) as rolname, "
3168 "relchecks, reltriggers, "
3169 "relhasindex, relhasrules, relhasoids, "
3170 "d.refobjid as owning_tab, "
3171 "d.refobjsubid as owning_col, "
3172 "NULL as reltablespace, "
3173 "NULL as reloptions "
3175 "left join pg_depend d on "
3176 "(c.relkind = '%c' and "
3177 "d.classid = c.tableoid and d.objid = c.oid and "
3178 "d.objsubid = 0 and "
3179 "d.refclassid = c.tableoid and d.deptype = 'i') "
3180 "where relkind in ('%c', '%c', '%c', '%c') "
3184 RELKIND_RELATION
, RELKIND_SEQUENCE
,
3185 RELKIND_VIEW
, RELKIND_COMPOSITE_TYPE
);
3187 else if (g_fout
->remoteVersion
>= 70200)
3189 appendPQExpBuffer(query
,
3190 "SELECT tableoid, oid, relname, relacl, relkind, "
3191 "0::oid as relnamespace, "
3192 "(%s relowner) as rolname, "
3193 "relchecks, reltriggers, "
3194 "relhasindex, relhasrules, relhasoids, "
3195 "NULL::oid as owning_tab, "
3196 "NULL::int4 as owning_col, "
3197 "NULL as reltablespace, "
3198 "NULL as reloptions "
3200 "where relkind in ('%c', '%c', '%c') "
3203 RELKIND_RELATION
, RELKIND_SEQUENCE
, RELKIND_VIEW
);
3205 else if (g_fout
->remoteVersion
>= 70100)
3207 /* all tables have oids in 7.1 */
3208 appendPQExpBuffer(query
,
3209 "SELECT tableoid, oid, relname, relacl, relkind, "
3210 "0::oid as relnamespace, "
3211 "(%s relowner) as rolname, "
3212 "relchecks, reltriggers, "
3213 "relhasindex, relhasrules, "
3214 "'t'::bool as relhasoids, "
3215 "NULL::oid as owning_tab, "
3216 "NULL::int4 as owning_col, "
3217 "NULL as reltablespace, "
3218 "NULL as reloptions "
3220 "where relkind in ('%c', '%c', '%c') "
3223 RELKIND_RELATION
, RELKIND_SEQUENCE
, RELKIND_VIEW
);
3228 * Before 7.1, view relkind was not set to 'v', so we must check if we
3229 * have a view by looking for a rule in pg_rewrite.
3231 appendPQExpBuffer(query
,
3233 "(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
3234 "oid, relname, relacl, "
3235 "CASE WHEN relhasrules and relkind = 'r' "
3236 " and EXISTS(SELECT rulename FROM pg_rewrite r WHERE "
3237 " r.ev_class = c.oid AND r.ev_type = '1') "
3238 "THEN '%c'::\"char\" "
3239 "ELSE relkind END AS relkind,"
3240 "0::oid as relnamespace, "
3241 "(%s relowner) as rolname, "
3242 "relchecks, reltriggers, "
3243 "relhasindex, relhasrules, "
3244 "'t'::bool as relhasoids, "
3245 "NULL::oid as owning_tab, "
3246 "NULL::int4 as owning_col, "
3247 "NULL as reltablespace, "
3248 "NULL as reloptions "
3250 "where relkind in ('%c', '%c') "
3254 RELKIND_RELATION
, RELKIND_SEQUENCE
);
3257 res
= PQexec(g_conn
, query
->data
);
3258 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3260 ntups
= PQntuples(res
);
3265 * Extract data from result and lock dumpable tables. We do the locking
3266 * before anything else, to minimize the window wherein a table could
3267 * disappear under us.
3269 * Note that we have to save info about all tables here, even when dumping
3270 * only one, because we don't yet know which tables might be inheritance
3271 * ancestors of the target table.
3273 tblinfo
= (TableInfo
*) calloc(ntups
, sizeof(TableInfo
));
3275 i_reltableoid
= PQfnumber(res
, "tableoid");
3276 i_reloid
= PQfnumber(res
, "oid");
3277 i_relname
= PQfnumber(res
, "relname");
3278 i_relnamespace
= PQfnumber(res
, "relnamespace");
3279 i_relacl
= PQfnumber(res
, "relacl");
3280 i_relkind
= PQfnumber(res
, "relkind");
3281 i_rolname
= PQfnumber(res
, "rolname");
3282 i_relchecks
= PQfnumber(res
, "relchecks");
3283 i_reltriggers
= PQfnumber(res
, "reltriggers");
3284 i_relhasindex
= PQfnumber(res
, "relhasindex");
3285 i_relhasrules
= PQfnumber(res
, "relhasrules");
3286 i_relhasoids
= PQfnumber(res
, "relhasoids");
3287 i_owning_tab
= PQfnumber(res
, "owning_tab");
3288 i_owning_col
= PQfnumber(res
, "owning_col");
3289 i_reltablespace
= PQfnumber(res
, "reltablespace");
3290 i_reloptions
= PQfnumber(res
, "reloptions");
3292 if (lockWaitTimeout
&& g_fout
->remoteVersion
>= 70300)
3295 * Arrange to fail instead of waiting forever for a table lock.
3297 * NB: this coding assumes that the only queries issued within
3298 * the following loop are LOCK TABLEs; else the timeout may be
3299 * undesirably applied to other things too.
3301 resetPQExpBuffer(query
);
3302 appendPQExpBuffer(query
, "SET statement_timeout = ");
3303 appendStringLiteralConn(query
, lockWaitTimeout
, g_conn
);
3304 do_sql_command(g_conn
, query
->data
);
3307 for (i
= 0; i
< ntups
; i
++)
3309 tblinfo
[i
].dobj
.objType
= DO_TABLE
;
3310 tblinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_reltableoid
));
3311 tblinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_reloid
));
3312 AssignDumpId(&tblinfo
[i
].dobj
);
3313 tblinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_relname
));
3314 tblinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_relnamespace
)),
3315 tblinfo
[i
].dobj
.catId
.oid
);
3316 tblinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
3317 tblinfo
[i
].relacl
= strdup(PQgetvalue(res
, i
, i_relacl
));
3318 tblinfo
[i
].relkind
= *(PQgetvalue(res
, i
, i_relkind
));
3319 tblinfo
[i
].hasindex
= (strcmp(PQgetvalue(res
, i
, i_relhasindex
), "t") == 0);
3320 tblinfo
[i
].hasrules
= (strcmp(PQgetvalue(res
, i
, i_relhasrules
), "t") == 0);
3321 tblinfo
[i
].hasoids
= (strcmp(PQgetvalue(res
, i
, i_relhasoids
), "t") == 0);
3322 tblinfo
[i
].ncheck
= atoi(PQgetvalue(res
, i
, i_relchecks
));
3323 tblinfo
[i
].ntrig
= atoi(PQgetvalue(res
, i
, i_reltriggers
));
3324 if (PQgetisnull(res
, i
, i_owning_tab
))
3326 tblinfo
[i
].owning_tab
= InvalidOid
;
3327 tblinfo
[i
].owning_col
= 0;
3331 tblinfo
[i
].owning_tab
= atooid(PQgetvalue(res
, i
, i_owning_tab
));
3332 tblinfo
[i
].owning_col
= atoi(PQgetvalue(res
, i
, i_owning_col
));
3334 tblinfo
[i
].reltablespace
= strdup(PQgetvalue(res
, i
, i_reltablespace
));
3335 tblinfo
[i
].reloptions
= strdup(PQgetvalue(res
, i
, i_reloptions
));
3337 /* other fields were zeroed above */
3340 * Decide whether we want to dump this table.
3342 if (tblinfo
[i
].relkind
== RELKIND_COMPOSITE_TYPE
)
3343 tblinfo
[i
].dobj
.dump
= false;
3345 selectDumpableTable(&tblinfo
[i
]);
3346 tblinfo
[i
].interesting
= tblinfo
[i
].dobj
.dump
;
3349 * Read-lock target tables to make sure they aren't DROPPED or altered
3350 * in schema before we get around to dumping them.
3352 * Note that we don't explicitly lock parents of the target tables; we
3353 * assume our lock on the child is enough to prevent schema
3354 * alterations to parent tables.
3356 * NOTE: it'd be kinda nice to lock views and sequences too, not only
3357 * plain tables, but the backend doesn't presently allow that.
3359 if (tblinfo
[i
].dobj
.dump
&& tblinfo
[i
].relkind
== RELKIND_RELATION
)
3361 resetPQExpBuffer(query
);
3362 appendPQExpBuffer(query
,
3363 "LOCK TABLE %s IN ACCESS SHARE MODE",
3364 fmtQualifiedId(tblinfo
[i
].dobj
.namespace->dobj
.name
,
3365 tblinfo
[i
].dobj
.name
));
3366 do_sql_command(g_conn
, query
->data
);
3369 /* Emit notice if join for owner failed */
3370 if (strlen(tblinfo
[i
].rolname
) == 0)
3371 write_msg(NULL
, "WARNING: owner of table \"%s\" appears to be invalid\n",
3372 tblinfo
[i
].dobj
.name
);
3375 if (lockWaitTimeout
&& g_fout
->remoteVersion
>= 70300)
3377 do_sql_command(g_conn
, "SET statement_timeout = 0");
3383 * Force sequences that are "owned" by table columns to be dumped whenever
3384 * their owning table is being dumped.
3386 for (i
= 0; i
< ntups
; i
++)
3388 TableInfo
*seqinfo
= &tblinfo
[i
];
3391 if (!OidIsValid(seqinfo
->owning_tab
))
3392 continue; /* not an owned sequence */
3393 if (seqinfo
->dobj
.dump
)
3394 continue; /* no need to search */
3396 /* can't use findTableByOid yet, unfortunately */
3397 for (j
= 0; j
< ntups
; j
++)
3399 if (tblinfo
[j
].dobj
.catId
.oid
== seqinfo
->owning_tab
)
3401 if (tblinfo
[j
].dobj
.dump
)
3403 seqinfo
->interesting
= true;
3404 seqinfo
->dobj
.dump
= true;
3411 destroyPQExpBuffer(query
);
3418 * read all the inheritance information
3419 * from the system catalogs return them in the InhInfo* structure
3421 * numInherits is set to the number of pairs read in
3424 getInherits(int *numInherits
)
3429 PQExpBuffer query
= createPQExpBuffer();
3435 /* Make sure we are in proper schema */
3436 selectSourceSchema("pg_catalog");
3438 /* find all the inheritance information */
3440 appendPQExpBuffer(query
, "SELECT inhrelid, inhparent from pg_inherits");
3442 res
= PQexec(g_conn
, query
->data
);
3443 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3445 ntups
= PQntuples(res
);
3447 *numInherits
= ntups
;
3449 inhinfo
= (InhInfo
*) malloc(ntups
* sizeof(InhInfo
));
3451 i_inhrelid
= PQfnumber(res
, "inhrelid");
3452 i_inhparent
= PQfnumber(res
, "inhparent");
3454 for (i
= 0; i
< ntups
; i
++)
3456 inhinfo
[i
].inhrelid
= atooid(PQgetvalue(res
, i
, i_inhrelid
));
3457 inhinfo
[i
].inhparent
= atooid(PQgetvalue(res
, i
, i_inhparent
));
3462 destroyPQExpBuffer(query
);
3469 * get information about every index on a dumpable table
3471 * Note: index data is not returned directly to the caller, but it
3472 * does get entered into the DumpableObject tables.
3475 getIndexes(TableInfo tblinfo
[], int numTables
)
3479 PQExpBuffer query
= createPQExpBuffer();
3482 ConstraintInfo
*constrinfo
;
3498 for (i
= 0; i
< numTables
; i
++)
3500 TableInfo
*tbinfo
= &tblinfo
[i
];
3502 /* Only plain tables have indexes */
3503 if (tbinfo
->relkind
!= RELKIND_RELATION
|| !tbinfo
->hasindex
)
3506 /* Ignore indexes of tables not to be dumped */
3507 if (!tbinfo
->dobj
.dump
)
3511 write_msg(NULL
, "reading indexes for table \"%s\"\n",
3514 /* Make sure we are in proper schema so indexdef is right */
3515 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
3518 * The point of the messy-looking outer join is to find a constraint
3519 * that is related by an internal dependency link to the index. If we
3520 * find one, create a CONSTRAINT entry linked to the INDEX entry. We
3521 * assume an index won't have more than one internal dependency.
3523 resetPQExpBuffer(query
);
3524 if (g_fout
->remoteVersion
>= 80200)
3526 appendPQExpBuffer(query
,
3527 "SELECT t.tableoid, t.oid, "
3528 "t.relname as indexname, "
3529 "pg_catalog.pg_get_indexdef(i.indexrelid) as indexdef, "
3530 "t.relnatts as indnkeys, "
3531 "i.indkey, i.indisclustered, "
3532 "c.contype, c.conname, "
3533 "c.tableoid as contableoid, "
3535 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) as tablespace, "
3536 "array_to_string(t.reloptions, ', ') as options "
3537 "FROM pg_catalog.pg_index i "
3538 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
3539 "LEFT JOIN pg_catalog.pg_depend d "
3540 "ON (d.classid = t.tableoid "
3541 "AND d.objid = t.oid "
3542 "AND d.deptype = 'i') "
3543 "LEFT JOIN pg_catalog.pg_constraint c "
3544 "ON (d.refclassid = c.tableoid "
3545 "AND d.refobjid = c.oid) "
3546 "WHERE i.indrelid = '%u'::pg_catalog.oid "
3547 "ORDER BY indexname",
3548 tbinfo
->dobj
.catId
.oid
);
3550 else if (g_fout
->remoteVersion
>= 80000)
3552 appendPQExpBuffer(query
,
3553 "SELECT t.tableoid, t.oid, "
3554 "t.relname as indexname, "
3555 "pg_catalog.pg_get_indexdef(i.indexrelid) as indexdef, "
3556 "t.relnatts as indnkeys, "
3557 "i.indkey, i.indisclustered, "
3558 "c.contype, c.conname, "
3559 "c.tableoid as contableoid, "
3561 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) as tablespace, "
3563 "FROM pg_catalog.pg_index i "
3564 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
3565 "LEFT JOIN pg_catalog.pg_depend d "
3566 "ON (d.classid = t.tableoid "
3567 "AND d.objid = t.oid "
3568 "AND d.deptype = 'i') "
3569 "LEFT JOIN pg_catalog.pg_constraint c "
3570 "ON (d.refclassid = c.tableoid "
3571 "AND d.refobjid = c.oid) "
3572 "WHERE i.indrelid = '%u'::pg_catalog.oid "
3573 "ORDER BY indexname",
3574 tbinfo
->dobj
.catId
.oid
);
3576 else if (g_fout
->remoteVersion
>= 70300)
3578 appendPQExpBuffer(query
,
3579 "SELECT t.tableoid, t.oid, "
3580 "t.relname as indexname, "
3581 "pg_catalog.pg_get_indexdef(i.indexrelid) as indexdef, "
3582 "t.relnatts as indnkeys, "
3583 "i.indkey, i.indisclustered, "
3584 "c.contype, c.conname, "
3585 "c.tableoid as contableoid, "
3587 "NULL as tablespace, "
3589 "FROM pg_catalog.pg_index i "
3590 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
3591 "LEFT JOIN pg_catalog.pg_depend d "
3592 "ON (d.classid = t.tableoid "
3593 "AND d.objid = t.oid "
3594 "AND d.deptype = 'i') "
3595 "LEFT JOIN pg_catalog.pg_constraint c "
3596 "ON (d.refclassid = c.tableoid "
3597 "AND d.refobjid = c.oid) "
3598 "WHERE i.indrelid = '%u'::pg_catalog.oid "
3599 "ORDER BY indexname",
3600 tbinfo
->dobj
.catId
.oid
);
3602 else if (g_fout
->remoteVersion
>= 70100)
3604 appendPQExpBuffer(query
,
3605 "SELECT t.tableoid, t.oid, "
3606 "t.relname as indexname, "
3607 "pg_get_indexdef(i.indexrelid) as indexdef, "
3608 "t.relnatts as indnkeys, "
3609 "i.indkey, false as indisclustered, "
3610 "CASE WHEN i.indisprimary THEN 'p'::char "
3611 "ELSE '0'::char END as contype, "
3612 "t.relname as conname, "
3613 "0::oid as contableoid, "
3615 "NULL as tablespace, "
3617 "FROM pg_index i, pg_class t "
3618 "WHERE t.oid = i.indexrelid "
3619 "AND i.indrelid = '%u'::oid "
3620 "ORDER BY indexname",
3621 tbinfo
->dobj
.catId
.oid
);
3625 appendPQExpBuffer(query
,
3627 "(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
3629 "t.relname as indexname, "
3630 "pg_get_indexdef(i.indexrelid) as indexdef, "
3631 "t.relnatts as indnkeys, "
3632 "i.indkey, false as indisclustered, "
3633 "CASE WHEN i.indisprimary THEN 'p'::char "
3634 "ELSE '0'::char END as contype, "
3635 "t.relname as conname, "
3636 "0::oid as contableoid, "
3638 "NULL as tablespace, "
3640 "FROM pg_index i, pg_class t "
3641 "WHERE t.oid = i.indexrelid "
3642 "AND i.indrelid = '%u'::oid "
3643 "ORDER BY indexname",
3644 tbinfo
->dobj
.catId
.oid
);
3647 res
= PQexec(g_conn
, query
->data
);
3648 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3650 ntups
= PQntuples(res
);
3652 i_tableoid
= PQfnumber(res
, "tableoid");
3653 i_oid
= PQfnumber(res
, "oid");
3654 i_indexname
= PQfnumber(res
, "indexname");
3655 i_indexdef
= PQfnumber(res
, "indexdef");
3656 i_indnkeys
= PQfnumber(res
, "indnkeys");
3657 i_indkey
= PQfnumber(res
, "indkey");
3658 i_indisclustered
= PQfnumber(res
, "indisclustered");
3659 i_contype
= PQfnumber(res
, "contype");
3660 i_conname
= PQfnumber(res
, "conname");
3661 i_contableoid
= PQfnumber(res
, "contableoid");
3662 i_conoid
= PQfnumber(res
, "conoid");
3663 i_tablespace
= PQfnumber(res
, "tablespace");
3664 i_options
= PQfnumber(res
, "options");
3666 indxinfo
= (IndxInfo
*) malloc(ntups
* sizeof(IndxInfo
));
3667 constrinfo
= (ConstraintInfo
*) malloc(ntups
* sizeof(ConstraintInfo
));
3669 for (j
= 0; j
< ntups
; j
++)
3673 indxinfo
[j
].dobj
.objType
= DO_INDEX
;
3674 indxinfo
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, i_tableoid
));
3675 indxinfo
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, i_oid
));
3676 AssignDumpId(&indxinfo
[j
].dobj
);
3677 indxinfo
[j
].dobj
.name
= strdup(PQgetvalue(res
, j
, i_indexname
));
3678 indxinfo
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
3679 indxinfo
[j
].indextable
= tbinfo
;
3680 indxinfo
[j
].indexdef
= strdup(PQgetvalue(res
, j
, i_indexdef
));
3681 indxinfo
[j
].indnkeys
= atoi(PQgetvalue(res
, j
, i_indnkeys
));
3682 indxinfo
[j
].tablespace
= strdup(PQgetvalue(res
, j
, i_tablespace
));
3683 indxinfo
[j
].options
= strdup(PQgetvalue(res
, j
, i_options
));
3686 * In pre-7.4 releases, indkeys may contain more entries than
3687 * indnkeys says (since indnkeys will be 1 for a functional
3688 * index). We don't actually care about this case since we don't
3689 * examine indkeys except for indexes associated with PRIMARY and
3690 * UNIQUE constraints, which are never functional indexes. But we
3691 * have to allocate enough space to keep parseOidArray from
3694 indxinfo
[j
].indkeys
= (Oid
*) malloc(INDEX_MAX_KEYS
* sizeof(Oid
));
3695 parseOidArray(PQgetvalue(res
, j
, i_indkey
),
3696 indxinfo
[j
].indkeys
, INDEX_MAX_KEYS
);
3697 indxinfo
[j
].indisclustered
= (PQgetvalue(res
, j
, i_indisclustered
)[0] == 't');
3698 contype
= *(PQgetvalue(res
, j
, i_contype
));
3700 if (contype
== 'p' || contype
== 'u')
3703 * If we found a constraint matching the index, create an
3706 * In a pre-7.3 database, we take this path iff the index was
3707 * marked indisprimary.
3709 constrinfo
[j
].dobj
.objType
= DO_CONSTRAINT
;
3710 constrinfo
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, i_contableoid
));
3711 constrinfo
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, i_conoid
));
3712 AssignDumpId(&constrinfo
[j
].dobj
);
3713 constrinfo
[j
].dobj
.name
= strdup(PQgetvalue(res
, j
, i_conname
));
3714 constrinfo
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
3715 constrinfo
[j
].contable
= tbinfo
;
3716 constrinfo
[j
].condomain
= NULL
;
3717 constrinfo
[j
].contype
= contype
;
3718 constrinfo
[j
].condef
= NULL
;
3719 constrinfo
[j
].confrelid
= InvalidOid
;
3720 constrinfo
[j
].conindex
= indxinfo
[j
].dobj
.dumpId
;
3721 constrinfo
[j
].conislocal
= true;
3722 constrinfo
[j
].separate
= true;
3724 indxinfo
[j
].indexconstraint
= constrinfo
[j
].dobj
.dumpId
;
3726 /* If pre-7.3 DB, better make sure table comes first */
3727 addObjectDependency(&constrinfo
[j
].dobj
,
3728 tbinfo
->dobj
.dumpId
);
3732 /* Plain secondary index */
3733 indxinfo
[j
].indexconstraint
= 0;
3740 destroyPQExpBuffer(query
);
3746 * Get info about constraints on dumpable tables.
3748 * Currently handles foreign keys only.
3749 * Unique and primary key constraints are handled with indexes,
3750 * while check constraints are processed in getTableAttrs().
3753 getConstraints(TableInfo tblinfo
[], int numTables
)
3757 ConstraintInfo
*constrinfo
;
3767 /* pg_constraint was created in 7.3, so nothing to do if older */
3768 if (g_fout
->remoteVersion
< 70300)
3771 query
= createPQExpBuffer();
3773 for (i
= 0; i
< numTables
; i
++)
3775 TableInfo
*tbinfo
= &tblinfo
[i
];
3777 if (tbinfo
->ntrig
== 0 || !tbinfo
->dobj
.dump
)
3781 write_msg(NULL
, "reading foreign key constraints for table \"%s\"\n",
3785 * select table schema to ensure constraint expr is qualified if
3788 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
3790 resetPQExpBuffer(query
);
3791 appendPQExpBuffer(query
,
3792 "SELECT tableoid, oid, conname, confrelid, "
3793 "pg_catalog.pg_get_constraintdef(oid) as condef "
3794 "FROM pg_catalog.pg_constraint "
3795 "WHERE conrelid = '%u'::pg_catalog.oid "
3796 "AND contype = 'f'",
3797 tbinfo
->dobj
.catId
.oid
);
3798 res
= PQexec(g_conn
, query
->data
);
3799 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3801 ntups
= PQntuples(res
);
3803 i_contableoid
= PQfnumber(res
, "tableoid");
3804 i_conoid
= PQfnumber(res
, "oid");
3805 i_conname
= PQfnumber(res
, "conname");
3806 i_confrelid
= PQfnumber(res
, "confrelid");
3807 i_condef
= PQfnumber(res
, "condef");
3809 constrinfo
= (ConstraintInfo
*) malloc(ntups
* sizeof(ConstraintInfo
));
3811 for (j
= 0; j
< ntups
; j
++)
3813 constrinfo
[j
].dobj
.objType
= DO_FK_CONSTRAINT
;
3814 constrinfo
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, i_contableoid
));
3815 constrinfo
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, i_conoid
));
3816 AssignDumpId(&constrinfo
[j
].dobj
);
3817 constrinfo
[j
].dobj
.name
= strdup(PQgetvalue(res
, j
, i_conname
));
3818 constrinfo
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
3819 constrinfo
[j
].contable
= tbinfo
;
3820 constrinfo
[j
].condomain
= NULL
;
3821 constrinfo
[j
].contype
= 'f';
3822 constrinfo
[j
].condef
= strdup(PQgetvalue(res
, j
, i_condef
));
3823 constrinfo
[j
].confrelid
= atooid(PQgetvalue(res
, j
, i_confrelid
));
3824 constrinfo
[j
].conindex
= 0;
3825 constrinfo
[j
].conislocal
= true;
3826 constrinfo
[j
].separate
= true;
3832 destroyPQExpBuffer(query
);
3836 * getDomainConstraints
3838 * Get info about constraints on a domain.
3841 getDomainConstraints(TypeInfo
*tinfo
)
3844 ConstraintInfo
*constrinfo
;
3853 /* pg_constraint was created in 7.3, so nothing to do if older */
3854 if (g_fout
->remoteVersion
< 70300)
3858 * select appropriate schema to ensure names in constraint are properly
3861 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
3863 query
= createPQExpBuffer();
3865 if (g_fout
->remoteVersion
>= 70400)
3866 appendPQExpBuffer(query
, "SELECT tableoid, oid, conname, "
3867 "pg_catalog.pg_get_constraintdef(oid) AS consrc "
3868 "FROM pg_catalog.pg_constraint "
3869 "WHERE contypid = '%u'::pg_catalog.oid "
3871 tinfo
->dobj
.catId
.oid
);
3873 appendPQExpBuffer(query
, "SELECT tableoid, oid, conname, "
3874 "'CHECK (' || consrc || ')' AS consrc "
3875 "FROM pg_catalog.pg_constraint "
3876 "WHERE contypid = '%u'::pg_catalog.oid "
3878 tinfo
->dobj
.catId
.oid
);
3880 res
= PQexec(g_conn
, query
->data
);
3881 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3883 ntups
= PQntuples(res
);
3885 i_tableoid
= PQfnumber(res
, "tableoid");
3886 i_oid
= PQfnumber(res
, "oid");
3887 i_conname
= PQfnumber(res
, "conname");
3888 i_consrc
= PQfnumber(res
, "consrc");
3890 constrinfo
= (ConstraintInfo
*) malloc(ntups
* sizeof(ConstraintInfo
));
3892 tinfo
->nDomChecks
= ntups
;
3893 tinfo
->domChecks
= constrinfo
;
3895 for (i
= 0; i
< ntups
; i
++)
3897 constrinfo
[i
].dobj
.objType
= DO_CONSTRAINT
;
3898 constrinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
3899 constrinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
3900 AssignDumpId(&constrinfo
[i
].dobj
);
3901 constrinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_conname
));
3902 constrinfo
[i
].dobj
.namespace = tinfo
->dobj
.namespace;
3903 constrinfo
[i
].contable
= NULL
;
3904 constrinfo
[i
].condomain
= tinfo
;
3905 constrinfo
[i
].contype
= 'c';
3906 constrinfo
[i
].condef
= strdup(PQgetvalue(res
, i
, i_consrc
));
3907 constrinfo
[i
].confrelid
= InvalidOid
;
3908 constrinfo
[i
].conindex
= 0;
3909 constrinfo
[i
].conislocal
= true;
3910 constrinfo
[i
].separate
= false;
3913 * Make the domain depend on the constraint, ensuring it won't be
3914 * output till any constraint dependencies are OK.
3916 addObjectDependency(&tinfo
->dobj
,
3917 constrinfo
[i
].dobj
.dumpId
);
3922 destroyPQExpBuffer(query
);
3927 * get basic information about every rule in the system
3929 * numRules is set to the number of rules read in
3932 getRules(int *numRules
)
3937 PQExpBuffer query
= createPQExpBuffer();
3947 /* Make sure we are in proper schema */
3948 selectSourceSchema("pg_catalog");
3950 if (g_fout
->remoteVersion
>= 80300)
3952 appendPQExpBuffer(query
, "SELECT "
3953 "tableoid, oid, rulename, "
3954 "ev_class as ruletable, ev_type, is_instead, "
3959 else if (g_fout
->remoteVersion
>= 70100)
3961 appendPQExpBuffer(query
, "SELECT "
3962 "tableoid, oid, rulename, "
3963 "ev_class as ruletable, ev_type, is_instead, "
3964 "'O'::char as ev_enabled "
3970 appendPQExpBuffer(query
, "SELECT "
3971 "(SELECT oid FROM pg_class WHERE relname = 'pg_rewrite') AS tableoid, "
3973 "ev_class as ruletable, ev_type, is_instead, "
3974 "'O'::char as ev_enabled "
3979 res
= PQexec(g_conn
, query
->data
);
3980 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3982 ntups
= PQntuples(res
);
3986 ruleinfo
= (RuleInfo
*) malloc(ntups
* sizeof(RuleInfo
));
3988 i_tableoid
= PQfnumber(res
, "tableoid");
3989 i_oid
= PQfnumber(res
, "oid");
3990 i_rulename
= PQfnumber(res
, "rulename");
3991 i_ruletable
= PQfnumber(res
, "ruletable");
3992 i_ev_type
= PQfnumber(res
, "ev_type");
3993 i_is_instead
= PQfnumber(res
, "is_instead");
3994 i_ev_enabled
= PQfnumber(res
, "ev_enabled");
3996 for (i
= 0; i
< ntups
; i
++)
4000 ruleinfo
[i
].dobj
.objType
= DO_RULE
;
4001 ruleinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
4002 ruleinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
4003 AssignDumpId(&ruleinfo
[i
].dobj
);
4004 ruleinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_rulename
));
4005 ruletableoid
= atooid(PQgetvalue(res
, i
, i_ruletable
));
4006 ruleinfo
[i
].ruletable
= findTableByOid(ruletableoid
);
4007 if (ruleinfo
[i
].ruletable
== NULL
)
4009 write_msg(NULL
, "failed sanity check, parent table OID %u of pg_rewrite entry OID %u not found\n",
4011 ruleinfo
[i
].dobj
.catId
.oid
);
4014 ruleinfo
[i
].dobj
.namespace = ruleinfo
[i
].ruletable
->dobj
.namespace;
4015 ruleinfo
[i
].dobj
.dump
= ruleinfo
[i
].ruletable
->dobj
.dump
;
4016 ruleinfo
[i
].ev_type
= *(PQgetvalue(res
, i
, i_ev_type
));
4017 ruleinfo
[i
].is_instead
= *(PQgetvalue(res
, i
, i_is_instead
)) == 't';
4018 ruleinfo
[i
].ev_enabled
= *(PQgetvalue(res
, i
, i_ev_enabled
));
4019 if (ruleinfo
[i
].ruletable
)
4022 * If the table is a view, force its ON SELECT rule to be sorted
4023 * before the view itself --- this ensures that any dependencies
4024 * for the rule affect the table's positioning. Other rules are
4025 * forced to appear after their table.
4027 if (ruleinfo
[i
].ruletable
->relkind
== RELKIND_VIEW
&&
4028 ruleinfo
[i
].ev_type
== '1' && ruleinfo
[i
].is_instead
)
4030 addObjectDependency(&ruleinfo
[i
].ruletable
->dobj
,
4031 ruleinfo
[i
].dobj
.dumpId
);
4032 /* We'll merge the rule into CREATE VIEW, if possible */
4033 ruleinfo
[i
].separate
= false;
4037 addObjectDependency(&ruleinfo
[i
].dobj
,
4038 ruleinfo
[i
].ruletable
->dobj
.dumpId
);
4039 ruleinfo
[i
].separate
= true;
4043 ruleinfo
[i
].separate
= true;
4048 destroyPQExpBuffer(query
);
4055 * get information about every trigger on a dumpable table
4057 * Note: trigger data is not returned directly to the caller, but it
4058 * does get entered into the DumpableObject tables.
4061 getTriggers(TableInfo tblinfo
[], int numTables
)
4065 PQExpBuffer query
= createPQExpBuffer();
4067 TriggerInfo
*tginfo
;
4084 for (i
= 0; i
< numTables
; i
++)
4086 TableInfo
*tbinfo
= &tblinfo
[i
];
4088 if (tbinfo
->ntrig
== 0 || !tbinfo
->dobj
.dump
)
4092 write_msg(NULL
, "reading triggers for table \"%s\"\n",
4096 * select table schema to ensure regproc name is qualified if needed
4098 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
4100 resetPQExpBuffer(query
);
4101 if (g_fout
->remoteVersion
>= 80300)
4104 * We ignore triggers that are tied to a foreign-key constraint
4106 appendPQExpBuffer(query
,
4108 "tgfoid::pg_catalog.regproc as tgfname, "
4109 "tgtype, tgnargs, tgargs, tgenabled, "
4110 "tgisconstraint, tgconstrname, tgdeferrable, "
4111 "tgconstrrelid, tginitdeferred, tableoid, oid, "
4112 "tgconstrrelid::pg_catalog.regclass as tgconstrrelname "
4113 "from pg_catalog.pg_trigger t "
4114 "where tgrelid = '%u'::pg_catalog.oid "
4115 "and tgconstraint = 0",
4116 tbinfo
->dobj
.catId
.oid
);
4118 else if (g_fout
->remoteVersion
>= 70300)
4121 * We ignore triggers that are tied to a foreign-key constraint,
4122 * but in these versions we have to grovel through pg_constraint
4125 appendPQExpBuffer(query
,
4127 "tgfoid::pg_catalog.regproc as tgfname, "
4128 "tgtype, tgnargs, tgargs, tgenabled, "
4129 "tgisconstraint, tgconstrname, tgdeferrable, "
4130 "tgconstrrelid, tginitdeferred, tableoid, oid, "
4131 "tgconstrrelid::pg_catalog.regclass as tgconstrrelname "
4132 "from pg_catalog.pg_trigger t "
4133 "where tgrelid = '%u'::pg_catalog.oid "
4134 "and (not tgisconstraint "
4136 " (SELECT 1 FROM pg_catalog.pg_depend d "
4137 " JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
4138 " WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))",
4139 tbinfo
->dobj
.catId
.oid
);
4141 else if (g_fout
->remoteVersion
>= 70100)
4143 appendPQExpBuffer(query
,
4144 "SELECT tgname, tgfoid::regproc as tgfname, "
4145 "tgtype, tgnargs, tgargs, tgenabled, "
4146 "tgisconstraint, tgconstrname, tgdeferrable, "
4147 "tgconstrrelid, tginitdeferred, tableoid, oid, "
4148 "(select relname from pg_class where oid = tgconstrrelid) "
4149 " as tgconstrrelname "
4151 "where tgrelid = '%u'::oid",
4152 tbinfo
->dobj
.catId
.oid
);
4156 appendPQExpBuffer(query
,
4157 "SELECT tgname, tgfoid::regproc as tgfname, "
4158 "tgtype, tgnargs, tgargs, tgenabled, "
4159 "tgisconstraint, tgconstrname, tgdeferrable, "
4160 "tgconstrrelid, tginitdeferred, "
4161 "(SELECT oid FROM pg_class WHERE relname = 'pg_trigger') AS tableoid, "
4164 "(select relname from pg_class where oid = tgconstrrelid) "
4165 " as tgconstrrelname "
4167 "where tgrelid = '%u'::oid",
4168 tbinfo
->dobj
.catId
.oid
);
4170 res
= PQexec(g_conn
, query
->data
);
4171 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
4173 ntups
= PQntuples(res
);
4176 * We may have less triggers than recorded due to having ignored
4177 * foreign-key triggers
4179 if (ntups
> tbinfo
->ntrig
)
4181 write_msg(NULL
, "expected %d triggers on table \"%s\" but found %d\n",
4182 tbinfo
->ntrig
, tbinfo
->dobj
.name
, ntups
);
4185 i_tableoid
= PQfnumber(res
, "tableoid");
4186 i_oid
= PQfnumber(res
, "oid");
4187 i_tgname
= PQfnumber(res
, "tgname");
4188 i_tgfname
= PQfnumber(res
, "tgfname");
4189 i_tgtype
= PQfnumber(res
, "tgtype");
4190 i_tgnargs
= PQfnumber(res
, "tgnargs");
4191 i_tgargs
= PQfnumber(res
, "tgargs");
4192 i_tgisconstraint
= PQfnumber(res
, "tgisconstraint");
4193 i_tgconstrname
= PQfnumber(res
, "tgconstrname");
4194 i_tgconstrrelid
= PQfnumber(res
, "tgconstrrelid");
4195 i_tgconstrrelname
= PQfnumber(res
, "tgconstrrelname");
4196 i_tgenabled
= PQfnumber(res
, "tgenabled");
4197 i_tgdeferrable
= PQfnumber(res
, "tgdeferrable");
4198 i_tginitdeferred
= PQfnumber(res
, "tginitdeferred");
4200 tginfo
= (TriggerInfo
*) malloc(ntups
* sizeof(TriggerInfo
));
4202 for (j
= 0; j
< ntups
; j
++)
4204 tginfo
[j
].dobj
.objType
= DO_TRIGGER
;
4205 tginfo
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, i_tableoid
));
4206 tginfo
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, i_oid
));
4207 AssignDumpId(&tginfo
[j
].dobj
);
4208 tginfo
[j
].dobj
.name
= strdup(PQgetvalue(res
, j
, i_tgname
));
4209 tginfo
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
4210 tginfo
[j
].tgtable
= tbinfo
;
4211 tginfo
[j
].tgfname
= strdup(PQgetvalue(res
, j
, i_tgfname
));
4212 tginfo
[j
].tgtype
= atoi(PQgetvalue(res
, j
, i_tgtype
));
4213 tginfo
[j
].tgnargs
= atoi(PQgetvalue(res
, j
, i_tgnargs
));
4214 tginfo
[j
].tgargs
= strdup(PQgetvalue(res
, j
, i_tgargs
));
4215 tginfo
[j
].tgisconstraint
= *(PQgetvalue(res
, j
, i_tgisconstraint
)) == 't';
4216 tginfo
[j
].tgenabled
= *(PQgetvalue(res
, j
, i_tgenabled
));
4217 tginfo
[j
].tgdeferrable
= *(PQgetvalue(res
, j
, i_tgdeferrable
)) == 't';
4218 tginfo
[j
].tginitdeferred
= *(PQgetvalue(res
, j
, i_tginitdeferred
)) == 't';
4220 if (tginfo
[j
].tgisconstraint
)
4222 tginfo
[j
].tgconstrname
= strdup(PQgetvalue(res
, j
, i_tgconstrname
));
4223 tginfo
[j
].tgconstrrelid
= atooid(PQgetvalue(res
, j
, i_tgconstrrelid
));
4224 if (OidIsValid(tginfo
[j
].tgconstrrelid
))
4226 if (PQgetisnull(res
, j
, i_tgconstrrelname
))
4228 write_msg(NULL
, "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)\n",
4229 tginfo
[j
].dobj
.name
, tbinfo
->dobj
.name
,
4230 tginfo
[j
].tgconstrrelid
);
4233 tginfo
[j
].tgconstrrelname
= strdup(PQgetvalue(res
, j
, i_tgconstrrelname
));
4236 tginfo
[j
].tgconstrrelname
= NULL
;
4240 tginfo
[j
].tgconstrname
= NULL
;
4241 tginfo
[j
].tgconstrrelid
= InvalidOid
;
4242 tginfo
[j
].tgconstrrelname
= NULL
;
4249 destroyPQExpBuffer(query
);
4254 * get basic information about every procedural language in the system
4256 * numProcLangs is set to the number of langs read in
4258 * NB: this must run after getFuncs() because we assume we can do
4262 getProcLangs(int *numProcLangs
)
4267 PQExpBuffer query
= createPQExpBuffer();
4268 ProcLangInfo
*planginfo
;
4273 int i_lanplcallfoid
;
4278 /* Make sure we are in proper schema */
4279 selectSourceSchema("pg_catalog");
4281 if (g_fout
->remoteVersion
>= 80300)
4283 /* pg_language has a lanowner column */
4284 appendPQExpBuffer(query
, "SELECT tableoid, oid, "
4285 "lanname, lanpltrusted, lanplcallfoid, "
4286 "lanvalidator, lanacl, "
4287 "(%s lanowner) as lanowner "
4293 else if (g_fout
->remoteVersion
>= 80100)
4295 /* Languages are owned by the bootstrap superuser, OID 10 */
4296 appendPQExpBuffer(query
, "SELECT tableoid, oid, *, "
4297 "(%s '10') as lanowner "
4303 else if (g_fout
->remoteVersion
>= 70400)
4305 /* Languages are owned by the bootstrap superuser, sysid 1 */
4306 appendPQExpBuffer(query
, "SELECT tableoid, oid, *, "
4307 "(%s '1') as lanowner "
4313 else if (g_fout
->remoteVersion
>= 70100)
4315 /* No clear notion of an owner at all before 7.4 ... */
4316 appendPQExpBuffer(query
, "SELECT tableoid, oid, * FROM pg_language "
4322 appendPQExpBuffer(query
, "SELECT "
4323 "(SELECT oid FROM pg_class WHERE relname = 'pg_language') AS tableoid, "
4324 "oid, * FROM pg_language "
4329 res
= PQexec(g_conn
, query
->data
);
4330 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
4332 ntups
= PQntuples(res
);
4334 *numProcLangs
= ntups
;
4336 planginfo
= (ProcLangInfo
*) malloc(ntups
* sizeof(ProcLangInfo
));
4338 i_tableoid
= PQfnumber(res
, "tableoid");
4339 i_oid
= PQfnumber(res
, "oid");
4340 i_lanname
= PQfnumber(res
, "lanname");
4341 i_lanpltrusted
= PQfnumber(res
, "lanpltrusted");
4342 i_lanplcallfoid
= PQfnumber(res
, "lanplcallfoid");
4343 /* these may fail and return -1: */
4344 i_lanvalidator
= PQfnumber(res
, "lanvalidator");
4345 i_lanacl
= PQfnumber(res
, "lanacl");
4346 i_lanowner
= PQfnumber(res
, "lanowner");
4348 for (i
= 0; i
< ntups
; i
++)
4350 planginfo
[i
].dobj
.objType
= DO_PROCLANG
;
4351 planginfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
4352 planginfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
4353 AssignDumpId(&planginfo
[i
].dobj
);
4355 planginfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_lanname
));
4356 planginfo
[i
].lanpltrusted
= *(PQgetvalue(res
, i
, i_lanpltrusted
)) == 't';
4357 planginfo
[i
].lanplcallfoid
= atooid(PQgetvalue(res
, i
, i_lanplcallfoid
));
4358 if (i_lanvalidator
>= 0)
4359 planginfo
[i
].lanvalidator
= atooid(PQgetvalue(res
, i
, i_lanvalidator
));
4361 planginfo
[i
].lanvalidator
= InvalidOid
;
4363 planginfo
[i
].lanacl
= strdup(PQgetvalue(res
, i
, i_lanacl
));
4365 planginfo
[i
].lanacl
= strdup("{=U}");
4366 if (i_lanowner
>= 0)
4367 planginfo
[i
].lanowner
= strdup(PQgetvalue(res
, i
, i_lanowner
));
4369 planginfo
[i
].lanowner
= strdup("");
4371 if (g_fout
->remoteVersion
< 70300)
4374 * We need to make a dependency to ensure the function will be
4375 * dumped first. (In 7.3 and later the regular dependency
4376 * mechanism will handle this for us.)
4378 FuncInfo
*funcInfo
= findFuncByOid(planginfo
[i
].lanplcallfoid
);
4381 addObjectDependency(&planginfo
[i
].dobj
,
4382 funcInfo
->dobj
.dumpId
);
4388 destroyPQExpBuffer(query
);
4395 * get basic information about every cast in the system
4397 * numCasts is set to the number of casts read in
4400 getCasts(int *numCasts
)
4405 PQExpBuffer query
= createPQExpBuffer();
4414 /* Make sure we are in proper schema */
4415 selectSourceSchema("pg_catalog");
4417 if (g_fout
->remoteVersion
>= 70300)
4419 appendPQExpBuffer(query
, "SELECT tableoid, oid, "
4420 "castsource, casttarget, castfunc, castcontext "
4421 "FROM pg_cast ORDER BY 3,4");
4425 appendPQExpBuffer(query
, "SELECT 0 as tableoid, p.oid, "
4426 "t1.oid as castsource, t2.oid as casttarget, "
4427 "p.oid as castfunc, 'e' as castcontext "
4428 "FROM pg_type t1, pg_type t2, pg_proc p "
4429 "WHERE p.pronargs = 1 AND "
4430 "p.proargtypes[0] = t1.oid AND "
4431 "p.prorettype = t2.oid AND p.proname = t2.typname "
4435 res
= PQexec(g_conn
, query
->data
);
4436 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
4438 ntups
= PQntuples(res
);
4442 castinfo
= (CastInfo
*) malloc(ntups
* sizeof(CastInfo
));
4444 i_tableoid
= PQfnumber(res
, "tableoid");
4445 i_oid
= PQfnumber(res
, "oid");
4446 i_castsource
= PQfnumber(res
, "castsource");
4447 i_casttarget
= PQfnumber(res
, "casttarget");
4448 i_castfunc
= PQfnumber(res
, "castfunc");
4449 i_castcontext
= PQfnumber(res
, "castcontext");
4451 for (i
= 0; i
< ntups
; i
++)
4453 PQExpBufferData namebuf
;
4454 TypeInfo
*sTypeInfo
;
4455 TypeInfo
*tTypeInfo
;
4457 castinfo
[i
].dobj
.objType
= DO_CAST
;
4458 castinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
4459 castinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
4460 AssignDumpId(&castinfo
[i
].dobj
);
4461 castinfo
[i
].castsource
= atooid(PQgetvalue(res
, i
, i_castsource
));
4462 castinfo
[i
].casttarget
= atooid(PQgetvalue(res
, i
, i_casttarget
));
4463 castinfo
[i
].castfunc
= atooid(PQgetvalue(res
, i
, i_castfunc
));
4464 castinfo
[i
].castcontext
= *(PQgetvalue(res
, i
, i_castcontext
));
4467 * Try to name cast as concatenation of typnames. This is only used
4468 * for purposes of sorting. If we fail to find either type, the name
4469 * will be an empty string.
4471 initPQExpBuffer(&namebuf
);
4472 sTypeInfo
= findTypeByOid(castinfo
[i
].castsource
);
4473 tTypeInfo
= findTypeByOid(castinfo
[i
].casttarget
);
4474 if (sTypeInfo
&& tTypeInfo
)
4475 appendPQExpBuffer(&namebuf
, "%s %s",
4476 sTypeInfo
->dobj
.name
, tTypeInfo
->dobj
.name
);
4477 castinfo
[i
].dobj
.name
= namebuf
.data
;
4479 if (OidIsValid(castinfo
[i
].castfunc
))
4482 * We need to make a dependency to ensure the function will be
4483 * dumped first. (In 7.3 and later the regular dependency
4484 * mechanism will handle this for us.)
4488 funcInfo
= findFuncByOid(castinfo
[i
].castfunc
);
4490 addObjectDependency(&castinfo
[i
].dobj
,
4491 funcInfo
->dobj
.dumpId
);
4497 destroyPQExpBuffer(query
);
4504 * for each interesting table, read info about its attributes
4505 * (names, types, default values, CHECK constraints, etc)
4507 * This is implemented in a very inefficient way right now, looping
4508 * through the tblinfo and doing a join per table to find the attrs and their
4509 * types. However, because we want type names and so forth to be named
4510 * relative to the schema of each table, we couldn't do it in just one
4511 * query. (Maybe one query per schema?)
4516 getTableAttrs(TableInfo
*tblinfo
, int numTables
)
4520 PQExpBuffer q
= createPQExpBuffer();
4525 int i_attstattarget
;
4536 for (i
= 0; i
< numTables
; i
++)
4538 TableInfo
*tbinfo
= &tblinfo
[i
];
4540 /* Don't bother to collect info for sequences */
4541 if (tbinfo
->relkind
== RELKIND_SEQUENCE
)
4544 /* Don't bother with uninteresting tables, either */
4545 if (!tbinfo
->interesting
)
4549 * Make sure we are in proper schema for this table; this allows
4550 * correct retrieval of formatted type names and default exprs
4552 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
4554 /* find all the user attributes and their types */
4557 * we must read the attribute names in attribute number order! because
4558 * we will use the attnum to index into the attnames array later. We
4559 * actually ask to order by "attrelid, attnum" because (at least up to
4560 * 7.3) the planner is not smart enough to realize it needn't re-sort
4561 * the output of an indexscan on pg_attribute_relid_attnum_index.
4564 write_msg(NULL
, "finding the columns and types of table \"%s\"\n",
4567 resetPQExpBuffer(q
);
4569 if (g_fout
->remoteVersion
>= 70300)
4571 /* need left join here to not fail on dropped columns ... */
4572 appendPQExpBuffer(q
, "SELECT a.attnum, a.attname, a.atttypmod, a.attstattarget, a.attstorage, t.typstorage, "
4573 "a.attnotnull, a.atthasdef, a.attisdropped, a.attislocal, "
4574 "pg_catalog.format_type(t.oid,a.atttypmod) as atttypname "
4575 "from pg_catalog.pg_attribute a left join pg_catalog.pg_type t "
4576 "on a.atttypid = t.oid "
4577 "where a.attrelid = '%u'::pg_catalog.oid "
4578 "and a.attnum > 0::pg_catalog.int2 "
4579 "order by a.attrelid, a.attnum",
4580 tbinfo
->dobj
.catId
.oid
);
4582 else if (g_fout
->remoteVersion
>= 70100)
4585 * attstattarget doesn't exist in 7.1. It does exist in 7.2, but
4586 * we don't dump it because we can't tell whether it's been
4587 * explicitly set or was just a default.
4589 appendPQExpBuffer(q
, "SELECT a.attnum, a.attname, a.atttypmod, -1 as attstattarget, a.attstorage, t.typstorage, "
4590 "a.attnotnull, a.atthasdef, false as attisdropped, false as attislocal, "
4591 "format_type(t.oid,a.atttypmod) as atttypname "
4592 "from pg_attribute a left join pg_type t "
4593 "on a.atttypid = t.oid "
4594 "where a.attrelid = '%u'::oid "
4595 "and a.attnum > 0::int2 "
4596 "order by a.attrelid, a.attnum",
4597 tbinfo
->dobj
.catId
.oid
);
4601 /* format_type not available before 7.1 */
4602 appendPQExpBuffer(q
, "SELECT attnum, attname, atttypmod, -1 as attstattarget, attstorage, attstorage as typstorage, "
4603 "attnotnull, atthasdef, false as attisdropped, false as attislocal, "
4604 "(select typname from pg_type where oid = atttypid) as atttypname "
4605 "from pg_attribute a "
4606 "where attrelid = '%u'::oid "
4607 "and attnum > 0::int2 "
4608 "order by attrelid, attnum",
4609 tbinfo
->dobj
.catId
.oid
);
4612 res
= PQexec(g_conn
, q
->data
);
4613 check_sql_result(res
, g_conn
, q
->data
, PGRES_TUPLES_OK
);
4615 ntups
= PQntuples(res
);
4617 i_attnum
= PQfnumber(res
, "attnum");
4618 i_attname
= PQfnumber(res
, "attname");
4619 i_atttypname
= PQfnumber(res
, "atttypname");
4620 i_atttypmod
= PQfnumber(res
, "atttypmod");
4621 i_attstattarget
= PQfnumber(res
, "attstattarget");
4622 i_attstorage
= PQfnumber(res
, "attstorage");
4623 i_typstorage
= PQfnumber(res
, "typstorage");
4624 i_attnotnull
= PQfnumber(res
, "attnotnull");
4625 i_atthasdef
= PQfnumber(res
, "atthasdef");
4626 i_attisdropped
= PQfnumber(res
, "attisdropped");
4627 i_attislocal
= PQfnumber(res
, "attislocal");
4629 tbinfo
->numatts
= ntups
;
4630 tbinfo
->attnames
= (char **) malloc(ntups
* sizeof(char *));
4631 tbinfo
->atttypnames
= (char **) malloc(ntups
* sizeof(char *));
4632 tbinfo
->atttypmod
= (int *) malloc(ntups
* sizeof(int));
4633 tbinfo
->attstattarget
= (int *) malloc(ntups
* sizeof(int));
4634 tbinfo
->attstorage
= (char *) malloc(ntups
* sizeof(char));
4635 tbinfo
->typstorage
= (char *) malloc(ntups
* sizeof(char));
4636 tbinfo
->attisdropped
= (bool *) malloc(ntups
* sizeof(bool));
4637 tbinfo
->attislocal
= (bool *) malloc(ntups
* sizeof(bool));
4638 tbinfo
->notnull
= (bool *) malloc(ntups
* sizeof(bool));
4639 tbinfo
->attrdefs
= (AttrDefInfo
**) malloc(ntups
* sizeof(AttrDefInfo
*));
4640 tbinfo
->inhAttrs
= (bool *) malloc(ntups
* sizeof(bool));
4641 tbinfo
->inhAttrDef
= (bool *) malloc(ntups
* sizeof(bool));
4642 tbinfo
->inhNotNull
= (bool *) malloc(ntups
* sizeof(bool));
4643 hasdefaults
= false;
4645 for (j
= 0; j
< ntups
; j
++)
4647 if (j
+ 1 != atoi(PQgetvalue(res
, j
, i_attnum
)))
4649 write_msg(NULL
, "invalid column numbering in table \"%s\"\n",
4653 tbinfo
->attnames
[j
] = strdup(PQgetvalue(res
, j
, i_attname
));
4654 tbinfo
->atttypnames
[j
] = strdup(PQgetvalue(res
, j
, i_atttypname
));
4655 tbinfo
->atttypmod
[j
] = atoi(PQgetvalue(res
, j
, i_atttypmod
));
4656 tbinfo
->attstattarget
[j
] = atoi(PQgetvalue(res
, j
, i_attstattarget
));
4657 tbinfo
->attstorage
[j
] = *(PQgetvalue(res
, j
, i_attstorage
));
4658 tbinfo
->typstorage
[j
] = *(PQgetvalue(res
, j
, i_typstorage
));
4659 tbinfo
->attisdropped
[j
] = (PQgetvalue(res
, j
, i_attisdropped
)[0] == 't');
4660 tbinfo
->attislocal
[j
] = (PQgetvalue(res
, j
, i_attislocal
)[0] == 't');
4661 tbinfo
->notnull
[j
] = (PQgetvalue(res
, j
, i_attnotnull
)[0] == 't');
4662 tbinfo
->attrdefs
[j
] = NULL
; /* fix below */
4663 if (PQgetvalue(res
, j
, i_atthasdef
)[0] == 't')
4665 /* these flags will be set in flagInhAttrs() */
4666 tbinfo
->inhAttrs
[j
] = false;
4667 tbinfo
->inhAttrDef
[j
] = false;
4668 tbinfo
->inhNotNull
[j
] = false;
4674 * Get info about column defaults
4678 AttrDefInfo
*attrdefs
;
4682 write_msg(NULL
, "finding default expressions of table \"%s\"\n",
4685 resetPQExpBuffer(q
);
4686 if (g_fout
->remoteVersion
>= 70300)
4688 appendPQExpBuffer(q
, "SELECT tableoid, oid, adnum, "
4689 "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
4690 "FROM pg_catalog.pg_attrdef "
4691 "WHERE adrelid = '%u'::pg_catalog.oid",
4692 tbinfo
->dobj
.catId
.oid
);
4694 else if (g_fout
->remoteVersion
>= 70200)
4696 /* 7.2 did not have OIDs in pg_attrdef */
4697 appendPQExpBuffer(q
, "SELECT tableoid, 0 as oid, adnum, "
4698 "pg_get_expr(adbin, adrelid) AS adsrc "
4700 "WHERE adrelid = '%u'::oid",
4701 tbinfo
->dobj
.catId
.oid
);
4703 else if (g_fout
->remoteVersion
>= 70100)
4705 /* no pg_get_expr, so must rely on adsrc */
4706 appendPQExpBuffer(q
, "SELECT tableoid, oid, adnum, adsrc "
4708 "WHERE adrelid = '%u'::oid",
4709 tbinfo
->dobj
.catId
.oid
);
4713 /* no pg_get_expr, no tableoid either */
4714 appendPQExpBuffer(q
, "SELECT "
4715 "(SELECT oid FROM pg_class WHERE relname = 'pg_attrdef') AS tableoid, "
4716 "oid, adnum, adsrc "
4718 "WHERE adrelid = '%u'::oid",
4719 tbinfo
->dobj
.catId
.oid
);
4721 res
= PQexec(g_conn
, q
->data
);
4722 check_sql_result(res
, g_conn
, q
->data
, PGRES_TUPLES_OK
);
4724 numDefaults
= PQntuples(res
);
4725 attrdefs
= (AttrDefInfo
*) malloc(numDefaults
* sizeof(AttrDefInfo
));
4727 for (j
= 0; j
< numDefaults
; j
++)
4731 attrdefs
[j
].dobj
.objType
= DO_ATTRDEF
;
4732 attrdefs
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, 0));
4733 attrdefs
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, 1));
4734 AssignDumpId(&attrdefs
[j
].dobj
);
4735 attrdefs
[j
].adtable
= tbinfo
;
4736 attrdefs
[j
].adnum
= adnum
= atoi(PQgetvalue(res
, j
, 2));
4737 attrdefs
[j
].adef_expr
= strdup(PQgetvalue(res
, j
, 3));
4739 attrdefs
[j
].dobj
.name
= strdup(tbinfo
->dobj
.name
);
4740 attrdefs
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
4742 attrdefs
[j
].dobj
.dump
= tbinfo
->dobj
.dump
;
4745 * Defaults on a VIEW must always be dumped as separate ALTER
4746 * TABLE commands. Defaults on regular tables are dumped as
4747 * part of the CREATE TABLE if possible. To check if it's
4748 * safe, we mark the default as needing to appear before the
4751 if (tbinfo
->relkind
== RELKIND_VIEW
)
4753 attrdefs
[j
].separate
= true;
4754 /* needed in case pre-7.3 DB: */
4755 addObjectDependency(&attrdefs
[j
].dobj
,
4756 tbinfo
->dobj
.dumpId
);
4760 attrdefs
[j
].separate
= false;
4761 addObjectDependency(&tbinfo
->dobj
,
4762 attrdefs
[j
].dobj
.dumpId
);
4765 if (adnum
<= 0 || adnum
> ntups
)
4767 write_msg(NULL
, "invalid adnum value %d for table \"%s\"\n",
4768 adnum
, tbinfo
->dobj
.name
);
4771 tbinfo
->attrdefs
[adnum
- 1] = &attrdefs
[j
];
4777 * Get info about table CHECK constraints
4779 if (tbinfo
->ncheck
> 0)
4781 ConstraintInfo
*constrs
;
4785 write_msg(NULL
, "finding check constraints for table \"%s\"\n",
4788 resetPQExpBuffer(q
);
4789 if (g_fout
->remoteVersion
>= 80400)
4791 appendPQExpBuffer(q
, "SELECT tableoid, oid, conname, "
4792 "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
4794 "FROM pg_catalog.pg_constraint "
4795 "WHERE conrelid = '%u'::pg_catalog.oid "
4796 " AND contype = 'c' "
4798 tbinfo
->dobj
.catId
.oid
);
4800 else if (g_fout
->remoteVersion
>= 70400)
4802 appendPQExpBuffer(q
, "SELECT tableoid, oid, conname, "
4803 "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
4804 "true as conislocal "
4805 "FROM pg_catalog.pg_constraint "
4806 "WHERE conrelid = '%u'::pg_catalog.oid "
4807 " AND contype = 'c' "
4809 tbinfo
->dobj
.catId
.oid
);
4811 else if (g_fout
->remoteVersion
>= 70300)
4813 /* no pg_get_constraintdef, must use consrc */
4814 appendPQExpBuffer(q
, "SELECT tableoid, oid, conname, "
4815 "'CHECK (' || consrc || ')' AS consrc, "
4816 "true as conislocal "
4817 "FROM pg_catalog.pg_constraint "
4818 "WHERE conrelid = '%u'::pg_catalog.oid "
4819 " AND contype = 'c' "
4821 tbinfo
->dobj
.catId
.oid
);
4823 else if (g_fout
->remoteVersion
>= 70200)
4825 /* 7.2 did not have OIDs in pg_relcheck */
4826 appendPQExpBuffer(q
, "SELECT tableoid, 0 as oid, "
4827 "rcname AS conname, "
4828 "'CHECK (' || rcsrc || ')' AS consrc, "
4829 "true as conislocal "
4831 "WHERE rcrelid = '%u'::oid "
4833 tbinfo
->dobj
.catId
.oid
);
4835 else if (g_fout
->remoteVersion
>= 70100)
4837 appendPQExpBuffer(q
, "SELECT tableoid, oid, "
4838 "rcname AS conname, "
4839 "'CHECK (' || rcsrc || ')' AS consrc, "
4840 "true as conislocal "
4842 "WHERE rcrelid = '%u'::oid "
4844 tbinfo
->dobj
.catId
.oid
);
4848 /* no tableoid in 7.0 */
4849 appendPQExpBuffer(q
, "SELECT "
4850 "(SELECT oid FROM pg_class WHERE relname = 'pg_relcheck') AS tableoid, "
4851 "oid, rcname AS conname, "
4852 "'CHECK (' || rcsrc || ')' AS consrc, "
4853 "true as conislocal "
4855 "WHERE rcrelid = '%u'::oid "
4857 tbinfo
->dobj
.catId
.oid
);
4859 res
= PQexec(g_conn
, q
->data
);
4860 check_sql_result(res
, g_conn
, q
->data
, PGRES_TUPLES_OK
);
4862 numConstrs
= PQntuples(res
);
4863 if (numConstrs
!= tbinfo
->ncheck
)
4865 write_msg(NULL
, "expected %d check constraints on table \"%s\" but found %d\n",
4866 tbinfo
->ncheck
, tbinfo
->dobj
.name
, numConstrs
);
4867 write_msg(NULL
, "(The system catalogs might be corrupted.)\n");
4871 constrs
= (ConstraintInfo
*) malloc(numConstrs
* sizeof(ConstraintInfo
));
4872 tbinfo
->checkexprs
= constrs
;
4874 for (j
= 0; j
< numConstrs
; j
++)
4876 constrs
[j
].dobj
.objType
= DO_CONSTRAINT
;
4877 constrs
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, 0));
4878 constrs
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, 1));
4879 AssignDumpId(&constrs
[j
].dobj
);
4880 constrs
[j
].dobj
.name
= strdup(PQgetvalue(res
, j
, 2));
4881 constrs
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
4882 constrs
[j
].contable
= tbinfo
;
4883 constrs
[j
].condomain
= NULL
;
4884 constrs
[j
].contype
= 'c';
4885 constrs
[j
].condef
= strdup(PQgetvalue(res
, j
, 3));
4886 constrs
[j
].confrelid
= InvalidOid
;
4887 constrs
[j
].conindex
= 0;
4888 constrs
[j
].conislocal
= (PQgetvalue(res
, j
, 4)[0] == 't');
4889 constrs
[j
].separate
= false;
4891 constrs
[j
].dobj
.dump
= tbinfo
->dobj
.dump
;
4894 * Mark the constraint as needing to appear before the table
4895 * --- this is so that any other dependencies of the
4896 * constraint will be emitted before we try to create the
4899 addObjectDependency(&tbinfo
->dobj
,
4900 constrs
[j
].dobj
.dumpId
);
4903 * If the constraint is inherited, this will be detected
4904 * later (in pre-8.4 databases). We also detect later if the
4905 * constraint must be split out from the table definition.
4912 destroyPQExpBuffer(q
);
4918 * read all text search parsers in the system catalogs and return them
4919 * in the TSParserInfo* structure
4921 * numTSParsers is set to the number of parsers read in
4924 getTSParsers(int *numTSParsers
)
4929 PQExpBuffer query
= createPQExpBuffer();
4930 TSParserInfo
*prsinfo
;
4941 /* Before 8.3, there is no built-in text search support */
4942 if (g_fout
->remoteVersion
< 80300)
4949 * find all text search objects, including builtin ones; we filter out
4950 * system-defined objects at dump-out time.
4953 /* Make sure we are in proper schema */
4954 selectSourceSchema("pg_catalog");
4956 appendPQExpBuffer(query
, "SELECT tableoid, oid, prsname, prsnamespace, "
4957 "prsstart::oid, prstoken::oid, "
4958 "prsend::oid, prsheadline::oid, prslextype::oid "
4959 "FROM pg_ts_parser");
4961 res
= PQexec(g_conn
, query
->data
);
4962 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
4964 ntups
= PQntuples(res
);
4965 *numTSParsers
= ntups
;
4967 prsinfo
= (TSParserInfo
*) malloc(ntups
* sizeof(TSParserInfo
));
4969 i_tableoid
= PQfnumber(res
, "tableoid");
4970 i_oid
= PQfnumber(res
, "oid");
4971 i_prsname
= PQfnumber(res
, "prsname");
4972 i_prsnamespace
= PQfnumber(res
, "prsnamespace");
4973 i_prsstart
= PQfnumber(res
, "prsstart");
4974 i_prstoken
= PQfnumber(res
, "prstoken");
4975 i_prsend
= PQfnumber(res
, "prsend");
4976 i_prsheadline
= PQfnumber(res
, "prsheadline");
4977 i_prslextype
= PQfnumber(res
, "prslextype");
4979 for (i
= 0; i
< ntups
; i
++)
4981 prsinfo
[i
].dobj
.objType
= DO_TSPARSER
;
4982 prsinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
4983 prsinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
4984 AssignDumpId(&prsinfo
[i
].dobj
);
4985 prsinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_prsname
));
4986 prsinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_prsnamespace
)),
4987 prsinfo
[i
].dobj
.catId
.oid
);
4988 prsinfo
[i
].prsstart
= atooid(PQgetvalue(res
, i
, i_prsstart
));
4989 prsinfo
[i
].prstoken
= atooid(PQgetvalue(res
, i
, i_prstoken
));
4990 prsinfo
[i
].prsend
= atooid(PQgetvalue(res
, i
, i_prsend
));
4991 prsinfo
[i
].prsheadline
= atooid(PQgetvalue(res
, i
, i_prsheadline
));
4992 prsinfo
[i
].prslextype
= atooid(PQgetvalue(res
, i
, i_prslextype
));
4994 /* Decide whether we want to dump it */
4995 selectDumpableObject(&(prsinfo
[i
].dobj
));
5000 destroyPQExpBuffer(query
);
5006 * getTSDictionaries:
5007 * read all text search dictionaries in the system catalogs and return them
5008 * in the TSDictInfo* structure
5010 * numTSDicts is set to the number of dictionaries read in
5013 getTSDictionaries(int *numTSDicts
)
5018 PQExpBuffer query
= createPQExpBuffer();
5019 TSDictInfo
*dictinfo
;
5023 int i_dictnamespace
;
5026 int i_dictinitoption
;
5028 /* Before 8.3, there is no built-in text search support */
5029 if (g_fout
->remoteVersion
< 80300)
5035 /* Make sure we are in proper schema */
5036 selectSourceSchema("pg_catalog");
5038 appendPQExpBuffer(query
, "SELECT tableoid, oid, dictname, "
5039 "dictnamespace, (%s dictowner) as rolname, "
5040 "dicttemplate, dictinitoption "
5044 res
= PQexec(g_conn
, query
->data
);
5045 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5047 ntups
= PQntuples(res
);
5048 *numTSDicts
= ntups
;
5050 dictinfo
= (TSDictInfo
*) malloc(ntups
* sizeof(TSDictInfo
));
5052 i_tableoid
= PQfnumber(res
, "tableoid");
5053 i_oid
= PQfnumber(res
, "oid");
5054 i_dictname
= PQfnumber(res
, "dictname");
5055 i_dictnamespace
= PQfnumber(res
, "dictnamespace");
5056 i_rolname
= PQfnumber(res
, "rolname");
5057 i_dictinitoption
= PQfnumber(res
, "dictinitoption");
5058 i_dicttemplate
= PQfnumber(res
, "dicttemplate");
5060 for (i
= 0; i
< ntups
; i
++)
5062 dictinfo
[i
].dobj
.objType
= DO_TSDICT
;
5063 dictinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
5064 dictinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
5065 AssignDumpId(&dictinfo
[i
].dobj
);
5066 dictinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_dictname
));
5067 dictinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_dictnamespace
)),
5068 dictinfo
[i
].dobj
.catId
.oid
);
5069 dictinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
5070 dictinfo
[i
].dicttemplate
= atooid(PQgetvalue(res
, i
, i_dicttemplate
));
5071 if (PQgetisnull(res
, i
, i_dictinitoption
))
5072 dictinfo
[i
].dictinitoption
= NULL
;
5074 dictinfo
[i
].dictinitoption
= strdup(PQgetvalue(res
, i
, i_dictinitoption
));
5076 /* Decide whether we want to dump it */
5077 selectDumpableObject(&(dictinfo
[i
].dobj
));
5082 destroyPQExpBuffer(query
);
5089 * read all text search templates in the system catalogs and return them
5090 * in the TSTemplateInfo* structure
5092 * numTSTemplates is set to the number of templates read in
5095 getTSTemplates(int *numTSTemplates
)
5100 PQExpBuffer query
= createPQExpBuffer();
5101 TSTemplateInfo
*tmplinfo
;
5105 int i_tmplnamespace
;
5109 /* Before 8.3, there is no built-in text search support */
5110 if (g_fout
->remoteVersion
< 80300)
5112 *numTSTemplates
= 0;
5116 /* Make sure we are in proper schema */
5117 selectSourceSchema("pg_catalog");
5119 appendPQExpBuffer(query
, "SELECT tableoid, oid, tmplname, "
5120 "tmplnamespace, tmplinit::oid, tmpllexize::oid "
5121 "FROM pg_ts_template");
5123 res
= PQexec(g_conn
, query
->data
);
5124 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5126 ntups
= PQntuples(res
);
5127 *numTSTemplates
= ntups
;
5129 tmplinfo
= (TSTemplateInfo
*) malloc(ntups
* sizeof(TSTemplateInfo
));
5131 i_tableoid
= PQfnumber(res
, "tableoid");
5132 i_oid
= PQfnumber(res
, "oid");
5133 i_tmplname
= PQfnumber(res
, "tmplname");
5134 i_tmplnamespace
= PQfnumber(res
, "tmplnamespace");
5135 i_tmplinit
= PQfnumber(res
, "tmplinit");
5136 i_tmpllexize
= PQfnumber(res
, "tmpllexize");
5138 for (i
= 0; i
< ntups
; i
++)
5140 tmplinfo
[i
].dobj
.objType
= DO_TSTEMPLATE
;
5141 tmplinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
5142 tmplinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
5143 AssignDumpId(&tmplinfo
[i
].dobj
);
5144 tmplinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_tmplname
));
5145 tmplinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_tmplnamespace
)),
5146 tmplinfo
[i
].dobj
.catId
.oid
);
5147 tmplinfo
[i
].tmplinit
= atooid(PQgetvalue(res
, i
, i_tmplinit
));
5148 tmplinfo
[i
].tmpllexize
= atooid(PQgetvalue(res
, i
, i_tmpllexize
));
5150 /* Decide whether we want to dump it */
5151 selectDumpableObject(&(tmplinfo
[i
].dobj
));
5156 destroyPQExpBuffer(query
);
5162 * getTSConfigurations:
5163 * read all text search configurations in the system catalogs and return
5164 * them in the TSConfigInfo* structure
5166 * numTSConfigs is set to the number of configurations read in
5169 getTSConfigurations(int *numTSConfigs
)
5174 PQExpBuffer query
= createPQExpBuffer();
5175 TSConfigInfo
*cfginfo
;
5183 /* Before 8.3, there is no built-in text search support */
5184 if (g_fout
->remoteVersion
< 80300)
5190 /* Make sure we are in proper schema */
5191 selectSourceSchema("pg_catalog");
5193 appendPQExpBuffer(query
, "SELECT tableoid, oid, cfgname, "
5194 "cfgnamespace, (%s cfgowner) as rolname, cfgparser "
5195 "FROM pg_ts_config",
5198 res
= PQexec(g_conn
, query
->data
);
5199 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5201 ntups
= PQntuples(res
);
5202 *numTSConfigs
= ntups
;
5204 cfginfo
= (TSConfigInfo
*) malloc(ntups
* sizeof(TSConfigInfo
));
5206 i_tableoid
= PQfnumber(res
, "tableoid");
5207 i_oid
= PQfnumber(res
, "oid");
5208 i_cfgname
= PQfnumber(res
, "cfgname");
5209 i_cfgnamespace
= PQfnumber(res
, "cfgnamespace");
5210 i_rolname
= PQfnumber(res
, "rolname");
5211 i_cfgparser
= PQfnumber(res
, "cfgparser");
5213 for (i
= 0; i
< ntups
; i
++)
5215 cfginfo
[i
].dobj
.objType
= DO_TSCONFIG
;
5216 cfginfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
5217 cfginfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
5218 AssignDumpId(&cfginfo
[i
].dobj
);
5219 cfginfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_cfgname
));
5220 cfginfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_cfgnamespace
)),
5221 cfginfo
[i
].dobj
.catId
.oid
);
5222 cfginfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
5223 cfginfo
[i
].cfgparser
= atooid(PQgetvalue(res
, i
, i_cfgparser
));
5225 /* Decide whether we want to dump it */
5226 selectDumpableObject(&(cfginfo
[i
].dobj
));
5231 destroyPQExpBuffer(query
);
5240 * This routine is used to dump any comments associated with the
5241 * object handed to this routine. The routine takes a constant character
5242 * string for the target part of the comment-creation command, plus
5243 * the namespace and owner of the object (for labeling the ArchiveEntry),
5244 * plus catalog ID and subid which are the lookup key for pg_description,
5245 * plus the dump ID for the object (for setting a dependency).
5246 * If a matching pg_description entry is found, it is dumped.
5248 * Note: although this routine takes a dumpId for dependency purposes,
5249 * that purpose is just to mark the dependency in the emitted dump file
5250 * for possible future use by pg_restore. We do NOT use it for determining
5251 * ordering of the comment in the dump file, because this routine is called
5252 * after dependency sorting occurs. This routine should be called just after
5253 * calling ArchiveEntry() for the specified object.
5256 dumpComment(Archive
*fout
, const char *target
,
5257 const char *namespace, const char *owner
,
5258 CatalogId catalogId
, int subid
, DumpId dumpId
)
5260 CommentItem
*comments
;
5263 /* Comments are SCHEMA not data */
5267 /* Search for comments associated with catalogId, using table */
5268 ncomments
= findComments(fout
, catalogId
.tableoid
, catalogId
.oid
,
5271 /* Is there one matching the subid? */
5272 while (ncomments
> 0)
5274 if (comments
->objsubid
== subid
)
5280 /* If a comment exists, build COMMENT ON statement */
5283 PQExpBuffer query
= createPQExpBuffer();
5285 appendPQExpBuffer(query
, "COMMENT ON %s IS ", target
);
5286 appendStringLiteralAH(query
, comments
->descr
, fout
);
5287 appendPQExpBuffer(query
, ";\n");
5289 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
5290 target
, namespace, NULL
, owner
, false,
5291 "COMMENT", query
->data
, "", NULL
,
5295 destroyPQExpBuffer(query
);
5300 * dumpTableComment --
5302 * As above, but dump comments for both the specified table (or view)
5306 dumpTableComment(Archive
*fout
, TableInfo
*tbinfo
,
5307 const char *reltypename
)
5309 CommentItem
*comments
;
5314 /* Comments are SCHEMA not data */
5318 /* Search for comments associated with relation, using table */
5319 ncomments
= findComments(fout
,
5320 tbinfo
->dobj
.catId
.tableoid
,
5321 tbinfo
->dobj
.catId
.oid
,
5324 /* If comments exist, build COMMENT ON statements */
5328 query
= createPQExpBuffer();
5329 target
= createPQExpBuffer();
5331 while (ncomments
> 0)
5333 const char *descr
= comments
->descr
;
5334 int objsubid
= comments
->objsubid
;
5338 resetPQExpBuffer(target
);
5339 appendPQExpBuffer(target
, "%s %s", reltypename
,
5340 fmtId(tbinfo
->dobj
.name
));
5342 resetPQExpBuffer(query
);
5343 appendPQExpBuffer(query
, "COMMENT ON %s IS ", target
->data
);
5344 appendStringLiteralAH(query
, descr
, fout
);
5345 appendPQExpBuffer(query
, ";\n");
5347 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
5349 tbinfo
->dobj
.namespace->dobj
.name
,
5352 false, "COMMENT", query
->data
, "", NULL
,
5353 &(tbinfo
->dobj
.dumpId
), 1,
5356 else if (objsubid
> 0 && objsubid
<= tbinfo
->numatts
)
5358 resetPQExpBuffer(target
);
5359 appendPQExpBuffer(target
, "COLUMN %s.",
5360 fmtId(tbinfo
->dobj
.name
));
5361 appendPQExpBuffer(target
, "%s",
5362 fmtId(tbinfo
->attnames
[objsubid
- 1]));
5364 resetPQExpBuffer(query
);
5365 appendPQExpBuffer(query
, "COMMENT ON %s IS ", target
->data
);
5366 appendStringLiteralAH(query
, descr
, fout
);
5367 appendPQExpBuffer(query
, ";\n");
5369 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
5371 tbinfo
->dobj
.namespace->dobj
.name
,
5374 false, "COMMENT", query
->data
, "", NULL
,
5375 &(tbinfo
->dobj
.dumpId
), 1,
5383 destroyPQExpBuffer(query
);
5384 destroyPQExpBuffer(target
);
5390 * Find the comment(s), if any, associated with the given object. All the
5391 * objsubid values associated with the given classoid/objoid are found with
5395 findComments(Archive
*fout
, Oid classoid
, Oid objoid
,
5396 CommentItem
**items
)
5398 /* static storage for table of comments */
5399 static CommentItem
*comments
= NULL
;
5400 static int ncomments
= -1;
5402 CommentItem
*middle
= NULL
;
5407 /* Get comments if we didn't already */
5409 ncomments
= collectComments(fout
, &comments
);
5412 * Pre-7.2, pg_description does not contain classoid, so collectComments
5413 * just stores a zero. If there's a collision on object OID, well, you
5414 * get duplicate comments.
5416 if (fout
->remoteVersion
< 70200)
5420 * Do binary search to find some item matching the object.
5423 high
= &comments
[ncomments
- 1];
5426 middle
= low
+ (high
- low
) / 2;
5428 if (classoid
< middle
->classoid
)
5430 else if (classoid
> middle
->classoid
)
5432 else if (objoid
< middle
->objoid
)
5434 else if (objoid
> middle
->objoid
)
5437 break; /* found a match */
5440 if (low
> high
) /* no matches */
5447 * Now determine how many items match the object. The search loop
5448 * invariant still holds: only items between low and high inclusive could
5452 while (middle
> low
)
5454 if (classoid
!= middle
[-1].classoid
||
5455 objoid
!= middle
[-1].objoid
)
5464 while (middle
<= high
)
5466 if (classoid
!= middle
->classoid
||
5467 objoid
!= middle
->objoid
)
5477 * collectComments --
5479 * Construct a table of all comments available for database objects.
5480 * We used to do per-object queries for the comments, but it's much faster
5481 * to pull them all over at once, and on most databases the memory cost
5484 * The table is sorted by classoid/objid/objsubid for speed in lookup.
5487 collectComments(Archive
*fout
, CommentItem
**items
)
5497 CommentItem
*comments
;
5500 * Note we do NOT change source schema here; preserve the caller's
5504 query
= createPQExpBuffer();
5506 if (fout
->remoteVersion
>= 70300)
5508 appendPQExpBuffer(query
, "SELECT description, classoid, objoid, objsubid "
5509 "FROM pg_catalog.pg_description "
5510 "ORDER BY classoid, objoid, objsubid");
5512 else if (fout
->remoteVersion
>= 70200)
5514 appendPQExpBuffer(query
, "SELECT description, classoid, objoid, objsubid "
5515 "FROM pg_description "
5516 "ORDER BY classoid, objoid, objsubid");
5520 /* Note: this will fail to find attribute comments in pre-7.2... */
5521 appendPQExpBuffer(query
, "SELECT description, 0 as classoid, objoid, 0 as objsubid "
5522 "FROM pg_description "
5526 res
= PQexec(g_conn
, query
->data
);
5527 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5529 /* Construct lookup table containing OIDs in numeric form */
5531 i_description
= PQfnumber(res
, "description");
5532 i_classoid
= PQfnumber(res
, "classoid");
5533 i_objoid
= PQfnumber(res
, "objoid");
5534 i_objsubid
= PQfnumber(res
, "objsubid");
5536 ntups
= PQntuples(res
);
5538 comments
= (CommentItem
*) malloc(ntups
* sizeof(CommentItem
));
5540 for (i
= 0; i
< ntups
; i
++)
5542 comments
[i
].descr
= PQgetvalue(res
, i
, i_description
);
5543 comments
[i
].classoid
= atooid(PQgetvalue(res
, i
, i_classoid
));
5544 comments
[i
].objoid
= atooid(PQgetvalue(res
, i
, i_objoid
));
5545 comments
[i
].objsubid
= atoi(PQgetvalue(res
, i
, i_objsubid
));
5548 /* Do NOT free the PGresult since we are keeping pointers into it */
5549 destroyPQExpBuffer(query
);
5556 * dumpDumpableObject
5558 * This routine and its subsidiaries are responsible for creating
5559 * ArchiveEntries (TOC objects) for each object to be dumped.
5562 dumpDumpableObject(Archive
*fout
, DumpableObject
*dobj
)
5564 switch (dobj
->objType
)
5567 dumpNamespace(fout
, (NamespaceInfo
*) dobj
);
5570 dumpType(fout
, (TypeInfo
*) dobj
);
5573 dumpShellType(fout
, (ShellTypeInfo
*) dobj
);
5576 dumpFunc(fout
, (FuncInfo
*) dobj
);
5579 dumpAgg(fout
, (AggInfo
*) dobj
);
5582 dumpOpr(fout
, (OprInfo
*) dobj
);
5585 dumpOpclass(fout
, (OpclassInfo
*) dobj
);
5588 dumpOpfamily(fout
, (OpfamilyInfo
*) dobj
);
5591 dumpConversion(fout
, (ConvInfo
*) dobj
);
5594 dumpTable(fout
, (TableInfo
*) dobj
);
5597 dumpAttrDef(fout
, (AttrDefInfo
*) dobj
);
5600 dumpIndex(fout
, (IndxInfo
*) dobj
);
5603 dumpRule(fout
, (RuleInfo
*) dobj
);
5606 dumpTrigger(fout
, (TriggerInfo
*) dobj
);
5609 dumpConstraint(fout
, (ConstraintInfo
*) dobj
);
5611 case DO_FK_CONSTRAINT
:
5612 dumpConstraint(fout
, (ConstraintInfo
*) dobj
);
5615 dumpProcLang(fout
, (ProcLangInfo
*) dobj
);
5618 dumpCast(fout
, (CastInfo
*) dobj
);
5621 dumpTableData(fout
, (TableDataInfo
*) dobj
);
5624 /* table rowtypes are never dumped separately */
5627 dumpTSParser(fout
, (TSParserInfo
*) dobj
);
5630 dumpTSDictionary(fout
, (TSDictInfo
*) dobj
);
5633 dumpTSTemplate(fout
, (TSTemplateInfo
*) dobj
);
5636 dumpTSConfig(fout
, (TSConfigInfo
*) dobj
);
5639 ArchiveEntry(fout
, dobj
->catId
, dobj
->dumpId
,
5640 dobj
->name
, NULL
, NULL
, "",
5641 false, "BLOBS", "", "", NULL
,
5645 case DO_BLOB_COMMENTS
:
5646 ArchiveEntry(fout
, dobj
->catId
, dobj
->dumpId
,
5647 dobj
->name
, NULL
, NULL
, "",
5648 false, "BLOB COMMENTS", "", "", NULL
,
5650 dumpBlobComments
, NULL
);
5657 * writes out to fout the queries to recreate a user-defined namespace
5660 dumpNamespace(Archive
*fout
, NamespaceInfo
*nspinfo
)
5666 /* Skip if not to be dumped */
5667 if (!nspinfo
->dobj
.dump
|| dataOnly
)
5670 /* don't dump dummy namespace from pre-7.3 source */
5671 if (strlen(nspinfo
->dobj
.name
) == 0)
5674 q
= createPQExpBuffer();
5675 delq
= createPQExpBuffer();
5677 qnspname
= strdup(fmtId(nspinfo
->dobj
.name
));
5679 appendPQExpBuffer(delq
, "DROP SCHEMA %s;\n", qnspname
);
5681 appendPQExpBuffer(q
, "CREATE SCHEMA %s;\n", qnspname
);
5683 ArchiveEntry(fout
, nspinfo
->dobj
.catId
, nspinfo
->dobj
.dumpId
,
5687 false, "SCHEMA", q
->data
, delq
->data
, NULL
,
5688 nspinfo
->dobj
.dependencies
, nspinfo
->dobj
.nDeps
,
5691 /* Dump Schema Comments */
5692 resetPQExpBuffer(q
);
5693 appendPQExpBuffer(q
, "SCHEMA %s", qnspname
);
5694 dumpComment(fout
, q
->data
,
5695 NULL
, nspinfo
->rolname
,
5696 nspinfo
->dobj
.catId
, 0, nspinfo
->dobj
.dumpId
);
5698 dumpACL(fout
, nspinfo
->dobj
.catId
, nspinfo
->dobj
.dumpId
, "SCHEMA",
5699 qnspname
, nspinfo
->dobj
.name
, NULL
,
5700 nspinfo
->rolname
, nspinfo
->nspacl
);
5704 destroyPQExpBuffer(q
);
5705 destroyPQExpBuffer(delq
);
5710 * writes out to fout the queries to recreate a user-defined type
5713 dumpType(Archive
*fout
, TypeInfo
*tinfo
)
5715 /* Skip if not to be dumped */
5716 if (!tinfo
->dobj
.dump
|| dataOnly
)
5719 /* Dump out in proper style */
5720 if (tinfo
->typtype
== TYPTYPE_BASE
)
5721 dumpBaseType(fout
, tinfo
);
5722 else if (tinfo
->typtype
== TYPTYPE_DOMAIN
)
5723 dumpDomain(fout
, tinfo
);
5724 else if (tinfo
->typtype
== TYPTYPE_COMPOSITE
)
5725 dumpCompositeType(fout
, tinfo
);
5726 else if (tinfo
->typtype
== TYPTYPE_ENUM
)
5727 dumpEnumType(fout
, tinfo
);
5732 * writes out to fout the queries to recreate a user-defined enum type
5735 dumpEnumType(Archive
*fout
, TypeInfo
*tinfo
)
5737 PQExpBuffer q
= createPQExpBuffer();
5738 PQExpBuffer delq
= createPQExpBuffer();
5739 PQExpBuffer query
= createPQExpBuffer();
5745 /* Set proper schema search path so regproc references list correctly */
5746 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
5748 appendPQExpBuffer(query
, "SELECT enumlabel FROM pg_catalog.pg_enum "
5749 "WHERE enumtypid = '%u'"
5751 tinfo
->dobj
.catId
.oid
);
5753 res
= PQexec(g_conn
, query
->data
);
5754 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5756 num
= PQntuples(res
);
5757 /* should be at least 1 value */
5760 write_msg(NULL
, "no label definitions found for enum ID %u\n", tinfo
->dobj
.catId
.oid
);
5765 * DROP must be fully qualified in case same name appears in pg_catalog.
5766 * CASCADE shouldn't be required here as for normal types since the I/O
5767 * functions are generic and do not get dropped.
5769 appendPQExpBuffer(delq
, "DROP TYPE %s.",
5770 fmtId(tinfo
->dobj
.namespace->dobj
.name
));
5771 appendPQExpBuffer(delq
, "%s;\n",
5772 fmtId(tinfo
->dobj
.name
));
5773 appendPQExpBuffer(q
, "CREATE TYPE %s AS ENUM (\n",
5774 fmtId(tinfo
->dobj
.name
));
5775 for (i
= 0; i
< num
; i
++)
5777 label
= PQgetvalue(res
, i
, 0);
5779 appendPQExpBuffer(q
, ",\n");
5780 appendPQExpBuffer(q
, " ");
5781 appendStringLiteralAH(q
, label
, fout
);
5783 appendPQExpBuffer(q
, "\n);\n");
5785 ArchiveEntry(fout
, tinfo
->dobj
.catId
, tinfo
->dobj
.dumpId
,
5787 tinfo
->dobj
.namespace->dobj
.name
,
5789 tinfo
->rolname
, false,
5790 "TYPE", q
->data
, delq
->data
, NULL
,
5791 tinfo
->dobj
.dependencies
, tinfo
->dobj
.nDeps
,
5794 /* Dump Type Comments */
5795 resetPQExpBuffer(q
);
5797 appendPQExpBuffer(q
, "TYPE %s", fmtId(tinfo
->dobj
.name
));
5798 dumpComment(fout
, q
->data
,
5799 tinfo
->dobj
.namespace->dobj
.name
, tinfo
->rolname
,
5800 tinfo
->dobj
.catId
, 0, tinfo
->dobj
.dumpId
);
5803 destroyPQExpBuffer(q
);
5804 destroyPQExpBuffer(delq
);
5805 destroyPQExpBuffer(query
);
5810 * writes out to fout the queries to recreate a user-defined base type
5813 dumpBaseType(Archive
*fout
, TypeInfo
*tinfo
)
5815 PQExpBuffer q
= createPQExpBuffer();
5816 PQExpBuffer delq
= createPQExpBuffer();
5817 PQExpBuffer query
= createPQExpBuffer();
5836 char *typispreferred
;
5842 bool typdefault_is_literal
= false;
5844 /* Set proper schema search path so regproc references list correctly */
5845 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
5847 /* Fetch type-specific details */
5848 if (fout
->remoteVersion
>= 80400)
5850 appendPQExpBuffer(query
, "SELECT typlen, "
5851 "typinput, typoutput, typreceive, typsend, "
5852 "typmodin, typmodout, typanalyze, "
5853 "typinput::pg_catalog.oid as typinputoid, "
5854 "typoutput::pg_catalog.oid as typoutputoid, "
5855 "typreceive::pg_catalog.oid as typreceiveoid, "
5856 "typsend::pg_catalog.oid as typsendoid, "
5857 "typmodin::pg_catalog.oid as typmodinoid, "
5858 "typmodout::pg_catalog.oid as typmodoutoid, "
5859 "typanalyze::pg_catalog.oid as typanalyzeoid, "
5860 "typcategory, typispreferred, "
5861 "typdelim, typbyval, typalign, typstorage, "
5862 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
5863 "FROM pg_catalog.pg_type "
5864 "WHERE oid = '%u'::pg_catalog.oid",
5865 tinfo
->dobj
.catId
.oid
);
5867 else if (fout
->remoteVersion
>= 80300)
5869 appendPQExpBuffer(query
, "SELECT typlen, "
5870 "typinput, typoutput, typreceive, typsend, "
5871 "typmodin, typmodout, typanalyze, "
5872 "typinput::pg_catalog.oid as typinputoid, "
5873 "typoutput::pg_catalog.oid as typoutputoid, "
5874 "typreceive::pg_catalog.oid as typreceiveoid, "
5875 "typsend::pg_catalog.oid as typsendoid, "
5876 "typmodin::pg_catalog.oid as typmodinoid, "
5877 "typmodout::pg_catalog.oid as typmodoutoid, "
5878 "typanalyze::pg_catalog.oid as typanalyzeoid, "
5879 "'U' as typcategory, false as typispreferred, "
5880 "typdelim, typbyval, typalign, typstorage, "
5881 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
5882 "FROM pg_catalog.pg_type "
5883 "WHERE oid = '%u'::pg_catalog.oid",
5884 tinfo
->dobj
.catId
.oid
);
5886 else if (fout
->remoteVersion
>= 80000)
5888 appendPQExpBuffer(query
, "SELECT typlen, "
5889 "typinput, typoutput, typreceive, typsend, "
5890 "'-' as typmodin, '-' as typmodout, "
5892 "typinput::pg_catalog.oid as typinputoid, "
5893 "typoutput::pg_catalog.oid as typoutputoid, "
5894 "typreceive::pg_catalog.oid as typreceiveoid, "
5895 "typsend::pg_catalog.oid as typsendoid, "
5896 "0 as typmodinoid, 0 as typmodoutoid, "
5897 "typanalyze::pg_catalog.oid as typanalyzeoid, "
5898 "'U' as typcategory, false as typispreferred, "
5899 "typdelim, typbyval, typalign, typstorage, "
5900 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
5901 "FROM pg_catalog.pg_type "
5902 "WHERE oid = '%u'::pg_catalog.oid",
5903 tinfo
->dobj
.catId
.oid
);
5905 else if (fout
->remoteVersion
>= 70400)
5907 appendPQExpBuffer(query
, "SELECT typlen, "
5908 "typinput, typoutput, typreceive, typsend, "
5909 "'-' as typmodin, '-' as typmodout, "
5910 "'-' as typanalyze, "
5911 "typinput::pg_catalog.oid as typinputoid, "
5912 "typoutput::pg_catalog.oid as typoutputoid, "
5913 "typreceive::pg_catalog.oid as typreceiveoid, "
5914 "typsend::pg_catalog.oid as typsendoid, "
5915 "0 as typmodinoid, 0 as typmodoutoid, "
5916 "0 as typanalyzeoid, "
5917 "'U' as typcategory, false as typispreferred, "
5918 "typdelim, typbyval, typalign, typstorage, "
5919 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
5920 "FROM pg_catalog.pg_type "
5921 "WHERE oid = '%u'::pg_catalog.oid",
5922 tinfo
->dobj
.catId
.oid
);
5924 else if (fout
->remoteVersion
>= 70300)
5926 appendPQExpBuffer(query
, "SELECT typlen, "
5927 "typinput, typoutput, "
5928 "'-' as typreceive, '-' as typsend, "
5929 "'-' as typmodin, '-' as typmodout, "
5930 "'-' as typanalyze, "
5931 "typinput::pg_catalog.oid as typinputoid, "
5932 "typoutput::pg_catalog.oid as typoutputoid, "
5933 "0 as typreceiveoid, 0 as typsendoid, "
5934 "0 as typmodinoid, 0 as typmodoutoid, "
5935 "0 as typanalyzeoid, "
5936 "'U' as typcategory, false as typispreferred, "
5937 "typdelim, typbyval, typalign, typstorage, "
5938 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
5939 "FROM pg_catalog.pg_type "
5940 "WHERE oid = '%u'::pg_catalog.oid",
5941 tinfo
->dobj
.catId
.oid
);
5943 else if (fout
->remoteVersion
>= 70200)
5946 * Note: although pre-7.3 catalogs contain typreceive and typsend,
5947 * ignore them because they are not right.
5949 appendPQExpBuffer(query
, "SELECT typlen, "
5950 "typinput, typoutput, "
5951 "'-' as typreceive, '-' as typsend, "
5952 "'-' as typmodin, '-' as typmodout, "
5953 "'-' as typanalyze, "
5954 "typinput::oid as typinputoid, "
5955 "typoutput::oid as typoutputoid, "
5956 "0 as typreceiveoid, 0 as typsendoid, "
5957 "0 as typmodinoid, 0 as typmodoutoid, "
5958 "0 as typanalyzeoid, "
5959 "'U' as typcategory, false as typispreferred, "
5960 "typdelim, typbyval, typalign, typstorage, "
5961 "NULL as typdefaultbin, typdefault "
5963 "WHERE oid = '%u'::oid",
5964 tinfo
->dobj
.catId
.oid
);
5966 else if (fout
->remoteVersion
>= 70100)
5969 * Ignore pre-7.2 typdefault; the field exists but has an unusable
5972 appendPQExpBuffer(query
, "SELECT typlen, "
5973 "typinput, typoutput, "
5974 "'-' as typreceive, '-' as typsend, "
5975 "'-' as typmodin, '-' as typmodout, "
5976 "'-' as typanalyze, "
5977 "typinput::oid as typinputoid, "
5978 "typoutput::oid as typoutputoid, "
5979 "0 as typreceiveoid, 0 as typsendoid, "
5980 "0 as typmodinoid, 0 as typmodoutoid, "
5981 "0 as typanalyzeoid, "
5982 "'U' as typcategory, false as typispreferred, "
5983 "typdelim, typbyval, typalign, typstorage, "
5984 "NULL as typdefaultbin, NULL as typdefault "
5986 "WHERE oid = '%u'::oid",
5987 tinfo
->dobj
.catId
.oid
);
5991 appendPQExpBuffer(query
, "SELECT typlen, "
5992 "typinput, typoutput, "
5993 "'-' as typreceive, '-' as typsend, "
5994 "'-' as typmodin, '-' as typmodout, "
5995 "'-' as typanalyze, "
5996 "typinput::oid as typinputoid, "
5997 "typoutput::oid as typoutputoid, "
5998 "0 as typreceiveoid, 0 as typsendoid, "
5999 "0 as typmodinoid, 0 as typmodoutoid, "
6000 "0 as typanalyzeoid, "
6001 "'U' as typcategory, false as typispreferred, "
6002 "typdelim, typbyval, typalign, "
6003 "'p'::char as typstorage, "
6004 "NULL as typdefaultbin, NULL as typdefault "
6006 "WHERE oid = '%u'::oid",
6007 tinfo
->dobj
.catId
.oid
);
6010 res
= PQexec(g_conn
, query
->data
);
6011 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
6013 /* Expecting a single result only */
6014 ntups
= PQntuples(res
);
6017 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
6018 ntups
, query
->data
);
6022 typlen
= PQgetvalue(res
, 0, PQfnumber(res
, "typlen"));
6023 typinput
= PQgetvalue(res
, 0, PQfnumber(res
, "typinput"));
6024 typoutput
= PQgetvalue(res
, 0, PQfnumber(res
, "typoutput"));
6025 typreceive
= PQgetvalue(res
, 0, PQfnumber(res
, "typreceive"));
6026 typsend
= PQgetvalue(res
, 0, PQfnumber(res
, "typsend"));
6027 typmodin
= PQgetvalue(res
, 0, PQfnumber(res
, "typmodin"));
6028 typmodout
= PQgetvalue(res
, 0, PQfnumber(res
, "typmodout"));
6029 typanalyze
= PQgetvalue(res
, 0, PQfnumber(res
, "typanalyze"));
6030 typinputoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typinputoid")));
6031 typoutputoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typoutputoid")));
6032 typreceiveoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typreceiveoid")));
6033 typsendoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typsendoid")));
6034 typmodinoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typmodinoid")));
6035 typmodoutoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typmodoutoid")));
6036 typanalyzeoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typanalyzeoid")));
6037 typcategory
= PQgetvalue(res
, 0, PQfnumber(res
, "typcategory"));
6038 typispreferred
= PQgetvalue(res
, 0, PQfnumber(res
, "typispreferred"));
6039 typdelim
= PQgetvalue(res
, 0, PQfnumber(res
, "typdelim"));
6040 typbyval
= PQgetvalue(res
, 0, PQfnumber(res
, "typbyval"));
6041 typalign
= PQgetvalue(res
, 0, PQfnumber(res
, "typalign"));
6042 typstorage
= PQgetvalue(res
, 0, PQfnumber(res
, "typstorage"));
6043 if (!PQgetisnull(res
, 0, PQfnumber(res
, "typdefaultbin")))
6044 typdefault
= PQgetvalue(res
, 0, PQfnumber(res
, "typdefaultbin"));
6045 else if (!PQgetisnull(res
, 0, PQfnumber(res
, "typdefault")))
6047 typdefault
= PQgetvalue(res
, 0, PQfnumber(res
, "typdefault"));
6048 typdefault_is_literal
= true; /* it needs quotes */
6054 * DROP must be fully qualified in case same name appears in pg_catalog.
6055 * The reason we include CASCADE is that the circular dependency between
6056 * the type and its I/O functions makes it impossible to drop the type any
6059 appendPQExpBuffer(delq
, "DROP TYPE %s.",
6060 fmtId(tinfo
->dobj
.namespace->dobj
.name
));
6061 appendPQExpBuffer(delq
, "%s CASCADE;\n",
6062 fmtId(tinfo
->dobj
.name
));
6064 appendPQExpBuffer(q
,
6065 "CREATE TYPE %s (\n"
6066 " INTERNALLENGTH = %s",
6067 fmtId(tinfo
->dobj
.name
),
6068 (strcmp(typlen
, "-1") == 0) ? "variable" : typlen
);
6070 if (fout
->remoteVersion
>= 70300)
6072 /* regproc result is correctly quoted as of 7.3 */
6073 appendPQExpBuffer(q
, ",\n INPUT = %s", typinput
);
6074 appendPQExpBuffer(q
, ",\n OUTPUT = %s", typoutput
);
6075 if (OidIsValid(typreceiveoid
))
6076 appendPQExpBuffer(q
, ",\n RECEIVE = %s", typreceive
);
6077 if (OidIsValid(typsendoid
))
6078 appendPQExpBuffer(q
, ",\n SEND = %s", typsend
);
6079 if (OidIsValid(typmodinoid
))
6080 appendPQExpBuffer(q
, ",\n TYPMOD_IN = %s", typmodin
);
6081 if (OidIsValid(typmodoutoid
))
6082 appendPQExpBuffer(q
, ",\n TYPMOD_OUT = %s", typmodout
);
6083 if (OidIsValid(typanalyzeoid
))
6084 appendPQExpBuffer(q
, ",\n ANALYZE = %s", typanalyze
);
6088 /* regproc delivers an unquoted name before 7.3 */
6089 /* cannot combine these because fmtId uses static result area */
6090 appendPQExpBuffer(q
, ",\n INPUT = %s", fmtId(typinput
));
6091 appendPQExpBuffer(q
, ",\n OUTPUT = %s", fmtId(typoutput
));
6092 /* receive/send/typmodin/typmodout/analyze need not be printed */
6095 if (typdefault
!= NULL
)
6097 appendPQExpBuffer(q
, ",\n DEFAULT = ");
6098 if (typdefault_is_literal
)
6099 appendStringLiteralAH(q
, typdefault
, fout
);
6101 appendPQExpBufferStr(q
, typdefault
);
6104 if (OidIsValid(tinfo
->typelem
))
6108 /* reselect schema in case changed by function dump */
6109 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
6110 elemType
= getFormattedTypeName(tinfo
->typelem
, zeroAsOpaque
);
6111 appendPQExpBuffer(q
, ",\n ELEMENT = %s", elemType
);
6115 if (strcmp(typcategory
, "U") != 0)
6117 appendPQExpBuffer(q
, ",\n CATEGORY = ");
6118 appendStringLiteralAH(q
, typcategory
, fout
);
6121 if (strcmp(typispreferred
, "t") == 0)
6122 appendPQExpBuffer(q
, ",\n PREFERRED = true");
6124 if (typdelim
&& strcmp(typdelim
, ",") != 0)
6126 appendPQExpBuffer(q
, ",\n DELIMITER = ");
6127 appendStringLiteralAH(q
, typdelim
, fout
);
6130 if (strcmp(typalign
, "c") == 0)
6131 appendPQExpBuffer(q
, ",\n ALIGNMENT = char");
6132 else if (strcmp(typalign
, "s") == 0)
6133 appendPQExpBuffer(q
, ",\n ALIGNMENT = int2");
6134 else if (strcmp(typalign
, "i") == 0)
6135 appendPQExpBuffer(q
, ",\n ALIGNMENT = int4");
6136 else if (strcmp(typalign
, "d") == 0)
6137 appendPQExpBuffer(q
, ",\n ALIGNMENT = double");
6139 if (strcmp(typstorage
, "p") == 0)
6140 appendPQExpBuffer(q
, ",\n STORAGE = plain");
6141 else if (strcmp(typstorage
, "e") == 0)
6142 appendPQExpBuffer(q
, ",\n STORAGE = external");
6143 else if (strcmp(typstorage
, "x") == 0)
6144 appendPQExpBuffer(q
, ",\n STORAGE = extended");
6145 else if (strcmp(typstorage
, "m") == 0)
6146 appendPQExpBuffer(q
, ",\n STORAGE = main");
6148 if (strcmp(typbyval
, "t") == 0)
6149 appendPQExpBuffer(q
, ",\n PASSEDBYVALUE");
6151 appendPQExpBuffer(q
, "\n);\n");
6153 ArchiveEntry(fout
, tinfo
->dobj
.catId
, tinfo
->dobj
.dumpId
,
6155 tinfo
->dobj
.namespace->dobj
.name
,
6157 tinfo
->rolname
, false,
6158 "TYPE", q
->data
, delq
->data
, NULL
,
6159 tinfo
->dobj
.dependencies
, tinfo
->dobj
.nDeps
,
6162 /* Dump Type Comments */
6163 resetPQExpBuffer(q
);
6165 appendPQExpBuffer(q
, "TYPE %s", fmtId(tinfo
->dobj
.name
));
6166 dumpComment(fout
, q
->data
,
6167 tinfo
->dobj
.namespace->dobj
.name
, tinfo
->rolname
,
6168 tinfo
->dobj
.catId
, 0, tinfo
->dobj
.dumpId
);
6171 destroyPQExpBuffer(q
);
6172 destroyPQExpBuffer(delq
);
6173 destroyPQExpBuffer(query
);
6178 * writes out to fout the queries to recreate a user-defined domain
6181 dumpDomain(Archive
*fout
, TypeInfo
*tinfo
)
6183 PQExpBuffer q
= createPQExpBuffer();
6184 PQExpBuffer delq
= createPQExpBuffer();
6185 PQExpBuffer query
= createPQExpBuffer();
6192 bool typdefault_is_literal
= false;
6194 /* Set proper schema search path so type references list correctly */
6195 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
6197 /* Fetch domain specific details */
6198 /* We assume here that remoteVersion must be at least 70300 */
6199 appendPQExpBuffer(query
, "SELECT typnotnull, "
6200 "pg_catalog.format_type(typbasetype, typtypmod) as typdefn, "
6201 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
6202 "FROM pg_catalog.pg_type "
6203 "WHERE oid = '%u'::pg_catalog.oid",
6204 tinfo
->dobj
.catId
.oid
);
6206 res
= PQexec(g_conn
, query
->data
);
6207 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
6209 /* Expecting a single result only */
6210 ntups
= PQntuples(res
);
6213 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
6214 ntups
, query
->data
);
6218 typnotnull
= PQgetvalue(res
, 0, PQfnumber(res
, "typnotnull"));
6219 typdefn
= PQgetvalue(res
, 0, PQfnumber(res
, "typdefn"));
6220 if (!PQgetisnull(res
, 0, PQfnumber(res
, "typdefaultbin")))
6221 typdefault
= PQgetvalue(res
, 0, PQfnumber(res
, "typdefaultbin"));
6222 else if (!PQgetisnull(res
, 0, PQfnumber(res
, "typdefault")))
6224 typdefault
= PQgetvalue(res
, 0, PQfnumber(res
, "typdefault"));
6225 typdefault_is_literal
= true; /* it needs quotes */
6230 appendPQExpBuffer(q
,
6231 "CREATE DOMAIN %s AS %s",
6232 fmtId(tinfo
->dobj
.name
),
6235 if (typnotnull
[0] == 't')
6236 appendPQExpBuffer(q
, " NOT NULL");
6238 if (typdefault
!= NULL
)
6240 appendPQExpBuffer(q
, " DEFAULT ");
6241 if (typdefault_is_literal
)
6242 appendStringLiteralAH(q
, typdefault
, fout
);
6244 appendPQExpBufferStr(q
, typdefault
);
6250 * Add any CHECK constraints for the domain
6252 for (i
= 0; i
< tinfo
->nDomChecks
; i
++)
6254 ConstraintInfo
*domcheck
= &(tinfo
->domChecks
[i
]);
6256 if (!domcheck
->separate
)
6257 appendPQExpBuffer(q
, "\n\tCONSTRAINT %s %s",
6258 fmtId(domcheck
->dobj
.name
), domcheck
->condef
);
6261 appendPQExpBuffer(q
, ";\n");
6264 * DROP must be fully qualified in case same name appears in pg_catalog
6266 appendPQExpBuffer(delq
, "DROP DOMAIN %s.",
6267 fmtId(tinfo
->dobj
.namespace->dobj
.name
));
6268 appendPQExpBuffer(delq
, "%s;\n",
6269 fmtId(tinfo
->dobj
.name
));
6271 ArchiveEntry(fout
, tinfo
->dobj
.catId
, tinfo
->dobj
.dumpId
,
6273 tinfo
->dobj
.namespace->dobj
.name
,
6275 tinfo
->rolname
, false,
6276 "DOMAIN", q
->data
, delq
->data
, NULL
,
6277 tinfo
->dobj
.dependencies
, tinfo
->dobj
.nDeps
,
6280 /* Dump Domain Comments */
6281 resetPQExpBuffer(q
);
6283 appendPQExpBuffer(q
, "DOMAIN %s", fmtId(tinfo
->dobj
.name
));
6284 dumpComment(fout
, q
->data
,
6285 tinfo
->dobj
.namespace->dobj
.name
, tinfo
->rolname
,
6286 tinfo
->dobj
.catId
, 0, tinfo
->dobj
.dumpId
);
6288 destroyPQExpBuffer(q
);
6289 destroyPQExpBuffer(delq
);
6290 destroyPQExpBuffer(query
);
6295 * writes out to fout the queries to recreate a user-defined stand-alone
6299 dumpCompositeType(Archive
*fout
, TypeInfo
*tinfo
)
6301 PQExpBuffer q
= createPQExpBuffer();
6302 PQExpBuffer delq
= createPQExpBuffer();
6303 PQExpBuffer query
= createPQExpBuffer();
6310 /* Set proper schema search path so type references list correctly */
6311 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
6313 /* Fetch type specific details */
6314 /* We assume here that remoteVersion must be at least 70300 */
6316 appendPQExpBuffer(query
, "SELECT a.attname, "
6317 "pg_catalog.format_type(a.atttypid, a.atttypmod) as atttypdefn "
6318 "FROM pg_catalog.pg_type t, pg_catalog.pg_attribute a "
6319 "WHERE t.oid = '%u'::pg_catalog.oid "
6320 "AND a.attrelid = t.typrelid "
6321 "AND NOT a.attisdropped "
6322 "ORDER BY a.attnum ",
6323 tinfo
->dobj
.catId
.oid
);
6325 res
= PQexec(g_conn
, query
->data
);
6326 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
6328 /* Expecting at least a single result */
6329 ntups
= PQntuples(res
);
6332 write_msg(NULL
, "query returned no rows: %s\n", query
->data
);
6336 i_attname
= PQfnumber(res
, "attname");
6337 i_atttypdefn
= PQfnumber(res
, "atttypdefn");
6339 appendPQExpBuffer(q
, "CREATE TYPE %s AS (",
6340 fmtId(tinfo
->dobj
.name
));
6342 for (i
= 0; i
< ntups
; i
++)
6347 attname
= PQgetvalue(res
, i
, i_attname
);
6348 atttypdefn
= PQgetvalue(res
, i
, i_atttypdefn
);
6350 appendPQExpBuffer(q
, "\n\t%s %s", fmtId(attname
), atttypdefn
);
6352 appendPQExpBuffer(q
, ",");
6354 appendPQExpBuffer(q
, "\n);\n");
6357 * DROP must be fully qualified in case same name appears in pg_catalog
6359 appendPQExpBuffer(delq
, "DROP TYPE %s.",
6360 fmtId(tinfo
->dobj
.namespace->dobj
.name
));
6361 appendPQExpBuffer(delq
, "%s;\n",
6362 fmtId(tinfo
->dobj
.name
));
6364 ArchiveEntry(fout
, tinfo
->dobj
.catId
, tinfo
->dobj
.dumpId
,
6366 tinfo
->dobj
.namespace->dobj
.name
,
6368 tinfo
->rolname
, false,
6369 "TYPE", q
->data
, delq
->data
, NULL
,
6370 tinfo
->dobj
.dependencies
, tinfo
->dobj
.nDeps
,
6374 /* Dump Type Comments */
6375 resetPQExpBuffer(q
);
6377 appendPQExpBuffer(q
, "TYPE %s", fmtId(tinfo
->dobj
.name
));
6378 dumpComment(fout
, q
->data
,
6379 tinfo
->dobj
.namespace->dobj
.name
, tinfo
->rolname
,
6380 tinfo
->dobj
.catId
, 0, tinfo
->dobj
.dumpId
);
6383 destroyPQExpBuffer(q
);
6384 destroyPQExpBuffer(delq
);
6385 destroyPQExpBuffer(query
);
6390 * writes out to fout the queries to create a shell type
6392 * We dump a shell definition in advance of the I/O functions for the type.
6395 dumpShellType(Archive
*fout
, ShellTypeInfo
*stinfo
)
6399 /* Skip if not to be dumped */
6400 if (!stinfo
->dobj
.dump
|| dataOnly
)
6403 q
= createPQExpBuffer();
6406 * Note the lack of a DROP command for the shell type; any required DROP
6407 * is driven off the base type entry, instead. This interacts with
6408 * _printTocEntry()'s use of the presence of a DROP command to decide
6409 * whether an entry needs an ALTER OWNER command. We don't want to alter
6410 * the shell type's owner immediately on creation; that should happen only
6411 * after it's filled in, otherwise the backend complains.
6414 appendPQExpBuffer(q
, "CREATE TYPE %s;\n",
6415 fmtId(stinfo
->dobj
.name
));
6417 ArchiveEntry(fout
, stinfo
->dobj
.catId
, stinfo
->dobj
.dumpId
,
6419 stinfo
->dobj
.namespace->dobj
.name
,
6421 stinfo
->baseType
->rolname
, false,
6422 "SHELL TYPE", q
->data
, "", NULL
,
6423 stinfo
->dobj
.dependencies
, stinfo
->dobj
.nDeps
,
6426 destroyPQExpBuffer(q
);
6430 * Determine whether we want to dump definitions for procedural languages.
6431 * Since the languages themselves don't have schemas, we can't rely on
6432 * the normal schema-based selection mechanism. We choose to dump them
6433 * whenever neither --schema nor --table was given. (Before 8.1, we used
6434 * the dump flag of the PL's call handler function, but in 8.1 this will
6435 * probably always be false since call handlers are created in pg_catalog.)
6437 * For some backwards compatibility with the older behavior, we forcibly
6438 * dump a PL if its handler function (and validator if any) are in a
6439 * dumpable namespace. That case is not checked here.
6442 shouldDumpProcLangs(void)
6444 if (!include_everything
)
6446 /* And they're schema not data */
6454 * writes out to fout the queries to recreate a user-defined
6455 * procedural language
6458 dumpProcLang(Archive
*fout
, ProcLangInfo
*plang
)
6466 FuncInfo
*validatorInfo
= NULL
;
6472 * Try to find the support function(s). It is not an error if we don't
6473 * find them --- if the functions are in the pg_catalog schema, as is
6474 * standard in 8.1 and up, then we won't have loaded them. (In this case
6475 * we will emit a parameterless CREATE LANGUAGE command, which will
6476 * require PL template knowledge in the backend to reload.)
6479 funcInfo
= findFuncByOid(plang
->lanplcallfoid
);
6480 if (funcInfo
!= NULL
&& !funcInfo
->dobj
.dump
)
6481 funcInfo
= NULL
; /* treat not-dumped same as not-found */
6483 if (OidIsValid(plang
->lanvalidator
))
6485 validatorInfo
= findFuncByOid(plang
->lanvalidator
);
6486 if (validatorInfo
!= NULL
&& !validatorInfo
->dobj
.dump
)
6487 validatorInfo
= NULL
;
6491 * If the functions are dumpable then emit a traditional CREATE LANGUAGE
6492 * with parameters. Otherwise, dump only if shouldDumpProcLangs() says to
6495 useParams
= (funcInfo
!= NULL
&&
6496 (validatorInfo
!= NULL
|| !OidIsValid(plang
->lanvalidator
)));
6498 if (!useParams
&& !shouldDumpProcLangs())
6501 defqry
= createPQExpBuffer();
6502 delqry
= createPQExpBuffer();
6504 qlanname
= strdup(fmtId(plang
->dobj
.name
));
6507 * If dumping a HANDLER clause, treat the language as being in the handler
6508 * function's schema; this avoids cluttering the HANDLER clause. Otherwise
6509 * it doesn't really have a schema.
6512 lanschema
= funcInfo
->dobj
.namespace->dobj
.name
;
6516 appendPQExpBuffer(delqry
, "DROP PROCEDURAL LANGUAGE %s;\n",
6519 appendPQExpBuffer(defqry
, "CREATE %sPROCEDURAL LANGUAGE %s",
6520 (useParams
&& plang
->lanpltrusted
) ? "TRUSTED " : "",
6524 appendPQExpBuffer(defqry
, " HANDLER %s",
6525 fmtId(funcInfo
->dobj
.name
));
6526 if (OidIsValid(plang
->lanvalidator
))
6528 appendPQExpBuffer(defqry
, " VALIDATOR ");
6529 /* Cope with possibility that validator is in different schema */
6530 if (validatorInfo
->dobj
.namespace != funcInfo
->dobj
.namespace)
6531 appendPQExpBuffer(defqry
, "%s.",
6532 fmtId(validatorInfo
->dobj
.namespace->dobj
.name
));
6533 appendPQExpBuffer(defqry
, "%s",
6534 fmtId(validatorInfo
->dobj
.name
));
6537 appendPQExpBuffer(defqry
, ";\n");
6539 ArchiveEntry(fout
, plang
->dobj
.catId
, plang
->dobj
.dumpId
,
6541 lanschema
, NULL
, plang
->lanowner
,
6542 false, "PROCEDURAL LANGUAGE",
6543 defqry
->data
, delqry
->data
, NULL
,
6544 plang
->dobj
.dependencies
, plang
->dobj
.nDeps
,
6547 /* Dump Proc Lang Comments */
6548 resetPQExpBuffer(defqry
);
6549 appendPQExpBuffer(defqry
, "LANGUAGE %s", qlanname
);
6550 dumpComment(fout
, defqry
->data
,
6552 plang
->dobj
.catId
, 0, plang
->dobj
.dumpId
);
6554 if (plang
->lanpltrusted
)
6555 dumpACL(fout
, plang
->dobj
.catId
, plang
->dobj
.dumpId
, "LANGUAGE",
6556 qlanname
, plang
->dobj
.name
,
6558 plang
->lanowner
, plang
->lanacl
);
6562 destroyPQExpBuffer(defqry
);
6563 destroyPQExpBuffer(delqry
);
6567 * format_function_arguments: generate function name and argument list
6569 * This is used when we can rely on pg_get_function_arguments to format
6570 * the argument list.
6572 static char *format_function_arguments(FuncInfo
*finfo
, char *funcargs
)
6576 initPQExpBuffer(&fn
);
6577 appendPQExpBuffer(&fn
, "%s(%s)", fmtId(finfo
->dobj
.name
), funcargs
);
6582 * format_function_arguments_old: generate function name and argument list
6584 * The argument type names are qualified if needed. The function name
6585 * is never qualified.
6587 * This is used only with pre-8.4 servers, so we aren't expecting to see
6588 * VARIADIC or TABLE arguments.
6590 * Any or all of allargtypes, argmodes, argnames may be NULL.
6593 format_function_arguments_old(FuncInfo
*finfo
, int nallargs
,
6601 initPQExpBuffer(&fn
);
6602 appendPQExpBuffer(&fn
, "%s(", fmtId(finfo
->dobj
.name
));
6603 for (j
= 0; j
< nallargs
; j
++)
6607 const char *argmode
;
6608 const char *argname
;
6610 typid
= allargtypes
? atooid(allargtypes
[j
]) : finfo
->argtypes
[j
];
6611 typname
= getFormattedTypeName(typid
, zeroAsOpaque
);
6615 switch (argmodes
[j
][0])
6620 case PROARGMODE_OUT
:
6623 case PROARGMODE_INOUT
:
6627 write_msg(NULL
, "WARNING: bogus value in proargmodes array\n");
6635 argname
= argnames
? argnames
[j
] : (char *) NULL
;
6636 if (argname
&& argname
[0] == '\0')
6639 appendPQExpBuffer(&fn
, "%s%s%s%s%s",
6640 (j
> 0) ? ", " : "",
6642 argname
? fmtId(argname
) : "",
6647 appendPQExpBuffer(&fn
, ")");
6652 * format_function_signature: generate function name and argument list
6654 * This is like format_function_arguments_old except that only a minimal
6655 * list of input argument types is generated; this is sufficient to
6656 * reference the function, but not to define it.
6658 * If honor_quotes is false then the function name is never quoted.
6659 * This is appropriate for use in TOC tags, but not in SQL commands.
6662 format_function_signature(FuncInfo
*finfo
, bool honor_quotes
)
6667 initPQExpBuffer(&fn
);
6669 appendPQExpBuffer(&fn
, "%s(", fmtId(finfo
->dobj
.name
));
6671 appendPQExpBuffer(&fn
, "%s(", finfo
->dobj
.name
);
6672 for (j
= 0; j
< finfo
->nargs
; j
++)
6676 typname
= getFormattedTypeName(finfo
->argtypes
[j
], zeroAsOpaque
);
6678 appendPQExpBuffer(&fn
, "%s%s",
6679 (j
> 0) ? ", " : "",
6683 appendPQExpBuffer(&fn
, ")");
6690 * dump out one function
6693 dumpFunc(Archive
*fout
, FuncInfo
*finfo
)
6708 char *proallargtypes
;
6720 char **allargtypes
= NULL
;
6721 char **argmodes
= NULL
;
6722 char **argnames
= NULL
;
6723 char **configitems
= NULL
;
6724 int nconfigitems
= 0;
6727 /* Skip if not to be dumped */
6728 if (!finfo
->dobj
.dump
|| dataOnly
)
6731 query
= createPQExpBuffer();
6732 q
= createPQExpBuffer();
6733 delqry
= createPQExpBuffer();
6734 asPart
= createPQExpBuffer();
6736 /* Set proper schema search path so type references list correctly */
6737 selectSourceSchema(finfo
->dobj
.namespace->dobj
.name
);
6739 /* Fetch function-specific details */
6740 if (g_fout
->remoteVersion
>= 80400)
6743 * In 8.4 and up we rely on pg_get_function_arguments and
6744 * pg_get_function_result instead of examining proallargtypes etc.
6746 appendPQExpBuffer(query
,
6747 "SELECT proretset, prosrc, probin, "
6748 "pg_catalog.pg_get_function_arguments(oid) as funcargs, "
6749 "pg_catalog.pg_get_function_result(oid) as funcresult, "
6750 "provolatile, proisstrict, prosecdef, "
6751 "proconfig, procost, prorows, "
6752 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
6753 "FROM pg_catalog.pg_proc "
6754 "WHERE oid = '%u'::pg_catalog.oid",
6755 finfo
->dobj
.catId
.oid
);
6757 else if (g_fout
->remoteVersion
>= 80300)
6759 appendPQExpBuffer(query
,
6760 "SELECT proretset, prosrc, probin, "
6761 "proallargtypes, proargmodes, proargnames, "
6762 "provolatile, proisstrict, prosecdef, "
6763 "proconfig, procost, prorows, "
6764 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
6765 "FROM pg_catalog.pg_proc "
6766 "WHERE oid = '%u'::pg_catalog.oid",
6767 finfo
->dobj
.catId
.oid
);
6769 else if (g_fout
->remoteVersion
>= 80100)
6771 appendPQExpBuffer(query
,
6772 "SELECT proretset, prosrc, probin, "
6773 "proallargtypes, proargmodes, proargnames, "
6774 "provolatile, proisstrict, prosecdef, "
6775 "null as proconfig, 0 as procost, 0 as prorows, "
6776 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
6777 "FROM pg_catalog.pg_proc "
6778 "WHERE oid = '%u'::pg_catalog.oid",
6779 finfo
->dobj
.catId
.oid
);
6781 else if (g_fout
->remoteVersion
>= 80000)
6783 appendPQExpBuffer(query
,
6784 "SELECT proretset, prosrc, probin, "
6785 "null as proallargtypes, "
6786 "null as proargmodes, "
6788 "provolatile, proisstrict, prosecdef, "
6789 "null as proconfig, 0 as procost, 0 as prorows, "
6790 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
6791 "FROM pg_catalog.pg_proc "
6792 "WHERE oid = '%u'::pg_catalog.oid",
6793 finfo
->dobj
.catId
.oid
);
6795 else if (g_fout
->remoteVersion
>= 70300)
6797 appendPQExpBuffer(query
,
6798 "SELECT proretset, prosrc, probin, "
6799 "null as proallargtypes, "
6800 "null as proargmodes, "
6801 "null as proargnames, "
6802 "provolatile, proisstrict, prosecdef, "
6803 "null as proconfig, 0 as procost, 0 as prorows, "
6804 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
6805 "FROM pg_catalog.pg_proc "
6806 "WHERE oid = '%u'::pg_catalog.oid",
6807 finfo
->dobj
.catId
.oid
);
6809 else if (g_fout
->remoteVersion
>= 70100)
6811 appendPQExpBuffer(query
,
6812 "SELECT proretset, prosrc, probin, "
6813 "null as proallargtypes, "
6814 "null as proargmodes, "
6815 "null as proargnames, "
6816 "case when proiscachable then 'i' else 'v' end as provolatile, "
6818 "'f'::boolean as prosecdef, "
6819 "null as proconfig, 0 as procost, 0 as prorows, "
6820 "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
6822 "WHERE oid = '%u'::oid",
6823 finfo
->dobj
.catId
.oid
);
6827 appendPQExpBuffer(query
,
6828 "SELECT proretset, prosrc, probin, "
6829 "null as proallargtypes, "
6830 "null as proargmodes, "
6831 "null as proargnames, "
6832 "case when proiscachable then 'i' else 'v' end as provolatile, "
6833 "'f'::boolean as proisstrict, "
6834 "'f'::boolean as prosecdef, "
6835 "null as proconfig, 0 as procost, 0 as prorows, "
6836 "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
6838 "WHERE oid = '%u'::oid",
6839 finfo
->dobj
.catId
.oid
);
6842 res
= PQexec(g_conn
, query
->data
);
6843 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
6845 /* Expecting a single result only */
6846 ntups
= PQntuples(res
);
6849 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
6850 ntups
, query
->data
);
6854 proretset
= PQgetvalue(res
, 0, PQfnumber(res
, "proretset"));
6855 prosrc
= PQgetvalue(res
, 0, PQfnumber(res
, "prosrc"));
6856 probin
= PQgetvalue(res
, 0, PQfnumber(res
, "probin"));
6857 if (g_fout
->remoteVersion
>= 80400)
6859 funcargs
= PQgetvalue(res
, 0, PQfnumber(res
, "funcargs"));
6860 funcresult
= PQgetvalue(res
, 0, PQfnumber(res
, "funcresult"));
6861 proallargtypes
= proargmodes
= proargnames
= NULL
;
6865 proallargtypes
= PQgetvalue(res
, 0, PQfnumber(res
, "proallargtypes"));
6866 proargmodes
= PQgetvalue(res
, 0, PQfnumber(res
, "proargmodes"));
6867 proargnames
= PQgetvalue(res
, 0, PQfnumber(res
, "proargnames"));
6868 funcargs
= funcresult
= NULL
;
6870 provolatile
= PQgetvalue(res
, 0, PQfnumber(res
, "provolatile"));
6871 proisstrict
= PQgetvalue(res
, 0, PQfnumber(res
, "proisstrict"));
6872 prosecdef
= PQgetvalue(res
, 0, PQfnumber(res
, "prosecdef"));
6873 proconfig
= PQgetvalue(res
, 0, PQfnumber(res
, "proconfig"));
6874 procost
= PQgetvalue(res
, 0, PQfnumber(res
, "procost"));
6875 prorows
= PQgetvalue(res
, 0, PQfnumber(res
, "prorows"));
6876 lanname
= PQgetvalue(res
, 0, PQfnumber(res
, "lanname"));
6879 * See backend/commands/functioncmds.c for details of how the 'AS' clause
6880 * is used. In 8.4 and up, an unused probin is NULL (here ""); previous
6881 * versions would set it to "-". There are no known cases in which prosrc
6882 * is unused, so the tests below for "-" are probably useless.
6884 if (probin
[0] != '\0' && strcmp(probin
, "-") != 0)
6886 appendPQExpBuffer(asPart
, "AS ");
6887 appendStringLiteralAH(asPart
, probin
, fout
);
6888 if (strcmp(prosrc
, "-") != 0)
6890 appendPQExpBuffer(asPart
, ", ");
6893 * where we have bin, use dollar quoting if allowed and src
6894 * contains quote or backslash; else use regular quoting.
6896 if (disable_dollar_quoting
||
6897 (strchr(prosrc
, '\'') == NULL
&& strchr(prosrc
, '\\') == NULL
))
6898 appendStringLiteralAH(asPart
, prosrc
, fout
);
6900 appendStringLiteralDQ(asPart
, prosrc
, NULL
);
6905 if (strcmp(prosrc
, "-") != 0)
6907 appendPQExpBuffer(asPart
, "AS ");
6908 /* with no bin, dollar quote src unconditionally if allowed */
6909 if (disable_dollar_quoting
)
6910 appendStringLiteralAH(asPart
, prosrc
, fout
);
6912 appendStringLiteralDQ(asPart
, prosrc
, NULL
);
6916 nallargs
= finfo
->nargs
; /* unless we learn different from allargs */
6918 if (proallargtypes
&& *proallargtypes
)
6922 if (!parsePGArray(proallargtypes
, &allargtypes
, &nitems
) ||
6923 nitems
< finfo
->nargs
)
6925 write_msg(NULL
, "WARNING: could not parse proallargtypes array\n");
6934 if (proargmodes
&& *proargmodes
)
6938 if (!parsePGArray(proargmodes
, &argmodes
, &nitems
) ||
6941 write_msg(NULL
, "WARNING: could not parse proargmodes array\n");
6948 if (proargnames
&& *proargnames
)
6952 if (!parsePGArray(proargnames
, &argnames
, &nitems
) ||
6955 write_msg(NULL
, "WARNING: could not parse proargnames array\n");
6962 if (proconfig
&& *proconfig
)
6964 if (!parsePGArray(proconfig
, &configitems
, &nconfigitems
))
6966 write_msg(NULL
, "WARNING: could not parse proconfig array\n");
6975 funcsig
= format_function_arguments(finfo
, funcargs
);
6977 funcsig
= format_function_arguments_old(finfo
, nallargs
, allargtypes
,
6978 argmodes
, argnames
);
6979 funcsig_tag
= format_function_signature(finfo
, false);
6982 * DROP must be fully qualified in case same name appears in pg_catalog
6984 appendPQExpBuffer(delqry
, "DROP FUNCTION %s.%s;\n",
6985 fmtId(finfo
->dobj
.namespace->dobj
.name
),
6988 appendPQExpBuffer(q
, "CREATE FUNCTION %s ", funcsig
);
6990 appendPQExpBuffer(q
, "RETURNS %s", funcresult
);
6993 rettypename
= getFormattedTypeName(finfo
->prorettype
, zeroAsOpaque
);
6994 appendPQExpBuffer(q
, "RETURNS %s%s",
6995 (proretset
[0] == 't') ? "SETOF " : "",
7000 appendPQExpBuffer(q
, "\n LANGUAGE %s", fmtId(lanname
));
7001 if (provolatile
[0] != PROVOLATILE_VOLATILE
)
7003 if (provolatile
[0] == PROVOLATILE_IMMUTABLE
)
7004 appendPQExpBuffer(q
, " IMMUTABLE");
7005 else if (provolatile
[0] == PROVOLATILE_STABLE
)
7006 appendPQExpBuffer(q
, " STABLE");
7007 else if (provolatile
[0] != PROVOLATILE_VOLATILE
)
7009 write_msg(NULL
, "unrecognized provolatile value for function \"%s\"\n",
7015 if (proisstrict
[0] == 't')
7016 appendPQExpBuffer(q
, " STRICT");
7018 if (prosecdef
[0] == 't')
7019 appendPQExpBuffer(q
, " SECURITY DEFINER");
7022 * COST and ROWS are emitted only if present and not default, so as not to
7023 * break backwards-compatibility of the dump without need. Keep this code
7024 * in sync with the defaults in functioncmds.c.
7026 if (strcmp(procost
, "0") != 0)
7028 if (strcmp(lanname
, "internal") == 0 || strcmp(lanname
, "c") == 0)
7030 /* default cost is 1 */
7031 if (strcmp(procost
, "1") != 0)
7032 appendPQExpBuffer(q
, " COST %s", procost
);
7036 /* default cost is 100 */
7037 if (strcmp(procost
, "100") != 0)
7038 appendPQExpBuffer(q
, " COST %s", procost
);
7041 if (proretset
[0] == 't' &&
7042 strcmp(prorows
, "0") != 0 && strcmp(prorows
, "1000") != 0)
7043 appendPQExpBuffer(q
, " ROWS %s", prorows
);
7045 for (i
= 0; i
< nconfigitems
; i
++)
7047 /* we feel free to scribble on configitems[] here */
7048 char *configitem
= configitems
[i
];
7051 pos
= strchr(configitem
, '=');
7055 appendPQExpBuffer(q
, "\n SET %s TO ", fmtId(configitem
));
7058 * Some GUC variable names are 'LIST' type and hence must not be
7061 if (pg_strcasecmp(configitem
, "DateStyle") == 0
7062 || pg_strcasecmp(configitem
, "search_path") == 0)
7063 appendPQExpBuffer(q
, "%s", pos
);
7065 appendStringLiteralAH(q
, pos
, fout
);
7068 appendPQExpBuffer(q
, "\n %s;\n", asPart
->data
);
7070 ArchiveEntry(fout
, finfo
->dobj
.catId
, finfo
->dobj
.dumpId
,
7072 finfo
->dobj
.namespace->dobj
.name
,
7074 finfo
->rolname
, false,
7075 "FUNCTION", q
->data
, delqry
->data
, NULL
,
7076 finfo
->dobj
.dependencies
, finfo
->dobj
.nDeps
,
7079 /* Dump Function Comments */
7080 resetPQExpBuffer(q
);
7081 appendPQExpBuffer(q
, "FUNCTION %s", funcsig
);
7082 dumpComment(fout
, q
->data
,
7083 finfo
->dobj
.namespace->dobj
.name
, finfo
->rolname
,
7084 finfo
->dobj
.catId
, 0, finfo
->dobj
.dumpId
);
7086 dumpACL(fout
, finfo
->dobj
.catId
, finfo
->dobj
.dumpId
, "FUNCTION",
7087 funcsig
, funcsig_tag
,
7088 finfo
->dobj
.namespace->dobj
.name
,
7089 finfo
->rolname
, finfo
->proacl
);
7093 destroyPQExpBuffer(query
);
7094 destroyPQExpBuffer(q
);
7095 destroyPQExpBuffer(delqry
);
7096 destroyPQExpBuffer(asPart
);
7111 * Dump a user-defined cast
7114 dumpCast(Archive
*fout
, CastInfo
*cast
)
7118 PQExpBuffer castsig
;
7119 FuncInfo
*funcInfo
= NULL
;
7120 TypeInfo
*sourceInfo
;
7121 TypeInfo
*targetInfo
;
7126 if (OidIsValid(cast
->castfunc
))
7128 funcInfo
= findFuncByOid(cast
->castfunc
);
7129 if (funcInfo
== NULL
)
7134 * As per discussion we dump casts if one or more of the underlying
7135 * objects (the conversion function and the two data types) are not
7136 * builtin AND if all of the non-builtin objects are included in the dump.
7137 * Builtin meaning, the namespace name does not start with "pg_".
7139 sourceInfo
= findTypeByOid(cast
->castsource
);
7140 targetInfo
= findTypeByOid(cast
->casttarget
);
7142 if (sourceInfo
== NULL
|| targetInfo
== NULL
)
7146 * Skip this cast if all objects are from pg_
7148 if ((funcInfo
== NULL
||
7149 strncmp(funcInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) == 0) &&
7150 strncmp(sourceInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) == 0 &&
7151 strncmp(targetInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) == 0)
7155 * Skip cast if function isn't from pg_ and is not to be dumped.
7158 strncmp(funcInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) != 0 &&
7159 !funcInfo
->dobj
.dump
)
7163 * Same for the source type
7165 if (strncmp(sourceInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) != 0 &&
7166 !sourceInfo
->dobj
.dump
)
7170 * and the target type.
7172 if (strncmp(targetInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) != 0 &&
7173 !targetInfo
->dobj
.dump
)
7176 /* Make sure we are in proper schema (needed for getFormattedTypeName) */
7177 selectSourceSchema("pg_catalog");
7179 defqry
= createPQExpBuffer();
7180 delqry
= createPQExpBuffer();
7181 castsig
= createPQExpBuffer();
7183 appendPQExpBuffer(delqry
, "DROP CAST (%s AS %s);\n",
7184 getFormattedTypeName(cast
->castsource
, zeroAsNone
),
7185 getFormattedTypeName(cast
->casttarget
, zeroAsNone
));
7187 appendPQExpBuffer(defqry
, "CREATE CAST (%s AS %s) ",
7188 getFormattedTypeName(cast
->castsource
, zeroAsNone
),
7189 getFormattedTypeName(cast
->casttarget
, zeroAsNone
));
7191 if (!OidIsValid(cast
->castfunc
))
7192 appendPQExpBuffer(defqry
, "WITHOUT FUNCTION");
7196 * Always qualify the function name, in case it is not in pg_catalog
7197 * schema (format_function_signature won't qualify it).
7199 appendPQExpBuffer(defqry
, "WITH FUNCTION %s.",
7200 fmtId(funcInfo
->dobj
.namespace->dobj
.name
));
7201 appendPQExpBuffer(defqry
, "%s",
7202 format_function_signature(funcInfo
, true));
7205 if (cast
->castcontext
== 'a')
7206 appendPQExpBuffer(defqry
, " AS ASSIGNMENT");
7207 else if (cast
->castcontext
== 'i')
7208 appendPQExpBuffer(defqry
, " AS IMPLICIT");
7209 appendPQExpBuffer(defqry
, ";\n");
7211 appendPQExpBuffer(castsig
, "CAST (%s AS %s)",
7212 getFormattedTypeName(cast
->castsource
, zeroAsNone
),
7213 getFormattedTypeName(cast
->casttarget
, zeroAsNone
));
7215 ArchiveEntry(fout
, cast
->dobj
.catId
, cast
->dobj
.dumpId
,
7217 "pg_catalog", NULL
, "",
7218 false, "CAST", defqry
->data
, delqry
->data
, NULL
,
7219 cast
->dobj
.dependencies
, cast
->dobj
.nDeps
,
7222 /* Dump Cast Comments */
7223 resetPQExpBuffer(defqry
);
7224 appendPQExpBuffer(defqry
, "CAST (%s AS %s)",
7225 getFormattedTypeName(cast
->castsource
, zeroAsNone
),
7226 getFormattedTypeName(cast
->casttarget
, zeroAsNone
));
7227 dumpComment(fout
, defqry
->data
,
7229 cast
->dobj
.catId
, 0, cast
->dobj
.dumpId
);
7231 destroyPQExpBuffer(defqry
);
7232 destroyPQExpBuffer(delqry
);
7233 destroyPQExpBuffer(castsig
);
7238 * write out a single operator definition
7241 dumpOpr(Archive
*fout
, OprInfo
*oprinfo
)
7247 PQExpBuffer details
;
7272 /* Skip if not to be dumped */
7273 if (!oprinfo
->dobj
.dump
|| dataOnly
)
7277 * some operators are invalid because they were the result of user
7278 * defining operators before commutators exist
7280 if (!OidIsValid(oprinfo
->oprcode
))
7283 query
= createPQExpBuffer();
7284 q
= createPQExpBuffer();
7285 delq
= createPQExpBuffer();
7286 oprid
= createPQExpBuffer();
7287 details
= createPQExpBuffer();
7289 /* Make sure we are in proper schema so regoperator works correctly */
7290 selectSourceSchema(oprinfo
->dobj
.namespace->dobj
.name
);
7292 if (g_fout
->remoteVersion
>= 80300)
7294 appendPQExpBuffer(query
, "SELECT oprkind, "
7295 "oprcode::pg_catalog.regprocedure, "
7296 "oprleft::pg_catalog.regtype, "
7297 "oprright::pg_catalog.regtype, "
7298 "oprcom::pg_catalog.regoperator, "
7299 "oprnegate::pg_catalog.regoperator, "
7300 "oprrest::pg_catalog.regprocedure, "
7301 "oprjoin::pg_catalog.regprocedure, "
7302 "oprcanmerge, oprcanhash "
7303 "from pg_catalog.pg_operator "
7304 "where oid = '%u'::pg_catalog.oid",
7305 oprinfo
->dobj
.catId
.oid
);
7307 else if (g_fout
->remoteVersion
>= 70300)
7309 appendPQExpBuffer(query
, "SELECT oprkind, "
7310 "oprcode::pg_catalog.regprocedure, "
7311 "oprleft::pg_catalog.regtype, "
7312 "oprright::pg_catalog.regtype, "
7313 "oprcom::pg_catalog.regoperator, "
7314 "oprnegate::pg_catalog.regoperator, "
7315 "oprrest::pg_catalog.regprocedure, "
7316 "oprjoin::pg_catalog.regprocedure, "
7317 "(oprlsortop != 0) as oprcanmerge, "
7319 "from pg_catalog.pg_operator "
7320 "where oid = '%u'::pg_catalog.oid",
7321 oprinfo
->dobj
.catId
.oid
);
7323 else if (g_fout
->remoteVersion
>= 70100)
7325 appendPQExpBuffer(query
, "SELECT oprkind, oprcode, "
7326 "CASE WHEN oprleft = 0 THEN '-' "
7327 "ELSE format_type(oprleft, NULL) END as oprleft, "
7328 "CASE WHEN oprright = 0 THEN '-' "
7329 "ELSE format_type(oprright, NULL) END as oprright, "
7330 "oprcom, oprnegate, oprrest, oprjoin, "
7331 "(oprlsortop != 0) as oprcanmerge, "
7334 "where oid = '%u'::oid",
7335 oprinfo
->dobj
.catId
.oid
);
7339 appendPQExpBuffer(query
, "SELECT oprkind, oprcode, "
7340 "CASE WHEN oprleft = 0 THEN '-'::name "
7341 "ELSE (select typname from pg_type where oid = oprleft) END as oprleft, "
7342 "CASE WHEN oprright = 0 THEN '-'::name "
7343 "ELSE (select typname from pg_type where oid = oprright) END as oprright, "
7344 "oprcom, oprnegate, oprrest, oprjoin, "
7345 "(oprlsortop != 0) as oprcanmerge, "
7348 "where oid = '%u'::oid",
7349 oprinfo
->dobj
.catId
.oid
);
7352 res
= PQexec(g_conn
, query
->data
);
7353 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
7355 /* Expecting a single result only */
7356 ntups
= PQntuples(res
);
7359 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
7360 ntups
, query
->data
);
7364 i_oprkind
= PQfnumber(res
, "oprkind");
7365 i_oprcode
= PQfnumber(res
, "oprcode");
7366 i_oprleft
= PQfnumber(res
, "oprleft");
7367 i_oprright
= PQfnumber(res
, "oprright");
7368 i_oprcom
= PQfnumber(res
, "oprcom");
7369 i_oprnegate
= PQfnumber(res
, "oprnegate");
7370 i_oprrest
= PQfnumber(res
, "oprrest");
7371 i_oprjoin
= PQfnumber(res
, "oprjoin");
7372 i_oprcanmerge
= PQfnumber(res
, "oprcanmerge");
7373 i_oprcanhash
= PQfnumber(res
, "oprcanhash");
7375 oprkind
= PQgetvalue(res
, 0, i_oprkind
);
7376 oprcode
= PQgetvalue(res
, 0, i_oprcode
);
7377 oprleft
= PQgetvalue(res
, 0, i_oprleft
);
7378 oprright
= PQgetvalue(res
, 0, i_oprright
);
7379 oprcom
= PQgetvalue(res
, 0, i_oprcom
);
7380 oprnegate
= PQgetvalue(res
, 0, i_oprnegate
);
7381 oprrest
= PQgetvalue(res
, 0, i_oprrest
);
7382 oprjoin
= PQgetvalue(res
, 0, i_oprjoin
);
7383 oprcanmerge
= PQgetvalue(res
, 0, i_oprcanmerge
);
7384 oprcanhash
= PQgetvalue(res
, 0, i_oprcanhash
);
7386 appendPQExpBuffer(details
, " PROCEDURE = %s",
7387 convertRegProcReference(oprcode
));
7389 appendPQExpBuffer(oprid
, "%s (",
7390 oprinfo
->dobj
.name
);
7393 * right unary means there's a left arg and left unary means there's a
7396 if (strcmp(oprkind
, "r") == 0 ||
7397 strcmp(oprkind
, "b") == 0)
7399 if (g_fout
->remoteVersion
>= 70100)
7402 name
= fmtId(oprleft
);
7403 appendPQExpBuffer(details
, ",\n LEFTARG = %s", name
);
7404 appendPQExpBuffer(oprid
, "%s", name
);
7407 appendPQExpBuffer(oprid
, "NONE");
7409 if (strcmp(oprkind
, "l") == 0 ||
7410 strcmp(oprkind
, "b") == 0)
7412 if (g_fout
->remoteVersion
>= 70100)
7415 name
= fmtId(oprright
);
7416 appendPQExpBuffer(details
, ",\n RIGHTARG = %s", name
);
7417 appendPQExpBuffer(oprid
, ", %s)", name
);
7420 appendPQExpBuffer(oprid
, ", NONE)");
7422 name
= convertOperatorReference(oprcom
);
7424 appendPQExpBuffer(details
, ",\n COMMUTATOR = %s", name
);
7426 name
= convertOperatorReference(oprnegate
);
7428 appendPQExpBuffer(details
, ",\n NEGATOR = %s", name
);
7430 if (strcmp(oprcanmerge
, "t") == 0)
7431 appendPQExpBuffer(details
, ",\n MERGES");
7433 if (strcmp(oprcanhash
, "t") == 0)
7434 appendPQExpBuffer(details
, ",\n HASHES");
7436 name
= convertRegProcReference(oprrest
);
7438 appendPQExpBuffer(details
, ",\n RESTRICT = %s", name
);
7440 name
= convertRegProcReference(oprjoin
);
7442 appendPQExpBuffer(details
, ",\n JOIN = %s", name
);
7445 * DROP must be fully qualified in case same name appears in pg_catalog
7447 appendPQExpBuffer(delq
, "DROP OPERATOR %s.%s;\n",
7448 fmtId(oprinfo
->dobj
.namespace->dobj
.name
),
7451 appendPQExpBuffer(q
, "CREATE OPERATOR %s (\n%s\n);\n",
7452 oprinfo
->dobj
.name
, details
->data
);
7454 ArchiveEntry(fout
, oprinfo
->dobj
.catId
, oprinfo
->dobj
.dumpId
,
7456 oprinfo
->dobj
.namespace->dobj
.name
,
7459 false, "OPERATOR", q
->data
, delq
->data
, NULL
,
7460 oprinfo
->dobj
.dependencies
, oprinfo
->dobj
.nDeps
,
7463 /* Dump Operator Comments */
7464 resetPQExpBuffer(q
);
7465 appendPQExpBuffer(q
, "OPERATOR %s", oprid
->data
);
7466 dumpComment(fout
, q
->data
,
7467 oprinfo
->dobj
.namespace->dobj
.name
, oprinfo
->rolname
,
7468 oprinfo
->dobj
.catId
, 0, oprinfo
->dobj
.dumpId
);
7472 destroyPQExpBuffer(query
);
7473 destroyPQExpBuffer(q
);
7474 destroyPQExpBuffer(delq
);
7475 destroyPQExpBuffer(oprid
);
7476 destroyPQExpBuffer(details
);
7480 * Convert a function reference obtained from pg_operator
7482 * Returns what to print, or NULL if function references is InvalidOid
7484 * In 7.3 the input is a REGPROCEDURE display; we have to strip the
7485 * argument-types part. In prior versions, the input is a REGPROC display.
7488 convertRegProcReference(const char *proc
)
7490 /* In all cases "-" means a null reference */
7491 if (strcmp(proc
, "-") == 0)
7494 if (g_fout
->remoteVersion
>= 70300)
7500 name
= strdup(proc
);
7501 /* find non-double-quoted left paren */
7503 for (paren
= name
; *paren
; paren
++)
7505 if (*paren
== '(' && !inquote
)
7516 /* REGPROC before 7.3 does not quote its result */
7521 * Convert an operator cross-reference obtained from pg_operator
7523 * Returns what to print, or NULL to print nothing
7525 * In 7.3 and up the input is a REGOPERATOR display; we have to strip the
7526 * argument-types part, and add OPERATOR() decoration if the name is
7527 * schema-qualified. In older versions, the input is just a numeric OID,
7528 * which we search our operator list for.
7531 convertOperatorReference(const char *opr
)
7535 /* In all cases "0" means a null reference */
7536 if (strcmp(opr
, "0") == 0)
7539 if (g_fout
->remoteVersion
>= 70300)
7548 /* find non-double-quoted left paren, and check for non-quoted dot */
7551 for (ptr
= name
; *ptr
; ptr
++)
7555 else if (*ptr
== '.' && !inquote
)
7557 else if (*ptr
== '(' && !inquote
)
7563 /* If not schema-qualified, don't need to add OPERATOR() */
7566 oname
= malloc(strlen(name
) + 11);
7567 sprintf(oname
, "OPERATOR(%s)", name
);
7572 oprInfo
= findOprByOid(atooid(opr
));
7573 if (oprInfo
== NULL
)
7575 write_msg(NULL
, "WARNING: could not find operator with OID %s\n",
7579 return oprInfo
->dobj
.name
;
7583 * Convert a function OID obtained from pg_ts_parser or pg_ts_template
7585 * It is sufficient to use REGPROC rather than REGPROCEDURE, since the
7586 * argument lists of these functions are predetermined. Note that the
7587 * caller should ensure we are in the proper schema, because the results
7588 * are search path dependent!
7591 convertTSFunction(Oid funcOid
)
7598 snprintf(query
, sizeof(query
),
7599 "SELECT '%u'::pg_catalog.regproc", funcOid
);
7600 res
= PQexec(g_conn
, query
);
7601 check_sql_result(res
, g_conn
, query
, PGRES_TUPLES_OK
);
7603 ntups
= PQntuples(res
);
7606 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
7611 result
= strdup(PQgetvalue(res
, 0, 0));
7621 * write out a single operator class definition
7624 dumpOpclass(Archive
*fout
, OpclassInfo
*opcinfo
)
7656 /* Skip if not to be dumped */
7657 if (!opcinfo
->dobj
.dump
|| dataOnly
)
7661 * XXX currently we do not implement dumping of operator classes from
7662 * pre-7.3 databases. This could be done but it seems not worth the
7665 if (g_fout
->remoteVersion
< 70300)
7668 query
= createPQExpBuffer();
7669 q
= createPQExpBuffer();
7670 delq
= createPQExpBuffer();
7672 /* Make sure we are in proper schema so regoperator works correctly */
7673 selectSourceSchema(opcinfo
->dobj
.namespace->dobj
.name
);
7675 /* Get additional fields from the pg_opclass row */
7676 if (g_fout
->remoteVersion
>= 80300)
7678 appendPQExpBuffer(query
, "SELECT opcintype::pg_catalog.regtype, "
7679 "opckeytype::pg_catalog.regtype, "
7681 "opfname AS opcfamily, "
7682 "nspname AS opcfamilynsp, "
7683 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
7684 "FROM pg_catalog.pg_opclass c "
7685 "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
7686 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
7687 "WHERE c.oid = '%u'::pg_catalog.oid",
7688 opcinfo
->dobj
.catId
.oid
);
7692 appendPQExpBuffer(query
, "SELECT opcintype::pg_catalog.regtype, "
7693 "opckeytype::pg_catalog.regtype, "
7695 "NULL AS opcfamily, "
7696 "NULL AS opcfamilynsp, "
7697 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
7698 "FROM pg_catalog.pg_opclass "
7699 "WHERE oid = '%u'::pg_catalog.oid",
7700 opcinfo
->dobj
.catId
.oid
);
7703 res
= PQexec(g_conn
, query
->data
);
7704 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
7706 /* Expecting a single result only */
7707 ntups
= PQntuples(res
);
7710 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
7711 ntups
, query
->data
);
7715 i_opcintype
= PQfnumber(res
, "opcintype");
7716 i_opckeytype
= PQfnumber(res
, "opckeytype");
7717 i_opcdefault
= PQfnumber(res
, "opcdefault");
7718 i_opcfamily
= PQfnumber(res
, "opcfamily");
7719 i_opcfamilynsp
= PQfnumber(res
, "opcfamilynsp");
7720 i_amname
= PQfnumber(res
, "amname");
7722 opcintype
= PQgetvalue(res
, 0, i_opcintype
);
7723 opckeytype
= PQgetvalue(res
, 0, i_opckeytype
);
7724 opcdefault
= PQgetvalue(res
, 0, i_opcdefault
);
7725 opcfamily
= PQgetvalue(res
, 0, i_opcfamily
);
7726 opcfamilynsp
= PQgetvalue(res
, 0, i_opcfamilynsp
);
7727 /* amname will still be needed after we PQclear res */
7728 amname
= strdup(PQgetvalue(res
, 0, i_amname
));
7731 * DROP must be fully qualified in case same name appears in pg_catalog
7733 appendPQExpBuffer(delq
, "DROP OPERATOR CLASS %s",
7734 fmtId(opcinfo
->dobj
.namespace->dobj
.name
));
7735 appendPQExpBuffer(delq
, ".%s",
7736 fmtId(opcinfo
->dobj
.name
));
7737 appendPQExpBuffer(delq
, " USING %s;\n",
7740 /* Build the fixed portion of the CREATE command */
7741 appendPQExpBuffer(q
, "CREATE OPERATOR CLASS %s\n ",
7742 fmtId(opcinfo
->dobj
.name
));
7743 if (strcmp(opcdefault
, "t") == 0)
7744 appendPQExpBuffer(q
, "DEFAULT ");
7745 appendPQExpBuffer(q
, "FOR TYPE %s USING %s",
7748 if (strlen(opcfamily
) > 0 &&
7749 (strcmp(opcfamily
, opcinfo
->dobj
.name
) != 0 ||
7750 strcmp(opcfamilynsp
, opcinfo
->dobj
.namespace->dobj
.name
) != 0))
7752 appendPQExpBuffer(q
, " FAMILY ");
7753 if (strcmp(opcfamilynsp
, opcinfo
->dobj
.namespace->dobj
.name
) != 0)
7754 appendPQExpBuffer(q
, "%s.", fmtId(opcfamilynsp
));
7755 appendPQExpBuffer(q
, "%s", fmtId(opcfamily
));
7757 appendPQExpBuffer(q
, " AS\n ");
7761 if (strcmp(opckeytype
, "-") != 0)
7763 appendPQExpBuffer(q
, "STORAGE %s",
7771 * Now fetch and print the OPERATOR entries (pg_amop rows).
7773 resetPQExpBuffer(query
);
7775 if (g_fout
->remoteVersion
>= 80400)
7778 * Print only those opfamily members that are tied to the opclass by
7779 * pg_depend entries.
7781 * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
7782 * an older server's table in which it is used. Would it be better
7783 * to silently ignore it?
7785 appendPQExpBuffer(query
, "SELECT amopstrategy, false as amopreqcheck, "
7786 "amopopr::pg_catalog.regoperator "
7787 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
7788 "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
7789 "AND refobjid = '%u'::pg_catalog.oid "
7790 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
7791 "AND objid = ao.oid "
7792 "ORDER BY amopstrategy",
7793 opcinfo
->dobj
.catId
.oid
);
7795 else if (g_fout
->remoteVersion
>= 80300)
7798 * Print only those opfamily members that are tied to the opclass by
7799 * pg_depend entries.
7801 appendPQExpBuffer(query
, "SELECT amopstrategy, amopreqcheck, "
7802 "amopopr::pg_catalog.regoperator "
7803 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
7804 "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
7805 "AND refobjid = '%u'::pg_catalog.oid "
7806 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
7807 "AND objid = ao.oid "
7808 "ORDER BY amopstrategy",
7809 opcinfo
->dobj
.catId
.oid
);
7813 appendPQExpBuffer(query
, "SELECT amopstrategy, amopreqcheck, "
7814 "amopopr::pg_catalog.regoperator "
7815 "FROM pg_catalog.pg_amop "
7816 "WHERE amopclaid = '%u'::pg_catalog.oid "
7817 "ORDER BY amopstrategy",
7818 opcinfo
->dobj
.catId
.oid
);
7821 res
= PQexec(g_conn
, query
->data
);
7822 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
7824 ntups
= PQntuples(res
);
7826 i_amopstrategy
= PQfnumber(res
, "amopstrategy");
7827 i_amopreqcheck
= PQfnumber(res
, "amopreqcheck");
7828 i_amopopr
= PQfnumber(res
, "amopopr");
7830 for (i
= 0; i
< ntups
; i
++)
7832 amopstrategy
= PQgetvalue(res
, i
, i_amopstrategy
);
7833 amopreqcheck
= PQgetvalue(res
, i
, i_amopreqcheck
);
7834 amopopr
= PQgetvalue(res
, i
, i_amopopr
);
7837 appendPQExpBuffer(q
, " ,\n ");
7839 appendPQExpBuffer(q
, "OPERATOR %s %s",
7840 amopstrategy
, amopopr
);
7841 if (strcmp(amopreqcheck
, "t") == 0)
7842 appendPQExpBuffer(q
, " RECHECK");
7850 * Now fetch and print the FUNCTION entries (pg_amproc rows).
7852 resetPQExpBuffer(query
);
7854 if (g_fout
->remoteVersion
>= 80300)
7857 * Print only those opfamily members that are tied to the opclass by
7858 * pg_depend entries.
7860 appendPQExpBuffer(query
, "SELECT amprocnum, "
7861 "amproc::pg_catalog.regprocedure "
7862 "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
7863 "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
7864 "AND refobjid = '%u'::pg_catalog.oid "
7865 "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
7866 "AND objid = ap.oid "
7867 "ORDER BY amprocnum",
7868 opcinfo
->dobj
.catId
.oid
);
7872 appendPQExpBuffer(query
, "SELECT amprocnum, "
7873 "amproc::pg_catalog.regprocedure "
7874 "FROM pg_catalog.pg_amproc "
7875 "WHERE amopclaid = '%u'::pg_catalog.oid "
7876 "ORDER BY amprocnum",
7877 opcinfo
->dobj
.catId
.oid
);
7880 res
= PQexec(g_conn
, query
->data
);
7881 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
7883 ntups
= PQntuples(res
);
7885 i_amprocnum
= PQfnumber(res
, "amprocnum");
7886 i_amproc
= PQfnumber(res
, "amproc");
7888 for (i
= 0; i
< ntups
; i
++)
7890 amprocnum
= PQgetvalue(res
, i
, i_amprocnum
);
7891 amproc
= PQgetvalue(res
, i
, i_amproc
);
7894 appendPQExpBuffer(q
, " ,\n ");
7896 appendPQExpBuffer(q
, "FUNCTION %s %s",
7904 appendPQExpBuffer(q
, ";\n");
7906 ArchiveEntry(fout
, opcinfo
->dobj
.catId
, opcinfo
->dobj
.dumpId
,
7908 opcinfo
->dobj
.namespace->dobj
.name
,
7911 false, "OPERATOR CLASS", q
->data
, delq
->data
, NULL
,
7912 opcinfo
->dobj
.dependencies
, opcinfo
->dobj
.nDeps
,
7915 /* Dump Operator Class Comments */
7916 resetPQExpBuffer(q
);
7917 appendPQExpBuffer(q
, "OPERATOR CLASS %s",
7918 fmtId(opcinfo
->dobj
.name
));
7919 appendPQExpBuffer(q
, " USING %s",
7921 dumpComment(fout
, q
->data
,
7922 NULL
, opcinfo
->rolname
,
7923 opcinfo
->dobj
.catId
, 0, opcinfo
->dobj
.dumpId
);
7926 destroyPQExpBuffer(query
);
7927 destroyPQExpBuffer(q
);
7928 destroyPQExpBuffer(delq
);
7933 * write out a single operator family definition
7936 dumpOpfamily(Archive
*fout
, OpfamilyInfo
*opfinfo
)
7943 PGresult
*res_procs
;
7951 int i_amproclefttype
;
7952 int i_amprocrighttype
;
7959 char *amproclefttype
;
7960 char *amprocrighttype
;
7964 /* Skip if not to be dumped */
7965 if (!opfinfo
->dobj
.dump
|| dataOnly
)
7969 * We want to dump the opfamily only if (1) it contains "loose" operators
7970 * or functions, or (2) it contains an opclass with a different name or
7971 * owner. Otherwise it's sufficient to let it be created during creation
7972 * of the contained opclass, and not dumping it improves portability of
7973 * the dump. Since we have to fetch the loose operators/funcs anyway, do
7977 query
= createPQExpBuffer();
7978 q
= createPQExpBuffer();
7979 delq
= createPQExpBuffer();
7981 /* Make sure we are in proper schema so regoperator works correctly */
7982 selectSourceSchema(opfinfo
->dobj
.namespace->dobj
.name
);
7985 * Fetch only those opfamily members that are tied directly to the
7986 * opfamily by pg_depend entries.
7988 if (g_fout
->remoteVersion
>= 80400)
7991 * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
7992 * an older server's table in which it is used. Would it be better
7993 * to silently ignore it?
7995 appendPQExpBuffer(query
, "SELECT amopstrategy, false as amopreqcheck, "
7996 "amopopr::pg_catalog.regoperator "
7997 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
7998 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
7999 "AND refobjid = '%u'::pg_catalog.oid "
8000 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
8001 "AND objid = ao.oid "
8002 "ORDER BY amopstrategy",
8003 opfinfo
->dobj
.catId
.oid
);
8007 appendPQExpBuffer(query
, "SELECT amopstrategy, amopreqcheck, "
8008 "amopopr::pg_catalog.regoperator "
8009 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
8010 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8011 "AND refobjid = '%u'::pg_catalog.oid "
8012 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
8013 "AND objid = ao.oid "
8014 "ORDER BY amopstrategy",
8015 opfinfo
->dobj
.catId
.oid
);
8018 res_ops
= PQexec(g_conn
, query
->data
);
8019 check_sql_result(res_ops
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8021 resetPQExpBuffer(query
);
8023 appendPQExpBuffer(query
, "SELECT amprocnum, "
8024 "amproc::pg_catalog.regprocedure, "
8025 "amproclefttype::pg_catalog.regtype, "
8026 "amprocrighttype::pg_catalog.regtype "
8027 "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
8028 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8029 "AND refobjid = '%u'::pg_catalog.oid "
8030 "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
8031 "AND objid = ap.oid "
8032 "ORDER BY amprocnum",
8033 opfinfo
->dobj
.catId
.oid
);
8035 res_procs
= PQexec(g_conn
, query
->data
);
8036 check_sql_result(res_procs
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8038 if (PQntuples(res_ops
) == 0 && PQntuples(res_procs
) == 0)
8040 /* No loose members, so check contained opclasses */
8041 resetPQExpBuffer(query
);
8043 appendPQExpBuffer(query
, "SELECT 1 "
8044 "FROM pg_catalog.pg_opclass c, pg_catalog.pg_opfamily f, pg_catalog.pg_depend "
8045 "WHERE f.oid = '%u'::pg_catalog.oid "
8046 "AND refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8047 "AND refobjid = f.oid "
8048 "AND classid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
8049 "AND objid = c.oid "
8050 "AND (opcname != opfname OR opcnamespace != opfnamespace OR opcowner != opfowner) "
8052 opfinfo
->dobj
.catId
.oid
);
8054 res
= PQexec(g_conn
, query
->data
);
8055 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8057 if (PQntuples(res
) == 0)
8059 /* no need to dump it, so bail out */
8063 destroyPQExpBuffer(query
);
8064 destroyPQExpBuffer(q
);
8065 destroyPQExpBuffer(delq
);
8072 /* Get additional fields from the pg_opfamily row */
8073 resetPQExpBuffer(query
);
8075 appendPQExpBuffer(query
, "SELECT "
8076 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opfmethod) AS amname "
8077 "FROM pg_catalog.pg_opfamily "
8078 "WHERE oid = '%u'::pg_catalog.oid",
8079 opfinfo
->dobj
.catId
.oid
);
8081 res
= PQexec(g_conn
, query
->data
);
8082 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8084 /* Expecting a single result only */
8085 ntups
= PQntuples(res
);
8088 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
8089 ntups
, query
->data
);
8093 i_amname
= PQfnumber(res
, "amname");
8095 /* amname will still be needed after we PQclear res */
8096 amname
= strdup(PQgetvalue(res
, 0, i_amname
));
8099 * DROP must be fully qualified in case same name appears in pg_catalog
8101 appendPQExpBuffer(delq
, "DROP OPERATOR FAMILY %s",
8102 fmtId(opfinfo
->dobj
.namespace->dobj
.name
));
8103 appendPQExpBuffer(delq
, ".%s",
8104 fmtId(opfinfo
->dobj
.name
));
8105 appendPQExpBuffer(delq
, " USING %s;\n",
8108 /* Build the fixed portion of the CREATE command */
8109 appendPQExpBuffer(q
, "CREATE OPERATOR FAMILY %s",
8110 fmtId(opfinfo
->dobj
.name
));
8111 appendPQExpBuffer(q
, " USING %s;\n",
8116 /* Do we need an ALTER to add loose members? */
8117 if (PQntuples(res_ops
) > 0 || PQntuples(res_procs
) > 0)
8119 appendPQExpBuffer(q
, "ALTER OPERATOR FAMILY %s",
8120 fmtId(opfinfo
->dobj
.name
));
8121 appendPQExpBuffer(q
, " USING %s ADD\n ",
8127 * Now fetch and print the OPERATOR entries (pg_amop rows).
8129 ntups
= PQntuples(res_ops
);
8131 i_amopstrategy
= PQfnumber(res_ops
, "amopstrategy");
8132 i_amopreqcheck
= PQfnumber(res_ops
, "amopreqcheck");
8133 i_amopopr
= PQfnumber(res_ops
, "amopopr");
8135 for (i
= 0; i
< ntups
; i
++)
8137 amopstrategy
= PQgetvalue(res_ops
, i
, i_amopstrategy
);
8138 amopreqcheck
= PQgetvalue(res_ops
, i
, i_amopreqcheck
);
8139 amopopr
= PQgetvalue(res_ops
, i
, i_amopopr
);
8142 appendPQExpBuffer(q
, " ,\n ");
8144 appendPQExpBuffer(q
, "OPERATOR %s %s",
8145 amopstrategy
, amopopr
);
8146 if (strcmp(amopreqcheck
, "t") == 0)
8147 appendPQExpBuffer(q
, " RECHECK");
8153 * Now fetch and print the FUNCTION entries (pg_amproc rows).
8155 ntups
= PQntuples(res_procs
);
8157 i_amprocnum
= PQfnumber(res_procs
, "amprocnum");
8158 i_amproc
= PQfnumber(res_procs
, "amproc");
8159 i_amproclefttype
= PQfnumber(res_procs
, "amproclefttype");
8160 i_amprocrighttype
= PQfnumber(res_procs
, "amprocrighttype");
8162 for (i
= 0; i
< ntups
; i
++)
8164 amprocnum
= PQgetvalue(res_procs
, i
, i_amprocnum
);
8165 amproc
= PQgetvalue(res_procs
, i
, i_amproc
);
8166 amproclefttype
= PQgetvalue(res_procs
, i
, i_amproclefttype
);
8167 amprocrighttype
= PQgetvalue(res_procs
, i
, i_amprocrighttype
);
8170 appendPQExpBuffer(q
, " ,\n ");
8172 appendPQExpBuffer(q
, "FUNCTION %s (%s, %s) %s",
8173 amprocnum
, amproclefttype
, amprocrighttype
,
8179 appendPQExpBuffer(q
, ";\n");
8182 ArchiveEntry(fout
, opfinfo
->dobj
.catId
, opfinfo
->dobj
.dumpId
,
8184 opfinfo
->dobj
.namespace->dobj
.name
,
8187 false, "OPERATOR FAMILY", q
->data
, delq
->data
, NULL
,
8188 opfinfo
->dobj
.dependencies
, opfinfo
->dobj
.nDeps
,
8191 /* Dump Operator Family Comments */
8192 resetPQExpBuffer(q
);
8193 appendPQExpBuffer(q
, "OPERATOR FAMILY %s",
8194 fmtId(opfinfo
->dobj
.name
));
8195 appendPQExpBuffer(q
, " USING %s",
8197 dumpComment(fout
, q
->data
,
8198 NULL
, opfinfo
->rolname
,
8199 opfinfo
->dobj
.catId
, 0, opfinfo
->dobj
.dumpId
);
8204 destroyPQExpBuffer(query
);
8205 destroyPQExpBuffer(q
);
8206 destroyPQExpBuffer(delq
);
8211 * write out a single conversion definition
8214 dumpConversion(Archive
*fout
, ConvInfo
*convinfo
)
8219 PQExpBuffer details
;
8223 int i_conforencoding
;
8224 int i_contoencoding
;
8227 const char *conname
;
8228 const char *conforencoding
;
8229 const char *contoencoding
;
8230 const char *conproc
;
8233 /* Skip if not to be dumped */
8234 if (!convinfo
->dobj
.dump
|| dataOnly
)
8237 query
= createPQExpBuffer();
8238 q
= createPQExpBuffer();
8239 delq
= createPQExpBuffer();
8240 details
= createPQExpBuffer();
8242 /* Make sure we are in proper schema */
8243 selectSourceSchema(convinfo
->dobj
.namespace->dobj
.name
);
8245 /* Get conversion-specific details */
8246 appendPQExpBuffer(query
, "SELECT conname, "
8247 "pg_catalog.pg_encoding_to_char(conforencoding) AS conforencoding, "
8248 "pg_catalog.pg_encoding_to_char(contoencoding) AS contoencoding, "
8249 "conproc, condefault "
8250 "FROM pg_catalog.pg_conversion c "
8251 "WHERE c.oid = '%u'::pg_catalog.oid",
8252 convinfo
->dobj
.catId
.oid
);
8254 res
= PQexec(g_conn
, query
->data
);
8255 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8257 /* Expecting a single result only */
8258 ntups
= PQntuples(res
);
8261 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
8262 ntups
, query
->data
);
8266 i_conname
= PQfnumber(res
, "conname");
8267 i_conforencoding
= PQfnumber(res
, "conforencoding");
8268 i_contoencoding
= PQfnumber(res
, "contoencoding");
8269 i_conproc
= PQfnumber(res
, "conproc");
8270 i_condefault
= PQfnumber(res
, "condefault");
8272 conname
= PQgetvalue(res
, 0, i_conname
);
8273 conforencoding
= PQgetvalue(res
, 0, i_conforencoding
);
8274 contoencoding
= PQgetvalue(res
, 0, i_contoencoding
);
8275 conproc
= PQgetvalue(res
, 0, i_conproc
);
8276 condefault
= (PQgetvalue(res
, 0, i_condefault
)[0] == 't');
8279 * DROP must be fully qualified in case same name appears in pg_catalog
8281 appendPQExpBuffer(delq
, "DROP CONVERSION %s",
8282 fmtId(convinfo
->dobj
.namespace->dobj
.name
));
8283 appendPQExpBuffer(delq
, ".%s;\n",
8284 fmtId(convinfo
->dobj
.name
));
8286 appendPQExpBuffer(q
, "CREATE %sCONVERSION %s FOR ",
8287 (condefault
) ? "DEFAULT " : "",
8288 fmtId(convinfo
->dobj
.name
));
8289 appendStringLiteralAH(q
, conforencoding
, fout
);
8290 appendPQExpBuffer(q
, " TO ");
8291 appendStringLiteralAH(q
, contoencoding
, fout
);
8292 /* regproc is automatically quoted in 7.3 and above */
8293 appendPQExpBuffer(q
, " FROM %s;\n", conproc
);
8295 ArchiveEntry(fout
, convinfo
->dobj
.catId
, convinfo
->dobj
.dumpId
,
8296 convinfo
->dobj
.name
,
8297 convinfo
->dobj
.namespace->dobj
.name
,
8300 false, "CONVERSION", q
->data
, delq
->data
, NULL
,
8301 convinfo
->dobj
.dependencies
, convinfo
->dobj
.nDeps
,
8304 /* Dump Conversion Comments */
8305 resetPQExpBuffer(q
);
8306 appendPQExpBuffer(q
, "CONVERSION %s", fmtId(convinfo
->dobj
.name
));
8307 dumpComment(fout
, q
->data
,
8308 convinfo
->dobj
.namespace->dobj
.name
, convinfo
->rolname
,
8309 convinfo
->dobj
.catId
, 0, convinfo
->dobj
.dumpId
);
8313 destroyPQExpBuffer(query
);
8314 destroyPQExpBuffer(q
);
8315 destroyPQExpBuffer(delq
);
8316 destroyPQExpBuffer(details
);
8320 * format_aggregate_signature: generate aggregate name and argument list
8322 * The argument type names are qualified if needed. The aggregate name
8323 * is never qualified.
8326 format_aggregate_signature(AggInfo
*agginfo
, Archive
*fout
, bool honor_quotes
)
8328 PQExpBufferData buf
;
8331 initPQExpBuffer(&buf
);
8333 appendPQExpBuffer(&buf
, "%s",
8334 fmtId(agginfo
->aggfn
.dobj
.name
));
8336 appendPQExpBuffer(&buf
, "%s", agginfo
->aggfn
.dobj
.name
);
8338 if (agginfo
->aggfn
.nargs
== 0)
8339 appendPQExpBuffer(&buf
, "(*)");
8342 appendPQExpBuffer(&buf
, "(");
8343 for (j
= 0; j
< agginfo
->aggfn
.nargs
; j
++)
8347 typname
= getFormattedTypeName(agginfo
->aggfn
.argtypes
[j
], zeroAsOpaque
);
8349 appendPQExpBuffer(&buf
, "%s%s",
8350 (j
> 0) ? ", " : "",
8354 appendPQExpBuffer(&buf
, ")");
8361 * write out a single aggregate definition
8364 dumpAgg(Archive
*fout
, AggInfo
*agginfo
)
8369 PQExpBuffer details
;
8380 const char *aggtransfn
;
8381 const char *aggfinalfn
;
8382 const char *aggsortop
;
8383 const char *aggtranstype
;
8384 const char *agginitval
;
8387 /* Skip if not to be dumped */
8388 if (!agginfo
->aggfn
.dobj
.dump
|| dataOnly
)
8391 query
= createPQExpBuffer();
8392 q
= createPQExpBuffer();
8393 delq
= createPQExpBuffer();
8394 details
= createPQExpBuffer();
8396 /* Make sure we are in proper schema */
8397 selectSourceSchema(agginfo
->aggfn
.dobj
.namespace->dobj
.name
);
8399 /* Get aggregate-specific details */
8400 if (g_fout
->remoteVersion
>= 80100)
8402 appendPQExpBuffer(query
, "SELECT aggtransfn, "
8403 "aggfinalfn, aggtranstype::pg_catalog.regtype, "
8404 "aggsortop::pg_catalog.regoperator, "
8406 "'t'::boolean as convertok "
8407 "from pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
8408 "where a.aggfnoid = p.oid "
8409 "and p.oid = '%u'::pg_catalog.oid",
8410 agginfo
->aggfn
.dobj
.catId
.oid
);
8412 else if (g_fout
->remoteVersion
>= 70300)
8414 appendPQExpBuffer(query
, "SELECT aggtransfn, "
8415 "aggfinalfn, aggtranstype::pg_catalog.regtype, "
8418 "'t'::boolean as convertok "
8419 "from pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
8420 "where a.aggfnoid = p.oid "
8421 "and p.oid = '%u'::pg_catalog.oid",
8422 agginfo
->aggfn
.dobj
.catId
.oid
);
8424 else if (g_fout
->remoteVersion
>= 70100)
8426 appendPQExpBuffer(query
, "SELECT aggtransfn, aggfinalfn, "
8427 "format_type(aggtranstype, NULL) as aggtranstype, "
8430 "'t'::boolean as convertok "
8431 "from pg_aggregate "
8432 "where oid = '%u'::oid",
8433 agginfo
->aggfn
.dobj
.catId
.oid
);
8437 appendPQExpBuffer(query
, "SELECT aggtransfn1 as aggtransfn, "
8439 "(select typname from pg_type where oid = aggtranstype1) as aggtranstype, "
8441 "agginitval1 as agginitval, "
8442 "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) as convertok "
8443 "from pg_aggregate "
8444 "where oid = '%u'::oid",
8445 agginfo
->aggfn
.dobj
.catId
.oid
);
8448 res
= PQexec(g_conn
, query
->data
);
8449 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8451 /* Expecting a single result only */
8452 ntups
= PQntuples(res
);
8455 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
8456 ntups
, query
->data
);
8460 i_aggtransfn
= PQfnumber(res
, "aggtransfn");
8461 i_aggfinalfn
= PQfnumber(res
, "aggfinalfn");
8462 i_aggsortop
= PQfnumber(res
, "aggsortop");
8463 i_aggtranstype
= PQfnumber(res
, "aggtranstype");
8464 i_agginitval
= PQfnumber(res
, "agginitval");
8465 i_convertok
= PQfnumber(res
, "convertok");
8467 aggtransfn
= PQgetvalue(res
, 0, i_aggtransfn
);
8468 aggfinalfn
= PQgetvalue(res
, 0, i_aggfinalfn
);
8469 aggsortop
= PQgetvalue(res
, 0, i_aggsortop
);
8470 aggtranstype
= PQgetvalue(res
, 0, i_aggtranstype
);
8471 agginitval
= PQgetvalue(res
, 0, i_agginitval
);
8472 convertok
= (PQgetvalue(res
, 0, i_convertok
)[0] == 't');
8474 aggsig
= format_aggregate_signature(agginfo
, fout
, true);
8475 aggsig_tag
= format_aggregate_signature(agginfo
, fout
, false);
8479 write_msg(NULL
, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
8484 if (g_fout
->remoteVersion
>= 70300)
8486 /* If using 7.3's regproc or regtype, data is already quoted */
8487 appendPQExpBuffer(details
, " SFUNC = %s,\n STYPE = %s",
8491 else if (g_fout
->remoteVersion
>= 70100)
8493 /* format_type quotes, regproc does not */
8494 appendPQExpBuffer(details
, " SFUNC = %s,\n STYPE = %s",
8500 /* need quotes all around */
8501 appendPQExpBuffer(details
, " SFUNC = %s,\n",
8503 appendPQExpBuffer(details
, " STYPE = %s",
8504 fmtId(aggtranstype
));
8507 if (!PQgetisnull(res
, 0, i_agginitval
))
8509 appendPQExpBuffer(details
, ",\n INITCOND = ");
8510 appendStringLiteralAH(details
, agginitval
, fout
);
8513 if (strcmp(aggfinalfn
, "-") != 0)
8515 appendPQExpBuffer(details
, ",\n FINALFUNC = %s",
8519 aggsortop
= convertOperatorReference(aggsortop
);
8522 appendPQExpBuffer(details
, ",\n SORTOP = %s",
8527 * DROP must be fully qualified in case same name appears in pg_catalog
8529 appendPQExpBuffer(delq
, "DROP AGGREGATE %s.%s;\n",
8530 fmtId(agginfo
->aggfn
.dobj
.namespace->dobj
.name
),
8533 appendPQExpBuffer(q
, "CREATE AGGREGATE %s (\n%s\n);\n",
8534 aggsig
, details
->data
);
8536 ArchiveEntry(fout
, agginfo
->aggfn
.dobj
.catId
, agginfo
->aggfn
.dobj
.dumpId
,
8538 agginfo
->aggfn
.dobj
.namespace->dobj
.name
,
8540 agginfo
->aggfn
.rolname
,
8541 false, "AGGREGATE", q
->data
, delq
->data
, NULL
,
8542 agginfo
->aggfn
.dobj
.dependencies
, agginfo
->aggfn
.dobj
.nDeps
,
8545 /* Dump Aggregate Comments */
8546 resetPQExpBuffer(q
);
8547 appendPQExpBuffer(q
, "AGGREGATE %s", aggsig
);
8548 dumpComment(fout
, q
->data
,
8549 agginfo
->aggfn
.dobj
.namespace->dobj
.name
, agginfo
->aggfn
.rolname
,
8550 agginfo
->aggfn
.dobj
.catId
, 0, agginfo
->aggfn
.dobj
.dumpId
);
8553 * Since there is no GRANT ON AGGREGATE syntax, we have to make the ACL
8554 * command look like a function's GRANT; in particular this affects the
8555 * syntax for zero-argument aggregates.
8560 aggsig
= format_function_signature(&agginfo
->aggfn
, true);
8561 aggsig_tag
= format_function_signature(&agginfo
->aggfn
, false);
8563 dumpACL(fout
, agginfo
->aggfn
.dobj
.catId
, agginfo
->aggfn
.dobj
.dumpId
,
8566 agginfo
->aggfn
.dobj
.namespace->dobj
.name
,
8567 agginfo
->aggfn
.rolname
, agginfo
->aggfn
.proacl
);
8574 destroyPQExpBuffer(query
);
8575 destroyPQExpBuffer(q
);
8576 destroyPQExpBuffer(delq
);
8577 destroyPQExpBuffer(details
);
8582 * write out a single text search parser
8585 dumpTSParser(Archive
*fout
, TSParserInfo
*prsinfo
)
8590 /* Skip if not to be dumped */
8591 if (!prsinfo
->dobj
.dump
|| dataOnly
)
8594 q
= createPQExpBuffer();
8595 delq
= createPQExpBuffer();
8597 /* Make sure we are in proper schema */
8598 selectSourceSchema(prsinfo
->dobj
.namespace->dobj
.name
);
8600 appendPQExpBuffer(q
, "CREATE TEXT SEARCH PARSER %s (\n",
8601 fmtId(prsinfo
->dobj
.name
));
8603 appendPQExpBuffer(q
, " START = %s,\n",
8604 convertTSFunction(prsinfo
->prsstart
));
8605 appendPQExpBuffer(q
, " GETTOKEN = %s,\n",
8606 convertTSFunction(prsinfo
->prstoken
));
8607 appendPQExpBuffer(q
, " END = %s,\n",
8608 convertTSFunction(prsinfo
->prsend
));
8609 if (prsinfo
->prsheadline
!= InvalidOid
)
8610 appendPQExpBuffer(q
, " HEADLINE = %s,\n",
8611 convertTSFunction(prsinfo
->prsheadline
));
8612 appendPQExpBuffer(q
, " LEXTYPES = %s );\n",
8613 convertTSFunction(prsinfo
->prslextype
));
8616 * DROP must be fully qualified in case same name appears in pg_catalog
8618 appendPQExpBuffer(delq
, "DROP TEXT SEARCH PARSER %s",
8619 fmtId(prsinfo
->dobj
.namespace->dobj
.name
));
8620 appendPQExpBuffer(delq
, ".%s;\n",
8621 fmtId(prsinfo
->dobj
.name
));
8623 ArchiveEntry(fout
, prsinfo
->dobj
.catId
, prsinfo
->dobj
.dumpId
,
8625 prsinfo
->dobj
.namespace->dobj
.name
,
8628 false, "TEXT SEARCH PARSER", q
->data
, delq
->data
, NULL
,
8629 prsinfo
->dobj
.dependencies
, prsinfo
->dobj
.nDeps
,
8632 /* Dump Parser Comments */
8633 resetPQExpBuffer(q
);
8634 appendPQExpBuffer(q
, "TEXT SEARCH PARSER %s",
8635 fmtId(prsinfo
->dobj
.name
));
8636 dumpComment(fout
, q
->data
,
8638 prsinfo
->dobj
.catId
, 0, prsinfo
->dobj
.dumpId
);
8640 destroyPQExpBuffer(q
);
8641 destroyPQExpBuffer(delq
);
8646 * write out a single text search dictionary
8649 dumpTSDictionary(Archive
*fout
, TSDictInfo
*dictinfo
)
8659 /* Skip if not to be dumped */
8660 if (!dictinfo
->dobj
.dump
|| dataOnly
)
8663 q
= createPQExpBuffer();
8664 delq
= createPQExpBuffer();
8665 query
= createPQExpBuffer();
8667 /* Fetch name and namespace of the dictionary's template */
8668 selectSourceSchema("pg_catalog");
8669 appendPQExpBuffer(query
, "SELECT nspname, tmplname "
8670 "FROM pg_ts_template p, pg_namespace n "
8671 "WHERE p.oid = '%u' AND n.oid = tmplnamespace",
8672 dictinfo
->dicttemplate
);
8673 res
= PQexec(g_conn
, query
->data
);
8674 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8675 ntups
= PQntuples(res
);
8678 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
8679 ntups
, query
->data
);
8682 nspname
= PQgetvalue(res
, 0, 0);
8683 tmplname
= PQgetvalue(res
, 0, 1);
8685 /* Make sure we are in proper schema */
8686 selectSourceSchema(dictinfo
->dobj
.namespace->dobj
.name
);
8688 appendPQExpBuffer(q
, "CREATE TEXT SEARCH DICTIONARY %s (\n",
8689 fmtId(dictinfo
->dobj
.name
));
8691 appendPQExpBuffer(q
, " TEMPLATE = ");
8692 if (strcmp(nspname
, dictinfo
->dobj
.namespace->dobj
.name
) != 0)
8693 appendPQExpBuffer(q
, "%s.", fmtId(nspname
));
8694 appendPQExpBuffer(q
, "%s", fmtId(tmplname
));
8698 /* the dictinitoption can be dumped straight into the command */
8699 if (dictinfo
->dictinitoption
)
8700 appendPQExpBuffer(q
, ",\n %s", dictinfo
->dictinitoption
);
8702 appendPQExpBuffer(q
, " );\n");
8705 * DROP must be fully qualified in case same name appears in pg_catalog
8707 appendPQExpBuffer(delq
, "DROP TEXT SEARCH DICTIONARY %s",
8708 fmtId(dictinfo
->dobj
.namespace->dobj
.name
));
8709 appendPQExpBuffer(delq
, ".%s;\n",
8710 fmtId(dictinfo
->dobj
.name
));
8712 ArchiveEntry(fout
, dictinfo
->dobj
.catId
, dictinfo
->dobj
.dumpId
,
8713 dictinfo
->dobj
.name
,
8714 dictinfo
->dobj
.namespace->dobj
.name
,
8717 false, "TEXT SEARCH DICTIONARY", q
->data
, delq
->data
, NULL
,
8718 dictinfo
->dobj
.dependencies
, dictinfo
->dobj
.nDeps
,
8721 /* Dump Dictionary Comments */
8722 resetPQExpBuffer(q
);
8723 appendPQExpBuffer(q
, "TEXT SEARCH DICTIONARY %s",
8724 fmtId(dictinfo
->dobj
.name
));
8725 dumpComment(fout
, q
->data
,
8726 NULL
, dictinfo
->rolname
,
8727 dictinfo
->dobj
.catId
, 0, dictinfo
->dobj
.dumpId
);
8729 destroyPQExpBuffer(q
);
8730 destroyPQExpBuffer(delq
);
8731 destroyPQExpBuffer(query
);
8736 * write out a single text search template
8739 dumpTSTemplate(Archive
*fout
, TSTemplateInfo
*tmplinfo
)
8744 /* Skip if not to be dumped */
8745 if (!tmplinfo
->dobj
.dump
|| dataOnly
)
8748 q
= createPQExpBuffer();
8749 delq
= createPQExpBuffer();
8751 /* Make sure we are in proper schema */
8752 selectSourceSchema(tmplinfo
->dobj
.namespace->dobj
.name
);
8754 appendPQExpBuffer(q
, "CREATE TEXT SEARCH TEMPLATE %s (\n",
8755 fmtId(tmplinfo
->dobj
.name
));
8757 if (tmplinfo
->tmplinit
!= InvalidOid
)
8758 appendPQExpBuffer(q
, " INIT = %s,\n",
8759 convertTSFunction(tmplinfo
->tmplinit
));
8760 appendPQExpBuffer(q
, " LEXIZE = %s );\n",
8761 convertTSFunction(tmplinfo
->tmpllexize
));
8764 * DROP must be fully qualified in case same name appears in pg_catalog
8766 appendPQExpBuffer(delq
, "DROP TEXT SEARCH TEMPLATE %s",
8767 fmtId(tmplinfo
->dobj
.namespace->dobj
.name
));
8768 appendPQExpBuffer(delq
, ".%s;\n",
8769 fmtId(tmplinfo
->dobj
.name
));
8771 ArchiveEntry(fout
, tmplinfo
->dobj
.catId
, tmplinfo
->dobj
.dumpId
,
8772 tmplinfo
->dobj
.name
,
8773 tmplinfo
->dobj
.namespace->dobj
.name
,
8776 false, "TEXT SEARCH TEMPLATE", q
->data
, delq
->data
, NULL
,
8777 tmplinfo
->dobj
.dependencies
, tmplinfo
->dobj
.nDeps
,
8780 /* Dump Template Comments */
8781 resetPQExpBuffer(q
);
8782 appendPQExpBuffer(q
, "TEXT SEARCH TEMPLATE %s",
8783 fmtId(tmplinfo
->dobj
.name
));
8784 dumpComment(fout
, q
->data
,
8786 tmplinfo
->dobj
.catId
, 0, tmplinfo
->dobj
.dumpId
);
8788 destroyPQExpBuffer(q
);
8789 destroyPQExpBuffer(delq
);
8794 * write out a single text search configuration
8797 dumpTSConfig(Archive
*fout
, TSConfigInfo
*cfginfo
)
8810 /* Skip if not to be dumped */
8811 if (!cfginfo
->dobj
.dump
|| dataOnly
)
8814 q
= createPQExpBuffer();
8815 delq
= createPQExpBuffer();
8816 query
= createPQExpBuffer();
8818 /* Fetch name and namespace of the config's parser */
8819 selectSourceSchema("pg_catalog");
8820 appendPQExpBuffer(query
, "SELECT nspname, prsname "
8821 "FROM pg_ts_parser p, pg_namespace n "
8822 "WHERE p.oid = '%u' AND n.oid = prsnamespace",
8823 cfginfo
->cfgparser
);
8824 res
= PQexec(g_conn
, query
->data
);
8825 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8826 ntups
= PQntuples(res
);
8829 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
8830 ntups
, query
->data
);
8833 nspname
= PQgetvalue(res
, 0, 0);
8834 prsname
= PQgetvalue(res
, 0, 1);
8836 /* Make sure we are in proper schema */
8837 selectSourceSchema(cfginfo
->dobj
.namespace->dobj
.name
);
8839 appendPQExpBuffer(q
, "CREATE TEXT SEARCH CONFIGURATION %s (\n",
8840 fmtId(cfginfo
->dobj
.name
));
8842 appendPQExpBuffer(q
, " PARSER = ");
8843 if (strcmp(nspname
, cfginfo
->dobj
.namespace->dobj
.name
) != 0)
8844 appendPQExpBuffer(q
, "%s.", fmtId(nspname
));
8845 appendPQExpBuffer(q
, "%s );\n", fmtId(prsname
));
8849 resetPQExpBuffer(query
);
8850 appendPQExpBuffer(query
,
8852 " ( SELECT alias FROM pg_catalog.ts_token_type('%u'::pg_catalog.oid) AS t \n"
8853 " WHERE t.tokid = m.maptokentype ) AS tokenname, \n"
8854 " m.mapdict::pg_catalog.regdictionary AS dictname \n"
8855 "FROM pg_catalog.pg_ts_config_map AS m \n"
8856 "WHERE m.mapcfg = '%u' \n"
8857 "ORDER BY m.mapcfg, m.maptokentype, m.mapseqno",
8858 cfginfo
->cfgparser
, cfginfo
->dobj
.catId
.oid
);
8860 res
= PQexec(g_conn
, query
->data
);
8861 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8862 ntups
= PQntuples(res
);
8864 i_tokenname
= PQfnumber(res
, "tokenname");
8865 i_dictname
= PQfnumber(res
, "dictname");
8867 for (i
= 0; i
< ntups
; i
++)
8869 char *tokenname
= PQgetvalue(res
, i
, i_tokenname
);
8870 char *dictname
= PQgetvalue(res
, i
, i_dictname
);
8873 strcmp(tokenname
, PQgetvalue(res
, i
- 1, i_tokenname
)) != 0)
8875 /* starting a new token type, so start a new command */
8877 appendPQExpBuffer(q
, ";\n");
8878 appendPQExpBuffer(q
, "\nALTER TEXT SEARCH CONFIGURATION %s\n",
8879 fmtId(cfginfo
->dobj
.name
));
8880 /* tokenname needs quoting, dictname does NOT */
8881 appendPQExpBuffer(q
, " ADD MAPPING FOR %s WITH %s",
8882 fmtId(tokenname
), dictname
);
8885 appendPQExpBuffer(q
, ", %s", dictname
);
8889 appendPQExpBuffer(q
, ";\n");
8894 * DROP must be fully qualified in case same name appears in pg_catalog
8896 appendPQExpBuffer(delq
, "DROP TEXT SEARCH CONFIGURATION %s",
8897 fmtId(cfginfo
->dobj
.namespace->dobj
.name
));
8898 appendPQExpBuffer(delq
, ".%s;\n",
8899 fmtId(cfginfo
->dobj
.name
));
8901 ArchiveEntry(fout
, cfginfo
->dobj
.catId
, cfginfo
->dobj
.dumpId
,
8903 cfginfo
->dobj
.namespace->dobj
.name
,
8906 false, "TEXT SEARCH CONFIGURATION", q
->data
, delq
->data
, NULL
,
8907 cfginfo
->dobj
.dependencies
, cfginfo
->dobj
.nDeps
,
8910 /* Dump Configuration Comments */
8911 resetPQExpBuffer(q
);
8912 appendPQExpBuffer(q
, "TEXT SEARCH CONFIGURATION %s",
8913 fmtId(cfginfo
->dobj
.name
));
8914 dumpComment(fout
, q
->data
,
8915 NULL
, cfginfo
->rolname
,
8916 cfginfo
->dobj
.catId
, 0, cfginfo
->dobj
.dumpId
);
8918 destroyPQExpBuffer(q
);
8919 destroyPQExpBuffer(delq
);
8920 destroyPQExpBuffer(query
);
8925 * Write out grant/revoke information
8927 * 'objCatId' is the catalog ID of the underlying object.
8928 * 'objDumpId' is the dump ID of the underlying object.
8929 * 'type' must be TABLE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, or TABLESPACE.
8930 * 'name' is the formatted name of the object. Must be quoted etc. already.
8931 * 'tag' is the tag for the archive entry (typ. unquoted name of object).
8932 * 'nspname' is the namespace the object is in (NULL if none).
8933 * 'owner' is the owner, NULL if there is no owner (for languages).
8934 * 'acls' is the string read out of the fooacl system catalog field;
8935 * it will be parsed here.
8939 dumpACL(Archive
*fout
, CatalogId objCatId
, DumpId objDumpId
,
8940 const char *type
, const char *name
,
8941 const char *tag
, const char *nspname
, const char *owner
,
8946 /* Do nothing if ACL dump is not enabled */
8947 if (dataOnly
|| aclsSkip
)
8950 sql
= createPQExpBuffer();
8952 if (!buildACLCommands(name
, type
, acls
, owner
, fout
->remoteVersion
, sql
))
8954 write_msg(NULL
, "could not parse ACL list (%s) for object \"%s\" (%s)\n",
8960 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
8964 false, "ACL", sql
->data
, "", NULL
,
8968 destroyPQExpBuffer(sql
);
8973 * write out to fout the declarations (not data) of a user-defined table
8976 dumpTable(Archive
*fout
, TableInfo
*tbinfo
)
8980 if (tbinfo
->dobj
.dump
)
8982 if (tbinfo
->relkind
== RELKIND_SEQUENCE
)
8983 dumpSequence(fout
, tbinfo
);
8985 dumpTableSchema(fout
, tbinfo
);
8987 /* Handle the ACL here */
8988 namecopy
= strdup(fmtId(tbinfo
->dobj
.name
));
8989 dumpACL(fout
, tbinfo
->dobj
.catId
, tbinfo
->dobj
.dumpId
,
8990 (tbinfo
->relkind
== RELKIND_SEQUENCE
) ? "SEQUENCE" : "TABLE",
8991 namecopy
, tbinfo
->dobj
.name
,
8992 tbinfo
->dobj
.namespace->dobj
.name
, tbinfo
->rolname
,
9000 * write the declaration (not data) of one user-defined table or view
9003 dumpTableSchema(Archive
*fout
, TableInfo
*tbinfo
)
9005 PQExpBuffer query
= createPQExpBuffer();
9006 PQExpBuffer q
= createPQExpBuffer();
9007 PQExpBuffer delq
= createPQExpBuffer();
9010 TableInfo
**parents
;
9011 int actual_atts
; /* number of attrs in this CREATE statment */
9017 /* Make sure we are in proper schema */
9018 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
9020 /* Is it a table or a view? */
9021 if (tbinfo
->relkind
== RELKIND_VIEW
)
9025 reltypename
= "VIEW";
9027 /* Fetch the view definition */
9028 if (g_fout
->remoteVersion
>= 70300)
9030 /* Beginning in 7.3, viewname is not unique; rely on OID */
9031 appendPQExpBuffer(query
,
9032 "SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) as viewdef",
9033 tbinfo
->dobj
.catId
.oid
);
9037 appendPQExpBuffer(query
, "SELECT definition as viewdef "
9038 " from pg_views where viewname = ");
9039 appendStringLiteralAH(query
, tbinfo
->dobj
.name
, fout
);
9040 appendPQExpBuffer(query
, ";");
9043 res
= PQexec(g_conn
, query
->data
);
9044 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
9046 if (PQntuples(res
) != 1)
9048 if (PQntuples(res
) < 1)
9049 write_msg(NULL
, "query to obtain definition of view \"%s\" returned no data\n",
9052 write_msg(NULL
, "query to obtain definition of view \"%s\" returned more than one definition\n",
9057 viewdef
= PQgetvalue(res
, 0, 0);
9059 if (strlen(viewdef
) == 0)
9061 write_msg(NULL
, "definition of view \"%s\" appears to be empty (length zero)\n",
9067 * DROP must be fully qualified in case same name appears in
9070 appendPQExpBuffer(delq
, "DROP VIEW %s.",
9071 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9072 appendPQExpBuffer(delq
, "%s;\n",
9073 fmtId(tbinfo
->dobj
.name
));
9075 appendPQExpBuffer(q
, "CREATE VIEW %s AS\n %s\n",
9076 fmtId(tbinfo
->dobj
.name
), viewdef
);
9082 reltypename
= "TABLE";
9083 numParents
= tbinfo
->numParents
;
9084 parents
= tbinfo
->parents
;
9087 * DROP must be fully qualified in case same name appears in
9090 appendPQExpBuffer(delq
, "DROP TABLE %s.",
9091 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9092 appendPQExpBuffer(delq
, "%s;\n",
9093 fmtId(tbinfo
->dobj
.name
));
9095 appendPQExpBuffer(q
, "CREATE TABLE %s (",
9096 fmtId(tbinfo
->dobj
.name
));
9098 for (j
= 0; j
< tbinfo
->numatts
; j
++)
9100 /* Is this one of the table's own attrs, and not dropped ? */
9101 if (!tbinfo
->inhAttrs
[j
] && !tbinfo
->attisdropped
[j
])
9103 /* Format properly if not first attr */
9104 if (actual_atts
> 0)
9105 appendPQExpBuffer(q
, ",");
9106 appendPQExpBuffer(q
, "\n ");
9108 /* Attribute name */
9109 appendPQExpBuffer(q
, "%s ",
9110 fmtId(tbinfo
->attnames
[j
]));
9112 /* Attribute type */
9113 if (g_fout
->remoteVersion
>= 70100)
9115 appendPQExpBuffer(q
, "%s",
9116 tbinfo
->atttypnames
[j
]);
9120 /* If no format_type, fake it */
9121 appendPQExpBuffer(q
, "%s",
9122 myFormatType(tbinfo
->atttypnames
[j
],
9123 tbinfo
->atttypmod
[j
]));
9127 * Default value --- suppress if inherited or to be printed
9130 if (tbinfo
->attrdefs
[j
] != NULL
&&
9131 !tbinfo
->inhAttrDef
[j
] &&
9132 !tbinfo
->attrdefs
[j
]->separate
)
9133 appendPQExpBuffer(q
, " DEFAULT %s",
9134 tbinfo
->attrdefs
[j
]->adef_expr
);
9137 * Not Null constraint --- suppress if inherited
9139 if (tbinfo
->notnull
[j
] && !tbinfo
->inhNotNull
[j
])
9140 appendPQExpBuffer(q
, " NOT NULL");
9147 * Add non-inherited CHECK constraints, if any.
9149 for (j
= 0; j
< tbinfo
->ncheck
; j
++)
9151 ConstraintInfo
*constr
= &(tbinfo
->checkexprs
[j
]);
9153 if (constr
->separate
|| !constr
->conislocal
)
9156 if (actual_atts
> 0)
9157 appendPQExpBuffer(q
, ",\n ");
9159 appendPQExpBuffer(q
, "CONSTRAINT %s ",
9160 fmtId(constr
->dobj
.name
));
9161 appendPQExpBuffer(q
, "%s", constr
->condef
);
9166 appendPQExpBuffer(q
, "\n)");
9170 appendPQExpBuffer(q
, "\nINHERITS (");
9171 for (k
= 0; k
< numParents
; k
++)
9173 TableInfo
*parentRel
= parents
[k
];
9176 appendPQExpBuffer(q
, ", ");
9177 if (parentRel
->dobj
.namespace != tbinfo
->dobj
.namespace)
9178 appendPQExpBuffer(q
, "%s.",
9179 fmtId(parentRel
->dobj
.namespace->dobj
.name
));
9180 appendPQExpBuffer(q
, "%s",
9181 fmtId(parentRel
->dobj
.name
));
9183 appendPQExpBuffer(q
, ")");
9186 if (tbinfo
->reloptions
&& strlen(tbinfo
->reloptions
) > 0)
9187 appendPQExpBuffer(q
, "\nWITH (%s)", tbinfo
->reloptions
);
9189 appendPQExpBuffer(q
, ";\n");
9191 /* Loop dumping statistics and storage statements */
9192 for (j
= 0; j
< tbinfo
->numatts
; j
++)
9195 * Dump per-column statistics information. We only issue an ALTER
9196 * TABLE statement if the attstattarget entry for this column is
9197 * non-negative (i.e. it's not the default value)
9199 if (tbinfo
->attstattarget
[j
] >= 0 &&
9200 !tbinfo
->attisdropped
[j
])
9202 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s ",
9203 fmtId(tbinfo
->dobj
.name
));
9204 appendPQExpBuffer(q
, "ALTER COLUMN %s ",
9205 fmtId(tbinfo
->attnames
[j
]));
9206 appendPQExpBuffer(q
, "SET STATISTICS %d;\n",
9207 tbinfo
->attstattarget
[j
]);
9211 * Dump per-column storage information. The statement is only
9212 * dumped if the storage has been changed from the type's default.
9214 if (!tbinfo
->attisdropped
[j
] && tbinfo
->attstorage
[j
] != tbinfo
->typstorage
[j
])
9216 switch (tbinfo
->attstorage
[j
])
9222 storage
= "EXTERNAL";
9228 storage
= "EXTENDED";
9235 * Only dump the statement if it's a storage type we recognize
9237 if (storage
!= NULL
)
9239 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s ",
9240 fmtId(tbinfo
->dobj
.name
));
9241 appendPQExpBuffer(q
, "ALTER COLUMN %s ",
9242 fmtId(tbinfo
->attnames
[j
]));
9243 appendPQExpBuffer(q
, "SET STORAGE %s;\n",
9250 ArchiveEntry(fout
, tbinfo
->dobj
.catId
, tbinfo
->dobj
.dumpId
,
9252 tbinfo
->dobj
.namespace->dobj
.name
,
9253 (tbinfo
->relkind
== RELKIND_VIEW
) ? NULL
: tbinfo
->reltablespace
,
9255 (strcmp(reltypename
, "TABLE") == 0) ? tbinfo
->hasoids
: false,
9256 reltypename
, q
->data
, delq
->data
, NULL
,
9257 tbinfo
->dobj
.dependencies
, tbinfo
->dobj
.nDeps
,
9260 /* Dump Table Comments */
9261 dumpTableComment(fout
, tbinfo
, reltypename
);
9263 /* Dump comments on inlined table constraints */
9264 for (j
= 0; j
< tbinfo
->ncheck
; j
++)
9266 ConstraintInfo
*constr
= &(tbinfo
->checkexprs
[j
]);
9268 if (constr
->separate
|| !constr
->conislocal
)
9271 dumpTableConstraintComment(fout
, constr
);
9274 destroyPQExpBuffer(query
);
9275 destroyPQExpBuffer(q
);
9276 destroyPQExpBuffer(delq
);
9280 * dumpAttrDef --- dump an attribute's default-value declaration
9283 dumpAttrDef(Archive
*fout
, AttrDefInfo
*adinfo
)
9285 TableInfo
*tbinfo
= adinfo
->adtable
;
9286 int adnum
= adinfo
->adnum
;
9290 /* Only print it if "separate" mode is selected */
9291 if (!tbinfo
->dobj
.dump
|| !adinfo
->separate
|| dataOnly
)
9294 /* Don't print inherited defaults, either */
9295 if (tbinfo
->inhAttrDef
[adnum
- 1])
9298 q
= createPQExpBuffer();
9299 delq
= createPQExpBuffer();
9301 appendPQExpBuffer(q
, "ALTER TABLE %s ",
9302 fmtId(tbinfo
->dobj
.name
));
9303 appendPQExpBuffer(q
, "ALTER COLUMN %s SET DEFAULT %s;\n",
9304 fmtId(tbinfo
->attnames
[adnum
- 1]),
9308 * DROP must be fully qualified in case same name appears in pg_catalog
9310 appendPQExpBuffer(delq
, "ALTER TABLE %s.",
9311 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9312 appendPQExpBuffer(delq
, "%s ",
9313 fmtId(tbinfo
->dobj
.name
));
9314 appendPQExpBuffer(delq
, "ALTER COLUMN %s DROP DEFAULT;\n",
9315 fmtId(tbinfo
->attnames
[adnum
- 1]));
9317 ArchiveEntry(fout
, adinfo
->dobj
.catId
, adinfo
->dobj
.dumpId
,
9318 tbinfo
->attnames
[adnum
- 1],
9319 tbinfo
->dobj
.namespace->dobj
.name
,
9322 false, "DEFAULT", q
->data
, delq
->data
, NULL
,
9323 adinfo
->dobj
.dependencies
, adinfo
->dobj
.nDeps
,
9326 destroyPQExpBuffer(q
);
9327 destroyPQExpBuffer(delq
);
9331 * getAttrName: extract the correct name for an attribute
9333 * The array tblInfo->attnames[] only provides names of user attributes;
9334 * if a system attribute number is supplied, we have to fake it.
9335 * We also do a little bit of bounds checking for safety's sake.
9338 getAttrName(int attrnum
, TableInfo
*tblInfo
)
9340 if (attrnum
> 0 && attrnum
<= tblInfo
->numatts
)
9341 return tblInfo
->attnames
[attrnum
- 1];
9344 case SelfItemPointerAttributeNumber
:
9346 case ObjectIdAttributeNumber
:
9348 case MinTransactionIdAttributeNumber
:
9350 case MinCommandIdAttributeNumber
:
9352 case MaxTransactionIdAttributeNumber
:
9354 case MaxCommandIdAttributeNumber
:
9356 case TableOidAttributeNumber
:
9359 write_msg(NULL
, "invalid column number %d for table \"%s\"\n",
9360 attrnum
, tblInfo
->dobj
.name
);
9362 return NULL
; /* keep compiler quiet */
9367 * write out to fout a user-defined index
9370 dumpIndex(Archive
*fout
, IndxInfo
*indxinfo
)
9372 TableInfo
*tbinfo
= indxinfo
->indextable
;
9379 q
= createPQExpBuffer();
9380 delq
= createPQExpBuffer();
9383 * If there's an associated constraint, don't dump the index per se, but
9384 * do dump any comment for it. (This is safe because dependency ordering
9385 * will have ensured the constraint is emitted first.)
9387 if (indxinfo
->indexconstraint
== 0)
9389 /* Plain secondary index */
9390 appendPQExpBuffer(q
, "%s;\n", indxinfo
->indexdef
);
9392 /* If the index is clustered, we need to record that. */
9393 if (indxinfo
->indisclustered
)
9395 appendPQExpBuffer(q
, "\nALTER TABLE %s CLUSTER",
9396 fmtId(tbinfo
->dobj
.name
));
9397 appendPQExpBuffer(q
, " ON %s;\n",
9398 fmtId(indxinfo
->dobj
.name
));
9402 * DROP must be fully qualified in case same name appears in
9405 appendPQExpBuffer(delq
, "DROP INDEX %s.",
9406 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9407 appendPQExpBuffer(delq
, "%s;\n",
9408 fmtId(indxinfo
->dobj
.name
));
9410 ArchiveEntry(fout
, indxinfo
->dobj
.catId
, indxinfo
->dobj
.dumpId
,
9411 indxinfo
->dobj
.name
,
9412 tbinfo
->dobj
.namespace->dobj
.name
,
9413 indxinfo
->tablespace
,
9414 tbinfo
->rolname
, false,
9415 "INDEX", q
->data
, delq
->data
, NULL
,
9416 indxinfo
->dobj
.dependencies
, indxinfo
->dobj
.nDeps
,
9420 /* Dump Index Comments */
9421 resetPQExpBuffer(q
);
9422 appendPQExpBuffer(q
, "INDEX %s",
9423 fmtId(indxinfo
->dobj
.name
));
9424 dumpComment(fout
, q
->data
,
9425 tbinfo
->dobj
.namespace->dobj
.name
,
9427 indxinfo
->dobj
.catId
, 0, indxinfo
->dobj
.dumpId
);
9429 destroyPQExpBuffer(q
);
9430 destroyPQExpBuffer(delq
);
9435 * write out to fout a user-defined constraint
9438 dumpConstraint(Archive
*fout
, ConstraintInfo
*coninfo
)
9440 TableInfo
*tbinfo
= coninfo
->contable
;
9444 /* Skip if not to be dumped */
9445 if (!coninfo
->dobj
.dump
|| dataOnly
)
9448 q
= createPQExpBuffer();
9449 delq
= createPQExpBuffer();
9451 if (coninfo
->contype
== 'p' || coninfo
->contype
== 'u')
9453 /* Index-related constraint */
9457 indxinfo
= (IndxInfo
*) findObjectByDumpId(coninfo
->conindex
);
9459 if (indxinfo
== NULL
)
9461 write_msg(NULL
, "missing index for constraint \"%s\"\n",
9462 coninfo
->dobj
.name
);
9466 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s\n",
9467 fmtId(tbinfo
->dobj
.name
));
9468 appendPQExpBuffer(q
, " ADD CONSTRAINT %s %s (",
9469 fmtId(coninfo
->dobj
.name
),
9470 coninfo
->contype
== 'p' ? "PRIMARY KEY" : "UNIQUE");
9472 for (k
= 0; k
< indxinfo
->indnkeys
; k
++)
9474 int indkey
= (int) indxinfo
->indkeys
[k
];
9475 const char *attname
;
9477 if (indkey
== InvalidAttrNumber
)
9479 attname
= getAttrName(indkey
, tbinfo
);
9481 appendPQExpBuffer(q
, "%s%s",
9482 (k
== 0) ? "" : ", ",
9486 appendPQExpBuffer(q
, ")");
9488 if (indxinfo
->options
&& strlen(indxinfo
->options
) > 0)
9489 appendPQExpBuffer(q
, " WITH (%s)", indxinfo
->options
);
9491 appendPQExpBuffer(q
, ";\n");
9493 /* If the index is clustered, we need to record that. */
9494 if (indxinfo
->indisclustered
)
9496 appendPQExpBuffer(q
, "\nALTER TABLE %s CLUSTER",
9497 fmtId(tbinfo
->dobj
.name
));
9498 appendPQExpBuffer(q
, " ON %s;\n",
9499 fmtId(indxinfo
->dobj
.name
));
9503 * DROP must be fully qualified in case same name appears in
9506 appendPQExpBuffer(delq
, "ALTER TABLE ONLY %s.",
9507 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9508 appendPQExpBuffer(delq
, "%s ",
9509 fmtId(tbinfo
->dobj
.name
));
9510 appendPQExpBuffer(delq
, "DROP CONSTRAINT %s;\n",
9511 fmtId(coninfo
->dobj
.name
));
9513 ArchiveEntry(fout
, coninfo
->dobj
.catId
, coninfo
->dobj
.dumpId
,
9515 tbinfo
->dobj
.namespace->dobj
.name
,
9516 indxinfo
->tablespace
,
9517 tbinfo
->rolname
, false,
9518 "CONSTRAINT", q
->data
, delq
->data
, NULL
,
9519 coninfo
->dobj
.dependencies
, coninfo
->dobj
.nDeps
,
9522 else if (coninfo
->contype
== 'f')
9525 * XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that the
9526 * current table data is not processed
9528 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s\n",
9529 fmtId(tbinfo
->dobj
.name
));
9530 appendPQExpBuffer(q
, " ADD CONSTRAINT %s %s;\n",
9531 fmtId(coninfo
->dobj
.name
),
9535 * DROP must be fully qualified in case same name appears in
9538 appendPQExpBuffer(delq
, "ALTER TABLE ONLY %s.",
9539 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9540 appendPQExpBuffer(delq
, "%s ",
9541 fmtId(tbinfo
->dobj
.name
));
9542 appendPQExpBuffer(delq
, "DROP CONSTRAINT %s;\n",
9543 fmtId(coninfo
->dobj
.name
));
9545 ArchiveEntry(fout
, coninfo
->dobj
.catId
, coninfo
->dobj
.dumpId
,
9547 tbinfo
->dobj
.namespace->dobj
.name
,
9549 tbinfo
->rolname
, false,
9550 "FK CONSTRAINT", q
->data
, delq
->data
, NULL
,
9551 coninfo
->dobj
.dependencies
, coninfo
->dobj
.nDeps
,
9554 else if (coninfo
->contype
== 'c' && tbinfo
)
9556 /* CHECK constraint on a table */
9558 /* Ignore if not to be dumped separately */
9559 if (coninfo
->separate
)
9561 /* not ONLY since we want it to propagate to children */
9562 appendPQExpBuffer(q
, "ALTER TABLE %s\n",
9563 fmtId(tbinfo
->dobj
.name
));
9564 appendPQExpBuffer(q
, " ADD CONSTRAINT %s %s;\n",
9565 fmtId(coninfo
->dobj
.name
),
9569 * DROP must be fully qualified in case same name appears in
9572 appendPQExpBuffer(delq
, "ALTER TABLE %s.",
9573 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9574 appendPQExpBuffer(delq
, "%s ",
9575 fmtId(tbinfo
->dobj
.name
));
9576 appendPQExpBuffer(delq
, "DROP CONSTRAINT %s;\n",
9577 fmtId(coninfo
->dobj
.name
));
9579 ArchiveEntry(fout
, coninfo
->dobj
.catId
, coninfo
->dobj
.dumpId
,
9581 tbinfo
->dobj
.namespace->dobj
.name
,
9583 tbinfo
->rolname
, false,
9584 "CHECK CONSTRAINT", q
->data
, delq
->data
, NULL
,
9585 coninfo
->dobj
.dependencies
, coninfo
->dobj
.nDeps
,
9589 else if (coninfo
->contype
== 'c' && tbinfo
== NULL
)
9591 /* CHECK constraint on a domain */
9592 TypeInfo
*tinfo
= coninfo
->condomain
;
9594 /* Ignore if not to be dumped separately */
9595 if (coninfo
->separate
)
9597 appendPQExpBuffer(q
, "ALTER DOMAIN %s\n",
9598 fmtId(tinfo
->dobj
.name
));
9599 appendPQExpBuffer(q
, " ADD CONSTRAINT %s %s;\n",
9600 fmtId(coninfo
->dobj
.name
),
9604 * DROP must be fully qualified in case same name appears in
9607 appendPQExpBuffer(delq
, "ALTER DOMAIN %s.",
9608 fmtId(tinfo
->dobj
.namespace->dobj
.name
));
9609 appendPQExpBuffer(delq
, "%s ",
9610 fmtId(tinfo
->dobj
.name
));
9611 appendPQExpBuffer(delq
, "DROP CONSTRAINT %s;\n",
9612 fmtId(coninfo
->dobj
.name
));
9614 ArchiveEntry(fout
, coninfo
->dobj
.catId
, coninfo
->dobj
.dumpId
,
9616 tinfo
->dobj
.namespace->dobj
.name
,
9618 tinfo
->rolname
, false,
9619 "CHECK CONSTRAINT", q
->data
, delq
->data
, NULL
,
9620 coninfo
->dobj
.dependencies
, coninfo
->dobj
.nDeps
,
9626 write_msg(NULL
, "unrecognized constraint type: %c\n", coninfo
->contype
);
9630 /* Dump Constraint Comments --- only works for table constraints */
9631 if (tbinfo
&& coninfo
->separate
)
9632 dumpTableConstraintComment(fout
, coninfo
);
9634 destroyPQExpBuffer(q
);
9635 destroyPQExpBuffer(delq
);
9639 * dumpTableConstraintComment --- dump a constraint's comment if any
9641 * This is split out because we need the function in two different places
9642 * depending on whether the constraint is dumped as part of CREATE TABLE
9643 * or as a separate ALTER command.
9646 dumpTableConstraintComment(Archive
*fout
, ConstraintInfo
*coninfo
)
9648 TableInfo
*tbinfo
= coninfo
->contable
;
9649 PQExpBuffer q
= createPQExpBuffer();
9651 appendPQExpBuffer(q
, "CONSTRAINT %s ",
9652 fmtId(coninfo
->dobj
.name
));
9653 appendPQExpBuffer(q
, "ON %s",
9654 fmtId(tbinfo
->dobj
.name
));
9655 dumpComment(fout
, q
->data
,
9656 tbinfo
->dobj
.namespace->dobj
.name
,
9658 coninfo
->dobj
.catId
, 0,
9659 coninfo
->separate
? coninfo
->dobj
.dumpId
: tbinfo
->dobj
.dumpId
);
9661 destroyPQExpBuffer(q
);
9665 * findLastBuiltInOid -
9666 * find the last built in oid
9668 * For 7.1 and 7.2, we do this by retrieving datlastsysoid from the
9669 * pg_database entry for the current database
9672 findLastBuiltinOid_V71(const char *dbname
)
9677 PQExpBuffer query
= createPQExpBuffer();
9679 resetPQExpBuffer(query
);
9680 appendPQExpBuffer(query
, "SELECT datlastsysoid from pg_database where datname = ");
9681 appendStringLiteralAH(query
, dbname
, g_fout
);
9683 res
= PQexec(g_conn
, query
->data
);
9684 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
9686 ntups
= PQntuples(res
);
9689 write_msg(NULL
, "missing pg_database entry for this database\n");
9694 write_msg(NULL
, "found more than one pg_database entry for this database\n");
9697 last_oid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "datlastsysoid")));
9699 destroyPQExpBuffer(query
);
9704 * findLastBuiltInOid -
9705 * find the last built in oid
9707 * For 7.0, we do this by assuming that the last thing that initdb does is to
9708 * create the pg_indexes view. This sucks in general, but seeing that 7.0.x
9709 * initdb won't be changing anymore, it'll do.
9712 findLastBuiltinOid_V70(void)
9718 res
= PQexec(g_conn
,
9719 "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'");
9720 check_sql_result(res
, g_conn
,
9721 "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'",
9723 ntups
= PQntuples(res
);
9726 write_msg(NULL
, "could not find entry for pg_indexes in pg_class\n");
9731 write_msg(NULL
, "found more than one entry for pg_indexes in pg_class\n");
9734 last_oid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "oid")));
9740 dumpSequence(Archive
*fout
, TableInfo
*tbinfo
)
9753 PQExpBuffer query
= createPQExpBuffer();
9754 PQExpBuffer delqry
= createPQExpBuffer();
9756 /* Make sure we are in proper schema */
9757 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
9759 snprintf(bufm
, sizeof(bufm
), INT64_FORMAT
, SEQ_MINVALUE
);
9760 snprintf(bufx
, sizeof(bufx
), INT64_FORMAT
, SEQ_MAXVALUE
);
9762 if (g_fout
->remoteVersion
>= 80400)
9764 appendPQExpBuffer(query
,
9765 "SELECT sequence_name, "
9766 "start_value, last_value, increment_by, "
9767 "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
9768 " WHEN increment_by < 0 AND max_value = -1 THEN NULL "
9770 "END AS max_value, "
9771 "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
9772 " WHEN increment_by < 0 AND min_value = %s THEN NULL "
9774 "END AS min_value, "
9775 "cache_value, is_cycled, is_called from %s",
9777 fmtId(tbinfo
->dobj
.name
));
9781 appendPQExpBuffer(query
,
9782 "SELECT sequence_name, "
9783 "0 as start_value, last_value, increment_by, "
9784 "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
9785 " WHEN increment_by < 0 AND max_value = -1 THEN NULL "
9787 "END AS max_value, "
9788 "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
9789 " WHEN increment_by < 0 AND min_value = %s THEN NULL "
9791 "END AS min_value, "
9792 "cache_value, is_cycled, is_called from %s",
9794 fmtId(tbinfo
->dobj
.name
));
9797 res
= PQexec(g_conn
, query
->data
);
9798 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
9800 if (PQntuples(res
) != 1)
9802 write_msg(NULL
, "query to get data of sequence \"%s\" returned %d rows (expected 1)\n",
9803 tbinfo
->dobj
.name
, PQntuples(res
));
9807 /* Disable this check: it fails if sequence has been renamed */
9809 if (strcmp(PQgetvalue(res
, 0, 0), tbinfo
->dobj
.name
) != 0)
9811 write_msg(NULL
, "query to get data of sequence \"%s\" returned name \"%s\"\n",
9812 tbinfo
->dobj
.name
, PQgetvalue(res
, 0, 0));
9817 startv
= PQgetvalue(res
, 0, 1);
9818 last
= PQgetvalue(res
, 0, 2);
9819 incby
= PQgetvalue(res
, 0, 3);
9820 if (!PQgetisnull(res
, 0, 4))
9821 maxv
= PQgetvalue(res
, 0, 4);
9822 if (!PQgetisnull(res
, 0, 5))
9823 minv
= PQgetvalue(res
, 0, 5);
9824 cache
= PQgetvalue(res
, 0, 6);
9825 cycled
= (strcmp(PQgetvalue(res
, 0, 7), "t") == 0);
9826 called
= (strcmp(PQgetvalue(res
, 0, 8), "t") == 0);
9829 * The logic we use for restoring sequences is as follows:
9831 * Add a CREATE SEQUENCE statement as part of a "schema" dump (use
9832 * last_val for start if called is false, else use min_val for start_val).
9833 * Also, if the sequence is owned by a column, add an ALTER SEQUENCE OWNED
9834 * BY command for it.
9836 * Add a 'SETVAL(seq, last_val, iscalled)' as part of a "data" dump.
9840 resetPQExpBuffer(delqry
);
9843 * DROP must be fully qualified in case same name appears in
9846 appendPQExpBuffer(delqry
, "DROP SEQUENCE %s.",
9847 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9848 appendPQExpBuffer(delqry
, "%s;\n",
9849 fmtId(tbinfo
->dobj
.name
));
9851 resetPQExpBuffer(query
);
9852 appendPQExpBuffer(query
,
9853 "CREATE SEQUENCE %s\n",
9854 fmtId(tbinfo
->dobj
.name
));
9856 if (g_fout
->remoteVersion
>= 80400)
9857 appendPQExpBuffer(query
, " START WITH %s\n", startv
);
9861 * Versions before 8.4 did not remember the true start value. If
9862 * is_called is false then the sequence has never been incremented
9863 * so we can use last_val. Otherwise punt and let it default.
9866 appendPQExpBuffer(query
, " START WITH %s\n", last
);
9869 appendPQExpBuffer(query
, " INCREMENT BY %s\n", incby
);
9872 appendPQExpBuffer(query
, " MAXVALUE %s\n", maxv
);
9874 appendPQExpBuffer(query
, " NO MAXVALUE\n");
9877 appendPQExpBuffer(query
, " MINVALUE %s\n", minv
);
9879 appendPQExpBuffer(query
, " NO MINVALUE\n");
9881 appendPQExpBuffer(query
,
9883 cache
, (cycled
? "\n CYCLE" : ""));
9885 appendPQExpBuffer(query
, ";\n");
9887 ArchiveEntry(fout
, tbinfo
->dobj
.catId
, tbinfo
->dobj
.dumpId
,
9889 tbinfo
->dobj
.namespace->dobj
.name
,
9892 false, "SEQUENCE", query
->data
, delqry
->data
, NULL
,
9893 tbinfo
->dobj
.dependencies
, tbinfo
->dobj
.nDeps
,
9897 * If the sequence is owned by a table column, emit the ALTER for it
9898 * as a separate TOC entry immediately following the sequence's own
9899 * entry. It's OK to do this rather than using full sorting logic,
9900 * because the dependency that tells us it's owned will have forced
9901 * the table to be created first. We can't just include the ALTER in
9902 * the TOC entry because it will fail if we haven't reassigned the
9903 * sequence owner to match the table's owner.
9905 * We need not schema-qualify the table reference because both
9906 * sequence and table must be in the same schema.
9908 if (OidIsValid(tbinfo
->owning_tab
))
9910 TableInfo
*owning_tab
= findTableByOid(tbinfo
->owning_tab
);
9912 if (owning_tab
&& owning_tab
->dobj
.dump
)
9914 resetPQExpBuffer(query
);
9915 appendPQExpBuffer(query
, "ALTER SEQUENCE %s",
9916 fmtId(tbinfo
->dobj
.name
));
9917 appendPQExpBuffer(query
, " OWNED BY %s",
9918 fmtId(owning_tab
->dobj
.name
));
9919 appendPQExpBuffer(query
, ".%s;\n",
9920 fmtId(owning_tab
->attnames
[tbinfo
->owning_col
- 1]));
9922 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
9924 tbinfo
->dobj
.namespace->dobj
.name
,
9927 false, "SEQUENCE OWNED BY", query
->data
, "", NULL
,
9928 &(tbinfo
->dobj
.dumpId
), 1,
9933 /* Dump Sequence Comments */
9934 resetPQExpBuffer(query
);
9935 appendPQExpBuffer(query
, "SEQUENCE %s", fmtId(tbinfo
->dobj
.name
));
9936 dumpComment(fout
, query
->data
,
9937 tbinfo
->dobj
.namespace->dobj
.name
, tbinfo
->rolname
,
9938 tbinfo
->dobj
.catId
, 0, tbinfo
->dobj
.dumpId
);
9943 resetPQExpBuffer(query
);
9944 appendPQExpBuffer(query
, "SELECT pg_catalog.setval(");
9945 appendStringLiteralAH(query
, fmtId(tbinfo
->dobj
.name
), fout
);
9946 appendPQExpBuffer(query
, ", %s, %s);\n",
9947 last
, (called
? "true" : "false"));
9949 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
9951 tbinfo
->dobj
.namespace->dobj
.name
,
9954 false, "SEQUENCE SET", query
->data
, "", NULL
,
9955 &(tbinfo
->dobj
.dumpId
), 1,
9961 destroyPQExpBuffer(query
);
9962 destroyPQExpBuffer(delqry
);
9966 dumpTrigger(Archive
*fout
, TriggerInfo
*tginfo
)
9968 TableInfo
*tbinfo
= tginfo
->tgtable
;
9977 query
= createPQExpBuffer();
9978 delqry
= createPQExpBuffer();
9981 * DROP must be fully qualified in case same name appears in pg_catalog
9983 appendPQExpBuffer(delqry
, "DROP TRIGGER %s ",
9984 fmtId(tginfo
->dobj
.name
));
9985 appendPQExpBuffer(delqry
, "ON %s.",
9986 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9987 appendPQExpBuffer(delqry
, "%s;\n",
9988 fmtId(tbinfo
->dobj
.name
));
9990 if (tginfo
->tgisconstraint
)
9992 appendPQExpBuffer(query
, "CREATE CONSTRAINT TRIGGER ");
9993 appendPQExpBufferStr(query
, fmtId(tginfo
->tgconstrname
));
9997 appendPQExpBuffer(query
, "CREATE TRIGGER ");
9998 appendPQExpBufferStr(query
, fmtId(tginfo
->dobj
.name
));
10000 appendPQExpBuffer(query
, "\n ");
10004 if (TRIGGER_FOR_BEFORE(tginfo
->tgtype
))
10005 appendPQExpBuffer(query
, "BEFORE");
10007 appendPQExpBuffer(query
, "AFTER");
10008 if (TRIGGER_FOR_INSERT(tginfo
->tgtype
))
10010 appendPQExpBuffer(query
, " INSERT");
10013 if (TRIGGER_FOR_DELETE(tginfo
->tgtype
))
10016 appendPQExpBuffer(query
, " OR DELETE");
10018 appendPQExpBuffer(query
, " DELETE");
10021 if (TRIGGER_FOR_UPDATE(tginfo
->tgtype
))
10024 appendPQExpBuffer(query
, " OR UPDATE");
10026 appendPQExpBuffer(query
, " UPDATE");
10028 if (TRIGGER_FOR_TRUNCATE(tginfo
->tgtype
))
10031 appendPQExpBuffer(query
, " OR TRUNCATE");
10033 appendPQExpBuffer(query
, " TRUNCATE");
10035 appendPQExpBuffer(query
, " ON %s\n",
10036 fmtId(tbinfo
->dobj
.name
));
10038 if (tginfo
->tgisconstraint
)
10040 if (OidIsValid(tginfo
->tgconstrrelid
))
10042 /* If we are using regclass, name is already quoted */
10043 if (g_fout
->remoteVersion
>= 70300)
10044 appendPQExpBuffer(query
, " FROM %s\n ",
10045 tginfo
->tgconstrrelname
);
10047 appendPQExpBuffer(query
, " FROM %s\n ",
10048 fmtId(tginfo
->tgconstrrelname
));
10050 if (!tginfo
->tgdeferrable
)
10051 appendPQExpBuffer(query
, "NOT ");
10052 appendPQExpBuffer(query
, "DEFERRABLE INITIALLY ");
10053 if (tginfo
->tginitdeferred
)
10054 appendPQExpBuffer(query
, "DEFERRED\n");
10056 appendPQExpBuffer(query
, "IMMEDIATE\n");
10059 if (TRIGGER_FOR_ROW(tginfo
->tgtype
))
10060 appendPQExpBuffer(query
, " FOR EACH ROW\n ");
10062 appendPQExpBuffer(query
, " FOR EACH STATEMENT\n ");
10064 /* In 7.3, result of regproc is already quoted */
10065 if (g_fout
->remoteVersion
>= 70300)
10066 appendPQExpBuffer(query
, "EXECUTE PROCEDURE %s(",
10069 appendPQExpBuffer(query
, "EXECUTE PROCEDURE %s(",
10070 fmtId(tginfo
->tgfname
));
10072 p
= tginfo
->tgargs
;
10073 for (findx
= 0; findx
< tginfo
->tgnargs
; findx
++)
10077 /* Set 'p' to end of arg string. marked by '\000' */
10080 p
= strchr(p
, '\\');
10083 write_msg(NULL
, "invalid argument string (%s) for trigger \"%s\" on table \"%s\"\n",
10086 tbinfo
->dobj
.name
);
10090 if (*p
== '\\') /* is it '\\'? */
10095 if (p
[0] == '0' && p
[1] == '0' && p
[2] == '0') /* is it '\000'? */
10100 appendPQExpBufferChar(query
, '\'');
10104 appendPQExpBufferChar(query
, '\'');
10107 * bytea unconditionally doubles backslashes, so we suppress the
10108 * doubling for standard_conforming_strings.
10110 if (fout
->std_strings
&& *s
== '\\' && s
[1] == '\\')
10112 appendPQExpBufferChar(query
, *s
++);
10114 appendPQExpBufferChar(query
, '\'');
10115 appendPQExpBuffer(query
,
10116 (findx
< tginfo
->tgnargs
- 1) ? ", " : "");
10119 appendPQExpBuffer(query
, ");\n");
10121 if (tginfo
->tgenabled
!= 't' && tginfo
->tgenabled
!= 'O')
10123 appendPQExpBuffer(query
, "\nALTER TABLE %s ",
10124 fmtId(tbinfo
->dobj
.name
));
10125 switch (tginfo
->tgenabled
)
10129 appendPQExpBuffer(query
, "DISABLE");
10132 appendPQExpBuffer(query
, "ENABLE ALWAYS");
10135 appendPQExpBuffer(query
, "ENABLE REPLICA");
10138 appendPQExpBuffer(query
, "ENABLE");
10141 appendPQExpBuffer(query
, " TRIGGER %s;\n",
10142 fmtId(tginfo
->dobj
.name
));
10145 ArchiveEntry(fout
, tginfo
->dobj
.catId
, tginfo
->dobj
.dumpId
,
10147 tbinfo
->dobj
.namespace->dobj
.name
,
10149 tbinfo
->rolname
, false,
10150 "TRIGGER", query
->data
, delqry
->data
, NULL
,
10151 tginfo
->dobj
.dependencies
, tginfo
->dobj
.nDeps
,
10154 resetPQExpBuffer(query
);
10155 appendPQExpBuffer(query
, "TRIGGER %s ",
10156 fmtId(tginfo
->dobj
.name
));
10157 appendPQExpBuffer(query
, "ON %s",
10158 fmtId(tbinfo
->dobj
.name
));
10160 dumpComment(fout
, query
->data
,
10161 tbinfo
->dobj
.namespace->dobj
.name
, tbinfo
->rolname
,
10162 tginfo
->dobj
.catId
, 0, tginfo
->dobj
.dumpId
);
10164 destroyPQExpBuffer(query
);
10165 destroyPQExpBuffer(delqry
);
10173 dumpRule(Archive
*fout
, RuleInfo
*rinfo
)
10175 TableInfo
*tbinfo
= rinfo
->ruletable
;
10178 PQExpBuffer delcmd
;
10181 /* Skip if not to be dumped */
10182 if (!rinfo
->dobj
.dump
|| dataOnly
)
10186 * If it is an ON SELECT rule that is created implicitly by CREATE VIEW,
10187 * we do not want to dump it as a separate object.
10189 if (!rinfo
->separate
)
10193 * Make sure we are in proper schema.
10195 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
10197 query
= createPQExpBuffer();
10198 cmd
= createPQExpBuffer();
10199 delcmd
= createPQExpBuffer();
10201 if (g_fout
->remoteVersion
>= 70300)
10203 appendPQExpBuffer(query
,
10204 "SELECT pg_catalog.pg_get_ruledef('%u'::pg_catalog.oid) AS definition",
10205 rinfo
->dobj
.catId
.oid
);
10209 /* Rule name was unique before 7.3 ... */
10210 appendPQExpBuffer(query
,
10211 "SELECT pg_get_ruledef('%s') AS definition",
10215 res
= PQexec(g_conn
, query
->data
);
10216 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
10218 if (PQntuples(res
) != 1)
10220 write_msg(NULL
, "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned\n",
10221 rinfo
->dobj
.name
, tbinfo
->dobj
.name
);
10225 printfPQExpBuffer(cmd
, "%s\n", PQgetvalue(res
, 0, 0));
10228 * Add the command to alter the rules replication firing semantics if it
10229 * differs from the default.
10231 if (rinfo
->ev_enabled
!= 'O')
10233 appendPQExpBuffer(cmd
, "ALTER TABLE %s.",
10234 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
10235 appendPQExpBuffer(cmd
, "%s ",
10236 fmtId(tbinfo
->dobj
.name
));
10237 switch (rinfo
->ev_enabled
)
10240 appendPQExpBuffer(cmd
, "ENABLE ALWAYS RULE %s;\n",
10241 fmtId(rinfo
->dobj
.name
));
10244 appendPQExpBuffer(cmd
, "ENABLE REPLICA RULE %s;\n",
10245 fmtId(rinfo
->dobj
.name
));
10248 appendPQExpBuffer(cmd
, "DISABLE RULE %s;\n",
10249 fmtId(rinfo
->dobj
.name
));
10255 * DROP must be fully qualified in case same name appears in pg_catalog
10257 appendPQExpBuffer(delcmd
, "DROP RULE %s ",
10258 fmtId(rinfo
->dobj
.name
));
10259 appendPQExpBuffer(delcmd
, "ON %s.",
10260 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
10261 appendPQExpBuffer(delcmd
, "%s;\n",
10262 fmtId(tbinfo
->dobj
.name
));
10264 ArchiveEntry(fout
, rinfo
->dobj
.catId
, rinfo
->dobj
.dumpId
,
10266 tbinfo
->dobj
.namespace->dobj
.name
,
10268 tbinfo
->rolname
, false,
10269 "RULE", cmd
->data
, delcmd
->data
, NULL
,
10270 rinfo
->dobj
.dependencies
, rinfo
->dobj
.nDeps
,
10273 /* Dump rule comments */
10274 resetPQExpBuffer(query
);
10275 appendPQExpBuffer(query
, "RULE %s",
10276 fmtId(rinfo
->dobj
.name
));
10277 appendPQExpBuffer(query
, " ON %s",
10278 fmtId(tbinfo
->dobj
.name
));
10279 dumpComment(fout
, query
->data
,
10280 tbinfo
->dobj
.namespace->dobj
.name
,
10282 rinfo
->dobj
.catId
, 0, rinfo
->dobj
.dumpId
);
10286 destroyPQExpBuffer(query
);
10287 destroyPQExpBuffer(cmd
);
10288 destroyPQExpBuffer(delcmd
);
10292 * getDependencies --- obtain available dependency data
10295 getDependencies(void)
10306 DumpableObject
*dobj
,
10309 /* No dependency info available before 7.3 */
10310 if (g_fout
->remoteVersion
< 70300)
10314 write_msg(NULL
, "reading dependency data\n");
10316 /* Make sure we are in proper schema */
10317 selectSourceSchema("pg_catalog");
10319 query
= createPQExpBuffer();
10321 appendPQExpBuffer(query
, "SELECT "
10322 "classid, objid, refclassid, refobjid, deptype "
10324 "WHERE deptype != 'p' "
10327 res
= PQexec(g_conn
, query
->data
);
10328 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
10330 ntups
= PQntuples(res
);
10332 i_classid
= PQfnumber(res
, "classid");
10333 i_objid
= PQfnumber(res
, "objid");
10334 i_refclassid
= PQfnumber(res
, "refclassid");
10335 i_refobjid
= PQfnumber(res
, "refobjid");
10336 i_deptype
= PQfnumber(res
, "deptype");
10339 * Since we ordered the SELECT by referencing ID, we can expect that
10340 * multiple entries for the same object will appear together; this saves
10345 for (i
= 0; i
< ntups
; i
++)
10348 CatalogId refobjId
;
10351 objId
.tableoid
= atooid(PQgetvalue(res
, i
, i_classid
));
10352 objId
.oid
= atooid(PQgetvalue(res
, i
, i_objid
));
10353 refobjId
.tableoid
= atooid(PQgetvalue(res
, i
, i_refclassid
));
10354 refobjId
.oid
= atooid(PQgetvalue(res
, i
, i_refobjid
));
10355 deptype
= *(PQgetvalue(res
, i
, i_deptype
));
10357 if (dobj
== NULL
||
10358 dobj
->catId
.tableoid
!= objId
.tableoid
||
10359 dobj
->catId
.oid
!= objId
.oid
)
10360 dobj
= findObjectByCatalogId(objId
);
10363 * Failure to find objects mentioned in pg_depend is not unexpected,
10364 * since for example we don't collect info about TOAST tables.
10369 fprintf(stderr
, "no referencing object %u %u\n",
10370 objId
.tableoid
, objId
.oid
);
10375 refdobj
= findObjectByCatalogId(refobjId
);
10377 if (refdobj
== NULL
)
10380 fprintf(stderr
, "no referenced object %u %u\n",
10381 refobjId
.tableoid
, refobjId
.oid
);
10387 * Ordinarily, table rowtypes have implicit dependencies on their
10388 * tables. However, for a composite type the implicit dependency goes
10389 * the other way in pg_depend; which is the right thing for DROP but
10390 * it doesn't produce the dependency ordering we need. So in that one
10391 * case, we reverse the direction of the dependency.
10393 if (deptype
== 'i' &&
10394 dobj
->objType
== DO_TABLE
&&
10395 refdobj
->objType
== DO_TYPE
)
10396 addObjectDependency(refdobj
, dobj
->dumpId
);
10399 addObjectDependency(dobj
, refdobj
->dumpId
);
10404 destroyPQExpBuffer(query
);
10409 * selectSourceSchema - make the specified schema the active search path
10410 * in the source database.
10412 * NB: pg_catalog is explicitly searched after the specified schema;
10413 * so user names are only qualified if they are cross-schema references,
10414 * and system names are only qualified if they conflict with a user name
10415 * in the current schema.
10417 * Whenever the selected schema is not pg_catalog, be careful to qualify
10418 * references to system catalogs and types in our emitted commands!
10421 selectSourceSchema(const char *schemaName
)
10423 static char *curSchemaName
= NULL
;
10426 /* Not relevant if fetching from pre-7.3 DB */
10427 if (g_fout
->remoteVersion
< 70300)
10429 /* Ignore null schema names */
10430 if (schemaName
== NULL
|| *schemaName
== '\0')
10432 /* Optimize away repeated selection of same schema */
10433 if (curSchemaName
&& strcmp(curSchemaName
, schemaName
) == 0)
10436 query
= createPQExpBuffer();
10437 appendPQExpBuffer(query
, "SET search_path = %s",
10438 fmtId(schemaName
));
10439 if (strcmp(schemaName
, "pg_catalog") != 0)
10440 appendPQExpBuffer(query
, ", pg_catalog");
10442 do_sql_command(g_conn
, query
->data
);
10444 destroyPQExpBuffer(query
);
10446 free(curSchemaName
);
10447 curSchemaName
= strdup(schemaName
);
10451 * getFormattedTypeName - retrieve a nicely-formatted type name for the
10454 * NB: in 7.3 and up the result may depend on the currently-selected
10455 * schema; this is why we don't try to cache the names.
10458 getFormattedTypeName(Oid oid
, OidOptions opts
)
10467 if ((opts
& zeroAsOpaque
) != 0)
10468 return strdup(g_opaque_type
);
10469 else if ((opts
& zeroAsAny
) != 0)
10470 return strdup("'any'");
10471 else if ((opts
& zeroAsStar
) != 0)
10472 return strdup("*");
10473 else if ((opts
& zeroAsNone
) != 0)
10474 return strdup("NONE");
10477 query
= createPQExpBuffer();
10478 if (g_fout
->remoteVersion
>= 70300)
10480 appendPQExpBuffer(query
, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)",
10483 else if (g_fout
->remoteVersion
>= 70100)
10485 appendPQExpBuffer(query
, "SELECT format_type('%u'::oid, NULL)",
10490 appendPQExpBuffer(query
, "SELECT typname "
10492 "WHERE oid = '%u'::oid",
10496 res
= PQexec(g_conn
, query
->data
);
10497 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
10499 /* Expecting a single result only */
10500 ntups
= PQntuples(res
);
10503 write_msg(NULL
, "query returned %d rows instead of one: %s\n",
10504 ntups
, query
->data
);
10508 if (g_fout
->remoteVersion
>= 70100)
10510 /* already quoted */
10511 result
= strdup(PQgetvalue(res
, 0, 0));
10515 /* may need to quote it */
10516 result
= strdup(fmtId(PQgetvalue(res
, 0, 0)));
10520 destroyPQExpBuffer(query
);
10526 * myFormatType --- local implementation of format_type for use with 7.0.
10529 myFormatType(const char *typname
, int32 typmod
)
10532 bool isarray
= false;
10533 PQExpBuffer buf
= createPQExpBuffer();
10535 /* Handle array types */
10536 if (typname
[0] == '_')
10542 /* Show lengths on bpchar and varchar */
10543 if (!strcmp(typname
, "bpchar"))
10545 int len
= (typmod
- VARHDRSZ
);
10547 appendPQExpBuffer(buf
, "character");
10549 appendPQExpBuffer(buf
, "(%d)",
10550 typmod
- VARHDRSZ
);
10552 else if (!strcmp(typname
, "varchar"))
10554 appendPQExpBuffer(buf
, "character varying");
10556 appendPQExpBuffer(buf
, "(%d)",
10557 typmod
- VARHDRSZ
);
10559 else if (!strcmp(typname
, "numeric"))
10561 appendPQExpBuffer(buf
, "numeric");
10568 tmp_typmod
= typmod
- VARHDRSZ
;
10569 precision
= (tmp_typmod
>> 16) & 0xffff;
10570 scale
= tmp_typmod
& 0xffff;
10571 appendPQExpBuffer(buf
, "(%d,%d)",
10577 * char is an internal single-byte data type; Let's make sure we force it
10578 * through with quotes. - thomas 1998-12-13
10580 else if (strcmp(typname
, "char") == 0)
10581 appendPQExpBuffer(buf
, "\"char\"");
10583 appendPQExpBuffer(buf
, "%s", fmtId(typname
));
10585 /* Append array qualifier for array types */
10587 appendPQExpBuffer(buf
, "[]");
10589 result
= strdup(buf
->data
);
10590 destroyPQExpBuffer(buf
);
10596 * fmtQualifiedId - convert a qualified name to the proper format for
10597 * the source database.
10599 * Like fmtId, use the result before calling again.
10601 static const char *
10602 fmtQualifiedId(const char *schema
, const char *id
)
10604 static PQExpBuffer id_return
= NULL
;
10606 if (id_return
) /* first time through? */
10607 resetPQExpBuffer(id_return
);
10609 id_return
= createPQExpBuffer();
10611 /* Suppress schema name if fetching from pre-7.3 DB */
10612 if (g_fout
->remoteVersion
>= 70300 && schema
&& *schema
)
10614 appendPQExpBuffer(id_return
, "%s.",
10617 appendPQExpBuffer(id_return
, "%s",
10620 return id_return
->data
;
10624 * Return a column list clause for the given relation.
10626 * Special case: if there are no undropped columns in the relation, return
10627 * "", not an invalid "()" column list.
10629 static const char *
10630 fmtCopyColumnList(const TableInfo
*ti
)
10632 static PQExpBuffer q
= NULL
;
10633 int numatts
= ti
->numatts
;
10634 char **attnames
= ti
->attnames
;
10635 bool *attisdropped
= ti
->attisdropped
;
10639 if (q
) /* first time through? */
10640 resetPQExpBuffer(q
);
10642 q
= createPQExpBuffer();
10644 appendPQExpBuffer(q
, "(");
10646 for (i
= 0; i
< numatts
; i
++)
10648 if (attisdropped
[i
])
10651 appendPQExpBuffer(q
, ", ");
10652 appendPQExpBuffer(q
, "%s", fmtId(attnames
[i
]));
10657 return ""; /* no undropped columns */
10659 appendPQExpBuffer(q
, ")");
10664 * Convenience subroutine to execute a SQL command and check for
10665 * COMMAND_OK status.
10668 do_sql_command(PGconn
*conn
, const char *query
)
10672 res
= PQexec(conn
, query
);
10673 check_sql_result(res
, conn
, query
, PGRES_COMMAND_OK
);
10678 * Convenience subroutine to verify a SQL command succeeded,
10679 * and exit with a useful error message if not.
10682 check_sql_result(PGresult
*res
, PGconn
*conn
, const char *query
,
10683 ExecStatusType expected
)
10687 if (res
&& PQresultStatus(res
) == expected
)
10690 write_msg(NULL
, "SQL command failed\n");
10692 err
= PQresultErrorMessage(res
);
10694 err
= PQerrorMessage(conn
);
10695 write_msg(NULL
, "Error message from server: %s", err
);
10696 write_msg(NULL
, "The command was: %s\n", query
);