📄 pg_dump.c
字号:
i_tgnargs, i_tgargs; int ntups2; int i2; if (g_verbose) fprintf(stderr, "%s finding Triggers for relation: '%s' %s\n", g_comment_start, tblinfo[i].relname, g_comment_end); sprintf(query, "SELECT tgname, tgfoid, tgtype, tgnargs, tgargs " "from pg_trigger " "where tgrelid = '%s'::oid ", tblinfo[i].oid); res2 = PQexec(g_conn, query); if (!res2 || PQresultStatus(res2) != PGRES_TUPLES_OK) { fprintf(stderr, "getTables(): SELECT (for TRIGGER) failed. Explanation from backend: '%s'.\n", PQerrorMessage(g_conn)); exit_nicely(g_conn); } ntups2 = PQntuples(res2); if (ntups2 != tblinfo[i].ntrig) { fprintf(stderr, "getTables(): relation '%s': %d Triggers were expected, but got %d\n", tblinfo[i].relname, tblinfo[i].ntrig, ntups2); exit_nicely(g_conn); } i_tgname = PQfnumber(res2, "tgname"); i_tgfoid = PQfnumber(res2, "tgfoid"); i_tgtype = PQfnumber(res2, "tgtype"); i_tgnargs = PQfnumber(res2, "tgnargs"); i_tgargs = PQfnumber(res2, "tgargs"); tblinfo[i].triggers = (char **) malloc(ntups2 * sizeof(char *)); for (i2 = 0, query[0] = 0; i2 < ntups2; i2++) { char *tgfunc = PQgetvalue(res2, i2, i_tgfoid); int2 tgtype = atoi(PQgetvalue(res2, i2, i_tgtype)); int tgnargs = atoi(PQgetvalue(res2, i2, i_tgnargs)); char *tgargs = PQgetvalue(res2, i2, i_tgargs); char *p; char farg[MAX_QUERY_SIZE]; int findx; for (findx = 0; findx < numFuncs; findx++) { if (strcmp(finfo[findx].oid, tgfunc) == 0 && finfo[findx].nargs == 0 && strcmp(finfo[findx].prorettype, "0") == 0) break; } if (findx == numFuncs) { fprintf(stderr, "getTables(): relation '%s': cannot find function with oid %s for trigger %s\n", tblinfo[i].relname, tgfunc, PQgetvalue(res2, i2, i_tgname)); exit_nicely(g_conn); } tgfunc = finfo[findx].proname;#if 0 /* XXX - how to emit this DROP TRIGGER? */ if (dropSchema) { sprintf(query, "DROP TRIGGER %s ON %s;\n", fmtId(PQgetvalue(res2, i2, i_tgname), force_quotes), fmtId(tblinfo[i].relname, force_quotes)); fputs(query, fout); }#endif sprintf(query, "CREATE TRIGGER %s ", fmtId(PQgetvalue(res2, i2, i_tgname), force_quotes)); /* Trigger type */ findx = 0; if (TRIGGER_FOR_BEFORE(tgtype)) strcat(query, "BEFORE"); else strcat(query, "AFTER"); if (TRIGGER_FOR_INSERT(tgtype)) { strcat(query, " INSERT"); findx++; } if (TRIGGER_FOR_DELETE(tgtype)) { if (findx > 0) strcat(query, " OR DELETE"); else strcat(query, " DELETE"); findx++; } if (TRIGGER_FOR_UPDATE(tgtype)) { if (findx > 0) strcat(query, " OR UPDATE"); else strcat(query, " UPDATE"); } sprintf(query, "%s ON %s FOR EACH ROW EXECUTE PROCEDURE %s (", query, fmtId(tblinfo[i].relname, force_quotes), tgfunc); for (findx = 0; findx < tgnargs; findx++) { char *s, *d; for (p = tgargs;;) { p = strchr(p, '\\'); if (p == NULL) { fprintf(stderr, "getTables(): relation '%s': bad argument string (%s) for trigger '%s'\n", tblinfo[i].relname, PQgetvalue(res2, i2, i_tgargs), PQgetvalue(res2, i2, i_tgname)); exit_nicely(g_conn); } p++; if (*p == '\\') { p++; continue; } if (p[0] == '0' && p[1] == '0' && p[2] == '0') break; } p--; for (s = tgargs, d = &(farg[0]); s < p;) { if (*s == '\'') *d++ = '\\'; *d++ = *s++; } *d = 0; sprintf(query, "%s'%s'%s", query, farg, (findx < tgnargs - 1) ? ", " : ""); tgargs = p + 4; } strcat(query, ");\n"); tblinfo[i].triggers[i2] = strdup(query); } PQclear(res2); } else tblinfo[i].triggers = NULL; } PQclear(res); return tblinfo;}/* * getInherits * read all the inheritance information * from the system catalogs return them in the InhInfo* structure * * numInherits is set to the number of tables read in * * */InhInfo *getInherits(int *numInherits){ PGresult *res; int ntups; int i; char query[MAX_QUERY_SIZE]; InhInfo *inhinfo; int i_inhrel; int i_inhparent; /* find all the inheritance information */ sprintf(query, "SELECT inhrel, inhparent from pg_inherits"); res = PQexec(g_conn, query); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "getInherits(): SELECT failed. Explanation from backend: '%s'.\n", PQerrorMessage(g_conn)); exit_nicely(g_conn); } ntups = PQntuples(res); *numInherits = ntups; inhinfo = (InhInfo *) malloc(ntups * sizeof(InhInfo)); i_inhrel = PQfnumber(res, "inhrel"); i_inhparent = PQfnumber(res, "inhparent"); for (i = 0; i < ntups; i++) { inhinfo[i].inhrel = strdup(PQgetvalue(res, i, i_inhrel)); inhinfo[i].inhparent = strdup(PQgetvalue(res, i, i_inhparent)); } PQclear(res); return inhinfo;}/* * getTableAttrs - * for each table in tblinfo, read its attributes types and names * * this is implemented in a very inefficient way right now, looping * through the tblinfo and doing a join per table to find the attrs and their * types * * modifies tblinfo */voidgetTableAttrs(TableInfo *tblinfo, int numTables){ int i, j; char q[MAX_QUERY_SIZE]; int i_attname; int i_typname; int i_atttypmod; int i_attnotnull; int i_atthasdef; PGresult *res; int ntups; for (i = 0; i < numTables; i++) { if (tblinfo[i].sequence) continue; /* find all the user attributes and their types */ /* we must read the attribute names in attribute number order! */ /* * because we will use the attnum to index into the attnames array * later */ if (g_verbose) fprintf(stderr, "%s finding the attrs and types for table: '%s' %s\n", g_comment_start, tblinfo[i].relname, g_comment_end); sprintf(q, "SELECT a.attnum, a.attname, t.typname, a.atttypmod, " "a.attnotnull, a.atthasdef " "from pg_attribute a, pg_type t " "where a.attrelid = '%s'::oid and a.atttypid = t.oid " "and a.attnum > 0 order by attnum", tblinfo[i].oid); res = PQexec(g_conn, q); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "getTableAttrs(): SELECT failed. Explanation from backend: '%s'.\n", PQerrorMessage(g_conn)); exit_nicely(g_conn); } ntups = PQntuples(res); i_attname = PQfnumber(res, "attname"); i_typname = PQfnumber(res, "typname"); i_atttypmod = PQfnumber(res, "atttypmod"); i_attnotnull = PQfnumber(res, "attnotnull"); i_atthasdef = PQfnumber(res, "atthasdef"); tblinfo[i].numatts = ntups; tblinfo[i].attnames = (char **) malloc(ntups * sizeof(char *)); tblinfo[i].typnames = (char **) malloc(ntups * sizeof(char *)); tblinfo[i].atttypmod = (int *) malloc(ntups * sizeof(int)); tblinfo[i].inhAttrs = (int *) malloc(ntups * sizeof(int)); tblinfo[i].notnull = (bool *) malloc(ntups * sizeof(bool)); tblinfo[i].adef_expr = (char **) malloc(ntups * sizeof(char *)); tblinfo[i].parentRels = NULL; tblinfo[i].numParents = 0; for (j = 0; j < ntups; j++) { tblinfo[i].attnames[j] = strdup(PQgetvalue(res, j, i_attname)); tblinfo[i].typnames[j] = strdup(PQgetvalue(res, j, i_typname)); tblinfo[i].atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod)); tblinfo[i].inhAttrs[j] = 0; /* this flag is set in * flagInhAttrs() */ tblinfo[i].notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't') ? true : false; if (PQgetvalue(res, j, i_atthasdef)[0] == 't') { PGresult *res2; if (g_verbose) fprintf(stderr, "%s finding DEFAULT expression for attr: '%s' %s\n", g_comment_start, tblinfo[i].attnames[j], g_comment_end); sprintf(q, "SELECT adsrc from pg_attrdef " "where adrelid = '%s'::oid and adnum = %d ", tblinfo[i].oid, j + 1); res2 = PQexec(g_conn, q); if (!res2 || PQresultStatus(res2) != PGRES_TUPLES_OK) { fprintf(stderr, "getTableAttrs(): SELECT (for DEFAULT) failed. Explanation from backend: '%s'.\n", PQerrorMessage(g_conn)); exit_nicely(g_conn); } tblinfo[i].adef_expr[j] = strdup(PQgetvalue(res2, 0, PQfnumber(res2, "adsrc"))); PQclear(res2); } else tblinfo[i].adef_expr[j] = NULL; } PQclear(res); }}/* * getIndices * read all the user-defined indices information * from the system catalogs return them in the InhInfo* structure * * numIndices is set to the number of indices read in * * */IndInfo *getIndices(int *numIndices){ int i; char query[MAX_QUERY_SIZE]; PGresult *res; int ntups; IndInfo *indinfo; int i_indexrelname; int i_indrelname; int i_indamname; int i_indproc; int i_indkey; int i_indclass; int i_indisunique; /* * find all the user-defined indices. We do not handle partial * indices. * * Notice we skip indices on inversion objects (relkind 'l') * * this is a 4-way join !! */ sprintf(query, "SELECT t1.relname as indexrelname, t2.relname as indrelname, " "i.indproc, i.indkey, i.indclass, " "a.amname as indamname, i.indisunique " "from pg_index i, pg_class t1, pg_class t2, pg_am a " "where t1.oid = i.indexrelid and t2.oid = i.indrelid " "and t1.relam = a.oid and i.indexrelid > '%u'::oid " "and t2.relname !~ '^pg_' and t2.relkind != 'l'", g_last_builtin_oid); res = PQexec(g_conn, query); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "getIndices(): SELECT failed. Explanation from backend: '%s'.\n", PQerrorMessage(g_conn)); exit_nicely(g_conn); } ntups = PQntuples(res); *numIndices = ntups; indinfo = (IndInfo *) malloc(ntups * sizeof(IndInfo)); i_indexrelname = PQfnumber(res, "indexrelname"); i_indrelname = PQfnumber(res, "indrelname"); i_indamname = PQfnumber(res, "indamname"); i_indproc = PQfnumber(res, "indproc"); i_indkey = PQfnumber(res, "indkey"); i_indclass = PQfnumber(res, "indclass"); i_indisunique = PQfnumber(res, "indisunique"); for (i = 0; i < ntups; i++) { indinfo[i].indexrelname = strdup(PQgetvalue(res, i, i_indexrelname)); indinfo[i].indrelname = strdup(PQgetvalue(res, i, i_indrelname)); indinfo[i].indamname = strdup(PQgetvalue(res, i, i_indamname)); indinfo[i].indproc = strdup(PQgetvalue(res, i, i_indproc)); parseArgTypes((char **) indinfo[i].indkey, (const char *) PQgetvalue(res, i, i_indkey)); parseArgTypes((char **) indinfo[i].indclass, (const char *) PQgetvalue(res, i, i_indclass)); indinfo[i].indisunique = strdup(PQgetvalue(res, i, i_indisunique)); } PQclear(res); return indinfo;}/* * dumpTypes * writes out to fout the queries to recreate all the user-defined types * */voiddumpTypes(FILE *fout, FuncInfo *finfo, int numFuncs, TypeInfo *tinfo, int numTypes){ int i; char q[MAX_QUERY_SIZE]; int funcInd; for (i = 0; i < numTypes; i++) { /* skip all the builtin types */ if (atoi(tinfo[i].oid) < g_last_builtin_oid) continue; /* skip relation types */ if (atoi(tinfo[i].typrelid) != 0) continue; /* skip all array types that start w/ underscore */ if ((tinfo[i].typname[0] == '_') && (strcmp(tinfo[i].typinput, "array_in") == 0)) continue; /* * before we create a type, we need to create the input and output * functions for it, if they haven't been created already */ funcInd = findFuncByName(finfo, numFuncs, tinfo[i].typinput); if (funcInd != -1) dumpOneFunc(fout, finfo, funcInd, tinfo, numTypes); funcInd = findFuncByName(finfo, numFuncs, tinfo[i].typoutput); if (funcInd != -1) dumpOneFunc(fout, finfo, funcInd, tinfo, numTypes); becomeUser(fout, tinfo[i].usename); if (dropSchema) { sprintf(q, "DROP TYPE %s;\n", fmtId(tinfo[i].typname, force_quotes)); fputs(q, fout); } sprintf(q, "CREATE TYPE %s " "( internallength = %s, externallength = %s, input = %s, " "output = %s, send = %s, receive = %s, default = '%s'", fmtId(tinfo[i].typname, force_quotes), tinfo[i].typlen, tinfo[i].typprtlen, tinfo[i].typinput, tinfo[i].typoutput, tinfo[i].typsend, tinfo[i].typreceive, tinfo[i].typdefault); if (tinfo[i].isArray) { char *elemType; elemType = findTypeByOid(tinfo, numTypes, tinfo[i].typelem); sprintf(q, "%s, element = %s, delimiter = '%s'", q, elemType, tinfo[i].typdelim); } if (tinfo[i].passedbyvalue) strcat(q, ",passedbyvalue);\n"); else strcat(q, ");\n"); fputs(q, fout); }}/* * dumpProcLangs * writes out to fout the queries to recreate user-defined procedural languages * */voiddumpProcLangs(FILE *fout, FuncInfo *finfo, int numFuncs, TypeInfo *tinfo, int numTypes){ PGresult *res; char query[MAX_QUERY_SIZE]; int ntups; int i_lanname; int i_lanpltrusted; int i_lanplcallfoid; int i_lancompiler; char *lanname; char *lancompiler; char *lanplcallfoid; int i, fidx; sprintf(query, "SELECT * FROM pg_language " "WHERE lanispl " "ORDER BY oid"); res = PQexec(g_conn, query); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "dumpProcLangs(): SELECT failed. Explanation from backend: '%s'.\n", PQerrorMessage(g_conn)); exit_nicely(g_conn); } ntups = PQntuples(res); i_lanname = PQfnumber(res, "lanname"); i_lanpltrusted = PQfnumber(res, "lanpltrusted"); i_lanplcallfoid = PQfnumber(res, "lanplcallfoid"); i_lancompiler = PQfnumber(res, "lancompiler"); for (i = 0; i < ntups; i++) { lanplcallfoid = PQgetvalue(res, i, i_lanplcallfoid); for (fidx = 0; fidx < numFuncs; fidx++) { if (!strcmp(finfo[fidx].oid, lanplcallfoid))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -