Ejemplo n.º 1
0
/* Establishes two network connections to a Postgres server: one for SQL, and one
 * for replication. context->conninfo contains the connection string or URL to connect
 * to, and context->app_name is the client name (which appears, for example, in
 * pg_stat_activity). Returns 0 on success. */
int client_connect(client_context_t context) {
    if (!context->conninfo || context->conninfo[0] == '\0') {
        client_error(context, "conninfo must be set in client context");
        return EINVAL;
    }
    if (!context->app_name || context->app_name[0] == '\0') {
        client_error(context, "app_name must be set in client context");
        return EINVAL;
    }

    context->sql_conn = PQconnectdb(context->conninfo);
    if (PQstatus(context->sql_conn) != CONNECTION_OK) {
        client_error(context, "Connection to database failed: %s", PQerrorMessage(context->sql_conn));
        return EIO;
    }

    /* Parse the connection string into key-value pairs */
    char *error = NULL;
    PQconninfoOption *parsed_opts = PQconninfoParse(context->conninfo, &error);
    if (!parsed_opts) {
        client_error(context, "Replication connection info: %s", error);
        PQfreemem(error);
        return EIO;
    }

    /* Copy the key-value pairs into a new structure with added replication options */
    PQconninfoOption *option;
    int optcount = 2; /* replication, fallback_application_name */
    for (option = parsed_opts; option->keyword != NULL; option++) {
        if (option->val != NULL && option->val[0] != '\0') optcount++;
    }

    const char **keys = malloc((optcount + 1) * sizeof(char *));
    const char **values = malloc((optcount + 1) * sizeof(char *));
    int i = 0;

    for (option = parsed_opts; option->keyword != NULL; option++) {
        if (option->val != NULL && option->val[0] != '\0') {
            keys[i] = option->keyword;
            values[i] = option->val;
            i++;
        }
    }

    keys[i] = "replication";               values[i] = "database";        i++;
    keys[i] = "fallback_application_name"; values[i] = context->app_name; i++;
    keys[i] = NULL;                        values[i] = NULL;

    int err = 0;
    context->repl.conn = PQconnectdbParams(keys, values, true);
    if (PQstatus(context->repl.conn) != CONNECTION_OK) {
        client_error(context, "Replication connection failed: %s", PQerrorMessage(context->repl.conn));
        err = EIO;
    }

    free(keys);
    free(values);
    PQconninfoFree(parsed_opts);
    return err;
}
Ejemplo n.º 2
0
int
FileRepConnClient_EstablishConnection(
									  char *hostAddress,
									  int port,
									  bool reportError)
{
	int			status = STATUS_OK;
	char		portbuf[11];
	char		timeoutbuf[11];
	const char *keys[5];
	const char *vals[5];

/*	FileRepConnClient_CloseConnection();*/

	snprintf(portbuf, sizeof(portbuf), "%d", port);
	snprintf(timeoutbuf, sizeof(timeoutbuf), "%d", gp_segment_connect_timeout);

	keys[0] = "host";
	vals[0] = hostAddress;
	keys[1] = "port";
	vals[1] = portbuf;
	keys[2] = "dbname";
	vals[2] = "postgres";
	keys[3] = "connect_timeout";
	vals[3] = timeoutbuf;
	keys[4] = NULL;
	vals[4] = NULL;

	filerep_conn = PQconnectdbParams(keys, vals, false);

	if (PQstatus(filerep_conn) != CONNECTION_OK)
	{
		if (reportError || Debug_filerep_print)
			ereport(WARNING,
					(errcode_for_socket_access(),
					 errmsg("could not establish connection with server, host:'%s' port:'%d' err:'%s' : %m",
							hostAddress,
							port,
							PQerrorMessage(filerep_conn)),
					 errSendAlert(true),
					 FileRep_errcontext()));

		status = STATUS_ERROR;

		if (filerep_conn)
		{
			PQfinish(filerep_conn);
			filerep_conn = NULL;
		}
	}

	/* NOTE Handle error message see ftsprobe.c */

	return status;
}
Ejemplo n.º 3
0
static PGconn *
loginDatabase(char *host, int port, char *user, char *password, char *dbname, const char *progname, char *encoding, char *password_prompt)
{
	bool new_pass = false;
	PGconn *coord_conn;
	char port_s[32];
#define PARAMS_ARRAY_SIZE 8
	const char *keywords[PARAMS_ARRAY_SIZE];
	const char *values[PARAMS_ARRAY_SIZE];

	sprintf(port_s, "%d", port);

	keywords[0] = "host";
	values[0] = host;
	keywords[1] = "port";
	values[1] = port_s;
	keywords[2] = "user";
	values[2] = user;
	keywords[3] = "password";
	keywords[4] = "dbname";
	values[4] = dbname;
	keywords[5] = "fallback_application_name";
	values[5] = progname;
	keywords[6] = "client_encoding";
	values[6] = encoding;
	keywords[7] = NULL;
	values[7] = NULL;

	/* Loop until we have a password if requested by backend */
	do
	{
		values[3] = password;

		new_pass = false;
		coord_conn = PQconnectdbParams(keywords, values, true);

		if (PQstatus(coord_conn) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(coord_conn) &&
			password == NULL &&
			try_password_opt != TRI_NO)
		{
			PQfinish(coord_conn);
			password = simple_prompt(password_prompt, 100, false);
			new_pass = true;
		}
	} while (new_pass);
		
	return(coord_conn);
}
Ejemplo n.º 4
0
bool PostgreSql::connect(const ::nnt::store::connection_info & info)
{
    this->close();
    
    const uint sz = 6;
    char const* keys[sz] = {0};
    char const* values[sz] = {0};
    uint idx = 0;
    
    cross::NetAddress addr(info.url);
    
    // 0
    if (addr.addr_type == cross::NetAddress::ADDRESS_NAME)
        keys[idx] = "host";
    else 
        keys[idx] = "hostaddr";
    values[idx++] = addr.address.c_str();
    
    // 1
    keys[idx] = "port";
    values[idx++] = addr.addport.c_str();
    
    // 2
    keys[idx] = "dbname";
    values[idx++] = info.database.c_str();
    
    // 3
    keys[idx] = "user";
    values[idx++] = info.user.c_str();
    
    // 4
    keys[idx] = "password";
    values[idx++] = info.passwd.c_str();
    
    PGconn* conn = PQconnectdbParams(keys, values, 0);
    if (CONNECTION_OK != PQstatus(conn))
    {
        PQfinish(conn);
        return false;
    }
    
    d_ptr->pg = conn;
    
    return true;
}
Ejemplo n.º 5
0
/*
 * ConnectToNode opens a connection to a remote PostgreSQL server. The function
 * configures the connection's fallback application name to 'citus' and sets
 * the remote encoding to match the local one.  All parameters are required to
 * be non NULL.
 *
 * We attempt to connect up to MAX_CONNECT_ATTEMPT times. After that we give up
 * and return NULL.
 */
PGconn *
ConnectToNode(char *nodeName, int32 nodePort, char *nodeUser)
{
	PGconn *connection = NULL;
	const char *clientEncoding = GetDatabaseEncodingName();
	const char *dbname = get_database_name(MyDatabaseId);
	int attemptIndex = 0;

	const char *keywordArray[] = {
		"host", "port", "fallback_application_name",
		"client_encoding", "connect_timeout", "dbname", "user", NULL
	};
	char nodePortString[12];
	const char *valueArray[] = {
		nodeName, nodePortString, "citus", clientEncoding,
		CLIENT_CONNECT_TIMEOUT_SECONDS, dbname, nodeUser, NULL
	};

	sprintf(nodePortString, "%d", nodePort);

	Assert(sizeof(keywordArray) == sizeof(valueArray));

	for (attemptIndex = 0; attemptIndex < MAX_CONNECT_ATTEMPTS; attemptIndex++)
	{
		connection = PQconnectdbParams(keywordArray, valueArray, false);
		if (PQstatus(connection) == CONNECTION_OK)
		{
			break;
		}
		else
		{
			/* warn if still erroring on final attempt */
			if (attemptIndex == MAX_CONNECT_ATTEMPTS - 1)
			{
				WarnRemoteError(connection, NULL);
			}

			PQfinish(connection);
			connection = NULL;
		}
	}

	return connection;
}
Ejemplo n.º 6
0
PGconn *
establishDBConnectionByParams(const char *keywords[], const char *values[],const bool exit_on_error)
{
	/* Make a connection to the database */
	PGconn *conn = PQconnectdbParams(keywords, values, true);

	/* Check to see that the backend connection was successfully made */
	if ((PQstatus(conn) != CONNECTION_OK))
	{
		log_err(_("Connection to database failed: %s\n"),
		        PQerrorMessage(conn));
		if (exit_on_error)
		{
			PQfinish(conn);
			exit(ERR_DB_CON);
		}
	}

	return conn;
}
Ejemplo n.º 7
0
/*!
 * \brief Create a new connection
 *
 * Create a new connection structure in private memory, open the PostgreSQL
 * connection and set reference count to 1
 * \param id database id
 * \return postgres connection structure, 0 on error
 */
struct pg_con* db_postgres_new_connection(struct db_id* id)
{
    struct pg_con* ptr;
    char *ports;
    int i = 0;
    const char *keywords[10], *values[10];
    char to[16];

    LM_DBG("db_id = %p\n", id);

    if (!id) {
        LM_ERR("invalid db_id parameter value\n");
        return 0;
    }

    ptr = (struct pg_con*)pkg_malloc(sizeof(struct pg_con));
    if (!ptr) {
        LM_ERR("failed trying to allocated %lu bytes for connection structure."
               "\n", (unsigned long)sizeof(struct pg_con));
        return 0;
    }
    LM_DBG("%p=pkg_malloc(%lu)\n", ptr, (unsigned long)sizeof(struct pg_con));

    memset(ptr, 0, sizeof(struct pg_con));
    ptr->ref = 1;

    memset(keywords, 0, (sizeof(char*) * 10));
    memset(values, 0, (sizeof(char*) * 10));
    memset(to, 0, (sizeof(char) * 16));

    if (id->port) {
        ports = int2str(id->port, 0);
        keywords[i] = "port";
        values[i++] = ports;
        LM_DBG("opening connection: postgres://xxxx:xxxx@%s:%d/%s\n", ZSW(id->host),
               id->port, ZSW(id->database));
    } else {
        ports = NULL;
        LM_DBG("opening connection: postgres://xxxx:xxxx@%s/%s\n", ZSW(id->host),
               ZSW(id->database));
    }

    keywords[i] = "host";
    values[i++] = id->host;
    keywords[i] = "dbname";
    values[i++] = id->database;
    keywords[i] = "user";
    values[i++] = id->username;
    keywords[i] = "password";
    values[i++] = id->password;
    if (pg_timeout > 0) {
        snprintf(to, sizeof(to)-1, "%d", pg_timeout + 3);
        keywords[i] = "connect_timeout";
        values[i++] = to;
    }

    keywords[i] = values[i] = NULL;

    /* don't attempt to re-init openssl if done already */
    if(tls_loaded()) PQinitSSL(0);

    ptr->con = PQconnectdbParams(keywords, values, 1);
    LM_DBG("PQconnectdbParams(%p)\n", ptr->con);

    if( (ptr->con == 0) || (PQstatus(ptr->con) != CONNECTION_OK) )
    {
        LM_ERR("%s\n", PQerrorMessage(ptr->con));
        PQfinish(ptr->con);
        goto err;
    }

    ptr->connected = 1;
    ptr->timestamp = time(0);
    ptr->id = id;

#if defined(SO_KEEPALIVE) && defined(TCP_KEEPIDLE)
    if (pg_keepalive) {
        i = 1;
        setsockopt(PQsocket(ptr->con), SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i));
        setsockopt(PQsocket(ptr->con), IPPROTO_TCP, TCP_KEEPIDLE, &pg_keepalive, sizeof(pg_keepalive));
    }
#endif

    return ptr;

err:
    if (ptr) {
        LM_ERR("cleaning up %p=pkg_free()\n", ptr);
        pkg_free(ptr);
    }
    return 0;
}
Ejemplo n.º 8
0
Archivo: command.c Proyecto: 50wu/gpdb
/*
 * do_connect -- handler for \connect
 *
 * Connects to a database with given parameters. If there exists an
 * established connection, NULL values will be replaced with the ones
 * in the current connection. Otherwise NULL will be passed for that
 * parameter to PQconnectdbParams(), so the libpq defaults will be used.
 *
 * In interactive mode, if connection fails with the given parameters,
 * the old connection will be kept.
 */
static bool
do_connect(char *dbname, char *user, char *host, char *port)
{
	PGconn	   *o_conn = pset.db,
			   *n_conn;
	char	   *password = NULL;

	if (!dbname)
		dbname = PQdb(o_conn);
	if (!user)
		user = PQuser(o_conn);
	if (!host)
		host = PQhost(o_conn);
	if (!port)
		port = PQport(o_conn);

	/*
	 * If the user asked to be prompted for a password, ask for one now. If
	 * not, use the password from the old connection, provided the username
	 * has not changed. Otherwise, try to connect without a password first,
	 * and then ask for a password if needed.
	 *
	 * XXX: this behavior leads to spurious connection attempts recorded in
	 * the postmaster's log.  But libpq offers no API that would let us obtain
	 * a password and then continue with the first connection attempt.
	 */
	if (pset.getPassword == TRI_YES)
	{
		password = prompt_for_password(user);
	}
	else if (o_conn && user && strcmp(PQuser(o_conn), user) == 0)
	{
		password = strdup(PQpass(o_conn));
	}

	while (true)
	{
#define PARAMS_ARRAY_SIZE	7
		const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
		const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));

		keywords[0] = "host";
		values[0] = host;
		keywords[1] = "port";
		values[1] = port;
		keywords[2] = "user";
		values[2] = user;
		keywords[3] = "password";
		values[3] = password;
		keywords[4] = "dbname";
		values[4] = dbname;
		keywords[5] = "fallback_application_name";
		values[5] = pset.progname;
		keywords[6] = NULL;
		values[6] = NULL;

		n_conn = PQconnectdbParams(keywords, values, true);

		free(keywords);
		free(values);

		/* We can immediately discard the password -- no longer needed */
		if (password)
			free(password);

		if (PQstatus(n_conn) == CONNECTION_OK)
			break;

		/*
		 * Connection attempt failed; either retry the connection attempt with
		 * a new password, or give up.
		 */
		if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO)
		{
			PQfinish(n_conn);
			password = prompt_for_password(user);
			continue;
		}

		/*
		 * Failed to connect to the database. In interactive mode, keep the
		 * previous connection to the DB; in scripting mode, close our
		 * previous connection as well.
		 */
		if (pset.cur_cmd_interactive)
		{
			psql_error("%s", PQerrorMessage(n_conn));

			/* pset.db is left unmodified */
			if (o_conn)
				fputs(_("Previous connection kept\n"), stderr);
		}
		else
		{
			psql_error("\\connect: %s", PQerrorMessage(n_conn));
			if (o_conn)
			{
				PQfinish(o_conn);
				pset.db = NULL;
			}
		}

		PQfinish(n_conn);
		return false;
	}

	/*
	 * Replace the old connection with the new one, and update
	 * connection-dependent variables.
	 */
	PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL);
	pset.db = n_conn;
	SyncVariables();
	connection_warnings(false); /* Must be after SyncVariables */

	/* Tell the user about the new connection */
	if (!pset.quiet)
	{
		if (param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) ||
			param_is_newly_set(PQport(o_conn), PQport(pset.db)))
		{
			char	*host = PQhost(pset.db);

			if (host == NULL)
				host = DEFAULT_PGSOCKET_DIR;
			/* If the host is an absolute path, the connection is via socket */
			if (is_absolute_path(host))
				printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
					   PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
			else
				printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
					   PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
		}
		else
			printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
				   PQdb(pset.db), PQuser(pset.db));
	}

	if (o_conn)
		PQfinish(o_conn);
	return true;
}
Ejemplo n.º 9
0
/*
 * Make a database connection with the given parameters.  An
 * interactive password prompt is automatically issued if required.
 */
PGconn *
connectDatabase(const char *dbname, const char *pghost, const char *pgport,
				const char *pguser, enum trivalue prompt_password,
				const char *progname)
{
	PGconn	   *conn;
	char	   *password = NULL;
	bool		new_pass;

	if (prompt_password == TRI_YES)
		password = simple_prompt("Password: "******"%s: out of memory\n"), progname);
			exit(1);
		}

		keywords[0] = "host";
		values[0] = pghost;
		keywords[1] = "port";
		values[1] = pgport;
		keywords[2] = "user";
		values[2] = pguser;
		keywords[3] = "password";
		values[3] = password;
		keywords[4] = "dbname";
		values[4] = dbname;
		keywords[5] = "fallback_application_name";
		values[5] = progname;
		keywords[6] = NULL;
		values[6] = NULL;

		new_pass = false;
		conn = PQconnectdbParams(keywords, values, true);

		free(keywords);
		free(values);

		if (!conn)
		{
			fprintf(stderr, _("%s: could not connect to database %s\n"),
					progname, dbname);
			exit(1);
		}

		if (PQstatus(conn) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(conn) &&
			password == NULL &&
			prompt_password != TRI_NO)
		{
			PQfinish(conn);
			password = simple_prompt("Password: "******"%s: could not connect to database %s: %s"),
				progname, dbname, PQerrorMessage(conn));
		exit(1);
	}

	return conn;
}
Ejemplo n.º 10
0
/*
 * Connect to remote server using specified server and user mapping properties.
 */
static PGconn *
connect_pg_server(ForeignServer *server, UserMapping *user)
{
	PGconn	   *volatile conn = NULL;

	/*
	 * Use PG_TRY block to ensure closing connection on error.
	 */
	PG_TRY();
	{
		const char **keywords;
		const char **values;
		int			n;

		/*
		 * Construct connection params from generic options of ForeignServer
		 * and UserMapping.  (Some of them might not be libpq options, in
		 * which case we'll just waste a few array slots.)  Add 3 extra slots
		 * for fallback_application_name, client_encoding, end marker.
		 */
		n = list_length(server->options) + list_length(user->options) + 3;
		keywords = (const char **) palloc(n * sizeof(char *));
		values = (const char **) palloc(n * sizeof(char *));

		n = 0;
		n += ExtractConnectionOptions(server->options,
									  keywords + n, values + n);
		n += ExtractConnectionOptions(user->options,
									  keywords + n, values + n);

		/* Use "postgres_fdw" as fallback_application_name. */
		keywords[n] = "fallback_application_name";
		values[n] = "postgres_fdw";
		n++;

		/* Set client_encoding so that libpq can convert encoding properly. */
		keywords[n] = "client_encoding";
		values[n] = GetDatabaseEncodingName();
		n++;

		keywords[n] = values[n] = NULL;

		/* verify connection parameters and make connection */
		check_conn_params(keywords, values);

		conn = PQconnectdbParams(keywords, values, false);
		if (!conn || PQstatus(conn) != CONNECTION_OK)
		{
			char	   *connmessage;
			int			msglen;

			/* libpq typically appends a newline, strip that */
			connmessage = pstrdup(PQerrorMessage(conn));
			msglen = strlen(connmessage);
			if (msglen > 0 && connmessage[msglen - 1] == '\n')
				connmessage[msglen - 1] = '\0';
			ereport(ERROR,
			   (errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION),
				errmsg("could not connect to server \"%s\"",
					   server->servername),
				errdetail_internal("%s", connmessage)));
		}

		/*
		 * Check that non-superuser has used password to establish connection;
		 * otherwise, he's piggybacking on the postgres server's user
		 * identity. See also dblink_security_check() in contrib/dblink.
		 */
		if (!superuser() && !PQconnectionUsedPassword(conn))
			ereport(ERROR,
				  (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
				   errmsg("password is required"),
				   errdetail("Non-superuser cannot connect if the server does not request a password."),
				   errhint("Target server's authentication method must be changed.")));

		/* Prepare new session for use */
		configure_remote_session(conn);

		pfree(keywords);
		pfree(values);
	}
	PG_CATCH();
	{
		/* Release PGconn data structure if we managed to create one */
		if (conn)
			PQfinish(conn);
		PG_RE_THROW();
	}
	PG_END_TRY();

	return conn;
}
Ejemplo n.º 11
0
/*
 * Connect to a QE as a client via libpq.
 * returns true if connected.
 */
void cdbconn_doConnect(SegmentDatabaseDescriptor *segdbDesc,
					   const char *gpqeid,
					   const char *options)
{
#define MAX_KEYWORDS 10
#define MAX_INT_STRING_LEN 20
	CdbComponentDatabaseInfo *cdbinfo = segdbDesc->segment_database_info;
	const char *keywords[MAX_KEYWORDS];
	const char *values[MAX_KEYWORDS];
	char portstr[MAX_INT_STRING_LEN];
	char timeoutstr[MAX_INT_STRING_LEN];
	int nkeywords = 0;

	keywords[nkeywords] = "gpqeid";
	values[nkeywords] = gpqeid;
	nkeywords++;

	/*
	 * Build the connection string
	 */
	if (options)
	{
		keywords[nkeywords] = "options";
		values[nkeywords] = options;
		nkeywords++;
	}

	/*
	 * For entry DB connection, we make sure both "hostaddr" and "host" are empty string.
	 * Or else, it will fall back to environment variables and won't use domain socket
	 * in function connectDBStart.
	 *
	 * For other QE connections, we set "hostaddr". "host" is not used.
	 */
	if (segdbDesc->segindex == MASTER_CONTENT_ID &&
		GpIdentity.segindex == MASTER_CONTENT_ID)
	{
		keywords[nkeywords] = "hostaddr";
		values[nkeywords] = "";
		nkeywords++;
	}
	else
	{
		Assert(cdbinfo->hostip != NULL);
		keywords[nkeywords] = "hostaddr";
		values[nkeywords] = cdbinfo->hostip;
		nkeywords++;
	}

	keywords[nkeywords] = "host";
	values[nkeywords] = "";
	nkeywords++;

	snprintf(portstr, sizeof(portstr), "%u", cdbinfo->port);
	keywords[nkeywords] = "port";
	values[nkeywords] = portstr;
	nkeywords++;

	if (MyProcPort->database_name)
	{
		keywords[nkeywords] = "dbname";
		values[nkeywords] = MyProcPort->database_name;
		nkeywords++;
	}

	Assert(MyProcPort->user_name);
	keywords[nkeywords] = "user";
	values[nkeywords] = MyProcPort->user_name;
	nkeywords++;

	snprintf(timeoutstr, sizeof(timeoutstr), "%d", gp_segment_connect_timeout);
	keywords[nkeywords] = "connect_timeout";
	values[nkeywords] = timeoutstr;
	nkeywords++;

	keywords[nkeywords] = NULL;
	values[nkeywords] = NULL;

	Assert(nkeywords < MAX_KEYWORDS);

	/*
	 * Call libpq to connect
	 */
	segdbDesc->conn = PQconnectdbParams(keywords, values, false);

	/*
	 * Check for connection failure.
	 */
	if (PQstatus(segdbDesc->conn) == CONNECTION_BAD)
	{
		if (!segdbDesc->errcode)
			segdbDesc->errcode = ERRCODE_GP_INTERCONNECTION_ERROR;

		appendPQExpBuffer(&segdbDesc->error_message, "%s", PQerrorMessage(segdbDesc->conn));

		/* Don't use elog, it's not thread-safe */
		if (gp_log_gang >= GPVARS_VERBOSITY_DEBUG)
			write_log("%s\n", segdbDesc->error_message.data);

		PQfinish(segdbDesc->conn);
		segdbDesc->conn = NULL;
	}
	/*
	 * Successfully connected.
	 */
	else
	{
		PQsetNoticeReceiver(segdbDesc->conn, &MPPnoticeReceiver, segdbDesc);
		/* Command the QE to initialize its motion layer.
		 * Wait for it to respond giving us the TCP port number
		 * where it listens for connections from the gang below.
		 */
		segdbDesc->motionListener = PQgetQEdetail(segdbDesc->conn);
		segdbDesc->backendPid = PQbackendPID(segdbDesc->conn);
		if (segdbDesc->motionListener == -1 || segdbDesc->motionListener == 0)
		{
			segdbDesc->errcode = ERRCODE_GP_INTERNAL_ERROR;
			appendPQExpBuffer(&segdbDesc->error_message,
					"Internal error: No motion listener port");

			if (gp_log_gang >= GPVARS_VERBOSITY_DEBUG)
				write_log("%s\n", segdbDesc->error_message.data);

			PQfinish(segdbDesc->conn);
			segdbDesc->conn = NULL;
		}
		else
		{
			if (gp_log_gang >= GPVARS_VERBOSITY_DEBUG)
				write_log("Connected to %s motionListener=%d with options: %s\n",
						segdbDesc->whoami, segdbDesc->motionListener, options);
		}
	}
}
Ejemplo n.º 12
0
/*
 * Make a database connection with the given parameters.  The
 * connection handle is returned, the parameters are stored in AHX.
 * An interactive password prompt is automatically issued if required.
 *
 * Note: it's not really all that sensible to use a single-entry password
 * cache if the username keeps changing.  In current usage, however, the
 * username never does change, so one savedPassword is sufficient.
 */
void
ConnectDatabase(Archive *AHX,
				const char *dbname,
				const char *pghost,
				const char *pgport,
				const char *username,
				trivalue prompt_password)
{
	ArchiveHandle *AH = (ArchiveHandle *) AHX;
	char	   *password;
	bool		new_pass;

	if (AH->connection)
		exit_horribly(modulename, "already connected to a database\n");

	password = AH->savedPassword ? pg_strdup(AH->savedPassword) : NULL;

	if (prompt_password == TRI_YES && password == NULL)
	{
		password = simple_prompt("Password: "******"out of memory\n");
	}
	AH->promptPassword = prompt_password;

	/*
	 * Start the connection.  Loop until we have a password if requested by
	 * backend.
	 */
	do
	{
		const char *keywords[7];
		const char *values[7];

		keywords[0] = "host";
		values[0] = pghost;
		keywords[1] = "port";
		values[1] = pgport;
		keywords[2] = "user";
		values[2] = username;
		keywords[3] = "password";
		values[3] = password;
		keywords[4] = "dbname";
		values[4] = dbname;
		keywords[5] = "fallback_application_name";
		values[5] = progname;
		keywords[6] = NULL;
		values[6] = NULL;

		new_pass = false;
		AH->connection = PQconnectdbParams(keywords, values, true);

		if (!AH->connection)
			exit_horribly(modulename, "failed to connect to database\n");

		if (PQstatus(AH->connection) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(AH->connection) &&
			password == NULL &&
			prompt_password != TRI_NO)
		{
			PQfinish(AH->connection);
			password = simple_prompt("Password: "******"out of memory\n");
			new_pass = true;
		}
	} while (new_pass);

	/* check to see that the backend connection was successfully made */
	if (PQstatus(AH->connection) == CONNECTION_BAD)
		exit_horribly(modulename, "connection to database \"%s\" failed: %s",
					  PQdb(AH->connection) ? PQdb(AH->connection) : "",
					  PQerrorMessage(AH->connection));

	/*
	 * We want to remember connection's actual password, whether or not we got
	 * it by prompting.  So we don't just store the password variable.
	 */
	if (PQconnectionUsedPassword(AH->connection))
	{
		if (AH->savedPassword)
			free(AH->savedPassword);
		AH->savedPassword = pg_strdup(PQpass(AH->connection));
	}
	if (password)
		free(password);

	/* check for version mismatch */
	_check_database_version(AH);

	PQsetNoticeProcessor(AH->connection, notice_processor, NULL);
}
Ejemplo n.º 13
0
/*
 * This vacuums LOs of one database. It returns 0 on success, -1 on failure.
 */
static int
vacuumlo(const char *database, const struct _param *param)
{
	PGconn	   *conn;
	PGresult   *res,
			   *res2;
	char		buf[BUFSIZE];
	long		matched;
	long		deleted;
	int			i;
	bool		new_pass;
	bool		success = true;
	static bool have_password = false;
	static char password[100];

	/* Note: password can be carried over from a previous call */
	if (param->pg_prompt == TRI_YES && !have_password)
	{
		simple_prompt("Password: "******"host";
		values[0] = param->pg_host;
		keywords[1] = "port";
		values[1] = param->pg_port;
		keywords[2] = "user";
		values[2] = param->pg_user;
		keywords[3] = "password";
		values[3] = have_password ? password : NULL;
		keywords[4] = "dbname";
		values[4] = database;
		keywords[5] = "fallback_application_name";
		values[5] = param->progname;
		keywords[6] = NULL;
		values[6] = NULL;

		new_pass = false;
		conn = PQconnectdbParams(keywords, values, true);
		if (!conn)
		{
			fprintf(stderr, "Connection to database \"%s\" failed\n",
					database);
			return -1;
		}

		if (PQstatus(conn) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(conn) &&
			!have_password &&
			param->pg_prompt != TRI_NO)
		{
			PQfinish(conn);
			simple_prompt("Password: "******"Connection to database \"%s\" failed:\n%s",
				database, PQerrorMessage(conn));
		PQfinish(conn);
		return -1;
	}

	if (param->verbose)
	{
		fprintf(stdout, "Connected to database \"%s\"\n", database);
		if (param->dry_run)
			fprintf(stdout, "Test run: no large objects will be removed!\n");
	}

	res = PQexec(conn, ALWAYS_SECURE_SEARCH_PATH_SQL);
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, "Failed to set search_path:\n");
		fprintf(stderr, "%s", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return -1;
	}
	PQclear(res);

	/*
	 * First we create and populate the LO temp table
	 */
	buf[0] = '\0';
	strcat(buf, "CREATE TEMP TABLE vacuum_l AS ");
	if (PQserverVersion(conn) >= 90000)
		strcat(buf, "SELECT oid AS lo FROM pg_largeobject_metadata");
	else
		strcat(buf, "SELECT DISTINCT loid AS lo FROM pg_largeobject");
	res = PQexec(conn, buf);
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, "Failed to create temp table:\n");
		fprintf(stderr, "%s", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return -1;
	}
	PQclear(res);

	/*
	 * Analyze the temp table so that planner will generate decent plans for
	 * the DELETEs below.
	 */
	buf[0] = '\0';
	strcat(buf, "ANALYZE vacuum_l");
	res = PQexec(conn, buf);
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, "Failed to vacuum temp table:\n");
		fprintf(stderr, "%s", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return -1;
	}
	PQclear(res);

	/*
	 * Now find any candidate tables that have columns of type oid.
	 *
	 * NOTE: we ignore system tables and temp tables by the expedient of
	 * rejecting tables in schemas named 'pg_*'.  In particular, the temp
	 * table formed above is ignored, and pg_largeobject will be too. If
	 * either of these were scanned, obviously we'd end up with nothing to
	 * delete...
	 *
	 * NOTE: the system oid column is ignored, as it has attnum < 1. This
	 * shouldn't matter for correctness, but it saves time.
	 */
	buf[0] = '\0';
	strcat(buf, "SELECT s.nspname, c.relname, a.attname ");
	strcat(buf, "FROM pg_class c, pg_attribute a, pg_namespace s, pg_type t ");
	strcat(buf, "WHERE a.attnum > 0 AND NOT a.attisdropped ");
	strcat(buf, "      AND a.attrelid = c.oid ");
	strcat(buf, "      AND a.atttypid = t.oid ");
	strcat(buf, "      AND c.relnamespace = s.oid ");
	strcat(buf, "      AND t.typname in ('oid', 'lo') ");
	strcat(buf, "      AND c.relkind in (" CppAsString2(RELKIND_RELATION) ", " CppAsString2(RELKIND_MATVIEW) ")");
	strcat(buf, "      AND s.nspname !~ '^pg_'");
	res = PQexec(conn, buf);
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, "Failed to find OID columns:\n");
		fprintf(stderr, "%s", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return -1;
	}

	for (i = 0; i < PQntuples(res); i++)
	{
		char	   *schema,
				   *table,
				   *field;

		schema = PQgetvalue(res, i, 0);
		table = PQgetvalue(res, i, 1);
		field = PQgetvalue(res, i, 2);

		if (param->verbose)
			fprintf(stdout, "Checking %s in %s.%s\n", field, schema, table);

		schema = PQescapeIdentifier(conn, schema, strlen(schema));
		table = PQescapeIdentifier(conn, table, strlen(table));
		field = PQescapeIdentifier(conn, field, strlen(field));

		if (!schema || !table || !field)
		{
			fprintf(stderr, "%s", PQerrorMessage(conn));
			PQclear(res);
			PQfinish(conn);
			if (schema != NULL)
				PQfreemem(schema);
			if (schema != NULL)
				PQfreemem(table);
			if (schema != NULL)
				PQfreemem(field);
			return -1;
		}

		snprintf(buf, BUFSIZE,
				 "DELETE FROM vacuum_l "
				 "WHERE lo IN (SELECT %s FROM %s.%s)",
				 field, schema, table);
		res2 = PQexec(conn, buf);
		if (PQresultStatus(res2) != PGRES_COMMAND_OK)
		{
			fprintf(stderr, "Failed to check %s in table %s.%s:\n",
					field, schema, table);
			fprintf(stderr, "%s", PQerrorMessage(conn));
			PQclear(res2);
			PQclear(res);
			PQfinish(conn);
			PQfreemem(schema);
			PQfreemem(table);
			PQfreemem(field);
			return -1;
		}
		PQclear(res2);

		PQfreemem(schema);
		PQfreemem(table);
		PQfreemem(field);
	}
	PQclear(res);

	/*
	 * Now, those entries remaining in vacuum_l are orphans.  Delete 'em.
	 *
	 * We don't want to run each delete as an individual transaction, because
	 * the commit overhead would be high.  However, since 9.0 the backend will
	 * acquire a lock per deleted LO, so deleting too many LOs per transaction
	 * risks running out of room in the shared-memory lock table. Accordingly,
	 * we delete up to transaction_limit LOs per transaction.
	 */
	res = PQexec(conn, "begin");
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, "Failed to start transaction:\n");
		fprintf(stderr, "%s", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return -1;
	}
	PQclear(res);

	buf[0] = '\0';
	strcat(buf,
		   "DECLARE myportal CURSOR WITH HOLD FOR SELECT lo FROM vacuum_l");
	res = PQexec(conn, buf);
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return -1;
	}
	PQclear(res);

	snprintf(buf, BUFSIZE, "FETCH FORWARD %ld IN myportal",
			 param->transaction_limit > 0 ? param->transaction_limit : 1000L);

	deleted = 0;

	while (1)
	{
		res = PQexec(conn, buf);
		if (PQresultStatus(res) != PGRES_TUPLES_OK)
		{
			fprintf(stderr, "FETCH FORWARD failed: %s", PQerrorMessage(conn));
			PQclear(res);
			PQfinish(conn);
			return -1;
		}

		matched = PQntuples(res);
		if (matched <= 0)
		{
			/* at end of resultset */
			PQclear(res);
			break;
		}

		for (i = 0; i < matched; i++)
		{
			Oid			lo = atooid(PQgetvalue(res, i, 0));

			if (param->verbose)
			{
				fprintf(stdout, "\rRemoving lo %6u   ", lo);
				fflush(stdout);
			}

			if (param->dry_run == 0)
			{
				if (lo_unlink(conn, lo) < 0)
				{
					fprintf(stderr, "\nFailed to remove lo %u: ", lo);
					fprintf(stderr, "%s", PQerrorMessage(conn));
					if (PQtransactionStatus(conn) == PQTRANS_INERROR)
					{
						success = false;
						PQclear(res);
						break;
					}
				}
				else
					deleted++;
			}
			else
				deleted++;

			if (param->transaction_limit > 0 &&
				(deleted % param->transaction_limit) == 0)
			{
				res2 = PQexec(conn, "commit");
				if (PQresultStatus(res2) != PGRES_COMMAND_OK)
				{
					fprintf(stderr, "Failed to commit transaction:\n");
					fprintf(stderr, "%s", PQerrorMessage(conn));
					PQclear(res2);
					PQclear(res);
					PQfinish(conn);
					return -1;
				}
				PQclear(res2);
				res2 = PQexec(conn, "begin");
				if (PQresultStatus(res2) != PGRES_COMMAND_OK)
				{
					fprintf(stderr, "Failed to start transaction:\n");
					fprintf(stderr, "%s", PQerrorMessage(conn));
					PQclear(res2);
					PQclear(res);
					PQfinish(conn);
					return -1;
				}
				PQclear(res2);
			}
		}

		PQclear(res);
	}

	/*
	 * That's all folks!
	 */
	res = PQexec(conn, "commit");
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, "Failed to commit transaction:\n");
		fprintf(stderr, "%s", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return -1;
	}
	PQclear(res);

	PQfinish(conn);

	if (param->verbose)
	{
		if (param->dry_run)
			fprintf(stdout, "\rWould remove %ld large objects from database \"%s\".\n",
					deleted, database);
		else if (success)
			fprintf(stdout,
					"\rSuccessfully removed %ld large objects from database \"%s\".\n",
					deleted, database);
		else
			fprintf(stdout, "\rRemoval from database \"%s\" failed at object %ld of %ld.\n",
					database, deleted, matched);
	}

	return ((param->dry_run || success) ? 0 : -1);
}
Ejemplo n.º 14
0
void *be_pg_init()
{
	struct pg_backend *conf;
	char *host, *user, *pass, *dbname, *p, *port, *sslcert, *sslkey;
	char *userquery;
	char **keywords = NULL;
	char **values = NULL;

	_log(LOG_DEBUG, "}}}} POSTGRES");

	host = p_stab("host");
	p = p_stab("port");
	user = p_stab("user");
	pass = p_stab("pass");
	dbname = p_stab("dbname");
	sslcert = p_stab("sslcert");
	sslkey = p_stab("sslkey");

	host = (host) ? host : strdup("");
	port = (p) ? p : strdup("");

	userquery = p_stab("userquery");

	if (!userquery) {
		_fatal("Mandatory option 'userquery' is missing");
		return (NULL);
	}
	if ((conf = (struct pg_backend *)malloc(sizeof(struct pg_backend))) == NULL)
		return (NULL);

	conf->conn = NULL;
	conf->host = host;
	conf->port = port;
	conf->user = user;
	conf->pass = pass;
	conf->dbname = dbname;
	conf->userquery = userquery;
	conf->superquery = p_stab("superquery");
	conf->aclquery = p_stab("aclquery");
	conf->sslcert = sslcert;
	conf->sslkey = sslkey;

	_log(LOG_DEBUG, "HERE: %s", conf->superquery);
	_log(LOG_DEBUG, "HERE: %s", conf->aclquery);

	const uint8_t MAX_KEYS = 7;
	keywords = (char **) calloc(MAX_KEYS + 1, sizeof(char *));
	values = (char **) calloc(MAX_KEYS + 1, sizeof(char *));

	if (conf->host) {
		addKeyValue(keywords, values, "host", conf->host, MAX_KEYS);
	}
	if (conf->port) {
		addKeyValue(keywords, values, "port", conf->port, MAX_KEYS);
	}
	if (conf->dbname) {
		addKeyValue(keywords, values, "dbname", conf->dbname, MAX_KEYS);
	}
	if (conf->user) {
		addKeyValue(keywords, values, "user", conf->user, MAX_KEYS);
	}
	if (conf->pass) {
		addKeyValue(keywords, values, "password", conf->pass, MAX_KEYS);
	}
	if (conf->sslcert) {
		addKeyValue(keywords, values, "sslcert", conf->sslcert, MAX_KEYS);
	}
	if (conf->sslkey) {
		addKeyValue(keywords, values, "sslkey", conf->sslkey, MAX_KEYS);
	}

	conf->conn = PQconnectdbParams(
		(const char * const *)keywords, (const char * const *)values, 0);

	free(keywords);
	free(values);

	if (PQstatus(conf->conn) == CONNECTION_BAD) {
		free(conf);
		_fatal("We were unable to connect to the database");
		return (NULL);
	}

	return ((void *)conf);
}
Ejemplo n.º 15
0
/*
 * Connect to the server. Returns a valid PGconn pointer if connected,
 * or NULL on non-permanent error. On permanent error, the function will
 * call exit(1) directly.
 */
PGconn *
GetConnection(void)
{
	PGconn	   *tmpconn;
	int			argcount = 4;	/* dbname, replication, fallback_app_name,
								 * password */
	int			i;
	const char **keywords;
	const char **values;
	char	   *password = NULL;
	const char *tmpparam;

	if (dbhost)
		argcount++;
	if (dbuser)
		argcount++;
	if (dbport)
		argcount++;

	keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
	values = pg_malloc0((argcount + 1) * sizeof(*values));

	keywords[0] = "dbname";
	values[0] = "replication";
	keywords[1] = "replication";
	values[1] = "true";
	keywords[2] = "fallback_application_name";
	values[2] = progname;
	i = 3;
	if (dbhost)
	{
		keywords[i] = "host";
		values[i] = dbhost;
		i++;
	}
	if (dbuser)
	{
		keywords[i] = "user";
		values[i] = dbuser;
		i++;
	}
	if (dbport)
	{
		keywords[i] = "port";
		values[i] = dbport;
		i++;
	}

	while (true)
	{
		if (password)
			free(password);

		if (dbpassword)
		{
			/*
			 * We've saved a password when a previous connection succeeded,
			 * meaning this is the call for a second session to the same
			 * database, so just forcibly reuse that password.
			 */
			keywords[argcount - 1] = "password";
			values[argcount - 1] = dbpassword;
			dbgetpassword = -1; /* Don't try again if this fails */
		}
		else if (dbgetpassword == 1)
		{
			password = simple_prompt(_("Password: "******"password";
			values[argcount - 1] = password;
		}

		tmpconn = PQconnectdbParams(keywords, values, true);

		/*
		 * If there is too little memory even to allocate the PGconn object
		 * and PQconnectdbParams returns NULL, we call exit(1) directly.
		 */
		if (!tmpconn)
		{
			fprintf(stderr, _("%s: could not connect to server\n"),
					progname);
			exit(1);
		}

		if (PQstatus(tmpconn) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(tmpconn) &&
			dbgetpassword != -1)
		{
			dbgetpassword = 1;	/* ask for password next time */
			PQfinish(tmpconn);
			continue;
		}

		if (PQstatus(tmpconn) != CONNECTION_OK)
		{
			fprintf(stderr, _("%s: could not connect to server: %s\n"),
					progname, PQerrorMessage(tmpconn));
			PQfinish(tmpconn);
			free(values);
			free(keywords);
			return NULL;
		}

		/* Connection ok! */
		free(values);
		free(keywords);

		/*
		 * Ensure we have the same value of integer timestamps as the server
		 * we are connecting to.
		 */
		tmpparam = PQparameterStatus(tmpconn, "integer_datetimes");
		if (!tmpparam)
		{
			fprintf(stderr,
					_("%s: could not determine server setting for integer_datetimes\n"),
					progname);
			PQfinish(tmpconn);
			exit(1);
		}

#ifdef HAVE_INT64_TIMESTAMP
		if (strcmp(tmpparam, "on") != 0)
#else
		if (strcmp(tmpparam, "off") != 0)
#endif
		{
			fprintf(stderr,
			 _("%s: integer_datetimes compile flag does not match server\n"),
					progname);
			PQfinish(tmpconn);
			exit(1);
		}

		/* Store the password for next run */
		if (password)
			dbpassword = password;
		return tmpconn;
	}
}
Ejemplo n.º 16
0
/* establish connection with database. */
PGconn *
sql_conn(struct options * my_opts)
{
	PGconn	   *conn;
	char	   *password = NULL;
	bool		new_pass;

	/*
	 * Start the connection.  Loop until we have a password if requested by
	 * backend.
	 */
	do
	{
#define PARAMS_ARRAY_SIZE	7

		const char *keywords[PARAMS_ARRAY_SIZE];
		const char *values[PARAMS_ARRAY_SIZE];

		keywords[0] = "host";
		values[0] = my_opts->hostname;
		keywords[1] = "port";
		values[1] = my_opts->port;
		keywords[2] = "user";
		values[2] = my_opts->username;
		keywords[3] = "password";
		values[3] = password;
		keywords[4] = "dbname";
		values[4] = my_opts->dbname;
		keywords[5] = "fallback_application_name";
		values[5] = my_opts->progname;
		keywords[6] = NULL;
		values[6] = NULL;

		new_pass = false;
		conn = PQconnectdbParams(keywords, values, true);

		if (!conn)
		{
			fprintf(stderr, "%s: could not connect to database %s\n",
					"oid2name", my_opts->dbname);
			exit(1);
		}

		if (PQstatus(conn) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(conn) &&
			password == NULL)
		{
			PQfinish(conn);
			password = simple_prompt("Password: "******"%s: could not connect to database %s: %s",
				"oid2name", my_opts->dbname, PQerrorMessage(conn));
		PQfinish(conn);
		exit(1);
	}

	/* return the conn if good */
	return conn;
}
Ejemplo n.º 17
0
/* this contains some quick hacks, needs to be cleaned up, but it works */
bool
ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
{
	struct sqlca_t *sqlca = ECPGget_sqlca();
	enum COMPAT_MODE compat = c;
	struct connection *this;
	int			i,
				connect_params = 0;
	char	   *dbname = name ? ecpg_strdup(name, lineno) : NULL,
			   *host = NULL,
			   *tmp,
			   *port = NULL,
			   *realname = NULL,
			   *options = NULL;
	const char **conn_keywords;
	const char **conn_values;

	ecpg_init_sqlca(sqlca);

	/*
	 * clear auto_mem structure because some error handling functions might
	 * access it
	 */
	ecpg_clear_auto_mem();

	if (INFORMIX_MODE(compat))
	{
		char	   *envname;

		/*
		 * Informix uses an environment variable DBPATH that overrides the
		 * connection parameters given here. We do the same with PG_DBPATH as
		 * the syntax is different.
		 */
		envname = getenv("PG_DBPATH");
		if (envname)
		{
			ecpg_free(dbname);
			dbname = ecpg_strdup(envname, lineno);
		}

	}

	if (dbname == NULL && connection_name == NULL)
		connection_name = "DEFAULT";

#if ENABLE_THREAD_SAFETY
	ecpg_pthreads_init();
#endif

	/* check if the identifier is unique */
	if (ecpg_get_connection(connection_name))
	{
		ecpg_free(dbname);
		ecpg_log("ECPGconnect: connection identifier %s is already in use\n",
				 connection_name);
		return false;
	}

	if ((this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno)) == NULL)
		return false;

	if (dbname != NULL)
	{
		/* get the detail information from dbname */
		if (strncmp(dbname, "tcp:", 4) == 0 || strncmp(dbname, "unix:", 5) == 0)
		{
			int			offset = 0;

			/*
			 * only allow protocols tcp and unix
			 */
			if (strncmp(dbname, "tcp:", 4) == 0)
				offset = 4;
			else if (strncmp(dbname, "unix:", 5) == 0)
				offset = 5;

			if (strncmp(dbname + offset, "postgresql://", strlen("postgresql://")) == 0)
			{

				/*------
				 * new style:
				 *	<tcp|unix>:postgresql://server[:port|:/unixsocket/path:]
				 *	[/db-name][?options]
				 *------
				 */
				offset += strlen("postgresql://");

				tmp = strrchr(dbname + offset, '?');
				if (tmp != NULL)	/* options given */
				{
					options = ecpg_strdup(tmp + 1, lineno);
					*tmp = '\0';
				}

				tmp = last_dir_separator(dbname + offset);
				if (tmp != NULL)	/* database name given */
				{
					if (tmp[1] != '\0') /* non-empty database name */
					{
						realname = ecpg_strdup(tmp + 1, lineno);
						connect_params++;
					}
					*tmp = '\0';
				}

				tmp = strrchr(dbname + offset, ':');
				if (tmp != NULL)	/* port number or Unix socket path given */
				{
					char	   *tmp2;

					*tmp = '\0';
					if ((tmp2 = strchr(tmp + 1, ':')) != NULL)
					{
						*tmp2 = '\0';
						host = ecpg_strdup(tmp + 1, lineno);
						connect_params++;
						if (strncmp(dbname, "unix:", 5) != 0)
						{
							ecpg_log("ECPGconnect: socketname %s given for TCP connection on line %d\n", host, lineno);
							ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : ecpg_gettext("<DEFAULT>"));
							if (host)
								ecpg_free(host);

							/*
							 * port not set yet if (port) ecpg_free(port);
							 */
							if (options)
								ecpg_free(options);
							if (realname)
								ecpg_free(realname);
							if (dbname)
								ecpg_free(dbname);
							free(this);
							return false;
						}
					}
					else
					{
						port = ecpg_strdup(tmp + 1, lineno);
						connect_params++;
					}
				}

				if (strncmp(dbname, "unix:", 5) == 0)
				{
					if (strcmp(dbname + offset, "localhost") != 0 && strcmp(dbname + offset, "127.0.0.1") != 0)
					{
						ecpg_log("ECPGconnect: non-localhost access via sockets on line %d\n", lineno);
						ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : ecpg_gettext("<DEFAULT>"));
						if (host)
							ecpg_free(host);
						if (port)
							ecpg_free(port);
						if (options)
							ecpg_free(options);
						if (realname)
							ecpg_free(realname);
						if (dbname)
							ecpg_free(dbname);
						free(this);
						return false;
					}
				}
				else
				{
					if (*(dbname + offset) != '\0')
					{
						host = ecpg_strdup(dbname + offset, lineno);
						connect_params++;
					}
				}

			}
		}
		else
		{
			/* old style: dbname[@server][:port] */
			tmp = strrchr(dbname, ':');
			if (tmp != NULL)	/* port number given */
			{
				port = ecpg_strdup(tmp + 1, lineno);
				connect_params++;
				*tmp = '\0';
			}

			tmp = strrchr(dbname, '@');
			if (tmp != NULL)	/* host name given */
			{
				host = ecpg_strdup(tmp + 1, lineno);
				connect_params++;
				*tmp = '\0';
			}

			if (strlen(dbname) > 0)
			{
				realname = ecpg_strdup(dbname, lineno);
				connect_params++;
			}
			else
				realname = NULL;
		}
	}
	else
		realname = NULL;

	/* add connection to our list */
#ifdef ENABLE_THREAD_SAFETY
	pthread_mutex_lock(&connections_mutex);
#endif
	if (connection_name != NULL)
		this->name = ecpg_strdup(connection_name, lineno);
	else
		this->name = ecpg_strdup(realname, lineno);

	this->cache_head = NULL;
	this->prep_stmts = NULL;

	if (all_connections == NULL)
		this->next = NULL;
	else
		this->next = all_connections;

	all_connections = this;
#ifdef ENABLE_THREAD_SAFETY
	pthread_setspecific(actual_connection_key, all_connections);
#endif
	actual_connection = all_connections;

	ecpg_log("ECPGconnect: opening database %s on %s port %s %s%s %s%s\n",
			 realname ? realname : "<DEFAULT>",
			 host ? host : "<DEFAULT>",
			 port ? (ecpg_internal_regression_mode ? "<REGRESSION_PORT>" : port) : "<DEFAULT>",
			 options ? "with options " : "", options ? options : "",
			 (user && strlen(user) > 0) ? "for user " : "", user ? user : "");

	if (options)
		for (i = 0; options[i]; i++)
			/* count options */
			if (options[i] == '=')
				connect_params++;

	if (user && strlen(user) > 0)
		connect_params++;
	if (passwd && strlen(passwd) > 0)
		connect_params++;

	/* allocate enough space for all connection parameters */
	conn_keywords = (const char **) ecpg_alloc((connect_params + 1) * sizeof(char *), lineno);
	conn_values = (const char **) ecpg_alloc(connect_params * sizeof(char *), lineno);
	if (conn_keywords == NULL || conn_values == NULL)
	{
		if (host)
			ecpg_free(host);
		if (port)
			ecpg_free(port);
		if (options)
			ecpg_free(options);
		if (realname)
			ecpg_free(realname);
		if (dbname)
			ecpg_free(dbname);
		if (conn_keywords)
			ecpg_free(conn_keywords);
		if (conn_values)
			ecpg_free(conn_values);
		free(this);
		return false;
	}

	i = 0;
	if (realname)
	{
		conn_keywords[i] = "dbname";
		conn_values[i] = realname;
		i++;
	}
	if (host)
	{
		conn_keywords[i] = "host";
		conn_values[i] = host;
		i++;
	}
	if (port)
	{
		conn_keywords[i] = "port";
		conn_values[i] = port;
		i++;
	}
	if (user && strlen(user) > 0)
	{
		conn_keywords[i] = "user";
		conn_values[i] = user;
		i++;
	}
	if (passwd && strlen(passwd) > 0)
	{
		conn_keywords[i] = "password";
		conn_values[i] = passwd;
		i++;
	}
	if (options)
	{
		char	   *str;

		/* options look like this "option1 = value1 option2 = value2 ... */
		/* we have to break up the string into single options */
		for (str = options; *str;)
		{
			int			e,
						a;
			char	   *token1,
					   *token2;

			for (token1 = str; *token1 && *token1 == ' '; token1++);
			for (e = 0; token1[e] && token1[e] != '='; e++);
			if (token1[e])		/* found "=" */
			{
				token1[e] = '\0';
				for (token2 = token1 + e + 1; *token2 && *token2 == ' '; token2++);
				for (a = 0; token2[a] && token2[a] != '&'; a++);
				if (token2[a])	/* found "&" => another option follows */
				{
					token2[a] = '\0';
					str = token2 + a + 1;
				}
				else
					str = token2 + a;

				conn_keywords[i] = token1;
				conn_values[i] = token2;
				i++;
			}
			else
				/* the parser should not be able to create this invalid option */
				str = token1 + e;
		}

	}
	conn_keywords[i] = NULL;	/* terminator */

	this->connection = PQconnectdbParams(conn_keywords, conn_values, 0);

	if (host)
		ecpg_free(host);
	if (port)
		ecpg_free(port);
	if (options)
		ecpg_free(options);
	if (dbname)
		ecpg_free(dbname);
	ecpg_free(conn_values);
	ecpg_free(conn_keywords);

	if (PQstatus(this->connection) == CONNECTION_BAD)
	{
		const char *errmsg = PQerrorMessage(this->connection);
		const char *db = realname ? realname : ecpg_gettext("<DEFAULT>");

		ecpg_log("ECPGconnect: could not open database: %s\n", errmsg);

		ecpg_finish(this);
#ifdef ENABLE_THREAD_SAFETY
		pthread_mutex_unlock(&connections_mutex);
#endif

		ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, db);
		if (realname)
			ecpg_free(realname);

		return false;
	}

	if (realname)
		ecpg_free(realname);

#ifdef ENABLE_THREAD_SAFETY
	pthread_mutex_unlock(&connections_mutex);
#endif

	this->autocommit = autocommit;

	PQsetNoticeReceiver(this->connection, &ECPGnoticeReceiver, (void *) this);

	return true;
}
Ejemplo n.º 18
0
/*
 * Create a new connection structure,
 * open the PostgreSQL connection and set reference count to 1
 */
struct pg_con* db_postgres_new_connection(struct db_id* id)
{
#define PSQL_PARAM(_k, _v) \
	do { \
		keywords[p] = (_k); \
		values[p] = (_v); \
		p++; \
	} while (0);
	struct pg_con* ptr;
	const char *keywords[PSQL_PARAMS_MAX];
	const char *values[PSQL_PARAMS_MAX];
	char *ports;
	char *dbname;
	int p = 0, lend, lenp;

	LM_DBG("db_id = %p\n", id);

	if (!id) {
		LM_ERR("invalid db_id parameter value\n");
		return 0;
	}

	ptr = (struct pg_con*)pkg_malloc(sizeof(struct pg_con));
	if (!ptr) {
		LM_ERR("failed trying to allocated %lu bytes for connection structure."
				"\n", (unsigned long)sizeof(struct pg_con));
		return 0;
	}
	LM_DBG("%p=pkg_malloc(%zu)\n", ptr, sizeof(struct pg_con));

	memset(ptr, 0, sizeof(struct pg_con));
	ptr->ref = 1;

	if (id->parameters) {
		lend = strlen(id->database);
		lenp = strlen(id->parameters);
		dbname = pkg_malloc(7 /* "dbname=" */ +
				lend + 1 /* ? */ + lenp + 1 /* '\0' */);
		if (!dbname) {
			LM_ERR("oom for building database name!\n");
			goto err;
		}
		memcpy(dbname, "dbname=", 7);
		memcpy(dbname + 7, id->database, lend);
		lend += 7;
		dbname[lend] = ' ';
		lend += 1;
		memcpy(dbname + lend, id->parameters, lenp);
		dbname[lend + lenp] = '\0';
		/* convert '&' to spaces */
		for (; dbname[lend] != '\0'; lend++) {
			if (dbname[lend] == '&' && lend > 2 &&
					(dbname[lend-1] != '\\' || (dbname[lend-2] != '\\')))
				dbname[lend] = ' ';
		}
	} else
		dbname = id->database;

	if (id->port) {
		ports = int2str(id->port, 0);
		LM_DBG("opening connection: postgres://xxxx:xxxx@%s:%d/%s\n", ZSW(id->host),
			id->port, ZSW(dbname));
		PSQL_PARAM("port", ports);
	} else {
		ports = NULL;
		LM_DBG("opening connection: postgres://xxxx:xxxx@%s/%s\n", ZSW(id->host),
			ZSW(dbname));
	}

	if (id->host)
		PSQL_PARAM("host", id->host);
	if (id->username)
		PSQL_PARAM("user", id->username);
	if (id->password)
		PSQL_PARAM("password", id->password);

	PSQL_PARAM("dbname", dbname);

	/* force the default timeout */
	if (pq_timeout > 0)
		PSQL_PARAM("connect_timeout", int2str(pq_timeout, 0));
	PSQL_PARAM(0, 0);

	ptr->con = PQconnectdbParams(keywords, values, 1);
	if (dbname != id->database)
		pkg_free(dbname);

	if( (ptr->con == 0) || (PQstatus(ptr->con) != CONNECTION_OK) )
	{
		LM_ERR("%s\n", PQerrorMessage(ptr->con));
		PQfinish(ptr->con);
		goto err;
	}

	ptr->connected = 1;
	ptr->timestamp = time(0);
	ptr->id = id;

	return ptr;

 err:
	if (ptr) {
		LM_ERR("cleaning up %p=pkg_free()\n", ptr);
		pkg_free(ptr);
	}
	return 0;
#undef PSQL_PARAM
}
Ejemplo n.º 19
0
int main(int argc, const char *argv[]) {

  #ifdef _MSC_VER
    #error This code is untested on the Windows platform
    WSAStartup();
  #endif


// Note that specifying "host":"localhost" is *not* equivalent to the default behaviour,
// which is to use a 'peer' connection.
// Network connections and peer connections have different permissions properties.
// We assume testuser allows only network connections.

  const char * const keywords[] = { "application_name",
                                    "host",
                                    "user",
                                    "password",
                                    "dbname",
                                    NULL };

  const char * const values[]   = { "libpqhw",     // application_name // TODO use CMake config.h name string
                                    "localhost",   // host
                                    "testuser",    // user
                                    "testuser",    // password (yes, hard-coded)
                                    "my_database", // dbname
                                    NULL };


  BOOST_STATIC_ASSERT(( sizeof keywords == sizeof values )); // Postgres won't do the equivalent runtime check

  PGconn * const conn = PQconnectdbParams(keywords,values,0);

  BOOST_ASSERT_MSG( (NULL != conn), "Unexpected error attempting to initiate connection" );

  const ConnStatusType status = PQstatus(conn);

  switch(status) {
    case CONNECTION_OK:
      doStuffWithConnection(conn);
      break;

    case CONNECTION_BAD:
      std::cerr << "Unable to connect. Reason: \n";
      printHorizontalBar(std::cerr);
      std::cerr << '\n';
      std::cerr << PQerrorMessage(conn);
      std::cerr << '\n';
      printHorizontalBar(std::cerr);
      std::cerr << "\n\n";
      break;

    default:
      BOOST_ASSERT_MSG( false, "Invalid connection status" );
      break;
  }

  PQfinish(conn);

  #ifdef _MSC_VER
    WSACleanup();
  #endif

  std::cout << "Terminating\n";

  return 0;
}
Ejemplo n.º 20
0
int pg_con_connect(db_con_t *con)
{
	struct pg_con *pcon;
	struct pg_uri *puri;
	char *port_str;
	int ret, i = 0;
	const char *keywords[10], *values[10];
	char to[16];

	pcon = DB_GET_PAYLOAD(con);
	puri = DB_GET_PAYLOAD(con->uri);

	/* Do not reconnect already connected connections */
	if(pcon->flags & PG_CONNECTED)
		return 0;

	DBG("postgres: Connecting to %.*s:%.*s\n", con->uri->scheme.len,
			ZSW(con->uri->scheme.s), con->uri->body.len, ZSW(con->uri->body.s));

	if(puri->port > 0) {
		port_str = int2str(puri->port, 0);
		keywords[i] = "port";
		values[i++] = port_str;
	} else {
		port_str = NULL;
	}

	if(pcon->con) {
		PQfinish(pcon->con);
		pcon->con = NULL;
	}

	keywords[i] = "host";
	values[i++] = puri->host;
	keywords[i] = "dbname";
	values[i++] = puri->database;
	keywords[i] = "user";
	values[i++] = puri->username;
	keywords[i] = "password";
	values[i++] = puri->password;
	if(pg_timeout > 0) {
		snprintf(to, sizeof(to) - 1, "%d", pg_timeout + 3);
		keywords[i] = "connect_timeout";
		values[i++] = to;
	}

	keywords[i] = values[i] = NULL;

	pcon->con = PQconnectdbParams(keywords, values, 1);

	if(pcon->con == NULL) {
		ERR("postgres: PQconnectdbParams ran out of memory\n");
		goto error;
	}

	if(PQstatus(pcon->con) != CONNECTION_OK) {
		ERR("postgres: %s\n", PQerrorMessage(pcon->con));
		goto error;
	}

	/* Override default notice processor */
	PQsetNoticeProcessor(pcon->con, notice_processor, 0);

#ifdef HAVE_PGSERVERVERSION
	DBG("postgres: Connected. Protocol version=%d, Server version=%d\n",
			PQprotocolVersion(pcon->con), PQserverVersion(pcon->con));
#else
	DBG("postgres: Connected. Protocol version=%d, Server version=%d\n",
			PQprotocolVersion(pcon->con), 0);
#endif

#if defined(SO_KEEPALIVE) && defined(TCP_KEEPIDLE)
	if(pg_keepalive) {
		i = 1;
		if(setsockopt(
				   PQsocket(pcon->con), SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i))
				< 0) {
			LM_WARN("failed to set socket option keepalive\n");
		}
		if(setsockopt(PQsocket(pcon->con), IPPROTO_TCP, TCP_KEEPIDLE,
				   &pg_keepalive, sizeof(pg_keepalive))
				< 0) {
			LM_WARN("failed to set socket option keepidle\n");
		}
	}
#endif

	ret = timestamp_format(pcon->con);
	if(ret == 1 || ret == -1) {
		/* Assume INT8 representation if detection fails */
		pcon->flags |= PG_INT8_TIMESTAMP;
	} else {
		pcon->flags &= ~PG_INT8_TIMESTAMP;
	}

	if(get_oids(con) < 0)
		goto error;

	pcon->flags |= PG_CONNECTED;
	return 0;

error:
	if(pcon->con)
		PQfinish(pcon->con);
	pcon->con = NULL;
	return -1;
}
Ejemplo n.º 21
0
/*
 * Connect to the db again.
 *
 * Note: it's not really all that sensible to use a single-entry password
 * cache if the username keeps changing.  In current usage, however, the
 * username never does change, so one savedPassword is sufficient.  We do
 * update the cache on the off chance that the password has changed since the
 * start of the run.
 */
static PGconn *
_connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
{
	PGconn	   *newConn;
	const char *newdb;
	const char *newuser;
	char	   *password;
	bool		new_pass;

	if (!reqdb)
		newdb = PQdb(AH->connection);
	else
		newdb = reqdb;

	if (!requser || strlen(requser) == 0)
		newuser = PQuser(AH->connection);
	else
		newuser = requser;

	ahlog(AH, 1, "connecting to database \"%s\" as user \"%s\"\n",
		  newdb, newuser);

	password = AH->savedPassword ? pg_strdup(AH->savedPassword) : NULL;

	if (AH->promptPassword == TRI_YES && password == NULL)
	{
		password = simple_prompt("Password: "******"out of memory\n");
	}

	do
	{
		const char *keywords[7];
		const char *values[7];

		keywords[0] = "host";
		values[0] = PQhost(AH->connection);
		keywords[1] = "port";
		values[1] = PQport(AH->connection);
		keywords[2] = "user";
		values[2] = newuser;
		keywords[3] = "password";
		values[3] = password;
		keywords[4] = "dbname";
		values[4] = newdb;
		keywords[5] = "fallback_application_name";
		values[5] = progname;
		keywords[6] = NULL;
		values[6] = NULL;

		new_pass = false;
		newConn = PQconnectdbParams(keywords, values, true);

		if (!newConn)
			exit_horribly(modulename, "failed to reconnect to database\n");

		if (PQstatus(newConn) == CONNECTION_BAD)
		{
			if (!PQconnectionNeedsPassword(newConn))
				exit_horribly(modulename, "could not reconnect to database: %s",
							  PQerrorMessage(newConn));
			PQfinish(newConn);

			if (password)
				fprintf(stderr, "Password incorrect\n");

			fprintf(stderr, "Connecting to %s as %s\n",
					newdb, newuser);

			if (password)
				free(password);

			if (AH->promptPassword != TRI_NO)
				password = simple_prompt("Password: "******"connection needs password\n");

			if (password == NULL)
				exit_horribly(modulename, "out of memory\n");
			new_pass = true;
		}
	} while (new_pass);

	/*
	 * We want to remember connection's actual password, whether or not we got
	 * it by prompting.  So we don't just store the password variable.
	 */
	if (PQconnectionUsedPassword(newConn))
	{
		if (AH->savedPassword)
			free(AH->savedPassword);
		AH->savedPassword = pg_strdup(PQpass(newConn));
	}
	if (password)
		free(password);

	/* check for version mismatch */
	_check_database_version(AH);

	PQsetNoticeProcessor(newConn, notice_processor, NULL);

	return newConn;
}
Ejemplo n.º 22
0
Archivo: repmgr.c Proyecto: fdr/repmgr
static void
do_standby_clone(void)
{
	PGconn 		*conn;
	PGresult	*res;
	char 		sqlquery[QUERY_STR_LEN];

	int			r = 0;
	int			i;
	bool		pg_dir = false;
	char		master_data_directory[MAXLEN];
	char		master_config_file[MAXLEN];
	char		master_hba_file[MAXLEN];
	char		master_ident_file[MAXLEN];

	char		master_control_file[MAXLEN];
	char		local_control_file[MAXLEN];

	const char	*first_wal_segment = NULL;
	const char	*last_wal_segment = NULL;

	char	master_version[MAXVERSIONSTR];

	/* if dest_dir hasn't been provided, initialize to current directory */
	if (dest_dir == NULL)
	{
		dest_dir = malloc(5);
		strcpy(dest_dir, ".");
	}

	/* Check this directory could be used as a PGDATA dir */
	switch (check_dir(dest_dir))
	{
	case 0:
		/* dest_dir not there, must create it */
		if (verbose)
			printf(_("creating directory %s ... "), dest_dir);
		fflush(stdout);

		if (!create_directory(dest_dir))
		{
			fprintf(stderr, _("%s: couldn't create directory %s ... "),
			        progname, dest_dir);
			return;
		}
		break;
	case 1:
		/* Present but empty, fix permissions and use it */
		if (verbose)
			printf(_("fixing permissions on existing directory %s ... "),
			       dest_dir);
		fflush(stdout);

		if (!set_directory_permissions(dest_dir))
		{
			fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
			        progname, dest_dir, strerror(errno));
			return;
		}
		break;
	case 2:
		/* Present and not empty */
		fprintf(stderr,
		        _("%s: directory \"%s\" exists but is not empty\n"),
		        progname, dest_dir);

		pg_dir = is_pg_dir(dest_dir);
		if (pg_dir && !force)
		{
			fprintf(stderr, _("\nThis looks like a PostgreSQL directroy.\n"
			                  "If you are sure you want to clone here, "
			                  "please check there is no PostgreSQL server "
			                  "running and use the --force option\n"));
			return;
		}
		else if (pg_dir && force)
		{
			/* Let it continue */
			break;
		}
		else
			return;
	default:
		/* Trouble accessing directory */
		fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
		        progname, dest_dir, strerror(errno));
	}

	/* Connection parameters for master only */
	keywords[0] = "host";
	values[0] = host;
	keywords[1] = "port";
	values[1] = masterport;

	/* We need to connect to check configuration and start a backup */
	conn = PQconnectdbParams(keywords, values, true);
	if (!conn)
	{
		fprintf(stderr, _("%s: could not connect to master\n"),
		        progname);
		return;
	}

	/* primary should be v9 or better */
	pg_version(conn, master_version);
	if (strcmp(master_version, "") == 0)
	{
		PQfinish(conn);
		fprintf(stderr, _("%s needs master to be PostgreSQL 9.0 or better\n"), progname);
		return;
	}

	/* Check we are cloning a primary node */
	if (is_standby(conn))
	{
		PQfinish(conn);
		fprintf(stderr, "\nThe command should clone a primary node\n");
		return;
	}

	/* And check if it is well configured */
	if (!guc_setted(conn, "wal_level", "=", "hot_standby"))
	{
		PQfinish(conn);
		fprintf(stderr, _("%s needs parameter 'wal_level' to be set to 'hot_standby'\n"), progname);
		return;
	}
	if (!guc_setted(conn, "wal_keep_segments", ">=", wal_keep_segments))
	{
		PQfinish(conn);
		fprintf(stderr, _("%s needs parameter 'wal_keep_segments' to be set to %s or greater\n"), wal_keep_segments, progname);
		return;
	}
	if (!guc_setted(conn, "archive_mode", "=", "on"))
	{
		PQfinish(conn);
		fprintf(stderr, _("%s needs parameter 'archive_mode' to be set to 'on'\n"), progname);
		return;
	}

	if (verbose)
		printf(_("Succesfully connected to primary. Current installation size is %s\n"), get_cluster_size(conn));

	/* Check if the tablespace locations exists and that we can write to them */
	sprintf(sqlquery, "select spclocation from pg_tablespace where spcname not in ('pg_default', 'pg_global')");
	res = PQexec(conn, sqlquery);
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, "Can't get info about tablespaces: %s\n", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return;
	}
	for (i = 0; i < PQntuples(res); i++)
	{
		char *tblspc_dir = NULL;

		strcpy(tblspc_dir, PQgetvalue(res, i, 0));
		/* Check this directory could be used as a PGDATA dir */
		switch (check_dir(tblspc_dir))
		{
		case 0:
			/* tblspc_dir not there, must create it */
			if (verbose)
				printf(_("creating directory \"%s\"... "), tblspc_dir);
			fflush(stdout);

			if (!create_directory(tblspc_dir))
			{
				fprintf(stderr, _("%s: couldn't create directory \"%s\"... "),
				        progname, tblspc_dir);
				PQclear(res);
				PQfinish(conn);
				return;
			}
			break;
		case 1:
			/* Present but empty, fix permissions and use it */
			if (verbose)
				printf(_("fixing permissions on existing directory \"%s\"... "),
				       tblspc_dir);
			fflush(stdout);

			if (!set_directory_permissions(tblspc_dir))
			{
				fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
				        progname, tblspc_dir, strerror(errno));
				PQclear(res);
				PQfinish(conn);
				return;
			}
			break;
		case 2:
			/* Present and not empty */
			if (!force)
			{
				fprintf(stderr,
				        _("%s: directory \"%s\" exists but is not empty\n"),
				        progname, tblspc_dir);
				PQclear(res);
				PQfinish(conn);
				return;
			}
		default:
			/* Trouble accessing directory */
			fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
			        progname, tblspc_dir, strerror(errno));
			PQclear(res);
			PQfinish(conn);
			return;
		}
	}

	fprintf(stderr, "Starting backup...\n");

	/* Get the data directory full path and the configuration files location */
	sprintf(sqlquery, "SELECT name, setting "
	        "  FROM pg_settings "
	        " WHERE name IN ('data_directory', 'config_file', 'hba_file', 'ident_file')");
	res = PQexec(conn, sqlquery);
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, "Can't get info about data directory and configuration files: %s\n", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return;
	}
	for (i = 0; i < PQntuples(res); i++)
	{
		if (strcmp(PQgetvalue(res, i, 0), "data_directory") == 0)
			strcpy(master_data_directory, PQgetvalue(res, i, 1));
		else if (strcmp(PQgetvalue(res, i, 0), "config_file") == 0)
			strcpy(master_config_file, PQgetvalue(res, i, 1));
		else if (strcmp(PQgetvalue(res, i, 0), "hba_file") == 0)
			strcpy(master_hba_file, PQgetvalue(res, i, 1));
		else if (strcmp(PQgetvalue(res, i, 0), "ident_file") == 0)
			strcpy(master_ident_file, PQgetvalue(res, i, 1));
		else
			fprintf(stderr, _("uknown parameter: %s"), PQgetvalue(res, i, 0));
	}
	PQclear(res);

	/*
	 * inform the master we will start a backup and get the first XLog filename
	 * so we can say to the user we need those files
	 */
	sprintf(sqlquery, "SELECT pg_xlogfile_name(pg_start_backup('repmgr_standby_clone_%ld'))", time(NULL));
	res = PQexec(conn, sqlquery);
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, "Can't start backup: %s\n", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return;
	}
	first_wal_segment = PQgetvalue(res, 0, 0);
	PQclear(res);

	/*
	 * 1) first move global/pg_control
	 *
	 * 2) then move data_directory ommiting the files we have already moved and pg_xlog
	 *    content
	 *
	 * 3) finally We need to backup configuration files (that could be on other directories, debian
	 * like systems likes to do that), so look at config_file, hba_file and ident_file but we
	 * can omit external_pid_file ;)
	 *
	 * On error we need to return but before that execute pg_stop_backup()
	 */

	/* need to create the global sub directory */
	sprintf(master_control_file, "%s/global/pg_control", master_data_directory);
	sprintf(local_control_file, "%s/global", dest_dir);
	if (!create_directory(local_control_file))
	{
		fprintf(stderr, _("%s: couldn't create directory %s ... "),
		        progname, dest_dir);
		goto stop_backup;
	}

	r = copy_remote_files(host, remote_user, master_control_file, local_control_file, false);
	if (r != 0)
		goto stop_backup;

	r = copy_remote_files(host, remote_user, master_data_directory, dest_dir, true);
	if (r != 0)
		goto stop_backup;

	/*
	 * Copy tablespace locations, i'm doing this separately because i couldn't find and appropiate
	 * rsync option but besides we could someday make all these rsync happen concurrently
	 */
	sprintf(sqlquery, "select spclocation from pg_tablespace where spcname not in ('pg_default', 'pg_global')");
	res = PQexec(conn, sqlquery);
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, "Can't get info about tablespaces: %s\n", PQerrorMessage(conn));
		PQclear(res);
		goto stop_backup;
	}
	for (i = 0; i < PQntuples(res); i++)
	{
		r = copy_remote_files(host, remote_user, PQgetvalue(res, i, 0), PQgetvalue(res, i, 0), true);
		if (r != 0)
			goto stop_backup;
	}

	r = copy_remote_files(host, remote_user, master_config_file, dest_dir, false);
	if (r != 0)
		goto stop_backup;

	r = copy_remote_files(host, remote_user, master_hba_file, dest_dir, false);
	if (r != 0)
		goto stop_backup;

	r = copy_remote_files(host, remote_user, master_ident_file, dest_dir, false);
	if (r != 0)
		goto stop_backup;

stop_backup:
	/* inform the master that we have finished the backup */
	conn = PQconnectdbParams(keywords, values, true);
	if (!conn)
	{
		fprintf(stderr, _("%s: could not connect to master\n"),
		        progname);
		return;
	}

	fprintf(stderr, "Finishing backup...\n");

	sprintf(sqlquery, "SELECT pg_xlogfile_name(pg_stop_backup())");
	res = PQexec(conn, sqlquery);
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, "Can't stop backup: %s\n", PQerrorMessage(conn));
		PQclear(res);
		PQfinish(conn);
		return;
	}
	last_wal_segment = PQgetvalue(res, 0, 0);
	PQclear(res);
	PQfinish(conn);

	/* Now, if the rsync failed then exit */
	if (r != 0)
		return;

	if (verbose)
		printf(_("%s requires primary to keep WAL files %s until at least %s\n"),
		       progname, first_wal_segment, last_wal_segment);

	/* we need to create the pg_xlog sub directory too, i'm reusing a variable here */
	sprintf(local_control_file, "%s/pg_xlog", dest_dir);
	if (!create_directory(local_control_file))
	{
		fprintf(stderr, _("%s: couldn't create directory %s, you will need to do it manually...\n"),
		        progname, dest_dir);
	}

	/* Finally, write the recovery.conf file */
	create_recovery_file(dest_dir);

	/* We don't start the service because we still may want to move the directory */
	return;
}
Ejemplo n.º 23
0
/*
 * Connect to the server. Returns a valid PGconn pointer if connected,
 * or NULL on non-permanent error. On permanent error, the function will
 * call exit(1) directly.
 */
PGconn *
GetConnection(void)
{
	PGconn	   *tmpconn;
	int			argcount = 7;	/* dbname, replication, fallback_app_name,
								 * host, user, port, password */
	int			i;
	const char **keywords;
	const char **values;
	const char *tmpparam;
	bool		need_password;
	PQconninfoOption *conn_opts = NULL;
	PQconninfoOption *conn_opt;
	char	   *err_msg = NULL;

	/*
	 * Merge the connection info inputs given in form of connection string,
	 * options and default values (dbname=replication, replication=true, etc.)
	 */
	i = 0;
	if (connection_string)
	{
		conn_opts = PQconninfoParse(connection_string, &err_msg);
		if (conn_opts == NULL)
		{
			fprintf(stderr, "%s: %s", progname, err_msg);
			exit(1);
		}

		for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
		{
			if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
				argcount++;
		}

		keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
		values = pg_malloc0((argcount + 1) * sizeof(*values));

		for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
		{
			if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
			{
				keywords[i] = conn_opt->keyword;
				values[i] = conn_opt->val;
				i++;
			}
		}
	}
	else
	{
		keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
		values = pg_malloc0((argcount + 1) * sizeof(*values));
	}

	keywords[i] = "dbname";
	values[i] = "replication";
	i++;
	keywords[i] = "replication";
	values[i] = "true";
	i++;
	keywords[i] = "fallback_application_name";
	values[i] = progname;
	i++;

	if (dbhost)
	{
		keywords[i] = "host";
		values[i] = dbhost;
		i++;
	}
	if (dbuser)
	{
		keywords[i] = "user";
		values[i] = dbuser;
		i++;
	}
	if (dbport)
	{
		keywords[i] = "port";
		values[i] = dbport;
		i++;
	}

	/* If -W was given, force prompt for password, but only the first time */
	need_password = (dbgetpassword == 1 && dbpassword == NULL);

	while (true)
	{
		/* Get a new password if appropriate */
		if (need_password)
		{
			if (dbpassword)
				free(dbpassword);
			dbpassword = simple_prompt(_("Password: "******"password";
			values[i] = dbpassword;
		}
		else
		{
			keywords[i] = NULL;
			values[i] = NULL;
		}

		tmpconn = PQconnectdbParams(keywords, values, true);

		/*
		 * If there is too little memory even to allocate the PGconn object
		 * and PQconnectdbParams returns NULL, we call exit(1) directly.
		 */
		if (!tmpconn)
		{
			fprintf(stderr, _("%s: could not connect to server\n"),
					progname);
			exit(1);
		}

		/* If we need a password and -w wasn't given, loop back and get one */
		if (PQstatus(tmpconn) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(tmpconn) &&
			dbgetpassword != -1)
		{
			PQfinish(tmpconn);
			need_password = true;
		}
		else
			break;
	}

	if (PQstatus(tmpconn) != CONNECTION_OK)
	{
		fprintf(stderr, _("%s: could not connect to server: %s\n"),
				progname, PQerrorMessage(tmpconn));
		PQfinish(tmpconn);
		free(values);
		free(keywords);
		if (conn_opts)
			PQconninfoFree(conn_opts);
		return NULL;
	}

	/* Connection ok! */
	free(values);
	free(keywords);
	if (conn_opts)
		PQconninfoFree(conn_opts);

	/*
	 * Ensure we have the same value of integer timestamps as the server we
	 * are connecting to.
	 */
	tmpparam = PQparameterStatus(tmpconn, "integer_datetimes");
	if (!tmpparam)
	{
		fprintf(stderr,
		 _("%s: could not determine server setting for integer_datetimes\n"),
				progname);
		PQfinish(tmpconn);
		exit(1);
	}

#ifdef HAVE_INT64_TIMESTAMP
	if (strcmp(tmpparam, "on") != 0)
#else
	if (strcmp(tmpparam, "off") != 0)
#endif
	{
		fprintf(stderr,
			 _("%s: integer_datetimes compile flag does not match server\n"),
				progname);
		PQfinish(tmpconn);
		exit(1);
	}

	return tmpconn;
}
Ejemplo n.º 24
0
/*
 * Make a database connection with the given parameters.  An
 * interactive password prompt is automatically issued if required.
 *
 * If fail_on_error is false, we return NULL without printing any message
 * on failure, but preserve any prompted password for the next try.
 */
static PGconn *
connectDatabase(const char *dbname, const char *pghost, const char *pgport,
	   const char *pguser, enum trivalue prompt_password, bool fail_on_error)
{
	PGconn	   *conn;
	bool		new_pass;
	const char *remoteversion_str;
	int			my_version;
	static char *password = NULL;

	if (prompt_password == TRI_YES && !password)
		password = simple_prompt("Password: "******"%s: out of memory\n"), progname);
			exit(1);
		}

		keywords[0] = "host";
		values[0] = pghost;
		keywords[1] = "port";
		values[1] = pgport;
		keywords[2] = "user";
		values[2] = pguser;
		keywords[3] = "password";
		values[3] = password;
		keywords[4] = "dbname";
		values[4] = dbname;
		keywords[5] = "fallback_application_name";
		values[5] = progname;
		keywords[6] = "options";
		values[6] = "-c gp_session_role=utility";
		keywords[7] = NULL;
		values[7] = NULL;

		new_pass = false;
		conn = PQconnectdbParams(keywords, values, true);

		free(keywords);
		free(values);

		if (!conn)
		{
			fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
					progname, dbname);
			exit(1);
		}

		if (PQstatus(conn) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(conn) &&
			password == NULL &&
			prompt_password != TRI_NO)
		{
			PQfinish(conn);
			password = simple_prompt("Password: "******"%s: could not connect to database \"%s\": %s\n"),
					progname, dbname, PQerrorMessage(conn));
			exit(1);
		}
		else
		{
			PQfinish(conn);
			return NULL;
		}
	}

	remoteversion_str = PQparameterStatus(conn, "server_version");
	if (!remoteversion_str)
	{
		fprintf(stderr, _("%s: could not get server version\n"), progname);
		exit(1);
	}
	server_version = parse_version(remoteversion_str);
	if (server_version < 0)
	{
		fprintf(stderr, _("%s: could not parse server version \"%s\"\n"),
				progname, remoteversion_str);
		exit(1);
	}

	my_version = parse_version(PG_VERSION);
	if (my_version < 0)
	{
		fprintf(stderr, _("%s: could not parse version \"%s\"\n"),
				progname, PG_VERSION);
		exit(1);
	}

	if (my_version != server_version
		&& (server_version < 80200		/* we can handle back to 8.2 */
			|| server_version > my_version))
	{
		fprintf(stderr, _("server version: %s; %s version: %s\n"),
				remoteversion_str, progname, PG_VERSION);
		if (ignoreVersion)
			fprintf(stderr, _("proceeding despite version mismatch\n"));
		else
		{
			fprintf(stderr, _("aborting because of version mismatch  (Use the -i option to proceed anyway.)\n"));
			exit(1);
		}
	}

	/*
	 * On 7.3 and later, make sure we are not fooled by non-system schemas in
	 * the search path.
	 */
	executeCommand(conn, "SET search_path = pg_catalog");

	return conn;
}
Ejemplo n.º 25
0
/* 
 * parse the given command line options and try to connect to the db.
 *
 * On success, the db conn is returned inside options->db
 */
int handle_options(int argc, char** argv, struct adhoc_opts * options)
{
	char	   *password = NULL;
	char	   *password_prompt = NULL;
	bool new_pass = true;

	parse_psql_options(argc, argv, options);

	if (!options->action_string)
	{
		fprintf(stderr, "Error: Must specify an sql command\n\n");
		usage();
		exit(1);
	}

	if (options->username == NULL)
		password_prompt = pg_strdup(_("Password: "******"Password for user %s: "),
								   options->username);

	if (pset.getPassword == TRI_YES)
		password = simple_prompt(password_prompt, 100, false);

	do
	{
#define PARAMS_ARRAY_SIZE	8
		const char **keywords = 
			pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
		const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));

		keywords[0] = "host";
		values[0] = options->host;
		keywords[1] = "port";
		values[1] = options->port;
		keywords[2] = "user";
		values[2] = options->username;
		keywords[3] = "password";
		values[3] = password;
		keywords[4] = "dbname";
		values[4] = options->dbname;
		keywords[5] = "fallback_application_name";
		values[5] = pset.progname;
		keywords[6] = "client_encoding";
		values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
		keywords[7] = NULL;
		values[7] = NULL;

		new_pass = false;
		pset.db = PQconnectdbParams(keywords, values, true);

		free(keywords);
		free(values);

		if (PQstatus(pset.db) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(pset.db) &&
			password == NULL &&
			pset.getPassword != TRI_NO)
		{
			PQfinish(pset.db);
			password = simple_prompt(password_prompt, 100, false);
			new_pass = true;
		}
	} while (new_pass);

	options->db = pset.db;

	return 0;
}
Ejemplo n.º 26
0
/*
 *
 * main
 *
 */
int
main(int argc, char *argv[])
{
    struct adhoc_opts options;
    int			successResult;
    char	   *password = NULL;
    char	   *password_prompt = NULL;
    bool		new_pass;

    set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql"));

    if (argc > 1)
    {
        if ((strcmp(argv[1], "-?") == 0) || (argc == 2 && (strcmp(argv[1], "--help") == 0)))
        {
            usage(NOPAGER);
            exit(EXIT_SUCCESS);
        }
        if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
        {
            showVersion();
            exit(EXIT_SUCCESS);
        }
    }

#ifdef WIN32
    setvbuf(stderr, NULL, _IONBF, 0);
#endif

    pset.progname = get_progname(argv[0]);

    pset.db = NULL;
    setDecimalLocale();
    pset.encoding = PQenv2encoding();
    pset.queryFout = stdout;
    pset.queryFoutPipe = false;
    pset.copyStream = NULL;
    pset.cur_cmd_source = stdin;
    pset.cur_cmd_interactive = false;

    /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
    pset.popt.topt.format = PRINT_ALIGNED;
    pset.popt.topt.border = 1;
    pset.popt.topt.pager = 1;
    pset.popt.topt.pager_min_lines = 0;
    pset.popt.topt.start_table = true;
    pset.popt.topt.stop_table = true;
    pset.popt.topt.default_footer = true;

    pset.popt.topt.unicode_border_linestyle = UNICODE_LINESTYLE_SINGLE;
    pset.popt.topt.unicode_column_linestyle = UNICODE_LINESTYLE_SINGLE;
    pset.popt.topt.unicode_header_linestyle = UNICODE_LINESTYLE_SINGLE;

    refresh_utf8format(&(pset.popt.topt));

    /* We must get COLUMNS here before readline() sets it */
    pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;

    pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));

    pset.getPassword = TRI_DEFAULT;

    EstablishVariableSpace();

    SetVariable(pset.vars, "VERSION", PG_VERSION_STR);

    /* Default values for variables */
    SetVariableBool(pset.vars, "AUTOCOMMIT");
    SetVariable(pset.vars, "VERBOSITY", "default");
    SetVariable(pset.vars, "SHOW_CONTEXT", "errors");
    SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
    SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
    SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);

    parse_psql_options(argc, argv, &options);

    /*
     * If no action was specified and we're in non-interactive mode, treat it
     * as if the user had specified "-f -".  This lets single-transaction mode
     * work in this case.
     */
    if (options.action == ACT_NOTHING && pset.notty)
    {
        options.action = ACT_FILE;
        options.action_string = NULL;
    }

    /* Bail out if -1 was specified but will be ignored. */
    if (options.single_txn && options.action != ACT_FILE && options.action == ACT_NOTHING)
    {
        fprintf(stderr, _("%s: -1 can only be used in non-interactive mode\n"), pset.progname);
        exit(EXIT_FAILURE);
    }

    if (!pset.popt.topt.fieldSep.separator &&
            !pset.popt.topt.fieldSep.separator_zero)
    {
        pset.popt.topt.fieldSep.separator = pg_strdup(DEFAULT_FIELD_SEP);
        pset.popt.topt.fieldSep.separator_zero = false;
    }
    if (!pset.popt.topt.recordSep.separator &&
            !pset.popt.topt.recordSep.separator_zero)
    {
        pset.popt.topt.recordSep.separator = pg_strdup(DEFAULT_RECORD_SEP);
        pset.popt.topt.recordSep.separator_zero = false;
    }

    if (options.username == NULL)
        password_prompt = pg_strdup(_("Password: "******"Password for user %s: "),
                                   options.username);

    if (pset.getPassword == TRI_YES)
        password = simple_prompt(password_prompt, 100, false);

    /* loop until we have a password if requested by backend */
    do
    {
#define PARAMS_ARRAY_SIZE	8
        const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
        const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));

        keywords[0] = "host";
        values[0] = options.host;
        keywords[1] = "port";
        values[1] = options.port;
        keywords[2] = "user";
        values[2] = options.username;
        keywords[3] = "password";
        values[3] = password;
        keywords[4] = "dbname";
        values[4] = (options.action == ACT_LIST_DB &&
                     options.dbname == NULL) ?
                    "postgres" : options.dbname;
        keywords[5] = "fallback_application_name";
        values[5] = pset.progname;
        keywords[6] = "client_encoding";
        values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
        keywords[7] = NULL;
        values[7] = NULL;

        new_pass = false;
        pset.db = PQconnectdbParams(keywords, values, true);
        free(keywords);
        free(values);

        if (PQstatus(pset.db) == CONNECTION_BAD &&
                PQconnectionNeedsPassword(pset.db) &&
                password == NULL &&
                pset.getPassword != TRI_NO)
        {
            PQfinish(pset.db);
            password = simple_prompt(password_prompt, 100, false);
            new_pass = true;
        }
    } while (new_pass);

    free(password);
    free(password_prompt);

    if (PQstatus(pset.db) == CONNECTION_BAD)
    {
        fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db));
        PQfinish(pset.db);
        exit(EXIT_BADCONN);
    }

    setup_cancel_handler();

    PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);

    SyncVariables();

    if (options.action == ACT_LIST_DB)
    {
        int			success;

        if (!options.no_psqlrc)
            process_psqlrc(argv[0]);

        success = listAllDbs(NULL, false);
        PQfinish(pset.db);
        exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
    }

    if (options.logfilename)
    {
        pset.logfile = fopen(options.logfilename, "a");
        if (!pset.logfile)
            fprintf(stderr, _("%s: could not open log file \"%s\": %s\n"),
                    pset.progname, options.logfilename, strerror(errno));
    }

    /*
     * Now find something to do
     */

    /*
     * process file given by -f
     */
    if (options.action == ACT_FILE)
    {
        if (!options.no_psqlrc)
            process_psqlrc(argv[0]);

        successResult = process_file(options.action_string, options.single_txn, false);
    }

    /*
     * process slash command if one was given to -c
     */
    else if (options.action == ACT_SINGLE_SLASH)
    {
        PsqlScanState scan_state;

        if (pset.echo == PSQL_ECHO_ALL)
            puts(options.action_string);

        scan_state = psql_scan_create();
        psql_scan_setup(scan_state,
                        options.action_string,
                        strlen(options.action_string));

        successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR
                        ? EXIT_SUCCESS : EXIT_FAILURE;

        psql_scan_destroy(scan_state);
    }

    /*
     * If the query given to -c was a normal one, send it
     */
    else if (options.action == ACT_SINGLE_QUERY)
    {
        if (pset.echo == PSQL_ECHO_ALL)
            puts(options.action_string);

        successResult = SendQuery(options.action_string)
                        ? EXIT_SUCCESS : EXIT_FAILURE;
    }

    /*
     * or otherwise enter interactive main loop
     */
    else
    {
        if (!options.no_psqlrc)
            process_psqlrc(argv[0]);

        connection_warnings(true);
        if (!pset.quiet)
            printf(_("Type \"help\" for help.\n\n"));
        initializeInput(options.no_readline ? 0 : 1);
        successResult = MainLoop(stdin);
    }

    /* clean up */
    if (pset.logfile)
        fclose(pset.logfile);
    PQfinish(pset.db);
    setQFout(NULL);

    return successResult;
}
Ejemplo n.º 27
0
int main(int argc, char* argv[]){

     struct qz_config* conf = init_config();

     tagger_pid = tagger_init(conf, argv);
     printf( "tagger_pid = %d\n", tagger_pid);
     signal( SIGTERM, cleanup );

     int j;
     xmlHashTablePtr ht = xmlHashCreate(NBRTESTS);
     struct handler_args hargs[NBRTESTS];
     struct session* s;

     const char* kw[] = { "host", "dbname", "user", "password", 
         "application_name", NULL };
     const char* vals[] = { "localhost", "info", "qz", "42", "qztest", NULL };

     const char* parts[] = { "qz", "one", "two", "three",  NULL };

     for(j=0; j<NBRTESTS; j++){
         fprintf(stderr, "setup_session %d\n", j);
         hargs[j].log = fopen("testsession.log", "w");
         hargs[j].conf = conf;
         hargs[j].uri_parts = parts;

         setup_session(&(hargs[j]), ht, conf);     
         hargs[j].uri_parts = NULL;
     }
     
     s = session_from_hargs(&hargs[NBRTESTS-1], ht, conf);
     s->is_logged_in = true;
     s->logged_in_time = time(NULL);

     s = session_from_hargs(&hargs[NBRTESTS-2], ht, conf);
     s->is_logged_in = true;
     s->logged_in_time = time(NULL);
     s->conn = PQconnectdbParams(kw, vals, 0);

     s = session_from_hargs(&hargs[NBRTESTS-3], ht, conf);
     s->is_logged_in = false;
     s->logged_in_time = time(NULL);
     s->conn = PQconnectdbParams(kw, vals, 0);

     for(j=0; j<NBRTESTS; j++){
         s = session_from_hargs(&hargs[j], ht, conf);
         printf("session_state[%d]:     %s\n", j,
             state_text( get_session_state(&(hargs[j])) ));
         //fclose( hargs[j].log );
     }
     printf("sleeping\n");
     sleep(5);
     printf("fin\n");

     for(j=0; j<100; j++){
         if (s->conn != NULL){
             PQfinish(s->conn);
             s->conn = NULL;
         }
     }
     kill( tagger_pid, 15);
     int status;
     waitpid(tagger_pid, &status, 0);
     fprintf(stderr, "killed tagger pid %d waitpid status = %d\n", 
         tagger_pid, status);

     return 0;
}