/* * DoCancelNotifyListen: This function executes a LISTEN or a NOTIFY command, with * name in the format N%s_%d_%d, where the %s is replaced by the CDBDumpKey, * and the 2 integers are the contentid and dbid. */ void DoCancelNotifyListen(PGconn *pConn, bool bListen, const char *pszCDBDumpKey, int role_id, int db_id, int target_db_id, const char *pszSuffix) { PGresult *pRes; PQExpBuffer q = createPQExpBuffer(); char *pszCmd = bListen ? "LISTEN" : "NOTIFY"; appendPQExpBuffer(q, "%s N%s_%d_%d", pszCmd, pszCDBDumpKey, role_id, db_id); /* this is valid only for restore operations */ if (target_db_id != -1) appendPQExpBuffer(q, "_T%d", target_db_id); if (pszSuffix != NULL) appendPQExpBuffer(q, "_%s", pszSuffix); pRes = PQexec(pConn, q->data); if (pRes == NULL || PQresultStatus(pRes) != PGRES_COMMAND_OK) { mpp_err_msg_cache("%s command failed for for backup key %s, instid %d, segid %d failed : %s", pszCmd, pszCDBDumpKey, role_id, db_id, PQerrorMessage(pConn)); } PQclear(pRes); destroyPQExpBuffer(q); }
/* * Build ALTER DEFAULT PRIVILEGES command(s) for single pg_default_acl entry. * * type: the object type (TABLES, FUNCTIONS, etc) * nspname: schema name, or NULL for global default privileges * acls: the ACL string fetched from the database * owner: username of privileges owner (will be passed through fmtId) * remoteVersion: version of database * * Returns TRUE if okay, FALSE if could not parse the acl string. * The resulting commands (if any) are appended to the contents of 'sql'. */ bool buildDefaultACLCommands(const char *type, const char *nspname, const char *acls, const char *owner, int remoteVersion, PQExpBuffer sql) { bool result; PQExpBuffer prefix; prefix = createPQExpBuffer(); /* * We incorporate the target role directly into the command, rather than * playing around with SET ROLE or anything like that. This is so that a * permissions error leads to nothing happening, rather than changing * default privileges for the wrong user. */ appendPQExpBuffer(prefix, "ALTER DEFAULT PRIVILEGES FOR ROLE %s ", fmtId(owner)); if (nspname) appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname)); result = buildACLCommands("", NULL, type, acls, owner, prefix->data, remoteVersion, sql); destroyPQExpBuffer(prefix); return result; }
static void cluster_one_database(const char *dbname, bool verbose, const char *table, const char *host, const char *port, const char *username, enum trivalue prompt_password, const char *progname, bool echo) { PQExpBufferData sql; PGconn *conn; initPQExpBuffer(&sql); appendPQExpBuffer(&sql, "CLUSTER"); if (verbose) appendPQExpBuffer(&sql, " VERBOSE"); if (table) appendPQExpBuffer(&sql, " %s", table); appendPQExpBuffer(&sql, ";\n"); conn = connectDatabase(dbname, host, port, username, prompt_password, progname, false); if (!executeMaintenanceCommand(conn, sql.data, echo)) { if (table) fprintf(stderr, _("%s: clustering of table \"%s\" in database \"%s\" failed: %s"), progname, table, dbname, PQerrorMessage(conn)); else fprintf(stderr, _("%s: clustering of database \"%s\" failed: %s"), progname, dbname, PQerrorMessage(conn)); PQfinish(conn); exit(1); } PQfinish(conn); termPQExpBuffer(&sql); }
/* * If calling from a thread it is illegal to leave username or dbName NULL. */ static void initPQConnectionBuffer(Segment *master, char *username, char *dbName, PQExpBuffer buffer, bool catdml) { char *user = username; if (user == NULL) user = MyProcPort->user_name; initPQExpBuffer(buffer); if (dbName == NULL) dbName = MyProcPort->database_name; /* * Build the connection string */ if (catdml) appendPQExpBuffer(buffer, "options='-c gp_session_role=UTILITY -c allow_system_table_mods=dml' "); /* * Use domain sockets on the master since we must do authentication * of this connection. */ appendPQExpBuffer(buffer, "port=%u ", master->port); appendPQExpBuffer(buffer, "dbname=%s ", dbName); appendPQExpBuffer(buffer, "user=%s ", user); appendPQExpBuffer(buffer, "connect_timeout=%d ", gp_segment_connect_timeout); }
/* * Run pg_dump on dbname. */ static int runPgDump(const char *dbname) { PQExpBuffer cmd = createPQExpBuffer(); int ret; appendPQExpBuffer(cmd, SYSTEMQUOTE "\"%s\" %s", pg_dump_bin, pgdumpopts->data); /* * If we have a filename, use the undocumented plain-append pg_dump * format. */ if (filename) appendPQExpBuffer(cmd, " -Fa "); else appendPQExpBuffer(cmd, " -Fp "); doShellQuoting(cmd, dbname); appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE); if (verbose) fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data); fflush(stdout); fflush(stderr); ret = system(cmd->data); destroyPQExpBuffer(cmd); return ret; }
/* * Append the given string to the shell command being built in the buffer, * with suitable shell-style quoting. */ static void doShellQuoting(PQExpBuffer buf, const char *str) { const char *p; #ifndef WIN32 appendPQExpBufferChar(buf, '\''); for (p = str; *p; p++) { if (*p == '\'') appendPQExpBuffer(buf, "'\"'\"'"); else appendPQExpBufferChar(buf, *p); } appendPQExpBufferChar(buf, '\''); #else /* WIN32 */ appendPQExpBufferChar(buf, '"'); for (p = str; *p; p++) { if (*p == '"') appendPQExpBuffer(buf, "\\\""); else appendPQExpBufferChar(buf, *p); } appendPQExpBufferChar(buf, '"'); #endif /* WIN32 */ }
/* * Helper function for dumpXXXConfig(). */ static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem, const char *type, const char *name) { char *pos; char *mine; PQExpBuffer buf = createPQExpBuffer(); mine = strdup(arrayitem); pos = strchr(mine, '='); if (pos == NULL) return; *pos = 0; appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name)); appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine)); /* * Some GUC variable names are 'LIST' type and hence must not be quoted. */ if (pg_strcasecmp(mine, "DateStyle") == 0 || pg_strcasecmp(mine, "search_path") == 0) appendPQExpBuffer(buf, "%s", pos + 1); else appendStringLiteralConn(buf, pos + 1, conn); appendPQExpBuffer(buf, ";\n"); fprintf(OPF, "%s", buf->data); destroyPQExpBuffer(buf); free(mine); }
static void reindex_system_catalogs(const char *dbname, const char *host, const char *port, const char *username, enum trivalue prompt_password, const char *progname, bool echo, bool verbose) { PQExpBufferData sql; PGconn *conn; initPQExpBuffer(&sql); appendPQExpBuffer(&sql, "REINDEX"); if (verbose) appendPQExpBuffer(&sql, " (VERBOSE)"); appendPQExpBuffer(&sql, " SYSTEM %s;", dbname); conn = connectDatabase(dbname, host, port, username, prompt_password, progname, false, false); if (!executeMaintenanceCommand(conn, sql.data, echo)) { fprintf(stderr, _("%s: reindexing of system catalogs failed: %s"), progname, PQerrorMessage(conn)); PQfinish(conn); exit(1); } PQfinish(conn); termPQExpBuffer(&sql); }
/* *Build the WITH clause for resource queue dump */ static void buildWithClause(const char *resname, const char *ressetting, PQExpBuffer buf) { if (0 == strncmp("memory_limit", resname, 12) && (strncmp(ressetting, "-1", 2) != 0)) appendPQExpBuffer(buf, " %s='%s'", resname, ressetting); else appendPQExpBuffer(buf, " %s=%s", resname, ressetting); }
/* * Append a privilege keyword to a keyword list, inserting comma if needed. */ static void AddAcl(PQExpBuffer aclbuf, const char *keyword, const char *subname) { if (aclbuf->len > 0) appendPQExpBufferChar(aclbuf, ','); appendPQExpBuffer(aclbuf, "%s", keyword); if (subname) appendPQExpBuffer(aclbuf, "(%s)", subname); }
/* * ReadBackendBackupFile: This function calls the backend function gp_read_backup_file * which reads the contents out of the appropriate file on the database server. * If the call succeeds/fails, it returns status code 0/-1, an appropriate error string * is inserted into the buffer of pszRtn. */ int ReadBackendBackupFileError(PGconn *pConn, const char *pszBackupDirectory, const char *pszKey, BackupFileType fileType, const char *progName, PQExpBuffer pszRtn) { char *pszFileType; PQExpBuffer Qry; PGresult *pRes; int status = 0; switch (fileType) { case BFT_BACKUP: pszFileType = "0"; break; case BFT_BACKUP_STATUS: pszFileType = "1"; break; case BFT_RESTORE_STATUS: pszFileType = "2"; break; default: appendPQExpBuffer(pszRtn, "Unknown file type passed to ReadBackendBackupFile"); mpp_err_msg("ERROR", progName, " %s: %d\n", pszRtn->data, fileType); return -1; } Qry = createPQExpBuffer(); appendPQExpBuffer(Qry, "SELECT * FROM gp_read_backup_file('%s', '%s', %s)", StringNotNull(pszBackupDirectory, ""), StringNotNull(pszKey, ""), pszFileType); pRes = PQexec(pConn, Qry->data); if (!pRes || PQresultStatus(pRes) != PGRES_TUPLES_OK || PQntuples(pRes) == 0) { appendPQExpBuffer(pszRtn, "Error executing query %s : %s\n", Qry->data, PQerrorMessage(pConn)); mpp_err_msg_cache("ERROR", progName, pszRtn->data); status = -1; } else { char *res = PQgetvalue(pRes, 0, 0); appendPQExpBufferStr(pszRtn, res); if (strstr(res, "ERROR:") || strstr(res, "[ERROR]")) { status = -1; } } PQclear(pRes); destroyPQExpBuffer(Qry); return status; }
/* * Append a psql meta-command that connects to the given database with the * then-current connection's user, host and port. */ void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname) { const char *s; bool complex; /* * If the name is plain ASCII characters, emit a trivial "\connect "foo"". * For other names, even many not technically requiring it, skip to the * general case. No database has a zero-length name. */ complex = false; for (s = dbname; *s; s++) { if (*s == '\n' || *s == '\r') { fprintf(stderr, _("database name contains a newline or carriage return: \"%s\"\n"), dbname); exit(EXIT_FAILURE); } if (!((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') || (*s >= '0' && *s <= '9') || *s == '_' || *s == '.')) { complex = true; } } appendPQExpBufferStr(buf, "\\connect "); if (complex) { PQExpBufferData connstr; initPQExpBuffer(&connstr); appendPQExpBuffer(&connstr, "dbname="); appendConnStrVal(&connstr, dbname); appendPQExpBuffer(buf, "-reuse-previous=on "); /* * As long as the name does not contain a newline, SQL identifier * quoting satisfies the psql meta-command parser. Prefer not to * involve psql-interpreted single quotes, which behaved differently * before PostgreSQL 9.2. */ appendPQExpBufferStr(buf, fmtId(connstr.data)); termPQExpBuffer(&connstr); } else appendPQExpBufferStr(buf, fmtId(dbname)); appendPQExpBufferChar(buf, '\n'); }
/* * Issue a query on a catalog table, and produce calls to a preassign support * function from the result set. * * The output is a string, containing SQL calls like: * * SELECT binary_upgrade.preassign_*_oid(<oid>, <other args); * * 'funcname' is the "preassign_*_oid" function to use. * 'sql' is the query to issue. The columns of the result set are passed as * arguments to the preassign-support function. * */ static void dump_rows(migratorContext *ctx, PQExpBuffer buf, FILE *file, PGconn *conn, const char *sql, const char *funcname) { int ntups; int ncols; int row; int col; PGresult *res; if (file != NULL) buf = createPQExpBuffer(); /* * Add a WHERE or AND clause to filter out built-in objects. * * If the query contains "UNION ALL", then it's the caller's * responsibility to do the filtering. This special case is for the * one more complicated query in get_old_oids() function; all the * other queries are very simple ones. */ if (strstr(sql, "WHERE ") == NULL) res = executeQueryOrDie(ctx, conn, "%s WHERE oid >= %u", sql, FirstNormalObjectId); else if (strstr(sql, "UNION ALL") == NULL) res = executeQueryOrDie(ctx, conn, "%s AND oid >= %u", sql, FirstNormalObjectId); else res = executeQueryOrDie(ctx, conn, "%s", sql); ntups = PQntuples(res); ncols = PQnfields(res); for (row = 0; row < ntups; row++) { appendPQExpBuffer(buf, "SELECT binary_upgrade.%s('%s'", funcname, simple_escape_literal(ctx, conn, PQgetvalue(res, row, 0))); for (col = 1; col < ncols; col++) appendPQExpBuffer(buf, ", '%s'", simple_escape_literal(ctx, conn, PQgetvalue(res, row, col))); appendPQExpBuffer(buf, ");\n"); if (file) { fwrite(buf->data, buf->len, 1, file); resetPQExpBuffer(buf); } } PQclear(res); if (file != NULL) destroyPQExpBuffer(buf); }
/* * Run pg_dump on dbname. */ static int runPgDump(const char *dbname) { PQExpBuffer cmd = createPQExpBuffer(); const char *p; int ret; /* * Win32 has to use double-quotes for args, rather than single quotes. * Strangely enough, this is the only place we pass a database name on the * command line, except "postgres" which doesn't need quoting. */ #ifndef WIN32 appendPQExpBuffer(cmd, "%s\"%s\" %s -Fp '", SYSTEMQUOTE, pg_dump_bin, #else appendPQExpBuffer(cmd, "%s\"%s\" %s -Fp \"", SYSTEMQUOTE, pg_dump_bin, #endif pgdumpopts->data); /* Shell quoting is not quite like SQL quoting, so can't use fmtId */ for (p = dbname; *p; p++) { #ifndef WIN32 if (*p == '\'') appendPQExpBuffer(cmd, "'\"'\"'"); #else if (*p == '"') appendPQExpBuffer(cmd, "\\\""); #endif else appendPQExpBufferChar(cmd, *p); } #ifndef WIN32 appendPQExpBufferChar(cmd, '\''); #else appendPQExpBufferChar(cmd, '"'); #endif appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE); if (verbose) fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data); fflush(stdout); fflush(stderr); ret = system(cmd->data); destroyPQExpBuffer(cmd); return ret; }
static void reindex_one_database(const char *name, const char *dbname, const char *type, const char *host, const char *port, const char *username, enum trivalue prompt_password, const char *progname, bool echo, bool verbose) { PQExpBufferData sql; PGconn *conn; initPQExpBuffer(&sql); appendPQExpBufferStr(&sql, "REINDEX"); if (verbose) appendPQExpBufferStr(&sql, " (VERBOSE)"); if (strcmp(type, "TABLE") == 0) appendPQExpBuffer(&sql, " TABLE %s", name); else if (strcmp(type, "INDEX") == 0) appendPQExpBuffer(&sql, " INDEX %s", name); else if (strcmp(type, "SCHEMA") == 0) appendPQExpBuffer(&sql, " SCHEMA %s", name); else if (strcmp(type, "DATABASE") == 0) appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name)); appendPQExpBufferChar(&sql, ';'); conn = connectDatabase(dbname, host, port, username, prompt_password, progname, false, false); if (!executeMaintenanceCommand(conn, sql.data, echo)) { if (strcmp(type, "TABLE") == 0) fprintf(stderr, _("%s: reindexing of table \"%s\" in database \"%s\" failed: %s"), progname, name, dbname, PQerrorMessage(conn)); if (strcmp(type, "INDEX") == 0) fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"), progname, name, dbname, PQerrorMessage(conn)); if (strcmp(type, "SCHEMA") == 0) fprintf(stderr, _("%s: reindexing of schema \"%s\" in database \"%s\" failed: %s"), progname, name, dbname, PQerrorMessage(conn)); else fprintf(stderr, _("%s: reindexing of database \"%s\" failed: %s"), progname, dbname, PQerrorMessage(conn)); PQfinish(conn); exit(1); } PQfinish(conn); termPQExpBuffer(&sql); }
/* * Atempt to get the name of relation and copy to relName * (if there's a database connection and the reloid changed) * Copy a string with oid if not found */ static void getRelName(uint32 relid) { resetPQExpBuffer(dbQry); if((conn) && (lastDbConn) && (lastRelOid != relid)) { PQclear(res); /* Try the relfilenode and oid just in case the filenode has changed If it has changed more than once we can't translate it's name */ appendPQExpBuffer(dbQry, "SELECT relname, oid FROM pg_class WHERE relfilenode = %i OR oid = %i", relid, relid); res = PQexec(lastDbConn, dbQry->data); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "SELECT FAILED: %s", PQerrorMessage(conn)); PQclear(res); exit_gracefuly(1); } resetPQExpBuffer(dbQry); lastRelOid = relid; if(PQntuples(res) > 0) { strcpy(relName, PQgetvalue(res, 0, 0)); /* copy the oid since it could be different from relfilenode */ lastRelOid = (uint32) atoi(PQgetvalue(res, 0, 1)); return; } } else if(lastRelOid == relid) return; /* Didn't find the name, return string with oid */ sprintf(relName, "%u", relid); return; }
/* * Atempt to get the name of database (if there's a database connection) */ static void getDbName(uint32 db) { resetPQExpBuffer(dbQry); if((conn) && (lastDbOid != db)) { PQclear(res); appendPQExpBuffer(dbQry, "SELECT datname FROM pg_database WHERE oid = %i", db); res = PQexec(conn, dbQry->data); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "SELECT FAILED: %s", PQerrorMessage(conn)); PQclear(res); exit_gracefuly(1); } resetPQExpBuffer(dbQry); lastDbOid = db; if(PQntuples(res) > 0) { strcpy(dbName, PQgetvalue(res, 0, 0)); // Database changed makes new connection PQfinish(lastDbConn); lastDbConn = DBConnect(pghost, pgport, dbName, username); return; } } else if(lastDbOid == db) return; /* Didn't find the name, return string with oid */ sprintf(dbName, "%u", db); return; }
/* * Atempt to read the name of tablespace into lastSpcName * (if there's a database connection and the oid changed since lastSpcOid) */ static void getSpaceName(uint32 space) { resetPQExpBuffer(dbQry); if((conn) && (lastSpcOid != space)) { PQclear(res); appendPQExpBuffer(dbQry, "SELECT spcname FROM pg_tablespace WHERE oid = %i", space); res = PQexec(conn, dbQry->data); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "SELECT FAILED: %s", PQerrorMessage(conn)); PQclear(res); exit_gracefuly(1); } resetPQExpBuffer(dbQry); lastSpcOid = space; if(PQntuples(res) > 0) { strcpy(spaceName, PQgetvalue(res, 0, 0)); return; } } else if(lastSpcOid == space) return; /* Didn't find the name, return string with oid */ sprintf(spaceName, "%u", space); return; }
/* * Dump database-specific configuration */ static void dumpDatabaseConfig(PGconn *conn, const char *dbname) { PQExpBuffer buf = createPQExpBuffer(); int count = 1; for (;;) { PGresult *res; printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count); appendStringLiteral(buf, dbname, true); appendPQExpBuffer(buf, ";"); res = executeQuery(conn, buf->data); if (!PQgetisnull(res, 0, 0)) { makeAlterConfigCommand(PQgetvalue(res, 0, 0), "DATABASE", dbname); PQclear(res); count++; } else { PQclear(res); break; } } destroyPQExpBuffer(buf); }
/* * This function takes a function description, e.g. "x" or "x(int)", and * issues a query on the given connection to retrieve the function's OID * using a cast to regproc or regprocedure (as appropriate). The result, * if there is one, is returned at *foid. Note that we'll fail if the * function doesn't exist OR if there are multiple matching candidates * OR if there's something syntactically wrong with the function description; * unfortunately it can be hard to tell the difference. */ static bool lookup_function_oid(PGconn *conn, const char *desc, Oid *foid) { bool result = true; PQExpBuffer query; PGresult *res; query = createPQExpBuffer(); printfPQExpBuffer(query, "SELECT "); appendStringLiteralConn(query, desc, conn); appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid", strchr(desc, '(') ? "regprocedure" : "regproc"); res = PQexec(conn, query->data); if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) *foid = atooid(PQgetvalue(res, 0, 0)); else { minimal_error_message(res); result = false; } PQclear(res); destroyPQExpBuffer(query); return result; }
/* * Append a privilege keyword to a keyword list, inserting comma if needed. */ static void AddAcl(PQExpBuffer aclbuf, const char *keyword) { if (aclbuf->len > 0) appendPQExpBufferChar(aclbuf, ','); appendPQExpBuffer(aclbuf, "%s", keyword); }
/* * Format a reloptions array and append it to the given buffer. * * "prefix" is prepended to the option names; typically it's "" or "toast.". * * Returns false if the reloptions array could not be parsed (in which case * nothing will have been appended to the buffer), or true on success. * * Note: this logic should generally match the backend's flatten_reloptions() * (in adt/ruleutils.c). */ bool appendReloptionsArray(PQExpBuffer buffer, const char *reloptions, const char *prefix, int encoding, bool std_strings) { char **options; int noptions; int i; if (!parsePGArray(reloptions, &options, &noptions)) { if (options) free(options); return false; } for (i = 0; i < noptions; i++) { char *option = options[i]; char *name; char *separator; char *value; /* * Each array element should have the form name=value. If the "=" is * missing for some reason, treat it like an empty value. */ name = option; separator = strchr(option, '='); if (separator) { *separator = '\0'; value = separator + 1; } else value = ""; if (i > 0) appendPQExpBufferStr(buffer, ", "); appendPQExpBuffer(buffer, "%s%s=", prefix, fmtId(name)); /* * In general we need to quote the value; but to avoid unnecessary * clutter, do not quote if it is an identifier that would not need * quoting. (We could also allow numbers, but that is a bit trickier * than it looks --- for example, are leading zeroes significant? We * don't want to assume very much here about what custom reloptions * might mean.) */ if (strcmp(fmtId(value), value) == 0) appendPQExpBufferStr(buffer, value); else appendStringLiteral(buffer, value, encoding, std_strings); } if (options) free(options); return true; }
static void cluster_one_database(const char *dbname, const char *table, const char *host, const char *port, const char *username, bool password, const char *progname, bool echo, bool quiet) { PQExpBufferData sql; PGconn *conn; PGresult *result; initPQExpBuffer(&sql); appendPQExpBuffer(&sql, "CLUSTER"); if (table) appendPQExpBuffer(&sql, " %s", fmtId(table)); appendPQExpBuffer(&sql, ";\n"); conn = connectDatabase(dbname, host, port, username, password, progname); if (echo) printf("%s", sql.data); result = PQexec(conn, sql.data); if (PQresultStatus(result) != PGRES_COMMAND_OK) { if (table) fprintf(stderr, _("%s: clustering of table \"%s\" in database \"%s\" failed: %s"), progname, table, dbname, PQerrorMessage(conn)); else fprintf(stderr, _("%s: clustering of database \"%s\" failed: %s"), progname, dbname, PQerrorMessage(conn)); PQfinish(conn); exit(1); } PQclear(result); PQfinish(conn); termPQExpBuffer(&sql); if (!quiet) { puts("CLUSTER"); fflush(stdout); } }
/* * Check all the connections of a gang. * * return the count of successful connections and * the count of failed connections due to recovery. */ static void checkConnectionStatus(Gang *gp, int *countInRecovery, int *countSuccessful, struct PQExpBufferData *errorMessage) { SegmentDatabaseDescriptor *segdbDesc = NULL; int size = gp->size; int i = 0; /* * In this loop, we check whether the connections were successful. If not, * we recreate the error message with palloc and report it. */ for (i = 0; i < size; i++) { segdbDesc = &gp->db_descriptors[i]; /* * check connection established or not, if not, we may have to * re-build this gang. */ if (segdbDesc->errcode && segdbDesc->error_message.len > 0) { /* * Log failed connections. Complete failures are taken care of * later. */ Assert(segdbDesc->whoami != NULL); elog(LOG, "Failed connection to %s", segdbDesc->whoami); insist_log(segdbDesc->errcode != 0 && segdbDesc->error_message.len != 0, "connection is null, but no error code or error message, for segDB %d", i); ereport(LOG, (errcode(segdbDesc->errcode), errmsg("%s", segdbDesc->error_message.data))); /* this connect failed -- but why ? */ if (segment_failure_due_to_recovery(segdbDesc->error_message.data)) { elog(LOG, "segment is in recovery mode (%s)", segdbDesc->whoami); (*countInRecovery)++; } else { appendPQExpBuffer(errorMessage, "%s (%s)\n", segdbDesc->error_message.data, segdbDesc->whoami); } cdbconn_resetQEErrorMessage(segdbDesc); } else { Assert(segdbDesc->errcode == 0 && segdbDesc->error_message.len == 0); /* We have a live connection! */ (*countSuccessful)++; } } }
static void create_new_objects(void) { int dbnum; prep_status("Restoring database schemas in the new cluster\n"); for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++) { char sql_file_name[MAXPGPATH], log_file_name[MAXPGPATH]; DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum]; PQExpBufferData connstr, escaped_connstr; initPQExpBuffer(&connstr); appendPQExpBuffer(&connstr, "dbname="); appendConnStrVal(&connstr, old_db->db_name); initPQExpBuffer(&escaped_connstr); appendShellString(&escaped_connstr, connstr.data); termPQExpBuffer(&connstr); pg_log(PG_STATUS, "%s", old_db->db_name); snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid); snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid); /* * pg_dump only produces its output at the end, so there is little * parallelism if using the pipe. */ parallel_exec_prog(log_file_name, NULL, "\"%s/pg_restore\" %s --exit-on-error --verbose --dbname %s \"%s\"", new_cluster.bindir, cluster_conn_opts(&new_cluster), escaped_connstr.data, sql_file_name); termPQExpBuffer(&escaped_connstr); } /* reap all children */ while (reap_child(true) == true) ; end_progress_output(); check_ok(); /* * We don't have minmxids for databases or relations in pre-9.3 clusters, * so set those after we have restored the schema. */ if (GET_MAJOR_VERSION(old_cluster.major_version) < 903) set_frozenxids(true); /* regenerate now that we have objects in the databases */ get_db_and_rel_infos(&new_cluster); }
/* * buildShSecLabelQuery * * Build a query to retrieve security labels for a shared object. */ void buildShSecLabelQuery(PGconn *conn, const char *catalog_name, uint32 objectId, PQExpBuffer sql) { appendPQExpBuffer(sql, "SELECT provider, label FROM pg_catalog.pg_shseclabel " "WHERE classoid = '%s'::pg_catalog.regclass AND " "objoid = %u", catalog_name, objectId); }
void RowDumpToString(Row *row, PQExpBuffer buf) { size_t i = 0; for (i = 0; i < RowSize(row); ++i) { Field *f = RowGetField(row, i); appendBinaryPQExpBuffer(buf, f->data, f->n); appendPQExpBuffer(buf, " "); } }
/* * Dump database-specific configuration */ static void dumpDatabaseConfig(PGconn *conn, const char *dbname) { PQExpBuffer buf = createPQExpBuffer(); int count = 1; for (;;) { PGresult *res; if (server_version >= 90000) printfPQExpBuffer(buf, "SELECT setconfig[%d] FROM pg_db_role_setting WHERE " "setrole = 0 AND setdatabase = (SELECT oid FROM pg_database WHERE datname = ", count); else printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count); appendStringLiteralConn(buf, dbname, conn); if (server_version >= 90000) appendPQExpBuffer(buf, ")"); appendPQExpBuffer(buf, ";"); res = executeQuery(conn, buf->data); if (PQntuples(res) == 1 && !PQgetisnull(res, 0, 0)) { makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0), "DATABASE", dbname, NULL, NULL); PQclear(res); count++; } else { PQclear(res); break; } } destroyPQExpBuffer(buf); }
/* * Build ALTER DEFAULT PRIVILEGES command(s) for single pg_default_acl entry. * * type: the object type (TABLES, FUNCTIONS, etc) * nspname: schema name, or NULL for global default privileges * acls: the ACL string fetched from the database * owner: username of privileges owner (will be passed through fmtId) * remoteVersion: version of database * * Returns TRUE if okay, FALSE if could not parse the acl string. * The resulting commands (if any) are appended to the contents of 'sql'. */ bool buildDefaultACLCommands(const char *type, const char *nspname, const char *acls, const char *racls, const char *initacls, const char *initracls, const char *owner, int remoteVersion, PQExpBuffer sql) { PQExpBuffer prefix; prefix = createPQExpBuffer(); /* * We incorporate the target role directly into the command, rather than * playing around with SET ROLE or anything like that. This is so that a * permissions error leads to nothing happening, rather than changing * default privileges for the wrong user. */ appendPQExpBuffer(prefix, "ALTER DEFAULT PRIVILEGES FOR ROLE %s ", fmtId(owner)); if (nspname) appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname)); if (strlen(initacls) != 0 || strlen(initracls) != 0) { appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n"); if (!buildACLCommands("", NULL, type, initacls, initracls, owner, prefix->data, remoteVersion, sql)) return false; appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n"); } if (!buildACLCommands("", NULL, type, acls, racls, owner, prefix->data, remoteVersion, sql)) return false; destroyPQExpBuffer(prefix); return true; }
/* * emitShSecLabels * * Format security label data retrieved by the query generated in * buildShSecLabelQuery. */ void emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer, const char *target, const char *objname) { int i; for (i = 0; i < PQntuples(res); i++) { char *provider = PQgetvalue(res, i, 0); char *label = PQgetvalue(res, i, 1); /* must use fmtId result before calling it again */ appendPQExpBuffer(buffer, "SECURITY LABEL FOR %s ON %s", fmtId(provider), target); appendPQExpBuffer(buffer, " %s IS ", fmtId(objname)); appendStringLiteralConn(buffer, label, conn); appendPQExpBuffer(buffer, ";\n"); } }