📄 pg_dump.c
字号:
break; } if (fidx >= numFuncs) { fprintf(stderr, "dumpProcLangs(): handler procedure for language %s not found\n", PQgetvalue(res, i, i_lanname)); exit_nicely(g_conn); } dumpOneFunc(fout, finfo, fidx, tinfo, numTypes); lanname = checkForQuote(PQgetvalue(res, i, i_lanname)); lancompiler = checkForQuote(PQgetvalue(res, i, i_lancompiler)); if (dropSchema) fprintf(fout, "DROP PROCEDURAL LANGUAGE '%s';\n", lanname); fprintf(fout, "CREATE %sPROCEDURAL LANGUAGE '%s' " "HANDLER %s LANCOMPILER '%s';\n", (PQgetvalue(res, i, i_lanpltrusted)[0] == 't') ? "TRUSTED " : "", lanname, fmtId(finfo[fidx].proname, force_quotes), lancompiler); free(lanname); free(lancompiler); } PQclear(res);}/* * dumpFuncs * writes out to fout the queries to recreate all the user-defined functions * */voiddumpFuncs(FILE *fout, FuncInfo *finfo, int numFuncs, TypeInfo *tinfo, int numTypes){ int i; for (i = 0; i < numFuncs; i++) dumpOneFunc(fout, finfo, i, tinfo, numTypes);}/* * dumpOneFunc: * dump out only one function, the index of which is given in the third * argument * */static voiddumpOneFunc(FILE *fout, FuncInfo *finfo, int i, TypeInfo *tinfo, int numTypes){ char q[MAX_QUERY_SIZE]; int j; char *func_def; char func_lang[NAMEDATALEN + 1]; if (finfo[i].dumped) return; else finfo[i].dumped = 1; becomeUser(fout, finfo[i].usename); if (finfo[i].lang == INTERNALlanguageId) { func_def = finfo[i].prosrc; strcpy(func_lang, "INTERNAL"); } else if (finfo[i].lang == ClanguageId) { func_def = finfo[i].probin; strcpy(func_lang, "C"); } else if (finfo[i].lang == SQLlanguageId) { func_def = finfo[i].prosrc; strcpy(func_lang, "SQL"); } else { PGresult *res; int nlangs; int i_lanname; char query[256]; sprintf(query, "SELECT lanname FROM pg_language " "WHERE oid = %u", finfo[i].lang); res = PQexec(g_conn, query); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "dumpOneFunc(): SELECT for procedural language failed. Explanation from backend: '%s'.\n", PQerrorMessage(g_conn)); exit_nicely(g_conn); } nlangs = PQntuples(res); if (nlangs != 1) { fprintf(stderr, "dumpOneFunc(): procedural language for function %s not found\n", finfo[i].proname); exit_nicely(g_conn); } i_lanname = PQfnumber(res, "lanname"); func_def = finfo[i].prosrc; strcpy(func_lang, PQgetvalue(res, 0, i_lanname)); PQclear(res); } if (dropSchema) { sprintf(q, "DROP FUNCTION %s (", fmtId(finfo[i].proname, force_quotes)); for (j = 0; j < finfo[i].nargs; j++) { char *typname; typname = findTypeByOid(tinfo, numTypes, finfo[i].argtypes[j]); sprintf(q, "%s%s%s", q, (j > 0) ? "," : "", fmtId(typname, false)); } sprintf(q, "%s);\n", q); fputs(q, fout); } sprintf(q, "CREATE FUNCTION %s (", fmtId(finfo[i].proname, force_quotes)); for (j = 0; j < finfo[i].nargs; j++) { char *typname; typname = findTypeByOid(tinfo, numTypes, finfo[i].argtypes[j]); sprintf(q, "%s%s%s", q, (j > 0) ? "," : "", fmtId(typname, false)); } sprintf(q, "%s ) RETURNS %s%s AS '%s' LANGUAGE '%s';\n", q, (finfo[i].retset) ? " SETOF " : "", fmtId(findTypeByOid(tinfo, numTypes, finfo[i].prorettype), false), func_def, func_lang); fputs(q, fout);}/* * dumpOprs * writes out to fout the queries to recreate all the user-defined operators * */voiddumpOprs(FILE *fout, OprInfo *oprinfo, int numOperators, TypeInfo *tinfo, int numTypes){ int i; char q[MAX_QUERY_SIZE]; char leftarg[MAX_QUERY_SIZE/8]; char rightarg[MAX_QUERY_SIZE/8]; char commutator[MAX_QUERY_SIZE/8]; char negator[MAX_QUERY_SIZE/8]; char restrictor[MAX_QUERY_SIZE/8]; char join[MAX_QUERY_SIZE/8]; char sort1[MAX_QUERY_SIZE/8]; char sort2[MAX_QUERY_SIZE/8]; for (i = 0; i < numOperators; i++) { /* skip all the builtin oids */ if (atoi(oprinfo[i].oid) < g_last_builtin_oid) continue; /* * some operator are invalid because they were the result of user * defining operators before commutators exist */ if (strcmp(oprinfo[i].oprcode, "-") == 0) continue; leftarg[0] = '\0'; rightarg[0] = '\0'; /* * right unary means there's a left arg and left unary means * there's a right arg */ if (strcmp(oprinfo[i].oprkind, "r") == 0 || strcmp(oprinfo[i].oprkind, "b") == 0) { sprintf(leftarg, ",\n\tLEFTARG = %s ", fmtId(findTypeByOid(tinfo, numTypes, oprinfo[i].oprleft), false)); } if (strcmp(oprinfo[i].oprkind, "l") == 0 || strcmp(oprinfo[i].oprkind, "b") == 0) { sprintf(rightarg, ",\n\tRIGHTARG = %s ", fmtId(findTypeByOid(tinfo, numTypes, oprinfo[i].oprright), false)); } if (strcmp(oprinfo[i].oprcom, "0") == 0) commutator[0] = '\0'; else sprintf(commutator, ",\n\tCOMMUTATOR = %s ", findOprByOid(oprinfo, numOperators, oprinfo[i].oprcom)); if (strcmp(oprinfo[i].oprnegate, "0") == 0) negator[0] = '\0'; else sprintf(negator, ",\n\tNEGATOR = %s ", findOprByOid(oprinfo, numOperators, oprinfo[i].oprnegate)); if (strcmp(oprinfo[i].oprrest, "-") == 0) restrictor[0] = '\0'; else sprintf(restrictor, ",\n\tRESTRICT = %s ", oprinfo[i].oprrest); if (strcmp(oprinfo[i].oprjoin, "-") == 0) join[0] = '\0'; else sprintf(join, ",\n\tJOIN = %s ", oprinfo[i].oprjoin); if (strcmp(oprinfo[i].oprlsortop, "0") == 0) sort1[0] = '\0'; else sprintf(sort1, ",\n\tSORT1 = %s ", findOprByOid(oprinfo, numOperators, oprinfo[i].oprlsortop)); if (strcmp(oprinfo[i].oprrsortop, "0") == 0) sort2[0] = '\0'; else sprintf(sort2, ",\n\tSORT2 = %s ", findOprByOid(oprinfo, numOperators, oprinfo[i].oprrsortop)); becomeUser(fout, oprinfo[i].usename); if (dropSchema) { sprintf(q, "DROP OPERATOR %s (%s, %s);\n", oprinfo[i].oprname, fmtId(findTypeByOid(tinfo, numTypes, oprinfo[i].oprleft), false), fmtId(findTypeByOid(tinfo, numTypes, oprinfo[i].oprright), false)); fputs(q, fout); } sprintf(q, "CREATE OPERATOR %s " "(PROCEDURE = %s %s%s%s%s%s%s%s%s%s);\n", oprinfo[i].oprname, oprinfo[i].oprcode, leftarg, rightarg, commutator, negator, restrictor, (strcmp(oprinfo[i].oprcanhash, "t") == 0) ? ",\n\tHASHES" : "", join, sort1, sort2); fputs(q, fout); }}/* * dumpAggs * writes out to fout the queries to create all the user-defined aggregates * */voiddumpAggs(FILE *fout, AggInfo *agginfo, int numAggs, TypeInfo *tinfo, int numTypes){ int i; char q[MAX_QUERY_SIZE]; char sfunc1[MAX_QUERY_SIZE]; char sfunc2[MAX_QUERY_SIZE]; char basetype[MAX_QUERY_SIZE]; char finalfunc[MAX_QUERY_SIZE]; char comma1[2], comma2[2]; for (i = 0; i < numAggs; i++) { /* skip all the builtin oids */ if (atoi(agginfo[i].oid) < g_last_builtin_oid) continue; sprintf(basetype, "BASETYPE = %s, ", fmtId(findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype), false)); if (strcmp(agginfo[i].aggtransfn1, "-") == 0) sfunc1[0] = '\0'; else { sprintf(sfunc1, "SFUNC1 = %s, STYPE1 = %s", agginfo[i].aggtransfn1, fmtId(findTypeByOid(tinfo, numTypes, agginfo[i].aggtranstype1), false)); if (agginfo[i].agginitval1) sprintf(sfunc1, "%s, INITCOND1 = '%s'", sfunc1, agginfo[i].agginitval1); } if (strcmp(agginfo[i].aggtransfn2, "-") == 0) sfunc2[0] = '\0'; else { sprintf(sfunc2, "SFUNC2 = %s, STYPE2 = %s", agginfo[i].aggtransfn2, fmtId(findTypeByOid(tinfo, numTypes, agginfo[i].aggtranstype2), false)); if (agginfo[i].agginitval2) sprintf(sfunc2, "%s, INITCOND2 = '%s'", sfunc2, agginfo[i].agginitval2); } if (strcmp(agginfo[i].aggfinalfn, "-") == 0) finalfunc[0] = '\0'; else sprintf(finalfunc, "FINALFUNC = %s", agginfo[i].aggfinalfn); if (sfunc1[0] != '\0' && sfunc2[0] != '\0') { comma1[0] = ','; comma1[1] = '\0'; } else comma1[0] = '\0'; if (finalfunc[0] != '\0' && (sfunc1[0] != '\0' || sfunc2[0] != '\0')) { comma2[0] = ','; comma2[1] = '\0'; } else comma2[0] = '\0'; becomeUser(fout, agginfo[i].usename); if (dropSchema) { sprintf(q, "DROP AGGREGATE %s %s;\n", agginfo[i].aggname, fmtId(findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype), false)); fputs(q, fout); } sprintf(q, "CREATE AGGREGATE %s ( %s %s%s %s%s %s );\n", agginfo[i].aggname, basetype, sfunc1, comma1, sfunc2, comma2, finalfunc); fputs(q, fout); }}/* * These are some support functions to fix the acl problem of pg_dump * * Matthew C. Aycock 12/02/97 *//* Append a keyword to a keyword list, inserting comma if needed. * Caller must make aclbuf big enough for all possible keywords. */static voidAddAcl(char *aclbuf, const char *keyword){ if (*aclbuf) strcat(aclbuf, ","); strcat(aclbuf, keyword);}/* * This will take a string of 'arwR' and return a malloced, * comma delimited string of SELECT,INSERT,UPDATE,DELETE,RULE */static char *GetPrivileges(const char *s){ char aclbuf[100]; aclbuf[0] = '\0'; if (strchr(s, 'a')) AddAcl(aclbuf, "INSERT"); if (strchr(s, 'w')) AddAcl(aclbuf, "UPDATE,DELETE"); if (strchr(s, 'r')) AddAcl(aclbuf, "SELECT"); if (strchr(s, 'R')) AddAcl(aclbuf, "RULE"); /* Special-case when they're all there */ if (strcmp(aclbuf, "INSERT,UPDATE,DELETE,SELECT,RULE") == 0) return strdup("ALL"); return strdup(aclbuf);}/* * dumpACL: * Write out grant/revoke information * Called for sequences and tables */static voiddumpACL(FILE *fout, TableInfo tbinfo){ const char *acls = tbinfo.relacl; char *aclbuf, *tok, *eqpos, *priv; if (strlen(acls) == 0) return; /* table has default permissions */ /* * Revoke Default permissions for PUBLIC. Is this actually necessary, * or is it just a waste of time? */ fprintf(fout, "REVOKE ALL on %s from PUBLIC;\n", fmtId(tbinfo.relname, force_quotes)); /* Make a working copy of acls so we can use strtok */ aclbuf = strdup(acls); /* Scan comma-separated ACL items */ for (tok = strtok(aclbuf, ","); tok != NULL; tok = strtok(NULL, ",")) { /* * Token may start with '{' and/or '"'. Actually only the start * of the string should have '{', but we don't verify that. */ if (*tok == '{') tok++; if (*tok == '"') tok++; /* User name is string up to = in tok */ eqpos = strchr(tok, '='); if (!eqpos) { fprintf(stderr, "Could not parse ACL list for '%s'...Exiting!\n", tbinfo.relname); exit_nicely(g_conn); } /* * Parse the privileges (right-hand side). Skip if there are * none. */ priv = GetPrivileges(eqpos + 1); if (*priv) { fprintf(fout, "GRANT %s on %s to ", priv, fmtId(tbinfo.relname, force_quotes)); /* * Note: fmtId() can only be called once per printf, so don't * try to merge printing of username into the above printf. */ if (eqpos == tok) { /* Empty left-hand side means "PUBLIC" */ fprintf(fout, "PUBLIC;\n"); } else { *eqpos = '\0'; /* it's ok to clobber aclbuf */ if (strncmp(tok, "group ", strlen("group ")) == 0) fprintf(fout, "GROUP %s;\n", fmtId(tok + strlen("group "), force_quotes)); else fprintf(fout, "%s;\n", fmtId(tok, force_quotes)); } } free(priv); } free(aclbuf);}/* * dumpTables: * write out to fout all the user-define tables */voiddumpTables(FILE *fout, TableInfo *tblinfo, int numTables, InhInfo *inhinfo, int numInherits, TypeInfo *tinfo, int numTypes, const char *tablename, const bool aclsSkip){ int i, j, k; char q[MAX_QUERY_SIZE]; char *serialSeq = NULL; /* implicit sequence name created * by SERIAL datatype */ const
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -