Пример #1
0
/*
 * 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);
}
Пример #2
0
/*
 * 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;
}
Пример #3
0
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);
}
Пример #4
0
/*
 * 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);
}
Пример #5
0
/*
 * 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;
}
Пример #6
0
/*
 * 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 */
}
Пример #7
0
/*
 * 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);
}
Пример #8
0
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);
}
Пример #9
0
/*
 *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);
}
Пример #10
0
/*
 * 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);
}
Пример #11
0
/*
 * 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;
}
Пример #12
0
/*
 * 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');
}
Пример #13
0
/*
 * 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);
}
Пример #14
0
/*
 * 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;
}
Пример #15
0
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);
}
Пример #16
0
/*
 * 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;
}
Пример #17
0
/*
 * 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;
}
Пример #18
0
/*
 * 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;
}
Пример #19
0
/*
 * 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);
}
Пример #20
0
/*
 * 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;
}
Пример #21
0
/*
 * 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);
}
Пример #22
0
/*
 * 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;
}
Пример #23
0
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);
	}
}
Пример #24
0
/*
 * 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)++;
		}
	}
}
Пример #25
0
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);
}
Пример #26
0
/*
 * 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);
}
Пример #27
0
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, " ");
	}
}
Пример #28
0
/*
 * 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);
}
Пример #29
0
/*
 * 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;
}
Пример #30
0
/*
 * 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");
	}
}