1 /*-------------------------------------------------------------------------
4 * pg_dump is a utility for dumping out a postgres database
7 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
10 * pg_dump will read the system catalogs in a database and dump out a
11 * script that reproduces the schema in terms of SQL that is understood
17 *-------------------------------------------------------------------------
20 #include "postgres_fe.h"
31 #include "getopt_long.h"
33 #include "access/attnum.h"
34 #include "access/sysattr.h"
35 #include "catalog/pg_cast.h"
36 #include "catalog/pg_class.h"
37 #include "catalog/pg_proc.h"
38 #include "catalog/pg_trigger.h"
39 #include "catalog/pg_type.h"
40 #include "libpq/libpq-fs.h"
42 #include "pg_backup_archiver.h"
43 #include "dumputils.h"
52 const char *descr
; /* comment for an object */
53 Oid classoid
; /* object class (catalog OID) */
54 Oid objoid
; /* object OID */
55 int objsubid
; /* subobject (table column #) */
60 bool g_verbose
; /* User wants verbose narration of our
62 Archive
*g_fout
; /* the script file */
63 PGconn
*g_conn
; /* the database connection */
65 /* various user-settable parameters */
69 const char *lockWaitTimeout
;
71 /* subquery used to convert user ID (eg, datdba) to user name */
72 static const char *username_subquery
;
74 /* obsolete as of 7.3: */
75 static Oid g_last_builtin_oid
; /* value of the last builtin oid */
78 * Object inclusion/exclusion lists
80 * The string lists record the patterns given by command-line switches,
81 * which we then convert to lists of OIDs of matching objects.
83 static SimpleStringList schema_include_patterns
= {NULL
, NULL
};
84 static SimpleOidList schema_include_oids
= {NULL
, NULL
};
85 static SimpleStringList schema_exclude_patterns
= {NULL
, NULL
};
86 static SimpleOidList schema_exclude_oids
= {NULL
, NULL
};
88 static SimpleStringList table_include_patterns
= {NULL
, NULL
};
89 static SimpleOidList table_include_oids
= {NULL
, NULL
};
90 static SimpleStringList table_exclude_patterns
= {NULL
, NULL
};
91 static SimpleOidList table_exclude_oids
= {NULL
, NULL
};
93 /* default, if no "inclusion" switches appear, is to dump everything */
94 static bool include_everything
= true;
96 char g_opaque_type
[10]; /* name for the opaque type */
98 /* placeholders for the delimiters for comments */
99 char g_comment_start
[10];
100 char g_comment_end
[10];
102 static const CatalogId nilCatalogId
= {0, 0};
104 /* these are to avoid passing around info for findNamespace() */
105 static NamespaceInfo
*g_namespaces
;
106 static int g_numNamespaces
;
108 /* flags for various command-line long options */
109 static int binary_upgrade
= 0;
110 static int disable_dollar_quoting
= 0;
111 static int dump_inserts
= 0;
112 static int column_inserts
= 0;
115 static void help(const char *progname
);
116 static void expand_schema_name_patterns(SimpleStringList
*patterns
,
117 SimpleOidList
*oids
);
118 static void expand_table_name_patterns(SimpleStringList
*patterns
,
119 SimpleOidList
*oids
);
120 static NamespaceInfo
*findNamespace(Oid nsoid
, Oid objoid
);
121 static void dumpTableData(Archive
*fout
, TableDataInfo
*tdinfo
);
122 static void guessConstraintInheritance(TableInfo
*tblinfo
, int numTables
);
123 static void dumpComment(Archive
*fout
, const char *target
,
124 const char *namespace, const char *owner
,
125 CatalogId catalogId
, int subid
, DumpId dumpId
);
126 static int findComments(Archive
*fout
, Oid classoid
, Oid objoid
,
127 CommentItem
**items
);
128 static int collectComments(Archive
*fout
, CommentItem
**items
);
129 static void dumpDumpableObject(Archive
*fout
, DumpableObject
*dobj
);
130 static void dumpNamespace(Archive
*fout
, NamespaceInfo
*nspinfo
);
131 static void dumpType(Archive
*fout
, TypeInfo
*tinfo
);
132 static void dumpBaseType(Archive
*fout
, TypeInfo
*tinfo
);
133 static void dumpEnumType(Archive
*fout
, TypeInfo
*tinfo
);
134 static void dumpDomain(Archive
*fout
, TypeInfo
*tinfo
);
135 static void dumpCompositeType(Archive
*fout
, TypeInfo
*tinfo
);
136 static void dumpShellType(Archive
*fout
, ShellTypeInfo
*stinfo
);
137 static void dumpProcLang(Archive
*fout
, ProcLangInfo
*plang
);
138 static void dumpFunc(Archive
*fout
, FuncInfo
*finfo
);
139 static void dumpCast(Archive
*fout
, CastInfo
*cast
);
140 static void dumpOpr(Archive
*fout
, OprInfo
*oprinfo
);
141 static void dumpOpclass(Archive
*fout
, OpclassInfo
*opcinfo
);
142 static void dumpOpfamily(Archive
*fout
, OpfamilyInfo
*opfinfo
);
143 static void dumpConversion(Archive
*fout
, ConvInfo
*convinfo
);
144 static void dumpRule(Archive
*fout
, RuleInfo
*rinfo
);
145 static void dumpAgg(Archive
*fout
, AggInfo
*agginfo
);
146 static void dumpTrigger(Archive
*fout
, TriggerInfo
*tginfo
);
147 static void dumpTable(Archive
*fout
, TableInfo
*tbinfo
);
148 static void dumpTableSchema(Archive
*fout
, TableInfo
*tbinfo
);
149 static void dumpAttrDef(Archive
*fout
, AttrDefInfo
*adinfo
);
150 static void dumpSequence(Archive
*fout
, TableInfo
*tbinfo
);
151 static void dumpIndex(Archive
*fout
, IndxInfo
*indxinfo
);
152 static void dumpConstraint(Archive
*fout
, ConstraintInfo
*coninfo
);
153 static void dumpTableConstraintComment(Archive
*fout
, ConstraintInfo
*coninfo
);
154 static void dumpTSParser(Archive
*fout
, TSParserInfo
*prsinfo
);
155 static void dumpTSDictionary(Archive
*fout
, TSDictInfo
*dictinfo
);
156 static void dumpTSTemplate(Archive
*fout
, TSTemplateInfo
*tmplinfo
);
157 static void dumpTSConfig(Archive
*fout
, TSConfigInfo
*cfginfo
);
158 static void dumpForeignDataWrapper(Archive
*fout
, FdwInfo
*fdwinfo
);
159 static void dumpForeignServer(Archive
*fout
, ForeignServerInfo
*srvinfo
);
160 static void dumpUserMappings(Archive
*fout
, const char *target
,
161 const char *servername
, const char *namespace,
162 const char *owner
, CatalogId catalogId
, DumpId dumpId
);
164 static void dumpACL(Archive
*fout
, CatalogId objCatId
, DumpId objDumpId
,
165 const char *type
, const char *name
, const char *subname
,
166 const char *tag
, const char *nspname
, const char *owner
,
169 static void getDependencies(void);
170 static void getDomainConstraints(TypeInfo
*tinfo
);
171 static void getTableData(TableInfo
*tblinfo
, int numTables
, bool oids
);
172 static void getTableDataFKConstraints(void);
173 static char *format_function_arguments(FuncInfo
*finfo
, char *funcargs
);
174 static char *format_function_arguments_old(FuncInfo
*finfo
, int nallargs
,
178 static char *format_function_signature(FuncInfo
*finfo
, bool honor_quotes
);
179 static const char *convertRegProcReference(const char *proc
);
180 static const char *convertOperatorReference(const char *opr
);
181 static const char *convertTSFunction(Oid funcOid
);
182 static Oid
findLastBuiltinOid_V71(const char *);
183 static Oid
findLastBuiltinOid_V70(void);
184 static void selectSourceSchema(const char *schemaName
);
185 static char *getFormattedTypeName(Oid oid
, OidOptions opts
);
186 static char *myFormatType(const char *typname
, int32 typmod
);
187 static const char *fmtQualifiedId(const char *schema
, const char *id
);
188 static bool hasBlobs(Archive
*AH
);
189 static int dumpBlobs(Archive
*AH
, void *arg
);
190 static int dumpBlobComments(Archive
*AH
, void *arg
);
191 static void dumpDatabase(Archive
*AH
);
192 static void dumpEncoding(Archive
*AH
);
193 static void dumpStdStrings(Archive
*AH
);
194 static const char *getAttrName(int attrnum
, TableInfo
*tblInfo
);
195 static const char *fmtCopyColumnList(const TableInfo
*ti
);
196 static void do_sql_command(PGconn
*conn
, const char *query
);
197 static void check_sql_result(PGresult
*res
, PGconn
*conn
, const char *query
,
198 ExecStatusType expected
);
202 main(int argc
, char **argv
)
205 const char *filename
= NULL
;
206 const char *format
= "p";
207 const char *dbname
= NULL
;
208 const char *pghost
= NULL
;
209 const char *pgport
= NULL
;
210 const char *username
= NULL
;
211 const char *dumpencoding
= NULL
;
212 const char *std_strings
;
216 DumpableObject
**dobjs
;
219 enum trivalue prompt_password
= TRI_DEFAULT
;
220 int compressLevel
= -1;
223 int outputCreate
= 0;
224 bool outputBlobs
= false;
225 int outputNoOwner
= 0;
226 char *outputSuperuser
= NULL
;
227 char *use_role
= NULL
;
230 RestoreOptions
*ropt
;
232 static int disable_triggers
= 0;
233 static int outputNoTablespaces
= 0;
234 static int use_setsessauth
= 0;
236 static struct option long_options
[] = {
237 {"data-only", no_argument
, NULL
, 'a'},
238 {"blobs", no_argument
, NULL
, 'b'},
239 {"clean", no_argument
, NULL
, 'c'},
240 {"create", no_argument
, NULL
, 'C'},
241 {"file", required_argument
, NULL
, 'f'},
242 {"format", required_argument
, NULL
, 'F'},
243 {"host", required_argument
, NULL
, 'h'},
244 {"ignore-version", no_argument
, NULL
, 'i'},
245 {"no-reconnect", no_argument
, NULL
, 'R'},
246 {"oids", no_argument
, NULL
, 'o'},
247 {"no-owner", no_argument
, NULL
, 'O'},
248 {"port", required_argument
, NULL
, 'p'},
249 {"schema", required_argument
, NULL
, 'n'},
250 {"exclude-schema", required_argument
, NULL
, 'N'},
251 {"schema-only", no_argument
, NULL
, 's'},
252 {"superuser", required_argument
, NULL
, 'S'},
253 {"table", required_argument
, NULL
, 't'},
254 {"exclude-table", required_argument
, NULL
, 'T'},
255 {"no-password", no_argument
, NULL
, 'w'},
256 {"password", no_argument
, NULL
, 'W'},
257 {"username", required_argument
, NULL
, 'U'},
258 {"verbose", no_argument
, NULL
, 'v'},
259 {"no-privileges", no_argument
, NULL
, 'x'},
260 {"no-acl", no_argument
, NULL
, 'x'},
261 {"compress", required_argument
, NULL
, 'Z'},
262 {"encoding", required_argument
, NULL
, 'E'},
263 {"help", no_argument
, NULL
, '?'},
264 {"version", no_argument
, NULL
, 'V'},
267 * the following options don't have an equivalent short option letter
269 {"attribute-inserts", no_argument
, &column_inserts
, 1},
270 {"binary-upgrade", no_argument
, &binary_upgrade
, 1},
271 {"column-inserts", no_argument
, &column_inserts
, 1},
272 {"disable-dollar-quoting", no_argument
, &disable_dollar_quoting
, 1},
273 {"disable-triggers", no_argument
, &disable_triggers
, 1},
274 {"inserts", no_argument
, &dump_inserts
, 1},
275 {"lock-wait-timeout", required_argument
, NULL
, 2},
276 {"no-tablespaces", no_argument
, &outputNoTablespaces
, 1},
277 {"role", required_argument
, NULL
, 3},
278 {"use-set-session-authorization", no_argument
, &use_setsessauth
, 1},
283 set_pglocale_pgservice(argv
[0], PG_TEXTDOMAIN("pg_dump"));
287 strcpy(g_comment_start
, "-- ");
288 g_comment_end
[0] = '\0';
289 strcpy(g_opaque_type
, "opaque");
291 dataOnly
= schemaOnly
= false;
292 lockWaitTimeout
= NULL
;
294 progname
= get_progname(argv
[0]);
296 /* Set default options based on progname */
297 if (strcmp(progname
, "pg_backup") == 0)
302 if (strcmp(argv
[1], "--help") == 0 || strcmp(argv
[1], "-?") == 0)
307 if (strcmp(argv
[1], "--version") == 0 || strcmp(argv
[1], "-V") == 0)
309 puts("pg_dump (PostgreSQL) " PG_VERSION
);
314 while ((c
= getopt_long(argc
, argv
, "abcCE:f:F:h:in:N:oOp:RsS:t:T:U:vwWxX:Z:",
315 long_options
, &optindex
)) != -1)
319 case 'a': /* Dump data only */
323 case 'b': /* Dump blobs */
327 case 'c': /* clean (i.e., drop) schema prior to create */
331 case 'C': /* Create DB */
335 case 'E': /* Dump encoding */
336 dumpencoding
= optarg
;
347 case 'h': /* server host */
352 /* ignored, deprecated option */
355 case 'n': /* include schema(s) */
356 simple_string_list_append(&schema_include_patterns
, optarg
);
357 include_everything
= false;
360 case 'N': /* exclude schema(s) */
361 simple_string_list_append(&schema_exclude_patterns
, optarg
);
364 case 'o': /* Dump oids */
368 case 'O': /* Don't reconnect to match owner */
372 case 'p': /* server port */
377 /* no-op, still accepted for backwards compatibility */
380 case 's': /* dump schema only */
384 case 'S': /* Username for superuser in plain text output */
385 outputSuperuser
= strdup(optarg
);
388 case 't': /* include table(s) */
389 simple_string_list_append(&table_include_patterns
, optarg
);
390 include_everything
= false;
393 case 'T': /* exclude table(s) */
394 simple_string_list_append(&table_exclude_patterns
, optarg
);
401 case 'v': /* verbose */
406 prompt_password
= TRI_NO
;
410 prompt_password
= TRI_YES
;
413 case 'x': /* skip ACL dump */
418 /* -X is a deprecated alternative to long options */
419 if (strcmp(optarg
, "disable-dollar-quoting") == 0)
420 disable_dollar_quoting
= 1;
421 else if (strcmp(optarg
, "disable-triggers") == 0)
422 disable_triggers
= 1;
423 else if (strcmp(optarg
, "no-tablespaces") == 0)
424 outputNoTablespaces
= 1;
425 else if (strcmp(optarg
, "use-set-session-authorization") == 0)
430 _("%s: invalid -X option -- %s\n"),
432 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), progname
);
437 case 'Z': /* Compression Level */
438 compressLevel
= atoi(optarg
);
442 /* This covers the long options equivalent to -X xxx. */
445 case 2: /* lock-wait-timeout */
446 lockWaitTimeout
= optarg
;
449 case 3: /* SET ROLE */
454 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), progname
);
459 if (optind
< (argc
- 1))
461 fprintf(stderr
, _("%s: too many command-line arguments (first is \"%s\")\n"),
462 progname
, argv
[optind
+ 1]);
463 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
468 /* Get database name from command line */
470 dbname
= argv
[optind
];
472 /* --column-inserts implies --inserts */
476 if (dataOnly
&& schemaOnly
)
478 write_msg(NULL
, "options -s/--schema-only and -a/--data-only cannot be used together\n");
482 if (dataOnly
&& outputClean
)
484 write_msg(NULL
, "options -c/--clean and -a/--data-only cannot be used together\n");
488 if (dump_inserts
&& oids
)
490 write_msg(NULL
, "options --inserts/--column-inserts and -o/--oids cannot be used together\n");
491 write_msg(NULL
, "(The INSERT command cannot set OIDs.)\n");
495 /* open the output file */
496 if (pg_strcasecmp(format
, "a") == 0 || pg_strcasecmp(format
, "append") == 0)
498 /* This is used by pg_dumpall, and is not documented */
500 g_fout
= CreateArchive(filename
, archNull
, 0, archModeAppend
);
502 else if (pg_strcasecmp(format
, "c") == 0 || pg_strcasecmp(format
, "custom") == 0)
503 g_fout
= CreateArchive(filename
, archCustom
, compressLevel
, archModeWrite
);
504 else if (pg_strcasecmp(format
, "f") == 0 || pg_strcasecmp(format
, "file") == 0)
507 * Dump files into the current directory; for demonstration only, not
510 g_fout
= CreateArchive(filename
, archFiles
, compressLevel
, archModeWrite
);
512 else if (pg_strcasecmp(format
, "p") == 0 || pg_strcasecmp(format
, "plain") == 0)
515 g_fout
= CreateArchive(filename
, archNull
, 0, archModeWrite
);
517 else if (pg_strcasecmp(format
, "t") == 0 || pg_strcasecmp(format
, "tar") == 0)
518 g_fout
= CreateArchive(filename
, archTar
, compressLevel
, archModeWrite
);
521 write_msg(NULL
, "invalid output format \"%s\" specified\n", format
);
527 write_msg(NULL
, "could not open output file \"%s\" for writing\n", filename
);
531 /* Let the archiver know how noisy to be */
532 g_fout
->verbose
= g_verbose
;
534 my_version
= parse_version(PG_VERSION
);
537 write_msg(NULL
, "could not parse version string \"%s\"\n", PG_VERSION
);
542 * We allow the server to be back to 7.0, and up to any minor release of
543 * our own major version. (See also version check in pg_dumpall.c.)
545 g_fout
->minRemoteVersion
= 70000;
546 g_fout
->maxRemoteVersion
= (my_version
/ 100) * 100 + 99;
549 * Open the database using the Archiver, so it knows about it. Errors mean
552 g_conn
= ConnectDatabase(g_fout
, dbname
, pghost
, pgport
,
553 username
, prompt_password
);
555 /* Set the client encoding if requested */
558 if (PQsetClientEncoding(g_conn
, dumpencoding
) < 0)
560 write_msg(NULL
, "invalid client encoding \"%s\" specified\n",
567 * Get the active encoding and the standard_conforming_strings setting, so
568 * we know how to escape strings.
570 g_fout
->encoding
= PQclientEncoding(g_conn
);
572 std_strings
= PQparameterStatus(g_conn
, "standard_conforming_strings");
573 g_fout
->std_strings
= (std_strings
&& strcmp(std_strings
, "on") == 0);
575 /* Set the role if requested */
576 if (use_role
&& g_fout
->remoteVersion
>= 80100)
578 PQExpBuffer query
= createPQExpBuffer();
580 appendPQExpBuffer(query
, "SET ROLE %s", fmtId(use_role
));
581 do_sql_command(g_conn
, query
->data
);
582 destroyPQExpBuffer(query
);
585 /* Set the datestyle to ISO to ensure the dump's portability */
586 do_sql_command(g_conn
, "SET DATESTYLE = ISO");
588 /* Likewise, avoid using sql_standard intervalstyle */
589 if (g_fout
->remoteVersion
>= 80400)
590 do_sql_command(g_conn
, "SET INTERVALSTYLE = POSTGRES");
593 * If supported, set extra_float_digits so that we can dump float data
594 * exactly (given correctly implemented float I/O code, anyway)
596 if (g_fout
->remoteVersion
>= 70400)
597 do_sql_command(g_conn
, "SET extra_float_digits TO 2");
600 * If synchronized scanning is supported, disable it, to prevent
601 * unpredictable changes in row ordering across a dump and reload.
603 if (g_fout
->remoteVersion
>= 80300)
604 do_sql_command(g_conn
, "SET synchronize_seqscans TO off");
607 * Disable timeouts if supported.
609 if (g_fout
->remoteVersion
>= 70300)
610 do_sql_command(g_conn
, "SET statement_timeout = 0");
613 * Start serializable transaction to dump consistent data.
615 do_sql_command(g_conn
, "BEGIN");
617 do_sql_command(g_conn
, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
619 /* Select the appropriate subquery to convert user IDs to names */
620 if (g_fout
->remoteVersion
>= 80100)
621 username_subquery
= "SELECT rolname FROM pg_catalog.pg_roles WHERE oid =";
622 else if (g_fout
->remoteVersion
>= 70300)
623 username_subquery
= "SELECT usename FROM pg_catalog.pg_user WHERE usesysid =";
625 username_subquery
= "SELECT usename FROM pg_user WHERE usesysid =";
627 /* Find the last built-in OID, if needed */
628 if (g_fout
->remoteVersion
< 70300)
630 if (g_fout
->remoteVersion
>= 70100)
631 g_last_builtin_oid
= findLastBuiltinOid_V71(PQdb(g_conn
));
633 g_last_builtin_oid
= findLastBuiltinOid_V70();
635 write_msg(NULL
, "last built-in OID is %u\n", g_last_builtin_oid
);
638 /* Expand schema selection patterns into OID lists */
639 if (schema_include_patterns
.head
!= NULL
)
641 expand_schema_name_patterns(&schema_include_patterns
,
642 &schema_include_oids
);
643 if (schema_include_oids
.head
== NULL
)
645 write_msg(NULL
, "No matching schemas were found\n");
649 expand_schema_name_patterns(&schema_exclude_patterns
,
650 &schema_exclude_oids
);
651 /* non-matching exclusion patterns aren't an error */
653 /* Expand table selection patterns into OID lists */
654 if (table_include_patterns
.head
!= NULL
)
656 expand_table_name_patterns(&table_include_patterns
,
657 &table_include_oids
);
658 if (table_include_oids
.head
== NULL
)
660 write_msg(NULL
, "No matching tables were found\n");
664 expand_table_name_patterns(&table_exclude_patterns
,
665 &table_exclude_oids
);
666 /* non-matching exclusion patterns aren't an error */
669 * Dumping blobs is now default unless we saw an inclusion switch or -s
670 * ... but even if we did see one of these, -b turns it back on.
672 if (include_everything
&& !schemaOnly
)
676 * Now scan the database and create DumpableObject structs for all the
677 * objects we intend to dump.
679 tblinfo
= getSchemaData(&numTables
);
681 if (g_fout
->remoteVersion
< 80400)
682 guessConstraintInheritance(tblinfo
, numTables
);
686 getTableData(tblinfo
, numTables
, oids
);
688 getTableDataFKConstraints();
691 if (outputBlobs
&& hasBlobs(g_fout
))
693 /* Add placeholders to allow correct sorting of blobs */
694 DumpableObject
*blobobj
;
695 DumpableObject
*blobcobj
;
697 blobobj
= (DumpableObject
*) malloc(sizeof(DumpableObject
));
698 blobobj
->objType
= DO_BLOBS
;
699 blobobj
->catId
= nilCatalogId
;
700 AssignDumpId(blobobj
);
701 blobobj
->name
= strdup("BLOBS");
703 blobcobj
= (DumpableObject
*) malloc(sizeof(DumpableObject
));
704 blobcobj
->objType
= DO_BLOB_COMMENTS
;
705 blobcobj
->catId
= nilCatalogId
;
706 AssignDumpId(blobcobj
);
707 blobcobj
->name
= strdup("BLOB COMMENTS");
708 addObjectDependency(blobcobj
, blobobj
->dumpId
);
712 * Collect dependency data to assist in ordering the objects.
717 * Sort the objects into a safe dump order (no forward references).
719 * In 7.3 or later, we can rely on dependency information to help us
720 * determine a safe order, so the initial sort is mostly for cosmetic
721 * purposes: we sort by name to ensure that logically identical schemas
722 * will dump identically. Before 7.3 we don't have dependencies and we
723 * use OID ordering as an (unreliable) guide to creation order.
725 getDumpableObjects(&dobjs
, &numObjs
);
727 if (g_fout
->remoteVersion
>= 70300)
728 sortDumpableObjectsByTypeName(dobjs
, numObjs
);
730 sortDumpableObjectsByTypeOid(dobjs
, numObjs
);
732 sortDumpableObjects(dobjs
, numObjs
);
735 * Create archive TOC entries for all the objects to be dumped, in a safe
739 /* First the special ENCODING and STDSTRINGS entries. */
740 dumpEncoding(g_fout
);
741 dumpStdStrings(g_fout
);
743 /* The database item is always next, unless we don't want it at all */
744 if (include_everything
&& !dataOnly
)
745 dumpDatabase(g_fout
);
747 /* Now the rearrangeable objects. */
748 for (i
= 0; i
< numObjs
; i
++)
749 dumpDumpableObject(g_fout
, dobjs
[i
]);
752 * And finally we can do the actual output.
756 ropt
= NewRestoreOptions();
757 ropt
->filename
= (char *) filename
;
758 ropt
->dropSchema
= outputClean
;
759 ropt
->aclsSkip
= aclsSkip
;
760 ropt
->superuser
= outputSuperuser
;
761 ropt
->create
= outputCreate
;
762 ropt
->noOwner
= outputNoOwner
;
763 ropt
->noTablespace
= outputNoTablespaces
;
764 ropt
->disable_triggers
= disable_triggers
;
765 ropt
->use_setsessauth
= use_setsessauth
;
766 ropt
->dataOnly
= dataOnly
;
768 if (compressLevel
== -1)
769 ropt
->compression
= 0;
771 ropt
->compression
= compressLevel
;
773 ropt
->suppressDumpWarnings
= true; /* We've already shown them */
775 RestoreArchive(g_fout
, ropt
);
778 CloseArchive(g_fout
);
787 help(const char *progname
)
789 printf(_("%s dumps a database as a text file or to other formats.\n\n"), progname
);
790 printf(_("Usage:\n"));
791 printf(_(" %s [OPTION]... [DBNAME]\n"), progname
);
793 printf(_("\nGeneral options:\n"));
794 printf(_(" -f, --file=FILENAME output file name\n"));
795 printf(_(" -F, --format=c|t|p output file format (custom, tar, plain text)\n"));
796 printf(_(" -v, --verbose verbose mode\n"));
797 printf(_(" -Z, --compress=0-9 compression level for compressed formats\n"));
798 printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
799 printf(_(" --help show this help, then exit\n"));
800 printf(_(" --version output version information, then exit\n"));
802 printf(_("\nOptions controlling the output content:\n"));
803 printf(_(" -a, --data-only dump only the data, not the schema\n"));
804 printf(_(" -b, --blobs include large objects in dump\n"));
805 printf(_(" -c, --clean clean (drop) database objects before recreating\n"));
806 printf(_(" -C, --create include commands to create database in dump\n"));
807 printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
808 printf(_(" -n, --schema=SCHEMA dump the named schema(s) only\n"));
809 printf(_(" -N, --exclude-schema=SCHEMA do NOT dump the named schema(s)\n"));
810 printf(_(" -o, --oids include OIDs in dump\n"));
811 printf(_(" -O, --no-owner skip restoration of object ownership in\n"
812 " plain-text format\n"));
813 printf(_(" -s, --schema-only dump only the schema, no data\n"));
814 printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n"));
815 printf(_(" -t, --table=TABLE dump the named table(s) only\n"));
816 printf(_(" -T, --exclude-table=TABLE do NOT dump the named table(s)\n"));
817 printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
818 printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
819 printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
820 printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
821 printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
822 printf(_(" --disable-triggers disable triggers during data-only restore\n"));
823 printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
824 printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
825 printf(_(" --use-set-session-authorization\n"
826 " use SET SESSION AUTHORIZATION commands instead of\n"
827 " ALTER OWNER commands to set ownership\n"));
829 printf(_("\nConnection options:\n"));
830 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
831 printf(_(" -p, --port=PORT database server port number\n"));
832 printf(_(" -U, --username=NAME connect as specified database user\n"));
833 printf(_(" -w, --no-password never prompt for password\n"));
834 printf(_(" -W, --password force password prompt (should happen automatically)\n"));
836 printf(_("\nIf no database name is supplied, then the PGDATABASE environment\n"
837 "variable value is used.\n\n"));
838 printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
846 write_msg(NULL
, "*** aborted because of error\n");
851 * Find the OIDs of all schemas matching the given list of patterns,
852 * and append them to the given OID list.
855 expand_schema_name_patterns(SimpleStringList
*patterns
, SimpleOidList
*oids
)
859 SimpleStringListCell
*cell
;
862 if (patterns
->head
== NULL
)
863 return; /* nothing to do */
865 if (g_fout
->remoteVersion
< 70300)
867 write_msg(NULL
, "server version must be at least 7.3 to use schema selection switches\n");
871 query
= createPQExpBuffer();
874 * We use UNION ALL rather than UNION; this might sometimes result in
875 * duplicate entries in the OID list, but we don't care.
878 for (cell
= patterns
->head
; cell
; cell
= cell
->next
)
880 if (cell
!= patterns
->head
)
881 appendPQExpBuffer(query
, "UNION ALL\n");
882 appendPQExpBuffer(query
,
883 "SELECT oid FROM pg_catalog.pg_namespace n\n");
884 processSQLNamePattern(g_conn
, query
, cell
->val
, false, false,
885 NULL
, "n.nspname", NULL
,
889 res
= PQexec(g_conn
, query
->data
);
890 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
892 for (i
= 0; i
< PQntuples(res
); i
++)
894 simple_oid_list_append(oids
, atooid(PQgetvalue(res
, i
, 0)));
898 destroyPQExpBuffer(query
);
902 * Find the OIDs of all tables matching the given list of patterns,
903 * and append them to the given OID list.
906 expand_table_name_patterns(SimpleStringList
*patterns
, SimpleOidList
*oids
)
910 SimpleStringListCell
*cell
;
913 if (patterns
->head
== NULL
)
914 return; /* nothing to do */
916 query
= createPQExpBuffer();
919 * We use UNION ALL rather than UNION; this might sometimes result in
920 * duplicate entries in the OID list, but we don't care.
923 for (cell
= patterns
->head
; cell
; cell
= cell
->next
)
925 if (cell
!= patterns
->head
)
926 appendPQExpBuffer(query
, "UNION ALL\n");
927 appendPQExpBuffer(query
,
929 "\nFROM pg_catalog.pg_class c"
930 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
931 "\nWHERE c.relkind in ('%c', '%c', '%c')\n",
932 RELKIND_RELATION
, RELKIND_SEQUENCE
, RELKIND_VIEW
);
933 processSQLNamePattern(g_conn
, query
, cell
->val
, true, false,
934 "n.nspname", "c.relname", NULL
,
935 "pg_catalog.pg_table_is_visible(c.oid)");
938 res
= PQexec(g_conn
, query
->data
);
939 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
941 for (i
= 0; i
< PQntuples(res
); i
++)
943 simple_oid_list_append(oids
, atooid(PQgetvalue(res
, i
, 0)));
947 destroyPQExpBuffer(query
);
951 * selectDumpableNamespace: policy-setting subroutine
952 * Mark a namespace as to be dumped or not
955 selectDumpableNamespace(NamespaceInfo
*nsinfo
)
958 * If specific tables are being dumped, do not dump any complete
959 * namespaces. If specific namespaces are being dumped, dump just those
960 * namespaces. Otherwise, dump all non-system namespaces.
962 if (table_include_oids
.head
!= NULL
)
963 nsinfo
->dobj
.dump
= false;
964 else if (schema_include_oids
.head
!= NULL
)
965 nsinfo
->dobj
.dump
= simple_oid_list_member(&schema_include_oids
,
966 nsinfo
->dobj
.catId
.oid
);
967 else if (strncmp(nsinfo
->dobj
.name
, "pg_", 3) == 0 ||
968 strcmp(nsinfo
->dobj
.name
, "information_schema") == 0)
969 nsinfo
->dobj
.dump
= false;
971 nsinfo
->dobj
.dump
= true;
974 * In any case, a namespace can be excluded by an exclusion switch
976 if (nsinfo
->dobj
.dump
&&
977 simple_oid_list_member(&schema_exclude_oids
,
978 nsinfo
->dobj
.catId
.oid
))
979 nsinfo
->dobj
.dump
= false;
983 * selectDumpableTable: policy-setting subroutine
984 * Mark a table as to be dumped or not
987 selectDumpableTable(TableInfo
*tbinfo
)
990 * If specific tables are being dumped, dump just those tables; else, dump
991 * according to the parent namespace's dump flag.
993 if (table_include_oids
.head
!= NULL
)
994 tbinfo
->dobj
.dump
= simple_oid_list_member(&table_include_oids
,
995 tbinfo
->dobj
.catId
.oid
);
997 tbinfo
->dobj
.dump
= tbinfo
->dobj
.namespace->dobj
.dump
;
1000 * In any case, a table can be excluded by an exclusion switch
1002 if (tbinfo
->dobj
.dump
&&
1003 simple_oid_list_member(&table_exclude_oids
,
1004 tbinfo
->dobj
.catId
.oid
))
1005 tbinfo
->dobj
.dump
= false;
1009 * selectDumpableType: policy-setting subroutine
1010 * Mark a type as to be dumped or not
1012 * If it's a table's rowtype or an autogenerated array type, we also apply a
1013 * special type code to facilitate sorting into the desired order. (We don't
1014 * want to consider those to be ordinary types because that would bring tables
1015 * up into the datatype part of the dump order.) Those tests should be made
1016 * first to ensure the objType change is applied regardless of namespace etc.
1019 selectDumpableType(TypeInfo
*tinfo
)
1021 /* skip complex types, except for standalone composite types */
1022 if (OidIsValid(tinfo
->typrelid
) &&
1023 tinfo
->typrelkind
!= RELKIND_COMPOSITE_TYPE
)
1025 tinfo
->dobj
.dump
= false;
1026 tinfo
->dobj
.objType
= DO_DUMMY_TYPE
;
1029 /* skip auto-generated array types */
1030 else if (tinfo
->isArray
)
1032 tinfo
->dobj
.dump
= false;
1033 tinfo
->dobj
.objType
= DO_DUMMY_TYPE
;
1036 /* dump only types in dumpable namespaces */
1037 else if (!tinfo
->dobj
.namespace->dobj
.dump
)
1038 tinfo
->dobj
.dump
= false;
1040 /* skip undefined placeholder types */
1041 else if (!tinfo
->isDefined
)
1042 tinfo
->dobj
.dump
= false;
1045 tinfo
->dobj
.dump
= true;
1049 * selectDumpableObject: policy-setting subroutine
1050 * Mark a generic dumpable object as to be dumped or not
1052 * Use this only for object types without a special-case routine above.
1055 selectDumpableObject(DumpableObject
*dobj
)
1058 * Default policy is to dump if parent namespace is dumpable, or always
1059 * for non-namespace-associated items.
1061 if (dobj
->namespace)
1062 dobj
->dump
= dobj
->namespace->dobj
.dump
;
1068 * Dump a table's contents for loading using the COPY command
1069 * - this routine is called by the Archiver when it wants the table
1074 dumpTableData_copy(Archive
*fout
, void *dcontext
)
1076 TableDataInfo
*tdinfo
= (TableDataInfo
*) dcontext
;
1077 TableInfo
*tbinfo
= tdinfo
->tdtable
;
1078 const char *classname
= tbinfo
->dobj
.name
;
1079 const bool hasoids
= tbinfo
->hasoids
;
1080 const bool oids
= tdinfo
->oids
;
1081 PQExpBuffer q
= createPQExpBuffer();
1085 const char *column_list
;
1088 write_msg(NULL
, "dumping contents of table %s\n", classname
);
1091 * Make sure we are in proper schema. We will qualify the table name
1092 * below anyway (in case its name conflicts with a pg_catalog table); but
1093 * this ensures reproducible results in case the table contains regproc,
1094 * regclass, etc columns.
1096 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
1099 * If possible, specify the column list explicitly so that we have no
1100 * possibility of retrieving data in the wrong column order. (The default
1101 * column ordering of COPY will not be what we want in certain corner
1102 * cases involving ADD COLUMN and inheritance.)
1104 if (g_fout
->remoteVersion
>= 70300)
1105 column_list
= fmtCopyColumnList(tbinfo
);
1107 column_list
= ""; /* can't select columns in COPY */
1109 if (oids
&& hasoids
)
1111 appendPQExpBuffer(q
, "COPY %s %s WITH OIDS TO stdout;",
1112 fmtQualifiedId(tbinfo
->dobj
.namespace->dobj
.name
,
1118 appendPQExpBuffer(q
, "COPY %s %s TO stdout;",
1119 fmtQualifiedId(tbinfo
->dobj
.namespace->dobj
.name
,
1123 res
= PQexec(g_conn
, q
->data
);
1124 check_sql_result(res
, g_conn
, q
->data
, PGRES_COPY_OUT
);
1129 ret
= PQgetCopyData(g_conn
, ©buf
, 0);
1132 break; /* done or error */
1136 WriteData(fout
, copybuf
, ret
);
1143 * There was considerable discussion in late July, 2000 regarding
1144 * slowing down pg_dump when backing up large tables. Users with both
1145 * slow & fast (multi-processor) machines experienced performance
1146 * degradation when doing a backup.
1148 * Initial attempts based on sleeping for a number of ms for each ms
1149 * of work were deemed too complex, then a simple 'sleep in each loop'
1150 * implementation was suggested. The latter failed because the loop
1151 * was too tight. Finally, the following was implemented:
1153 * If throttle is non-zero, then
1154 * See how long since the last sleep.
1155 * Work out how long to sleep (based on ratio).
1156 * If sleep is more than 100ms, then
1162 * where the throttle value was the number of ms to sleep per ms of
1163 * work. The calculation was done in each loop.
1165 * Most of the hard work is done in the backend, and this solution
1166 * still did not work particularly well: on slow machines, the ratio
1167 * was 50:1, and on medium paced machines, 1:1, and on fast
1168 * multi-processor machines, it had little or no effect, for reasons
1169 * that were unclear.
1171 * Further discussion ensued, and the proposal was dropped.
1173 * For those people who want this feature, it can be implemented using
1174 * gettimeofday in each loop, calculating the time since last sleep,
1175 * multiplying that by the sleep ratio, then if the result is more
1176 * than a preset 'minimum sleep time' (say 100ms), call the 'select'
1177 * function to sleep for a subsecond period ie.
1179 * select(0, NULL, NULL, NULL, &tvi);
1181 * This will return after the interval specified in the structure tvi.
1182 * Finally, call gettimeofday again to save the 'last sleep time'.
1186 archprintf(fout
, "\\.\n\n\n");
1190 /* copy data transfer failed */
1191 write_msg(NULL
, "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed.\n", classname
);
1192 write_msg(NULL
, "Error message from server: %s", PQerrorMessage(g_conn
));
1193 write_msg(NULL
, "The command was: %s\n", q
->data
);
1197 /* Check command status and return to normal libpq state */
1198 res
= PQgetResult(g_conn
);
1199 check_sql_result(res
, g_conn
, q
->data
, PGRES_COMMAND_OK
);
1202 destroyPQExpBuffer(q
);
1207 dumpTableData_insert(Archive
*fout
, void *dcontext
)
1209 TableDataInfo
*tdinfo
= (TableDataInfo
*) dcontext
;
1210 TableInfo
*tbinfo
= tdinfo
->tdtable
;
1211 const char *classname
= tbinfo
->dobj
.name
;
1212 PQExpBuffer q
= createPQExpBuffer();
1219 * Make sure we are in proper schema. We will qualify the table name
1220 * below anyway (in case its name conflicts with a pg_catalog table); but
1221 * this ensures reproducible results in case the table contains regproc,
1222 * regclass, etc columns.
1224 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
1226 if (fout
->remoteVersion
>= 70100)
1228 appendPQExpBuffer(q
, "DECLARE _pg_dump_cursor CURSOR FOR "
1229 "SELECT * FROM ONLY %s",
1230 fmtQualifiedId(tbinfo
->dobj
.namespace->dobj
.name
,
1235 appendPQExpBuffer(q
, "DECLARE _pg_dump_cursor CURSOR FOR "
1237 fmtQualifiedId(tbinfo
->dobj
.namespace->dobj
.name
,
1241 res
= PQexec(g_conn
, q
->data
);
1242 check_sql_result(res
, g_conn
, q
->data
, PGRES_COMMAND_OK
);
1248 res
= PQexec(g_conn
, "FETCH 100 FROM _pg_dump_cursor");
1249 check_sql_result(res
, g_conn
, "FETCH 100 FROM _pg_dump_cursor",
1251 nfields
= PQnfields(res
);
1252 for (tuple
= 0; tuple
< PQntuples(res
); tuple
++)
1254 archprintf(fout
, "INSERT INTO %s ", fmtId(classname
));
1257 /* corner case for zero-column table */
1258 archprintf(fout
, "DEFAULT VALUES;\n");
1263 resetPQExpBuffer(q
);
1264 appendPQExpBuffer(q
, "(");
1265 for (field
= 0; field
< nfields
; field
++)
1268 appendPQExpBuffer(q
, ", ");
1269 appendPQExpBufferStr(q
, fmtId(PQfname(res
, field
)));
1271 appendPQExpBuffer(q
, ") ");
1272 archputs(q
->data
, fout
);
1274 archprintf(fout
, "VALUES (");
1275 for (field
= 0; field
< nfields
; field
++)
1278 archprintf(fout
, ", ");
1279 if (PQgetisnull(res
, tuple
, field
))
1281 archprintf(fout
, "NULL");
1285 /* XXX This code is partially duplicated in ruleutils.c */
1286 switch (PQftype(res
, field
))
1297 * These types are printed without quotes unless
1298 * they contain values that aren't accepted by the
1299 * scanner unquoted (e.g., 'NaN'). Note that
1300 * strtod() and friends might accept NaN, so we
1301 * can't use that to test.
1303 * In reality we only need to defend against
1304 * infinity and NaN, so we need not get too crazy
1305 * about pattern matching here.
1307 const char *s
= PQgetvalue(res
, tuple
, field
);
1309 if (strspn(s
, "0123456789 +-eE.") == strlen(s
))
1310 archprintf(fout
, "%s", s
);
1312 archprintf(fout
, "'%s'", s
);
1318 archprintf(fout
, "B'%s'",
1319 PQgetvalue(res
, tuple
, field
));
1323 if (strcmp(PQgetvalue(res
, tuple
, field
), "t") == 0)
1324 archprintf(fout
, "true");
1326 archprintf(fout
, "false");
1330 /* All other types are printed as string literals. */
1331 resetPQExpBuffer(q
);
1332 appendStringLiteralAH(q
,
1333 PQgetvalue(res
, tuple
, field
),
1335 archputs(q
->data
, fout
);
1339 archprintf(fout
, ");\n");
1341 } while (PQntuples(res
) > 0);
1345 archprintf(fout
, "\n\n");
1347 do_sql_command(g_conn
, "CLOSE _pg_dump_cursor");
1349 destroyPQExpBuffer(q
);
1356 * dump the contents of a single table
1358 * Actually, this just makes an ArchiveEntry for the table contents.
1361 dumpTableData(Archive
*fout
, TableDataInfo
*tdinfo
)
1363 TableInfo
*tbinfo
= tdinfo
->tdtable
;
1364 PQExpBuffer copyBuf
= createPQExpBuffer();
1365 DataDumperPtr dumpFn
;
1370 /* Dump/restore using COPY */
1371 dumpFn
= dumpTableData_copy
;
1372 /* must use 2 steps here 'cause fmtId is nonreentrant */
1373 appendPQExpBuffer(copyBuf
, "COPY %s ",
1374 fmtId(tbinfo
->dobj
.name
));
1375 appendPQExpBuffer(copyBuf
, "%s %sFROM stdin;\n",
1376 fmtCopyColumnList(tbinfo
),
1377 (tdinfo
->oids
&& tbinfo
->hasoids
) ? "WITH OIDS " : "");
1378 copyStmt
= copyBuf
->data
;
1382 /* Restore using INSERT */
1383 dumpFn
= dumpTableData_insert
;
1387 ArchiveEntry(fout
, tdinfo
->dobj
.catId
, tdinfo
->dobj
.dumpId
,
1388 tbinfo
->dobj
.name
, tbinfo
->dobj
.namespace->dobj
.name
,
1389 NULL
, tbinfo
->rolname
,
1390 false, "TABLE DATA", SECTION_DATA
,
1392 tdinfo
->dobj
.dependencies
, tdinfo
->dobj
.nDeps
,
1395 destroyPQExpBuffer(copyBuf
);
1400 * set up dumpable objects representing the contents of tables
1403 getTableData(TableInfo
*tblinfo
, int numTables
, bool oids
)
1407 for (i
= 0; i
< numTables
; i
++)
1409 /* Skip VIEWs (no data to dump) */
1410 if (tblinfo
[i
].relkind
== RELKIND_VIEW
)
1412 /* Skip SEQUENCEs (handled elsewhere) */
1413 if (tblinfo
[i
].relkind
== RELKIND_SEQUENCE
)
1416 if (tblinfo
[i
].dobj
.dump
)
1418 TableDataInfo
*tdinfo
;
1420 tdinfo
= (TableDataInfo
*) malloc(sizeof(TableDataInfo
));
1422 tdinfo
->dobj
.objType
= DO_TABLE_DATA
;
1425 * Note: use tableoid 0 so that this object won't be mistaken for
1426 * something that pg_depend entries apply to.
1428 tdinfo
->dobj
.catId
.tableoid
= 0;
1429 tdinfo
->dobj
.catId
.oid
= tblinfo
[i
].dobj
.catId
.oid
;
1430 AssignDumpId(&tdinfo
->dobj
);
1431 tdinfo
->dobj
.name
= tblinfo
[i
].dobj
.name
;
1432 tdinfo
->dobj
.namespace = tblinfo
[i
].dobj
.namespace;
1433 tdinfo
->tdtable
= &(tblinfo
[i
]);
1434 tdinfo
->oids
= oids
;
1435 addObjectDependency(&tdinfo
->dobj
, tblinfo
[i
].dobj
.dumpId
);
1437 tblinfo
[i
].dataObj
= tdinfo
;
1443 * getTableDataFKConstraints -
1444 * add dump-order dependencies reflecting foreign key constraints
1446 * This code is executed only in a data-only dump --- in schema+data dumps
1447 * we handle foreign key issues by not creating the FK constraints until
1448 * after the data is loaded. In a data-only dump, however, we want to
1449 * order the table data objects in such a way that a table's referenced
1450 * tables are restored first. (In the presence of circular references or
1451 * self-references this may be impossible; we'll detect and complain about
1452 * that during the dependency sorting step.)
1455 getTableDataFKConstraints(void)
1457 DumpableObject
**dobjs
;
1461 /* Search through all the dumpable objects for FK constraints */
1462 getDumpableObjects(&dobjs
, &numObjs
);
1463 for (i
= 0; i
< numObjs
; i
++)
1465 if (dobjs
[i
]->objType
== DO_FK_CONSTRAINT
)
1467 ConstraintInfo
*cinfo
= (ConstraintInfo
*) dobjs
[i
];
1470 /* Not interesting unless both tables are to be dumped */
1471 if (cinfo
->contable
== NULL
||
1472 cinfo
->contable
->dataObj
== NULL
)
1474 ftable
= findTableByOid(cinfo
->confrelid
);
1475 if (ftable
== NULL
||
1476 ftable
->dataObj
== NULL
)
1480 * Okay, make referencing table's TABLE_DATA object depend on the
1481 * referenced table's TABLE_DATA object.
1483 addObjectDependency(&cinfo
->contable
->dataObj
->dobj
,
1484 ftable
->dataObj
->dobj
.dumpId
);
1492 * guessConstraintInheritance:
1493 * In pre-8.4 databases, we can't tell for certain which constraints
1494 * are inherited. We assume a CHECK constraint is inherited if its name
1495 * matches the name of any constraint in the parent. Originally this code
1496 * tried to compare the expression texts, but that can fail for various
1497 * reasons --- for example, if the parent and child tables are in different
1498 * schemas, reverse-listing of function calls may produce different text
1499 * (schema-qualified or not) depending on search path.
1501 * In 8.4 and up we can rely on the conislocal field to decide which
1502 * constraints must be dumped; much safer.
1504 * This function assumes all conislocal flags were initialized to TRUE.
1505 * It clears the flag on anything that seems to be inherited.
1508 guessConstraintInheritance(TableInfo
*tblinfo
, int numTables
)
1514 for (i
= 0; i
< numTables
; i
++)
1516 TableInfo
*tbinfo
= &(tblinfo
[i
]);
1518 TableInfo
**parents
;
1521 /* Sequences and views never have parents */
1522 if (tbinfo
->relkind
== RELKIND_SEQUENCE
||
1523 tbinfo
->relkind
== RELKIND_VIEW
)
1526 /* Don't bother computing anything for non-target tables, either */
1527 if (!tbinfo
->dobj
.dump
)
1530 numParents
= tbinfo
->numParents
;
1531 parents
= tbinfo
->parents
;
1533 if (numParents
== 0)
1534 continue; /* nothing to see here, move along */
1536 /* scan for inherited CHECK constraints */
1537 for (j
= 0; j
< tbinfo
->ncheck
; j
++)
1539 ConstraintInfo
*constr
;
1541 constr
= &(tbinfo
->checkexprs
[j
]);
1543 for (k
= 0; k
< numParents
; k
++)
1547 parent
= parents
[k
];
1548 for (l
= 0; l
< parent
->ncheck
; l
++)
1550 ConstraintInfo
*pconstr
= &(parent
->checkexprs
[l
]);
1552 if (strcmp(pconstr
->dobj
.name
, constr
->dobj
.name
) == 0)
1554 constr
->conislocal
= false;
1558 if (!constr
->conislocal
)
1568 * dump the database definition
1571 dumpDatabase(Archive
*AH
)
1573 PQExpBuffer dbQry
= createPQExpBuffer();
1574 PQExpBuffer delQry
= createPQExpBuffer();
1575 PQExpBuffer creaQry
= createPQExpBuffer();
1588 const char *datname
,
1596 datname
= PQdb(g_conn
);
1599 write_msg(NULL
, "saving database definition\n");
1601 /* Make sure we are in proper schema */
1602 selectSourceSchema("pg_catalog");
1604 /* Get the database owner and parameters from pg_database */
1605 if (g_fout
->remoteVersion
>= 80400)
1607 appendPQExpBuffer(dbQry
, "SELECT tableoid, oid, "
1608 "(%s datdba) AS dba, "
1609 "pg_encoding_to_char(encoding) AS encoding, "
1610 "datcollate, datctype, datfrozenxid, "
1611 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
1612 "shobj_description(oid, 'pg_database') AS description "
1617 appendStringLiteralAH(dbQry
, datname
, AH
);
1619 else if (g_fout
->remoteVersion
>= 80200)
1621 appendPQExpBuffer(dbQry
, "SELECT tableoid, oid, "
1622 "(%s datdba) AS dba, "
1623 "pg_encoding_to_char(encoding) AS encoding, "
1624 "NULL AS datcollate, NULL AS datctype, datfrozenxid, "
1625 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
1626 "shobj_description(oid, 'pg_database') AS description "
1631 appendStringLiteralAH(dbQry
, datname
, AH
);
1633 else if (g_fout
->remoteVersion
>= 80000)
1635 appendPQExpBuffer(dbQry
, "SELECT tableoid, oid, "
1636 "(%s datdba) AS dba, "
1637 "pg_encoding_to_char(encoding) AS encoding, "
1638 "NULL AS datcollate, NULL AS datctype, datfrozenxid, "
1639 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace "
1643 appendStringLiteralAH(dbQry
, datname
, AH
);
1645 else if (g_fout
->remoteVersion
>= 70100)
1647 appendPQExpBuffer(dbQry
, "SELECT tableoid, oid, "
1648 "(%s datdba) AS dba, "
1649 "pg_encoding_to_char(encoding) AS encoding, "
1650 "NULL AS datcollate, NULL AS datctype, "
1651 "0 AS datfrozenxid, "
1652 "NULL AS tablespace "
1656 appendStringLiteralAH(dbQry
, datname
, AH
);
1660 appendPQExpBuffer(dbQry
, "SELECT "
1661 "(SELECT oid FROM pg_class WHERE relname = 'pg_database') AS tableoid, "
1663 "(%s datdba) AS dba, "
1664 "pg_encoding_to_char(encoding) AS encoding, "
1665 "NULL AS datcollate, NULL AS datctype, "
1666 "0 AS datfrozenxid, "
1667 "NULL AS tablespace "
1671 appendStringLiteralAH(dbQry
, datname
, AH
);
1674 res
= PQexec(g_conn
, dbQry
->data
);
1675 check_sql_result(res
, g_conn
, dbQry
->data
, PGRES_TUPLES_OK
);
1677 ntups
= PQntuples(res
);
1681 write_msg(NULL
, "missing pg_database entry for database \"%s\"\n",
1688 write_msg(NULL
, "query returned more than one (%d) pg_database entry for database \"%s\"\n",
1693 i_tableoid
= PQfnumber(res
, "tableoid");
1694 i_oid
= PQfnumber(res
, "oid");
1695 i_dba
= PQfnumber(res
, "dba");
1696 i_encoding
= PQfnumber(res
, "encoding");
1697 i_collate
= PQfnumber(res
, "datcollate");
1698 i_ctype
= PQfnumber(res
, "datctype");
1699 i_frozenxid
= PQfnumber(res
, "datfrozenxid");
1700 i_tablespace
= PQfnumber(res
, "tablespace");
1702 dbCatId
.tableoid
= atooid(PQgetvalue(res
, 0, i_tableoid
));
1703 dbCatId
.oid
= atooid(PQgetvalue(res
, 0, i_oid
));
1704 dba
= PQgetvalue(res
, 0, i_dba
);
1705 encoding
= PQgetvalue(res
, 0, i_encoding
);
1706 collate
= PQgetvalue(res
, 0, i_collate
);
1707 ctype
= PQgetvalue(res
, 0, i_ctype
);
1708 frozenxid
= atooid(PQgetvalue(res
, 0, i_frozenxid
));
1709 tablespace
= PQgetvalue(res
, 0, i_tablespace
);
1711 appendPQExpBuffer(creaQry
, "CREATE DATABASE %s WITH TEMPLATE = template0",
1713 if (strlen(encoding
) > 0)
1715 appendPQExpBuffer(creaQry
, " ENCODING = ");
1716 appendStringLiteralAH(creaQry
, encoding
, AH
);
1718 if (strlen(collate
) > 0)
1720 appendPQExpBuffer(creaQry
, " LC_COLLATE = ");
1721 appendStringLiteralAH(creaQry
, collate
, AH
);
1723 if (strlen(ctype
) > 0)
1725 appendPQExpBuffer(creaQry
, " LC_CTYPE = ");
1726 appendStringLiteralAH(creaQry
, ctype
, AH
);
1728 if (strlen(tablespace
) > 0 && strcmp(tablespace
, "pg_default") != 0)
1729 appendPQExpBuffer(creaQry
, " TABLESPACE = %s",
1731 appendPQExpBuffer(creaQry
, ";\n");
1735 appendPQExpBuffer(creaQry
, "\n-- For binary upgrade, set datfrozenxid.\n");
1736 appendPQExpBuffer(creaQry
, "UPDATE pg_catalog.pg_database\n"
1737 "SET datfrozenxid = '%u'\n"
1740 appendStringLiteralAH(creaQry
, datname
, AH
);
1741 appendPQExpBuffer(creaQry
, ";\n");
1744 appendPQExpBuffer(delQry
, "DROP DATABASE %s;\n",
1747 dbDumpId
= createDumpId();
1750 dbCatId
, /* catalog ID */
1751 dbDumpId
, /* dump ID */
1753 NULL
, /* Namespace */
1754 NULL
, /* Tablespace */
1756 false, /* with oids */
1757 "DATABASE", /* Desc */
1758 SECTION_PRE_DATA
, /* Section */
1759 creaQry
->data
, /* Create */
1760 delQry
->data
, /* Del */
1765 NULL
); /* Dumper Arg */
1767 /* Dump DB comment if any */
1768 if (g_fout
->remoteVersion
>= 80200)
1771 * 8.2 keeps comments on shared objects in a shared table, so we
1772 * cannot use the dumpComment used for other database objects.
1774 char *comment
= PQgetvalue(res
, 0, PQfnumber(res
, "description"));
1776 if (comment
&& strlen(comment
))
1778 resetPQExpBuffer(dbQry
);
1781 * Generates warning when loaded into a differently-named
1784 appendPQExpBuffer(dbQry
, "COMMENT ON DATABASE %s IS ", fmtId(datname
));
1785 appendStringLiteralAH(dbQry
, comment
, AH
);
1786 appendPQExpBuffer(dbQry
, ";\n");
1788 ArchiveEntry(AH
, dbCatId
, createDumpId(), datname
, NULL
, NULL
,
1789 dba
, false, "COMMENT", SECTION_NONE
,
1790 dbQry
->data
, "", NULL
,
1791 &dbDumpId
, 1, NULL
, NULL
);
1796 resetPQExpBuffer(dbQry
);
1797 appendPQExpBuffer(dbQry
, "DATABASE %s", fmtId(datname
));
1798 dumpComment(AH
, dbQry
->data
, NULL
, "",
1799 dbCatId
, 0, dbDumpId
);
1804 destroyPQExpBuffer(dbQry
);
1805 destroyPQExpBuffer(delQry
);
1806 destroyPQExpBuffer(creaQry
);
1811 * dumpEncoding: put the correct encoding into the archive
1814 dumpEncoding(Archive
*AH
)
1816 const char *encname
= pg_encoding_to_char(AH
->encoding
);
1817 PQExpBuffer qry
= createPQExpBuffer();
1820 write_msg(NULL
, "saving encoding = %s\n", encname
);
1822 appendPQExpBuffer(qry
, "SET client_encoding = ");
1823 appendStringLiteralAH(qry
, encname
, AH
);
1824 appendPQExpBuffer(qry
, ";\n");
1826 ArchiveEntry(AH
, nilCatalogId
, createDumpId(),
1827 "ENCODING", NULL
, NULL
, "",
1828 false, "ENCODING", SECTION_PRE_DATA
,
1829 qry
->data
, "", NULL
,
1833 destroyPQExpBuffer(qry
);
1838 * dumpStdStrings: put the correct escape string behavior into the archive
1841 dumpStdStrings(Archive
*AH
)
1843 const char *stdstrings
= AH
->std_strings
? "on" : "off";
1844 PQExpBuffer qry
= createPQExpBuffer();
1847 write_msg(NULL
, "saving standard_conforming_strings = %s\n",
1850 appendPQExpBuffer(qry
, "SET standard_conforming_strings = '%s';\n",
1853 ArchiveEntry(AH
, nilCatalogId
, createDumpId(),
1854 "STDSTRINGS", NULL
, NULL
, "",
1855 false, "STDSTRINGS", SECTION_PRE_DATA
,
1856 qry
->data
, "", NULL
,
1860 destroyPQExpBuffer(qry
);
1866 * Test whether database contains any large objects
1869 hasBlobs(Archive
*AH
)
1872 const char *blobQry
;
1875 /* Make sure we are in proper schema */
1876 selectSourceSchema("pg_catalog");
1878 /* Check for BLOB OIDs */
1879 if (AH
->remoteVersion
>= 70100)
1880 blobQry
= "SELECT loid FROM pg_largeobject LIMIT 1";
1882 blobQry
= "SELECT oid FROM pg_class WHERE relkind = 'l' LIMIT 1";
1884 res
= PQexec(g_conn
, blobQry
);
1885 check_sql_result(res
, g_conn
, blobQry
, PGRES_TUPLES_OK
);
1887 result
= PQntuples(res
) > 0;
1899 dumpBlobs(Archive
*AH
, void *arg
)
1901 const char *blobQry
;
1902 const char *blobFetchQry
;
1904 char buf
[LOBBUFSIZE
];
1909 write_msg(NULL
, "saving large objects\n");
1911 /* Make sure we are in proper schema */
1912 selectSourceSchema("pg_catalog");
1914 /* Cursor to get all BLOB OIDs */
1915 if (AH
->remoteVersion
>= 70100)
1916 blobQry
= "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
1918 blobQry
= "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class WHERE relkind = 'l'";
1920 res
= PQexec(g_conn
, blobQry
);
1921 check_sql_result(res
, g_conn
, blobQry
, PGRES_COMMAND_OK
);
1923 /* Command to fetch from cursor */
1924 blobFetchQry
= "FETCH 1000 IN bloboid";
1931 res
= PQexec(g_conn
, blobFetchQry
);
1932 check_sql_result(res
, g_conn
, blobFetchQry
, PGRES_TUPLES_OK
);
1934 /* Process the tuples, if any */
1935 for (i
= 0; i
< PQntuples(res
); i
++)
1940 blobOid
= atooid(PQgetvalue(res
, i
, 0));
1942 loFd
= lo_open(g_conn
, blobOid
, INV_READ
);
1945 write_msg(NULL
, "dumpBlobs(): could not open large object: %s",
1946 PQerrorMessage(g_conn
));
1950 StartBlob(AH
, blobOid
);
1952 /* Now read it in chunks, sending data to archive */
1955 cnt
= lo_read(g_conn
, loFd
, buf
, LOBBUFSIZE
);
1958 write_msg(NULL
, "dumpBlobs(): error reading large object: %s",
1959 PQerrorMessage(g_conn
));
1963 WriteData(AH
, buf
, cnt
);
1966 lo_close(g_conn
, loFd
);
1968 EndBlob(AH
, blobOid
);
1970 } while (PQntuples(res
) > 0);
1979 * dump all blob comments
1981 * Since we don't provide any way to be selective about dumping blobs,
1982 * there's no need to be selective about their comments either. We put
1983 * all the comments into one big TOC entry.
1986 dumpBlobComments(Archive
*AH
, void *arg
)
1988 const char *blobQry
;
1989 const char *blobFetchQry
;
1990 PQExpBuffer commentcmd
= createPQExpBuffer();
1995 write_msg(NULL
, "saving large object comments\n");
1997 /* Make sure we are in proper schema */
1998 selectSourceSchema("pg_catalog");
2000 /* Cursor to get all BLOB comments */
2001 if (AH
->remoteVersion
>= 70300)
2002 blobQry
= "DECLARE blobcmt CURSOR FOR SELECT loid, "
2003 "obj_description(loid, 'pg_largeobject') "
2004 "FROM (SELECT DISTINCT loid FROM "
2005 "pg_description d JOIN pg_largeobject l ON (objoid = loid) "
2006 "WHERE classoid = 'pg_largeobject'::regclass) ss";
2007 else if (AH
->remoteVersion
>= 70200)
2008 blobQry
= "DECLARE blobcmt CURSOR FOR SELECT loid, "
2009 "obj_description(loid, 'pg_largeobject') "
2010 "FROM (SELECT DISTINCT loid FROM pg_largeobject) ss";
2011 else if (AH
->remoteVersion
>= 70100)
2012 blobQry
= "DECLARE blobcmt CURSOR FOR SELECT loid, "
2013 "obj_description(loid) "
2014 "FROM (SELECT DISTINCT loid FROM pg_largeobject) ss";
2016 blobQry
= "DECLARE blobcmt CURSOR FOR SELECT oid, "
2018 " SELECT description "
2019 " FROM pg_description pd "
2020 " WHERE pd.objoid=pc.oid "
2022 "FROM pg_class pc WHERE relkind = 'l'";
2024 res
= PQexec(g_conn
, blobQry
);
2025 check_sql_result(res
, g_conn
, blobQry
, PGRES_COMMAND_OK
);
2027 /* Command to fetch from cursor */
2028 blobFetchQry
= "FETCH 100 IN blobcmt";
2035 res
= PQexec(g_conn
, blobFetchQry
);
2036 check_sql_result(res
, g_conn
, blobFetchQry
, PGRES_TUPLES_OK
);
2038 /* Process the tuples, if any */
2039 for (i
= 0; i
< PQntuples(res
); i
++)
2044 /* ignore blobs without comments */
2045 if (PQgetisnull(res
, i
, 1))
2048 blobOid
= atooid(PQgetvalue(res
, i
, 0));
2049 comment
= PQgetvalue(res
, i
, 1);
2051 printfPQExpBuffer(commentcmd
, "COMMENT ON LARGE OBJECT %u IS ",
2053 appendStringLiteralAH(commentcmd
, comment
, AH
);
2054 appendPQExpBuffer(commentcmd
, ";\n");
2056 archputs(commentcmd
->data
, AH
);
2058 } while (PQntuples(res
) > 0);
2064 destroyPQExpBuffer(commentcmd
);
2071 * read all namespaces in the system catalogs and return them in the
2072 * NamespaceInfo* structure
2074 * numNamespaces is set to the number of namespaces read in
2077 getNamespaces(int *numNamespaces
)
2083 NamespaceInfo
*nsinfo
;
2091 * Before 7.3, there are no real namespaces; create two dummy entries, one
2092 * for user stuff and one for system stuff.
2094 if (g_fout
->remoteVersion
< 70300)
2096 nsinfo
= (NamespaceInfo
*) malloc(2 * sizeof(NamespaceInfo
));
2098 nsinfo
[0].dobj
.objType
= DO_NAMESPACE
;
2099 nsinfo
[0].dobj
.catId
.tableoid
= 0;
2100 nsinfo
[0].dobj
.catId
.oid
= 0;
2101 AssignDumpId(&nsinfo
[0].dobj
);
2102 nsinfo
[0].dobj
.name
= strdup("public");
2103 nsinfo
[0].rolname
= strdup("");
2104 nsinfo
[0].nspacl
= strdup("");
2106 selectDumpableNamespace(&nsinfo
[0]);
2108 nsinfo
[1].dobj
.objType
= DO_NAMESPACE
;
2109 nsinfo
[1].dobj
.catId
.tableoid
= 0;
2110 nsinfo
[1].dobj
.catId
.oid
= 1;
2111 AssignDumpId(&nsinfo
[1].dobj
);
2112 nsinfo
[1].dobj
.name
= strdup("pg_catalog");
2113 nsinfo
[1].rolname
= strdup("");
2114 nsinfo
[1].nspacl
= strdup("");
2116 selectDumpableNamespace(&nsinfo
[1]);
2118 g_namespaces
= nsinfo
;
2119 g_numNamespaces
= *numNamespaces
= 2;
2124 query
= createPQExpBuffer();
2126 /* Make sure we are in proper schema */
2127 selectSourceSchema("pg_catalog");
2130 * we fetch all namespaces including system ones, so that every object we
2131 * read in can be linked to a containing namespace.
2133 appendPQExpBuffer(query
, "SELECT tableoid, oid, nspname, "
2134 "(%s nspowner) AS rolname, "
2135 "nspacl FROM pg_namespace",
2138 res
= PQexec(g_conn
, query
->data
);
2139 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2141 ntups
= PQntuples(res
);
2143 nsinfo
= (NamespaceInfo
*) malloc(ntups
* sizeof(NamespaceInfo
));
2145 i_tableoid
= PQfnumber(res
, "tableoid");
2146 i_oid
= PQfnumber(res
, "oid");
2147 i_nspname
= PQfnumber(res
, "nspname");
2148 i_rolname
= PQfnumber(res
, "rolname");
2149 i_nspacl
= PQfnumber(res
, "nspacl");
2151 for (i
= 0; i
< ntups
; i
++)
2153 nsinfo
[i
].dobj
.objType
= DO_NAMESPACE
;
2154 nsinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2155 nsinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2156 AssignDumpId(&nsinfo
[i
].dobj
);
2157 nsinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_nspname
));
2158 nsinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2159 nsinfo
[i
].nspacl
= strdup(PQgetvalue(res
, i
, i_nspacl
));
2161 /* Decide whether to dump this namespace */
2162 selectDumpableNamespace(&nsinfo
[i
]);
2164 if (strlen(nsinfo
[i
].rolname
) == 0)
2165 write_msg(NULL
, "WARNING: owner of schema \"%s\" appears to be invalid\n",
2166 nsinfo
[i
].dobj
.name
);
2170 destroyPQExpBuffer(query
);
2172 g_namespaces
= nsinfo
;
2173 g_numNamespaces
= *numNamespaces
= ntups
;
2180 * given a namespace OID and an object OID, look up the info read by
2183 * NB: for pre-7.3 source database, we use object OID to guess whether it's
2184 * a system object or not. In 7.3 and later there is no guessing.
2186 static NamespaceInfo
*
2187 findNamespace(Oid nsoid
, Oid objoid
)
2191 if (g_fout
->remoteVersion
>= 70300)
2193 for (i
= 0; i
< g_numNamespaces
; i
++)
2195 NamespaceInfo
*nsinfo
= &g_namespaces
[i
];
2197 if (nsoid
== nsinfo
->dobj
.catId
.oid
)
2200 write_msg(NULL
, "schema with OID %u does not exist\n", nsoid
);
2205 /* This code depends on the layout set up by getNamespaces. */
2206 if (objoid
> g_last_builtin_oid
)
2207 i
= 0; /* user object */
2209 i
= 1; /* system object */
2210 return &g_namespaces
[i
];
2213 return NULL
; /* keep compiler quiet */
2218 * read all types in the system catalogs and return them in the
2219 * TypeInfo* structure
2221 * numTypes is set to the number of types read in
2223 * NB: this must run after getFuncs() because we assume we can do
2227 getTypes(int *numTypes
)
2232 PQExpBuffer query
= createPQExpBuffer();
2234 ShellTypeInfo
*stinfo
;
2250 * we include even the built-in types because those may be used as array
2251 * elements by user-defined types
2253 * we filter out the built-in types when we dump out the types
2255 * same approach for undefined (shell) types and array types
2257 * Note: as of 8.3 we can reliably detect whether a type is an
2258 * auto-generated array type by checking the element type's typarray.
2259 * (Before that the test is capable of generating false positives.) We
2260 * still check for name beginning with '_', though, so as to avoid the
2261 * cost of the subselect probe for all standard types. This would have to
2262 * be revisited if the backend ever allows renaming of array types.
2265 /* Make sure we are in proper schema */
2266 selectSourceSchema("pg_catalog");
2268 if (g_fout
->remoteVersion
>= 80300)
2270 appendPQExpBuffer(query
, "SELECT tableoid, oid, typname, "
2272 "(%s typowner) AS rolname, "
2273 "typinput::oid AS typinput, "
2274 "typoutput::oid AS typoutput, typelem, typrelid, "
2275 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2276 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2277 "typtype, typisdefined, "
2278 "typname[0] = '_' AND typelem != 0 AND "
2279 "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
2283 else if (g_fout
->remoteVersion
>= 70300)
2285 appendPQExpBuffer(query
, "SELECT tableoid, oid, typname, "
2287 "(%s typowner) AS rolname, "
2288 "typinput::oid AS typinput, "
2289 "typoutput::oid AS typoutput, typelem, typrelid, "
2290 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2291 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2292 "typtype, typisdefined, "
2293 "typname[0] = '_' AND typelem != 0 AS isarray "
2297 else if (g_fout
->remoteVersion
>= 70100)
2299 appendPQExpBuffer(query
, "SELECT tableoid, oid, typname, "
2300 "0::oid AS typnamespace, "
2301 "(%s typowner) AS rolname, "
2302 "typinput::oid AS typinput, "
2303 "typoutput::oid AS typoutput, typelem, typrelid, "
2304 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2305 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2306 "typtype, typisdefined, "
2307 "typname[0] = '_' AND typelem != 0 AS isarray "
2313 appendPQExpBuffer(query
, "SELECT "
2314 "(SELECT oid FROM pg_class WHERE relname = 'pg_type') AS tableoid, "
2316 "0::oid AS typnamespace, "
2317 "(%s typowner) AS rolname, "
2318 "typinput::oid AS typinput, "
2319 "typoutput::oid AS typoutput, typelem, typrelid, "
2320 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
2321 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
2322 "typtype, typisdefined, "
2323 "typname[0] = '_' AND typelem != 0 AS isarray "
2328 res
= PQexec(g_conn
, query
->data
);
2329 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2331 ntups
= PQntuples(res
);
2333 tinfo
= (TypeInfo
*) malloc(ntups
* sizeof(TypeInfo
));
2335 i_tableoid
= PQfnumber(res
, "tableoid");
2336 i_oid
= PQfnumber(res
, "oid");
2337 i_typname
= PQfnumber(res
, "typname");
2338 i_typnamespace
= PQfnumber(res
, "typnamespace");
2339 i_rolname
= PQfnumber(res
, "rolname");
2340 i_typinput
= PQfnumber(res
, "typinput");
2341 i_typoutput
= PQfnumber(res
, "typoutput");
2342 i_typelem
= PQfnumber(res
, "typelem");
2343 i_typrelid
= PQfnumber(res
, "typrelid");
2344 i_typrelkind
= PQfnumber(res
, "typrelkind");
2345 i_typtype
= PQfnumber(res
, "typtype");
2346 i_typisdefined
= PQfnumber(res
, "typisdefined");
2347 i_isarray
= PQfnumber(res
, "isarray");
2349 for (i
= 0; i
< ntups
; i
++)
2351 tinfo
[i
].dobj
.objType
= DO_TYPE
;
2352 tinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2353 tinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2354 AssignDumpId(&tinfo
[i
].dobj
);
2355 tinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_typname
));
2356 tinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_typnamespace
)),
2357 tinfo
[i
].dobj
.catId
.oid
);
2358 tinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2359 tinfo
[i
].typelem
= atooid(PQgetvalue(res
, i
, i_typelem
));
2360 tinfo
[i
].typrelid
= atooid(PQgetvalue(res
, i
, i_typrelid
));
2361 tinfo
[i
].typrelkind
= *PQgetvalue(res
, i
, i_typrelkind
);
2362 tinfo
[i
].typtype
= *PQgetvalue(res
, i
, i_typtype
);
2363 tinfo
[i
].shellType
= NULL
;
2365 if (strcmp(PQgetvalue(res
, i
, i_typisdefined
), "t") == 0)
2366 tinfo
[i
].isDefined
= true;
2368 tinfo
[i
].isDefined
= false;
2370 if (strcmp(PQgetvalue(res
, i
, i_isarray
), "t") == 0)
2371 tinfo
[i
].isArray
= true;
2373 tinfo
[i
].isArray
= false;
2375 /* Decide whether we want to dump it */
2376 selectDumpableType(&tinfo
[i
]);
2379 * If it's a domain, fetch info about its constraints, if any
2381 tinfo
[i
].nDomChecks
= 0;
2382 tinfo
[i
].domChecks
= NULL
;
2383 if (tinfo
[i
].dobj
.dump
&& tinfo
[i
].typtype
== TYPTYPE_DOMAIN
)
2384 getDomainConstraints(&(tinfo
[i
]));
2387 * If it's a base type, make a DumpableObject representing a shell
2388 * definition of the type. We will need to dump that ahead of the I/O
2389 * functions for the type.
2391 * Note: the shell type doesn't have a catId. You might think it
2392 * should copy the base type's catId, but then it might capture the
2393 * pg_depend entries for the type, which we don't want.
2395 if (tinfo
[i
].dobj
.dump
&& tinfo
[i
].typtype
== TYPTYPE_BASE
)
2397 stinfo
= (ShellTypeInfo
*) malloc(sizeof(ShellTypeInfo
));
2398 stinfo
->dobj
.objType
= DO_SHELL_TYPE
;
2399 stinfo
->dobj
.catId
= nilCatalogId
;
2400 AssignDumpId(&stinfo
->dobj
);
2401 stinfo
->dobj
.name
= strdup(tinfo
[i
].dobj
.name
);
2402 stinfo
->dobj
.namespace = tinfo
[i
].dobj
.namespace;
2403 stinfo
->baseType
= &(tinfo
[i
]);
2404 tinfo
[i
].shellType
= stinfo
;
2407 * Initially mark the shell type as not to be dumped. We'll only
2408 * dump it if the I/O functions need to be dumped; this is taken
2409 * care of while sorting dependencies.
2411 stinfo
->dobj
.dump
= false;
2414 * However, if dumping from pre-7.3, there will be no dependency
2415 * info so we have to fake it here. We only need to worry about
2416 * typinput and typoutput since the other functions only exist
2419 if (g_fout
->remoteVersion
< 70300)
2425 typinput
= atooid(PQgetvalue(res
, i
, i_typinput
));
2426 typoutput
= atooid(PQgetvalue(res
, i
, i_typoutput
));
2428 funcInfo
= findFuncByOid(typinput
);
2429 if (funcInfo
&& funcInfo
->dobj
.dump
)
2431 /* base type depends on function */
2432 addObjectDependency(&tinfo
[i
].dobj
,
2433 funcInfo
->dobj
.dumpId
);
2434 /* function depends on shell type */
2435 addObjectDependency(&funcInfo
->dobj
,
2436 stinfo
->dobj
.dumpId
);
2437 /* mark shell type as to be dumped */
2438 stinfo
->dobj
.dump
= true;
2441 funcInfo
= findFuncByOid(typoutput
);
2442 if (funcInfo
&& funcInfo
->dobj
.dump
)
2444 /* base type depends on function */
2445 addObjectDependency(&tinfo
[i
].dobj
,
2446 funcInfo
->dobj
.dumpId
);
2447 /* function depends on shell type */
2448 addObjectDependency(&funcInfo
->dobj
,
2449 stinfo
->dobj
.dumpId
);
2450 /* mark shell type as to be dumped */
2451 stinfo
->dobj
.dump
= true;
2456 if (strlen(tinfo
[i
].rolname
) == 0 && tinfo
[i
].isDefined
)
2457 write_msg(NULL
, "WARNING: owner of data type \"%s\" appears to be invalid\n",
2458 tinfo
[i
].dobj
.name
);
2465 destroyPQExpBuffer(query
);
2472 * read all operators in the system catalogs and return them in the
2473 * OprInfo* structure
2475 * numOprs is set to the number of operators read in
2478 getOperators(int *numOprs
)
2483 PQExpBuffer query
= createPQExpBuffer();
2493 * find all operators, including builtin operators; we filter out
2494 * system-defined operators at dump-out time.
2497 /* Make sure we are in proper schema */
2498 selectSourceSchema("pg_catalog");
2500 if (g_fout
->remoteVersion
>= 70300)
2502 appendPQExpBuffer(query
, "SELECT tableoid, oid, oprname, "
2504 "(%s oprowner) AS rolname, "
2505 "oprcode::oid AS oprcode "
2509 else if (g_fout
->remoteVersion
>= 70100)
2511 appendPQExpBuffer(query
, "SELECT tableoid, oid, oprname, "
2512 "0::oid AS oprnamespace, "
2513 "(%s oprowner) AS rolname, "
2514 "oprcode::oid AS oprcode "
2520 appendPQExpBuffer(query
, "SELECT "
2521 "(SELECT oid FROM pg_class WHERE relname = 'pg_operator') AS tableoid, "
2523 "0::oid AS oprnamespace, "
2524 "(%s oprowner) AS rolname, "
2525 "oprcode::oid AS oprcode "
2530 res
= PQexec(g_conn
, query
->data
);
2531 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2533 ntups
= PQntuples(res
);
2536 oprinfo
= (OprInfo
*) malloc(ntups
* sizeof(OprInfo
));
2538 i_tableoid
= PQfnumber(res
, "tableoid");
2539 i_oid
= PQfnumber(res
, "oid");
2540 i_oprname
= PQfnumber(res
, "oprname");
2541 i_oprnamespace
= PQfnumber(res
, "oprnamespace");
2542 i_rolname
= PQfnumber(res
, "rolname");
2543 i_oprcode
= PQfnumber(res
, "oprcode");
2545 for (i
= 0; i
< ntups
; i
++)
2547 oprinfo
[i
].dobj
.objType
= DO_OPERATOR
;
2548 oprinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2549 oprinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2550 AssignDumpId(&oprinfo
[i
].dobj
);
2551 oprinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_oprname
));
2552 oprinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_oprnamespace
)),
2553 oprinfo
[i
].dobj
.catId
.oid
);
2554 oprinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2555 oprinfo
[i
].oprcode
= atooid(PQgetvalue(res
, i
, i_oprcode
));
2557 /* Decide whether we want to dump it */
2558 selectDumpableObject(&(oprinfo
[i
].dobj
));
2560 if (strlen(oprinfo
[i
].rolname
) == 0)
2561 write_msg(NULL
, "WARNING: owner of operator \"%s\" appears to be invalid\n",
2562 oprinfo
[i
].dobj
.name
);
2567 destroyPQExpBuffer(query
);
2574 * read all conversions in the system catalogs and return them in the
2575 * ConvInfo* structure
2577 * numConversions is set to the number of conversions read in
2580 getConversions(int *numConversions
)
2585 PQExpBuffer query
= createPQExpBuffer();
2593 /* Conversions didn't exist pre-7.3 */
2594 if (g_fout
->remoteVersion
< 70300)
2596 *numConversions
= 0;
2601 * find all conversions, including builtin conversions; we filter out
2602 * system-defined conversions at dump-out time.
2605 /* Make sure we are in proper schema */
2606 selectSourceSchema("pg_catalog");
2608 appendPQExpBuffer(query
, "SELECT tableoid, oid, conname, "
2610 "(%s conowner) AS rolname "
2611 "FROM pg_conversion",
2614 res
= PQexec(g_conn
, query
->data
);
2615 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2617 ntups
= PQntuples(res
);
2618 *numConversions
= ntups
;
2620 convinfo
= (ConvInfo
*) malloc(ntups
* sizeof(ConvInfo
));
2622 i_tableoid
= PQfnumber(res
, "tableoid");
2623 i_oid
= PQfnumber(res
, "oid");
2624 i_conname
= PQfnumber(res
, "conname");
2625 i_connamespace
= PQfnumber(res
, "connamespace");
2626 i_rolname
= PQfnumber(res
, "rolname");
2628 for (i
= 0; i
< ntups
; i
++)
2630 convinfo
[i
].dobj
.objType
= DO_CONVERSION
;
2631 convinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2632 convinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2633 AssignDumpId(&convinfo
[i
].dobj
);
2634 convinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_conname
));
2635 convinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_connamespace
)),
2636 convinfo
[i
].dobj
.catId
.oid
);
2637 convinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2639 /* Decide whether we want to dump it */
2640 selectDumpableObject(&(convinfo
[i
].dobj
));
2645 destroyPQExpBuffer(query
);
2652 * read all opclasses in the system catalogs and return them in the
2653 * OpclassInfo* structure
2655 * numOpclasses is set to the number of opclasses read in
2658 getOpclasses(int *numOpclasses
)
2663 PQExpBuffer query
= createPQExpBuffer();
2664 OpclassInfo
*opcinfo
;
2672 * find all opclasses, including builtin opclasses; we filter out
2673 * system-defined opclasses at dump-out time.
2676 /* Make sure we are in proper schema */
2677 selectSourceSchema("pg_catalog");
2679 if (g_fout
->remoteVersion
>= 70300)
2681 appendPQExpBuffer(query
, "SELECT tableoid, oid, opcname, "
2683 "(%s opcowner) AS rolname "
2687 else if (g_fout
->remoteVersion
>= 70100)
2689 appendPQExpBuffer(query
, "SELECT tableoid, oid, opcname, "
2690 "0::oid AS opcnamespace, "
2691 "''::name AS rolname "
2696 appendPQExpBuffer(query
, "SELECT "
2697 "(SELECT oid FROM pg_class WHERE relname = 'pg_opclass') AS tableoid, "
2699 "0::oid AS opcnamespace, "
2700 "''::name AS rolname "
2704 res
= PQexec(g_conn
, query
->data
);
2705 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2707 ntups
= PQntuples(res
);
2708 *numOpclasses
= ntups
;
2710 opcinfo
= (OpclassInfo
*) malloc(ntups
* sizeof(OpclassInfo
));
2712 i_tableoid
= PQfnumber(res
, "tableoid");
2713 i_oid
= PQfnumber(res
, "oid");
2714 i_opcname
= PQfnumber(res
, "opcname");
2715 i_opcnamespace
= PQfnumber(res
, "opcnamespace");
2716 i_rolname
= PQfnumber(res
, "rolname");
2718 for (i
= 0; i
< ntups
; i
++)
2720 opcinfo
[i
].dobj
.objType
= DO_OPCLASS
;
2721 opcinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2722 opcinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2723 AssignDumpId(&opcinfo
[i
].dobj
);
2724 opcinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_opcname
));
2725 opcinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_opcnamespace
)),
2726 opcinfo
[i
].dobj
.catId
.oid
);
2727 opcinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2729 /* Decide whether we want to dump it */
2730 selectDumpableObject(&(opcinfo
[i
].dobj
));
2732 if (g_fout
->remoteVersion
>= 70300)
2734 if (strlen(opcinfo
[i
].rolname
) == 0)
2735 write_msg(NULL
, "WARNING: owner of operator class \"%s\" appears to be invalid\n",
2736 opcinfo
[i
].dobj
.name
);
2742 destroyPQExpBuffer(query
);
2749 * read all opfamilies in the system catalogs and return them in the
2750 * OpfamilyInfo* structure
2752 * numOpfamilies is set to the number of opfamilies read in
2755 getOpfamilies(int *numOpfamilies
)
2761 OpfamilyInfo
*opfinfo
;
2768 /* Before 8.3, there is no separate concept of opfamilies */
2769 if (g_fout
->remoteVersion
< 80300)
2775 query
= createPQExpBuffer();
2778 * find all opfamilies, including builtin opfamilies; we filter out
2779 * system-defined opfamilies at dump-out time.
2782 /* Make sure we are in proper schema */
2783 selectSourceSchema("pg_catalog");
2785 appendPQExpBuffer(query
, "SELECT tableoid, oid, opfname, "
2787 "(%s opfowner) AS rolname "
2791 res
= PQexec(g_conn
, query
->data
);
2792 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2794 ntups
= PQntuples(res
);
2795 *numOpfamilies
= ntups
;
2797 opfinfo
= (OpfamilyInfo
*) malloc(ntups
* sizeof(OpfamilyInfo
));
2799 i_tableoid
= PQfnumber(res
, "tableoid");
2800 i_oid
= PQfnumber(res
, "oid");
2801 i_opfname
= PQfnumber(res
, "opfname");
2802 i_opfnamespace
= PQfnumber(res
, "opfnamespace");
2803 i_rolname
= PQfnumber(res
, "rolname");
2805 for (i
= 0; i
< ntups
; i
++)
2807 opfinfo
[i
].dobj
.objType
= DO_OPFAMILY
;
2808 opfinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2809 opfinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2810 AssignDumpId(&opfinfo
[i
].dobj
);
2811 opfinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_opfname
));
2812 opfinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_opfnamespace
)),
2813 opfinfo
[i
].dobj
.catId
.oid
);
2814 opfinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2816 /* Decide whether we want to dump it */
2817 selectDumpableObject(&(opfinfo
[i
].dobj
));
2819 if (g_fout
->remoteVersion
>= 70300)
2821 if (strlen(opfinfo
[i
].rolname
) == 0)
2822 write_msg(NULL
, "WARNING: owner of operator family \"%s\" appears to be invalid\n",
2823 opfinfo
[i
].dobj
.name
);
2829 destroyPQExpBuffer(query
);
2836 * read all the user-defined aggregates in the system catalogs and
2837 * return them in the AggInfo* structure
2839 * numAggs is set to the number of aggregates read in
2842 getAggregates(int *numAggs
)
2847 PQExpBuffer query
= createPQExpBuffer();
2858 /* Make sure we are in proper schema */
2859 selectSourceSchema("pg_catalog");
2861 /* find all user-defined aggregates */
2863 if (g_fout
->remoteVersion
>= 80200)
2865 appendPQExpBuffer(query
, "SELECT tableoid, oid, proname AS aggname, "
2866 "pronamespace AS aggnamespace, "
2867 "pronargs, proargtypes, "
2868 "(%s proowner) AS rolname, "
2872 "AND pronamespace != "
2873 "(SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog')",
2876 else if (g_fout
->remoteVersion
>= 70300)
2878 appendPQExpBuffer(query
, "SELECT tableoid, oid, proname AS aggname, "
2879 "pronamespace AS aggnamespace, "
2880 "CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, "
2882 "(%s proowner) AS rolname, "
2886 "AND pronamespace != "
2887 "(SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog')",
2890 else if (g_fout
->remoteVersion
>= 70100)
2892 appendPQExpBuffer(query
, "SELECT tableoid, oid, aggname, "
2893 "0::oid AS aggnamespace, "
2894 "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
2895 "aggbasetype AS proargtypes, "
2896 "(%s aggowner) AS rolname, "
2898 "FROM pg_aggregate "
2899 "where oid > '%u'::oid",
2901 g_last_builtin_oid
);
2905 appendPQExpBuffer(query
, "SELECT "
2906 "(SELECT oid FROM pg_class WHERE relname = 'pg_aggregate') AS tableoid, "
2908 "0::oid AS aggnamespace, "
2909 "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
2910 "aggbasetype AS proargtypes, "
2911 "(%s aggowner) AS rolname, "
2913 "FROM pg_aggregate "
2914 "where oid > '%u'::oid",
2916 g_last_builtin_oid
);
2919 res
= PQexec(g_conn
, query
->data
);
2920 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
2922 ntups
= PQntuples(res
);
2925 agginfo
= (AggInfo
*) malloc(ntups
* sizeof(AggInfo
));
2927 i_tableoid
= PQfnumber(res
, "tableoid");
2928 i_oid
= PQfnumber(res
, "oid");
2929 i_aggname
= PQfnumber(res
, "aggname");
2930 i_aggnamespace
= PQfnumber(res
, "aggnamespace");
2931 i_pronargs
= PQfnumber(res
, "pronargs");
2932 i_proargtypes
= PQfnumber(res
, "proargtypes");
2933 i_rolname
= PQfnumber(res
, "rolname");
2934 i_aggacl
= PQfnumber(res
, "aggacl");
2936 for (i
= 0; i
< ntups
; i
++)
2938 agginfo
[i
].aggfn
.dobj
.objType
= DO_AGG
;
2939 agginfo
[i
].aggfn
.dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
2940 agginfo
[i
].aggfn
.dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
2941 AssignDumpId(&agginfo
[i
].aggfn
.dobj
);
2942 agginfo
[i
].aggfn
.dobj
.name
= strdup(PQgetvalue(res
, i
, i_aggname
));
2943 agginfo
[i
].aggfn
.dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_aggnamespace
)),
2944 agginfo
[i
].aggfn
.dobj
.catId
.oid
);
2945 agginfo
[i
].aggfn
.rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
2946 if (strlen(agginfo
[i
].aggfn
.rolname
) == 0)
2947 write_msg(NULL
, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
2948 agginfo
[i
].aggfn
.dobj
.name
);
2949 agginfo
[i
].aggfn
.lang
= InvalidOid
; /* not currently interesting */
2950 agginfo
[i
].aggfn
.prorettype
= InvalidOid
; /* not saved */
2951 agginfo
[i
].aggfn
.proacl
= strdup(PQgetvalue(res
, i
, i_aggacl
));
2952 agginfo
[i
].aggfn
.nargs
= atoi(PQgetvalue(res
, i
, i_pronargs
));
2953 if (agginfo
[i
].aggfn
.nargs
== 0)
2954 agginfo
[i
].aggfn
.argtypes
= NULL
;
2957 agginfo
[i
].aggfn
.argtypes
= (Oid
*) malloc(agginfo
[i
].aggfn
.nargs
* sizeof(Oid
));
2958 if (g_fout
->remoteVersion
>= 70300)
2959 parseOidArray(PQgetvalue(res
, i
, i_proargtypes
),
2960 agginfo
[i
].aggfn
.argtypes
,
2961 agginfo
[i
].aggfn
.nargs
);
2963 /* it's just aggbasetype */
2964 agginfo
[i
].aggfn
.argtypes
[0] = atooid(PQgetvalue(res
, i
, i_proargtypes
));
2967 /* Decide whether we want to dump it */
2968 selectDumpableObject(&(agginfo
[i
].aggfn
.dobj
));
2973 destroyPQExpBuffer(query
);
2980 * read all the user-defined functions in the system catalogs and
2981 * return them in the FuncInfo* structure
2983 * numFuncs is set to the number of functions read in
2986 getFuncs(int *numFuncs
)
2991 PQExpBuffer query
= createPQExpBuffer();
3004 /* Make sure we are in proper schema */
3005 selectSourceSchema("pg_catalog");
3007 /* find all user-defined funcs */
3009 if (g_fout
->remoteVersion
>= 70300)
3011 appendPQExpBuffer(query
,
3012 "SELECT tableoid, oid, proname, prolang, "
3013 "pronargs, proargtypes, prorettype, proacl, "
3015 "(%s proowner) AS rolname "
3017 "WHERE NOT proisagg "
3018 "AND pronamespace != "
3019 "(SELECT oid FROM pg_namespace "
3020 "WHERE nspname = 'pg_catalog')",
3023 else if (g_fout
->remoteVersion
>= 70100)
3025 appendPQExpBuffer(query
,
3026 "SELECT tableoid, oid, proname, prolang, "
3027 "pronargs, proargtypes, prorettype, "
3028 "'{=X}' AS proacl, "
3029 "0::oid AS pronamespace, "
3030 "(%s proowner) AS rolname "
3032 "WHERE pg_proc.oid > '%u'::oid",
3034 g_last_builtin_oid
);
3038 appendPQExpBuffer(query
,
3040 "(SELECT oid FROM pg_class "
3041 " WHERE relname = 'pg_proc') AS tableoid, "
3042 "oid, proname, prolang, "
3043 "pronargs, proargtypes, prorettype, "
3044 "'{=X}' AS proacl, "
3045 "0::oid AS pronamespace, "
3046 "(%s proowner) AS rolname "
3048 "where pg_proc.oid > '%u'::oid",
3050 g_last_builtin_oid
);
3053 res
= PQexec(g_conn
, query
->data
);
3054 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3056 ntups
= PQntuples(res
);
3060 finfo
= (FuncInfo
*) calloc(ntups
, sizeof(FuncInfo
));
3062 i_tableoid
= PQfnumber(res
, "tableoid");
3063 i_oid
= PQfnumber(res
, "oid");
3064 i_proname
= PQfnumber(res
, "proname");
3065 i_pronamespace
= PQfnumber(res
, "pronamespace");
3066 i_rolname
= PQfnumber(res
, "rolname");
3067 i_prolang
= PQfnumber(res
, "prolang");
3068 i_pronargs
= PQfnumber(res
, "pronargs");
3069 i_proargtypes
= PQfnumber(res
, "proargtypes");
3070 i_prorettype
= PQfnumber(res
, "prorettype");
3071 i_proacl
= PQfnumber(res
, "proacl");
3073 for (i
= 0; i
< ntups
; i
++)
3075 finfo
[i
].dobj
.objType
= DO_FUNC
;
3076 finfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
3077 finfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
3078 AssignDumpId(&finfo
[i
].dobj
);
3079 finfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_proname
));
3080 finfo
[i
].dobj
.namespace =
3081 findNamespace(atooid(PQgetvalue(res
, i
, i_pronamespace
)),
3082 finfo
[i
].dobj
.catId
.oid
);
3083 finfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
3084 finfo
[i
].lang
= atooid(PQgetvalue(res
, i
, i_prolang
));
3085 finfo
[i
].prorettype
= atooid(PQgetvalue(res
, i
, i_prorettype
));
3086 finfo
[i
].proacl
= strdup(PQgetvalue(res
, i
, i_proacl
));
3087 finfo
[i
].nargs
= atoi(PQgetvalue(res
, i
, i_pronargs
));
3088 if (finfo
[i
].nargs
== 0)
3089 finfo
[i
].argtypes
= NULL
;
3092 finfo
[i
].argtypes
= (Oid
*) malloc(finfo
[i
].nargs
* sizeof(Oid
));
3093 parseOidArray(PQgetvalue(res
, i
, i_proargtypes
),
3094 finfo
[i
].argtypes
, finfo
[i
].nargs
);
3097 /* Decide whether we want to dump it */
3098 selectDumpableObject(&(finfo
[i
].dobj
));
3100 if (strlen(finfo
[i
].rolname
) == 0)
3102 "WARNING: owner of function \"%s\" appears to be invalid\n",
3103 finfo
[i
].dobj
.name
);
3108 destroyPQExpBuffer(query
);
3115 * read all the user-defined tables (no indexes, no catalogs)
3116 * in the system catalogs return them in the TableInfo* structure
3118 * numTables is set to the number of tables read in
3121 getTables(int *numTables
)
3126 PQExpBuffer query
= createPQExpBuffer();
3136 int i_relhastriggers
;
3143 int i_reltablespace
;
3145 int i_toastreloptions
;
3147 /* Make sure we are in proper schema */
3148 selectSourceSchema("pg_catalog");
3151 * Find all the tables (including views and sequences).
3153 * We include system catalogs, so that we can work if a user table is
3154 * defined to inherit from a system catalog (pretty weird, but...)
3156 * We ignore tables that are not type 'r' (ordinary relation), 'S'
3157 * (sequence), 'v' (view), or 'c' (composite type).
3159 * Composite-type table entries won't be dumped as such, but we have to
3160 * make a DumpableObject for them so that we can track dependencies of the
3161 * composite type (pg_depend entries for columns of the composite type
3162 * link to the pg_class entry not the pg_type entry).
3164 * Note: in this phase we should collect only a minimal amount of
3165 * information about each table, basically just enough to decide if it is
3166 * interesting. We must fetch all tables in this phase because otherwise
3167 * we cannot correctly identify inherited columns, owned sequences, etc.
3170 if (g_fout
->remoteVersion
>= 80400)
3173 * Left join to pick up dependency info linking sequences to their
3174 * owning column, if any (note this dependency is AUTO as of 8.2)
3176 appendPQExpBuffer(query
,
3177 "SELECT c.tableoid, c.oid, c.relname, "
3178 "c.relacl, c.relkind, c.relnamespace, "
3179 "(%s c.relowner) AS rolname, "
3180 "c.relchecks, c.relhastriggers, "
3181 "c.relhasindex, c.relhasrules, c.relhasoids, "
3183 "d.refobjid AS owning_tab, "
3184 "d.refobjsubid AS owning_col, "
3185 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3186 "array_to_string(c.reloptions, ', ') AS reloptions, "
3187 "array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions "
3189 "LEFT JOIN pg_depend d ON "
3190 "(c.relkind = '%c' AND "
3191 "d.classid = c.tableoid AND d.objid = c.oid AND "
3192 "d.objsubid = 0 AND "
3193 "d.refclassid = c.tableoid AND d.deptype = 'a') "
3194 "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
3195 "WHERE c.relkind in ('%c', '%c', '%c', '%c') "
3199 RELKIND_RELATION
, RELKIND_SEQUENCE
,
3200 RELKIND_VIEW
, RELKIND_COMPOSITE_TYPE
);
3202 else if (g_fout
->remoteVersion
>= 80200)
3205 * Left join to pick up dependency info linking sequences to their
3206 * owning column, if any (note this dependency is AUTO as of 8.2)
3208 appendPQExpBuffer(query
,
3209 "SELECT c.tableoid, c.oid, relname, "
3210 "relacl, relkind, relnamespace, "
3211 "(%s relowner) AS rolname, "
3212 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3213 "relhasindex, relhasrules, relhasoids, "
3215 "d.refobjid AS owning_tab, "
3216 "d.refobjsubid AS owning_col, "
3217 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3218 "array_to_string(c.reloptions, ', ') AS reloptions, "
3219 "NULL AS toast_reloptions "
3221 "LEFT JOIN pg_depend d ON "
3222 "(c.relkind = '%c' AND "
3223 "d.classid = c.tableoid AND d.objid = c.oid AND "
3224 "d.objsubid = 0 AND "
3225 "d.refclassid = c.tableoid AND d.deptype = 'a') "
3226 "WHERE relkind in ('%c', '%c', '%c', '%c') "
3230 RELKIND_RELATION
, RELKIND_SEQUENCE
,
3231 RELKIND_VIEW
, RELKIND_COMPOSITE_TYPE
);
3233 else if (g_fout
->remoteVersion
>= 80000)
3236 * Left join to pick up dependency info linking sequences to their
3237 * owning column, if any
3239 appendPQExpBuffer(query
,
3240 "SELECT c.tableoid, c.oid, relname, "
3241 "relacl, relkind, relnamespace, "
3242 "(%s relowner) AS rolname, "
3243 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3244 "relhasindex, relhasrules, relhasoids, "
3245 "0 AS relfrozenxid, "
3246 "d.refobjid AS owning_tab, "
3247 "d.refobjsubid AS owning_col, "
3248 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
3249 "NULL AS reloptions, "
3250 "NULL AS toast_reloptions "
3252 "LEFT JOIN pg_depend d ON "
3253 "(c.relkind = '%c' AND "
3254 "d.classid = c.tableoid AND d.objid = c.oid AND "
3255 "d.objsubid = 0 AND "
3256 "d.refclassid = c.tableoid AND d.deptype = 'i') "
3257 "WHERE relkind in ('%c', '%c', '%c', '%c') "
3261 RELKIND_RELATION
, RELKIND_SEQUENCE
,
3262 RELKIND_VIEW
, RELKIND_COMPOSITE_TYPE
);
3264 else if (g_fout
->remoteVersion
>= 70300)
3267 * Left join to pick up dependency info linking sequences to their
3268 * owning column, if any
3270 appendPQExpBuffer(query
,
3271 "SELECT c.tableoid, c.oid, relname, "
3272 "relacl, relkind, relnamespace, "
3273 "(%s relowner) AS rolname, "
3274 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3275 "relhasindex, relhasrules, relhasoids, "
3276 "0 AS relfrozenxid, "
3277 "d.refobjid AS owning_tab, "
3278 "d.refobjsubid AS owning_col, "
3279 "NULL AS reltablespace, "
3280 "NULL AS reloptions, "
3281 "NULL AS toast_reloptions "
3283 "LEFT JOIN pg_depend d ON "
3284 "(c.relkind = '%c' AND "
3285 "d.classid = c.tableoid AND d.objid = c.oid AND "
3286 "d.objsubid = 0 AND "
3287 "d.refclassid = c.tableoid AND d.deptype = 'i') "
3288 "WHERE relkind IN ('%c', '%c', '%c', '%c') "
3292 RELKIND_RELATION
, RELKIND_SEQUENCE
,
3293 RELKIND_VIEW
, RELKIND_COMPOSITE_TYPE
);
3295 else if (g_fout
->remoteVersion
>= 70200)
3297 appendPQExpBuffer(query
,
3298 "SELECT tableoid, oid, relname, relacl, relkind, "
3299 "0::oid AS relnamespace, "
3300 "(%s relowner) AS rolname, "
3301 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3302 "relhasindex, relhasrules, relhasoids, "
3303 "0 AS relfrozenxid, "
3304 "NULL::oid AS owning_tab, "
3305 "NULL::int4 AS owning_col, "
3306 "NULL AS reltablespace, "
3307 "NULL AS reloptions, "
3308 "NULL AS toast_reloptions "
3310 "WHERE relkind IN ('%c', '%c', '%c') "
3313 RELKIND_RELATION
, RELKIND_SEQUENCE
, RELKIND_VIEW
);
3315 else if (g_fout
->remoteVersion
>= 70100)
3317 /* all tables have oids in 7.1 */
3318 appendPQExpBuffer(query
,
3319 "SELECT tableoid, oid, relname, relacl, relkind, "
3320 "0::oid AS relnamespace, "
3321 "(%s relowner) AS rolname, "
3322 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3323 "relhasindex, relhasrules, "
3324 "'t'::bool AS relhasoids, "
3325 "0 AS relfrozenxid, "
3326 "NULL::oid AS owning_tab, "
3327 "NULL::int4 AS owning_col, "
3328 "NULL AS reltablespace, "
3329 "NULL AS reloptions, "
3330 "NULL AS toast_reloptions "
3332 "WHERE relkind IN ('%c', '%c', '%c') "
3335 RELKIND_RELATION
, RELKIND_SEQUENCE
, RELKIND_VIEW
);
3340 * Before 7.1, view relkind was not set to 'v', so we must check if we
3341 * have a view by looking for a rule in pg_rewrite.
3343 appendPQExpBuffer(query
,
3345 "(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
3346 "oid, relname, relacl, "
3347 "CASE WHEN relhasrules and relkind = 'r' "
3348 " and EXISTS(SELECT rulename FROM pg_rewrite r WHERE "
3349 " r.ev_class = c.oid AND r.ev_type = '1') "
3350 "THEN '%c'::\"char\" "
3351 "ELSE relkind END AS relkind,"
3352 "0::oid AS relnamespace, "
3353 "(%s relowner) AS rolname, "
3354 "relchecks, (reltriggers <> 0) AS relhastriggers, "
3355 "relhasindex, relhasrules, "
3356 "'t'::bool AS relhasoids, "
3357 "0 as relfrozenxid, "
3358 "NULL::oid AS owning_tab, "
3359 "NULL::int4 AS owning_col, "
3360 "NULL AS reltablespace, "
3361 "NULL AS reloptions, "
3362 "NULL AS toast_reloptions "
3364 "WHERE relkind IN ('%c', '%c') "
3368 RELKIND_RELATION
, RELKIND_SEQUENCE
);
3371 res
= PQexec(g_conn
, query
->data
);
3372 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3374 ntups
= PQntuples(res
);
3379 * Extract data from result and lock dumpable tables. We do the locking
3380 * before anything else, to minimize the window wherein a table could
3381 * disappear under us.
3383 * Note that we have to save info about all tables here, even when dumping
3384 * only one, because we don't yet know which tables might be inheritance
3385 * ancestors of the target table.
3387 tblinfo
= (TableInfo
*) calloc(ntups
, sizeof(TableInfo
));
3389 i_reltableoid
= PQfnumber(res
, "tableoid");
3390 i_reloid
= PQfnumber(res
, "oid");
3391 i_relname
= PQfnumber(res
, "relname");
3392 i_relnamespace
= PQfnumber(res
, "relnamespace");
3393 i_relacl
= PQfnumber(res
, "relacl");
3394 i_relkind
= PQfnumber(res
, "relkind");
3395 i_rolname
= PQfnumber(res
, "rolname");
3396 i_relchecks
= PQfnumber(res
, "relchecks");
3397 i_relhastriggers
= PQfnumber(res
, "relhastriggers");
3398 i_relhasindex
= PQfnumber(res
, "relhasindex");
3399 i_relhasrules
= PQfnumber(res
, "relhasrules");
3400 i_relhasoids
= PQfnumber(res
, "relhasoids");
3401 i_relfrozenxid
= PQfnumber(res
, "relfrozenxid");
3402 i_owning_tab
= PQfnumber(res
, "owning_tab");
3403 i_owning_col
= PQfnumber(res
, "owning_col");
3404 i_reltablespace
= PQfnumber(res
, "reltablespace");
3405 i_reloptions
= PQfnumber(res
, "reloptions");
3406 i_toastreloptions
= PQfnumber(res
, "toast_reloptions");
3408 if (lockWaitTimeout
&& g_fout
->remoteVersion
>= 70300)
3411 * Arrange to fail instead of waiting forever for a table lock.
3413 * NB: this coding assumes that the only queries issued within the
3414 * following loop are LOCK TABLEs; else the timeout may be undesirably
3415 * applied to other things too.
3417 resetPQExpBuffer(query
);
3418 appendPQExpBuffer(query
, "SET statement_timeout = ");
3419 appendStringLiteralConn(query
, lockWaitTimeout
, g_conn
);
3420 do_sql_command(g_conn
, query
->data
);
3423 for (i
= 0; i
< ntups
; i
++)
3425 tblinfo
[i
].dobj
.objType
= DO_TABLE
;
3426 tblinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_reltableoid
));
3427 tblinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_reloid
));
3428 AssignDumpId(&tblinfo
[i
].dobj
);
3429 tblinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_relname
));
3430 tblinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_relnamespace
)),
3431 tblinfo
[i
].dobj
.catId
.oid
);
3432 tblinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
3433 tblinfo
[i
].relacl
= strdup(PQgetvalue(res
, i
, i_relacl
));
3434 tblinfo
[i
].relkind
= *(PQgetvalue(res
, i
, i_relkind
));
3435 tblinfo
[i
].hasindex
= (strcmp(PQgetvalue(res
, i
, i_relhasindex
), "t") == 0);
3436 tblinfo
[i
].hasrules
= (strcmp(PQgetvalue(res
, i
, i_relhasrules
), "t") == 0);
3437 tblinfo
[i
].hastriggers
= (strcmp(PQgetvalue(res
, i
, i_relhastriggers
), "t") == 0);
3438 tblinfo
[i
].hasoids
= (strcmp(PQgetvalue(res
, i
, i_relhasoids
), "t") == 0);
3439 tblinfo
[i
].frozenxid
= atooid(PQgetvalue(res
, i
, i_relfrozenxid
));
3440 tblinfo
[i
].ncheck
= atoi(PQgetvalue(res
, i
, i_relchecks
));
3441 if (PQgetisnull(res
, i
, i_owning_tab
))
3443 tblinfo
[i
].owning_tab
= InvalidOid
;
3444 tblinfo
[i
].owning_col
= 0;
3448 tblinfo
[i
].owning_tab
= atooid(PQgetvalue(res
, i
, i_owning_tab
));
3449 tblinfo
[i
].owning_col
= atoi(PQgetvalue(res
, i
, i_owning_col
));
3451 tblinfo
[i
].reltablespace
= strdup(PQgetvalue(res
, i
, i_reltablespace
));
3452 tblinfo
[i
].reloptions
= strdup(PQgetvalue(res
, i
, i_reloptions
));
3453 tblinfo
[i
].toast_reloptions
= strdup(PQgetvalue(res
, i
, i_toastreloptions
));
3455 /* other fields were zeroed above */
3458 * Decide whether we want to dump this table.
3460 if (tblinfo
[i
].relkind
== RELKIND_COMPOSITE_TYPE
)
3461 tblinfo
[i
].dobj
.dump
= false;
3463 selectDumpableTable(&tblinfo
[i
]);
3464 tblinfo
[i
].interesting
= tblinfo
[i
].dobj
.dump
;
3467 * Read-lock target tables to make sure they aren't DROPPED or altered
3468 * in schema before we get around to dumping them.
3470 * Note that we don't explicitly lock parents of the target tables; we
3471 * assume our lock on the child is enough to prevent schema
3472 * alterations to parent tables.
3474 * NOTE: it'd be kinda nice to lock views and sequences too, not only
3475 * plain tables, but the backend doesn't presently allow that.
3477 if (tblinfo
[i
].dobj
.dump
&& tblinfo
[i
].relkind
== RELKIND_RELATION
)
3479 resetPQExpBuffer(query
);
3480 appendPQExpBuffer(query
,
3481 "LOCK TABLE %s IN ACCESS SHARE MODE",
3482 fmtQualifiedId(tblinfo
[i
].dobj
.namespace->dobj
.name
,
3483 tblinfo
[i
].dobj
.name
));
3484 do_sql_command(g_conn
, query
->data
);
3487 /* Emit notice if join for owner failed */
3488 if (strlen(tblinfo
[i
].rolname
) == 0)
3489 write_msg(NULL
, "WARNING: owner of table \"%s\" appears to be invalid\n",
3490 tblinfo
[i
].dobj
.name
);
3493 if (lockWaitTimeout
&& g_fout
->remoteVersion
>= 70300)
3495 do_sql_command(g_conn
, "SET statement_timeout = 0");
3501 * Force sequences that are "owned" by table columns to be dumped whenever
3502 * their owning table is being dumped.
3504 for (i
= 0; i
< ntups
; i
++)
3506 TableInfo
*seqinfo
= &tblinfo
[i
];
3509 if (!OidIsValid(seqinfo
->owning_tab
))
3510 continue; /* not an owned sequence */
3511 if (seqinfo
->dobj
.dump
)
3512 continue; /* no need to search */
3514 /* can't use findTableByOid yet, unfortunately */
3515 for (j
= 0; j
< ntups
; j
++)
3517 if (tblinfo
[j
].dobj
.catId
.oid
== seqinfo
->owning_tab
)
3519 if (tblinfo
[j
].dobj
.dump
)
3521 seqinfo
->interesting
= true;
3522 seqinfo
->dobj
.dump
= true;
3529 destroyPQExpBuffer(query
);
3536 * read all the inheritance information
3537 * from the system catalogs return them in the InhInfo* structure
3539 * numInherits is set to the number of pairs read in
3542 getInherits(int *numInherits
)
3547 PQExpBuffer query
= createPQExpBuffer();
3553 /* Make sure we are in proper schema */
3554 selectSourceSchema("pg_catalog");
3556 /* find all the inheritance information */
3558 appendPQExpBuffer(query
, "SELECT inhrelid, inhparent FROM pg_inherits");
3560 res
= PQexec(g_conn
, query
->data
);
3561 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3563 ntups
= PQntuples(res
);
3565 *numInherits
= ntups
;
3567 inhinfo
= (InhInfo
*) malloc(ntups
* sizeof(InhInfo
));
3569 i_inhrelid
= PQfnumber(res
, "inhrelid");
3570 i_inhparent
= PQfnumber(res
, "inhparent");
3572 for (i
= 0; i
< ntups
; i
++)
3574 inhinfo
[i
].inhrelid
= atooid(PQgetvalue(res
, i
, i_inhrelid
));
3575 inhinfo
[i
].inhparent
= atooid(PQgetvalue(res
, i
, i_inhparent
));
3580 destroyPQExpBuffer(query
);
3587 * get information about every index on a dumpable table
3589 * Note: index data is not returned directly to the caller, but it
3590 * does get entered into the DumpableObject tables.
3593 getIndexes(TableInfo tblinfo
[], int numTables
)
3597 PQExpBuffer query
= createPQExpBuffer();
3600 ConstraintInfo
*constrinfo
;
3616 for (i
= 0; i
< numTables
; i
++)
3618 TableInfo
*tbinfo
= &tblinfo
[i
];
3620 /* Only plain tables have indexes */
3621 if (tbinfo
->relkind
!= RELKIND_RELATION
|| !tbinfo
->hasindex
)
3624 /* Ignore indexes of tables not to be dumped */
3625 if (!tbinfo
->dobj
.dump
)
3629 write_msg(NULL
, "reading indexes for table \"%s\"\n",
3632 /* Make sure we are in proper schema so indexdef is right */
3633 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
3636 * The point of the messy-looking outer join is to find a constraint
3637 * that is related by an internal dependency link to the index. If we
3638 * find one, create a CONSTRAINT entry linked to the INDEX entry. We
3639 * assume an index won't have more than one internal dependency.
3641 resetPQExpBuffer(query
);
3642 if (g_fout
->remoteVersion
>= 80200)
3644 appendPQExpBuffer(query
,
3645 "SELECT t.tableoid, t.oid, "
3646 "t.relname AS indexname, "
3647 "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
3648 "t.relnatts AS indnkeys, "
3649 "i.indkey, i.indisclustered, "
3650 "c.contype, c.conname, "
3651 "c.tableoid AS contableoid, "
3653 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
3654 "array_to_string(t.reloptions, ', ') AS options "
3655 "FROM pg_catalog.pg_index i "
3656 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
3657 "LEFT JOIN pg_catalog.pg_depend d "
3658 "ON (d.classid = t.tableoid "
3659 "AND d.objid = t.oid "
3660 "AND d.deptype = 'i') "
3661 "LEFT JOIN pg_catalog.pg_constraint c "
3662 "ON (d.refclassid = c.tableoid "
3663 "AND d.refobjid = c.oid) "
3664 "WHERE i.indrelid = '%u'::pg_catalog.oid "
3665 "ORDER BY indexname",
3666 tbinfo
->dobj
.catId
.oid
);
3668 else if (g_fout
->remoteVersion
>= 80000)
3670 appendPQExpBuffer(query
,
3671 "SELECT t.tableoid, t.oid, "
3672 "t.relname AS indexname, "
3673 "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
3674 "t.relnatts AS indnkeys, "
3675 "i.indkey, i.indisclustered, "
3676 "c.contype, c.conname, "
3677 "c.tableoid AS contableoid, "
3679 "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
3681 "FROM pg_catalog.pg_index i "
3682 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
3683 "LEFT JOIN pg_catalog.pg_depend d "
3684 "ON (d.classid = t.tableoid "
3685 "AND d.objid = t.oid "
3686 "AND d.deptype = 'i') "
3687 "LEFT JOIN pg_catalog.pg_constraint c "
3688 "ON (d.refclassid = c.tableoid "
3689 "AND d.refobjid = c.oid) "
3690 "WHERE i.indrelid = '%u'::pg_catalog.oid "
3691 "ORDER BY indexname",
3692 tbinfo
->dobj
.catId
.oid
);
3694 else if (g_fout
->remoteVersion
>= 70300)
3696 appendPQExpBuffer(query
,
3697 "SELECT t.tableoid, t.oid, "
3698 "t.relname AS indexname, "
3699 "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
3700 "t.relnatts AS indnkeys, "
3701 "i.indkey, i.indisclustered, "
3702 "c.contype, c.conname, "
3703 "c.tableoid AS contableoid, "
3705 "NULL AS tablespace, "
3707 "FROM pg_catalog.pg_index i "
3708 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
3709 "LEFT JOIN pg_catalog.pg_depend d "
3710 "ON (d.classid = t.tableoid "
3711 "AND d.objid = t.oid "
3712 "AND d.deptype = 'i') "
3713 "LEFT JOIN pg_catalog.pg_constraint c "
3714 "ON (d.refclassid = c.tableoid "
3715 "AND d.refobjid = c.oid) "
3716 "WHERE i.indrelid = '%u'::pg_catalog.oid "
3717 "ORDER BY indexname",
3718 tbinfo
->dobj
.catId
.oid
);
3720 else if (g_fout
->remoteVersion
>= 70100)
3722 appendPQExpBuffer(query
,
3723 "SELECT t.tableoid, t.oid, "
3724 "t.relname AS indexname, "
3725 "pg_get_indexdef(i.indexrelid) AS indexdef, "
3726 "t.relnatts AS indnkeys, "
3727 "i.indkey, false AS indisclustered, "
3728 "CASE WHEN i.indisprimary THEN 'p'::char "
3729 "ELSE '0'::char END AS contype, "
3730 "t.relname AS conname, "
3731 "0::oid AS contableoid, "
3733 "NULL AS tablespace, "
3735 "FROM pg_index i, pg_class t "
3736 "WHERE t.oid = i.indexrelid "
3737 "AND i.indrelid = '%u'::oid "
3738 "ORDER BY indexname",
3739 tbinfo
->dobj
.catId
.oid
);
3743 appendPQExpBuffer(query
,
3745 "(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
3747 "t.relname AS indexname, "
3748 "pg_get_indexdef(i.indexrelid) AS indexdef, "
3749 "t.relnatts AS indnkeys, "
3750 "i.indkey, false AS indisclustered, "
3751 "CASE WHEN i.indisprimary THEN 'p'::char "
3752 "ELSE '0'::char END AS contype, "
3753 "t.relname AS conname, "
3754 "0::oid AS contableoid, "
3756 "NULL AS tablespace, "
3758 "FROM pg_index i, pg_class t "
3759 "WHERE t.oid = i.indexrelid "
3760 "AND i.indrelid = '%u'::oid "
3761 "ORDER BY indexname",
3762 tbinfo
->dobj
.catId
.oid
);
3765 res
= PQexec(g_conn
, query
->data
);
3766 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3768 ntups
= PQntuples(res
);
3770 i_tableoid
= PQfnumber(res
, "tableoid");
3771 i_oid
= PQfnumber(res
, "oid");
3772 i_indexname
= PQfnumber(res
, "indexname");
3773 i_indexdef
= PQfnumber(res
, "indexdef");
3774 i_indnkeys
= PQfnumber(res
, "indnkeys");
3775 i_indkey
= PQfnumber(res
, "indkey");
3776 i_indisclustered
= PQfnumber(res
, "indisclustered");
3777 i_contype
= PQfnumber(res
, "contype");
3778 i_conname
= PQfnumber(res
, "conname");
3779 i_contableoid
= PQfnumber(res
, "contableoid");
3780 i_conoid
= PQfnumber(res
, "conoid");
3781 i_tablespace
= PQfnumber(res
, "tablespace");
3782 i_options
= PQfnumber(res
, "options");
3784 indxinfo
= (IndxInfo
*) malloc(ntups
* sizeof(IndxInfo
));
3785 constrinfo
= (ConstraintInfo
*) malloc(ntups
* sizeof(ConstraintInfo
));
3787 for (j
= 0; j
< ntups
; j
++)
3791 indxinfo
[j
].dobj
.objType
= DO_INDEX
;
3792 indxinfo
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, i_tableoid
));
3793 indxinfo
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, i_oid
));
3794 AssignDumpId(&indxinfo
[j
].dobj
);
3795 indxinfo
[j
].dobj
.name
= strdup(PQgetvalue(res
, j
, i_indexname
));
3796 indxinfo
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
3797 indxinfo
[j
].indextable
= tbinfo
;
3798 indxinfo
[j
].indexdef
= strdup(PQgetvalue(res
, j
, i_indexdef
));
3799 indxinfo
[j
].indnkeys
= atoi(PQgetvalue(res
, j
, i_indnkeys
));
3800 indxinfo
[j
].tablespace
= strdup(PQgetvalue(res
, j
, i_tablespace
));
3801 indxinfo
[j
].options
= strdup(PQgetvalue(res
, j
, i_options
));
3804 * In pre-7.4 releases, indkeys may contain more entries than
3805 * indnkeys says (since indnkeys will be 1 for a functional
3806 * index). We don't actually care about this case since we don't
3807 * examine indkeys except for indexes associated with PRIMARY and
3808 * UNIQUE constraints, which are never functional indexes. But we
3809 * have to allocate enough space to keep parseOidArray from
3812 indxinfo
[j
].indkeys
= (Oid
*) malloc(INDEX_MAX_KEYS
* sizeof(Oid
));
3813 parseOidArray(PQgetvalue(res
, j
, i_indkey
),
3814 indxinfo
[j
].indkeys
, INDEX_MAX_KEYS
);
3815 indxinfo
[j
].indisclustered
= (PQgetvalue(res
, j
, i_indisclustered
)[0] == 't');
3816 contype
= *(PQgetvalue(res
, j
, i_contype
));
3818 if (contype
== 'p' || contype
== 'u')
3821 * If we found a constraint matching the index, create an
3824 * In a pre-7.3 database, we take this path iff the index was
3825 * marked indisprimary.
3827 constrinfo
[j
].dobj
.objType
= DO_CONSTRAINT
;
3828 constrinfo
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, i_contableoid
));
3829 constrinfo
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, i_conoid
));
3830 AssignDumpId(&constrinfo
[j
].dobj
);
3831 constrinfo
[j
].dobj
.name
= strdup(PQgetvalue(res
, j
, i_conname
));
3832 constrinfo
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
3833 constrinfo
[j
].contable
= tbinfo
;
3834 constrinfo
[j
].condomain
= NULL
;
3835 constrinfo
[j
].contype
= contype
;
3836 constrinfo
[j
].condef
= NULL
;
3837 constrinfo
[j
].confrelid
= InvalidOid
;
3838 constrinfo
[j
].conindex
= indxinfo
[j
].dobj
.dumpId
;
3839 constrinfo
[j
].conislocal
= true;
3840 constrinfo
[j
].separate
= true;
3842 indxinfo
[j
].indexconstraint
= constrinfo
[j
].dobj
.dumpId
;
3844 /* If pre-7.3 DB, better make sure table comes first */
3845 addObjectDependency(&constrinfo
[j
].dobj
,
3846 tbinfo
->dobj
.dumpId
);
3850 /* Plain secondary index */
3851 indxinfo
[j
].indexconstraint
= 0;
3858 destroyPQExpBuffer(query
);
3864 * Get info about constraints on dumpable tables.
3866 * Currently handles foreign keys only.
3867 * Unique and primary key constraints are handled with indexes,
3868 * while check constraints are processed in getTableAttrs().
3871 getConstraints(TableInfo tblinfo
[], int numTables
)
3875 ConstraintInfo
*constrinfo
;
3885 /* pg_constraint was created in 7.3, so nothing to do if older */
3886 if (g_fout
->remoteVersion
< 70300)
3889 query
= createPQExpBuffer();
3891 for (i
= 0; i
< numTables
; i
++)
3893 TableInfo
*tbinfo
= &tblinfo
[i
];
3895 if (!tbinfo
->hastriggers
|| !tbinfo
->dobj
.dump
)
3899 write_msg(NULL
, "reading foreign key constraints for table \"%s\"\n",
3903 * select table schema to ensure constraint expr is qualified if
3906 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
3908 resetPQExpBuffer(query
);
3909 appendPQExpBuffer(query
,
3910 "SELECT tableoid, oid, conname, confrelid, "
3911 "pg_catalog.pg_get_constraintdef(oid) AS condef "
3912 "FROM pg_catalog.pg_constraint "
3913 "WHERE conrelid = '%u'::pg_catalog.oid "
3914 "AND contype = 'f'",
3915 tbinfo
->dobj
.catId
.oid
);
3916 res
= PQexec(g_conn
, query
->data
);
3917 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
3919 ntups
= PQntuples(res
);
3921 i_contableoid
= PQfnumber(res
, "tableoid");
3922 i_conoid
= PQfnumber(res
, "oid");
3923 i_conname
= PQfnumber(res
, "conname");
3924 i_confrelid
= PQfnumber(res
, "confrelid");
3925 i_condef
= PQfnumber(res
, "condef");
3927 constrinfo
= (ConstraintInfo
*) malloc(ntups
* sizeof(ConstraintInfo
));
3929 for (j
= 0; j
< ntups
; j
++)
3931 constrinfo
[j
].dobj
.objType
= DO_FK_CONSTRAINT
;
3932 constrinfo
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, i_contableoid
));
3933 constrinfo
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, i_conoid
));
3934 AssignDumpId(&constrinfo
[j
].dobj
);
3935 constrinfo
[j
].dobj
.name
= strdup(PQgetvalue(res
, j
, i_conname
));
3936 constrinfo
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
3937 constrinfo
[j
].contable
= tbinfo
;
3938 constrinfo
[j
].condomain
= NULL
;
3939 constrinfo
[j
].contype
= 'f';
3940 constrinfo
[j
].condef
= strdup(PQgetvalue(res
, j
, i_condef
));
3941 constrinfo
[j
].confrelid
= atooid(PQgetvalue(res
, j
, i_confrelid
));
3942 constrinfo
[j
].conindex
= 0;
3943 constrinfo
[j
].conislocal
= true;
3944 constrinfo
[j
].separate
= true;
3950 destroyPQExpBuffer(query
);
3954 * getDomainConstraints
3956 * Get info about constraints on a domain.
3959 getDomainConstraints(TypeInfo
*tinfo
)
3962 ConstraintInfo
*constrinfo
;
3971 /* pg_constraint was created in 7.3, so nothing to do if older */
3972 if (g_fout
->remoteVersion
< 70300)
3976 * select appropriate schema to ensure names in constraint are properly
3979 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
3981 query
= createPQExpBuffer();
3983 if (g_fout
->remoteVersion
>= 70400)
3984 appendPQExpBuffer(query
, "SELECT tableoid, oid, conname, "
3985 "pg_catalog.pg_get_constraintdef(oid) AS consrc "
3986 "FROM pg_catalog.pg_constraint "
3987 "WHERE contypid = '%u'::pg_catalog.oid "
3989 tinfo
->dobj
.catId
.oid
);
3991 appendPQExpBuffer(query
, "SELECT tableoid, oid, conname, "
3992 "'CHECK (' || consrc || ')' AS consrc "
3993 "FROM pg_catalog.pg_constraint "
3994 "WHERE contypid = '%u'::pg_catalog.oid "
3996 tinfo
->dobj
.catId
.oid
);
3998 res
= PQexec(g_conn
, query
->data
);
3999 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
4001 ntups
= PQntuples(res
);
4003 i_tableoid
= PQfnumber(res
, "tableoid");
4004 i_oid
= PQfnumber(res
, "oid");
4005 i_conname
= PQfnumber(res
, "conname");
4006 i_consrc
= PQfnumber(res
, "consrc");
4008 constrinfo
= (ConstraintInfo
*) malloc(ntups
* sizeof(ConstraintInfo
));
4010 tinfo
->nDomChecks
= ntups
;
4011 tinfo
->domChecks
= constrinfo
;
4013 for (i
= 0; i
< ntups
; i
++)
4015 constrinfo
[i
].dobj
.objType
= DO_CONSTRAINT
;
4016 constrinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
4017 constrinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
4018 AssignDumpId(&constrinfo
[i
].dobj
);
4019 constrinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_conname
));
4020 constrinfo
[i
].dobj
.namespace = tinfo
->dobj
.namespace;
4021 constrinfo
[i
].contable
= NULL
;
4022 constrinfo
[i
].condomain
= tinfo
;
4023 constrinfo
[i
].contype
= 'c';
4024 constrinfo
[i
].condef
= strdup(PQgetvalue(res
, i
, i_consrc
));
4025 constrinfo
[i
].confrelid
= InvalidOid
;
4026 constrinfo
[i
].conindex
= 0;
4027 constrinfo
[i
].conislocal
= true;
4028 constrinfo
[i
].separate
= false;
4031 * Make the domain depend on the constraint, ensuring it won't be
4032 * output till any constraint dependencies are OK.
4034 addObjectDependency(&tinfo
->dobj
,
4035 constrinfo
[i
].dobj
.dumpId
);
4040 destroyPQExpBuffer(query
);
4045 * get basic information about every rule in the system
4047 * numRules is set to the number of rules read in
4050 getRules(int *numRules
)
4055 PQExpBuffer query
= createPQExpBuffer();
4065 /* Make sure we are in proper schema */
4066 selectSourceSchema("pg_catalog");
4068 if (g_fout
->remoteVersion
>= 80300)
4070 appendPQExpBuffer(query
, "SELECT "
4071 "tableoid, oid, rulename, "
4072 "ev_class AS ruletable, ev_type, is_instead, "
4077 else if (g_fout
->remoteVersion
>= 70100)
4079 appendPQExpBuffer(query
, "SELECT "
4080 "tableoid, oid, rulename, "
4081 "ev_class AS ruletable, ev_type, is_instead, "
4082 "'O'::char AS ev_enabled "
4088 appendPQExpBuffer(query
, "SELECT "
4089 "(SELECT oid FROM pg_class WHERE relname = 'pg_rewrite') AS tableoid, "
4091 "ev_class AS ruletable, ev_type, is_instead, "
4092 "'O'::char AS ev_enabled "
4097 res
= PQexec(g_conn
, query
->data
);
4098 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
4100 ntups
= PQntuples(res
);
4104 ruleinfo
= (RuleInfo
*) malloc(ntups
* sizeof(RuleInfo
));
4106 i_tableoid
= PQfnumber(res
, "tableoid");
4107 i_oid
= PQfnumber(res
, "oid");
4108 i_rulename
= PQfnumber(res
, "rulename");
4109 i_ruletable
= PQfnumber(res
, "ruletable");
4110 i_ev_type
= PQfnumber(res
, "ev_type");
4111 i_is_instead
= PQfnumber(res
, "is_instead");
4112 i_ev_enabled
= PQfnumber(res
, "ev_enabled");
4114 for (i
= 0; i
< ntups
; i
++)
4118 ruleinfo
[i
].dobj
.objType
= DO_RULE
;
4119 ruleinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
4120 ruleinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
4121 AssignDumpId(&ruleinfo
[i
].dobj
);
4122 ruleinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_rulename
));
4123 ruletableoid
= atooid(PQgetvalue(res
, i
, i_ruletable
));
4124 ruleinfo
[i
].ruletable
= findTableByOid(ruletableoid
);
4125 if (ruleinfo
[i
].ruletable
== NULL
)
4127 write_msg(NULL
, "failed sanity check, parent table OID %u of pg_rewrite entry OID %u not found\n",
4129 ruleinfo
[i
].dobj
.catId
.oid
);
4132 ruleinfo
[i
].dobj
.namespace = ruleinfo
[i
].ruletable
->dobj
.namespace;
4133 ruleinfo
[i
].dobj
.dump
= ruleinfo
[i
].ruletable
->dobj
.dump
;
4134 ruleinfo
[i
].ev_type
= *(PQgetvalue(res
, i
, i_ev_type
));
4135 ruleinfo
[i
].is_instead
= *(PQgetvalue(res
, i
, i_is_instead
)) == 't';
4136 ruleinfo
[i
].ev_enabled
= *(PQgetvalue(res
, i
, i_ev_enabled
));
4137 if (ruleinfo
[i
].ruletable
)
4140 * If the table is a view, force its ON SELECT rule to be sorted
4141 * before the view itself --- this ensures that any dependencies
4142 * for the rule affect the table's positioning. Other rules are
4143 * forced to appear after their table.
4145 if (ruleinfo
[i
].ruletable
->relkind
== RELKIND_VIEW
&&
4146 ruleinfo
[i
].ev_type
== '1' && ruleinfo
[i
].is_instead
)
4148 addObjectDependency(&ruleinfo
[i
].ruletable
->dobj
,
4149 ruleinfo
[i
].dobj
.dumpId
);
4150 /* We'll merge the rule into CREATE VIEW, if possible */
4151 ruleinfo
[i
].separate
= false;
4155 addObjectDependency(&ruleinfo
[i
].dobj
,
4156 ruleinfo
[i
].ruletable
->dobj
.dumpId
);
4157 ruleinfo
[i
].separate
= true;
4161 ruleinfo
[i
].separate
= true;
4166 destroyPQExpBuffer(query
);
4173 * get information about every trigger on a dumpable table
4175 * Note: trigger data is not returned directly to the caller, but it
4176 * does get entered into the DumpableObject tables.
4179 getTriggers(TableInfo tblinfo
[], int numTables
)
4183 PQExpBuffer query
= createPQExpBuffer();
4185 TriggerInfo
*tginfo
;
4202 for (i
= 0; i
< numTables
; i
++)
4204 TableInfo
*tbinfo
= &tblinfo
[i
];
4206 if (!tbinfo
->hastriggers
|| !tbinfo
->dobj
.dump
)
4210 write_msg(NULL
, "reading triggers for table \"%s\"\n",
4214 * select table schema to ensure regproc name is qualified if needed
4216 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
4218 resetPQExpBuffer(query
);
4219 if (g_fout
->remoteVersion
>= 80300)
4222 * We ignore triggers that are tied to a foreign-key constraint
4224 appendPQExpBuffer(query
,
4226 "tgfoid::pg_catalog.regproc AS tgfname, "
4227 "tgtype, tgnargs, tgargs, tgenabled, "
4228 "tgisconstraint, tgconstrname, tgdeferrable, "
4229 "tgconstrrelid, tginitdeferred, tableoid, oid, "
4230 "tgconstrrelid::pg_catalog.regclass AS tgconstrrelname "
4231 "FROM pg_catalog.pg_trigger t "
4232 "WHERE tgrelid = '%u'::pg_catalog.oid "
4233 "AND tgconstraint = 0",
4234 tbinfo
->dobj
.catId
.oid
);
4236 else if (g_fout
->remoteVersion
>= 70300)
4239 * We ignore triggers that are tied to a foreign-key constraint,
4240 * but in these versions we have to grovel through pg_constraint
4243 appendPQExpBuffer(query
,
4245 "tgfoid::pg_catalog.regproc AS tgfname, "
4246 "tgtype, tgnargs, tgargs, tgenabled, "
4247 "tgisconstraint, tgconstrname, tgdeferrable, "
4248 "tgconstrrelid, tginitdeferred, tableoid, oid, "
4249 "tgconstrrelid::pg_catalog.regclass AS tgconstrrelname "
4250 "FROM pg_catalog.pg_trigger t "
4251 "WHERE tgrelid = '%u'::pg_catalog.oid "
4252 "AND (NOT tgisconstraint "
4254 " (SELECT 1 FROM pg_catalog.pg_depend d "
4255 " JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
4256 " WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))",
4257 tbinfo
->dobj
.catId
.oid
);
4259 else if (g_fout
->remoteVersion
>= 70100)
4261 appendPQExpBuffer(query
,
4262 "SELECT tgname, tgfoid::regproc AS tgfname, "
4263 "tgtype, tgnargs, tgargs, tgenabled, "
4264 "tgisconstraint, tgconstrname, tgdeferrable, "
4265 "tgconstrrelid, tginitdeferred, tableoid, oid, "
4266 "(SELECT relname FROM pg_class WHERE oid = tgconstrrelid) "
4267 " AS tgconstrrelname "
4269 "WHERE tgrelid = '%u'::oid",
4270 tbinfo
->dobj
.catId
.oid
);
4274 appendPQExpBuffer(query
,
4275 "SELECT tgname, tgfoid::regproc AS tgfname, "
4276 "tgtype, tgnargs, tgargs, tgenabled, "
4277 "tgisconstraint, tgconstrname, tgdeferrable, "
4278 "tgconstrrelid, tginitdeferred, "
4279 "(SELECT oid FROM pg_class WHERE relname = 'pg_trigger') AS tableoid, "
4281 "(SELECT relname FROM pg_class WHERE oid = tgconstrrelid) "
4282 " AS tgconstrrelname "
4284 "WHERE tgrelid = '%u'::oid",
4285 tbinfo
->dobj
.catId
.oid
);
4287 res
= PQexec(g_conn
, query
->data
);
4288 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
4290 ntups
= PQntuples(res
);
4292 i_tableoid
= PQfnumber(res
, "tableoid");
4293 i_oid
= PQfnumber(res
, "oid");
4294 i_tgname
= PQfnumber(res
, "tgname");
4295 i_tgfname
= PQfnumber(res
, "tgfname");
4296 i_tgtype
= PQfnumber(res
, "tgtype");
4297 i_tgnargs
= PQfnumber(res
, "tgnargs");
4298 i_tgargs
= PQfnumber(res
, "tgargs");
4299 i_tgisconstraint
= PQfnumber(res
, "tgisconstraint");
4300 i_tgconstrname
= PQfnumber(res
, "tgconstrname");
4301 i_tgconstrrelid
= PQfnumber(res
, "tgconstrrelid");
4302 i_tgconstrrelname
= PQfnumber(res
, "tgconstrrelname");
4303 i_tgenabled
= PQfnumber(res
, "tgenabled");
4304 i_tgdeferrable
= PQfnumber(res
, "tgdeferrable");
4305 i_tginitdeferred
= PQfnumber(res
, "tginitdeferred");
4307 tginfo
= (TriggerInfo
*) malloc(ntups
* sizeof(TriggerInfo
));
4309 for (j
= 0; j
< ntups
; j
++)
4311 tginfo
[j
].dobj
.objType
= DO_TRIGGER
;
4312 tginfo
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, i_tableoid
));
4313 tginfo
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, i_oid
));
4314 AssignDumpId(&tginfo
[j
].dobj
);
4315 tginfo
[j
].dobj
.name
= strdup(PQgetvalue(res
, j
, i_tgname
));
4316 tginfo
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
4317 tginfo
[j
].tgtable
= tbinfo
;
4318 tginfo
[j
].tgfname
= strdup(PQgetvalue(res
, j
, i_tgfname
));
4319 tginfo
[j
].tgtype
= atoi(PQgetvalue(res
, j
, i_tgtype
));
4320 tginfo
[j
].tgnargs
= atoi(PQgetvalue(res
, j
, i_tgnargs
));
4321 tginfo
[j
].tgargs
= strdup(PQgetvalue(res
, j
, i_tgargs
));
4322 tginfo
[j
].tgisconstraint
= *(PQgetvalue(res
, j
, i_tgisconstraint
)) == 't';
4323 tginfo
[j
].tgenabled
= *(PQgetvalue(res
, j
, i_tgenabled
));
4324 tginfo
[j
].tgdeferrable
= *(PQgetvalue(res
, j
, i_tgdeferrable
)) == 't';
4325 tginfo
[j
].tginitdeferred
= *(PQgetvalue(res
, j
, i_tginitdeferred
)) == 't';
4327 if (tginfo
[j
].tgisconstraint
)
4329 tginfo
[j
].tgconstrname
= strdup(PQgetvalue(res
, j
, i_tgconstrname
));
4330 tginfo
[j
].tgconstrrelid
= atooid(PQgetvalue(res
, j
, i_tgconstrrelid
));
4331 if (OidIsValid(tginfo
[j
].tgconstrrelid
))
4333 if (PQgetisnull(res
, j
, i_tgconstrrelname
))
4335 write_msg(NULL
, "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)\n",
4336 tginfo
[j
].dobj
.name
, tbinfo
->dobj
.name
,
4337 tginfo
[j
].tgconstrrelid
);
4340 tginfo
[j
].tgconstrrelname
= strdup(PQgetvalue(res
, j
, i_tgconstrrelname
));
4343 tginfo
[j
].tgconstrrelname
= NULL
;
4347 tginfo
[j
].tgconstrname
= NULL
;
4348 tginfo
[j
].tgconstrrelid
= InvalidOid
;
4349 tginfo
[j
].tgconstrrelname
= NULL
;
4356 destroyPQExpBuffer(query
);
4361 * get basic information about every procedural language in the system
4363 * numProcLangs is set to the number of langs read in
4365 * NB: this must run after getFuncs() because we assume we can do
4369 getProcLangs(int *numProcLangs
)
4374 PQExpBuffer query
= createPQExpBuffer();
4375 ProcLangInfo
*planginfo
;
4380 int i_lanplcallfoid
;
4385 /* Make sure we are in proper schema */
4386 selectSourceSchema("pg_catalog");
4388 if (g_fout
->remoteVersion
>= 80300)
4390 /* pg_language has a lanowner column */
4391 appendPQExpBuffer(query
, "SELECT tableoid, oid, "
4392 "lanname, lanpltrusted, lanplcallfoid, "
4393 "lanvalidator, lanacl, "
4394 "(%s lanowner) AS lanowner "
4400 else if (g_fout
->remoteVersion
>= 80100)
4402 /* Languages are owned by the bootstrap superuser, OID 10 */
4403 appendPQExpBuffer(query
, "SELECT tableoid, oid, *, "
4404 "(%s '10') AS lanowner "
4410 else if (g_fout
->remoteVersion
>= 70400)
4412 /* Languages are owned by the bootstrap superuser, sysid 1 */
4413 appendPQExpBuffer(query
, "SELECT tableoid, oid, *, "
4414 "(%s '1') AS lanowner "
4420 else if (g_fout
->remoteVersion
>= 70100)
4422 /* No clear notion of an owner at all before 7.4 ... */
4423 appendPQExpBuffer(query
, "SELECT tableoid, oid, * FROM pg_language "
4429 appendPQExpBuffer(query
, "SELECT "
4430 "(SELECT oid FROM pg_class WHERE relname = 'pg_language') AS tableoid, "
4431 "oid, * FROM pg_language "
4436 res
= PQexec(g_conn
, query
->data
);
4437 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
4439 ntups
= PQntuples(res
);
4441 *numProcLangs
= ntups
;
4443 planginfo
= (ProcLangInfo
*) malloc(ntups
* sizeof(ProcLangInfo
));
4445 i_tableoid
= PQfnumber(res
, "tableoid");
4446 i_oid
= PQfnumber(res
, "oid");
4447 i_lanname
= PQfnumber(res
, "lanname");
4448 i_lanpltrusted
= PQfnumber(res
, "lanpltrusted");
4449 i_lanplcallfoid
= PQfnumber(res
, "lanplcallfoid");
4450 /* these may fail and return -1: */
4451 i_lanvalidator
= PQfnumber(res
, "lanvalidator");
4452 i_lanacl
= PQfnumber(res
, "lanacl");
4453 i_lanowner
= PQfnumber(res
, "lanowner");
4455 for (i
= 0; i
< ntups
; i
++)
4457 planginfo
[i
].dobj
.objType
= DO_PROCLANG
;
4458 planginfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
4459 planginfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
4460 AssignDumpId(&planginfo
[i
].dobj
);
4462 planginfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_lanname
));
4463 planginfo
[i
].lanpltrusted
= *(PQgetvalue(res
, i
, i_lanpltrusted
)) == 't';
4464 planginfo
[i
].lanplcallfoid
= atooid(PQgetvalue(res
, i
, i_lanplcallfoid
));
4465 if (i_lanvalidator
>= 0)
4466 planginfo
[i
].lanvalidator
= atooid(PQgetvalue(res
, i
, i_lanvalidator
));
4468 planginfo
[i
].lanvalidator
= InvalidOid
;
4470 planginfo
[i
].lanacl
= strdup(PQgetvalue(res
, i
, i_lanacl
));
4472 planginfo
[i
].lanacl
= strdup("{=U}");
4473 if (i_lanowner
>= 0)
4474 planginfo
[i
].lanowner
= strdup(PQgetvalue(res
, i
, i_lanowner
));
4476 planginfo
[i
].lanowner
= strdup("");
4478 if (g_fout
->remoteVersion
< 70300)
4481 * We need to make a dependency to ensure the function will be
4482 * dumped first. (In 7.3 and later the regular dependency
4483 * mechanism will handle this for us.)
4485 FuncInfo
*funcInfo
= findFuncByOid(planginfo
[i
].lanplcallfoid
);
4488 addObjectDependency(&planginfo
[i
].dobj
,
4489 funcInfo
->dobj
.dumpId
);
4495 destroyPQExpBuffer(query
);
4502 * get basic information about every cast in the system
4504 * numCasts is set to the number of casts read in
4507 getCasts(int *numCasts
)
4512 PQExpBuffer query
= createPQExpBuffer();
4522 /* Make sure we are in proper schema */
4523 selectSourceSchema("pg_catalog");
4525 if (g_fout
->remoteVersion
>= 80400)
4527 appendPQExpBuffer(query
, "SELECT tableoid, oid, "
4528 "castsource, casttarget, castfunc, castcontext, "
4530 "FROM pg_cast ORDER BY 3,4");
4532 else if (g_fout
->remoteVersion
>= 70300)
4534 appendPQExpBuffer(query
, "SELECT tableoid, oid, "
4535 "castsource, casttarget, castfunc, castcontext, "
4536 "CASE WHEN castfunc = 0 THEN 'b' ELSE 'f' END AS castmethod "
4537 "FROM pg_cast ORDER BY 3,4");
4541 appendPQExpBuffer(query
, "SELECT 0 AS tableoid, p.oid, "
4542 "t1.oid AS castsource, t2.oid AS casttarget, "
4543 "p.oid AS castfunc, 'e' AS castcontext, "
4544 "'f' AS castmethod "
4545 "FROM pg_type t1, pg_type t2, pg_proc p "
4546 "WHERE p.pronargs = 1 AND "
4547 "p.proargtypes[0] = t1.oid AND "
4548 "p.prorettype = t2.oid AND p.proname = t2.typname "
4552 res
= PQexec(g_conn
, query
->data
);
4553 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
4555 ntups
= PQntuples(res
);
4559 castinfo
= (CastInfo
*) malloc(ntups
* sizeof(CastInfo
));
4561 i_tableoid
= PQfnumber(res
, "tableoid");
4562 i_oid
= PQfnumber(res
, "oid");
4563 i_castsource
= PQfnumber(res
, "castsource");
4564 i_casttarget
= PQfnumber(res
, "casttarget");
4565 i_castfunc
= PQfnumber(res
, "castfunc");
4566 i_castcontext
= PQfnumber(res
, "castcontext");
4567 i_castmethod
= PQfnumber(res
, "castmethod");
4569 for (i
= 0; i
< ntups
; i
++)
4571 PQExpBufferData namebuf
;
4572 TypeInfo
*sTypeInfo
;
4573 TypeInfo
*tTypeInfo
;
4575 castinfo
[i
].dobj
.objType
= DO_CAST
;
4576 castinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
4577 castinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
4578 AssignDumpId(&castinfo
[i
].dobj
);
4579 castinfo
[i
].castsource
= atooid(PQgetvalue(res
, i
, i_castsource
));
4580 castinfo
[i
].casttarget
= atooid(PQgetvalue(res
, i
, i_casttarget
));
4581 castinfo
[i
].castfunc
= atooid(PQgetvalue(res
, i
, i_castfunc
));
4582 castinfo
[i
].castcontext
= *(PQgetvalue(res
, i
, i_castcontext
));
4583 castinfo
[i
].castmethod
= *(PQgetvalue(res
, i
, i_castmethod
));
4586 * Try to name cast as concatenation of typnames. This is only used
4587 * for purposes of sorting. If we fail to find either type, the name
4588 * will be an empty string.
4590 initPQExpBuffer(&namebuf
);
4591 sTypeInfo
= findTypeByOid(castinfo
[i
].castsource
);
4592 tTypeInfo
= findTypeByOid(castinfo
[i
].casttarget
);
4593 if (sTypeInfo
&& tTypeInfo
)
4594 appendPQExpBuffer(&namebuf
, "%s %s",
4595 sTypeInfo
->dobj
.name
, tTypeInfo
->dobj
.name
);
4596 castinfo
[i
].dobj
.name
= namebuf
.data
;
4598 if (OidIsValid(castinfo
[i
].castfunc
))
4601 * We need to make a dependency to ensure the function will be
4602 * dumped first. (In 7.3 and later the regular dependency
4603 * mechanism will handle this for us.)
4607 funcInfo
= findFuncByOid(castinfo
[i
].castfunc
);
4609 addObjectDependency(&castinfo
[i
].dobj
,
4610 funcInfo
->dobj
.dumpId
);
4616 destroyPQExpBuffer(query
);
4623 * for each interesting table, read info about its attributes
4624 * (names, types, default values, CHECK constraints, etc)
4626 * This is implemented in a very inefficient way right now, looping
4627 * through the tblinfo and doing a join per table to find the attrs and their
4628 * types. However, because we want type names and so forth to be named
4629 * relative to the schema of each table, we couldn't do it in just one
4630 * query. (Maybe one query per schema?)
4635 getTableAttrs(TableInfo
*tblinfo
, int numTables
)
4639 PQExpBuffer q
= createPQExpBuffer();
4644 int i_attstattarget
;
4657 for (i
= 0; i
< numTables
; i
++)
4659 TableInfo
*tbinfo
= &tblinfo
[i
];
4661 /* Don't bother to collect info for sequences */
4662 if (tbinfo
->relkind
== RELKIND_SEQUENCE
)
4665 /* Don't bother with uninteresting tables, either */
4666 if (!tbinfo
->interesting
)
4670 * Make sure we are in proper schema for this table; this allows
4671 * correct retrieval of formatted type names and default exprs
4673 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
4675 /* find all the user attributes and their types */
4678 * we must read the attribute names in attribute number order! because
4679 * we will use the attnum to index into the attnames array later. We
4680 * actually ask to order by "attrelid, attnum" because (at least up to
4681 * 7.3) the planner is not smart enough to realize it needn't re-sort
4682 * the output of an indexscan on pg_attribute_relid_attnum_index.
4685 write_msg(NULL
, "finding the columns and types of table \"%s\"\n",
4688 resetPQExpBuffer(q
);
4690 if (g_fout
->remoteVersion
>= 70300)
4692 /* need left join here to not fail on dropped columns ... */
4693 appendPQExpBuffer(q
, "SELECT a.attnum, a.attname, a.atttypmod, "
4694 "a.attstattarget, a.attstorage, t.typstorage, "
4695 "a.attnotnull, a.atthasdef, a.attisdropped, "
4696 "a.attlen, a.attalign, a.attislocal, "
4697 "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname "
4698 "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
4699 "ON a.atttypid = t.oid "
4700 "WHERE a.attrelid = '%u'::pg_catalog.oid "
4701 "AND a.attnum > 0::pg_catalog.int2 "
4702 "ORDER BY a.attrelid, a.attnum",
4703 tbinfo
->dobj
.catId
.oid
);
4705 else if (g_fout
->remoteVersion
>= 70100)
4708 * attstattarget doesn't exist in 7.1. It does exist in 7.2, but
4709 * we don't dump it because we can't tell whether it's been
4710 * explicitly set or was just a default.
4712 appendPQExpBuffer(q
, "SELECT a.attnum, a.attname, "
4713 "a.atttypmod, -1 AS attstattarget, a.attstorage, "
4714 "t.typstorage, a.attnotnull, a.atthasdef, "
4715 "false AS attisdropped, a.attlen, "
4716 "a.attalign, false AS attislocal, "
4717 "format_type(t.oid,a.atttypmod) AS atttypname "
4718 "FROM pg_attribute a LEFT JOIN pg_type t "
4719 "ON a.atttypid = t.oid "
4720 "WHERE a.attrelid = '%u'::oid "
4721 "AND a.attnum > 0::int2 "
4722 "ORDER BY a.attrelid, a.attnum",
4723 tbinfo
->dobj
.catId
.oid
);
4727 /* format_type not available before 7.1 */
4728 appendPQExpBuffer(q
, "SELECT attnum, attname, atttypmod, "
4729 "-1 AS attstattarget, attstorage, "
4730 "attstorage AS typstorage, "
4731 "attnotnull, atthasdef, false AS attisdropped, "
4732 "attlen, attalign, "
4733 "false AS attislocal, "
4734 "(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname "
4735 "FROM pg_attribute a "
4736 "WHERE attrelid = '%u'::oid "
4737 "AND attnum > 0::int2 "
4738 "ORDER BY attrelid, attnum",
4739 tbinfo
->dobj
.catId
.oid
);
4742 res
= PQexec(g_conn
, q
->data
);
4743 check_sql_result(res
, g_conn
, q
->data
, PGRES_TUPLES_OK
);
4745 ntups
= PQntuples(res
);
4747 i_attnum
= PQfnumber(res
, "attnum");
4748 i_attname
= PQfnumber(res
, "attname");
4749 i_atttypname
= PQfnumber(res
, "atttypname");
4750 i_atttypmod
= PQfnumber(res
, "atttypmod");
4751 i_attstattarget
= PQfnumber(res
, "attstattarget");
4752 i_attstorage
= PQfnumber(res
, "attstorage");
4753 i_typstorage
= PQfnumber(res
, "typstorage");
4754 i_attnotnull
= PQfnumber(res
, "attnotnull");
4755 i_atthasdef
= PQfnumber(res
, "atthasdef");
4756 i_attisdropped
= PQfnumber(res
, "attisdropped");
4757 i_attlen
= PQfnumber(res
, "attlen");
4758 i_attalign
= PQfnumber(res
, "attalign");
4759 i_attislocal
= PQfnumber(res
, "attislocal");
4761 tbinfo
->numatts
= ntups
;
4762 tbinfo
->attnames
= (char **) malloc(ntups
* sizeof(char *));
4763 tbinfo
->atttypnames
= (char **) malloc(ntups
* sizeof(char *));
4764 tbinfo
->atttypmod
= (int *) malloc(ntups
* sizeof(int));
4765 tbinfo
->attstattarget
= (int *) malloc(ntups
* sizeof(int));
4766 tbinfo
->attstorage
= (char *) malloc(ntups
* sizeof(char));
4767 tbinfo
->typstorage
= (char *) malloc(ntups
* sizeof(char));
4768 tbinfo
->attisdropped
= (bool *) malloc(ntups
* sizeof(bool));
4769 tbinfo
->attlen
= (int *) malloc(ntups
* sizeof(int));
4770 tbinfo
->attalign
= (char *) malloc(ntups
* sizeof(char));
4771 tbinfo
->attislocal
= (bool *) malloc(ntups
* sizeof(bool));
4772 tbinfo
->notnull
= (bool *) malloc(ntups
* sizeof(bool));
4773 tbinfo
->attrdefs
= (AttrDefInfo
**) malloc(ntups
* sizeof(AttrDefInfo
*));
4774 tbinfo
->inhAttrs
= (bool *) malloc(ntups
* sizeof(bool));
4775 tbinfo
->inhAttrDef
= (bool *) malloc(ntups
* sizeof(bool));
4776 tbinfo
->inhNotNull
= (bool *) malloc(ntups
* sizeof(bool));
4777 hasdefaults
= false;
4779 for (j
= 0; j
< ntups
; j
++)
4781 if (j
+ 1 != atoi(PQgetvalue(res
, j
, i_attnum
)))
4783 write_msg(NULL
, "invalid column numbering in table \"%s\"\n",
4787 tbinfo
->attnames
[j
] = strdup(PQgetvalue(res
, j
, i_attname
));
4788 tbinfo
->atttypnames
[j
] = strdup(PQgetvalue(res
, j
, i_atttypname
));
4789 tbinfo
->atttypmod
[j
] = atoi(PQgetvalue(res
, j
, i_atttypmod
));
4790 tbinfo
->attstattarget
[j
] = atoi(PQgetvalue(res
, j
, i_attstattarget
));
4791 tbinfo
->attstorage
[j
] = *(PQgetvalue(res
, j
, i_attstorage
));
4792 tbinfo
->typstorage
[j
] = *(PQgetvalue(res
, j
, i_typstorage
));
4793 tbinfo
->attisdropped
[j
] = (PQgetvalue(res
, j
, i_attisdropped
)[0] == 't');
4794 tbinfo
->attlen
[j
] = atoi(PQgetvalue(res
, j
, i_attlen
));
4795 tbinfo
->attalign
[j
] = *(PQgetvalue(res
, j
, i_attalign
));
4796 tbinfo
->attislocal
[j
] = (PQgetvalue(res
, j
, i_attislocal
)[0] == 't');
4797 tbinfo
->notnull
[j
] = (PQgetvalue(res
, j
, i_attnotnull
)[0] == 't');
4798 tbinfo
->attrdefs
[j
] = NULL
; /* fix below */
4799 if (PQgetvalue(res
, j
, i_atthasdef
)[0] == 't')
4801 /* these flags will be set in flagInhAttrs() */
4802 tbinfo
->inhAttrs
[j
] = false;
4803 tbinfo
->inhAttrDef
[j
] = false;
4804 tbinfo
->inhNotNull
[j
] = false;
4810 * Get info about column defaults
4814 AttrDefInfo
*attrdefs
;
4818 write_msg(NULL
, "finding default expressions of table \"%s\"\n",
4821 resetPQExpBuffer(q
);
4822 if (g_fout
->remoteVersion
>= 70300)
4824 appendPQExpBuffer(q
, "SELECT tableoid, oid, adnum, "
4825 "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
4826 "FROM pg_catalog.pg_attrdef "
4827 "WHERE adrelid = '%u'::pg_catalog.oid",
4828 tbinfo
->dobj
.catId
.oid
);
4830 else if (g_fout
->remoteVersion
>= 70200)
4832 /* 7.2 did not have OIDs in pg_attrdef */
4833 appendPQExpBuffer(q
, "SELECT tableoid, 0 AS oid, adnum, "
4834 "pg_get_expr(adbin, adrelid) AS adsrc "
4836 "WHERE adrelid = '%u'::oid",
4837 tbinfo
->dobj
.catId
.oid
);
4839 else if (g_fout
->remoteVersion
>= 70100)
4841 /* no pg_get_expr, so must rely on adsrc */
4842 appendPQExpBuffer(q
, "SELECT tableoid, oid, adnum, adsrc "
4844 "WHERE adrelid = '%u'::oid",
4845 tbinfo
->dobj
.catId
.oid
);
4849 /* no pg_get_expr, no tableoid either */
4850 appendPQExpBuffer(q
, "SELECT "
4851 "(SELECT oid FROM pg_class WHERE relname = 'pg_attrdef') AS tableoid, "
4852 "oid, adnum, adsrc "
4854 "WHERE adrelid = '%u'::oid",
4855 tbinfo
->dobj
.catId
.oid
);
4857 res
= PQexec(g_conn
, q
->data
);
4858 check_sql_result(res
, g_conn
, q
->data
, PGRES_TUPLES_OK
);
4860 numDefaults
= PQntuples(res
);
4861 attrdefs
= (AttrDefInfo
*) malloc(numDefaults
* sizeof(AttrDefInfo
));
4863 for (j
= 0; j
< numDefaults
; j
++)
4867 attrdefs
[j
].dobj
.objType
= DO_ATTRDEF
;
4868 attrdefs
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, 0));
4869 attrdefs
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, 1));
4870 AssignDumpId(&attrdefs
[j
].dobj
);
4871 attrdefs
[j
].adtable
= tbinfo
;
4872 attrdefs
[j
].adnum
= adnum
= atoi(PQgetvalue(res
, j
, 2));
4873 attrdefs
[j
].adef_expr
= strdup(PQgetvalue(res
, j
, 3));
4875 attrdefs
[j
].dobj
.name
= strdup(tbinfo
->dobj
.name
);
4876 attrdefs
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
4878 attrdefs
[j
].dobj
.dump
= tbinfo
->dobj
.dump
;
4881 * Defaults on a VIEW must always be dumped as separate ALTER
4882 * TABLE commands. Defaults on regular tables are dumped as
4883 * part of the CREATE TABLE if possible. To check if it's
4884 * safe, we mark the default as needing to appear before the
4887 if (tbinfo
->relkind
== RELKIND_VIEW
)
4889 attrdefs
[j
].separate
= true;
4890 /* needed in case pre-7.3 DB: */
4891 addObjectDependency(&attrdefs
[j
].dobj
,
4892 tbinfo
->dobj
.dumpId
);
4896 attrdefs
[j
].separate
= false;
4897 addObjectDependency(&tbinfo
->dobj
,
4898 attrdefs
[j
].dobj
.dumpId
);
4901 if (adnum
<= 0 || adnum
> ntups
)
4903 write_msg(NULL
, "invalid adnum value %d for table \"%s\"\n",
4904 adnum
, tbinfo
->dobj
.name
);
4907 tbinfo
->attrdefs
[adnum
- 1] = &attrdefs
[j
];
4913 * Get info about table CHECK constraints
4915 if (tbinfo
->ncheck
> 0)
4917 ConstraintInfo
*constrs
;
4921 write_msg(NULL
, "finding check constraints for table \"%s\"\n",
4924 resetPQExpBuffer(q
);
4925 if (g_fout
->remoteVersion
>= 80400)
4927 appendPQExpBuffer(q
, "SELECT tableoid, oid, conname, "
4928 "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
4930 "FROM pg_catalog.pg_constraint "
4931 "WHERE conrelid = '%u'::pg_catalog.oid "
4932 " AND contype = 'c' "
4934 tbinfo
->dobj
.catId
.oid
);
4936 else if (g_fout
->remoteVersion
>= 70400)
4938 appendPQExpBuffer(q
, "SELECT tableoid, oid, conname, "
4939 "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
4940 "true AS conislocal "
4941 "FROM pg_catalog.pg_constraint "
4942 "WHERE conrelid = '%u'::pg_catalog.oid "
4943 " AND contype = 'c' "
4945 tbinfo
->dobj
.catId
.oid
);
4947 else if (g_fout
->remoteVersion
>= 70300)
4949 /* no pg_get_constraintdef, must use consrc */
4950 appendPQExpBuffer(q
, "SELECT tableoid, oid, conname, "
4951 "'CHECK (' || consrc || ')' AS consrc, "
4952 "true AS conislocal "
4953 "FROM pg_catalog.pg_constraint "
4954 "WHERE conrelid = '%u'::pg_catalog.oid "
4955 " AND contype = 'c' "
4957 tbinfo
->dobj
.catId
.oid
);
4959 else if (g_fout
->remoteVersion
>= 70200)
4961 /* 7.2 did not have OIDs in pg_relcheck */
4962 appendPQExpBuffer(q
, "SELECT tableoid, 0 AS oid, "
4963 "rcname AS conname, "
4964 "'CHECK (' || rcsrc || ')' AS consrc, "
4965 "true AS conislocal "
4967 "WHERE rcrelid = '%u'::oid "
4969 tbinfo
->dobj
.catId
.oid
);
4971 else if (g_fout
->remoteVersion
>= 70100)
4973 appendPQExpBuffer(q
, "SELECT tableoid, oid, "
4974 "rcname AS conname, "
4975 "'CHECK (' || rcsrc || ')' AS consrc, "
4976 "true AS conislocal "
4978 "WHERE rcrelid = '%u'::oid "
4980 tbinfo
->dobj
.catId
.oid
);
4984 /* no tableoid in 7.0 */
4985 appendPQExpBuffer(q
, "SELECT "
4986 "(SELECT oid FROM pg_class WHERE relname = 'pg_relcheck') AS tableoid, "
4987 "oid, rcname AS conname, "
4988 "'CHECK (' || rcsrc || ')' AS consrc, "
4989 "true AS conislocal "
4991 "WHERE rcrelid = '%u'::oid "
4993 tbinfo
->dobj
.catId
.oid
);
4995 res
= PQexec(g_conn
, q
->data
);
4996 check_sql_result(res
, g_conn
, q
->data
, PGRES_TUPLES_OK
);
4998 numConstrs
= PQntuples(res
);
4999 if (numConstrs
!= tbinfo
->ncheck
)
5001 write_msg(NULL
, ngettext("expected %d check constraint on table \"%s\" but found %d\n",
5002 "expected %d check constraints on table \"%s\" but found %d\n",
5004 tbinfo
->ncheck
, tbinfo
->dobj
.name
, numConstrs
);
5005 write_msg(NULL
, "(The system catalogs might be corrupted.)\n");
5009 constrs
= (ConstraintInfo
*) malloc(numConstrs
* sizeof(ConstraintInfo
));
5010 tbinfo
->checkexprs
= constrs
;
5012 for (j
= 0; j
< numConstrs
; j
++)
5014 constrs
[j
].dobj
.objType
= DO_CONSTRAINT
;
5015 constrs
[j
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, j
, 0));
5016 constrs
[j
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, j
, 1));
5017 AssignDumpId(&constrs
[j
].dobj
);
5018 constrs
[j
].dobj
.name
= strdup(PQgetvalue(res
, j
, 2));
5019 constrs
[j
].dobj
.namespace = tbinfo
->dobj
.namespace;
5020 constrs
[j
].contable
= tbinfo
;
5021 constrs
[j
].condomain
= NULL
;
5022 constrs
[j
].contype
= 'c';
5023 constrs
[j
].condef
= strdup(PQgetvalue(res
, j
, 3));
5024 constrs
[j
].confrelid
= InvalidOid
;
5025 constrs
[j
].conindex
= 0;
5026 constrs
[j
].conislocal
= (PQgetvalue(res
, j
, 4)[0] == 't');
5027 constrs
[j
].separate
= false;
5029 constrs
[j
].dobj
.dump
= tbinfo
->dobj
.dump
;
5032 * Mark the constraint as needing to appear before the table
5033 * --- this is so that any other dependencies of the
5034 * constraint will be emitted before we try to create the
5037 addObjectDependency(&tbinfo
->dobj
,
5038 constrs
[j
].dobj
.dumpId
);
5041 * If the constraint is inherited, this will be detected later
5042 * (in pre-8.4 databases). We also detect later if the
5043 * constraint must be split out from the table definition.
5050 destroyPQExpBuffer(q
);
5056 * read all text search parsers in the system catalogs and return them
5057 * in the TSParserInfo* structure
5059 * numTSParsers is set to the number of parsers read in
5062 getTSParsers(int *numTSParsers
)
5067 PQExpBuffer query
= createPQExpBuffer();
5068 TSParserInfo
*prsinfo
;
5079 /* Before 8.3, there is no built-in text search support */
5080 if (g_fout
->remoteVersion
< 80300)
5087 * find all text search objects, including builtin ones; we filter out
5088 * system-defined objects at dump-out time.
5091 /* Make sure we are in proper schema */
5092 selectSourceSchema("pg_catalog");
5094 appendPQExpBuffer(query
, "SELECT tableoid, oid, prsname, prsnamespace, "
5095 "prsstart::oid, prstoken::oid, "
5096 "prsend::oid, prsheadline::oid, prslextype::oid "
5097 "FROM pg_ts_parser");
5099 res
= PQexec(g_conn
, query
->data
);
5100 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5102 ntups
= PQntuples(res
);
5103 *numTSParsers
= ntups
;
5105 prsinfo
= (TSParserInfo
*) malloc(ntups
* sizeof(TSParserInfo
));
5107 i_tableoid
= PQfnumber(res
, "tableoid");
5108 i_oid
= PQfnumber(res
, "oid");
5109 i_prsname
= PQfnumber(res
, "prsname");
5110 i_prsnamespace
= PQfnumber(res
, "prsnamespace");
5111 i_prsstart
= PQfnumber(res
, "prsstart");
5112 i_prstoken
= PQfnumber(res
, "prstoken");
5113 i_prsend
= PQfnumber(res
, "prsend");
5114 i_prsheadline
= PQfnumber(res
, "prsheadline");
5115 i_prslextype
= PQfnumber(res
, "prslextype");
5117 for (i
= 0; i
< ntups
; i
++)
5119 prsinfo
[i
].dobj
.objType
= DO_TSPARSER
;
5120 prsinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
5121 prsinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
5122 AssignDumpId(&prsinfo
[i
].dobj
);
5123 prsinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_prsname
));
5124 prsinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_prsnamespace
)),
5125 prsinfo
[i
].dobj
.catId
.oid
);
5126 prsinfo
[i
].prsstart
= atooid(PQgetvalue(res
, i
, i_prsstart
));
5127 prsinfo
[i
].prstoken
= atooid(PQgetvalue(res
, i
, i_prstoken
));
5128 prsinfo
[i
].prsend
= atooid(PQgetvalue(res
, i
, i_prsend
));
5129 prsinfo
[i
].prsheadline
= atooid(PQgetvalue(res
, i
, i_prsheadline
));
5130 prsinfo
[i
].prslextype
= atooid(PQgetvalue(res
, i
, i_prslextype
));
5132 /* Decide whether we want to dump it */
5133 selectDumpableObject(&(prsinfo
[i
].dobj
));
5138 destroyPQExpBuffer(query
);
5144 * getTSDictionaries:
5145 * read all text search dictionaries in the system catalogs and return them
5146 * in the TSDictInfo* structure
5148 * numTSDicts is set to the number of dictionaries read in
5151 getTSDictionaries(int *numTSDicts
)
5156 PQExpBuffer query
= createPQExpBuffer();
5157 TSDictInfo
*dictinfo
;
5161 int i_dictnamespace
;
5164 int i_dictinitoption
;
5166 /* Before 8.3, there is no built-in text search support */
5167 if (g_fout
->remoteVersion
< 80300)
5173 /* Make sure we are in proper schema */
5174 selectSourceSchema("pg_catalog");
5176 appendPQExpBuffer(query
, "SELECT tableoid, oid, dictname, "
5177 "dictnamespace, (%s dictowner) AS rolname, "
5178 "dicttemplate, dictinitoption "
5182 res
= PQexec(g_conn
, query
->data
);
5183 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5185 ntups
= PQntuples(res
);
5186 *numTSDicts
= ntups
;
5188 dictinfo
= (TSDictInfo
*) malloc(ntups
* sizeof(TSDictInfo
));
5190 i_tableoid
= PQfnumber(res
, "tableoid");
5191 i_oid
= PQfnumber(res
, "oid");
5192 i_dictname
= PQfnumber(res
, "dictname");
5193 i_dictnamespace
= PQfnumber(res
, "dictnamespace");
5194 i_rolname
= PQfnumber(res
, "rolname");
5195 i_dictinitoption
= PQfnumber(res
, "dictinitoption");
5196 i_dicttemplate
= PQfnumber(res
, "dicttemplate");
5198 for (i
= 0; i
< ntups
; i
++)
5200 dictinfo
[i
].dobj
.objType
= DO_TSDICT
;
5201 dictinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
5202 dictinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
5203 AssignDumpId(&dictinfo
[i
].dobj
);
5204 dictinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_dictname
));
5205 dictinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_dictnamespace
)),
5206 dictinfo
[i
].dobj
.catId
.oid
);
5207 dictinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
5208 dictinfo
[i
].dicttemplate
= atooid(PQgetvalue(res
, i
, i_dicttemplate
));
5209 if (PQgetisnull(res
, i
, i_dictinitoption
))
5210 dictinfo
[i
].dictinitoption
= NULL
;
5212 dictinfo
[i
].dictinitoption
= strdup(PQgetvalue(res
, i
, i_dictinitoption
));
5214 /* Decide whether we want to dump it */
5215 selectDumpableObject(&(dictinfo
[i
].dobj
));
5220 destroyPQExpBuffer(query
);
5227 * read all text search templates in the system catalogs and return them
5228 * in the TSTemplateInfo* structure
5230 * numTSTemplates is set to the number of templates read in
5233 getTSTemplates(int *numTSTemplates
)
5238 PQExpBuffer query
= createPQExpBuffer();
5239 TSTemplateInfo
*tmplinfo
;
5243 int i_tmplnamespace
;
5247 /* Before 8.3, there is no built-in text search support */
5248 if (g_fout
->remoteVersion
< 80300)
5250 *numTSTemplates
= 0;
5254 /* Make sure we are in proper schema */
5255 selectSourceSchema("pg_catalog");
5257 appendPQExpBuffer(query
, "SELECT tableoid, oid, tmplname, "
5258 "tmplnamespace, tmplinit::oid, tmpllexize::oid "
5259 "FROM pg_ts_template");
5261 res
= PQexec(g_conn
, query
->data
);
5262 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5264 ntups
= PQntuples(res
);
5265 *numTSTemplates
= ntups
;
5267 tmplinfo
= (TSTemplateInfo
*) malloc(ntups
* sizeof(TSTemplateInfo
));
5269 i_tableoid
= PQfnumber(res
, "tableoid");
5270 i_oid
= PQfnumber(res
, "oid");
5271 i_tmplname
= PQfnumber(res
, "tmplname");
5272 i_tmplnamespace
= PQfnumber(res
, "tmplnamespace");
5273 i_tmplinit
= PQfnumber(res
, "tmplinit");
5274 i_tmpllexize
= PQfnumber(res
, "tmpllexize");
5276 for (i
= 0; i
< ntups
; i
++)
5278 tmplinfo
[i
].dobj
.objType
= DO_TSTEMPLATE
;
5279 tmplinfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
5280 tmplinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
5281 AssignDumpId(&tmplinfo
[i
].dobj
);
5282 tmplinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_tmplname
));
5283 tmplinfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_tmplnamespace
)),
5284 tmplinfo
[i
].dobj
.catId
.oid
);
5285 tmplinfo
[i
].tmplinit
= atooid(PQgetvalue(res
, i
, i_tmplinit
));
5286 tmplinfo
[i
].tmpllexize
= atooid(PQgetvalue(res
, i
, i_tmpllexize
));
5288 /* Decide whether we want to dump it */
5289 selectDumpableObject(&(tmplinfo
[i
].dobj
));
5294 destroyPQExpBuffer(query
);
5300 * getTSConfigurations:
5301 * read all text search configurations in the system catalogs and return
5302 * them in the TSConfigInfo* structure
5304 * numTSConfigs is set to the number of configurations read in
5307 getTSConfigurations(int *numTSConfigs
)
5312 PQExpBuffer query
= createPQExpBuffer();
5313 TSConfigInfo
*cfginfo
;
5321 /* Before 8.3, there is no built-in text search support */
5322 if (g_fout
->remoteVersion
< 80300)
5328 /* Make sure we are in proper schema */
5329 selectSourceSchema("pg_catalog");
5331 appendPQExpBuffer(query
, "SELECT tableoid, oid, cfgname, "
5332 "cfgnamespace, (%s cfgowner) AS rolname, cfgparser "
5333 "FROM pg_ts_config",
5336 res
= PQexec(g_conn
, query
->data
);
5337 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5339 ntups
= PQntuples(res
);
5340 *numTSConfigs
= ntups
;
5342 cfginfo
= (TSConfigInfo
*) malloc(ntups
* sizeof(TSConfigInfo
));
5344 i_tableoid
= PQfnumber(res
, "tableoid");
5345 i_oid
= PQfnumber(res
, "oid");
5346 i_cfgname
= PQfnumber(res
, "cfgname");
5347 i_cfgnamespace
= PQfnumber(res
, "cfgnamespace");
5348 i_rolname
= PQfnumber(res
, "rolname");
5349 i_cfgparser
= PQfnumber(res
, "cfgparser");
5351 for (i
= 0; i
< ntups
; i
++)
5353 cfginfo
[i
].dobj
.objType
= DO_TSCONFIG
;
5354 cfginfo
[i
].dobj
.catId
.tableoid
= atooid(PQgetvalue(res
, i
, i_tableoid
));
5355 cfginfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
5356 AssignDumpId(&cfginfo
[i
].dobj
);
5357 cfginfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_cfgname
));
5358 cfginfo
[i
].dobj
.namespace = findNamespace(atooid(PQgetvalue(res
, i
, i_cfgnamespace
)),
5359 cfginfo
[i
].dobj
.catId
.oid
);
5360 cfginfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
5361 cfginfo
[i
].cfgparser
= atooid(PQgetvalue(res
, i
, i_cfgparser
));
5363 /* Decide whether we want to dump it */
5364 selectDumpableObject(&(cfginfo
[i
].dobj
));
5369 destroyPQExpBuffer(query
);
5375 * getForeignDataWrappers:
5376 * read all foreign-data wrappers in the system catalogs and return
5377 * them in the FdwInfo* structure
5379 * numForeignDataWrappers is set to the number of fdws read in
5382 getForeignDataWrappers(int *numForeignDataWrappers
)
5387 PQExpBuffer query
= createPQExpBuffer();
5396 /* Before 8.4, there are no foreign-data wrappers */
5397 if (g_fout
->remoteVersion
< 80400)
5399 *numForeignDataWrappers
= 0;
5403 /* Make sure we are in proper schema */
5404 selectSourceSchema("pg_catalog");
5406 appendPQExpBuffer(query
, "SELECT oid, fdwname, "
5407 "(%s fdwowner) AS rolname, fdwvalidator::pg_catalog.regproc, fdwacl,"
5408 "array_to_string(ARRAY("
5409 " SELECT option_name || ' ' || quote_literal(option_value) "
5410 " FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
5411 "FROM pg_foreign_data_wrapper",
5414 res
= PQexec(g_conn
, query
->data
);
5415 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5417 ntups
= PQntuples(res
);
5418 *numForeignDataWrappers
= ntups
;
5420 fdwinfo
= (FdwInfo
*) malloc(ntups
* sizeof(FdwInfo
));
5422 i_oid
= PQfnumber(res
, "oid");
5423 i_fdwname
= PQfnumber(res
, "fdwname");
5424 i_rolname
= PQfnumber(res
, "rolname");
5425 i_fdwvalidator
= PQfnumber(res
, "fdwvalidator");
5426 i_fdwacl
= PQfnumber(res
, "fdwacl");
5427 i_fdwoptions
= PQfnumber(res
, "fdwoptions");
5429 for (i
= 0; i
< ntups
; i
++)
5431 fdwinfo
[i
].dobj
.objType
= DO_FDW
;
5432 fdwinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
5433 AssignDumpId(&fdwinfo
[i
].dobj
);
5434 fdwinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_fdwname
));
5435 fdwinfo
[i
].dobj
.namespace = NULL
;
5436 fdwinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
5437 fdwinfo
[i
].fdwvalidator
= strdup(PQgetvalue(res
, i
, i_fdwvalidator
));
5438 fdwinfo
[i
].fdwoptions
= strdup(PQgetvalue(res
, i
, i_fdwoptions
));
5439 fdwinfo
[i
].fdwacl
= strdup(PQgetvalue(res
, i
, i_fdwacl
));
5442 /* Decide whether we want to dump it */
5443 selectDumpableObject(&(fdwinfo
[i
].dobj
));
5448 destroyPQExpBuffer(query
);
5454 * getForeignServers:
5455 * read all foreign servers in the system catalogs and return
5456 * them in the ForeignServerInfo * structure
5458 * numForeignServers is set to the number of servers read in
5461 getForeignServers(int *numForeignServers
)
5466 PQExpBuffer query
= createPQExpBuffer();
5467 ForeignServerInfo
*srvinfo
;
5477 /* Before 8.4, there are no foreign servers */
5478 if (g_fout
->remoteVersion
< 80400)
5480 *numForeignServers
= 0;
5484 /* Make sure we are in proper schema */
5485 selectSourceSchema("pg_catalog");
5487 appendPQExpBuffer(query
, "SELECT oid, srvname, "
5488 "(%s srvowner) AS rolname, "
5489 "srvfdw, srvtype, srvversion, srvacl,"
5490 "array_to_string(ARRAY("
5491 " SELECT option_name || ' ' || quote_literal(option_value) "
5492 " FROM pg_options_to_table(srvoptions)), ', ') AS srvoptions "
5493 "FROM pg_foreign_server",
5496 res
= PQexec(g_conn
, query
->data
);
5497 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5499 ntups
= PQntuples(res
);
5500 *numForeignServers
= ntups
;
5502 srvinfo
= (ForeignServerInfo
*) malloc(ntups
* sizeof(ForeignServerInfo
));
5504 i_oid
= PQfnumber(res
, "oid");
5505 i_srvname
= PQfnumber(res
, "srvname");
5506 i_rolname
= PQfnumber(res
, "rolname");
5507 i_srvfdw
= PQfnumber(res
, "srvfdw");
5508 i_srvtype
= PQfnumber(res
, "srvtype");
5509 i_srvversion
= PQfnumber(res
, "srvversion");
5510 i_srvacl
= PQfnumber(res
, "srvacl");
5511 i_srvoptions
= PQfnumber(res
, "srvoptions");
5513 for (i
= 0; i
< ntups
; i
++)
5515 srvinfo
[i
].dobj
.objType
= DO_FOREIGN_SERVER
;
5516 srvinfo
[i
].dobj
.catId
.oid
= atooid(PQgetvalue(res
, i
, i_oid
));
5517 AssignDumpId(&srvinfo
[i
].dobj
);
5518 srvinfo
[i
].dobj
.name
= strdup(PQgetvalue(res
, i
, i_srvname
));
5519 srvinfo
[i
].dobj
.namespace = NULL
;
5520 srvinfo
[i
].rolname
= strdup(PQgetvalue(res
, i
, i_rolname
));
5521 srvinfo
[i
].srvfdw
= atooid(PQgetvalue(res
, i
, i_srvfdw
));
5522 srvinfo
[i
].srvtype
= strdup(PQgetvalue(res
, i
, i_srvtype
));
5523 srvinfo
[i
].srvversion
= strdup(PQgetvalue(res
, i
, i_srvversion
));
5524 srvinfo
[i
].srvoptions
= strdup(PQgetvalue(res
, i
, i_srvoptions
));
5525 srvinfo
[i
].srvacl
= strdup(PQgetvalue(res
, i
, i_srvacl
));
5527 /* Decide whether we want to dump it */
5528 selectDumpableObject(&(srvinfo
[i
].dobj
));
5533 destroyPQExpBuffer(query
);
5541 * This routine is used to dump any comments associated with the
5542 * object handed to this routine. The routine takes a constant character
5543 * string for the target part of the comment-creation command, plus
5544 * the namespace and owner of the object (for labeling the ArchiveEntry),
5545 * plus catalog ID and subid which are the lookup key for pg_description,
5546 * plus the dump ID for the object (for setting a dependency).
5547 * If a matching pg_description entry is found, it is dumped.
5549 * Note: although this routine takes a dumpId for dependency purposes,
5550 * that purpose is just to mark the dependency in the emitted dump file
5551 * for possible future use by pg_restore. We do NOT use it for determining
5552 * ordering of the comment in the dump file, because this routine is called
5553 * after dependency sorting occurs. This routine should be called just after
5554 * calling ArchiveEntry() for the specified object.
5557 dumpComment(Archive
*fout
, const char *target
,
5558 const char *namespace, const char *owner
,
5559 CatalogId catalogId
, int subid
, DumpId dumpId
)
5561 CommentItem
*comments
;
5564 /* Comments are SCHEMA not data */
5568 /* Search for comments associated with catalogId, using table */
5569 ncomments
= findComments(fout
, catalogId
.tableoid
, catalogId
.oid
,
5572 /* Is there one matching the subid? */
5573 while (ncomments
> 0)
5575 if (comments
->objsubid
== subid
)
5581 /* If a comment exists, build COMMENT ON statement */
5584 PQExpBuffer query
= createPQExpBuffer();
5586 appendPQExpBuffer(query
, "COMMENT ON %s IS ", target
);
5587 appendStringLiteralAH(query
, comments
->descr
, fout
);
5588 appendPQExpBuffer(query
, ";\n");
5591 * We mark comments as SECTION_NONE because they really belong in the
5592 * same section as their parent, whether that is pre-data or
5595 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
5596 target
, namespace, NULL
, owner
,
5597 false, "COMMENT", SECTION_NONE
,
5598 query
->data
, "", NULL
,
5602 destroyPQExpBuffer(query
);
5607 * dumpTableComment --
5609 * As above, but dump comments for both the specified table (or view)
5613 dumpTableComment(Archive
*fout
, TableInfo
*tbinfo
,
5614 const char *reltypename
)
5616 CommentItem
*comments
;
5621 /* Comments are SCHEMA not data */
5625 /* Search for comments associated with relation, using table */
5626 ncomments
= findComments(fout
,
5627 tbinfo
->dobj
.catId
.tableoid
,
5628 tbinfo
->dobj
.catId
.oid
,
5631 /* If comments exist, build COMMENT ON statements */
5635 query
= createPQExpBuffer();
5636 target
= createPQExpBuffer();
5638 while (ncomments
> 0)
5640 const char *descr
= comments
->descr
;
5641 int objsubid
= comments
->objsubid
;
5645 resetPQExpBuffer(target
);
5646 appendPQExpBuffer(target
, "%s %s", reltypename
,
5647 fmtId(tbinfo
->dobj
.name
));
5649 resetPQExpBuffer(query
);
5650 appendPQExpBuffer(query
, "COMMENT ON %s IS ", target
->data
);
5651 appendStringLiteralAH(query
, descr
, fout
);
5652 appendPQExpBuffer(query
, ";\n");
5654 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
5656 tbinfo
->dobj
.namespace->dobj
.name
,
5657 NULL
, tbinfo
->rolname
,
5658 false, "COMMENT", SECTION_NONE
,
5659 query
->data
, "", NULL
,
5660 &(tbinfo
->dobj
.dumpId
), 1,
5663 else if (objsubid
> 0 && objsubid
<= tbinfo
->numatts
)
5665 resetPQExpBuffer(target
);
5666 appendPQExpBuffer(target
, "COLUMN %s.",
5667 fmtId(tbinfo
->dobj
.name
));
5668 appendPQExpBuffer(target
, "%s",
5669 fmtId(tbinfo
->attnames
[objsubid
- 1]));
5671 resetPQExpBuffer(query
);
5672 appendPQExpBuffer(query
, "COMMENT ON %s IS ", target
->data
);
5673 appendStringLiteralAH(query
, descr
, fout
);
5674 appendPQExpBuffer(query
, ";\n");
5676 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
5678 tbinfo
->dobj
.namespace->dobj
.name
,
5679 NULL
, tbinfo
->rolname
,
5680 false, "COMMENT", SECTION_NONE
,
5681 query
->data
, "", NULL
,
5682 &(tbinfo
->dobj
.dumpId
), 1,
5690 destroyPQExpBuffer(query
);
5691 destroyPQExpBuffer(target
);
5697 * Find the comment(s), if any, associated with the given object. All the
5698 * objsubid values associated with the given classoid/objoid are found with
5702 findComments(Archive
*fout
, Oid classoid
, Oid objoid
,
5703 CommentItem
**items
)
5705 /* static storage for table of comments */
5706 static CommentItem
*comments
= NULL
;
5707 static int ncomments
= -1;
5709 CommentItem
*middle
= NULL
;
5714 /* Get comments if we didn't already */
5716 ncomments
= collectComments(fout
, &comments
);
5719 * Pre-7.2, pg_description does not contain classoid, so collectComments
5720 * just stores a zero. If there's a collision on object OID, well, you
5721 * get duplicate comments.
5723 if (fout
->remoteVersion
< 70200)
5727 * Do binary search to find some item matching the object.
5730 high
= &comments
[ncomments
- 1];
5733 middle
= low
+ (high
- low
) / 2;
5735 if (classoid
< middle
->classoid
)
5737 else if (classoid
> middle
->classoid
)
5739 else if (objoid
< middle
->objoid
)
5741 else if (objoid
> middle
->objoid
)
5744 break; /* found a match */
5747 if (low
> high
) /* no matches */
5754 * Now determine how many items match the object. The search loop
5755 * invariant still holds: only items between low and high inclusive could
5759 while (middle
> low
)
5761 if (classoid
!= middle
[-1].classoid
||
5762 objoid
!= middle
[-1].objoid
)
5771 while (middle
<= high
)
5773 if (classoid
!= middle
->classoid
||
5774 objoid
!= middle
->objoid
)
5784 * collectComments --
5786 * Construct a table of all comments available for database objects.
5787 * We used to do per-object queries for the comments, but it's much faster
5788 * to pull them all over at once, and on most databases the memory cost
5791 * The table is sorted by classoid/objid/objsubid for speed in lookup.
5794 collectComments(Archive
*fout
, CommentItem
**items
)
5804 CommentItem
*comments
;
5807 * Note we do NOT change source schema here; preserve the caller's
5811 query
= createPQExpBuffer();
5813 if (fout
->remoteVersion
>= 70300)
5815 appendPQExpBuffer(query
, "SELECT description, classoid, objoid, objsubid "
5816 "FROM pg_catalog.pg_description "
5817 "ORDER BY classoid, objoid, objsubid");
5819 else if (fout
->remoteVersion
>= 70200)
5821 appendPQExpBuffer(query
, "SELECT description, classoid, objoid, objsubid "
5822 "FROM pg_description "
5823 "ORDER BY classoid, objoid, objsubid");
5827 /* Note: this will fail to find attribute comments in pre-7.2... */
5828 appendPQExpBuffer(query
, "SELECT description, 0 AS classoid, objoid, 0 AS objsubid "
5829 "FROM pg_description "
5833 res
= PQexec(g_conn
, query
->data
);
5834 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
5836 /* Construct lookup table containing OIDs in numeric form */
5838 i_description
= PQfnumber(res
, "description");
5839 i_classoid
= PQfnumber(res
, "classoid");
5840 i_objoid
= PQfnumber(res
, "objoid");
5841 i_objsubid
= PQfnumber(res
, "objsubid");
5843 ntups
= PQntuples(res
);
5845 comments
= (CommentItem
*) malloc(ntups
* sizeof(CommentItem
));
5847 for (i
= 0; i
< ntups
; i
++)
5849 comments
[i
].descr
= PQgetvalue(res
, i
, i_description
);
5850 comments
[i
].classoid
= atooid(PQgetvalue(res
, i
, i_classoid
));
5851 comments
[i
].objoid
= atooid(PQgetvalue(res
, i
, i_objoid
));
5852 comments
[i
].objsubid
= atoi(PQgetvalue(res
, i
, i_objsubid
));
5855 /* Do NOT free the PGresult since we are keeping pointers into it */
5856 destroyPQExpBuffer(query
);
5863 * dumpDumpableObject
5865 * This routine and its subsidiaries are responsible for creating
5866 * ArchiveEntries (TOC objects) for each object to be dumped.
5869 dumpDumpableObject(Archive
*fout
, DumpableObject
*dobj
)
5871 switch (dobj
->objType
)
5874 dumpNamespace(fout
, (NamespaceInfo
*) dobj
);
5877 dumpType(fout
, (TypeInfo
*) dobj
);
5880 dumpShellType(fout
, (ShellTypeInfo
*) dobj
);
5883 dumpFunc(fout
, (FuncInfo
*) dobj
);
5886 dumpAgg(fout
, (AggInfo
*) dobj
);
5889 dumpOpr(fout
, (OprInfo
*) dobj
);
5892 dumpOpclass(fout
, (OpclassInfo
*) dobj
);
5895 dumpOpfamily(fout
, (OpfamilyInfo
*) dobj
);
5898 dumpConversion(fout
, (ConvInfo
*) dobj
);
5901 dumpTable(fout
, (TableInfo
*) dobj
);
5904 dumpAttrDef(fout
, (AttrDefInfo
*) dobj
);
5907 dumpIndex(fout
, (IndxInfo
*) dobj
);
5910 dumpRule(fout
, (RuleInfo
*) dobj
);
5913 dumpTrigger(fout
, (TriggerInfo
*) dobj
);
5916 dumpConstraint(fout
, (ConstraintInfo
*) dobj
);
5918 case DO_FK_CONSTRAINT
:
5919 dumpConstraint(fout
, (ConstraintInfo
*) dobj
);
5922 dumpProcLang(fout
, (ProcLangInfo
*) dobj
);
5925 dumpCast(fout
, (CastInfo
*) dobj
);
5928 dumpTableData(fout
, (TableDataInfo
*) dobj
);
5931 /* table rowtypes and array types are never dumped separately */
5934 dumpTSParser(fout
, (TSParserInfo
*) dobj
);
5937 dumpTSDictionary(fout
, (TSDictInfo
*) dobj
);
5940 dumpTSTemplate(fout
, (TSTemplateInfo
*) dobj
);
5943 dumpTSConfig(fout
, (TSConfigInfo
*) dobj
);
5946 dumpForeignDataWrapper(fout
, (FdwInfo
*) dobj
);
5948 case DO_FOREIGN_SERVER
:
5949 dumpForeignServer(fout
, (ForeignServerInfo
*) dobj
);
5952 ArchiveEntry(fout
, dobj
->catId
, dobj
->dumpId
,
5953 dobj
->name
, NULL
, NULL
, "",
5954 false, "BLOBS", SECTION_DATA
,
5956 dobj
->dependencies
, dobj
->nDeps
,
5959 case DO_BLOB_COMMENTS
:
5960 ArchiveEntry(fout
, dobj
->catId
, dobj
->dumpId
,
5961 dobj
->name
, NULL
, NULL
, "",
5962 false, "BLOB COMMENTS", SECTION_DATA
,
5964 dobj
->dependencies
, dobj
->nDeps
,
5965 dumpBlobComments
, NULL
);
5972 * writes out to fout the queries to recreate a user-defined namespace
5975 dumpNamespace(Archive
*fout
, NamespaceInfo
*nspinfo
)
5981 /* Skip if not to be dumped */
5982 if (!nspinfo
->dobj
.dump
|| dataOnly
)
5985 /* don't dump dummy namespace from pre-7.3 source */
5986 if (strlen(nspinfo
->dobj
.name
) == 0)
5989 q
= createPQExpBuffer();
5990 delq
= createPQExpBuffer();
5992 qnspname
= strdup(fmtId(nspinfo
->dobj
.name
));
5994 appendPQExpBuffer(delq
, "DROP SCHEMA %s;\n", qnspname
);
5996 appendPQExpBuffer(q
, "CREATE SCHEMA %s;\n", qnspname
);
5998 ArchiveEntry(fout
, nspinfo
->dobj
.catId
, nspinfo
->dobj
.dumpId
,
6002 false, "SCHEMA", SECTION_PRE_DATA
,
6003 q
->data
, delq
->data
, NULL
,
6004 nspinfo
->dobj
.dependencies
, nspinfo
->dobj
.nDeps
,
6007 /* Dump Schema Comments */
6008 resetPQExpBuffer(q
);
6009 appendPQExpBuffer(q
, "SCHEMA %s", qnspname
);
6010 dumpComment(fout
, q
->data
,
6011 NULL
, nspinfo
->rolname
,
6012 nspinfo
->dobj
.catId
, 0, nspinfo
->dobj
.dumpId
);
6014 dumpACL(fout
, nspinfo
->dobj
.catId
, nspinfo
->dobj
.dumpId
, "SCHEMA",
6015 qnspname
, NULL
, nspinfo
->dobj
.name
, NULL
,
6016 nspinfo
->rolname
, nspinfo
->nspacl
);
6020 destroyPQExpBuffer(q
);
6021 destroyPQExpBuffer(delq
);
6026 * writes out to fout the queries to recreate a user-defined type
6029 dumpType(Archive
*fout
, TypeInfo
*tinfo
)
6031 /* Skip if not to be dumped */
6032 if (!tinfo
->dobj
.dump
|| dataOnly
)
6035 /* Dump out in proper style */
6036 if (tinfo
->typtype
== TYPTYPE_BASE
)
6037 dumpBaseType(fout
, tinfo
);
6038 else if (tinfo
->typtype
== TYPTYPE_DOMAIN
)
6039 dumpDomain(fout
, tinfo
);
6040 else if (tinfo
->typtype
== TYPTYPE_COMPOSITE
)
6041 dumpCompositeType(fout
, tinfo
);
6042 else if (tinfo
->typtype
== TYPTYPE_ENUM
)
6043 dumpEnumType(fout
, tinfo
);
6048 * writes out to fout the queries to recreate a user-defined enum type
6051 dumpEnumType(Archive
*fout
, TypeInfo
*tinfo
)
6053 PQExpBuffer q
= createPQExpBuffer();
6054 PQExpBuffer delq
= createPQExpBuffer();
6055 PQExpBuffer query
= createPQExpBuffer();
6061 /* Set proper schema search path so regproc references list correctly */
6062 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
6064 appendPQExpBuffer(query
, "SELECT enumlabel FROM pg_catalog.pg_enum "
6065 "WHERE enumtypid = '%u'"
6067 tinfo
->dobj
.catId
.oid
);
6069 res
= PQexec(g_conn
, query
->data
);
6070 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
6072 num
= PQntuples(res
);
6073 /* should be at least 1 value */
6076 write_msg(NULL
, "no label definitions found for enum ID %u\n", tinfo
->dobj
.catId
.oid
);
6081 * DROP must be fully qualified in case same name appears in pg_catalog.
6082 * CASCADE shouldn't be required here as for normal types since the I/O
6083 * functions are generic and do not get dropped.
6085 appendPQExpBuffer(delq
, "DROP TYPE %s.",
6086 fmtId(tinfo
->dobj
.namespace->dobj
.name
));
6087 appendPQExpBuffer(delq
, "%s;\n",
6088 fmtId(tinfo
->dobj
.name
));
6089 appendPQExpBuffer(q
, "CREATE TYPE %s AS ENUM (\n",
6090 fmtId(tinfo
->dobj
.name
));
6091 for (i
= 0; i
< num
; i
++)
6093 label
= PQgetvalue(res
, i
, 0);
6095 appendPQExpBuffer(q
, ",\n");
6096 appendPQExpBuffer(q
, " ");
6097 appendStringLiteralAH(q
, label
, fout
);
6099 appendPQExpBuffer(q
, "\n);\n");
6101 ArchiveEntry(fout
, tinfo
->dobj
.catId
, tinfo
->dobj
.dumpId
,
6103 tinfo
->dobj
.namespace->dobj
.name
,
6105 tinfo
->rolname
, false,
6106 "TYPE", SECTION_PRE_DATA
,
6107 q
->data
, delq
->data
, NULL
,
6108 tinfo
->dobj
.dependencies
, tinfo
->dobj
.nDeps
,
6111 /* Dump Type Comments */
6112 resetPQExpBuffer(q
);
6114 appendPQExpBuffer(q
, "TYPE %s", fmtId(tinfo
->dobj
.name
));
6115 dumpComment(fout
, q
->data
,
6116 tinfo
->dobj
.namespace->dobj
.name
, tinfo
->rolname
,
6117 tinfo
->dobj
.catId
, 0, tinfo
->dobj
.dumpId
);
6120 destroyPQExpBuffer(q
);
6121 destroyPQExpBuffer(delq
);
6122 destroyPQExpBuffer(query
);
6127 * writes out to fout the queries to recreate a user-defined base type
6130 dumpBaseType(Archive
*fout
, TypeInfo
*tinfo
)
6132 PQExpBuffer q
= createPQExpBuffer();
6133 PQExpBuffer delq
= createPQExpBuffer();
6134 PQExpBuffer query
= createPQExpBuffer();
6153 char *typispreferred
;
6159 bool typdefault_is_literal
= false;
6161 /* Set proper schema search path so regproc references list correctly */
6162 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
6164 /* Fetch type-specific details */
6165 if (fout
->remoteVersion
>= 80400)
6167 appendPQExpBuffer(query
, "SELECT typlen, "
6168 "typinput, typoutput, typreceive, typsend, "
6169 "typmodin, typmodout, typanalyze, "
6170 "typinput::pg_catalog.oid AS typinputoid, "
6171 "typoutput::pg_catalog.oid AS typoutputoid, "
6172 "typreceive::pg_catalog.oid AS typreceiveoid, "
6173 "typsend::pg_catalog.oid AS typsendoid, "
6174 "typmodin::pg_catalog.oid AS typmodinoid, "
6175 "typmodout::pg_catalog.oid AS typmodoutoid, "
6176 "typanalyze::pg_catalog.oid AS typanalyzeoid, "
6177 "typcategory, typispreferred, "
6178 "typdelim, typbyval, typalign, typstorage, "
6179 "pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault "
6180 "FROM pg_catalog.pg_type "
6181 "WHERE oid = '%u'::pg_catalog.oid",
6182 tinfo
->dobj
.catId
.oid
);
6184 else if (fout
->remoteVersion
>= 80300)
6186 /* Before 8.4, pg_get_expr does not allow 0 for its second arg */
6187 appendPQExpBuffer(query
, "SELECT typlen, "
6188 "typinput, typoutput, typreceive, typsend, "
6189 "typmodin, typmodout, typanalyze, "
6190 "typinput::pg_catalog.oid AS typinputoid, "
6191 "typoutput::pg_catalog.oid AS typoutputoid, "
6192 "typreceive::pg_catalog.oid AS typreceiveoid, "
6193 "typsend::pg_catalog.oid AS typsendoid, "
6194 "typmodin::pg_catalog.oid AS typmodinoid, "
6195 "typmodout::pg_catalog.oid AS typmodoutoid, "
6196 "typanalyze::pg_catalog.oid AS typanalyzeoid, "
6197 "'U' AS typcategory, false AS typispreferred, "
6198 "typdelim, typbyval, typalign, typstorage, "
6199 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
6200 "FROM pg_catalog.pg_type "
6201 "WHERE oid = '%u'::pg_catalog.oid",
6202 tinfo
->dobj
.catId
.oid
);
6204 else if (fout
->remoteVersion
>= 80000)
6206 appendPQExpBuffer(query
, "SELECT typlen, "
6207 "typinput, typoutput, typreceive, typsend, "
6208 "'-' AS typmodin, '-' AS typmodout, "
6210 "typinput::pg_catalog.oid AS typinputoid, "
6211 "typoutput::pg_catalog.oid AS typoutputoid, "
6212 "typreceive::pg_catalog.oid AS typreceiveoid, "
6213 "typsend::pg_catalog.oid AS typsendoid, "
6214 "0 AS typmodinoid, 0 AS typmodoutoid, "
6215 "typanalyze::pg_catalog.oid AS typanalyzeoid, "
6216 "'U' AS typcategory, false AS typispreferred, "
6217 "typdelim, typbyval, typalign, typstorage, "
6218 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
6219 "FROM pg_catalog.pg_type "
6220 "WHERE oid = '%u'::pg_catalog.oid",
6221 tinfo
->dobj
.catId
.oid
);
6223 else if (fout
->remoteVersion
>= 70400)
6225 appendPQExpBuffer(query
, "SELECT typlen, "
6226 "typinput, typoutput, typreceive, typsend, "
6227 "'-' AS typmodin, '-' AS typmodout, "
6228 "'-' AS typanalyze, "
6229 "typinput::pg_catalog.oid AS typinputoid, "
6230 "typoutput::pg_catalog.oid AS typoutputoid, "
6231 "typreceive::pg_catalog.oid AS typreceiveoid, "
6232 "typsend::pg_catalog.oid AS typsendoid, "
6233 "0 AS typmodinoid, 0 AS typmodoutoid, "
6234 "0 AS typanalyzeoid, "
6235 "'U' AS typcategory, false AS typispreferred, "
6236 "typdelim, typbyval, typalign, typstorage, "
6237 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
6238 "FROM pg_catalog.pg_type "
6239 "WHERE oid = '%u'::pg_catalog.oid",
6240 tinfo
->dobj
.catId
.oid
);
6242 else if (fout
->remoteVersion
>= 70300)
6244 appendPQExpBuffer(query
, "SELECT typlen, "
6245 "typinput, typoutput, "
6246 "'-' AS typreceive, '-' AS typsend, "
6247 "'-' AS typmodin, '-' AS typmodout, "
6248 "'-' AS typanalyze, "
6249 "typinput::pg_catalog.oid AS typinputoid, "
6250 "typoutput::pg_catalog.oid AS typoutputoid, "
6251 "0 AS typreceiveoid, 0 AS typsendoid, "
6252 "0 AS typmodinoid, 0 AS typmodoutoid, "
6253 "0 AS typanalyzeoid, "
6254 "'U' AS typcategory, false AS typispreferred, "
6255 "typdelim, typbyval, typalign, typstorage, "
6256 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
6257 "FROM pg_catalog.pg_type "
6258 "WHERE oid = '%u'::pg_catalog.oid",
6259 tinfo
->dobj
.catId
.oid
);
6261 else if (fout
->remoteVersion
>= 70200)
6264 * Note: although pre-7.3 catalogs contain typreceive and typsend,
6265 * ignore them because they are not right.
6267 appendPQExpBuffer(query
, "SELECT typlen, "
6268 "typinput, typoutput, "
6269 "'-' AS typreceive, '-' AS typsend, "
6270 "'-' AS typmodin, '-' AS typmodout, "
6271 "'-' AS typanalyze, "
6272 "typinput::oid AS typinputoid, "
6273 "typoutput::oid AS typoutputoid, "
6274 "0 AS typreceiveoid, 0 AS typsendoid, "
6275 "0 AS typmodinoid, 0 AS typmodoutoid, "
6276 "0 AS typanalyzeoid, "
6277 "'U' AS typcategory, false AS typispreferred, "
6278 "typdelim, typbyval, typalign, typstorage, "
6279 "NULL AS typdefaultbin, typdefault "
6281 "WHERE oid = '%u'::oid",
6282 tinfo
->dobj
.catId
.oid
);
6284 else if (fout
->remoteVersion
>= 70100)
6287 * Ignore pre-7.2 typdefault; the field exists but has an unusable
6290 appendPQExpBuffer(query
, "SELECT typlen, "
6291 "typinput, typoutput, "
6292 "'-' AS typreceive, '-' AS typsend, "
6293 "'-' AS typmodin, '-' AS typmodout, "
6294 "'-' AS typanalyze, "
6295 "typinput::oid AS typinputoid, "
6296 "typoutput::oid AS typoutputoid, "
6297 "0 AS typreceiveoid, 0 AS typsendoid, "
6298 "0 AS typmodinoid, 0 AS typmodoutoid, "
6299 "0 AS typanalyzeoid, "
6300 "'U' AS typcategory, false AS typispreferred, "
6301 "typdelim, typbyval, typalign, typstorage, "
6302 "NULL AS typdefaultbin, NULL AS typdefault "
6304 "WHERE oid = '%u'::oid",
6305 tinfo
->dobj
.catId
.oid
);
6309 appendPQExpBuffer(query
, "SELECT typlen, "
6310 "typinput, typoutput, "
6311 "'-' AS typreceive, '-' AS typsend, "
6312 "'-' AS typmodin, '-' AS typmodout, "
6313 "'-' AS typanalyze, "
6314 "typinput::oid AS typinputoid, "
6315 "typoutput::oid AS typoutputoid, "
6316 "0 AS typreceiveoid, 0 AS typsendoid, "
6317 "0 AS typmodinoid, 0 AS typmodoutoid, "
6318 "0 AS typanalyzeoid, "
6319 "'U' AS typcategory, false AS typispreferred, "
6320 "typdelim, typbyval, typalign, "
6321 "'p'::char AS typstorage, "
6322 "NULL AS typdefaultbin, NULL AS typdefault "
6324 "WHERE oid = '%u'::oid",
6325 tinfo
->dobj
.catId
.oid
);
6328 res
= PQexec(g_conn
, query
->data
);
6329 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
6331 /* Expecting a single result only */
6332 ntups
= PQntuples(res
);
6335 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
6336 "query returned %d rows instead of one: %s\n",
6338 ntups
, query
->data
);
6342 typlen
= PQgetvalue(res
, 0, PQfnumber(res
, "typlen"));
6343 typinput
= PQgetvalue(res
, 0, PQfnumber(res
, "typinput"));
6344 typoutput
= PQgetvalue(res
, 0, PQfnumber(res
, "typoutput"));
6345 typreceive
= PQgetvalue(res
, 0, PQfnumber(res
, "typreceive"));
6346 typsend
= PQgetvalue(res
, 0, PQfnumber(res
, "typsend"));
6347 typmodin
= PQgetvalue(res
, 0, PQfnumber(res
, "typmodin"));
6348 typmodout
= PQgetvalue(res
, 0, PQfnumber(res
, "typmodout"));
6349 typanalyze
= PQgetvalue(res
, 0, PQfnumber(res
, "typanalyze"));
6350 typinputoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typinputoid")));
6351 typoutputoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typoutputoid")));
6352 typreceiveoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typreceiveoid")));
6353 typsendoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typsendoid")));
6354 typmodinoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typmodinoid")));
6355 typmodoutoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typmodoutoid")));
6356 typanalyzeoid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "typanalyzeoid")));
6357 typcategory
= PQgetvalue(res
, 0, PQfnumber(res
, "typcategory"));
6358 typispreferred
= PQgetvalue(res
, 0, PQfnumber(res
, "typispreferred"));
6359 typdelim
= PQgetvalue(res
, 0, PQfnumber(res
, "typdelim"));
6360 typbyval
= PQgetvalue(res
, 0, PQfnumber(res
, "typbyval"));
6361 typalign
= PQgetvalue(res
, 0, PQfnumber(res
, "typalign"));
6362 typstorage
= PQgetvalue(res
, 0, PQfnumber(res
, "typstorage"));
6363 if (!PQgetisnull(res
, 0, PQfnumber(res
, "typdefaultbin")))
6364 typdefault
= PQgetvalue(res
, 0, PQfnumber(res
, "typdefaultbin"));
6365 else if (!PQgetisnull(res
, 0, PQfnumber(res
, "typdefault")))
6367 typdefault
= PQgetvalue(res
, 0, PQfnumber(res
, "typdefault"));
6368 typdefault_is_literal
= true; /* it needs quotes */
6374 * DROP must be fully qualified in case same name appears in pg_catalog.
6375 * The reason we include CASCADE is that the circular dependency between
6376 * the type and its I/O functions makes it impossible to drop the type any
6379 appendPQExpBuffer(delq
, "DROP TYPE %s.",
6380 fmtId(tinfo
->dobj
.namespace->dobj
.name
));
6381 appendPQExpBuffer(delq
, "%s CASCADE;\n",
6382 fmtId(tinfo
->dobj
.name
));
6384 appendPQExpBuffer(q
,
6385 "CREATE TYPE %s (\n"
6386 " INTERNALLENGTH = %s",
6387 fmtId(tinfo
->dobj
.name
),
6388 (strcmp(typlen
, "-1") == 0) ? "variable" : typlen
);
6390 if (fout
->remoteVersion
>= 70300)
6392 /* regproc result is correctly quoted as of 7.3 */
6393 appendPQExpBuffer(q
, ",\n INPUT = %s", typinput
);
6394 appendPQExpBuffer(q
, ",\n OUTPUT = %s", typoutput
);
6395 if (OidIsValid(typreceiveoid
))
6396 appendPQExpBuffer(q
, ",\n RECEIVE = %s", typreceive
);
6397 if (OidIsValid(typsendoid
))
6398 appendPQExpBuffer(q
, ",\n SEND = %s", typsend
);
6399 if (OidIsValid(typmodinoid
))
6400 appendPQExpBuffer(q
, ",\n TYPMOD_IN = %s", typmodin
);
6401 if (OidIsValid(typmodoutoid
))
6402 appendPQExpBuffer(q
, ",\n TYPMOD_OUT = %s", typmodout
);
6403 if (OidIsValid(typanalyzeoid
))
6404 appendPQExpBuffer(q
, ",\n ANALYZE = %s", typanalyze
);
6408 /* regproc delivers an unquoted name before 7.3 */
6409 /* cannot combine these because fmtId uses static result area */
6410 appendPQExpBuffer(q
, ",\n INPUT = %s", fmtId(typinput
));
6411 appendPQExpBuffer(q
, ",\n OUTPUT = %s", fmtId(typoutput
));
6412 /* receive/send/typmodin/typmodout/analyze need not be printed */
6415 if (typdefault
!= NULL
)
6417 appendPQExpBuffer(q
, ",\n DEFAULT = ");
6418 if (typdefault_is_literal
)
6419 appendStringLiteralAH(q
, typdefault
, fout
);
6421 appendPQExpBufferStr(q
, typdefault
);
6424 if (OidIsValid(tinfo
->typelem
))
6428 /* reselect schema in case changed by function dump */
6429 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
6430 elemType
= getFormattedTypeName(tinfo
->typelem
, zeroAsOpaque
);
6431 appendPQExpBuffer(q
, ",\n ELEMENT = %s", elemType
);
6435 if (strcmp(typcategory
, "U") != 0)
6437 appendPQExpBuffer(q
, ",\n CATEGORY = ");
6438 appendStringLiteralAH(q
, typcategory
, fout
);
6441 if (strcmp(typispreferred
, "t") == 0)
6442 appendPQExpBuffer(q
, ",\n PREFERRED = true");
6444 if (typdelim
&& strcmp(typdelim
, ",") != 0)
6446 appendPQExpBuffer(q
, ",\n DELIMITER = ");
6447 appendStringLiteralAH(q
, typdelim
, fout
);
6450 if (strcmp(typalign
, "c") == 0)
6451 appendPQExpBuffer(q
, ",\n ALIGNMENT = char");
6452 else if (strcmp(typalign
, "s") == 0)
6453 appendPQExpBuffer(q
, ",\n ALIGNMENT = int2");
6454 else if (strcmp(typalign
, "i") == 0)
6455 appendPQExpBuffer(q
, ",\n ALIGNMENT = int4");
6456 else if (strcmp(typalign
, "d") == 0)
6457 appendPQExpBuffer(q
, ",\n ALIGNMENT = double");
6459 if (strcmp(typstorage
, "p") == 0)
6460 appendPQExpBuffer(q
, ",\n STORAGE = plain");
6461 else if (strcmp(typstorage
, "e") == 0)
6462 appendPQExpBuffer(q
, ",\n STORAGE = external");
6463 else if (strcmp(typstorage
, "x") == 0)
6464 appendPQExpBuffer(q
, ",\n STORAGE = extended");
6465 else if (strcmp(typstorage
, "m") == 0)
6466 appendPQExpBuffer(q
, ",\n STORAGE = main");
6468 if (strcmp(typbyval
, "t") == 0)
6469 appendPQExpBuffer(q
, ",\n PASSEDBYVALUE");
6471 appendPQExpBuffer(q
, "\n);\n");
6473 ArchiveEntry(fout
, tinfo
->dobj
.catId
, tinfo
->dobj
.dumpId
,
6475 tinfo
->dobj
.namespace->dobj
.name
,
6477 tinfo
->rolname
, false,
6478 "TYPE", SECTION_PRE_DATA
,
6479 q
->data
, delq
->data
, NULL
,
6480 tinfo
->dobj
.dependencies
, tinfo
->dobj
.nDeps
,
6483 /* Dump Type Comments */
6484 resetPQExpBuffer(q
);
6486 appendPQExpBuffer(q
, "TYPE %s", fmtId(tinfo
->dobj
.name
));
6487 dumpComment(fout
, q
->data
,
6488 tinfo
->dobj
.namespace->dobj
.name
, tinfo
->rolname
,
6489 tinfo
->dobj
.catId
, 0, tinfo
->dobj
.dumpId
);
6492 destroyPQExpBuffer(q
);
6493 destroyPQExpBuffer(delq
);
6494 destroyPQExpBuffer(query
);
6499 * writes out to fout the queries to recreate a user-defined domain
6502 dumpDomain(Archive
*fout
, TypeInfo
*tinfo
)
6504 PQExpBuffer q
= createPQExpBuffer();
6505 PQExpBuffer delq
= createPQExpBuffer();
6506 PQExpBuffer query
= createPQExpBuffer();
6513 bool typdefault_is_literal
= false;
6515 /* Set proper schema search path so type references list correctly */
6516 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
6518 /* Fetch domain specific details */
6519 /* We assume here that remoteVersion must be at least 70300 */
6520 appendPQExpBuffer(query
, "SELECT typnotnull, "
6521 "pg_catalog.format_type(typbasetype, typtypmod) AS typdefn, "
6522 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
6523 "FROM pg_catalog.pg_type "
6524 "WHERE oid = '%u'::pg_catalog.oid",
6525 tinfo
->dobj
.catId
.oid
);
6527 res
= PQexec(g_conn
, query
->data
);
6528 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
6530 /* Expecting a single result only */
6531 ntups
= PQntuples(res
);
6534 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
6535 "query returned %d rows instead of one: %s\n",
6537 ntups
, query
->data
);
6541 typnotnull
= PQgetvalue(res
, 0, PQfnumber(res
, "typnotnull"));
6542 typdefn
= PQgetvalue(res
, 0, PQfnumber(res
, "typdefn"));
6543 if (!PQgetisnull(res
, 0, PQfnumber(res
, "typdefaultbin")))
6544 typdefault
= PQgetvalue(res
, 0, PQfnumber(res
, "typdefaultbin"));
6545 else if (!PQgetisnull(res
, 0, PQfnumber(res
, "typdefault")))
6547 typdefault
= PQgetvalue(res
, 0, PQfnumber(res
, "typdefault"));
6548 typdefault_is_literal
= true; /* it needs quotes */
6553 appendPQExpBuffer(q
,
6554 "CREATE DOMAIN %s AS %s",
6555 fmtId(tinfo
->dobj
.name
),
6558 if (typnotnull
[0] == 't')
6559 appendPQExpBuffer(q
, " NOT NULL");
6561 if (typdefault
!= NULL
)
6563 appendPQExpBuffer(q
, " DEFAULT ");
6564 if (typdefault_is_literal
)
6565 appendStringLiteralAH(q
, typdefault
, fout
);
6567 appendPQExpBufferStr(q
, typdefault
);
6573 * Add any CHECK constraints for the domain
6575 for (i
= 0; i
< tinfo
->nDomChecks
; i
++)
6577 ConstraintInfo
*domcheck
= &(tinfo
->domChecks
[i
]);
6579 if (!domcheck
->separate
)
6580 appendPQExpBuffer(q
, "\n\tCONSTRAINT %s %s",
6581 fmtId(domcheck
->dobj
.name
), domcheck
->condef
);
6584 appendPQExpBuffer(q
, ";\n");
6587 * DROP must be fully qualified in case same name appears in pg_catalog
6589 appendPQExpBuffer(delq
, "DROP DOMAIN %s.",
6590 fmtId(tinfo
->dobj
.namespace->dobj
.name
));
6591 appendPQExpBuffer(delq
, "%s;\n",
6592 fmtId(tinfo
->dobj
.name
));
6594 ArchiveEntry(fout
, tinfo
->dobj
.catId
, tinfo
->dobj
.dumpId
,
6596 tinfo
->dobj
.namespace->dobj
.name
,
6598 tinfo
->rolname
, false,
6599 "DOMAIN", SECTION_PRE_DATA
,
6600 q
->data
, delq
->data
, NULL
,
6601 tinfo
->dobj
.dependencies
, tinfo
->dobj
.nDeps
,
6604 /* Dump Domain Comments */
6605 resetPQExpBuffer(q
);
6607 appendPQExpBuffer(q
, "DOMAIN %s", fmtId(tinfo
->dobj
.name
));
6608 dumpComment(fout
, q
->data
,
6609 tinfo
->dobj
.namespace->dobj
.name
, tinfo
->rolname
,
6610 tinfo
->dobj
.catId
, 0, tinfo
->dobj
.dumpId
);
6612 destroyPQExpBuffer(q
);
6613 destroyPQExpBuffer(delq
);
6614 destroyPQExpBuffer(query
);
6619 * writes out to fout the queries to recreate a user-defined stand-alone
6623 dumpCompositeType(Archive
*fout
, TypeInfo
*tinfo
)
6625 PQExpBuffer q
= createPQExpBuffer();
6626 PQExpBuffer delq
= createPQExpBuffer();
6627 PQExpBuffer query
= createPQExpBuffer();
6634 /* Set proper schema search path so type references list correctly */
6635 selectSourceSchema(tinfo
->dobj
.namespace->dobj
.name
);
6637 /* Fetch type specific details */
6638 /* We assume here that remoteVersion must be at least 70300 */
6640 appendPQExpBuffer(query
, "SELECT a.attname, "
6641 "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn "
6642 "FROM pg_catalog.pg_type t, pg_catalog.pg_attribute a "
6643 "WHERE t.oid = '%u'::pg_catalog.oid "
6644 "AND a.attrelid = t.typrelid "
6645 "AND NOT a.attisdropped "
6646 "ORDER BY a.attnum ",
6647 tinfo
->dobj
.catId
.oid
);
6649 res
= PQexec(g_conn
, query
->data
);
6650 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
6652 /* Expecting at least a single result */
6653 ntups
= PQntuples(res
);
6656 write_msg(NULL
, "query returned no rows: %s\n", query
->data
);
6660 i_attname
= PQfnumber(res
, "attname");
6661 i_atttypdefn
= PQfnumber(res
, "atttypdefn");
6663 appendPQExpBuffer(q
, "CREATE TYPE %s AS (",
6664 fmtId(tinfo
->dobj
.name
));
6666 for (i
= 0; i
< ntups
; i
++)
6671 attname
= PQgetvalue(res
, i
, i_attname
);
6672 atttypdefn
= PQgetvalue(res
, i
, i_atttypdefn
);
6674 appendPQExpBuffer(q
, "\n\t%s %s", fmtId(attname
), atttypdefn
);
6676 appendPQExpBuffer(q
, ",");
6678 appendPQExpBuffer(q
, "\n);\n");
6681 * DROP must be fully qualified in case same name appears in pg_catalog
6683 appendPQExpBuffer(delq
, "DROP TYPE %s.",
6684 fmtId(tinfo
->dobj
.namespace->dobj
.name
));
6685 appendPQExpBuffer(delq
, "%s;\n",
6686 fmtId(tinfo
->dobj
.name
));
6688 ArchiveEntry(fout
, tinfo
->dobj
.catId
, tinfo
->dobj
.dumpId
,
6690 tinfo
->dobj
.namespace->dobj
.name
,
6692 tinfo
->rolname
, false,
6693 "TYPE", SECTION_PRE_DATA
,
6694 q
->data
, delq
->data
, NULL
,
6695 tinfo
->dobj
.dependencies
, tinfo
->dobj
.nDeps
,
6699 /* Dump Type Comments */
6700 resetPQExpBuffer(q
);
6702 appendPQExpBuffer(q
, "TYPE %s", fmtId(tinfo
->dobj
.name
));
6703 dumpComment(fout
, q
->data
,
6704 tinfo
->dobj
.namespace->dobj
.name
, tinfo
->rolname
,
6705 tinfo
->dobj
.catId
, 0, tinfo
->dobj
.dumpId
);
6708 destroyPQExpBuffer(q
);
6709 destroyPQExpBuffer(delq
);
6710 destroyPQExpBuffer(query
);
6715 * writes out to fout the queries to create a shell type
6717 * We dump a shell definition in advance of the I/O functions for the type.
6720 dumpShellType(Archive
*fout
, ShellTypeInfo
*stinfo
)
6724 /* Skip if not to be dumped */
6725 if (!stinfo
->dobj
.dump
|| dataOnly
)
6728 q
= createPQExpBuffer();
6731 * Note the lack of a DROP command for the shell type; any required DROP
6732 * is driven off the base type entry, instead. This interacts with
6733 * _printTocEntry()'s use of the presence of a DROP command to decide
6734 * whether an entry needs an ALTER OWNER command. We don't want to alter
6735 * the shell type's owner immediately on creation; that should happen only
6736 * after it's filled in, otherwise the backend complains.
6739 appendPQExpBuffer(q
, "CREATE TYPE %s;\n",
6740 fmtId(stinfo
->dobj
.name
));
6742 ArchiveEntry(fout
, stinfo
->dobj
.catId
, stinfo
->dobj
.dumpId
,
6744 stinfo
->dobj
.namespace->dobj
.name
,
6746 stinfo
->baseType
->rolname
, false,
6747 "SHELL TYPE", SECTION_PRE_DATA
,
6749 stinfo
->dobj
.dependencies
, stinfo
->dobj
.nDeps
,
6752 destroyPQExpBuffer(q
);
6756 * Determine whether we want to dump definitions for procedural languages.
6757 * Since the languages themselves don't have schemas, we can't rely on
6758 * the normal schema-based selection mechanism. We choose to dump them
6759 * whenever neither --schema nor --table was given. (Before 8.1, we used
6760 * the dump flag of the PL's call handler function, but in 8.1 this will
6761 * probably always be false since call handlers are created in pg_catalog.)
6763 * For some backwards compatibility with the older behavior, we forcibly
6764 * dump a PL if its handler function (and validator if any) are in a
6765 * dumpable namespace. That case is not checked here.
6768 shouldDumpProcLangs(void)
6770 if (!include_everything
)
6772 /* And they're schema not data */
6780 * writes out to fout the queries to recreate a user-defined
6781 * procedural language
6784 dumpProcLang(Archive
*fout
, ProcLangInfo
*plang
)
6792 FuncInfo
*validatorInfo
= NULL
;
6798 * Try to find the support function(s). It is not an error if we don't
6799 * find them --- if the functions are in the pg_catalog schema, as is
6800 * standard in 8.1 and up, then we won't have loaded them. (In this case
6801 * we will emit a parameterless CREATE LANGUAGE command, which will
6802 * require PL template knowledge in the backend to reload.)
6805 funcInfo
= findFuncByOid(plang
->lanplcallfoid
);
6806 if (funcInfo
!= NULL
&& !funcInfo
->dobj
.dump
)
6807 funcInfo
= NULL
; /* treat not-dumped same as not-found */
6809 if (OidIsValid(plang
->lanvalidator
))
6811 validatorInfo
= findFuncByOid(plang
->lanvalidator
);
6812 if (validatorInfo
!= NULL
&& !validatorInfo
->dobj
.dump
)
6813 validatorInfo
= NULL
;
6817 * If the functions are dumpable then emit a traditional CREATE LANGUAGE
6818 * with parameters. Otherwise, dump only if shouldDumpProcLangs() says to
6821 useParams
= (funcInfo
!= NULL
&&
6822 (validatorInfo
!= NULL
|| !OidIsValid(plang
->lanvalidator
)));
6824 if (!useParams
&& !shouldDumpProcLangs())
6827 defqry
= createPQExpBuffer();
6828 delqry
= createPQExpBuffer();
6830 qlanname
= strdup(fmtId(plang
->dobj
.name
));
6833 * If dumping a HANDLER clause, treat the language as being in the handler
6834 * function's schema; this avoids cluttering the HANDLER clause. Otherwise
6835 * it doesn't really have a schema.
6838 lanschema
= funcInfo
->dobj
.namespace->dobj
.name
;
6842 appendPQExpBuffer(delqry
, "DROP PROCEDURAL LANGUAGE %s;\n",
6845 appendPQExpBuffer(defqry
, "CREATE %sPROCEDURAL LANGUAGE %s",
6846 (useParams
&& plang
->lanpltrusted
) ? "TRUSTED " : "",
6850 appendPQExpBuffer(defqry
, " HANDLER %s",
6851 fmtId(funcInfo
->dobj
.name
));
6852 if (OidIsValid(plang
->lanvalidator
))
6854 appendPQExpBuffer(defqry
, " VALIDATOR ");
6855 /* Cope with possibility that validator is in different schema */
6856 if (validatorInfo
->dobj
.namespace != funcInfo
->dobj
.namespace)
6857 appendPQExpBuffer(defqry
, "%s.",
6858 fmtId(validatorInfo
->dobj
.namespace->dobj
.name
));
6859 appendPQExpBuffer(defqry
, "%s",
6860 fmtId(validatorInfo
->dobj
.name
));
6863 appendPQExpBuffer(defqry
, ";\n");
6865 ArchiveEntry(fout
, plang
->dobj
.catId
, plang
->dobj
.dumpId
,
6867 lanschema
, NULL
, plang
->lanowner
,
6868 false, "PROCEDURAL LANGUAGE", SECTION_PRE_DATA
,
6869 defqry
->data
, delqry
->data
, NULL
,
6870 plang
->dobj
.dependencies
, plang
->dobj
.nDeps
,
6873 /* Dump Proc Lang Comments */
6874 resetPQExpBuffer(defqry
);
6875 appendPQExpBuffer(defqry
, "LANGUAGE %s", qlanname
);
6876 dumpComment(fout
, defqry
->data
,
6878 plang
->dobj
.catId
, 0, plang
->dobj
.dumpId
);
6880 if (plang
->lanpltrusted
)
6881 dumpACL(fout
, plang
->dobj
.catId
, plang
->dobj
.dumpId
, "LANGUAGE",
6882 qlanname
, NULL
, plang
->dobj
.name
,
6884 plang
->lanowner
, plang
->lanacl
);
6888 destroyPQExpBuffer(defqry
);
6889 destroyPQExpBuffer(delqry
);
6893 * format_function_arguments: generate function name and argument list
6895 * This is used when we can rely on pg_get_function_arguments to format
6896 * the argument list.
6899 format_function_arguments(FuncInfo
*finfo
, char *funcargs
)
6903 initPQExpBuffer(&fn
);
6904 appendPQExpBuffer(&fn
, "%s(%s)", fmtId(finfo
->dobj
.name
), funcargs
);
6909 * format_function_arguments_old: generate function name and argument list
6911 * The argument type names are qualified if needed. The function name
6912 * is never qualified.
6914 * This is used only with pre-8.4 servers, so we aren't expecting to see
6915 * VARIADIC or TABLE arguments, nor are there any defaults for arguments.
6917 * Any or all of allargtypes, argmodes, argnames may be NULL.
6920 format_function_arguments_old(FuncInfo
*finfo
, int nallargs
,
6928 initPQExpBuffer(&fn
);
6929 appendPQExpBuffer(&fn
, "%s(", fmtId(finfo
->dobj
.name
));
6930 for (j
= 0; j
< nallargs
; j
++)
6934 const char *argmode
;
6935 const char *argname
;
6937 typid
= allargtypes
? atooid(allargtypes
[j
]) : finfo
->argtypes
[j
];
6938 typname
= getFormattedTypeName(typid
, zeroAsOpaque
);
6942 switch (argmodes
[j
][0])
6947 case PROARGMODE_OUT
:
6950 case PROARGMODE_INOUT
:
6954 write_msg(NULL
, "WARNING: bogus value in proargmodes array\n");
6962 argname
= argnames
? argnames
[j
] : (char *) NULL
;
6963 if (argname
&& argname
[0] == '\0')
6966 appendPQExpBuffer(&fn
, "%s%s%s%s%s",
6967 (j
> 0) ? ", " : "",
6969 argname
? fmtId(argname
) : "",
6974 appendPQExpBuffer(&fn
, ")");
6979 * format_function_signature: generate function name and argument list
6981 * This is like format_function_arguments_old except that only a minimal
6982 * list of input argument types is generated; this is sufficient to
6983 * reference the function, but not to define it.
6985 * If honor_quotes is false then the function name is never quoted.
6986 * This is appropriate for use in TOC tags, but not in SQL commands.
6989 format_function_signature(FuncInfo
*finfo
, bool honor_quotes
)
6994 initPQExpBuffer(&fn
);
6996 appendPQExpBuffer(&fn
, "%s(", fmtId(finfo
->dobj
.name
));
6998 appendPQExpBuffer(&fn
, "%s(", finfo
->dobj
.name
);
6999 for (j
= 0; j
< finfo
->nargs
; j
++)
7003 typname
= getFormattedTypeName(finfo
->argtypes
[j
], zeroAsOpaque
);
7005 appendPQExpBuffer(&fn
, "%s%s",
7006 (j
> 0) ? ", " : "",
7010 appendPQExpBuffer(&fn
, ")");
7017 * dump out one function
7020 dumpFunc(Archive
*fout
, FuncInfo
*finfo
)
7027 char *funcsig
; /* identity signature */
7028 char *funcfullsig
; /* full signature */
7037 char *proallargtypes
;
7050 char **allargtypes
= NULL
;
7051 char **argmodes
= NULL
;
7052 char **argnames
= NULL
;
7053 char **configitems
= NULL
;
7054 int nconfigitems
= 0;
7057 /* Skip if not to be dumped */
7058 if (!finfo
->dobj
.dump
|| dataOnly
)
7061 query
= createPQExpBuffer();
7062 q
= createPQExpBuffer();
7063 delqry
= createPQExpBuffer();
7064 asPart
= createPQExpBuffer();
7066 /* Set proper schema search path so type references list correctly */
7067 selectSourceSchema(finfo
->dobj
.namespace->dobj
.name
);
7069 /* Fetch function-specific details */
7070 if (g_fout
->remoteVersion
>= 80400)
7073 * In 8.4 and up we rely on pg_get_function_arguments and
7074 * pg_get_function_result instead of examining proallargtypes etc.
7076 appendPQExpBuffer(query
,
7077 "SELECT proretset, prosrc, probin, "
7078 "pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
7079 "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
7080 "pg_catalog.pg_get_function_result(oid) AS funcresult, "
7081 "proiswindow, provolatile, proisstrict, prosecdef, "
7082 "proconfig, procost, prorows, "
7083 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
7084 "FROM pg_catalog.pg_proc "
7085 "WHERE oid = '%u'::pg_catalog.oid",
7086 finfo
->dobj
.catId
.oid
);
7088 else if (g_fout
->remoteVersion
>= 80300)
7090 appendPQExpBuffer(query
,
7091 "SELECT proretset, prosrc, probin, "
7092 "proallargtypes, proargmodes, proargnames, "
7093 "false AS proiswindow, "
7094 "provolatile, proisstrict, prosecdef, "
7095 "proconfig, procost, prorows, "
7096 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
7097 "FROM pg_catalog.pg_proc "
7098 "WHERE oid = '%u'::pg_catalog.oid",
7099 finfo
->dobj
.catId
.oid
);
7101 else if (g_fout
->remoteVersion
>= 80100)
7103 appendPQExpBuffer(query
,
7104 "SELECT proretset, prosrc, probin, "
7105 "proallargtypes, proargmodes, proargnames, "
7106 "false AS proiswindow, "
7107 "provolatile, proisstrict, prosecdef, "
7108 "null AS proconfig, 0 AS procost, 0 AS prorows, "
7109 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
7110 "FROM pg_catalog.pg_proc "
7111 "WHERE oid = '%u'::pg_catalog.oid",
7112 finfo
->dobj
.catId
.oid
);
7114 else if (g_fout
->remoteVersion
>= 80000)
7116 appendPQExpBuffer(query
,
7117 "SELECT proretset, prosrc, probin, "
7118 "null AS proallargtypes, "
7119 "null AS proargmodes, "
7121 "false AS proiswindow, "
7122 "provolatile, proisstrict, prosecdef, "
7123 "null AS proconfig, 0 AS procost, 0 AS prorows, "
7124 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
7125 "FROM pg_catalog.pg_proc "
7126 "WHERE oid = '%u'::pg_catalog.oid",
7127 finfo
->dobj
.catId
.oid
);
7129 else if (g_fout
->remoteVersion
>= 70300)
7131 appendPQExpBuffer(query
,
7132 "SELECT proretset, prosrc, probin, "
7133 "null AS proallargtypes, "
7134 "null AS proargmodes, "
7135 "null AS proargnames, "
7136 "false AS proiswindow, "
7137 "provolatile, proisstrict, prosecdef, "
7138 "null AS proconfig, 0 AS procost, 0 AS prorows, "
7139 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
7140 "FROM pg_catalog.pg_proc "
7141 "WHERE oid = '%u'::pg_catalog.oid",
7142 finfo
->dobj
.catId
.oid
);
7144 else if (g_fout
->remoteVersion
>= 70100)
7146 appendPQExpBuffer(query
,
7147 "SELECT proretset, prosrc, probin, "
7148 "null AS proallargtypes, "
7149 "null AS proargmodes, "
7150 "null AS proargnames, "
7151 "false AS proiswindow, "
7152 "case when proiscachable then 'i' else 'v' end AS provolatile, "
7154 "false AS prosecdef, "
7155 "null AS proconfig, 0 AS procost, 0 AS prorows, "
7156 "(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname "
7158 "WHERE oid = '%u'::oid",
7159 finfo
->dobj
.catId
.oid
);
7163 appendPQExpBuffer(query
,
7164 "SELECT proretset, prosrc, probin, "
7165 "null AS proallargtypes, "
7166 "null AS proargmodes, "
7167 "null AS proargnames, "
7168 "false AS proiswindow, "
7169 "CASE WHEN proiscachable THEN 'i' ELSE 'v' END AS provolatile, "
7170 "false AS proisstrict, "
7171 "false AS prosecdef, "
7172 "NULL AS proconfig, 0 AS procost, 0 AS prorows, "
7173 "(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname "
7175 "WHERE oid = '%u'::oid",
7176 finfo
->dobj
.catId
.oid
);
7179 res
= PQexec(g_conn
, query
->data
);
7180 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
7182 /* Expecting a single result only */
7183 ntups
= PQntuples(res
);
7186 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
7187 "query returned %d rows instead of one: %s\n",
7189 ntups
, query
->data
);
7193 proretset
= PQgetvalue(res
, 0, PQfnumber(res
, "proretset"));
7194 prosrc
= PQgetvalue(res
, 0, PQfnumber(res
, "prosrc"));
7195 probin
= PQgetvalue(res
, 0, PQfnumber(res
, "probin"));
7196 if (g_fout
->remoteVersion
>= 80400)
7198 funcargs
= PQgetvalue(res
, 0, PQfnumber(res
, "funcargs"));
7199 funciargs
= PQgetvalue(res
, 0, PQfnumber(res
, "funciargs"));
7200 funcresult
= PQgetvalue(res
, 0, PQfnumber(res
, "funcresult"));
7201 proallargtypes
= proargmodes
= proargnames
= NULL
;
7205 proallargtypes
= PQgetvalue(res
, 0, PQfnumber(res
, "proallargtypes"));
7206 proargmodes
= PQgetvalue(res
, 0, PQfnumber(res
, "proargmodes"));
7207 proargnames
= PQgetvalue(res
, 0, PQfnumber(res
, "proargnames"));
7208 funcargs
= funciargs
= funcresult
= NULL
;
7210 proiswindow
= PQgetvalue(res
, 0, PQfnumber(res
, "proiswindow"));
7211 provolatile
= PQgetvalue(res
, 0, PQfnumber(res
, "provolatile"));
7212 proisstrict
= PQgetvalue(res
, 0, PQfnumber(res
, "proisstrict"));
7213 prosecdef
= PQgetvalue(res
, 0, PQfnumber(res
, "prosecdef"));
7214 proconfig
= PQgetvalue(res
, 0, PQfnumber(res
, "proconfig"));
7215 procost
= PQgetvalue(res
, 0, PQfnumber(res
, "procost"));
7216 prorows
= PQgetvalue(res
, 0, PQfnumber(res
, "prorows"));
7217 lanname
= PQgetvalue(res
, 0, PQfnumber(res
, "lanname"));
7220 * See backend/commands/functioncmds.c for details of how the 'AS' clause
7221 * is used. In 8.4 and up, an unused probin is NULL (here ""); previous
7222 * versions would set it to "-". There are no known cases in which prosrc
7223 * is unused, so the tests below for "-" are probably useless.
7225 if (probin
[0] != '\0' && strcmp(probin
, "-") != 0)
7227 appendPQExpBuffer(asPart
, "AS ");
7228 appendStringLiteralAH(asPart
, probin
, fout
);
7229 if (strcmp(prosrc
, "-") != 0)
7231 appendPQExpBuffer(asPart
, ", ");
7234 * where we have bin, use dollar quoting if allowed and src
7235 * contains quote or backslash; else use regular quoting.
7237 if (disable_dollar_quoting
||
7238 (strchr(prosrc
, '\'') == NULL
&& strchr(prosrc
, '\\') == NULL
))
7239 appendStringLiteralAH(asPart
, prosrc
, fout
);
7241 appendStringLiteralDQ(asPart
, prosrc
, NULL
);
7246 if (strcmp(prosrc
, "-") != 0)
7248 appendPQExpBuffer(asPart
, "AS ");
7249 /* with no bin, dollar quote src unconditionally if allowed */
7250 if (disable_dollar_quoting
)
7251 appendStringLiteralAH(asPart
, prosrc
, fout
);
7253 appendStringLiteralDQ(asPart
, prosrc
, NULL
);
7257 nallargs
= finfo
->nargs
; /* unless we learn different from allargs */
7259 if (proallargtypes
&& *proallargtypes
)
7263 if (!parsePGArray(proallargtypes
, &allargtypes
, &nitems
) ||
7264 nitems
< finfo
->nargs
)
7266 write_msg(NULL
, "WARNING: could not parse proallargtypes array\n");
7275 if (proargmodes
&& *proargmodes
)
7279 if (!parsePGArray(proargmodes
, &argmodes
, &nitems
) ||
7282 write_msg(NULL
, "WARNING: could not parse proargmodes array\n");
7289 if (proargnames
&& *proargnames
)
7293 if (!parsePGArray(proargnames
, &argnames
, &nitems
) ||
7296 write_msg(NULL
, "WARNING: could not parse proargnames array\n");
7303 if (proconfig
&& *proconfig
)
7305 if (!parsePGArray(proconfig
, &configitems
, &nconfigitems
))
7307 write_msg(NULL
, "WARNING: could not parse proconfig array\n");
7317 /* 8.4 or later; we rely on server-side code for most of the work */
7318 funcfullsig
= format_function_arguments(finfo
, funcargs
);
7319 funcsig
= format_function_arguments(finfo
, funciargs
);
7323 /* pre-8.4, do it ourselves */
7324 funcsig
= format_function_arguments_old(finfo
, nallargs
, allargtypes
,
7325 argmodes
, argnames
);
7326 funcfullsig
= funcsig
;
7329 funcsig_tag
= format_function_signature(finfo
, false);
7332 * DROP must be fully qualified in case same name appears in pg_catalog
7334 appendPQExpBuffer(delqry
, "DROP FUNCTION %s.%s;\n",
7335 fmtId(finfo
->dobj
.namespace->dobj
.name
),
7338 appendPQExpBuffer(q
, "CREATE FUNCTION %s ", funcfullsig
);
7340 appendPQExpBuffer(q
, "RETURNS %s", funcresult
);
7343 rettypename
= getFormattedTypeName(finfo
->prorettype
, zeroAsOpaque
);
7344 appendPQExpBuffer(q
, "RETURNS %s%s",
7345 (proretset
[0] == 't') ? "SETOF " : "",
7350 appendPQExpBuffer(q
, "\n LANGUAGE %s", fmtId(lanname
));
7352 if (proiswindow
[0] == 't')
7353 appendPQExpBuffer(q
, " WINDOW");
7355 if (provolatile
[0] != PROVOLATILE_VOLATILE
)
7357 if (provolatile
[0] == PROVOLATILE_IMMUTABLE
)
7358 appendPQExpBuffer(q
, " IMMUTABLE");
7359 else if (provolatile
[0] == PROVOLATILE_STABLE
)
7360 appendPQExpBuffer(q
, " STABLE");
7361 else if (provolatile
[0] != PROVOLATILE_VOLATILE
)
7363 write_msg(NULL
, "unrecognized provolatile value for function \"%s\"\n",
7369 if (proisstrict
[0] == 't')
7370 appendPQExpBuffer(q
, " STRICT");
7372 if (prosecdef
[0] == 't')
7373 appendPQExpBuffer(q
, " SECURITY DEFINER");
7376 * COST and ROWS are emitted only if present and not default, so as not to
7377 * break backwards-compatibility of the dump without need. Keep this code
7378 * in sync with the defaults in functioncmds.c.
7380 if (strcmp(procost
, "0") != 0)
7382 if (strcmp(lanname
, "internal") == 0 || strcmp(lanname
, "c") == 0)
7384 /* default cost is 1 */
7385 if (strcmp(procost
, "1") != 0)
7386 appendPQExpBuffer(q
, " COST %s", procost
);
7390 /* default cost is 100 */
7391 if (strcmp(procost
, "100") != 0)
7392 appendPQExpBuffer(q
, " COST %s", procost
);
7395 if (proretset
[0] == 't' &&
7396 strcmp(prorows
, "0") != 0 && strcmp(prorows
, "1000") != 0)
7397 appendPQExpBuffer(q
, " ROWS %s", prorows
);
7399 for (i
= 0; i
< nconfigitems
; i
++)
7401 /* we feel free to scribble on configitems[] here */
7402 char *configitem
= configitems
[i
];
7405 pos
= strchr(configitem
, '=');
7409 appendPQExpBuffer(q
, "\n SET %s TO ", fmtId(configitem
));
7412 * Some GUC variable names are 'LIST' type and hence must not be
7415 if (pg_strcasecmp(configitem
, "DateStyle") == 0
7416 || pg_strcasecmp(configitem
, "search_path") == 0)
7417 appendPQExpBuffer(q
, "%s", pos
);
7419 appendStringLiteralAH(q
, pos
, fout
);
7422 appendPQExpBuffer(q
, "\n %s;\n", asPart
->data
);
7424 ArchiveEntry(fout
, finfo
->dobj
.catId
, finfo
->dobj
.dumpId
,
7426 finfo
->dobj
.namespace->dobj
.name
,
7428 finfo
->rolname
, false,
7429 "FUNCTION", SECTION_PRE_DATA
,
7430 q
->data
, delqry
->data
, NULL
,
7431 finfo
->dobj
.dependencies
, finfo
->dobj
.nDeps
,
7434 /* Dump Function Comments */
7435 resetPQExpBuffer(q
);
7436 appendPQExpBuffer(q
, "FUNCTION %s", funcsig
);
7437 dumpComment(fout
, q
->data
,
7438 finfo
->dobj
.namespace->dobj
.name
, finfo
->rolname
,
7439 finfo
->dobj
.catId
, 0, finfo
->dobj
.dumpId
);
7441 dumpACL(fout
, finfo
->dobj
.catId
, finfo
->dobj
.dumpId
, "FUNCTION",
7442 funcsig
, NULL
, funcsig_tag
,
7443 finfo
->dobj
.namespace->dobj
.name
,
7444 finfo
->rolname
, finfo
->proacl
);
7448 destroyPQExpBuffer(query
);
7449 destroyPQExpBuffer(q
);
7450 destroyPQExpBuffer(delqry
);
7451 destroyPQExpBuffer(asPart
);
7466 * Dump a user-defined cast
7469 dumpCast(Archive
*fout
, CastInfo
*cast
)
7473 PQExpBuffer castsig
;
7474 FuncInfo
*funcInfo
= NULL
;
7475 TypeInfo
*sourceInfo
;
7476 TypeInfo
*targetInfo
;
7481 if (OidIsValid(cast
->castfunc
))
7483 funcInfo
= findFuncByOid(cast
->castfunc
);
7484 if (funcInfo
== NULL
)
7489 * As per discussion we dump casts if one or more of the underlying
7490 * objects (the conversion function and the two data types) are not
7491 * builtin AND if all of the non-builtin objects are included in the dump.
7492 * Builtin meaning, the namespace name does not start with "pg_".
7494 sourceInfo
= findTypeByOid(cast
->castsource
);
7495 targetInfo
= findTypeByOid(cast
->casttarget
);
7497 if (sourceInfo
== NULL
|| targetInfo
== NULL
)
7501 * Skip this cast if all objects are from pg_
7503 if ((funcInfo
== NULL
||
7504 strncmp(funcInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) == 0) &&
7505 strncmp(sourceInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) == 0 &&
7506 strncmp(targetInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) == 0)
7510 * Skip cast if function isn't from pg_ and is not to be dumped.
7513 strncmp(funcInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) != 0 &&
7514 !funcInfo
->dobj
.dump
)
7518 * Same for the source type
7520 if (strncmp(sourceInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) != 0 &&
7521 !sourceInfo
->dobj
.dump
)
7525 * and the target type.
7527 if (strncmp(targetInfo
->dobj
.namespace->dobj
.name
, "pg_", 3) != 0 &&
7528 !targetInfo
->dobj
.dump
)
7531 /* Make sure we are in proper schema (needed for getFormattedTypeName) */
7532 selectSourceSchema("pg_catalog");
7534 defqry
= createPQExpBuffer();
7535 delqry
= createPQExpBuffer();
7536 castsig
= createPQExpBuffer();
7538 appendPQExpBuffer(delqry
, "DROP CAST (%s AS %s);\n",
7539 getFormattedTypeName(cast
->castsource
, zeroAsNone
),
7540 getFormattedTypeName(cast
->casttarget
, zeroAsNone
));
7542 appendPQExpBuffer(defqry
, "CREATE CAST (%s AS %s) ",
7543 getFormattedTypeName(cast
->castsource
, zeroAsNone
),
7544 getFormattedTypeName(cast
->casttarget
, zeroAsNone
));
7546 switch (cast
->castmethod
)
7548 case COERCION_METHOD_BINARY
:
7549 appendPQExpBuffer(defqry
, "WITHOUT FUNCTION");
7551 case COERCION_METHOD_INOUT
:
7552 appendPQExpBuffer(defqry
, "WITH INOUT");
7554 case COERCION_METHOD_FUNCTION
:
7557 * Always qualify the function name, in case it is not in
7558 * pg_catalog schema (format_function_signature won't qualify it).
7560 appendPQExpBuffer(defqry
, "WITH FUNCTION %s.",
7561 fmtId(funcInfo
->dobj
.namespace->dobj
.name
));
7562 appendPQExpBuffer(defqry
, "%s",
7563 format_function_signature(funcInfo
, true));
7566 write_msg(NULL
, "WARNING: bogus value in pg_cast.castmethod field\n");
7569 if (cast
->castcontext
== 'a')
7570 appendPQExpBuffer(defqry
, " AS ASSIGNMENT");
7571 else if (cast
->castcontext
== 'i')
7572 appendPQExpBuffer(defqry
, " AS IMPLICIT");
7573 appendPQExpBuffer(defqry
, ";\n");
7575 appendPQExpBuffer(castsig
, "CAST (%s AS %s)",
7576 getFormattedTypeName(cast
->castsource
, zeroAsNone
),
7577 getFormattedTypeName(cast
->casttarget
, zeroAsNone
));
7579 ArchiveEntry(fout
, cast
->dobj
.catId
, cast
->dobj
.dumpId
,
7581 "pg_catalog", NULL
, "",
7582 false, "CAST", SECTION_PRE_DATA
,
7583 defqry
->data
, delqry
->data
, NULL
,
7584 cast
->dobj
.dependencies
, cast
->dobj
.nDeps
,
7587 /* Dump Cast Comments */
7588 resetPQExpBuffer(defqry
);
7589 appendPQExpBuffer(defqry
, "CAST (%s AS %s)",
7590 getFormattedTypeName(cast
->castsource
, zeroAsNone
),
7591 getFormattedTypeName(cast
->casttarget
, zeroAsNone
));
7592 dumpComment(fout
, defqry
->data
,
7594 cast
->dobj
.catId
, 0, cast
->dobj
.dumpId
);
7596 destroyPQExpBuffer(defqry
);
7597 destroyPQExpBuffer(delqry
);
7598 destroyPQExpBuffer(castsig
);
7603 * write out a single operator definition
7606 dumpOpr(Archive
*fout
, OprInfo
*oprinfo
)
7612 PQExpBuffer details
;
7637 /* Skip if not to be dumped */
7638 if (!oprinfo
->dobj
.dump
|| dataOnly
)
7642 * some operators are invalid because they were the result of user
7643 * defining operators before commutators exist
7645 if (!OidIsValid(oprinfo
->oprcode
))
7648 query
= createPQExpBuffer();
7649 q
= createPQExpBuffer();
7650 delq
= createPQExpBuffer();
7651 oprid
= createPQExpBuffer();
7652 details
= createPQExpBuffer();
7654 /* Make sure we are in proper schema so regoperator works correctly */
7655 selectSourceSchema(oprinfo
->dobj
.namespace->dobj
.name
);
7657 if (g_fout
->remoteVersion
>= 80300)
7659 appendPQExpBuffer(query
, "SELECT oprkind, "
7660 "oprcode::pg_catalog.regprocedure, "
7661 "oprleft::pg_catalog.regtype, "
7662 "oprright::pg_catalog.regtype, "
7663 "oprcom::pg_catalog.regoperator, "
7664 "oprnegate::pg_catalog.regoperator, "
7665 "oprrest::pg_catalog.regprocedure, "
7666 "oprjoin::pg_catalog.regprocedure, "
7667 "oprcanmerge, oprcanhash "
7668 "FROM pg_catalog.pg_operator "
7669 "WHERE oid = '%u'::pg_catalog.oid",
7670 oprinfo
->dobj
.catId
.oid
);
7672 else if (g_fout
->remoteVersion
>= 70300)
7674 appendPQExpBuffer(query
, "SELECT oprkind, "
7675 "oprcode::pg_catalog.regprocedure, "
7676 "oprleft::pg_catalog.regtype, "
7677 "oprright::pg_catalog.regtype, "
7678 "oprcom::pg_catalog.regoperator, "
7679 "oprnegate::pg_catalog.regoperator, "
7680 "oprrest::pg_catalog.regprocedure, "
7681 "oprjoin::pg_catalog.regprocedure, "
7682 "(oprlsortop != 0) AS oprcanmerge, "
7684 "FROM pg_catalog.pg_operator "
7685 "WHERE oid = '%u'::pg_catalog.oid",
7686 oprinfo
->dobj
.catId
.oid
);
7688 else if (g_fout
->remoteVersion
>= 70100)
7690 appendPQExpBuffer(query
, "SELECT oprkind, oprcode, "
7691 "CASE WHEN oprleft = 0 THEN '-' "
7692 "ELSE format_type(oprleft, NULL) END AS oprleft, "
7693 "CASE WHEN oprright = 0 THEN '-' "
7694 "ELSE format_type(oprright, NULL) END AS oprright, "
7695 "oprcom, oprnegate, oprrest, oprjoin, "
7696 "(oprlsortop != 0) AS oprcanmerge, "
7699 "WHERE oid = '%u'::oid",
7700 oprinfo
->dobj
.catId
.oid
);
7704 appendPQExpBuffer(query
, "SELECT oprkind, oprcode, "
7705 "CASE WHEN oprleft = 0 THEN '-'::name "
7706 "ELSE (SELECT typname FROM pg_type WHERE oid = oprleft) END AS oprleft, "
7707 "CASE WHEN oprright = 0 THEN '-'::name "
7708 "ELSE (SELECT typname FROM pg_type WHERE oid = oprright) END AS oprright, "
7709 "oprcom, oprnegate, oprrest, oprjoin, "
7710 "(oprlsortop != 0) AS oprcanmerge, "
7713 "WHERE oid = '%u'::oid",
7714 oprinfo
->dobj
.catId
.oid
);
7717 res
= PQexec(g_conn
, query
->data
);
7718 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
7720 /* Expecting a single result only */
7721 ntups
= PQntuples(res
);
7724 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
7725 "query returned %d rows instead of one: %s\n",
7727 ntups
, query
->data
);
7731 i_oprkind
= PQfnumber(res
, "oprkind");
7732 i_oprcode
= PQfnumber(res
, "oprcode");
7733 i_oprleft
= PQfnumber(res
, "oprleft");
7734 i_oprright
= PQfnumber(res
, "oprright");
7735 i_oprcom
= PQfnumber(res
, "oprcom");
7736 i_oprnegate
= PQfnumber(res
, "oprnegate");
7737 i_oprrest
= PQfnumber(res
, "oprrest");
7738 i_oprjoin
= PQfnumber(res
, "oprjoin");
7739 i_oprcanmerge
= PQfnumber(res
, "oprcanmerge");
7740 i_oprcanhash
= PQfnumber(res
, "oprcanhash");
7742 oprkind
= PQgetvalue(res
, 0, i_oprkind
);
7743 oprcode
= PQgetvalue(res
, 0, i_oprcode
);
7744 oprleft
= PQgetvalue(res
, 0, i_oprleft
);
7745 oprright
= PQgetvalue(res
, 0, i_oprright
);
7746 oprcom
= PQgetvalue(res
, 0, i_oprcom
);
7747 oprnegate
= PQgetvalue(res
, 0, i_oprnegate
);
7748 oprrest
= PQgetvalue(res
, 0, i_oprrest
);
7749 oprjoin
= PQgetvalue(res
, 0, i_oprjoin
);
7750 oprcanmerge
= PQgetvalue(res
, 0, i_oprcanmerge
);
7751 oprcanhash
= PQgetvalue(res
, 0, i_oprcanhash
);
7753 appendPQExpBuffer(details
, " PROCEDURE = %s",
7754 convertRegProcReference(oprcode
));
7756 appendPQExpBuffer(oprid
, "%s (",
7757 oprinfo
->dobj
.name
);
7760 * right unary means there's a left arg and left unary means there's a
7763 if (strcmp(oprkind
, "r") == 0 ||
7764 strcmp(oprkind
, "b") == 0)
7766 if (g_fout
->remoteVersion
>= 70100)
7769 name
= fmtId(oprleft
);
7770 appendPQExpBuffer(details
, ",\n LEFTARG = %s", name
);
7771 appendPQExpBuffer(oprid
, "%s", name
);
7774 appendPQExpBuffer(oprid
, "NONE");
7776 if (strcmp(oprkind
, "l") == 0 ||
7777 strcmp(oprkind
, "b") == 0)
7779 if (g_fout
->remoteVersion
>= 70100)
7782 name
= fmtId(oprright
);
7783 appendPQExpBuffer(details
, ",\n RIGHTARG = %s", name
);
7784 appendPQExpBuffer(oprid
, ", %s)", name
);
7787 appendPQExpBuffer(oprid
, ", NONE)");
7789 name
= convertOperatorReference(oprcom
);
7791 appendPQExpBuffer(details
, ",\n COMMUTATOR = %s", name
);
7793 name
= convertOperatorReference(oprnegate
);
7795 appendPQExpBuffer(details
, ",\n NEGATOR = %s", name
);
7797 if (strcmp(oprcanmerge
, "t") == 0)
7798 appendPQExpBuffer(details
, ",\n MERGES");
7800 if (strcmp(oprcanhash
, "t") == 0)
7801 appendPQExpBuffer(details
, ",\n HASHES");
7803 name
= convertRegProcReference(oprrest
);
7805 appendPQExpBuffer(details
, ",\n RESTRICT = %s", name
);
7807 name
= convertRegProcReference(oprjoin
);
7809 appendPQExpBuffer(details
, ",\n JOIN = %s", name
);
7812 * DROP must be fully qualified in case same name appears in pg_catalog
7814 appendPQExpBuffer(delq
, "DROP OPERATOR %s.%s;\n",
7815 fmtId(oprinfo
->dobj
.namespace->dobj
.name
),
7818 appendPQExpBuffer(q
, "CREATE OPERATOR %s (\n%s\n);\n",
7819 oprinfo
->dobj
.name
, details
->data
);
7821 ArchiveEntry(fout
, oprinfo
->dobj
.catId
, oprinfo
->dobj
.dumpId
,
7823 oprinfo
->dobj
.namespace->dobj
.name
,
7826 false, "OPERATOR", SECTION_PRE_DATA
,
7827 q
->data
, delq
->data
, NULL
,
7828 oprinfo
->dobj
.dependencies
, oprinfo
->dobj
.nDeps
,
7831 /* Dump Operator Comments */
7832 resetPQExpBuffer(q
);
7833 appendPQExpBuffer(q
, "OPERATOR %s", oprid
->data
);
7834 dumpComment(fout
, q
->data
,
7835 oprinfo
->dobj
.namespace->dobj
.name
, oprinfo
->rolname
,
7836 oprinfo
->dobj
.catId
, 0, oprinfo
->dobj
.dumpId
);
7840 destroyPQExpBuffer(query
);
7841 destroyPQExpBuffer(q
);
7842 destroyPQExpBuffer(delq
);
7843 destroyPQExpBuffer(oprid
);
7844 destroyPQExpBuffer(details
);
7848 * Convert a function reference obtained from pg_operator
7850 * Returns what to print, or NULL if function references is InvalidOid
7852 * In 7.3 the input is a REGPROCEDURE display; we have to strip the
7853 * argument-types part. In prior versions, the input is a REGPROC display.
7856 convertRegProcReference(const char *proc
)
7858 /* In all cases "-" means a null reference */
7859 if (strcmp(proc
, "-") == 0)
7862 if (g_fout
->remoteVersion
>= 70300)
7868 name
= strdup(proc
);
7869 /* find non-double-quoted left paren */
7871 for (paren
= name
; *paren
; paren
++)
7873 if (*paren
== '(' && !inquote
)
7884 /* REGPROC before 7.3 does not quote its result */
7889 * Convert an operator cross-reference obtained from pg_operator
7891 * Returns what to print, or NULL to print nothing
7893 * In 7.3 and up the input is a REGOPERATOR display; we have to strip the
7894 * argument-types part, and add OPERATOR() decoration if the name is
7895 * schema-qualified. In older versions, the input is just a numeric OID,
7896 * which we search our operator list for.
7899 convertOperatorReference(const char *opr
)
7903 /* In all cases "0" means a null reference */
7904 if (strcmp(opr
, "0") == 0)
7907 if (g_fout
->remoteVersion
>= 70300)
7916 /* find non-double-quoted left paren, and check for non-quoted dot */
7919 for (ptr
= name
; *ptr
; ptr
++)
7923 else if (*ptr
== '.' && !inquote
)
7925 else if (*ptr
== '(' && !inquote
)
7931 /* If not schema-qualified, don't need to add OPERATOR() */
7934 oname
= malloc(strlen(name
) + 11);
7935 sprintf(oname
, "OPERATOR(%s)", name
);
7940 oprInfo
= findOprByOid(atooid(opr
));
7941 if (oprInfo
== NULL
)
7943 write_msg(NULL
, "WARNING: could not find operator with OID %s\n",
7947 return oprInfo
->dobj
.name
;
7951 * Convert a function OID obtained from pg_ts_parser or pg_ts_template
7953 * It is sufficient to use REGPROC rather than REGPROCEDURE, since the
7954 * argument lists of these functions are predetermined. Note that the
7955 * caller should ensure we are in the proper schema, because the results
7956 * are search path dependent!
7959 convertTSFunction(Oid funcOid
)
7966 snprintf(query
, sizeof(query
),
7967 "SELECT '%u'::pg_catalog.regproc", funcOid
);
7968 res
= PQexec(g_conn
, query
);
7969 check_sql_result(res
, g_conn
, query
, PGRES_TUPLES_OK
);
7971 ntups
= PQntuples(res
);
7974 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
7975 "query returned %d rows instead of one: %s\n",
7981 result
= strdup(PQgetvalue(res
, 0, 0));
7991 * write out a single operator class definition
7994 dumpOpclass(Archive
*fout
, OpclassInfo
*opcinfo
)
8026 /* Skip if not to be dumped */
8027 if (!opcinfo
->dobj
.dump
|| dataOnly
)
8031 * XXX currently we do not implement dumping of operator classes from
8032 * pre-7.3 databases. This could be done but it seems not worth the
8035 if (g_fout
->remoteVersion
< 70300)
8038 query
= createPQExpBuffer();
8039 q
= createPQExpBuffer();
8040 delq
= createPQExpBuffer();
8042 /* Make sure we are in proper schema so regoperator works correctly */
8043 selectSourceSchema(opcinfo
->dobj
.namespace->dobj
.name
);
8045 /* Get additional fields from the pg_opclass row */
8046 if (g_fout
->remoteVersion
>= 80300)
8048 appendPQExpBuffer(query
, "SELECT opcintype::pg_catalog.regtype, "
8049 "opckeytype::pg_catalog.regtype, "
8051 "opfname AS opcfamily, "
8052 "nspname AS opcfamilynsp, "
8053 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
8054 "FROM pg_catalog.pg_opclass c "
8055 "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
8056 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
8057 "WHERE c.oid = '%u'::pg_catalog.oid",
8058 opcinfo
->dobj
.catId
.oid
);
8062 appendPQExpBuffer(query
, "SELECT opcintype::pg_catalog.regtype, "
8063 "opckeytype::pg_catalog.regtype, "
8065 "NULL AS opcfamily, "
8066 "NULL AS opcfamilynsp, "
8067 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
8068 "FROM pg_catalog.pg_opclass "
8069 "WHERE oid = '%u'::pg_catalog.oid",
8070 opcinfo
->dobj
.catId
.oid
);
8073 res
= PQexec(g_conn
, query
->data
);
8074 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8076 /* Expecting a single result only */
8077 ntups
= PQntuples(res
);
8080 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
8081 "query returned %d rows instead of one: %s\n",
8083 ntups
, query
->data
);
8087 i_opcintype
= PQfnumber(res
, "opcintype");
8088 i_opckeytype
= PQfnumber(res
, "opckeytype");
8089 i_opcdefault
= PQfnumber(res
, "opcdefault");
8090 i_opcfamily
= PQfnumber(res
, "opcfamily");
8091 i_opcfamilynsp
= PQfnumber(res
, "opcfamilynsp");
8092 i_amname
= PQfnumber(res
, "amname");
8094 opcintype
= PQgetvalue(res
, 0, i_opcintype
);
8095 opckeytype
= PQgetvalue(res
, 0, i_opckeytype
);
8096 opcdefault
= PQgetvalue(res
, 0, i_opcdefault
);
8097 opcfamily
= PQgetvalue(res
, 0, i_opcfamily
);
8098 opcfamilynsp
= PQgetvalue(res
, 0, i_opcfamilynsp
);
8099 /* amname will still be needed after we PQclear res */
8100 amname
= strdup(PQgetvalue(res
, 0, i_amname
));
8103 * DROP must be fully qualified in case same name appears in pg_catalog
8105 appendPQExpBuffer(delq
, "DROP OPERATOR CLASS %s",
8106 fmtId(opcinfo
->dobj
.namespace->dobj
.name
));
8107 appendPQExpBuffer(delq
, ".%s",
8108 fmtId(opcinfo
->dobj
.name
));
8109 appendPQExpBuffer(delq
, " USING %s;\n",
8112 /* Build the fixed portion of the CREATE command */
8113 appendPQExpBuffer(q
, "CREATE OPERATOR CLASS %s\n ",
8114 fmtId(opcinfo
->dobj
.name
));
8115 if (strcmp(opcdefault
, "t") == 0)
8116 appendPQExpBuffer(q
, "DEFAULT ");
8117 appendPQExpBuffer(q
, "FOR TYPE %s USING %s",
8120 if (strlen(opcfamily
) > 0 &&
8121 (strcmp(opcfamily
, opcinfo
->dobj
.name
) != 0 ||
8122 strcmp(opcfamilynsp
, opcinfo
->dobj
.namespace->dobj
.name
) != 0))
8124 appendPQExpBuffer(q
, " FAMILY ");
8125 if (strcmp(opcfamilynsp
, opcinfo
->dobj
.namespace->dobj
.name
) != 0)
8126 appendPQExpBuffer(q
, "%s.", fmtId(opcfamilynsp
));
8127 appendPQExpBuffer(q
, "%s", fmtId(opcfamily
));
8129 appendPQExpBuffer(q
, " AS\n ");
8133 if (strcmp(opckeytype
, "-") != 0)
8135 appendPQExpBuffer(q
, "STORAGE %s",
8143 * Now fetch and print the OPERATOR entries (pg_amop rows).
8145 resetPQExpBuffer(query
);
8147 if (g_fout
->remoteVersion
>= 80400)
8150 * Print only those opfamily members that are tied to the opclass by
8151 * pg_depend entries.
8153 * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
8154 * an older server's opclass in which it is used. This is to avoid
8155 * hard-to-detect breakage if a newer pg_dump is used to dump from an
8156 * older server and then reload into that old version. This can go
8157 * away once 8.3 is so old as to not be of interest to anyone.
8159 appendPQExpBuffer(query
, "SELECT amopstrategy, false AS amopreqcheck, "
8160 "amopopr::pg_catalog.regoperator "
8161 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
8162 "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
8163 "AND refobjid = '%u'::pg_catalog.oid "
8164 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
8165 "AND objid = ao.oid "
8166 "ORDER BY amopstrategy",
8167 opcinfo
->dobj
.catId
.oid
);
8169 else if (g_fout
->remoteVersion
>= 80300)
8172 * Print only those opfamily members that are tied to the opclass by
8173 * pg_depend entries.
8175 appendPQExpBuffer(query
, "SELECT amopstrategy, amopreqcheck, "
8176 "amopopr::pg_catalog.regoperator "
8177 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
8178 "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
8179 "AND refobjid = '%u'::pg_catalog.oid "
8180 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
8181 "AND objid = ao.oid "
8182 "ORDER BY amopstrategy",
8183 opcinfo
->dobj
.catId
.oid
);
8187 appendPQExpBuffer(query
, "SELECT amopstrategy, amopreqcheck, "
8188 "amopopr::pg_catalog.regoperator "
8189 "FROM pg_catalog.pg_amop "
8190 "WHERE amopclaid = '%u'::pg_catalog.oid "
8191 "ORDER BY amopstrategy",
8192 opcinfo
->dobj
.catId
.oid
);
8195 res
= PQexec(g_conn
, query
->data
);
8196 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8198 ntups
= PQntuples(res
);
8200 i_amopstrategy
= PQfnumber(res
, "amopstrategy");
8201 i_amopreqcheck
= PQfnumber(res
, "amopreqcheck");
8202 i_amopopr
= PQfnumber(res
, "amopopr");
8204 for (i
= 0; i
< ntups
; i
++)
8206 amopstrategy
= PQgetvalue(res
, i
, i_amopstrategy
);
8207 amopreqcheck
= PQgetvalue(res
, i
, i_amopreqcheck
);
8208 amopopr
= PQgetvalue(res
, i
, i_amopopr
);
8211 appendPQExpBuffer(q
, " ,\n ");
8213 appendPQExpBuffer(q
, "OPERATOR %s %s",
8214 amopstrategy
, amopopr
);
8215 if (strcmp(amopreqcheck
, "t") == 0)
8216 appendPQExpBuffer(q
, " RECHECK");
8224 * Now fetch and print the FUNCTION entries (pg_amproc rows).
8226 resetPQExpBuffer(query
);
8228 if (g_fout
->remoteVersion
>= 80300)
8231 * Print only those opfamily members that are tied to the opclass by
8232 * pg_depend entries.
8234 appendPQExpBuffer(query
, "SELECT amprocnum, "
8235 "amproc::pg_catalog.regprocedure "
8236 "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
8237 "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
8238 "AND refobjid = '%u'::pg_catalog.oid "
8239 "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
8240 "AND objid = ap.oid "
8241 "ORDER BY amprocnum",
8242 opcinfo
->dobj
.catId
.oid
);
8246 appendPQExpBuffer(query
, "SELECT amprocnum, "
8247 "amproc::pg_catalog.regprocedure "
8248 "FROM pg_catalog.pg_amproc "
8249 "WHERE amopclaid = '%u'::pg_catalog.oid "
8250 "ORDER BY amprocnum",
8251 opcinfo
->dobj
.catId
.oid
);
8254 res
= PQexec(g_conn
, query
->data
);
8255 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8257 ntups
= PQntuples(res
);
8259 i_amprocnum
= PQfnumber(res
, "amprocnum");
8260 i_amproc
= PQfnumber(res
, "amproc");
8262 for (i
= 0; i
< ntups
; i
++)
8264 amprocnum
= PQgetvalue(res
, i
, i_amprocnum
);
8265 amproc
= PQgetvalue(res
, i
, i_amproc
);
8268 appendPQExpBuffer(q
, " ,\n ");
8270 appendPQExpBuffer(q
, "FUNCTION %s %s",
8278 appendPQExpBuffer(q
, ";\n");
8280 ArchiveEntry(fout
, opcinfo
->dobj
.catId
, opcinfo
->dobj
.dumpId
,
8282 opcinfo
->dobj
.namespace->dobj
.name
,
8285 false, "OPERATOR CLASS", SECTION_PRE_DATA
,
8286 q
->data
, delq
->data
, NULL
,
8287 opcinfo
->dobj
.dependencies
, opcinfo
->dobj
.nDeps
,
8290 /* Dump Operator Class Comments */
8291 resetPQExpBuffer(q
);
8292 appendPQExpBuffer(q
, "OPERATOR CLASS %s",
8293 fmtId(opcinfo
->dobj
.name
));
8294 appendPQExpBuffer(q
, " USING %s",
8296 dumpComment(fout
, q
->data
,
8297 NULL
, opcinfo
->rolname
,
8298 opcinfo
->dobj
.catId
, 0, opcinfo
->dobj
.dumpId
);
8301 destroyPQExpBuffer(query
);
8302 destroyPQExpBuffer(q
);
8303 destroyPQExpBuffer(delq
);
8308 * write out a single operator family definition
8311 dumpOpfamily(Archive
*fout
, OpfamilyInfo
*opfinfo
)
8318 PGresult
*res_procs
;
8326 int i_amproclefttype
;
8327 int i_amprocrighttype
;
8334 char *amproclefttype
;
8335 char *amprocrighttype
;
8339 /* Skip if not to be dumped */
8340 if (!opfinfo
->dobj
.dump
|| dataOnly
)
8344 * We want to dump the opfamily only if (1) it contains "loose" operators
8345 * or functions, or (2) it contains an opclass with a different name or
8346 * owner. Otherwise it's sufficient to let it be created during creation
8347 * of the contained opclass, and not dumping it improves portability of
8348 * the dump. Since we have to fetch the loose operators/funcs anyway, do
8352 query
= createPQExpBuffer();
8353 q
= createPQExpBuffer();
8354 delq
= createPQExpBuffer();
8356 /* Make sure we are in proper schema so regoperator works correctly */
8357 selectSourceSchema(opfinfo
->dobj
.namespace->dobj
.name
);
8360 * Fetch only those opfamily members that are tied directly to the
8361 * opfamily by pg_depend entries.
8363 if (g_fout
->remoteVersion
>= 80400)
8366 * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
8367 * an older server's opclass in which it is used. This is to avoid
8368 * hard-to-detect breakage if a newer pg_dump is used to dump from an
8369 * older server and then reload into that old version. This can go
8370 * away once 8.3 is so old as to not be of interest to anyone.
8372 appendPQExpBuffer(query
, "SELECT amopstrategy, false AS amopreqcheck, "
8373 "amopopr::pg_catalog.regoperator "
8374 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
8375 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8376 "AND refobjid = '%u'::pg_catalog.oid "
8377 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
8378 "AND objid = ao.oid "
8379 "ORDER BY amopstrategy",
8380 opfinfo
->dobj
.catId
.oid
);
8384 appendPQExpBuffer(query
, "SELECT amopstrategy, amopreqcheck, "
8385 "amopopr::pg_catalog.regoperator "
8386 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
8387 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8388 "AND refobjid = '%u'::pg_catalog.oid "
8389 "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
8390 "AND objid = ao.oid "
8391 "ORDER BY amopstrategy",
8392 opfinfo
->dobj
.catId
.oid
);
8395 res_ops
= PQexec(g_conn
, query
->data
);
8396 check_sql_result(res_ops
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8398 resetPQExpBuffer(query
);
8400 appendPQExpBuffer(query
, "SELECT amprocnum, "
8401 "amproc::pg_catalog.regprocedure, "
8402 "amproclefttype::pg_catalog.regtype, "
8403 "amprocrighttype::pg_catalog.regtype "
8404 "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
8405 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8406 "AND refobjid = '%u'::pg_catalog.oid "
8407 "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
8408 "AND objid = ap.oid "
8409 "ORDER BY amprocnum",
8410 opfinfo
->dobj
.catId
.oid
);
8412 res_procs
= PQexec(g_conn
, query
->data
);
8413 check_sql_result(res_procs
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8415 if (PQntuples(res_ops
) == 0 && PQntuples(res_procs
) == 0)
8417 /* No loose members, so check contained opclasses */
8418 resetPQExpBuffer(query
);
8420 appendPQExpBuffer(query
, "SELECT 1 "
8421 "FROM pg_catalog.pg_opclass c, pg_catalog.pg_opfamily f, pg_catalog.pg_depend "
8422 "WHERE f.oid = '%u'::pg_catalog.oid "
8423 "AND refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
8424 "AND refobjid = f.oid "
8425 "AND classid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
8426 "AND objid = c.oid "
8427 "AND (opcname != opfname OR opcnamespace != opfnamespace OR opcowner != opfowner) "
8429 opfinfo
->dobj
.catId
.oid
);
8431 res
= PQexec(g_conn
, query
->data
);
8432 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8434 if (PQntuples(res
) == 0)
8436 /* no need to dump it, so bail out */
8440 destroyPQExpBuffer(query
);
8441 destroyPQExpBuffer(q
);
8442 destroyPQExpBuffer(delq
);
8449 /* Get additional fields from the pg_opfamily row */
8450 resetPQExpBuffer(query
);
8452 appendPQExpBuffer(query
, "SELECT "
8453 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opfmethod) AS amname "
8454 "FROM pg_catalog.pg_opfamily "
8455 "WHERE oid = '%u'::pg_catalog.oid",
8456 opfinfo
->dobj
.catId
.oid
);
8458 res
= PQexec(g_conn
, query
->data
);
8459 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8461 /* Expecting a single result only */
8462 ntups
= PQntuples(res
);
8465 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
8466 "query returned %d rows instead of one: %s\n",
8468 ntups
, query
->data
);
8472 i_amname
= PQfnumber(res
, "amname");
8474 /* amname will still be needed after we PQclear res */
8475 amname
= strdup(PQgetvalue(res
, 0, i_amname
));
8478 * DROP must be fully qualified in case same name appears in pg_catalog
8480 appendPQExpBuffer(delq
, "DROP OPERATOR FAMILY %s",
8481 fmtId(opfinfo
->dobj
.namespace->dobj
.name
));
8482 appendPQExpBuffer(delq
, ".%s",
8483 fmtId(opfinfo
->dobj
.name
));
8484 appendPQExpBuffer(delq
, " USING %s;\n",
8487 /* Build the fixed portion of the CREATE command */
8488 appendPQExpBuffer(q
, "CREATE OPERATOR FAMILY %s",
8489 fmtId(opfinfo
->dobj
.name
));
8490 appendPQExpBuffer(q
, " USING %s;\n",
8495 /* Do we need an ALTER to add loose members? */
8496 if (PQntuples(res_ops
) > 0 || PQntuples(res_procs
) > 0)
8498 appendPQExpBuffer(q
, "ALTER OPERATOR FAMILY %s",
8499 fmtId(opfinfo
->dobj
.name
));
8500 appendPQExpBuffer(q
, " USING %s ADD\n ",
8506 * Now fetch and print the OPERATOR entries (pg_amop rows).
8508 ntups
= PQntuples(res_ops
);
8510 i_amopstrategy
= PQfnumber(res_ops
, "amopstrategy");
8511 i_amopreqcheck
= PQfnumber(res_ops
, "amopreqcheck");
8512 i_amopopr
= PQfnumber(res_ops
, "amopopr");
8514 for (i
= 0; i
< ntups
; i
++)
8516 amopstrategy
= PQgetvalue(res_ops
, i
, i_amopstrategy
);
8517 amopreqcheck
= PQgetvalue(res_ops
, i
, i_amopreqcheck
);
8518 amopopr
= PQgetvalue(res_ops
, i
, i_amopopr
);
8521 appendPQExpBuffer(q
, " ,\n ");
8523 appendPQExpBuffer(q
, "OPERATOR %s %s",
8524 amopstrategy
, amopopr
);
8525 if (strcmp(amopreqcheck
, "t") == 0)
8526 appendPQExpBuffer(q
, " RECHECK");
8532 * Now fetch and print the FUNCTION entries (pg_amproc rows).
8534 ntups
= PQntuples(res_procs
);
8536 i_amprocnum
= PQfnumber(res_procs
, "amprocnum");
8537 i_amproc
= PQfnumber(res_procs
, "amproc");
8538 i_amproclefttype
= PQfnumber(res_procs
, "amproclefttype");
8539 i_amprocrighttype
= PQfnumber(res_procs
, "amprocrighttype");
8541 for (i
= 0; i
< ntups
; i
++)
8543 amprocnum
= PQgetvalue(res_procs
, i
, i_amprocnum
);
8544 amproc
= PQgetvalue(res_procs
, i
, i_amproc
);
8545 amproclefttype
= PQgetvalue(res_procs
, i
, i_amproclefttype
);
8546 amprocrighttype
= PQgetvalue(res_procs
, i
, i_amprocrighttype
);
8549 appendPQExpBuffer(q
, " ,\n ");
8551 appendPQExpBuffer(q
, "FUNCTION %s (%s, %s) %s",
8552 amprocnum
, amproclefttype
, amprocrighttype
,
8558 appendPQExpBuffer(q
, ";\n");
8561 ArchiveEntry(fout
, opfinfo
->dobj
.catId
, opfinfo
->dobj
.dumpId
,
8563 opfinfo
->dobj
.namespace->dobj
.name
,
8566 false, "OPERATOR FAMILY", SECTION_PRE_DATA
,
8567 q
->data
, delq
->data
, NULL
,
8568 opfinfo
->dobj
.dependencies
, opfinfo
->dobj
.nDeps
,
8571 /* Dump Operator Family Comments */
8572 resetPQExpBuffer(q
);
8573 appendPQExpBuffer(q
, "OPERATOR FAMILY %s",
8574 fmtId(opfinfo
->dobj
.name
));
8575 appendPQExpBuffer(q
, " USING %s",
8577 dumpComment(fout
, q
->data
,
8578 NULL
, opfinfo
->rolname
,
8579 opfinfo
->dobj
.catId
, 0, opfinfo
->dobj
.dumpId
);
8584 destroyPQExpBuffer(query
);
8585 destroyPQExpBuffer(q
);
8586 destroyPQExpBuffer(delq
);
8591 * write out a single conversion definition
8594 dumpConversion(Archive
*fout
, ConvInfo
*convinfo
)
8599 PQExpBuffer details
;
8603 int i_conforencoding
;
8604 int i_contoencoding
;
8607 const char *conname
;
8608 const char *conforencoding
;
8609 const char *contoencoding
;
8610 const char *conproc
;
8613 /* Skip if not to be dumped */
8614 if (!convinfo
->dobj
.dump
|| dataOnly
)
8617 query
= createPQExpBuffer();
8618 q
= createPQExpBuffer();
8619 delq
= createPQExpBuffer();
8620 details
= createPQExpBuffer();
8622 /* Make sure we are in proper schema */
8623 selectSourceSchema(convinfo
->dobj
.namespace->dobj
.name
);
8625 /* Get conversion-specific details */
8626 appendPQExpBuffer(query
, "SELECT conname, "
8627 "pg_catalog.pg_encoding_to_char(conforencoding) AS conforencoding, "
8628 "pg_catalog.pg_encoding_to_char(contoencoding) AS contoencoding, "
8629 "conproc, condefault "
8630 "FROM pg_catalog.pg_conversion c "
8631 "WHERE c.oid = '%u'::pg_catalog.oid",
8632 convinfo
->dobj
.catId
.oid
);
8634 res
= PQexec(g_conn
, query
->data
);
8635 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8637 /* Expecting a single result only */
8638 ntups
= PQntuples(res
);
8641 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
8642 "query returned %d rows instead of one: %s\n",
8644 ntups
, query
->data
);
8648 i_conname
= PQfnumber(res
, "conname");
8649 i_conforencoding
= PQfnumber(res
, "conforencoding");
8650 i_contoencoding
= PQfnumber(res
, "contoencoding");
8651 i_conproc
= PQfnumber(res
, "conproc");
8652 i_condefault
= PQfnumber(res
, "condefault");
8654 conname
= PQgetvalue(res
, 0, i_conname
);
8655 conforencoding
= PQgetvalue(res
, 0, i_conforencoding
);
8656 contoencoding
= PQgetvalue(res
, 0, i_contoencoding
);
8657 conproc
= PQgetvalue(res
, 0, i_conproc
);
8658 condefault
= (PQgetvalue(res
, 0, i_condefault
)[0] == 't');
8661 * DROP must be fully qualified in case same name appears in pg_catalog
8663 appendPQExpBuffer(delq
, "DROP CONVERSION %s",
8664 fmtId(convinfo
->dobj
.namespace->dobj
.name
));
8665 appendPQExpBuffer(delq
, ".%s;\n",
8666 fmtId(convinfo
->dobj
.name
));
8668 appendPQExpBuffer(q
, "CREATE %sCONVERSION %s FOR ",
8669 (condefault
) ? "DEFAULT " : "",
8670 fmtId(convinfo
->dobj
.name
));
8671 appendStringLiteralAH(q
, conforencoding
, fout
);
8672 appendPQExpBuffer(q
, " TO ");
8673 appendStringLiteralAH(q
, contoencoding
, fout
);
8674 /* regproc is automatically quoted in 7.3 and above */
8675 appendPQExpBuffer(q
, " FROM %s;\n", conproc
);
8677 ArchiveEntry(fout
, convinfo
->dobj
.catId
, convinfo
->dobj
.dumpId
,
8678 convinfo
->dobj
.name
,
8679 convinfo
->dobj
.namespace->dobj
.name
,
8682 false, "CONVERSION", SECTION_PRE_DATA
,
8683 q
->data
, delq
->data
, NULL
,
8684 convinfo
->dobj
.dependencies
, convinfo
->dobj
.nDeps
,
8687 /* Dump Conversion Comments */
8688 resetPQExpBuffer(q
);
8689 appendPQExpBuffer(q
, "CONVERSION %s", fmtId(convinfo
->dobj
.name
));
8690 dumpComment(fout
, q
->data
,
8691 convinfo
->dobj
.namespace->dobj
.name
, convinfo
->rolname
,
8692 convinfo
->dobj
.catId
, 0, convinfo
->dobj
.dumpId
);
8696 destroyPQExpBuffer(query
);
8697 destroyPQExpBuffer(q
);
8698 destroyPQExpBuffer(delq
);
8699 destroyPQExpBuffer(details
);
8703 * format_aggregate_signature: generate aggregate name and argument list
8705 * The argument type names are qualified if needed. The aggregate name
8706 * is never qualified.
8709 format_aggregate_signature(AggInfo
*agginfo
, Archive
*fout
, bool honor_quotes
)
8711 PQExpBufferData buf
;
8714 initPQExpBuffer(&buf
);
8716 appendPQExpBuffer(&buf
, "%s",
8717 fmtId(agginfo
->aggfn
.dobj
.name
));
8719 appendPQExpBuffer(&buf
, "%s", agginfo
->aggfn
.dobj
.name
);
8721 if (agginfo
->aggfn
.nargs
== 0)
8722 appendPQExpBuffer(&buf
, "(*)");
8725 appendPQExpBuffer(&buf
, "(");
8726 for (j
= 0; j
< agginfo
->aggfn
.nargs
; j
++)
8730 typname
= getFormattedTypeName(agginfo
->aggfn
.argtypes
[j
], zeroAsOpaque
);
8732 appendPQExpBuffer(&buf
, "%s%s",
8733 (j
> 0) ? ", " : "",
8737 appendPQExpBuffer(&buf
, ")");
8744 * write out a single aggregate definition
8747 dumpAgg(Archive
*fout
, AggInfo
*agginfo
)
8752 PQExpBuffer details
;
8763 const char *aggtransfn
;
8764 const char *aggfinalfn
;
8765 const char *aggsortop
;
8766 const char *aggtranstype
;
8767 const char *agginitval
;
8770 /* Skip if not to be dumped */
8771 if (!agginfo
->aggfn
.dobj
.dump
|| dataOnly
)
8774 query
= createPQExpBuffer();
8775 q
= createPQExpBuffer();
8776 delq
= createPQExpBuffer();
8777 details
= createPQExpBuffer();
8779 /* Make sure we are in proper schema */
8780 selectSourceSchema(agginfo
->aggfn
.dobj
.namespace->dobj
.name
);
8782 /* Get aggregate-specific details */
8783 if (g_fout
->remoteVersion
>= 80100)
8785 appendPQExpBuffer(query
, "SELECT aggtransfn, "
8786 "aggfinalfn, aggtranstype::pg_catalog.regtype, "
8787 "aggsortop::pg_catalog.regoperator, "
8789 "'t'::boolean AS convertok "
8790 "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
8791 "WHERE a.aggfnoid = p.oid "
8792 "AND p.oid = '%u'::pg_catalog.oid",
8793 agginfo
->aggfn
.dobj
.catId
.oid
);
8795 else if (g_fout
->remoteVersion
>= 70300)
8797 appendPQExpBuffer(query
, "SELECT aggtransfn, "
8798 "aggfinalfn, aggtranstype::pg_catalog.regtype, "
8801 "'t'::boolean AS convertok "
8802 "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
8803 "WHERE a.aggfnoid = p.oid "
8804 "AND p.oid = '%u'::pg_catalog.oid",
8805 agginfo
->aggfn
.dobj
.catId
.oid
);
8807 else if (g_fout
->remoteVersion
>= 70100)
8809 appendPQExpBuffer(query
, "SELECT aggtransfn, aggfinalfn, "
8810 "format_type(aggtranstype, NULL) AS aggtranstype, "
8813 "'t'::boolean AS convertok "
8814 "FROM pg_aggregate "
8815 "WHERE oid = '%u'::oid",
8816 agginfo
->aggfn
.dobj
.catId
.oid
);
8820 appendPQExpBuffer(query
, "SELECT aggtransfn1 AS aggtransfn, "
8822 "(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, "
8824 "agginitval1 AS agginitval, "
8825 "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) AS convertok "
8826 "FROM pg_aggregate "
8827 "WHERE oid = '%u'::oid",
8828 agginfo
->aggfn
.dobj
.catId
.oid
);
8831 res
= PQexec(g_conn
, query
->data
);
8832 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
8834 /* Expecting a single result only */
8835 ntups
= PQntuples(res
);
8838 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
8839 "query returned %d rows instead of one: %s\n",
8841 ntups
, query
->data
);
8845 i_aggtransfn
= PQfnumber(res
, "aggtransfn");
8846 i_aggfinalfn
= PQfnumber(res
, "aggfinalfn");
8847 i_aggsortop
= PQfnumber(res
, "aggsortop");
8848 i_aggtranstype
= PQfnumber(res
, "aggtranstype");
8849 i_agginitval
= PQfnumber(res
, "agginitval");
8850 i_convertok
= PQfnumber(res
, "convertok");
8852 aggtransfn
= PQgetvalue(res
, 0, i_aggtransfn
);
8853 aggfinalfn
= PQgetvalue(res
, 0, i_aggfinalfn
);
8854 aggsortop
= PQgetvalue(res
, 0, i_aggsortop
);
8855 aggtranstype
= PQgetvalue(res
, 0, i_aggtranstype
);
8856 agginitval
= PQgetvalue(res
, 0, i_agginitval
);
8857 convertok
= (PQgetvalue(res
, 0, i_convertok
)[0] == 't');
8859 aggsig
= format_aggregate_signature(agginfo
, fout
, true);
8860 aggsig_tag
= format_aggregate_signature(agginfo
, fout
, false);
8864 write_msg(NULL
, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
8869 if (g_fout
->remoteVersion
>= 70300)
8871 /* If using 7.3's regproc or regtype, data is already quoted */
8872 appendPQExpBuffer(details
, " SFUNC = %s,\n STYPE = %s",
8876 else if (g_fout
->remoteVersion
>= 70100)
8878 /* format_type quotes, regproc does not */
8879 appendPQExpBuffer(details
, " SFUNC = %s,\n STYPE = %s",
8885 /* need quotes all around */
8886 appendPQExpBuffer(details
, " SFUNC = %s,\n",
8888 appendPQExpBuffer(details
, " STYPE = %s",
8889 fmtId(aggtranstype
));
8892 if (!PQgetisnull(res
, 0, i_agginitval
))
8894 appendPQExpBuffer(details
, ",\n INITCOND = ");
8895 appendStringLiteralAH(details
, agginitval
, fout
);
8898 if (strcmp(aggfinalfn
, "-") != 0)
8900 appendPQExpBuffer(details
, ",\n FINALFUNC = %s",
8904 aggsortop
= convertOperatorReference(aggsortop
);
8907 appendPQExpBuffer(details
, ",\n SORTOP = %s",
8912 * DROP must be fully qualified in case same name appears in pg_catalog
8914 appendPQExpBuffer(delq
, "DROP AGGREGATE %s.%s;\n",
8915 fmtId(agginfo
->aggfn
.dobj
.namespace->dobj
.name
),
8918 appendPQExpBuffer(q
, "CREATE AGGREGATE %s (\n%s\n);\n",
8919 aggsig
, details
->data
);
8921 ArchiveEntry(fout
, agginfo
->aggfn
.dobj
.catId
, agginfo
->aggfn
.dobj
.dumpId
,
8923 agginfo
->aggfn
.dobj
.namespace->dobj
.name
,
8925 agginfo
->aggfn
.rolname
,
8926 false, "AGGREGATE", SECTION_PRE_DATA
,
8927 q
->data
, delq
->data
, NULL
,
8928 agginfo
->aggfn
.dobj
.dependencies
, agginfo
->aggfn
.dobj
.nDeps
,
8931 /* Dump Aggregate Comments */
8932 resetPQExpBuffer(q
);
8933 appendPQExpBuffer(q
, "AGGREGATE %s", aggsig
);
8934 dumpComment(fout
, q
->data
,
8935 agginfo
->aggfn
.dobj
.namespace->dobj
.name
, agginfo
->aggfn
.rolname
,
8936 agginfo
->aggfn
.dobj
.catId
, 0, agginfo
->aggfn
.dobj
.dumpId
);
8939 * Since there is no GRANT ON AGGREGATE syntax, we have to make the ACL
8940 * command look like a function's GRANT; in particular this affects the
8941 * syntax for zero-argument aggregates.
8946 aggsig
= format_function_signature(&agginfo
->aggfn
, true);
8947 aggsig_tag
= format_function_signature(&agginfo
->aggfn
, false);
8949 dumpACL(fout
, agginfo
->aggfn
.dobj
.catId
, agginfo
->aggfn
.dobj
.dumpId
,
8951 aggsig
, NULL
, aggsig_tag
,
8952 agginfo
->aggfn
.dobj
.namespace->dobj
.name
,
8953 agginfo
->aggfn
.rolname
, agginfo
->aggfn
.proacl
);
8960 destroyPQExpBuffer(query
);
8961 destroyPQExpBuffer(q
);
8962 destroyPQExpBuffer(delq
);
8963 destroyPQExpBuffer(details
);
8968 * write out a single text search parser
8971 dumpTSParser(Archive
*fout
, TSParserInfo
*prsinfo
)
8976 /* Skip if not to be dumped */
8977 if (!prsinfo
->dobj
.dump
|| dataOnly
)
8980 q
= createPQExpBuffer();
8981 delq
= createPQExpBuffer();
8983 /* Make sure we are in proper schema */
8984 selectSourceSchema(prsinfo
->dobj
.namespace->dobj
.name
);
8986 appendPQExpBuffer(q
, "CREATE TEXT SEARCH PARSER %s (\n",
8987 fmtId(prsinfo
->dobj
.name
));
8989 appendPQExpBuffer(q
, " START = %s,\n",
8990 convertTSFunction(prsinfo
->prsstart
));
8991 appendPQExpBuffer(q
, " GETTOKEN = %s,\n",
8992 convertTSFunction(prsinfo
->prstoken
));
8993 appendPQExpBuffer(q
, " END = %s,\n",
8994 convertTSFunction(prsinfo
->prsend
));
8995 if (prsinfo
->prsheadline
!= InvalidOid
)
8996 appendPQExpBuffer(q
, " HEADLINE = %s,\n",
8997 convertTSFunction(prsinfo
->prsheadline
));
8998 appendPQExpBuffer(q
, " LEXTYPES = %s );\n",
8999 convertTSFunction(prsinfo
->prslextype
));
9002 * DROP must be fully qualified in case same name appears in pg_catalog
9004 appendPQExpBuffer(delq
, "DROP TEXT SEARCH PARSER %s",
9005 fmtId(prsinfo
->dobj
.namespace->dobj
.name
));
9006 appendPQExpBuffer(delq
, ".%s;\n",
9007 fmtId(prsinfo
->dobj
.name
));
9009 ArchiveEntry(fout
, prsinfo
->dobj
.catId
, prsinfo
->dobj
.dumpId
,
9011 prsinfo
->dobj
.namespace->dobj
.name
,
9014 false, "TEXT SEARCH PARSER", SECTION_PRE_DATA
,
9015 q
->data
, delq
->data
, NULL
,
9016 prsinfo
->dobj
.dependencies
, prsinfo
->dobj
.nDeps
,
9019 /* Dump Parser Comments */
9020 resetPQExpBuffer(q
);
9021 appendPQExpBuffer(q
, "TEXT SEARCH PARSER %s",
9022 fmtId(prsinfo
->dobj
.name
));
9023 dumpComment(fout
, q
->data
,
9025 prsinfo
->dobj
.catId
, 0, prsinfo
->dobj
.dumpId
);
9027 destroyPQExpBuffer(q
);
9028 destroyPQExpBuffer(delq
);
9033 * write out a single text search dictionary
9036 dumpTSDictionary(Archive
*fout
, TSDictInfo
*dictinfo
)
9046 /* Skip if not to be dumped */
9047 if (!dictinfo
->dobj
.dump
|| dataOnly
)
9050 q
= createPQExpBuffer();
9051 delq
= createPQExpBuffer();
9052 query
= createPQExpBuffer();
9054 /* Fetch name and namespace of the dictionary's template */
9055 selectSourceSchema("pg_catalog");
9056 appendPQExpBuffer(query
, "SELECT nspname, tmplname "
9057 "FROM pg_ts_template p, pg_namespace n "
9058 "WHERE p.oid = '%u' AND n.oid = tmplnamespace",
9059 dictinfo
->dicttemplate
);
9060 res
= PQexec(g_conn
, query
->data
);
9061 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
9062 ntups
= PQntuples(res
);
9065 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
9066 "query returned %d rows instead of one: %s\n",
9068 ntups
, query
->data
);
9071 nspname
= PQgetvalue(res
, 0, 0);
9072 tmplname
= PQgetvalue(res
, 0, 1);
9074 /* Make sure we are in proper schema */
9075 selectSourceSchema(dictinfo
->dobj
.namespace->dobj
.name
);
9077 appendPQExpBuffer(q
, "CREATE TEXT SEARCH DICTIONARY %s (\n",
9078 fmtId(dictinfo
->dobj
.name
));
9080 appendPQExpBuffer(q
, " TEMPLATE = ");
9081 if (strcmp(nspname
, dictinfo
->dobj
.namespace->dobj
.name
) != 0)
9082 appendPQExpBuffer(q
, "%s.", fmtId(nspname
));
9083 appendPQExpBuffer(q
, "%s", fmtId(tmplname
));
9087 /* the dictinitoption can be dumped straight into the command */
9088 if (dictinfo
->dictinitoption
)
9089 appendPQExpBuffer(q
, ",\n %s", dictinfo
->dictinitoption
);
9091 appendPQExpBuffer(q
, " );\n");
9094 * DROP must be fully qualified in case same name appears in pg_catalog
9096 appendPQExpBuffer(delq
, "DROP TEXT SEARCH DICTIONARY %s",
9097 fmtId(dictinfo
->dobj
.namespace->dobj
.name
));
9098 appendPQExpBuffer(delq
, ".%s;\n",
9099 fmtId(dictinfo
->dobj
.name
));
9101 ArchiveEntry(fout
, dictinfo
->dobj
.catId
, dictinfo
->dobj
.dumpId
,
9102 dictinfo
->dobj
.name
,
9103 dictinfo
->dobj
.namespace->dobj
.name
,
9106 false, "TEXT SEARCH DICTIONARY", SECTION_PRE_DATA
,
9107 q
->data
, delq
->data
, NULL
,
9108 dictinfo
->dobj
.dependencies
, dictinfo
->dobj
.nDeps
,
9111 /* Dump Dictionary Comments */
9112 resetPQExpBuffer(q
);
9113 appendPQExpBuffer(q
, "TEXT SEARCH DICTIONARY %s",
9114 fmtId(dictinfo
->dobj
.name
));
9115 dumpComment(fout
, q
->data
,
9116 NULL
, dictinfo
->rolname
,
9117 dictinfo
->dobj
.catId
, 0, dictinfo
->dobj
.dumpId
);
9119 destroyPQExpBuffer(q
);
9120 destroyPQExpBuffer(delq
);
9121 destroyPQExpBuffer(query
);
9126 * write out a single text search template
9129 dumpTSTemplate(Archive
*fout
, TSTemplateInfo
*tmplinfo
)
9134 /* Skip if not to be dumped */
9135 if (!tmplinfo
->dobj
.dump
|| dataOnly
)
9138 q
= createPQExpBuffer();
9139 delq
= createPQExpBuffer();
9141 /* Make sure we are in proper schema */
9142 selectSourceSchema(tmplinfo
->dobj
.namespace->dobj
.name
);
9144 appendPQExpBuffer(q
, "CREATE TEXT SEARCH TEMPLATE %s (\n",
9145 fmtId(tmplinfo
->dobj
.name
));
9147 if (tmplinfo
->tmplinit
!= InvalidOid
)
9148 appendPQExpBuffer(q
, " INIT = %s,\n",
9149 convertTSFunction(tmplinfo
->tmplinit
));
9150 appendPQExpBuffer(q
, " LEXIZE = %s );\n",
9151 convertTSFunction(tmplinfo
->tmpllexize
));
9154 * DROP must be fully qualified in case same name appears in pg_catalog
9156 appendPQExpBuffer(delq
, "DROP TEXT SEARCH TEMPLATE %s",
9157 fmtId(tmplinfo
->dobj
.namespace->dobj
.name
));
9158 appendPQExpBuffer(delq
, ".%s;\n",
9159 fmtId(tmplinfo
->dobj
.name
));
9161 ArchiveEntry(fout
, tmplinfo
->dobj
.catId
, tmplinfo
->dobj
.dumpId
,
9162 tmplinfo
->dobj
.name
,
9163 tmplinfo
->dobj
.namespace->dobj
.name
,
9166 false, "TEXT SEARCH TEMPLATE", SECTION_PRE_DATA
,
9167 q
->data
, delq
->data
, NULL
,
9168 tmplinfo
->dobj
.dependencies
, tmplinfo
->dobj
.nDeps
,
9171 /* Dump Template Comments */
9172 resetPQExpBuffer(q
);
9173 appendPQExpBuffer(q
, "TEXT SEARCH TEMPLATE %s",
9174 fmtId(tmplinfo
->dobj
.name
));
9175 dumpComment(fout
, q
->data
,
9177 tmplinfo
->dobj
.catId
, 0, tmplinfo
->dobj
.dumpId
);
9179 destroyPQExpBuffer(q
);
9180 destroyPQExpBuffer(delq
);
9185 * write out a single text search configuration
9188 dumpTSConfig(Archive
*fout
, TSConfigInfo
*cfginfo
)
9201 /* Skip if not to be dumped */
9202 if (!cfginfo
->dobj
.dump
|| dataOnly
)
9205 q
= createPQExpBuffer();
9206 delq
= createPQExpBuffer();
9207 query
= createPQExpBuffer();
9209 /* Fetch name and namespace of the config's parser */
9210 selectSourceSchema("pg_catalog");
9211 appendPQExpBuffer(query
, "SELECT nspname, prsname "
9212 "FROM pg_ts_parser p, pg_namespace n "
9213 "WHERE p.oid = '%u' AND n.oid = prsnamespace",
9214 cfginfo
->cfgparser
);
9215 res
= PQexec(g_conn
, query
->data
);
9216 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
9217 ntups
= PQntuples(res
);
9220 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
9221 "query returned %d rows instead of one: %s\n",
9223 ntups
, query
->data
);
9226 nspname
= PQgetvalue(res
, 0, 0);
9227 prsname
= PQgetvalue(res
, 0, 1);
9229 /* Make sure we are in proper schema */
9230 selectSourceSchema(cfginfo
->dobj
.namespace->dobj
.name
);
9232 appendPQExpBuffer(q
, "CREATE TEXT SEARCH CONFIGURATION %s (\n",
9233 fmtId(cfginfo
->dobj
.name
));
9235 appendPQExpBuffer(q
, " PARSER = ");
9236 if (strcmp(nspname
, cfginfo
->dobj
.namespace->dobj
.name
) != 0)
9237 appendPQExpBuffer(q
, "%s.", fmtId(nspname
));
9238 appendPQExpBuffer(q
, "%s );\n", fmtId(prsname
));
9242 resetPQExpBuffer(query
);
9243 appendPQExpBuffer(query
,
9245 " ( SELECT alias FROM pg_catalog.ts_token_type('%u'::pg_catalog.oid) AS t \n"
9246 " WHERE t.tokid = m.maptokentype ) AS tokenname, \n"
9247 " m.mapdict::pg_catalog.regdictionary AS dictname \n"
9248 "FROM pg_catalog.pg_ts_config_map AS m \n"
9249 "WHERE m.mapcfg = '%u' \n"
9250 "ORDER BY m.mapcfg, m.maptokentype, m.mapseqno",
9251 cfginfo
->cfgparser
, cfginfo
->dobj
.catId
.oid
);
9253 res
= PQexec(g_conn
, query
->data
);
9254 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
9255 ntups
= PQntuples(res
);
9257 i_tokenname
= PQfnumber(res
, "tokenname");
9258 i_dictname
= PQfnumber(res
, "dictname");
9260 for (i
= 0; i
< ntups
; i
++)
9262 char *tokenname
= PQgetvalue(res
, i
, i_tokenname
);
9263 char *dictname
= PQgetvalue(res
, i
, i_dictname
);
9266 strcmp(tokenname
, PQgetvalue(res
, i
- 1, i_tokenname
)) != 0)
9268 /* starting a new token type, so start a new command */
9270 appendPQExpBuffer(q
, ";\n");
9271 appendPQExpBuffer(q
, "\nALTER TEXT SEARCH CONFIGURATION %s\n",
9272 fmtId(cfginfo
->dobj
.name
));
9273 /* tokenname needs quoting, dictname does NOT */
9274 appendPQExpBuffer(q
, " ADD MAPPING FOR %s WITH %s",
9275 fmtId(tokenname
), dictname
);
9278 appendPQExpBuffer(q
, ", %s", dictname
);
9282 appendPQExpBuffer(q
, ";\n");
9287 * DROP must be fully qualified in case same name appears in pg_catalog
9289 appendPQExpBuffer(delq
, "DROP TEXT SEARCH CONFIGURATION %s",
9290 fmtId(cfginfo
->dobj
.namespace->dobj
.name
));
9291 appendPQExpBuffer(delq
, ".%s;\n",
9292 fmtId(cfginfo
->dobj
.name
));
9294 ArchiveEntry(fout
, cfginfo
->dobj
.catId
, cfginfo
->dobj
.dumpId
,
9296 cfginfo
->dobj
.namespace->dobj
.name
,
9299 false, "TEXT SEARCH CONFIGURATION", SECTION_PRE_DATA
,
9300 q
->data
, delq
->data
, NULL
,
9301 cfginfo
->dobj
.dependencies
, cfginfo
->dobj
.nDeps
,
9304 /* Dump Configuration Comments */
9305 resetPQExpBuffer(q
);
9306 appendPQExpBuffer(q
, "TEXT SEARCH CONFIGURATION %s",
9307 fmtId(cfginfo
->dobj
.name
));
9308 dumpComment(fout
, q
->data
,
9309 NULL
, cfginfo
->rolname
,
9310 cfginfo
->dobj
.catId
, 0, cfginfo
->dobj
.dumpId
);
9312 destroyPQExpBuffer(q
);
9313 destroyPQExpBuffer(delq
);
9314 destroyPQExpBuffer(query
);
9318 * dumpForeignDataWrapper
9319 * write out a single foreign-data wrapper definition
9322 dumpForeignDataWrapper(Archive
*fout
, FdwInfo
*fdwinfo
)
9328 /* Skip if not to be dumped */
9329 if (!fdwinfo
->dobj
.dump
|| dataOnly
)
9332 q
= createPQExpBuffer();
9333 delq
= createPQExpBuffer();
9335 appendPQExpBuffer(q
, "CREATE FOREIGN DATA WRAPPER %s",
9336 fmtId(fdwinfo
->dobj
.name
));
9338 if (fdwinfo
->fdwvalidator
&& strcmp(fdwinfo
->fdwvalidator
, "-") != 0)
9339 appendPQExpBuffer(q
, " VALIDATOR %s",
9340 fdwinfo
->fdwvalidator
);
9342 if (fdwinfo
->fdwoptions
&& strlen(fdwinfo
->fdwoptions
) > 0)
9343 appendPQExpBuffer(q
, " OPTIONS (%s)", fdwinfo
->fdwoptions
);
9345 appendPQExpBuffer(q
, ";\n");
9347 appendPQExpBuffer(delq
, "DROP FOREIGN DATA WRAPPER %s;\n",
9348 fmtId(fdwinfo
->dobj
.name
));
9350 ArchiveEntry(fout
, fdwinfo
->dobj
.catId
, fdwinfo
->dobj
.dumpId
,
9355 false, "FOREIGN DATA WRAPPER", SECTION_PRE_DATA
,
9356 q
->data
, delq
->data
, NULL
,
9357 fdwinfo
->dobj
.dependencies
, fdwinfo
->dobj
.nDeps
,
9360 /* Handle the ACL */
9361 namecopy
= strdup(fmtId(fdwinfo
->dobj
.name
));
9362 dumpACL(fout
, fdwinfo
->dobj
.catId
, fdwinfo
->dobj
.dumpId
,
9363 "FOREIGN DATA WRAPPER",
9364 namecopy
, NULL
, fdwinfo
->dobj
.name
,
9365 NULL
, fdwinfo
->rolname
,
9369 destroyPQExpBuffer(q
);
9370 destroyPQExpBuffer(delq
);
9375 * write out a foreign server definition
9378 dumpForeignServer(Archive
*fout
, ForeignServerInfo
*srvinfo
)
9388 /* Skip if not to be dumped */
9389 if (!srvinfo
->dobj
.dump
|| dataOnly
)
9392 q
= createPQExpBuffer();
9393 delq
= createPQExpBuffer();
9394 query
= createPQExpBuffer();
9396 /* look up the foreign-data wrapper */
9397 appendPQExpBuffer(query
, "SELECT fdwname "
9398 "FROM pg_foreign_data_wrapper w "
9399 "WHERE w.oid = '%u'",
9401 res
= PQexec(g_conn
, query
->data
);
9402 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
9403 ntups
= PQntuples(res
);
9406 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
9407 "query returned %d rows instead of one: %s\n",
9409 ntups
, query
->data
);
9412 fdwname
= PQgetvalue(res
, 0, 0);
9414 appendPQExpBuffer(q
, "CREATE SERVER %s", fmtId(srvinfo
->dobj
.name
));
9415 if (srvinfo
->srvtype
&& strlen(srvinfo
->srvtype
) > 0)
9417 appendPQExpBuffer(q
, " TYPE ");
9418 appendStringLiteralAH(q
, srvinfo
->srvtype
, fout
);
9420 if (srvinfo
->srvversion
&& strlen(srvinfo
->srvversion
) > 0)
9422 appendPQExpBuffer(q
, " VERSION ");
9423 appendStringLiteralAH(q
, srvinfo
->srvversion
, fout
);
9426 appendPQExpBuffer(q
, " FOREIGN DATA WRAPPER ");
9427 appendPQExpBuffer(q
, "%s", fmtId(fdwname
));
9429 if (srvinfo
->srvoptions
&& strlen(srvinfo
->srvoptions
) > 0)
9430 appendPQExpBuffer(q
, " OPTIONS (%s)", srvinfo
->srvoptions
);
9432 appendPQExpBuffer(q
, ";\n");
9434 appendPQExpBuffer(delq
, "DROP SERVER %s;\n",
9435 fmtId(srvinfo
->dobj
.name
));
9437 ArchiveEntry(fout
, srvinfo
->dobj
.catId
, srvinfo
->dobj
.dumpId
,
9442 false, "SERVER", SECTION_PRE_DATA
,
9443 q
->data
, delq
->data
, NULL
,
9444 srvinfo
->dobj
.dependencies
, srvinfo
->dobj
.nDeps
,
9447 /* Handle the ACL */
9448 namecopy
= strdup(fmtId(srvinfo
->dobj
.name
));
9449 dumpACL(fout
, srvinfo
->dobj
.catId
, srvinfo
->dobj
.dumpId
,
9451 namecopy
, NULL
, srvinfo
->dobj
.name
,
9452 NULL
, srvinfo
->rolname
,
9456 /* Dump user mappings */
9457 resetPQExpBuffer(q
);
9458 appendPQExpBuffer(q
, "SERVER %s", fmtId(srvinfo
->dobj
.name
));
9459 dumpUserMappings(fout
, q
->data
,
9460 srvinfo
->dobj
.name
, NULL
,
9462 srvinfo
->dobj
.catId
, srvinfo
->dobj
.dumpId
);
9464 destroyPQExpBuffer(q
);
9465 destroyPQExpBuffer(delq
);
9471 * This routine is used to dump any user mappings associated with the
9472 * server handed to this routine. Should be called after ArchiveEntry()
9476 dumpUserMappings(Archive
*fout
, const char *target
,
9477 const char *servername
, const char *namespace,
9479 CatalogId catalogId
, DumpId dumpId
)
9491 q
= createPQExpBuffer();
9492 tag
= createPQExpBuffer();
9493 delq
= createPQExpBuffer();
9494 query
= createPQExpBuffer();
9496 appendPQExpBuffer(query
,
9497 "SELECT (%s umuser) AS umuser, "
9498 "array_to_string(ARRAY(SELECT option_name || ' ' || quote_literal(option_value) FROM pg_options_to_table(umoptions)), ', ') AS umoptions\n"
9499 "FROM pg_user_mapping "
9500 "WHERE umserver=%u",
9504 res
= PQexec(g_conn
, query
->data
);
9505 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
9507 ntups
= PQntuples(res
);
9508 i_umuser
= PQfnumber(res
, "umuser");
9509 i_umoptions
= PQfnumber(res
, "umoptions");
9511 for (i
= 0; i
< ntups
; i
++)
9516 umuser
= PQgetvalue(res
, i
, i_umuser
);
9517 umoptions
= PQgetvalue(res
, i
, i_umoptions
);
9519 resetPQExpBuffer(q
);
9520 appendPQExpBuffer(q
, "CREATE USER MAPPING FOR %s", fmtId(umuser
));
9521 appendPQExpBuffer(q
, " SERVER %s", fmtId(servername
));
9523 if (umoptions
&& strlen(umoptions
) > 0)
9524 appendPQExpBuffer(q
, " OPTIONS (%s)", umoptions
);
9526 appendPQExpBuffer(q
, ";\n");
9528 resetPQExpBuffer(delq
);
9529 appendPQExpBuffer(delq
, "DROP USER MAPPING FOR %s SERVER %s;\n", fmtId(umuser
), fmtId(servername
));
9531 resetPQExpBuffer(tag
);
9532 appendPQExpBuffer(tag
, "USER MAPPING %s %s", fmtId(umuser
), target
);
9534 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
9539 "USER MAPPING", SECTION_PRE_DATA
,
9540 q
->data
, delq
->data
, NULL
,
9547 destroyPQExpBuffer(query
);
9548 destroyPQExpBuffer(delq
);
9549 destroyPQExpBuffer(q
);
9553 * Write out grant/revoke information
9555 * 'objCatId' is the catalog ID of the underlying object.
9556 * 'objDumpId' is the dump ID of the underlying object.
9557 * 'type' must be TABLE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, or TABLESPACE.
9558 * 'name' is the formatted name of the object. Must be quoted etc. already.
9559 * 'subname' is the formatted name of the sub-object, if any. Must be quoted.
9560 * 'tag' is the tag for the archive entry (typ. unquoted name of object).
9561 * 'nspname' is the namespace the object is in (NULL if none).
9562 * 'owner' is the owner, NULL if there is no owner (for languages).
9563 * 'acls' is the string read out of the fooacl system catalog field;
9564 * it will be parsed here.
9568 dumpACL(Archive
*fout
, CatalogId objCatId
, DumpId objDumpId
,
9569 const char *type
, const char *name
, const char *subname
,
9570 const char *tag
, const char *nspname
, const char *owner
,
9575 /* Do nothing if ACL dump is not enabled */
9576 if (dataOnly
|| aclsSkip
)
9579 sql
= createPQExpBuffer();
9581 if (!buildACLCommands(name
, subname
, type
, acls
, owner
, fout
->remoteVersion
, sql
))
9583 write_msg(NULL
, "could not parse ACL list (%s) for object \"%s\" (%s)\n",
9589 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
9593 false, "ACL", SECTION_NONE
,
9594 sql
->data
, "", NULL
,
9598 destroyPQExpBuffer(sql
);
9603 * write out to fout the declarations (not data) of a user-defined table
9606 dumpTable(Archive
*fout
, TableInfo
*tbinfo
)
9608 if (tbinfo
->dobj
.dump
)
9612 if (tbinfo
->relkind
== RELKIND_SEQUENCE
)
9613 dumpSequence(fout
, tbinfo
);
9615 dumpTableSchema(fout
, tbinfo
);
9617 /* Handle the ACL here */
9618 namecopy
= strdup(fmtId(tbinfo
->dobj
.name
));
9619 dumpACL(fout
, tbinfo
->dobj
.catId
, tbinfo
->dobj
.dumpId
,
9620 (tbinfo
->relkind
== RELKIND_SEQUENCE
) ? "SEQUENCE" : "TABLE",
9621 namecopy
, NULL
, tbinfo
->dobj
.name
,
9622 tbinfo
->dobj
.namespace->dobj
.name
, tbinfo
->rolname
,
9626 * Handle column ACLs, if any. Note: we pull these with a separate
9627 * query rather than trying to fetch them during getTableAttrs, so
9628 * that we won't miss ACLs on system columns.
9630 if (g_fout
->remoteVersion
>= 80400)
9632 PQExpBuffer query
= createPQExpBuffer();
9636 appendPQExpBuffer(query
,
9637 "SELECT attname, attacl FROM pg_catalog.pg_attribute "
9638 "WHERE attrelid = '%u' AND NOT attisdropped AND attacl IS NOT NULL "
9640 tbinfo
->dobj
.catId
.oid
);
9641 res
= PQexec(g_conn
, query
->data
);
9642 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
9644 for (i
= 0; i
< PQntuples(res
); i
++)
9646 char *attname
= PQgetvalue(res
, i
, 0);
9647 char *attacl
= PQgetvalue(res
, i
, 1);
9651 attnamecopy
= strdup(fmtId(attname
));
9652 acltag
= malloc(strlen(tbinfo
->dobj
.name
) + strlen(attname
) + 2);
9653 sprintf(acltag
, "%s.%s", tbinfo
->dobj
.name
, attname
);
9654 /* Column's GRANT type is always TABLE */
9655 dumpACL(fout
, tbinfo
->dobj
.catId
, tbinfo
->dobj
.dumpId
, "TABLE",
9656 namecopy
, attnamecopy
, acltag
,
9657 tbinfo
->dobj
.namespace->dobj
.name
, tbinfo
->rolname
,
9663 destroyPQExpBuffer(query
);
9672 * write the declaration (not data) of one user-defined table or view
9675 dumpTableSchema(Archive
*fout
, TableInfo
*tbinfo
)
9677 PQExpBuffer query
= createPQExpBuffer();
9678 PQExpBuffer q
= createPQExpBuffer();
9679 PQExpBuffer delq
= createPQExpBuffer();
9682 TableInfo
**parents
;
9683 int actual_atts
; /* number of attrs in this CREATE statment */
9689 /* Make sure we are in proper schema */
9690 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
9692 /* Is it a table or a view? */
9693 if (tbinfo
->relkind
== RELKIND_VIEW
)
9697 reltypename
= "VIEW";
9699 /* Fetch the view definition */
9700 if (g_fout
->remoteVersion
>= 70300)
9702 /* Beginning in 7.3, viewname is not unique; rely on OID */
9703 appendPQExpBuffer(query
,
9704 "SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) AS viewdef",
9705 tbinfo
->dobj
.catId
.oid
);
9709 appendPQExpBuffer(query
, "SELECT definition AS viewdef "
9710 "FROM pg_views WHERE viewname = ");
9711 appendStringLiteralAH(query
, tbinfo
->dobj
.name
, fout
);
9712 appendPQExpBuffer(query
, ";");
9715 res
= PQexec(g_conn
, query
->data
);
9716 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
9718 if (PQntuples(res
) != 1)
9720 if (PQntuples(res
) < 1)
9721 write_msg(NULL
, "query to obtain definition of view \"%s\" returned no data\n",
9724 write_msg(NULL
, "query to obtain definition of view \"%s\" returned more than one definition\n",
9729 viewdef
= PQgetvalue(res
, 0, 0);
9731 if (strlen(viewdef
) == 0)
9733 write_msg(NULL
, "definition of view \"%s\" appears to be empty (length zero)\n",
9739 * DROP must be fully qualified in case same name appears in
9742 appendPQExpBuffer(delq
, "DROP VIEW %s.",
9743 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9744 appendPQExpBuffer(delq
, "%s;\n",
9745 fmtId(tbinfo
->dobj
.name
));
9747 appendPQExpBuffer(q
, "CREATE VIEW %s AS\n %s\n",
9748 fmtId(tbinfo
->dobj
.name
), viewdef
);
9754 reltypename
= "TABLE";
9755 numParents
= tbinfo
->numParents
;
9756 parents
= tbinfo
->parents
;
9759 * DROP must be fully qualified in case same name appears in
9762 appendPQExpBuffer(delq
, "DROP TABLE %s.",
9763 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
9764 appendPQExpBuffer(delq
, "%s;\n",
9765 fmtId(tbinfo
->dobj
.name
));
9767 appendPQExpBuffer(q
, "CREATE TABLE %s (",
9768 fmtId(tbinfo
->dobj
.name
));
9770 for (j
= 0; j
< tbinfo
->numatts
; j
++)
9773 * Normally, dump if it's one of the table's own attrs, and not
9774 * dropped. But for binary upgrade, dump all the columns.
9776 if ((!tbinfo
->inhAttrs
[j
] && !tbinfo
->attisdropped
[j
]) ||
9779 /* Format properly if not first attr */
9780 if (actual_atts
> 0)
9781 appendPQExpBuffer(q
, ",");
9782 appendPQExpBuffer(q
, "\n ");
9785 /* Attribute name */
9786 appendPQExpBuffer(q
, "%s ",
9787 fmtId(tbinfo
->attnames
[j
]));
9789 if (tbinfo
->attisdropped
[j
])
9792 * ALTER TABLE DROP COLUMN clears pg_attribute.atttypid,
9793 * so we will not have gotten a valid type name; insert
9794 * INTEGER as a stopgap. We'll clean things up later.
9796 appendPQExpBuffer(q
, "INTEGER /* dummy */");
9797 /* Skip all the rest, too */
9801 /* Attribute type */
9802 if (g_fout
->remoteVersion
>= 70100)
9804 appendPQExpBuffer(q
, "%s",
9805 tbinfo
->atttypnames
[j
]);
9809 /* If no format_type, fake it */
9810 appendPQExpBuffer(q
, "%s",
9811 myFormatType(tbinfo
->atttypnames
[j
],
9812 tbinfo
->atttypmod
[j
]));
9816 * Default value --- suppress if inherited (except in
9817 * binary-upgrade case, where we're not doing normal
9818 * inheritance) or if it's to be printed separately.
9820 if (tbinfo
->attrdefs
[j
] != NULL
&&
9821 (!tbinfo
->inhAttrDef
[j
] || binary_upgrade
) &&
9822 !tbinfo
->attrdefs
[j
]->separate
)
9823 appendPQExpBuffer(q
, " DEFAULT %s",
9824 tbinfo
->attrdefs
[j
]->adef_expr
);
9827 * Not Null constraint --- suppress if inherited, except
9828 * in binary-upgrade case.
9830 if (tbinfo
->notnull
[j
] &&
9831 (!tbinfo
->inhNotNull
[j
] || binary_upgrade
))
9832 appendPQExpBuffer(q
, " NOT NULL");
9837 * Add non-inherited CHECK constraints, if any.
9839 for (j
= 0; j
< tbinfo
->ncheck
; j
++)
9841 ConstraintInfo
*constr
= &(tbinfo
->checkexprs
[j
]);
9843 if (constr
->separate
|| !constr
->conislocal
)
9846 if (actual_atts
> 0)
9847 appendPQExpBuffer(q
, ",\n ");
9849 appendPQExpBuffer(q
, "CONSTRAINT %s ",
9850 fmtId(constr
->dobj
.name
));
9851 appendPQExpBuffer(q
, "%s", constr
->condef
);
9856 appendPQExpBuffer(q
, "\n)");
9858 if (numParents
> 0 && !binary_upgrade
)
9860 appendPQExpBuffer(q
, "\nINHERITS (");
9861 for (k
= 0; k
< numParents
; k
++)
9863 TableInfo
*parentRel
= parents
[k
];
9866 appendPQExpBuffer(q
, ", ");
9867 if (parentRel
->dobj
.namespace != tbinfo
->dobj
.namespace)
9868 appendPQExpBuffer(q
, "%s.",
9869 fmtId(parentRel
->dobj
.namespace->dobj
.name
));
9870 appendPQExpBuffer(q
, "%s",
9871 fmtId(parentRel
->dobj
.name
));
9873 appendPQExpBuffer(q
, ")");
9876 if ((tbinfo
->reloptions
&& strlen(tbinfo
->reloptions
) > 0) ||
9877 (tbinfo
->toast_reloptions
&& strlen(tbinfo
->toast_reloptions
) > 0))
9879 bool addcomma
= false;
9881 appendPQExpBuffer(q
, "\nWITH (");
9882 if (tbinfo
->reloptions
&& strlen(tbinfo
->reloptions
) > 0)
9885 appendPQExpBuffer(q
, "%s", tbinfo
->reloptions
);
9887 if (tbinfo
->toast_reloptions
&& strlen(tbinfo
->toast_reloptions
) > 0)
9889 appendPQExpBuffer(q
, "%s%s", addcomma
? ", " : "",
9890 tbinfo
->toast_reloptions
);
9892 appendPQExpBuffer(q
, ")");
9895 appendPQExpBuffer(q
, ";\n");
9898 * To create binary-compatible heap files, we have to ensure the
9899 * same physical column order, including dropped columns, as in the
9900 * original. Therefore, we create dropped columns above and drop
9901 * them here, also updating their attlen/attalign values so that
9902 * the dropped column can be skipped properly. (We do not bother
9903 * with restoring the original attbyval setting.) Also, inheritance
9904 * relationships are set up by doing ALTER INHERIT rather than using
9905 * an INHERITS clause --- the latter would possibly mess up the
9906 * column order. That also means we have to take care about setting
9907 * attislocal correctly, plus fix up any inherited CHECK constraints.
9911 for (j
= 0; j
< tbinfo
->numatts
; j
++)
9913 if (tbinfo
->attisdropped
[j
])
9915 appendPQExpBuffer(q
, "\n-- For binary upgrade, recreate dropped column.\n");
9916 appendPQExpBuffer(q
, "UPDATE pg_catalog.pg_attribute\n"
9918 "attalign = '%c', attbyval = false\n"
9921 tbinfo
->attalign
[j
]);
9922 appendStringLiteralAH(q
, tbinfo
->attnames
[j
], fout
);
9923 appendPQExpBuffer(q
, "\n AND attrelid = ");
9924 appendStringLiteralAH(q
, fmtId(tbinfo
->dobj
.name
), fout
);
9925 appendPQExpBuffer(q
, "::pg_catalog.regclass;\n");
9927 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s ",
9928 fmtId(tbinfo
->dobj
.name
));
9929 appendPQExpBuffer(q
, "DROP COLUMN %s;\n",
9930 fmtId(tbinfo
->attnames
[j
]));
9932 else if (!tbinfo
->attislocal
[j
])
9934 appendPQExpBuffer(q
, "\n-- For binary upgrade, recreate inherited column.\n");
9935 appendPQExpBuffer(q
, "UPDATE pg_catalog.pg_attribute\n"
9936 "SET attislocal = false\n"
9937 "WHERE attname = ");
9938 appendStringLiteralAH(q
, tbinfo
->attnames
[j
], fout
);
9939 appendPQExpBuffer(q
, "\n AND attrelid = ");
9940 appendStringLiteralAH(q
, fmtId(tbinfo
->dobj
.name
), fout
);
9941 appendPQExpBuffer(q
, "::pg_catalog.regclass;\n");
9945 for (k
= 0; k
< tbinfo
->ncheck
; k
++)
9947 ConstraintInfo
*constr
= &(tbinfo
->checkexprs
[k
]);
9949 if (constr
->separate
|| constr
->conislocal
)
9952 appendPQExpBuffer(q
, "\n-- For binary upgrade, set up inherited constraint.\n");
9953 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s ",
9954 fmtId(tbinfo
->dobj
.name
));
9955 appendPQExpBuffer(q
, " ADD CONSTRAINT %s ",
9956 fmtId(constr
->dobj
.name
));
9957 appendPQExpBuffer(q
, "%s;\n", constr
->condef
);
9958 appendPQExpBuffer(q
, "UPDATE pg_catalog.pg_constraint\n"
9959 "SET conislocal = false\n"
9960 "WHERE contype = 'c' AND conname = ");
9961 appendStringLiteralAH(q
, constr
->dobj
.name
, fout
);
9962 appendPQExpBuffer(q
, "\n AND conrelid = ");
9963 appendStringLiteralAH(q
, fmtId(tbinfo
->dobj
.name
), fout
);
9964 appendPQExpBuffer(q
, "::pg_catalog.regclass;\n");
9969 appendPQExpBuffer(q
, "\n-- For binary upgrade, set up inheritance this way.\n");
9970 for (k
= 0; k
< numParents
; k
++)
9972 TableInfo
*parentRel
= parents
[k
];
9974 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s INHERIT ",
9975 fmtId(tbinfo
->dobj
.name
));
9976 if (parentRel
->dobj
.namespace != tbinfo
->dobj
.namespace)
9977 appendPQExpBuffer(q
, "%s.",
9978 fmtId(parentRel
->dobj
.namespace->dobj
.name
));
9979 appendPQExpBuffer(q
, "%s;\n",
9980 fmtId(parentRel
->dobj
.name
));
9984 appendPQExpBuffer(q
, "\n-- For binary upgrade, set relfrozenxid.\n");
9985 appendPQExpBuffer(q
, "UPDATE pg_catalog.pg_class\n"
9986 "SET relfrozenxid = '%u'\n"
9989 appendStringLiteralAH(q
, fmtId(tbinfo
->dobj
.name
), fout
);
9990 appendPQExpBuffer(q
, "::pg_catalog.regclass;\n");
9993 /* Loop dumping statistics and storage statements */
9994 for (j
= 0; j
< tbinfo
->numatts
; j
++)
9997 * Dump per-column statistics information. We only issue an ALTER
9998 * TABLE statement if the attstattarget entry for this column is
9999 * non-negative (i.e. it's not the default value)
10001 if (tbinfo
->attstattarget
[j
] >= 0 &&
10002 !tbinfo
->attisdropped
[j
])
10004 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s ",
10005 fmtId(tbinfo
->dobj
.name
));
10006 appendPQExpBuffer(q
, "ALTER COLUMN %s ",
10007 fmtId(tbinfo
->attnames
[j
]));
10008 appendPQExpBuffer(q
, "SET STATISTICS %d;\n",
10009 tbinfo
->attstattarget
[j
]);
10013 * Dump per-column storage information. The statement is only
10014 * dumped if the storage has been changed from the type's default.
10016 if (!tbinfo
->attisdropped
[j
] && tbinfo
->attstorage
[j
] != tbinfo
->typstorage
[j
])
10018 switch (tbinfo
->attstorage
[j
])
10024 storage
= "EXTERNAL";
10030 storage
= "EXTENDED";
10037 * Only dump the statement if it's a storage type we recognize
10039 if (storage
!= NULL
)
10041 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s ",
10042 fmtId(tbinfo
->dobj
.name
));
10043 appendPQExpBuffer(q
, "ALTER COLUMN %s ",
10044 fmtId(tbinfo
->attnames
[j
]));
10045 appendPQExpBuffer(q
, "SET STORAGE %s;\n",
10052 ArchiveEntry(fout
, tbinfo
->dobj
.catId
, tbinfo
->dobj
.dumpId
,
10054 tbinfo
->dobj
.namespace->dobj
.name
,
10055 (tbinfo
->relkind
== RELKIND_VIEW
) ? NULL
: tbinfo
->reltablespace
,
10057 (strcmp(reltypename
, "TABLE") == 0) ? tbinfo
->hasoids
: false,
10058 reltypename
, SECTION_PRE_DATA
,
10059 q
->data
, delq
->data
, NULL
,
10060 tbinfo
->dobj
.dependencies
, tbinfo
->dobj
.nDeps
,
10063 /* Dump Table Comments */
10064 dumpTableComment(fout
, tbinfo
, reltypename
);
10066 /* Dump comments on inlined table constraints */
10067 for (j
= 0; j
< tbinfo
->ncheck
; j
++)
10069 ConstraintInfo
*constr
= &(tbinfo
->checkexprs
[j
]);
10071 if (constr
->separate
|| !constr
->conislocal
)
10074 dumpTableConstraintComment(fout
, constr
);
10077 destroyPQExpBuffer(query
);
10078 destroyPQExpBuffer(q
);
10079 destroyPQExpBuffer(delq
);
10083 * dumpAttrDef --- dump an attribute's default-value declaration
10086 dumpAttrDef(Archive
*fout
, AttrDefInfo
*adinfo
)
10088 TableInfo
*tbinfo
= adinfo
->adtable
;
10089 int adnum
= adinfo
->adnum
;
10093 /* Only print it if "separate" mode is selected */
10094 if (!tbinfo
->dobj
.dump
|| !adinfo
->separate
|| dataOnly
)
10097 /* Don't print inherited defaults, either, except for binary upgrade */
10098 if (tbinfo
->inhAttrDef
[adnum
- 1] && !binary_upgrade
)
10101 q
= createPQExpBuffer();
10102 delq
= createPQExpBuffer();
10104 appendPQExpBuffer(q
, "ALTER TABLE %s ",
10105 fmtId(tbinfo
->dobj
.name
));
10106 appendPQExpBuffer(q
, "ALTER COLUMN %s SET DEFAULT %s;\n",
10107 fmtId(tbinfo
->attnames
[adnum
- 1]),
10108 adinfo
->adef_expr
);
10111 * DROP must be fully qualified in case same name appears in pg_catalog
10113 appendPQExpBuffer(delq
, "ALTER TABLE %s.",
10114 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
10115 appendPQExpBuffer(delq
, "%s ",
10116 fmtId(tbinfo
->dobj
.name
));
10117 appendPQExpBuffer(delq
, "ALTER COLUMN %s DROP DEFAULT;\n",
10118 fmtId(tbinfo
->attnames
[adnum
- 1]));
10120 ArchiveEntry(fout
, adinfo
->dobj
.catId
, adinfo
->dobj
.dumpId
,
10121 tbinfo
->attnames
[adnum
- 1],
10122 tbinfo
->dobj
.namespace->dobj
.name
,
10125 false, "DEFAULT", SECTION_PRE_DATA
,
10126 q
->data
, delq
->data
, NULL
,
10127 adinfo
->dobj
.dependencies
, adinfo
->dobj
.nDeps
,
10130 destroyPQExpBuffer(q
);
10131 destroyPQExpBuffer(delq
);
10135 * getAttrName: extract the correct name for an attribute
10137 * The array tblInfo->attnames[] only provides names of user attributes;
10138 * if a system attribute number is supplied, we have to fake it.
10139 * We also do a little bit of bounds checking for safety's sake.
10141 static const char *
10142 getAttrName(int attrnum
, TableInfo
*tblInfo
)
10144 if (attrnum
> 0 && attrnum
<= tblInfo
->numatts
)
10145 return tblInfo
->attnames
[attrnum
- 1];
10148 case SelfItemPointerAttributeNumber
:
10150 case ObjectIdAttributeNumber
:
10152 case MinTransactionIdAttributeNumber
:
10154 case MinCommandIdAttributeNumber
:
10156 case MaxTransactionIdAttributeNumber
:
10158 case MaxCommandIdAttributeNumber
:
10160 case TableOidAttributeNumber
:
10163 write_msg(NULL
, "invalid column number %d for table \"%s\"\n",
10164 attrnum
, tblInfo
->dobj
.name
);
10166 return NULL
; /* keep compiler quiet */
10171 * write out to fout a user-defined index
10174 dumpIndex(Archive
*fout
, IndxInfo
*indxinfo
)
10176 TableInfo
*tbinfo
= indxinfo
->indextable
;
10183 q
= createPQExpBuffer();
10184 delq
= createPQExpBuffer();
10187 * If there's an associated constraint, don't dump the index per se, but
10188 * do dump any comment for it. (This is safe because dependency ordering
10189 * will have ensured the constraint is emitted first.)
10191 if (indxinfo
->indexconstraint
== 0)
10193 /* Plain secondary index */
10194 appendPQExpBuffer(q
, "%s;\n", indxinfo
->indexdef
);
10196 /* If the index is clustered, we need to record that. */
10197 if (indxinfo
->indisclustered
)
10199 appendPQExpBuffer(q
, "\nALTER TABLE %s CLUSTER",
10200 fmtId(tbinfo
->dobj
.name
));
10201 appendPQExpBuffer(q
, " ON %s;\n",
10202 fmtId(indxinfo
->dobj
.name
));
10206 * DROP must be fully qualified in case same name appears in
10209 appendPQExpBuffer(delq
, "DROP INDEX %s.",
10210 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
10211 appendPQExpBuffer(delq
, "%s;\n",
10212 fmtId(indxinfo
->dobj
.name
));
10214 ArchiveEntry(fout
, indxinfo
->dobj
.catId
, indxinfo
->dobj
.dumpId
,
10215 indxinfo
->dobj
.name
,
10216 tbinfo
->dobj
.namespace->dobj
.name
,
10217 indxinfo
->tablespace
,
10218 tbinfo
->rolname
, false,
10219 "INDEX", SECTION_POST_DATA
,
10220 q
->data
, delq
->data
, NULL
,
10221 indxinfo
->dobj
.dependencies
, indxinfo
->dobj
.nDeps
,
10225 /* Dump Index Comments */
10226 resetPQExpBuffer(q
);
10227 appendPQExpBuffer(q
, "INDEX %s",
10228 fmtId(indxinfo
->dobj
.name
));
10229 dumpComment(fout
, q
->data
,
10230 tbinfo
->dobj
.namespace->dobj
.name
,
10232 indxinfo
->dobj
.catId
, 0, indxinfo
->dobj
.dumpId
);
10234 destroyPQExpBuffer(q
);
10235 destroyPQExpBuffer(delq
);
10240 * write out to fout a user-defined constraint
10243 dumpConstraint(Archive
*fout
, ConstraintInfo
*coninfo
)
10245 TableInfo
*tbinfo
= coninfo
->contable
;
10249 /* Skip if not to be dumped */
10250 if (!coninfo
->dobj
.dump
|| dataOnly
)
10253 q
= createPQExpBuffer();
10254 delq
= createPQExpBuffer();
10256 if (coninfo
->contype
== 'p' || coninfo
->contype
== 'u')
10258 /* Index-related constraint */
10259 IndxInfo
*indxinfo
;
10262 indxinfo
= (IndxInfo
*) findObjectByDumpId(coninfo
->conindex
);
10264 if (indxinfo
== NULL
)
10266 write_msg(NULL
, "missing index for constraint \"%s\"\n",
10267 coninfo
->dobj
.name
);
10271 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s\n",
10272 fmtId(tbinfo
->dobj
.name
));
10273 appendPQExpBuffer(q
, " ADD CONSTRAINT %s %s (",
10274 fmtId(coninfo
->dobj
.name
),
10275 coninfo
->contype
== 'p' ? "PRIMARY KEY" : "UNIQUE");
10277 for (k
= 0; k
< indxinfo
->indnkeys
; k
++)
10279 int indkey
= (int) indxinfo
->indkeys
[k
];
10280 const char *attname
;
10282 if (indkey
== InvalidAttrNumber
)
10284 attname
= getAttrName(indkey
, tbinfo
);
10286 appendPQExpBuffer(q
, "%s%s",
10287 (k
== 0) ? "" : ", ",
10291 appendPQExpBuffer(q
, ")");
10293 if (indxinfo
->options
&& strlen(indxinfo
->options
) > 0)
10294 appendPQExpBuffer(q
, " WITH (%s)", indxinfo
->options
);
10296 appendPQExpBuffer(q
, ";\n");
10298 /* If the index is clustered, we need to record that. */
10299 if (indxinfo
->indisclustered
)
10301 appendPQExpBuffer(q
, "\nALTER TABLE %s CLUSTER",
10302 fmtId(tbinfo
->dobj
.name
));
10303 appendPQExpBuffer(q
, " ON %s;\n",
10304 fmtId(indxinfo
->dobj
.name
));
10308 * DROP must be fully qualified in case same name appears in
10311 appendPQExpBuffer(delq
, "ALTER TABLE ONLY %s.",
10312 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
10313 appendPQExpBuffer(delq
, "%s ",
10314 fmtId(tbinfo
->dobj
.name
));
10315 appendPQExpBuffer(delq
, "DROP CONSTRAINT %s;\n",
10316 fmtId(coninfo
->dobj
.name
));
10318 ArchiveEntry(fout
, coninfo
->dobj
.catId
, coninfo
->dobj
.dumpId
,
10319 coninfo
->dobj
.name
,
10320 tbinfo
->dobj
.namespace->dobj
.name
,
10321 indxinfo
->tablespace
,
10322 tbinfo
->rolname
, false,
10323 "CONSTRAINT", SECTION_POST_DATA
,
10324 q
->data
, delq
->data
, NULL
,
10325 coninfo
->dobj
.dependencies
, coninfo
->dobj
.nDeps
,
10328 else if (coninfo
->contype
== 'f')
10331 * XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that the
10332 * current table data is not processed
10334 appendPQExpBuffer(q
, "ALTER TABLE ONLY %s\n",
10335 fmtId(tbinfo
->dobj
.name
));
10336 appendPQExpBuffer(q
, " ADD CONSTRAINT %s %s;\n",
10337 fmtId(coninfo
->dobj
.name
),
10341 * DROP must be fully qualified in case same name appears in
10344 appendPQExpBuffer(delq
, "ALTER TABLE ONLY %s.",
10345 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
10346 appendPQExpBuffer(delq
, "%s ",
10347 fmtId(tbinfo
->dobj
.name
));
10348 appendPQExpBuffer(delq
, "DROP CONSTRAINT %s;\n",
10349 fmtId(coninfo
->dobj
.name
));
10351 ArchiveEntry(fout
, coninfo
->dobj
.catId
, coninfo
->dobj
.dumpId
,
10352 coninfo
->dobj
.name
,
10353 tbinfo
->dobj
.namespace->dobj
.name
,
10355 tbinfo
->rolname
, false,
10356 "FK CONSTRAINT", SECTION_POST_DATA
,
10357 q
->data
, delq
->data
, NULL
,
10358 coninfo
->dobj
.dependencies
, coninfo
->dobj
.nDeps
,
10361 else if (coninfo
->contype
== 'c' && tbinfo
)
10363 /* CHECK constraint on a table */
10365 /* Ignore if not to be dumped separately */
10366 if (coninfo
->separate
)
10368 /* not ONLY since we want it to propagate to children */
10369 appendPQExpBuffer(q
, "ALTER TABLE %s\n",
10370 fmtId(tbinfo
->dobj
.name
));
10371 appendPQExpBuffer(q
, " ADD CONSTRAINT %s %s;\n",
10372 fmtId(coninfo
->dobj
.name
),
10376 * DROP must be fully qualified in case same name appears in
10379 appendPQExpBuffer(delq
, "ALTER TABLE %s.",
10380 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
10381 appendPQExpBuffer(delq
, "%s ",
10382 fmtId(tbinfo
->dobj
.name
));
10383 appendPQExpBuffer(delq
, "DROP CONSTRAINT %s;\n",
10384 fmtId(coninfo
->dobj
.name
));
10386 ArchiveEntry(fout
, coninfo
->dobj
.catId
, coninfo
->dobj
.dumpId
,
10387 coninfo
->dobj
.name
,
10388 tbinfo
->dobj
.namespace->dobj
.name
,
10390 tbinfo
->rolname
, false,
10391 "CHECK CONSTRAINT", SECTION_POST_DATA
,
10392 q
->data
, delq
->data
, NULL
,
10393 coninfo
->dobj
.dependencies
, coninfo
->dobj
.nDeps
,
10397 else if (coninfo
->contype
== 'c' && tbinfo
== NULL
)
10399 /* CHECK constraint on a domain */
10400 TypeInfo
*tinfo
= coninfo
->condomain
;
10402 /* Ignore if not to be dumped separately */
10403 if (coninfo
->separate
)
10405 appendPQExpBuffer(q
, "ALTER DOMAIN %s\n",
10406 fmtId(tinfo
->dobj
.name
));
10407 appendPQExpBuffer(q
, " ADD CONSTRAINT %s %s;\n",
10408 fmtId(coninfo
->dobj
.name
),
10412 * DROP must be fully qualified in case same name appears in
10415 appendPQExpBuffer(delq
, "ALTER DOMAIN %s.",
10416 fmtId(tinfo
->dobj
.namespace->dobj
.name
));
10417 appendPQExpBuffer(delq
, "%s ",
10418 fmtId(tinfo
->dobj
.name
));
10419 appendPQExpBuffer(delq
, "DROP CONSTRAINT %s;\n",
10420 fmtId(coninfo
->dobj
.name
));
10422 ArchiveEntry(fout
, coninfo
->dobj
.catId
, coninfo
->dobj
.dumpId
,
10423 coninfo
->dobj
.name
,
10424 tinfo
->dobj
.namespace->dobj
.name
,
10426 tinfo
->rolname
, false,
10427 "CHECK CONSTRAINT", SECTION_POST_DATA
,
10428 q
->data
, delq
->data
, NULL
,
10429 coninfo
->dobj
.dependencies
, coninfo
->dobj
.nDeps
,
10435 write_msg(NULL
, "unrecognized constraint type: %c\n", coninfo
->contype
);
10439 /* Dump Constraint Comments --- only works for table constraints */
10440 if (tbinfo
&& coninfo
->separate
)
10441 dumpTableConstraintComment(fout
, coninfo
);
10443 destroyPQExpBuffer(q
);
10444 destroyPQExpBuffer(delq
);
10448 * dumpTableConstraintComment --- dump a constraint's comment if any
10450 * This is split out because we need the function in two different places
10451 * depending on whether the constraint is dumped as part of CREATE TABLE
10452 * or as a separate ALTER command.
10455 dumpTableConstraintComment(Archive
*fout
, ConstraintInfo
*coninfo
)
10457 TableInfo
*tbinfo
= coninfo
->contable
;
10458 PQExpBuffer q
= createPQExpBuffer();
10460 appendPQExpBuffer(q
, "CONSTRAINT %s ",
10461 fmtId(coninfo
->dobj
.name
));
10462 appendPQExpBuffer(q
, "ON %s",
10463 fmtId(tbinfo
->dobj
.name
));
10464 dumpComment(fout
, q
->data
,
10465 tbinfo
->dobj
.namespace->dobj
.name
,
10467 coninfo
->dobj
.catId
, 0,
10468 coninfo
->separate
? coninfo
->dobj
.dumpId
: tbinfo
->dobj
.dumpId
);
10470 destroyPQExpBuffer(q
);
10474 * findLastBuiltInOid -
10475 * find the last built in oid
10477 * For 7.1 and 7.2, we do this by retrieving datlastsysoid from the
10478 * pg_database entry for the current database
10481 findLastBuiltinOid_V71(const char *dbname
)
10486 PQExpBuffer query
= createPQExpBuffer();
10488 resetPQExpBuffer(query
);
10489 appendPQExpBuffer(query
, "SELECT datlastsysoid from pg_database where datname = ");
10490 appendStringLiteralAH(query
, dbname
, g_fout
);
10492 res
= PQexec(g_conn
, query
->data
);
10493 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
10495 ntups
= PQntuples(res
);
10498 write_msg(NULL
, "missing pg_database entry for this database\n");
10503 write_msg(NULL
, "found more than one pg_database entry for this database\n");
10506 last_oid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "datlastsysoid")));
10508 destroyPQExpBuffer(query
);
10513 * findLastBuiltInOid -
10514 * find the last built in oid
10516 * For 7.0, we do this by assuming that the last thing that initdb does is to
10517 * create the pg_indexes view. This sucks in general, but seeing that 7.0.x
10518 * initdb won't be changing anymore, it'll do.
10521 findLastBuiltinOid_V70(void)
10527 res
= PQexec(g_conn
,
10528 "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'");
10529 check_sql_result(res
, g_conn
,
10530 "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'",
10532 ntups
= PQntuples(res
);
10535 write_msg(NULL
, "could not find entry for pg_indexes in pg_class\n");
10540 write_msg(NULL
, "found more than one entry for pg_indexes in pg_class\n");
10543 last_oid
= atooid(PQgetvalue(res
, 0, PQfnumber(res
, "oid")));
10549 dumpSequence(Archive
*fout
, TableInfo
*tbinfo
)
10562 PQExpBuffer query
= createPQExpBuffer();
10563 PQExpBuffer delqry
= createPQExpBuffer();
10565 /* Make sure we are in proper schema */
10566 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
10568 snprintf(bufm
, sizeof(bufm
), INT64_FORMAT
, SEQ_MINVALUE
);
10569 snprintf(bufx
, sizeof(bufx
), INT64_FORMAT
, SEQ_MAXVALUE
);
10571 if (g_fout
->remoteVersion
>= 80400)
10573 appendPQExpBuffer(query
,
10574 "SELECT sequence_name, "
10575 "start_value, last_value, increment_by, "
10576 "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
10577 " WHEN increment_by < 0 AND max_value = -1 THEN NULL "
10579 "END AS max_value, "
10580 "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
10581 " WHEN increment_by < 0 AND min_value = %s THEN NULL "
10583 "END AS min_value, "
10584 "cache_value, is_cycled, is_called from %s",
10586 fmtId(tbinfo
->dobj
.name
));
10590 appendPQExpBuffer(query
,
10591 "SELECT sequence_name, "
10592 "0 AS start_value, last_value, increment_by, "
10593 "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
10594 " WHEN increment_by < 0 AND max_value = -1 THEN NULL "
10596 "END AS max_value, "
10597 "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
10598 " WHEN increment_by < 0 AND min_value = %s THEN NULL "
10600 "END AS min_value, "
10601 "cache_value, is_cycled, is_called from %s",
10603 fmtId(tbinfo
->dobj
.name
));
10606 res
= PQexec(g_conn
, query
->data
);
10607 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
10609 if (PQntuples(res
) != 1)
10611 write_msg(NULL
, ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)\n",
10612 "query to get data of sequence \"%s\" returned %d rows (expected 1)\n",
10614 tbinfo
->dobj
.name
, PQntuples(res
));
10618 /* Disable this check: it fails if sequence has been renamed */
10620 if (strcmp(PQgetvalue(res
, 0, 0), tbinfo
->dobj
.name
) != 0)
10622 write_msg(NULL
, "query to get data of sequence \"%s\" returned name \"%s\"\n",
10623 tbinfo
->dobj
.name
, PQgetvalue(res
, 0, 0));
10628 startv
= PQgetvalue(res
, 0, 1);
10629 last
= PQgetvalue(res
, 0, 2);
10630 incby
= PQgetvalue(res
, 0, 3);
10631 if (!PQgetisnull(res
, 0, 4))
10632 maxv
= PQgetvalue(res
, 0, 4);
10633 if (!PQgetisnull(res
, 0, 5))
10634 minv
= PQgetvalue(res
, 0, 5);
10635 cache
= PQgetvalue(res
, 0, 6);
10636 cycled
= (strcmp(PQgetvalue(res
, 0, 7), "t") == 0);
10637 called
= (strcmp(PQgetvalue(res
, 0, 8), "t") == 0);
10640 * The logic we use for restoring sequences is as follows:
10642 * Add a CREATE SEQUENCE statement as part of a "schema" dump (use
10643 * last_val for start if called is false, else use min_val for start_val).
10644 * Also, if the sequence is owned by a column, add an ALTER SEQUENCE OWNED
10645 * BY command for it.
10647 * Add a 'SETVAL(seq, last_val, iscalled)' as part of a "data" dump.
10651 resetPQExpBuffer(delqry
);
10654 * DROP must be fully qualified in case same name appears in
10657 appendPQExpBuffer(delqry
, "DROP SEQUENCE %s.",
10658 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
10659 appendPQExpBuffer(delqry
, "%s;\n",
10660 fmtId(tbinfo
->dobj
.name
));
10662 resetPQExpBuffer(query
);
10663 appendPQExpBuffer(query
,
10664 "CREATE SEQUENCE %s\n",
10665 fmtId(tbinfo
->dobj
.name
));
10667 if (g_fout
->remoteVersion
>= 80400)
10668 appendPQExpBuffer(query
, " START WITH %s\n", startv
);
10672 * Versions before 8.4 did not remember the true start value. If
10673 * is_called is false then the sequence has never been incremented
10674 * so we can use last_val. Otherwise punt and let it default.
10677 appendPQExpBuffer(query
, " START WITH %s\n", last
);
10680 appendPQExpBuffer(query
, " INCREMENT BY %s\n", incby
);
10683 appendPQExpBuffer(query
, " MAXVALUE %s\n", maxv
);
10685 appendPQExpBuffer(query
, " NO MAXVALUE\n");
10688 appendPQExpBuffer(query
, " MINVALUE %s\n", minv
);
10690 appendPQExpBuffer(query
, " NO MINVALUE\n");
10692 appendPQExpBuffer(query
,
10694 cache
, (cycled
? "\n CYCLE" : ""));
10696 appendPQExpBuffer(query
, ";\n");
10698 ArchiveEntry(fout
, tbinfo
->dobj
.catId
, tbinfo
->dobj
.dumpId
,
10700 tbinfo
->dobj
.namespace->dobj
.name
,
10703 false, "SEQUENCE", SECTION_PRE_DATA
,
10704 query
->data
, delqry
->data
, NULL
,
10705 tbinfo
->dobj
.dependencies
, tbinfo
->dobj
.nDeps
,
10709 * If the sequence is owned by a table column, emit the ALTER for it
10710 * as a separate TOC entry immediately following the sequence's own
10711 * entry. It's OK to do this rather than using full sorting logic,
10712 * because the dependency that tells us it's owned will have forced
10713 * the table to be created first. We can't just include the ALTER in
10714 * the TOC entry because it will fail if we haven't reassigned the
10715 * sequence owner to match the table's owner.
10717 * We need not schema-qualify the table reference because both
10718 * sequence and table must be in the same schema.
10720 if (OidIsValid(tbinfo
->owning_tab
))
10722 TableInfo
*owning_tab
= findTableByOid(tbinfo
->owning_tab
);
10724 if (owning_tab
&& owning_tab
->dobj
.dump
)
10726 resetPQExpBuffer(query
);
10727 appendPQExpBuffer(query
, "ALTER SEQUENCE %s",
10728 fmtId(tbinfo
->dobj
.name
));
10729 appendPQExpBuffer(query
, " OWNED BY %s",
10730 fmtId(owning_tab
->dobj
.name
));
10731 appendPQExpBuffer(query
, ".%s;\n",
10732 fmtId(owning_tab
->attnames
[tbinfo
->owning_col
- 1]));
10734 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
10736 tbinfo
->dobj
.namespace->dobj
.name
,
10739 false, "SEQUENCE OWNED BY", SECTION_PRE_DATA
,
10740 query
->data
, "", NULL
,
10741 &(tbinfo
->dobj
.dumpId
), 1,
10746 /* Dump Sequence Comments */
10747 resetPQExpBuffer(query
);
10748 appendPQExpBuffer(query
, "SEQUENCE %s", fmtId(tbinfo
->dobj
.name
));
10749 dumpComment(fout
, query
->data
,
10750 tbinfo
->dobj
.namespace->dobj
.name
, tbinfo
->rolname
,
10751 tbinfo
->dobj
.catId
, 0, tbinfo
->dobj
.dumpId
);
10756 resetPQExpBuffer(query
);
10757 appendPQExpBuffer(query
, "SELECT pg_catalog.setval(");
10758 appendStringLiteralAH(query
, fmtId(tbinfo
->dobj
.name
), fout
);
10759 appendPQExpBuffer(query
, ", %s, %s);\n",
10760 last
, (called
? "true" : "false"));
10762 ArchiveEntry(fout
, nilCatalogId
, createDumpId(),
10764 tbinfo
->dobj
.namespace->dobj
.name
,
10767 false, "SEQUENCE SET", SECTION_PRE_DATA
,
10768 query
->data
, "", NULL
,
10769 &(tbinfo
->dobj
.dumpId
), 1,
10775 destroyPQExpBuffer(query
);
10776 destroyPQExpBuffer(delqry
);
10780 dumpTrigger(Archive
*fout
, TriggerInfo
*tginfo
)
10782 TableInfo
*tbinfo
= tginfo
->tgtable
;
10784 PQExpBuffer delqry
;
10791 query
= createPQExpBuffer();
10792 delqry
= createPQExpBuffer();
10795 * DROP must be fully qualified in case same name appears in pg_catalog
10797 appendPQExpBuffer(delqry
, "DROP TRIGGER %s ",
10798 fmtId(tginfo
->dobj
.name
));
10799 appendPQExpBuffer(delqry
, "ON %s.",
10800 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
10801 appendPQExpBuffer(delqry
, "%s;\n",
10802 fmtId(tbinfo
->dobj
.name
));
10804 if (tginfo
->tgisconstraint
)
10806 appendPQExpBuffer(query
, "CREATE CONSTRAINT TRIGGER ");
10807 appendPQExpBufferStr(query
, fmtId(tginfo
->tgconstrname
));
10811 appendPQExpBuffer(query
, "CREATE TRIGGER ");
10812 appendPQExpBufferStr(query
, fmtId(tginfo
->dobj
.name
));
10814 appendPQExpBuffer(query
, "\n ");
10818 if (TRIGGER_FOR_BEFORE(tginfo
->tgtype
))
10819 appendPQExpBuffer(query
, "BEFORE");
10821 appendPQExpBuffer(query
, "AFTER");
10822 if (TRIGGER_FOR_INSERT(tginfo
->tgtype
))
10824 appendPQExpBuffer(query
, " INSERT");
10827 if (TRIGGER_FOR_DELETE(tginfo
->tgtype
))
10830 appendPQExpBuffer(query
, " OR DELETE");
10832 appendPQExpBuffer(query
, " DELETE");
10835 if (TRIGGER_FOR_UPDATE(tginfo
->tgtype
))
10838 appendPQExpBuffer(query
, " OR UPDATE");
10840 appendPQExpBuffer(query
, " UPDATE");
10842 if (TRIGGER_FOR_TRUNCATE(tginfo
->tgtype
))
10845 appendPQExpBuffer(query
, " OR TRUNCATE");
10847 appendPQExpBuffer(query
, " TRUNCATE");
10849 appendPQExpBuffer(query
, " ON %s\n",
10850 fmtId(tbinfo
->dobj
.name
));
10852 if (tginfo
->tgisconstraint
)
10854 if (OidIsValid(tginfo
->tgconstrrelid
))
10856 /* If we are using regclass, name is already quoted */
10857 if (g_fout
->remoteVersion
>= 70300)
10858 appendPQExpBuffer(query
, " FROM %s\n ",
10859 tginfo
->tgconstrrelname
);
10861 appendPQExpBuffer(query
, " FROM %s\n ",
10862 fmtId(tginfo
->tgconstrrelname
));
10864 if (!tginfo
->tgdeferrable
)
10865 appendPQExpBuffer(query
, "NOT ");
10866 appendPQExpBuffer(query
, "DEFERRABLE INITIALLY ");
10867 if (tginfo
->tginitdeferred
)
10868 appendPQExpBuffer(query
, "DEFERRED\n");
10870 appendPQExpBuffer(query
, "IMMEDIATE\n");
10873 if (TRIGGER_FOR_ROW(tginfo
->tgtype
))
10874 appendPQExpBuffer(query
, " FOR EACH ROW\n ");
10876 appendPQExpBuffer(query
, " FOR EACH STATEMENT\n ");
10878 /* In 7.3, result of regproc is already quoted */
10879 if (g_fout
->remoteVersion
>= 70300)
10880 appendPQExpBuffer(query
, "EXECUTE PROCEDURE %s(",
10883 appendPQExpBuffer(query
, "EXECUTE PROCEDURE %s(",
10884 fmtId(tginfo
->tgfname
));
10886 p
= tginfo
->tgargs
;
10887 for (findx
= 0; findx
< tginfo
->tgnargs
; findx
++)
10891 /* Set 'p' to end of arg string. marked by '\000' */
10894 p
= strchr(p
, '\\');
10897 write_msg(NULL
, "invalid argument string (%s) for trigger \"%s\" on table \"%s\"\n",
10900 tbinfo
->dobj
.name
);
10904 if (*p
== '\\') /* is it '\\'? */
10909 if (p
[0] == '0' && p
[1] == '0' && p
[2] == '0') /* is it '\000'? */
10914 appendPQExpBufferChar(query
, '\'');
10918 appendPQExpBufferChar(query
, '\'');
10921 * bytea unconditionally doubles backslashes, so we suppress the
10922 * doubling for standard_conforming_strings.
10924 if (fout
->std_strings
&& *s
== '\\' && s
[1] == '\\')
10926 appendPQExpBufferChar(query
, *s
++);
10928 appendPQExpBufferChar(query
, '\'');
10929 appendPQExpBuffer(query
,
10930 (findx
< tginfo
->tgnargs
- 1) ? ", " : "");
10933 appendPQExpBuffer(query
, ");\n");
10935 if (tginfo
->tgenabled
!= 't' && tginfo
->tgenabled
!= 'O')
10937 appendPQExpBuffer(query
, "\nALTER TABLE %s ",
10938 fmtId(tbinfo
->dobj
.name
));
10939 switch (tginfo
->tgenabled
)
10943 appendPQExpBuffer(query
, "DISABLE");
10946 appendPQExpBuffer(query
, "ENABLE ALWAYS");
10949 appendPQExpBuffer(query
, "ENABLE REPLICA");
10952 appendPQExpBuffer(query
, "ENABLE");
10955 appendPQExpBuffer(query
, " TRIGGER %s;\n",
10956 fmtId(tginfo
->dobj
.name
));
10959 ArchiveEntry(fout
, tginfo
->dobj
.catId
, tginfo
->dobj
.dumpId
,
10961 tbinfo
->dobj
.namespace->dobj
.name
,
10963 tbinfo
->rolname
, false,
10964 "TRIGGER", SECTION_POST_DATA
,
10965 query
->data
, delqry
->data
, NULL
,
10966 tginfo
->dobj
.dependencies
, tginfo
->dobj
.nDeps
,
10969 resetPQExpBuffer(query
);
10970 appendPQExpBuffer(query
, "TRIGGER %s ",
10971 fmtId(tginfo
->dobj
.name
));
10972 appendPQExpBuffer(query
, "ON %s",
10973 fmtId(tbinfo
->dobj
.name
));
10975 dumpComment(fout
, query
->data
,
10976 tbinfo
->dobj
.namespace->dobj
.name
, tbinfo
->rolname
,
10977 tginfo
->dobj
.catId
, 0, tginfo
->dobj
.dumpId
);
10979 destroyPQExpBuffer(query
);
10980 destroyPQExpBuffer(delqry
);
10988 dumpRule(Archive
*fout
, RuleInfo
*rinfo
)
10990 TableInfo
*tbinfo
= rinfo
->ruletable
;
10993 PQExpBuffer delcmd
;
10996 /* Skip if not to be dumped */
10997 if (!rinfo
->dobj
.dump
|| dataOnly
)
11001 * If it is an ON SELECT rule that is created implicitly by CREATE VIEW,
11002 * we do not want to dump it as a separate object.
11004 if (!rinfo
->separate
)
11008 * Make sure we are in proper schema.
11010 selectSourceSchema(tbinfo
->dobj
.namespace->dobj
.name
);
11012 query
= createPQExpBuffer();
11013 cmd
= createPQExpBuffer();
11014 delcmd
= createPQExpBuffer();
11016 if (g_fout
->remoteVersion
>= 70300)
11018 appendPQExpBuffer(query
,
11019 "SELECT pg_catalog.pg_get_ruledef('%u'::pg_catalog.oid) AS definition",
11020 rinfo
->dobj
.catId
.oid
);
11024 /* Rule name was unique before 7.3 ... */
11025 appendPQExpBuffer(query
,
11026 "SELECT pg_get_ruledef('%s') AS definition",
11030 res
= PQexec(g_conn
, query
->data
);
11031 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
11033 if (PQntuples(res
) != 1)
11035 write_msg(NULL
, "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned\n",
11036 rinfo
->dobj
.name
, tbinfo
->dobj
.name
);
11040 printfPQExpBuffer(cmd
, "%s\n", PQgetvalue(res
, 0, 0));
11043 * Add the command to alter the rules replication firing semantics if it
11044 * differs from the default.
11046 if (rinfo
->ev_enabled
!= 'O')
11048 appendPQExpBuffer(cmd
, "ALTER TABLE %s.",
11049 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
11050 appendPQExpBuffer(cmd
, "%s ",
11051 fmtId(tbinfo
->dobj
.name
));
11052 switch (rinfo
->ev_enabled
)
11055 appendPQExpBuffer(cmd
, "ENABLE ALWAYS RULE %s;\n",
11056 fmtId(rinfo
->dobj
.name
));
11059 appendPQExpBuffer(cmd
, "ENABLE REPLICA RULE %s;\n",
11060 fmtId(rinfo
->dobj
.name
));
11063 appendPQExpBuffer(cmd
, "DISABLE RULE %s;\n",
11064 fmtId(rinfo
->dobj
.name
));
11070 * DROP must be fully qualified in case same name appears in pg_catalog
11072 appendPQExpBuffer(delcmd
, "DROP RULE %s ",
11073 fmtId(rinfo
->dobj
.name
));
11074 appendPQExpBuffer(delcmd
, "ON %s.",
11075 fmtId(tbinfo
->dobj
.namespace->dobj
.name
));
11076 appendPQExpBuffer(delcmd
, "%s;\n",
11077 fmtId(tbinfo
->dobj
.name
));
11079 ArchiveEntry(fout
, rinfo
->dobj
.catId
, rinfo
->dobj
.dumpId
,
11081 tbinfo
->dobj
.namespace->dobj
.name
,
11083 tbinfo
->rolname
, false,
11084 "RULE", SECTION_POST_DATA
,
11085 cmd
->data
, delcmd
->data
, NULL
,
11086 rinfo
->dobj
.dependencies
, rinfo
->dobj
.nDeps
,
11089 /* Dump rule comments */
11090 resetPQExpBuffer(query
);
11091 appendPQExpBuffer(query
, "RULE %s",
11092 fmtId(rinfo
->dobj
.name
));
11093 appendPQExpBuffer(query
, " ON %s",
11094 fmtId(tbinfo
->dobj
.name
));
11095 dumpComment(fout
, query
->data
,
11096 tbinfo
->dobj
.namespace->dobj
.name
,
11098 rinfo
->dobj
.catId
, 0, rinfo
->dobj
.dumpId
);
11102 destroyPQExpBuffer(query
);
11103 destroyPQExpBuffer(cmd
);
11104 destroyPQExpBuffer(delcmd
);
11108 * getDependencies --- obtain available dependency data
11111 getDependencies(void)
11122 DumpableObject
*dobj
,
11125 /* No dependency info available before 7.3 */
11126 if (g_fout
->remoteVersion
< 70300)
11130 write_msg(NULL
, "reading dependency data\n");
11132 /* Make sure we are in proper schema */
11133 selectSourceSchema("pg_catalog");
11135 query
= createPQExpBuffer();
11137 appendPQExpBuffer(query
, "SELECT "
11138 "classid, objid, refclassid, refobjid, deptype "
11140 "WHERE deptype != 'p' "
11143 res
= PQexec(g_conn
, query
->data
);
11144 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
11146 ntups
= PQntuples(res
);
11148 i_classid
= PQfnumber(res
, "classid");
11149 i_objid
= PQfnumber(res
, "objid");
11150 i_refclassid
= PQfnumber(res
, "refclassid");
11151 i_refobjid
= PQfnumber(res
, "refobjid");
11152 i_deptype
= PQfnumber(res
, "deptype");
11155 * Since we ordered the SELECT by referencing ID, we can expect that
11156 * multiple entries for the same object will appear together; this saves
11161 for (i
= 0; i
< ntups
; i
++)
11164 CatalogId refobjId
;
11167 objId
.tableoid
= atooid(PQgetvalue(res
, i
, i_classid
));
11168 objId
.oid
= atooid(PQgetvalue(res
, i
, i_objid
));
11169 refobjId
.tableoid
= atooid(PQgetvalue(res
, i
, i_refclassid
));
11170 refobjId
.oid
= atooid(PQgetvalue(res
, i
, i_refobjid
));
11171 deptype
= *(PQgetvalue(res
, i
, i_deptype
));
11173 if (dobj
== NULL
||
11174 dobj
->catId
.tableoid
!= objId
.tableoid
||
11175 dobj
->catId
.oid
!= objId
.oid
)
11176 dobj
= findObjectByCatalogId(objId
);
11179 * Failure to find objects mentioned in pg_depend is not unexpected,
11180 * since for example we don't collect info about TOAST tables.
11185 fprintf(stderr
, "no referencing object %u %u\n",
11186 objId
.tableoid
, objId
.oid
);
11191 refdobj
= findObjectByCatalogId(refobjId
);
11193 if (refdobj
== NULL
)
11196 fprintf(stderr
, "no referenced object %u %u\n",
11197 refobjId
.tableoid
, refobjId
.oid
);
11203 * Ordinarily, table rowtypes have implicit dependencies on their
11204 * tables. However, for a composite type the implicit dependency goes
11205 * the other way in pg_depend; which is the right thing for DROP but
11206 * it doesn't produce the dependency ordering we need. So in that one
11207 * case, we reverse the direction of the dependency.
11209 if (deptype
== 'i' &&
11210 dobj
->objType
== DO_TABLE
&&
11211 refdobj
->objType
== DO_TYPE
)
11212 addObjectDependency(refdobj
, dobj
->dumpId
);
11215 addObjectDependency(dobj
, refdobj
->dumpId
);
11220 destroyPQExpBuffer(query
);
11225 * selectSourceSchema - make the specified schema the active search path
11226 * in the source database.
11228 * NB: pg_catalog is explicitly searched after the specified schema;
11229 * so user names are only qualified if they are cross-schema references,
11230 * and system names are only qualified if they conflict with a user name
11231 * in the current schema.
11233 * Whenever the selected schema is not pg_catalog, be careful to qualify
11234 * references to system catalogs and types in our emitted commands!
11237 selectSourceSchema(const char *schemaName
)
11239 static char *curSchemaName
= NULL
;
11242 /* Not relevant if fetching from pre-7.3 DB */
11243 if (g_fout
->remoteVersion
< 70300)
11245 /* Ignore null schema names */
11246 if (schemaName
== NULL
|| *schemaName
== '\0')
11248 /* Optimize away repeated selection of same schema */
11249 if (curSchemaName
&& strcmp(curSchemaName
, schemaName
) == 0)
11252 query
= createPQExpBuffer();
11253 appendPQExpBuffer(query
, "SET search_path = %s",
11254 fmtId(schemaName
));
11255 if (strcmp(schemaName
, "pg_catalog") != 0)
11256 appendPQExpBuffer(query
, ", pg_catalog");
11258 do_sql_command(g_conn
, query
->data
);
11260 destroyPQExpBuffer(query
);
11262 free(curSchemaName
);
11263 curSchemaName
= strdup(schemaName
);
11267 * getFormattedTypeName - retrieve a nicely-formatted type name for the
11270 * NB: in 7.3 and up the result may depend on the currently-selected
11271 * schema; this is why we don't try to cache the names.
11274 getFormattedTypeName(Oid oid
, OidOptions opts
)
11283 if ((opts
& zeroAsOpaque
) != 0)
11284 return strdup(g_opaque_type
);
11285 else if ((opts
& zeroAsAny
) != 0)
11286 return strdup("'any'");
11287 else if ((opts
& zeroAsStar
) != 0)
11288 return strdup("*");
11289 else if ((opts
& zeroAsNone
) != 0)
11290 return strdup("NONE");
11293 query
= createPQExpBuffer();
11294 if (g_fout
->remoteVersion
>= 70300)
11296 appendPQExpBuffer(query
, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)",
11299 else if (g_fout
->remoteVersion
>= 70100)
11301 appendPQExpBuffer(query
, "SELECT format_type('%u'::oid, NULL)",
11306 appendPQExpBuffer(query
, "SELECT typname "
11308 "WHERE oid = '%u'::oid",
11312 res
= PQexec(g_conn
, query
->data
);
11313 check_sql_result(res
, g_conn
, query
->data
, PGRES_TUPLES_OK
);
11315 /* Expecting a single result only */
11316 ntups
= PQntuples(res
);
11319 write_msg(NULL
, ngettext("query returned %d row instead of one: %s\n",
11320 "query returned %d rows instead of one: %s\n",
11322 ntups
, query
->data
);
11326 if (g_fout
->remoteVersion
>= 70100)
11328 /* already quoted */
11329 result
= strdup(PQgetvalue(res
, 0, 0));
11333 /* may need to quote it */
11334 result
= strdup(fmtId(PQgetvalue(res
, 0, 0)));
11338 destroyPQExpBuffer(query
);
11344 * myFormatType --- local implementation of format_type for use with 7.0.
11347 myFormatType(const char *typname
, int32 typmod
)
11350 bool isarray
= false;
11351 PQExpBuffer buf
= createPQExpBuffer();
11353 /* Handle array types */
11354 if (typname
[0] == '_')
11360 /* Show lengths on bpchar and varchar */
11361 if (!strcmp(typname
, "bpchar"))
11363 int len
= (typmod
- VARHDRSZ
);
11365 appendPQExpBuffer(buf
, "character");
11367 appendPQExpBuffer(buf
, "(%d)",
11368 typmod
- VARHDRSZ
);
11370 else if (!strcmp(typname
, "varchar"))
11372 appendPQExpBuffer(buf
, "character varying");
11374 appendPQExpBuffer(buf
, "(%d)",
11375 typmod
- VARHDRSZ
);
11377 else if (!strcmp(typname
, "numeric"))
11379 appendPQExpBuffer(buf
, "numeric");
11386 tmp_typmod
= typmod
- VARHDRSZ
;
11387 precision
= (tmp_typmod
>> 16) & 0xffff;
11388 scale
= tmp_typmod
& 0xffff;
11389 appendPQExpBuffer(buf
, "(%d,%d)",
11395 * char is an internal single-byte data type; Let's make sure we force it
11396 * through with quotes. - thomas 1998-12-13
11398 else if (strcmp(typname
, "char") == 0)
11399 appendPQExpBuffer(buf
, "\"char\"");
11401 appendPQExpBuffer(buf
, "%s", fmtId(typname
));
11403 /* Append array qualifier for array types */
11405 appendPQExpBuffer(buf
, "[]");
11407 result
= strdup(buf
->data
);
11408 destroyPQExpBuffer(buf
);
11414 * fmtQualifiedId - convert a qualified name to the proper format for
11415 * the source database.
11417 * Like fmtId, use the result before calling again.
11419 static const char *
11420 fmtQualifiedId(const char *schema
, const char *id
)
11422 static PQExpBuffer id_return
= NULL
;
11424 if (id_return
) /* first time through? */
11425 resetPQExpBuffer(id_return
);
11427 id_return
= createPQExpBuffer();
11429 /* Suppress schema name if fetching from pre-7.3 DB */
11430 if (g_fout
->remoteVersion
>= 70300 && schema
&& *schema
)
11432 appendPQExpBuffer(id_return
, "%s.",
11435 appendPQExpBuffer(id_return
, "%s",
11438 return id_return
->data
;
11442 * Return a column list clause for the given relation.
11444 * Special case: if there are no undropped columns in the relation, return
11445 * "", not an invalid "()" column list.
11447 static const char *
11448 fmtCopyColumnList(const TableInfo
*ti
)
11450 static PQExpBuffer q
= NULL
;
11451 int numatts
= ti
->numatts
;
11452 char **attnames
= ti
->attnames
;
11453 bool *attisdropped
= ti
->attisdropped
;
11457 if (q
) /* first time through? */
11458 resetPQExpBuffer(q
);
11460 q
= createPQExpBuffer();
11462 appendPQExpBuffer(q
, "(");
11464 for (i
= 0; i
< numatts
; i
++)
11466 if (attisdropped
[i
])
11469 appendPQExpBuffer(q
, ", ");
11470 appendPQExpBuffer(q
, "%s", fmtId(attnames
[i
]));
11475 return ""; /* no undropped columns */
11477 appendPQExpBuffer(q
, ")");
11482 * Convenience subroutine to execute a SQL command and check for
11483 * COMMAND_OK status.
11486 do_sql_command(PGconn
*conn
, const char *query
)
11490 res
= PQexec(conn
, query
);
11491 check_sql_result(res
, conn
, query
, PGRES_COMMAND_OK
);
11496 * Convenience subroutine to verify a SQL command succeeded,
11497 * and exit with a useful error message if not.
11500 check_sql_result(PGresult
*res
, PGconn
*conn
, const char *query
,
11501 ExecStatusType expected
)
11505 if (res
&& PQresultStatus(res
) == expected
)
11508 write_msg(NULL
, "SQL command failed\n");
11510 err
= PQresultErrorMessage(res
);
11512 err
= PQerrorMessage(conn
);
11513 write_msg(NULL
, "Error message from server: %s", err
);
11514 write_msg(NULL
, "The command was: %s\n", query
);