Beispiel #1
0
static apr_dbd_t *dbd_pgsql_open(apr_pool_t *pool, const char *params,
                                 const char **error)
{
    apr_dbd_t *sql;
    
    PGconn *conn = PQconnectdb(params);

    /* if there's an error in the connect string or something we get
     * back a * bogus connection object, and things like PQreset are
     * liable to segfault, so just close it out now.  it would be nice
     * if we could give an indication of why we failed to connect... */
    if (PQstatus(conn) != CONNECTION_OK) {
        if (error) {
            *error = apr_pstrdup(pool, PQerrorMessage(conn));
        }
        PQfinish(conn);
        return NULL;
    }

    PQsetNoticeReceiver(conn, null_notice_receiver, NULL);
    PQsetNoticeProcessor(conn, null_notice_processor, NULL);

    sql = apr_pcalloc (pool, sizeof (*sql));

    sql->conn = conn;

    return sql;
}
Beispiel #2
0
static int
_conn_async_connect(connectionObject *self)
{
    PGconn *pgconn;

    self->pgconn = pgconn = PQconnectStart(self->dsn);

    Dprintf("conn_connect: new postgresql connection at %p", pgconn);

    if (pgconn == NULL)
    {
        Dprintf("conn_connect: PQconnectStart(%s) FAILED", self->dsn);
        PyErr_SetString(OperationalError, "PQconnectStart() failed");
        return -1;
    }
    else if (PQstatus(pgconn) == CONNECTION_BAD)
    {
        Dprintf("conn_connect: PQconnectdb(%s) returned BAD", self->dsn);
        PyErr_SetString(OperationalError, PQerrorMessage(pgconn));
        return -1;
    }

    PQsetNoticeProcessor(pgconn, conn_notice_callback, (void*)self);

    /* The connection will be completed banging on poll():
     * First with _conn_poll_connecting() that will finish connection,
     * then with _conn_poll_setup_async() that will do the same job
     * of setup_async(). */

    return 0;
}
CAMLprim value PQsetNoticeProcessor_stub(value v_conn, value v_cb)
{
  np_decr_refcount(get_conn_cb(v_conn));
  set_conn_cb(v_conn, np_new(v_cb));
  PQsetNoticeProcessor(get_conn(v_conn), &notice_ml, get_conn_cb(v_conn));
  return Val_unit;
}
Beispiel #4
0
static int
_conn_sync_connect(connectionObject *self)
{
    PGconn *pgconn;
    int green;

    /* store this value to prevent inconsistencies due to a change
     * in the middle of the function. */
    green = psyco_green();
    if (!green) {
        Py_BEGIN_ALLOW_THREADS;
        self->pgconn = pgconn = PQconnectdb(self->dsn);
        Py_END_ALLOW_THREADS;
        Dprintf("conn_connect: new postgresql connection at %p", pgconn);
    }
    else {
        Py_BEGIN_ALLOW_THREADS;
        self->pgconn = pgconn = PQconnectStart(self->dsn);
        Py_END_ALLOW_THREADS;
        Dprintf("conn_connect: new green postgresql connection at %p", pgconn);
    }

    if (pgconn == NULL)
    {
        Dprintf("conn_connect: PQconnectdb(%s) FAILED", self->dsn);
        PyErr_SetString(OperationalError, "PQconnectdb() failed");
        return -1;
    }
    else if (PQstatus(pgconn) == CONNECTION_BAD)
    {
        Dprintf("conn_connect: PQconnectdb(%s) returned BAD", self->dsn);
        PyErr_SetString(OperationalError, PQerrorMessage(pgconn));
        return -1;
    }

    PQsetNoticeProcessor(pgconn, conn_notice_callback, (void*)self);

    /* if the connection is green, wait to finish connection */
    if (green) {
        if (0 > pq_set_non_blocking(self, 1)) {
            return -1;
        }
        if (0 != psyco_wait(self)) {
            return -1;
        }
    }

    /* From here the connection is considered ready: with the new status,
     * poll() will use PQisBusy instead of PQconnectPoll.
     */
    self->status = CONN_STATUS_READY;

    if (conn_setup(self, self->pgconn) == -1) {
        return -1;
    }

    return 0;
}
Beispiel #5
0
VALUE db_postgres_adapter_initialize(VALUE self, VALUE options) {
    char *connection_info;
    VALUE db, user, pass, host, port, ssl;
    Adapter *a = db_postgres_adapter_handle(self);

    if (TYPE(options) != T_HASH)
        rb_raise(eSwiftArgumentError, "options needs to be a hash");

    db   = rb_hash_aref(options, ID2SYM(rb_intern("db")));
    user = rb_hash_aref(options, ID2SYM(rb_intern("user")));
    pass = rb_hash_aref(options, ID2SYM(rb_intern("password")));
    host = rb_hash_aref(options, ID2SYM(rb_intern("host")));
    port = rb_hash_aref(options, ID2SYM(rb_intern("port")));
    ssl  = rb_hash_aref(options, ID2SYM(rb_intern("ssl")));

    if (NIL_P(db))
        rb_raise(eSwiftConnectionError, "Invalid db name");
    if (NIL_P(host))
        host = rb_str_new2("127.0.0.1");
    if (NIL_P(port))
        port = rb_str_new2("5432");
    if (NIL_P(user))
        user = sUser;

    if (!NIL_P(ssl) && TYPE(ssl) != T_HASH)
            rb_raise(eSwiftArgumentError, "ssl options needs to be a hash");

    connection_info = (char *)malloc(4096);
    snprintf(connection_info, 4096, "dbname='%s' user='******' password='******' host='%s' port='%s'",
        CSTRING(db), CSTRING(user), CSTRING(pass), CSTRING(host), CSTRING(port));

    if (!NIL_P(ssl)) {
        append_ssl_option(connection_info, 4096, ssl, "sslmode",      "allow");
        append_ssl_option(connection_info, 4096, ssl, "sslcert",      0);
        append_ssl_option(connection_info, 4096, ssl, "sslkey",       0);
        append_ssl_option(connection_info, 4096, ssl, "sslrootcert",  0);
        append_ssl_option(connection_info, 4096, ssl, "sslcrl",       0);
    }

    a->connection = PQconnectdb(connection_info);
    free(connection_info);

    if (!a->connection)
        rb_raise(eSwiftRuntimeError, "unable to allocate database handle");
    if (PQstatus(a->connection) == CONNECTION_BAD)
        rb_raise(eSwiftConnectionError, PQerrorMessage(a->connection));

    PQsetNoticeProcessor(a->connection, (PQnoticeProcessor)db_postgres_adapter_notice, (void*)self);
    PQsetClientEncoding(a->connection, "utf8");
    return self;
}
Beispiel #6
0
int pg_createconn(ClipMachine* mp){
	char* pghost	= _clip_parc(mp,2);
	char* pgport	= _clip_parc(mp,3);
	char* login		= _clip_parc(mp,4);
	char* pwd		= _clip_parc(mp,5);
	char* dbName	= _clip_parc(mp,6);
	char* pgtty		= _clip_parc(mp,7);
	char* pgoptions = _clip_parc(mp,8);
	char* trpars	= _clip_parc(mp,10);
	PGconn* tmpconn;
	PGresult* res;
	PG_CONN* conn;
	char str[256];

	tmpconn = PQsetdbLogin(pghost,pgport,pgoptions,pgtty,dbName,login,pwd);
	if(PQstatus(tmpconn)!=CONNECTION_OK){
		_clip_trap_err(mp,0,0,0,subsys,ER_CONNECT,PQerrorMessage(tmpconn));
		return -1;
	}
	conn = malloc(sizeof(PG_CONN));
	memset(conn,0,sizeof(PG_CONN));
	conn->conn = tmpconn;
	conn->vtbl = &vtbl;
	res = PQexec(tmpconn,"SET DATESTYLE='ISO'");
	if(PQresultStatus(res) != PGRES_COMMAND_OK){
		_clip_trap_err(mp,0,0,0,subsys,ER_BADSTATEMENT,
			PQresultErrorMessage(res));
		return -1;
	}

	if(!trpars)
		trpars = _clip_fetch_item(mp, _clip_hashstr("PG_ISOLATION_LEVEL"));
	if(!trpars)
		trpars = _clip_fetch_item(mp, _clip_hashstr("SQL_ISOLATION_LEVEL"));
	if(trpars){
		snprintf(str,sizeof(str),"set session characteristics as transaction isolation level %s",trpars);
		res = PQexec(tmpconn,str);
		if(PQresultStatus(res) != PGRES_COMMAND_OK){
			_clip_trap_err(mp,0,0,0,subsys,ER_BADSTATEMENT,
				PQresultErrorMessage(res));
			return -1;
		}
	}

	PQsetNoticeProcessor(tmpconn, notice_processor, NULL);

	return _clip_store_c_item(mp,(void*)conn,_C_ITEM_TYPE_SQL,destroy_pg_conn);
}
Beispiel #7
0
static NEOERR* pgsql_mdb_connect(const char* dsn, mdb_conn **rconn)
{
    struct _mdb_conn_pgsql* conn;
  
    *rconn = NULL;
    conn = calloc(1, sizeof(struct _mdb_conn_pgsql));
    if (!conn) return nerr_raise(NERR_NOMEM, "calloc for ms connect failure");
    *rconn = (mdb_conn*)conn;

    conn->pg = PQconnectdb(dsn);
    if (PQstatus(conn->pg) == CONNECTION_BAD)
        return nerr_raise(NERR_SYSTEM, "connect to %s failure %s",
                          dsn, PQerrorMessage(conn->pg));
    PQsetNoticeProcessor(conn->pg, notices_black_hole, NULL);

    return STATUS_OK;
}
Beispiel #8
0
/*
** Connects to a data source.
*/
static int env_connect (lua_State *L) {
	const char *sourcename = luaL_checkstring(L, 2);
	const char *username = luaL_optstring(L, 3, NULL);
	const char *password = luaL_optstring(L, 4, NULL);
	const char *pghost = luaL_optstring(L, 5, NULL);
	const char *pgport = luaL_optstring(L, 6, NULL);
	PGconn *conn;
	getenvironment (L);	/* validate environment */
	conn = PQsetdbLogin(pghost, pgport, NULL, NULL, sourcename, username, password);

	if (PQstatus(conn) == CONNECTION_BAD) {
		int rc = luasql_failmsg(L, "error connecting to database. PostgreSQL: ", PQerrorMessage(conn));
		PQfinish(conn);
		return rc;
	}
	PQsetNoticeProcessor(conn, notice_processor, NULL);
	return create_connection(L, 1, conn);
}
int pgsql_connected() 
{
	static int connected = 0;
	PGresult *res;

	if (connected != 0) {
		if (PQstatus(pgsql) != CONNECTION_OK) {
			PQreset(pgsql);
			res = PQexec(pgsql, "SET timezone TO 'utc';");
			PQclear(res);
		}
		return connected;
	}

	struct stat buf;
	if (stat(pgsql_config_file, &buf) != 0) {
		eprintf(DEBUG_ERROR, "stat config file: %s (%d)", strerror(errno), errno);
		eprintf(DEBUG_GENERAL, "missing %s config file", pgsql_config_file);
		return connected;
	}
	if (!S_ISREG(buf.st_mode)) {
		eprintf(DEBUG_GENERAL, "missing %s config file", pgsql_config_file);
		return connected;
	}
	setenv("PGSERVICEFILE", pgsql_config_file, 0);

	char dsnbuf[1024];
	snprintf(dsnbuf, sizeof(dsnbuf), "service = %s", pgsql_config_name);
	pgsql = PQconnectdb(dsnbuf);
	if (PQstatus(pgsql) != CONNECTION_OK) {
		eprintf(DEBUG_ERROR,  "pgsql error: %s", PQerrorMessage(pgsql));
		return connected;
	}
	PQsetNoticeProcessor(pgsql, pgsqlNoticeProcessor, NULL);

	res = PQexec(pgsql, "SET timezone TO 'utc';");
	PQclear(res);

	connected = 1;

	return connected;
}
Beispiel #10
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);
}
Beispiel #11
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;
}
Beispiel #12
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], "--help") == 0 || strcmp(argv[1], "-?") == 0)
		{
			usage();
			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

	setup_cancel_handler();

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

	pset.db = NULL;
	setDecimalLocale();
	pset.encoding = PQenv2encoding();
	pset.queryFout = stdout;
	pset.queryFoutPipe = false;
	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.start_table = true;
	pset.popt.topt.stop_table = true;
	pset.popt.default_footer = true;
	/* 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, "PROMPT1", DEFAULT_PROMPT1);
	SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
	SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);

	parse_psql_options(argc, argv, &options);

	if (!pset.popt.topt.fieldSep)
		pset.popt.topt.fieldSep = pg_strdup(DEFAULT_FIELD_SEP);
	if (!pset.popt.topt.recordSep)
		pset.popt.topt.recordSep = pg_strdup(DEFAULT_RECORD_SEP);

	if (options.username == NULL)
		password_prompt = pg_strdup(_("Password: "******"Password for user %s: ")) - 2 +
								 strlen(options.username) + 1);
		sprintf(password_prompt, _("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
	{
		new_pass = false;
		pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
					options.action == ACT_LIST_DB && options.dbname == NULL ?
							   "postgres" : options.dbname,
							   options.username, password);

		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);
	}

	PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);

	SyncVariables();

	if (options.action == ACT_LIST_DB)
	{
		int			success = listAllDbs(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 && strcmp(options.action_string, "-") != 0)
	{
		if (!options.no_psqlrc)
			process_psqlrc(argv[0]);

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

	/*
	 * 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();
		if (!pset.quiet && !pset.notty)
			printf(_("Type \"help\" for help.\n\n"));
		if (!pset.notty)
			initializeInput(options.no_readline ? 0 : 1);
		if (options.action_string)		/* -f - was used */
			pset.inputfile = "<stdin>";

		successResult = MainLoop(stdin);
	}

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

	return successResult;
}
Beispiel #13
0
int main(int argc, char* argv[])
{
    char sPGhost[26], sPGport[26], sPGdb[26], sPGuser[26], sPGpass[26];
    printf("Postgres connection settings\n Host>");
    scanf("%s", sPGhost);
    printf(" Port>");
    scanf("%s", sPGport);
    printf(" Base>");
    scanf("%s", sPGdb);
    printf(" User>");
    scanf("%s", sPGuser);
    printf(" Pass>");
    scanf("%s", sPGpass);

    ///////////////////////////////
    ///////PGSQL Connect///////////
    ///////////////////////////////
    PGconn* mPGconn = NULL;
    mPGconn = PQsetdbLogin(sPGhost, sPGport, NULL, NULL, sPGdb, sPGuser, sPGpass);

    if (PQstatus(mPGconn) != CONNECTION_OK)
    {
        printf("Could not connect to Postgre database at [%s]: \n %s\n", sPGhost, PQerrorMessage(mPGconn));
        PQfinish(mPGconn);
        return 1;
    }
    else
    {
        printf("Connected to Postgre database at [%s]\n", sPGhost);
        printf(" PostgreSQL server ver: [%d]\n\n", PQserverVersion(mPGconn));
    }

    /// Set dummy notice processor
    PQsetNoticeProcessor(mPGconn, pg_notice, mPGconn);

    ///////////////////////////////
    ///////MySQL Connect///////////
    ///////////////////////////////
    MYSQL* mysqlInit;
    mysqlInit = mysql_init(NULL);
    if (!mysqlInit)
    {
        printf("Could not initialize Mysql connection\n");
        return 1;
    }

    char sMYhost[26], sMYdb[26], sMYuser[26], sMYpass[26];
    int    iMYport;
    printf("Mysql connection settings \n Host>");
    scanf("%s", sMYhost);
    printf(" Port>");
    scanf("%d", &iMYport);
    printf(" Base>");
    scanf("%s", sMYdb);
    printf(" User>");
    scanf("%s", sMYuser);
    printf(" Pass>");
    scanf("%s", sMYpass);

    mysql_options(mysqlInit, MYSQL_SET_CHARSET_NAME, "utf8");

    MYSQL* mMysql;
    mMysql = mysql_real_connect(mysqlInit, sMYhost, sMYuser,  sMYpass, sMYdb, iMYport, NULL, 0);

    if (mMysql)
    {
        printf("Connected to MySQL database at [%s] \n", sMYhost);
        printf(" MySQL client library: [%s] \n", mysql_get_client_info());
        printf(" MySQL server ver: [%s] \n\n", mysql_get_server_info(mMysql));
    }
    else
    {
        printf("Could not connect to MySQL database at [%s]:\n %s\n", sMYhost , mysql_error(mysqlInit));
        mysql_close(mysqlInit);
        return 1;
    }

    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    MYSQL_RES* result = NULL;
    MYSQL_ROW row;
    MYSQL_FIELD* fields = NULL;
    uint64 rowCount = 0;
    uint32 fieldCount = 0;
    result = mysql_list_tables(mMysql , NULL);
    rowCount   = mysql_num_rows(result);

    /***********************/
    /* get list of tables  */
    /***********************/
    T_TableList mTableList;
    mTableList.reserve((size_t)rowCount);
    while ((row = mysql_fetch_row(result)) != NULL)
    {
        for (uint32 i = 0; i < mysql_num_fields(result); i++)
        {
            mTableList.push_back(row[i]);
        }
    }
    mysql_free_result(result);

    /****************************************/
    /* convert filed type and default type  */
    /****************************************/
    T_Table m_Table;
    TDataBase m_DataBase_Map;
    m_DataBase_Map.clear();
    for (uint32 j = 0; j < mTableList.size(); ++j)
    {
        result     = mysql_list_fields(mMysql, mTableList[j].c_str(), NULL);
        fieldCount = mysql_num_fields(result);
        fields     = mysql_fetch_fields(result);

        for (uint32 i = 0; i < fieldCount; ++i)
        {
            sField mfield;
            mfield.name   = fields[i].name;
            if (!fields[i].def)
            {
                mfield.def = "NULL";
            }
            else if (!strcmp(fields[i].def, "0000-00-00 00:00:00"))
            {
                /// Convert MySQL Default timestamp to PGSQL Default timestamp
                mfield.def.append("'1970-01-01 00:00:00'");
            }
            else
            {
                /// Append '
                mfield.def.append("'");
                mfield.def.append(fields[i].def);;
                mfield.def.append("'");
            }
            mfield.type = ConvertNativeType(fields[i].type, fields[i].length);
            mfield.flags  = fields[i].flags;
            m_Table.push_back(mfield);
        }
        m_DataBase_Map[mTableList[j]] = m_Table;
        m_Table.clear();
        mysql_free_result(result);
    }

    /******************************************/
    /* Conversion of the layout of the tables */
    /******************************************/

    uint32 count = 0;
    TDataBase::const_iterator citr;
    for (citr = m_DataBase_Map.begin(); citr != m_DataBase_Map.end(); ++citr)
    {
        ostringstream sql_str;
        sql_str << "DROP TABLE IF EXISTS " << (*citr).first.c_str() << ";\n";
        sql_str << "CREATE TABLE " << (*citr).first.c_str() << "(\n";

        T_Table::const_iterator v_iter;
        ostringstream prim_key_str;
        ostringstream index_str;
        for (v_iter = (*citr).second.begin();
                v_iter != (*citr).second.end();
                ++v_iter)
        {
            sql_str << " " << (*v_iter).name;
            if (((*v_iter).flags & AUTO_INCREMENT_FLAG) != 0)
            {
                /// AUTO_INCREMENT fields not have "default" data
                sql_str << " bigserial";
            }
            else
            {
                sql_str << " " << (*v_iter).type;
                sql_str << " default " << (*v_iter).def;
            }
            /// IF column have PRIMARY KEY flag then use column in PRIMARY KEY
            if (IS_PRI_KEY((*v_iter).flags) != 0)
            {
                if (prim_key_str.str().size())
                    prim_key_str << ", ";
                else
                {
                    prim_key_str << "ALTER TABLE ";
                    prim_key_str << (*citr).first.c_str();
                    prim_key_str << " ADD CONSTRAINT pk_";
                    prim_key_str << (*citr).first.c_str();
                    prim_key_str << "_";
                    prim_key_str << (*v_iter).name;
                    prim_key_str << " PRIMARY KEY (";
                }
                prim_key_str << (*v_iter).name;
            }
            else if (((*v_iter).flags & MULTIPLE_KEY_FLAG) != 0)
            {
                /// IF column have INDEX flag then create INDEX
                index_str << "CREATE INDEX  idx_";
                index_str << (*citr).first.c_str();
                index_str << "_";
                index_str << (*v_iter).name;
                index_str << " ON ";
                index_str << (*citr).first.c_str();
                index_str << " USING btree (";
                index_str << (*v_iter).name;
                index_str << ");\n";
            }
            else if (((*v_iter).flags & UNIQUE_KEY_FLAG) != 0)
            {
                /// IF column have UNIQUE INDEX flag then create INDEX
                index_str << "CREATE UNIQUE INDEX  uidx_";
                index_str << (*citr).first.c_str();
                index_str << "_";
                index_str << (*v_iter).name;
                index_str << " ON ";
                index_str << (*citr).first.c_str();
                index_str << " USING btree (";
                index_str << (*v_iter).name;
                index_str << ");\n";
            }
            /// don't output "," for last column
            if (v_iter + 1 != (*citr).second.end())
                sql_str << ",\n";
            else
                sql_str << "\n";
        }
        sql_str << ")\n";

        /// Out Table structure
        PG_Exec_str(sql_str.str(), mPGconn);

        /// out PRIMARY KEY
        if (prim_key_str.str().size())
        {
            prim_key_str << ")";
            PG_Exec_str(prim_key_str.str(), mPGconn);
        }

        /// out INDEX's
        if (index_str.str().size())
            PG_Exec_str(index_str.str(), mPGconn);

        ++count;
        printf("Convert [%d] tables...\r", count);
    }
    printf("Completed the conversion of [%d] tables!\n", count);

    /****************/
    /* Copying data */
    /****************/

    count = 0;
    for (uint32 j = 0; j < mTableList.size(); ++j)
    {
        ostringstream sql_str;
        sql_str << "SELECT * FROM ";
        sql_str << mTableList[j].c_str();

        if (mysql_query(mysqlInit, sql_str.str().c_str()))
            continue;
        if (!(result = mysql_store_result(mysqlInit)))
            continue;

        while ((row = mysql_fetch_row(result)) != NULL)
        {
            ostringstream insert_str;
            insert_str << "INSERT INTO ";
            insert_str << mTableList[j].c_str();
            insert_str << " VALUES (";

            fieldCount = mysql_num_fields(result);
            fields     = mysql_fetch_fields(result);
            for (uint32 i = 0 ; i < fieldCount ; ++i)
            {
                if (!row[i])
                    insert_str << "NULL";
                else
                {
                    if (IsNeeedEscapeString(fields[i].type))
                    {
                        string field_str = row[i];
                        PG_Escape_Str(field_str);
                        insert_str << "E'";
                        insert_str << field_str.c_str();
                        insert_str << "'";
                    }
                    else if (!strcmp(row[i], "0000-00-00 00:00:00"))
                    {
                        /// Convert MySQL  timestamp to PGSQL timestamp
                        insert_str << "'1970-01-01 00:00:00'";
                    }
                    else
                    {
                        insert_str << "'";
                        insert_str << row[i];
                        insert_str << "'";
                    }
                }

                /// don't output "," for last column
                if (i + 1 != fieldCount)
                    insert_str << ",";
                else
                    insert_str << ")\n";
            }
            PG_Exec_str(insert_str.str(), mPGconn);
        }
        mysql_free_result(result);
        ++count;
        printf("Copied data from [%d] tables...\r", count);
    }
    printf("Finished copying the data from [%d] tables!\n", count);
    mTableList.clear();
    m_DataBase_Map.clear();

    /// Close connections
    mysql_close(mMysql);
    PQfinish(mPGconn);

    printf("end\n");
    return 0;

}
Beispiel #14
0
Datei: db.c Projekt: caomw/grass
int db__driver_open_database(dbHandle * handle)
{
    char buf[500];
    const char *name, *schema, *user, *password;
    dbConnection connection;
    PGCONN pgconn;
    PGresult *res;
    int row;

    db_get_connection(&connection);
    name = db_get_handle_dbname(handle);

    /* if name is empty use connection.databaseName */
    if (strlen(name) == 0)
	name = connection.databaseName;

    G_debug(3,
	    "db_driver_open_database(): driver=pg database definition = '%s'",
	    name);

    if (parse_conn(name, &pgconn) == DB_FAILED) {
	db_d_report_error();
	return DB_FAILED;
    }

    G_debug(3,
	    "db_driver_open_database(): host = %s, port = %s, options = %s, tty = %s, "
	    "dbname = %s, user = %s, password = %s, "
	    "schema = %s", pgconn.host, pgconn.port, pgconn.options,
	    pgconn.tty, pgconn.dbname, pgconn.user, pgconn.password,
	    pgconn.schema);

    db_get_login("pg", name, &user, &password);

    pg_conn = PQsetdbLogin(pgconn.host, pgconn.port, pgconn.options, pgconn.tty,
			   pgconn.dbname, user, password);
    
    if (PQstatus(pg_conn) == CONNECTION_BAD) {
	db_d_append_error("%s\n%s",
			  _("Connection failed."),
			  PQerrorMessage(pg_conn));
	db_d_report_error();
	PQfinish(pg_conn);
	return DB_FAILED;
    }

    /* set schema */
    schema = db_get_handle_dbschema(handle);

    /* Cannot use default schema because link to table can point to
       different database */
    /*
       if ( schema ) 
       schema = connection.schemaName;
    */

    if (pgconn.schema) {
	schema = pgconn.schema;
    }

    /* set path to the schema */
    if (schema && strlen(schema) > 0) {
	sprintf(buf, "set search_path to %s", schema);
	res = PQexec(pg_conn, buf);

	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
	    db_d_append_error("%s %s",
			      _("Unable to set schema:"),
			      schema);
	    db_d_report_error();
	    PQclear(res);
	    return DB_FAILED;
	}
    }

    /* read internal codes */
    res = PQexec(pg_conn,
		 "select oid, typname from pg_type where typname in ( "
		 "'bit', 'int2', 'int4', 'int8', 'serial', 'oid', "
		 "'float4', 'float8', 'numeric', "
		 "'char', 'bpchar', 'varchar', 'text', "
		 "'time', 'date', 'timestamp', "
		 "'bool', 'geometry', 'topogeometry') order by oid");
    
    if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
	db_d_append_error(_("Unable to select data types"));
	db_d_report_error();
	PQclear(res);
	return DB_FAILED;
    }

    pg_ntypes = PQntuples(res);
    pg_types = G_realloc(pg_types, 2 * pg_ntypes * sizeof(int));

    for (row = 0; row < pg_ntypes; row++) {
	int pgtype, type;

	pgtype = atoi(PQgetvalue(res, row, 0));

	pg_types[row][0] = pgtype;

        G_debug(3, "row = %d value = %s", row, PQgetvalue(res, row, 1));
	if (strcmp(PQgetvalue(res, row, 1), "bit") == 0)
	    type = PG_TYPE_BIT;
	else if (strcmp(PQgetvalue(res, row, 1), "int2") == 0)
	    type = PG_TYPE_INT2;
	else if (strcmp(PQgetvalue(res, row, 1), "int4") == 0)
	    type = PG_TYPE_INT4;
	else if (strcmp(PQgetvalue(res, row, 1), "int8") == 0)
	    type = PG_TYPE_INT8;
	else if (strcmp(PQgetvalue(res, row, 1), "serial") == 0)
	    type = PG_TYPE_SERIAL;
	else if (strcmp(PQgetvalue(res, row, 1), "oid") == 0)
	    type = PG_TYPE_OID;
	else if (strcmp(PQgetvalue(res, row, 1), "float4") == 0)
	    type = PG_TYPE_FLOAT4;
	else if (strcmp(PQgetvalue(res, row, 1), "float8") == 0)
	    type = PG_TYPE_FLOAT8;
	else if (strcmp(PQgetvalue(res, row, 1), "numeric") == 0)
	    type = PG_TYPE_NUMERIC;
	else if (strcmp(PQgetvalue(res, row, 1), "char") == 0)
	    type = PG_TYPE_CHAR;
	else if (strcmp(PQgetvalue(res, row, 1), "bpchar") == 0)
	    type = PG_TYPE_BPCHAR;
	else if (strcmp(PQgetvalue(res, row, 1), "varchar") == 0)
	    type = PG_TYPE_VARCHAR;
	else if (strcmp(PQgetvalue(res, row, 1), "text") == 0)
	    type = PG_TYPE_TEXT;
	else if (strcmp(PQgetvalue(res, row, 1), "date") == 0)
	    type = PG_TYPE_DATE;
	else if (strcmp(PQgetvalue(res, row, 1), "time") == 0)
	    type = PG_TYPE_TIME;
	else if (strcmp(PQgetvalue(res, row, 1), "timestamp") == 0)
	    type = PG_TYPE_TIMESTAMP;
	else if (strcmp(PQgetvalue(res, row, 1), "bool") == 0)
	    type = PG_TYPE_BOOL;
	else if (strcmp(PQgetvalue(res, row, 1), "geometry") == 0)
	    type = PG_TYPE_POSTGIS_GEOM;
	else if (strcmp(PQgetvalue(res, row, 1), "topogeometry") == 0)
	    type = PG_TYPE_POSTGIS_TOPOGEOM;
	else
	    type = PG_TYPE_UNKNOWN;

	G_debug(3, "db_driver_open_database(): pgtype = %d, name = %s -> type = %d", pgtype,
		PQgetvalue(res, row, 1), type);
	pg_types[row][1] = type;
    }
    
    /* print notice messages only on verbose level */
    PQsetNoticeProcessor(pg_conn, notice_processor, NULL);
    
    PQclear(res);

    return DB_OK;
}
bool EpollPostgresql::syncConnectInternal(bool infinityTry)
{
    conn=PQconnectdb(strCoPG);
    ConnStatusType connStatusType=PQstatus(conn);
    if(connStatusType==CONNECTION_BAD)
    {
        std::string lastErrorMessage=errorMessage();
        if(!infinityTry)
        {
            if(lastErrorMessage.find("pg_hba.conf")!=std::string::npos)
                return false;
            if(lastErrorMessage.find("authentication failed")!=std::string::npos)
                return false;
            if(lastErrorMessage.find("role \"")!=std::string::npos)
            {
                if(lastErrorMessage.find("\" does not exist")!=std::string::npos)
                    return false;
                if(lastErrorMessage.find("\" is not permitted to log in")!=std::string::npos)
                    return false;
            }
        }
        std::cerr << "pg connexion not OK: " << lastErrorMessage << ", retrying..., infinityTry: " << std::to_string(infinityTry) << std::endl;

        unsigned int index=0;
        while(index<considerDownAfterNumberOfTry && connStatusType==CONNECTION_BAD)
        {
            auto start = std::chrono::high_resolution_clock::now();
            PQfinish(conn);
            conn=PQconnectdb(strCoPG);
            connStatusType=PQstatus(conn);
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double, std::milli> elapsed = end-start;
            if(elapsed.count()<(uint32_t)tryInterval*1000 && connStatusType==CONNECTION_BAD)
            {
                std::string newErrorMessage=errorMessage();
                if(lastErrorMessage!=newErrorMessage)
                {
                    std::cerr << "pg connexion not OK: " << lastErrorMessage << ", retrying..." << std::endl;
                    lastErrorMessage=newErrorMessage;
                }
                const unsigned int ms=(uint32_t)tryInterval*1000-elapsed.count();
                std::this_thread::sleep_for(std::chrono::milliseconds(ms));
            }
            if(!infinityTry)
                index++;
            if(lastErrorMessage.find("the database system is starting up")!=std::string::npos || lastErrorMessage.find("the database system is shutting down")!=std::string::npos)
                index=0;
        }
        if(connStatusType==CONNECTION_BAD)
            return false;
    }
    #if defined(CATCHCHALLENGER_DB_PREPAREDSTATEMENT)
    {
        unsigned int index=0;
        while(index<preparedStatementUnitList.size())
        {
            const PreparedStatementStore &preparedStatement=preparedStatementUnitList.at(index);
            queryPrepare(preparedStatement.name.c_str(),preparedStatement.query.c_str(),preparedStatement.nParams,false);
            index++;
        }
    }
    #endif
    if(!setBlocking(1))
    {
       std::cerr << "pg no blocking error" << std::endl;
       return false;
    }
    int sock = PQsocket(conn);
    if (sock < 0)
    {
       std::cerr << "pg no sock" << std::endl;
       return false;
    }
    /* Use no delay, will not be able to group tcp message because is ordened into a queue
     * Then the execution is on by one, and the RTT will slow down this */
    {
        int state = 1;
        if(setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &state, sizeof(state))!=0)
            std::cerr << "Unable to apply tcp no delay" << std::endl;
    }
    epoll_event event;
    event.events = EPOLLOUT | EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLET;
    event.data.ptr = this;

    // add the socket to the epoll file descriptors
    if(Epoll::epoll.ctl(EPOLL_CTL_ADD,sock,&event) != 0)
    {
        std::cerr << "epoll_ctl, adding socket error" << std::endl;
        return false;
    }

    PQsetNoticeReceiver(conn,noticeReceiver,NULL);
    PQsetNoticeProcessor(conn,noticeProcessor,NULL);
    started=true;
    std::cout << "Connected to postgresql, Protocol version: " << PQprotocolVersion(conn) << ", Server version:" << PQserverVersion(conn) << std::endl;
    return true;
}
Beispiel #16
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;
}
Beispiel #17
0
int	main(int argc, char *argv[])
{
  int Pid;
  int c;
  int rvExist1=0, rvExist2=0;
  PGresult *result;
  char *NewDir=".";
  char *AgentName = "ununpack";
  char *AgentARSName = "ununpack_ars";
  char *agent_desc = "Unpacks archives (iso, tar, etc)";
  int   Recurse=0;
  int   ars_pk = 0;
  int   user_pk = 0;
  long  Pfile_size = 0;
  char *ListOutName=NULL;
  char *Fname = NULL;
  char *FnameCheck = NULL;
  char *COMMIT_HASH;
  char *VERSION;
  char agent_rev[PATH_MAX];
  struct stat Stat;

  /* connect to the scheduler */
  fo_scheduler_connect(&argc, argv, &pgConn);

  while((c = getopt(argc,argv,"ACc:d:FfHhL:m:PQiqRr:T:t:U:VvXx")) != -1)
  {
    switch(c)
    {
      case 'A':	SetContainerArtifact=0; break;
      case 'C':	ForceContinue=1; break;
      case 'c':	break;  /* handled by fo_scheduler_connect() */
      case 'd':	
        /* if there is a %U in the path, substitute a unique ID */
        NewDir=PathCheck(optarg);
        break;
      case 'F':	UseRepository=1; break;
      case 'f':	ForceDuplicate=1; break;
      case 'L':	ListOutName=optarg; break;
      case 'm':
        MaxThread = atoi(optarg);
        if (MaxThread < 1) MaxThread=1;
        break;
      case 'P':	PruneFiles=1; break;
      case 'R':	Recurse=-1; break;
      case 'r':	Recurse=atoi(optarg); break;
      case 'i':
        if (!IsExe("dpkg-source",Quiet))
          LOG_WARNING("dpkg-source is not available on this system.  This means that debian source packages will NOT be unpacked.");
        SafeExit(0);
        break; /* never reached */
      case 'Q':
        UseRepository=1;

        user_pk = fo_scheduler_userID(); /* get user_pk for user who queued the agent */

        /* Get the upload_pk from the scheduler */
        if((Upload_Pk = fo_scheduler_next()) == NULL) SafeExit(0);
        break;
      case 'q':	Quiet=1; break;
      case 'T':
        memset(REP_GOLD,0,sizeof(REP_GOLD));
        strncpy(REP_GOLD,optarg,sizeof(REP_GOLD)-1);
        break;
      case 't':
        memset(REP_FILES,0,sizeof(REP_FILES));
        strncpy(REP_FILES,optarg,sizeof(REP_FILES)-1);
        break;
      case 'U':	
        UseRepository = 1;
        Recurse = -1;
        Upload_Pk = optarg; 
        break;
      case 'V': printf("%s", BuildVersion);SafeExit(0);
      case 'v':	Verbose++; break;
      case 'X':	UnlinkSource=1; break;
      case 'x':	UnlinkAll=1; break;
      default:
        Usage(argv[0], BuildVersion);
        SafeExit(25);
    }
  }

  /* Open DB and Initialize CMD table */
  if (UseRepository) 
  {
    /* Check Permissions */
    if (GetUploadPerm(pgConn, atoi(Upload_Pk), user_pk) < PERM_WRITE)
    {
      LOG_ERROR("You have no update permissions on upload %s", Upload_Pk);
      SafeExit(100);
    }
        
    COMMIT_HASH = fo_sysconfig(AgentName, "COMMIT_HASH");
    VERSION = fo_sysconfig(AgentName, "VERSION");
    sprintf(agent_rev, "%s.%s", VERSION, COMMIT_HASH);
    /* Get the unpack agent key */
    agent_pk = fo_GetAgentKey(pgConn, AgentName, atoi(Upload_Pk), agent_rev,agent_desc);

    InitCmd();

    /* Make sure ars table exists */
    if (!fo_CreateARSTable(pgConn, AgentARSName)) SafeExit(0);

    /* Has this user previously unpacked this upload_pk successfully?
     *    In this case we are done.  No new ars record is needed since no
     *    processing is initiated.
     * The unpack version is ignored.
     */
    snprintf(SQL,MAXSQL,
        "SELECT ars_pk from %s where upload_fk='%s' and ars_success=TRUE",
           AgentARSName, Upload_Pk);
    result =  PQexec(pgConn, SQL);
    if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__)) SafeExit(101);

    if (PQntuples(result) > 0) /* if there is a value */
    {  
      PQclear(result);
      LOG_WARNING("Upload_pk %s, has already been unpacked.  No further action required", 
              Upload_Pk)
      SafeExit(0);
    }
    PQclear(result);

    /* write the unpack_ars start record */
    ars_pk = fo_WriteARS(pgConn, ars_pk, atoi(Upload_Pk), agent_pk, AgentARSName, 0, 0);

    /* Get Pfile path and Pfile_Pk, from Upload_Pk */
  snprintf(SQL,MAXSQL,
        "SELECT pfile.pfile_sha1 || '.' || pfile.pfile_md5 || '.' || pfile.pfile_size AS pfile, pfile_fk, pfile_size FROM upload INNER JOIN pfile ON upload.pfile_fk = pfile.pfile_pk WHERE upload.upload_pk = '%s'", 
           Upload_Pk);
    result =  PQexec(pgConn, SQL);
    if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__)) SafeExit(102);

    if (PQntuples(result) > 0) /* if there is a value */
    {  
      Pfile = strdup(PQgetvalue(result,0,0));
      Pfile_Pk = strdup(PQgetvalue(result,0,1));
      Pfile_size = atol(PQgetvalue(result, 0, 2));
      if (Pfile_size == 0)
      {  
        PQclear(result);
        LOG_WARNING("Uploaded file (Upload_pk %s), is zero length.  There is nothing to unpack.", 
                      Upload_Pk)
        SafeExit(0);
      }

      PQclear(result);
    }

    // Determine if uploadtree records should go into a separate table.
    // If the input file size is > 500MB, then create a separate uploadtree_{upload_pk} table
    // that inherits from the master uploadtree table.
    // Save uploadtree_tablename, it will get written to upload.uploadtree_tablename later.
    if (Pfile_size > 500000000)
    {
      sprintf(uploadtree_tablename, "uploadtree_%s", Upload_Pk);
      if (!fo_tableExists(pgConn, uploadtree_tablename))
      {
        snprintf(SQL,MAXSQL,"CREATE TABLE %s (LIKE uploadtree INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES); ALTER TABLE %s ADD CONSTRAINT %s CHECK (upload_fk=%s); ALTER TABLE %s INHERIT uploadtree", 
               uploadtree_tablename, uploadtree_tablename, uploadtree_tablename, Upload_Pk, uploadtree_tablename);
        PQsetNoticeProcessor(pgConn, SQLNoticeProcessor, SQL);  // ignore notice about implicit primary key index creation
        result =  PQexec(pgConn, SQL);
        // Ignore postgres notice about creating an implicit index
        if (PQresultStatus(result) != PGRES_NONFATAL_ERROR)
          if (fo_checkPQcommand(pgConn, result, SQL, __FILE__, __LINE__)) SafeExit(103);
        PQclear(result);
      }
    }
    else
      strcpy(uploadtree_tablename, "uploadtree_a");

  }

  CheckCommands(Quiet);
  if (NewDir) MkDir(NewDir);
  if (Verbose) { fclose(stderr) ; stderr=stdout; } /* don't interlace! */
  if (ListOutName != NULL)
  {
    if ((ListOutName[0]=='-') && (ListOutName[1]=='\0'))
      ListOutFile=stdout;
    else ListOutFile = fopen(ListOutName,"w");
    if (!ListOutFile)
    {
      LOG_ERROR("pfile %s Unable to write to %s\n",Pfile_Pk,ListOutName)
      SafeExit(104);
    }
    else
    {
      /* Start the file */
      fputs("<xml tool=\"ununpack\" ",ListOutFile);
      fputs("version=\"",ListOutFile);
      fputs(Version,ListOutFile);
      fputs("\" ",ListOutFile);
      fputs("compiled_date=\"",ListOutFile);
      fputs(__DATE__,ListOutFile);
      fputs(" ",ListOutFile);
      fputs(__TIME__,ListOutFile);
      fputs("\"",ListOutFile);
      fputs(">\n",ListOutFile);
    }
    /* Problem: When parallel processing, the XML may be generated out
	   of order.  Solution?  When using XML, only use 1 thread. */
    MaxThread=1;
  }

  // Set ReunpackSwitch if the uploadtree records are missing from the database.
  if (!ReunpackSwitch && UseRepository)
  {
    snprintf(SQL,MAXSQL,"SELECT uploadtree_pk FROM uploadtree WHERE upload_fk=%s limit 1;",Upload_Pk);
    result =  PQexec(pgConn, SQL);
    if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__)) SafeExit(105);
    if (PQntuples(result) == 0) ReunpackSwitch=1;
    PQclear(result);
  }

  /*** process files from command line ***/
  for( ; optind<argc; optind++)
  {
    CksumFile *CF=NULL;
    Cksum *Sum;
    int i;
    if (Fname) { free(Fname); Fname=NULL; }
    if (ListOutName != NULL)
    {
      fprintf(ListOutFile,"<source source=\"%s\" ",argv[optind]);
      if (UseRepository && !fo_RepExist(REP_FILES,argv[optind]))
      {
        /* make sure the source exists in the src repository */
        if (fo_RepImport(argv[optind],REP_FILES,argv[optind],1) != 0)
        {
          LOG_ERROR("Failed to import '%s' as '%s' into the repository",argv[optind],argv[optind])
          SafeExit(106);
        }
      }
    }

    if (UseRepository)
    {
      if (fo_RepExist(REP_FILES,argv[optind]))
      {
        Fname=fo_RepMkPath(REP_FILES,argv[optind]);
      }
      else if (fo_RepExist(REP_GOLD,argv[optind]))
      {
        Fname=fo_RepMkPath(REP_GOLD,argv[optind]);
        if (fo_RepImport(Fname,REP_FILES,argv[optind],1) != 0)
        {
          LOG_ERROR("Failed to import '%s' as '%s' into the repository",Fname,argv[optind])
          SafeExit(107);
        }
      }

      if (Fname)
      {
        FnameCheck = Fname;
        CF = SumOpenFile(Fname);
      }
      else
      {
        LOG_ERROR("NO file unpacked.  File %s does not exist either in GOLD or FILES", Pfile);
        SafeExit(108);
      }
      /* else: Fname is NULL and CF is NULL */
    }
    else 
    {
      FnameCheck = argv[optind];
      CF = SumOpenFile(argv[optind]);
    }

    /* Check file to unpack.  Does it exist?  Is it zero length? */
    if (stat(FnameCheck,&Stat)) 
    {
      LOG_ERROR("File to unpack is unavailable: %s, error: %s", Fname, strerror(errno));
      SafeExit(109);
    }
    else
    if (Stat.st_size < 1)
    {
      LOG_WARNING("File to unpack is empty: %s", Fname);
      SafeExit(110);
    }

    if (ListOutFile)
    {
      if (CF)
      {
        Sum = SumComputeBuff(CF);
        SumCloseFile(CF);
        if (Sum)
        {
          fputs("fuid=\"",ListOutFile);
          for(i=0; i<20; i++)
          { fprintf(ListOutFile,"%02X",Sum->SHA1digest[i]); }
          fputs(".",ListOutFile);
          for(i=0; i<16; i++)
          { fprintf(ListOutFile,"%02X",Sum->MD5digest[i]); }
          fputs(".",ListOutFile);
          fprintf(ListOutFile,"%Lu",(long long unsigned int)Sum->DataLen);
          fputs("\" ",ListOutFile);
          free(Sum);
        } /* if Sum */
      } /* if CF */
      else /* file too large to mmap (probably) */
      {
        FILE *Fin;
        Fin = fopen(argv[optind],"rb");
        if (Fin)
        {
          Sum = SumComputeFile(Fin);
          if (Sum)
          {
            fputs("fuid=\"",ListOutFile);
            for(i=0; i<20; i++)
            { fprintf(ListOutFile,"%02X",Sum->SHA1digest[i]); }
            fputs(".",ListOutFile);
            for(i=0; i<16; i++)
            { fprintf(ListOutFile,"%02X",Sum->MD5digest[i]); }
            fputs(".",ListOutFile);
            fprintf(ListOutFile,"%Lu",(long long unsigned int)Sum->DataLen);
            fputs("\" ",ListOutFile);
            free(Sum);
          }
          fclose(Fin);
        }
      } /* else no CF */
      fprintf(ListOutFile,">\n"); /* end source XML */
    }
    if (Fname)	TraverseStart(Fname,"called by main via args",NewDir,Recurse);
    else		TraverseStart(argv[optind],"called by main",NewDir,Recurse);
    if (ListOutName != NULL) fprintf(ListOutFile,"</source>\n");
  } /* end for */

  /* free memory */
  if (Fname) { free(Fname); Fname=NULL; }

  /* process pfile from scheduler */
  if (Pfile)
  {
    if (0 == (rvExist1 = fo_RepExist2(REP_FILES,Pfile)))
    {
      Fname=fo_RepMkPath(REP_FILES,Pfile);
    }
    else if (0 == (rvExist2 = fo_RepExist2(REP_GOLD,Pfile)))
    {
      Fname=fo_RepMkPath(REP_GOLD,Pfile);
      if (fo_RepImport(Fname,REP_FILES,Pfile,1) != 0)
      {
        LOG_ERROR("Failed to import '%s' as '%s' into the repository",Fname,Pfile)
        SafeExit(111);
      }
    }
    if (Fname)
    {
      TraverseStart(Fname,"called by main via env",NewDir,Recurse);
      free(Fname);
      Fname=NULL;
    }
    else
    {
      LOG_ERROR("NO file unpacked!");
      if (rvExist1 > 0)
      {
        Fname=fo_RepMkPath(REP_FILES, Pfile);
        LOG_ERROR("Error is %s for %s", strerror(rvExist1), Fname);
      }
      if (rvExist2 > 0)
      {
        Fname=fo_RepMkPath(REP_GOLD, Pfile);
        LOG_ERROR("Error is %s for %s", strerror(rvExist2), Fname);
      }
      SafeExit(112);
    }
  }

  /* recurse on all the children */
  if (Thread > 0) do
  {
    Pid = ParentWait();
    Thread--;
    if (Pid >= 0)
    {
      if (!Queue[Pid].ChildEnd)
      {
        /* copy over data */
        if (Recurse > 0)
          Traverse(Queue[Pid].ChildRecurse,NULL,"called by wait",NULL,Recurse-1,&Queue[Pid].PI);
        else if (Recurse < 0)
          Traverse(Queue[Pid].ChildRecurse,NULL,"called by wait",NULL,Recurse,&Queue[Pid].PI);
      }
    }
  } while(Pid >= 0);

  if (MagicCookie) magic_close(MagicCookie);
  if (ListOutFile)
  {
    fprintf(ListOutFile,"<summary files_regular=\"%d\" files_compressed=\"%d\" artifacts=\"%d\" directories=\"%d\" containers=\"%d\" />\n",
        TotalFiles,TotalCompressedFiles,TotalArtifacts,
        TotalDirectories,TotalContainers);
    fputs("</xml>\n",ListOutFile);
  }
  if (pgConn)
  {
    /* If it completes, mark it! */
    if (Upload_Pk)
    {
      snprintf(SQL,MAXSQL,"UPDATE upload SET upload_mode = (upload_mode | (1<<5)), uploadtree_tablename='%s' WHERE upload_pk = '%s';",uploadtree_tablename, Upload_Pk);
      result =  PQexec(pgConn, SQL); /* UPDATE upload */
      if (fo_checkPQcommand(pgConn, result, SQL, __FILE__ ,__LINE__)) SafeExit(113);
      PQclear(result);

      snprintf(SQL,MAXSQL,"UPDATE %s SET realparent = getItemParent(uploadtree_pk) WHERE upload_fk = '%s'",uploadtree_tablename, Upload_Pk);
      result =  PQexec(pgConn, SQL); /* UPDATE uploadtree */
      if (fo_checkPQcommand(pgConn, result, SQL, __FILE__ ,__LINE__)) SafeExit(114);
      PQclear(result);
    }

    if (ars_pk) fo_WriteARS(pgConn, ars_pk, atoi(Upload_Pk), agent_pk, AgentARSName, 0, 1);
  }
  if (ListOutFile && (ListOutFile != stdout))
  {
    fclose(ListOutFile);
  }

  if (UnlinkAll && MaxThread > 1)
  {
    /* Delete temporary files */
    if (strcmp(NewDir, ".")) RemoveDir(NewDir);
  }
 
  SafeExit(0);
  return(0);  // never executed but makes the compiler happy
} 
Beispiel #18
0
/*
 * 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;
}
Beispiel #19
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;
}
Beispiel #20
0
void dbgPgConn::setNoticeHandler( PQnoticeProcessor handler, void *arg )
{
	PQnoticeProcessor p = NULL;
	p = PQsetNoticeProcessor( m_pgConn, handler, arg );
}
Beispiel #21
0
bool pgConn::Initialize()
{
	// Set client encoding to Unicode/Ascii, Datestyle to ISO, and ask for notices.
	if (PQstatus(conn) == CONNECTION_OK)
	{
		connStatus = PGCONN_OK;
		PQsetNoticeProcessor(conn, pgNoticeProcessor, this);

		wxString sql = wxT("SET DateStyle=ISO;\nSET client_min_messages=notice;\n");
		if (BackendMinimumVersion(9, 0))
			sql += wxT("SET bytea_output=escape;\n");

		sql += wxT("SELECT oid, pg_encoding_to_char(encoding) AS encoding, datlastsysoid\n")
		       wxT("  FROM pg_database WHERE ");

		if (save_oid)
			sql += wxT("oid = ") + NumToStr(save_oid);
		else
		{
			// Note, can't use qtDbString here as we don't know the server version yet.
			wxString db = save_database;
			db.Replace(wxT("\\"), wxT("\\\\"));
			db.Replace(wxT("'"), wxT("''"));
			sql += wxT("datname=") + qtString(db);
		}

		pgSet *set = ExecuteSet(sql);
		if (set)
		{
			if (set->ColNumber(wxT("\"datlastsysoid\"")) >= 0)
				needColQuoting = true;

			lastSystemOID = set->GetOid(wxT("datlastsysoid"));
			dbOid = set->GetOid(wxT("oid"));
			wxString encoding = set->GetVal(wxT("encoding"));

			if (encoding != wxT("SQL_ASCII") && encoding != wxT("MULE_INTERNAL"))
			{
				encoding = wxT("UNICODE");
				conv = &wxConvUTF8;
			}
			else
				conv = &wxConvLibc;

			wxLogInfo(wxT("Setting client_encoding to '%s'"), encoding.c_str());
			if (PQsetClientEncoding(conn, encoding.ToAscii()))
			{
				wxLogError(wxT("%s"), GetLastError().c_str());
			}

			delete set;

			// Switch to the requested default role if supported by backend
			if (dbRole != wxEmptyString && BackendMinimumVersion(8, 1))
			{
				sql = wxT("SET ROLE TO ");
				sql += qtIdent(dbRole);

				pgSet *set = ExecuteSet(sql);

				if (set)
					delete set;
				else
					return false;
			}
			return true;
		}
	}
	return false;
}
Beispiel #22
0
// This function also needs a lot of work
void PostgreSQLDatabase::init( const PostgreSQLConfig& config)
{
	int connections = config.connections();

	m_connStr = buildConnStr( config.host(), config.port(), config.dbName(),
				  config.user(), config.password(),
				  config.sslMode(), config.sslCert(), config.sslKey(),
				  config.sslRootCert(), config.sslCRL(),
				  config.connectTimeout() );
	LOG_DATA << "PostgreSQL database '" << m_ID << "' connection string <" << m_connStr << ">";

	for ( unsigned short i = 0; i < connections; i++ )	{
		PGconn* conn = PQconnectdb( m_connStr.c_str() );
		if ( conn == NULL )
			LOG_ALERT << "Failed to connect to PostgreSQL database '" << m_ID << "'";
		else	{
			if (i == 0)
			{
				//... the first connection is used to load some info
				m_serverSettings.load( conn);
			}

			PQsetNoticeProcessor( conn, &noticeProcessor, this);

			ConnStatusType stat = PQstatus( conn );
			std::string err = PQerrorMessage( conn );
			while ( !err.empty() && ( err[ err.size() - 1 ] == '\r' ||  err[ err.size() - 1 ] == '\n' ))
				err.erase( err.size() - 1 );
			switch( stat )	{
				case CONNECTION_OK:
					LOG_TRACE << "PostgreSQL database '" << m_ID << "' constructor: connection "
						      << i << " connected OK.";
					break;
				case CONNECTION_BAD:
					if ( err.compare( 0, 6, "FATAL:" ) == 0 )	{
						LOG_ALERT << "PostgreSQL database '" << m_ID << "' (connection "
							      << i << ") error: '" << err << "'";
						throw std::runtime_error( "Fatal error connecting to the PostgreSQL database" );
					}
					LOG_WARNING << "PostgreSQL database '" << m_ID << "' connection "
							<< i << " error: '" << err << "'";
					break;
				case CONNECTION_STARTED:
					LOG_ALERT << "PostgreSQL database '" << m_ID << "' constructor: connection "
						      << i << " connection STARTED: '" << err << "'";
					throw std::range_error( "PostgreSQL database: CONNECTION_STARTED in synchronous connection" );
					break;
				case CONNECTION_MADE:
					LOG_ALERT << "PostgreSQL database '" << m_ID << "' constructor: connection "
						      << i << " connection MADE: '" << err << "'";
					throw std::range_error( "PostgreSQL database: CONNECTION_MADE in synchronous connection" );
					break;
				case CONNECTION_AWAITING_RESPONSE:
					LOG_ALERT << "PostgreSQL database '" << m_ID << "' constructor: connection "
						      << i << " connection AWAITING RESPONSE: '" << err << "'";
					throw std::range_error( "PostgreSQL database: CONNECTION_AWAITING_RESPONSE in synchronous connection" );
					break;
				case CONNECTION_AUTH_OK:
					LOG_ALERT << "PostgreSQL database '" << m_ID << "' constructor: connection "
						      << i << " connection AUTH OK: '" << err << "'";
					throw std::range_error( "PostgreSQL database: CONNECTION_AUTH_OK in synchronous connection" );
					break;
				case CONNECTION_SSL_STARTUP:
					LOG_ALERT << "PostgreSQL database '" << m_ID << "' constructor: connection "
						      << i << " connection SSL start: '" << err << "'";
					throw std::range_error( "PostgreSQL database: CONNECTION_SSL_STARTUP in synchronous connection" );
					break;
				case CONNECTION_SETENV:
					LOG_ALERT << "PostgreSQL database '" << m_ID << "' constructor: connection "
						      << i << " connection SETENV: '" << err << "'";
					throw std::range_error( "PostgreSQL database: CONNECTION_SETENV in synchronous connection" );
					break;
				case CONNECTION_NEEDED:
					LOG_ALERT << "PostgreSQL database '" << m_ID << "' constructor: connection "
						      << i << " connection NEEDED: '" << err << "'";
					throw std::range_error( "PostgreSQL database: CONNECTION_NEEDED in synchronous connection" );
					break;
			}

			std::stringstream statement_timeout_s;
			statement_timeout_s << "SET statement_timeout = " << config.statementTimeout();
			PGresult* res = PQexec( conn, statement_timeout_s.str( ).c_str( ) );
			PQclear( res);

			m_connPool.add( conn );
			m_connections++;
		}
	}
	LOG_DEBUG << "PostgreSQL database '" << m_ID << "' created with a pool of " << m_connections << " connections";
}
Beispiel #23
0
static int
perform_pgsql_search(uschar *query, uschar *server, uschar **resultptr,
  uschar **errmsg, BOOL *defer_break, BOOL *do_cache)
{
PGconn *pg_conn = NULL;
PGresult *pg_result = NULL;

int i;
int ssize = 0;
int offset = 0;
int yield = DEFER;
unsigned int num_fields, num_tuples;
uschar *result = NULL;
pgsql_connection *cn;
uschar *server_copy = NULL;
uschar *sdata[3];

/* Disaggregate the parameters from the server argument. The order is host or
path, database, user, password. We can write to the string, since it is in a
nextinlist temporary buffer. The copy of the string that is used for caching
has the password removed. This copy is also used for debugging output. */

for (i = 2; i >= 0; i--)
  {
  uschar *pp = Ustrrchr(server, '/');
  if (pp == NULL)
    {
    *errmsg = string_sprintf("incomplete pgSQL server data: %s",
      (i == 2)? server : server_copy);
    *defer_break = TRUE;
    return DEFER;
    }
  *pp++ = 0;
  sdata[i] = pp;
  if (i == 2) server_copy = string_copy(server);  /* sans password */
  }

/* The total server string has now been truncated so that what is left at the
start is the identification of the server (host or path). See if we have a
cached connection to the server. */

for (cn = pgsql_connections; cn != NULL; cn = cn->next)
  {
  if (Ustrcmp(cn->server, server_copy) == 0)
    {
    pg_conn = cn->handle;
    break;
    }
  }

/* If there is no cached connection, we must set one up. */

if (cn == NULL)
  {
  uschar *port = US"";

  /* For a Unix domain socket connection, the path is in parentheses */

  if (*server == '(')
    {
    uschar *last_slash, *last_dot, *p;

    p = ++server;
    while (*p != 0 && *p != ')') p++;
    *p = 0;

    last_slash = Ustrrchr(server, '/');
    last_dot = Ustrrchr(server, '.');

    DEBUG(D_lookup) debug_printf("PGSQL new connection: socket=%s "
      "database=%s user=%s\n", server, sdata[0], sdata[1]);

    /* A valid socket name looks like this: /var/run/postgresql/.s.PGSQL.5432
    We have to call PQsetdbLogin with '/var/run/postgresql' as the hostname
    argument and put '5432' into the port variable. */

    if (last_slash == NULL || last_dot == NULL)
      {
      *errmsg = string_sprintf("PGSQL invalid filename for socket: %s",
        server);
      *defer_break = TRUE;
      return DEFER;
      }

    /* Terminate the path name and set up the port: we'll have something like
    server = "/var/run/postgresql" and port = "5432". */

    *last_slash = 0;
    port = last_dot + 1;
    }

  /* Host connection; sort out the port */

  else
    {
    uschar *p;
    if ((p = Ustrchr(server, ':')) != NULL)
      {
      *p++ = 0;
      port = p;
      }

    if (Ustrchr(server, '/') != NULL)
      {
      *errmsg = string_sprintf("unexpected slash in pgSQL server hostname: %s",
        server);
      *defer_break = TRUE;
      return DEFER;
      }

    DEBUG(D_lookup) debug_printf("PGSQL new connection: host=%s port=%s "
      "database=%s user=%s\n", server, port, sdata[0], sdata[1]);
    }

  /* If the database is the empty string, set it NULL - the query must then
  define it. */

  if (sdata[0][0] == 0) sdata[0] = NULL;

  /* Get store for a new handle, initialize it, and connect to the server */

  pg_conn=PQsetdbLogin(
    /*  host      port  options tty   database       user       passwd */
    CS server, CS port,  NULL, NULL, CS sdata[0], CS sdata[1], CS sdata[2]);

  if(PQstatus(pg_conn) == CONNECTION_BAD)
    {
    store_reset(server_copy);
    *errmsg = string_sprintf("PGSQL connection failed: %s",
      PQerrorMessage(pg_conn));
    PQfinish(pg_conn);
    goto PGSQL_EXIT;
    }

  /* Set the client encoding to SQL_ASCII, which means that the server will
  not try to interpret the query as being in any fancy encoding such as UTF-8
  or other multibyte code that might cause problems with escaping. */

  PQsetClientEncoding(pg_conn, "SQL_ASCII");

  /* Set the notice processor to prevent notices from being written to stderr
  (which is what the default does). Our function (above) just produces debug
  output. */

  PQsetNoticeProcessor(pg_conn, notice_processor, NULL);

  /* Add the connection to the cache */

  cn = store_get(sizeof(pgsql_connection));
  cn->server = server_copy;
  cn->handle = pg_conn;
  cn->next = pgsql_connections;
  pgsql_connections = cn;
  }

/* Else use a previously cached connection */

else
  {
  DEBUG(D_lookup) debug_printf("PGSQL using cached connection for %s\n",
    server_copy);
  }

/* Run the query */

  pg_result = PQexec(pg_conn, CS query);
  switch(PQresultStatus(pg_result))
    {
    case PGRES_EMPTY_QUERY:
    case PGRES_COMMAND_OK:
    /* The command was successful but did not return any data since it was
     * not SELECT but either an INSERT, UPDATE or DELETE statement. Tell the
     * high level code to not cache this query, and clean the current cache for
     * this handle by setting *do_cache FALSE. */
    result = string_copy(US PQcmdTuples(pg_result));
    offset = Ustrlen(result);
    *do_cache = FALSE;
    DEBUG(D_lookup) debug_printf("PGSQL: command does not return any data "
      "but was successful. Rows affected: %s\n", result);

    case PGRES_TUPLES_OK:
    break;

    default:
    /* This was the original code:
    *errmsg = string_sprintf("PGSQL: query failed: %s\n",
                             PQresultErrorMessage(pg_result));
    This was suggested by a user:
    */

    *errmsg = string_sprintf("PGSQL: query failed: %s (%s) (%s)\n",
                             PQresultErrorMessage(pg_result),
                             PQresStatus(PQresultStatus(pg_result)), query);
    goto PGSQL_EXIT;
    }

/* Result is in pg_result. Find the number of fields returned. If this is one,
we don't add field names to the data. Otherwise we do. If the query did not
return anything we skip the for loop; this also applies to the case
PGRES_COMMAND_OK. */

num_fields = PQnfields(pg_result);
num_tuples = PQntuples(pg_result);

/* Get the fields and construct the result string. If there is more than one
row, we insert '\n' between them. */

for (i = 0; i < num_tuples; i++)
  {
  if (result != NULL)
    result = string_cat(result, &ssize, &offset, US"\n", 1);

   if (num_fields == 1)
    {
    result = string_cat(result, &ssize, &offset,
      US PQgetvalue(pg_result, i, 0), PQgetlength(pg_result, i, 0));
    }

   else
    {
    int j;
    for (j = 0; j < num_fields; j++)
      {
      uschar *tmp = US PQgetvalue(pg_result, i, j);
      result = lf_quote(US PQfname(pg_result, j), tmp, Ustrlen(tmp), result,
        &ssize, &offset);
      }
    }
  }

/* If result is NULL then no data has been found and so we return FAIL.
Otherwise, we must terminate the string which has been built; string_cat()
always leaves enough room for a terminating zero. */

if (result == NULL)
  {
  yield = FAIL;
  *errmsg = US"PGSQL: no data found";
  }
else
  {
  result[offset] = 0;
  store_reset(result + offset + 1);
  }

/* Get here by goto from various error checks. */

PGSQL_EXIT:

/* Free store for any result that was got; don't close the connection, as
it is cached. */

if (pg_result != NULL) PQclear(pg_result);

/* Non-NULL result indicates a sucessful result */

if (result != NULL)
  {
  *resultptr = result;
  return OK;
  }
else
  {
  DEBUG(D_lookup) debug_printf("%s\n", *errmsg);
  return yield;      /* FAIL or DEFER */
  }
}
Beispiel #24
0
int pg_con_connect(db_con_t* con)
{
	struct pg_con* pcon;
	struct pg_uri* puri;
	char* port_str;
	int ret;
	
	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);
	} else {
		port_str = NULL;
	}

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

	pcon->con = PQsetdbLogin(puri->host, port_str,
							 NULL, NULL, puri->database,
							 puri->username, puri->password);
	
	if (pcon->con == NULL) {
		ERR("postgres: PQsetdbLogin 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);
	
	DBG("postgres: Connected. Protocol version=%d, Server version=%d\n", 
	    PQprotocolVersion(pcon->con),
#ifdef HAVE_PGSERVERVERSION
	    PQserverVersion(pcon->con)
#else
	    0
#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;
}