int
main(int argc, char** argv)
{
	int	c, i, optindex;

	static struct option long_options[] = {
		{"host", required_argument, NULL, 'h'},
		{"port", required_argument, NULL, 'p'},
		{"username", required_argument, NULL, 'U'},
		{"help", no_argument, NULL, '?'},
		{NULL, 0, NULL, 0}
	};
	
	if (argc == 1 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-?"))
		help();

	while ((c = getopt_long(argc, argv, "h:p:U:",
							long_options, &optindex)) != -1)
	{
		switch (c)
		{
			case 'h':			/* host for tranlsting oids */
				pghost = optarg;
				break;
			case 'p':			/* port for translating oids */
				pgport = optarg;
				break;
			case 'U':			/* username for translating oids */
				username = optarg;
				break;
			default:
				fprintf(stderr, "Try \"changetrackingdump --help\" for more information.\n");
				exit(1);
		}
	}

	if(pghost)
	{
		conn = DBConnect(pghost, pgport, "template1", username);
	}
	dbQry = createPQExpBuffer();

	for (i = optind; i < argc; i++)
	{
		char *fname = argv[i];
		logFd = open(fname, O_RDONLY | PG_BINARY, 0);

		if (logFd < 0)
		{
			perror(fname);
			continue;
		}
		dumpChangeTracking(fname);
	}

	exit_gracefuly(0);
	
	/* just to avoid a warning */
	return 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;
}
/*
 * 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;
}
/*
 * Open a database connection
 */
static PGconn *
DBConnect(const char *host, const char *port, char *database, const char *user)
{
	char	*password = NULL;
	char	*password_prompt = NULL;
	bool	need_pass;
	PGconn	*conn = NULL;

	/* loop until we have a password if requested by backend */
	do
	{
		need_pass = false;

		conn = PQsetdbLogin(host,
	                     port,
	                     NULL,
	                     NULL,
	                     database,
	                     user,
	                     password);

		if (PQstatus(conn) == CONNECTION_BAD &&
			strcmp(PQerrorMessage(conn), PQnoPasswordSupplied) == 0 &&
			!feof(stdin))
		{
			PQfinish(conn);
			need_pass = true;
			free(password);
			password = NULL;
			printf("\nPassword: "******"Connection to database failed: %s",
			PQerrorMessage(conn));
		exit_gracefuly(1);
	}

	if (password)
		free(password);
	
	return conn;
}
Exemple #6
0
int
main(int argc, char** argv)
{
	int	c, i, optindex;
	bool oid2name = false;
	bool oid2name_gen = false;
	char *pghost = NULL; /* connection host */
	char *pgport = NULL; /* connection port */
	char *pguser = NULL; /* connection username */
	char *dbname = NULL; /* connection database name */
	char *oid2name_file = NULL;

	static struct option long_options[] = {
		{"transactions", no_argument, NULL, 't'},
		{"statements", no_argument, NULL, 's'},
		{"stats", no_argument, NULL, 'S'},
		{"hide-timestamps", no_argument, NULL, 'T'},	
		{"rmid", required_argument, NULL, 'r'},
		{"oid2name", no_argument, NULL, 'n'},
		{"gen_oid2name", no_argument, NULL, 'g'},
		{"xid", required_argument, NULL, 'x'},
		{"host", required_argument, NULL, 'h'},
		{"port", required_argument, NULL, 'p'},
		{"user", required_argument, NULL, 'U'},
		{"dbname", required_argument, NULL, 'd'},
		{"file", required_argument, NULL, 'f'},
		{"help", no_argument, NULL, '?'},
		{NULL, 0, NULL, 0}
	};
	
	if (argc == 1 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-?"))
		help();

	pghost = strdup("localhost");
	pgport = strdup("5432");
	pguser = getenv("USER");
	dbname = strdup("postgres");
	oid2name_file = strdup(DATADIR "/contrib/" OID2NAME_FILE);

	while ((c = getopt_long(argc, argv, "sStTngr:x:h:p:U:d:f:",
							long_options, &optindex)) != -1)
	{
		switch (c)
		{
			case 's':			/* show statements */
				statements = true;
				break;

			case 'S':			/* show statistics */
				enable_stats = true;
				enable_rmgr_dump(false);
				break;

			case 't':			
				transactions = true;	/* show only transactions */
				break;

			case 'T':			/* hide timestamps (used for testing) */
				hideTimestamps = true;
				break;
			case 'n':
				oid2name = true;
				break;
			case 'g':
				oid2name_gen = true;
				break;
			case 'r':			/* output only rmid passed */
			  	rmid = atoi(optarg);
				break;
			case 'x':			/* output only xid passed */
			  	xid = atoi(optarg);
				break;
			case 'h':			/* host for tranlsting oids */
				pghost = optarg;
				break;
			case 'p':			/* port for translating oids */
				pgport = optarg;
				break;
			case 'U':			/* username for translating oids */
				pguser = optarg;
				break;
			case 'd':			/* database name for translating oids */
				dbname = optarg;
				break;
			case 'f':
				oid2name_file = optarg;
				break;
			default:
				fprintf(stderr, "Try \"xlogdump --help\" for more information.\n");
				exit(1);
		}
	}

	if (statements && transactions)
	{
		fprintf(stderr, "options \"statements\" (-s) and \"transactions\" (-t) cannot be used together\n");
		exit(1);
	}

	if (rmid>=0 && transactions)
	{
		fprintf(stderr, "options \"rmid\" (-r) and \"transactions\" (-t) cannot be used together\n");
		exit(1);
	}

	if (oid2name)
	{
		if ( !oid2name_from_file(oid2name_file) )
		{
			/* if not found in share/contrib, read from the cwd. */
			oid2name_from_file(OID2NAME_FILE);
		}

		if ( !DBConnect(pghost, pgport, dbname, pguser) )
			fprintf(stderr, "WARNING: Database connection to lookup the system catalog is not available.\n");
	}

	/*
	 * Generate an oid2name cache file.
	 */
	if (oid2name_gen)
	{
		if ( !DBConnect(pghost, pgport, dbname, pguser) )
			exit_gracefuly(1);

		if (oid2name_to_file("oid2name.out"))
		{
			printf("oid2name.out successfully created.\n");
		}

		exit_gracefuly(0);
	}

	for (i = optind; i < argc; i++)
	{
		char *fname = argv[i];
		logFd = open(fname, O_RDONLY | PG_BINARY, 0);

		if (logFd < 0)
		{
			perror(fname);
			continue;
		}
		dumpXLog(fname);
	}

	if (enable_stats)
		print_xlog_stats();

	exit_gracefuly(0);
	
	/* just to avoid a warning */
	return 0;
}