Пример #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;
}
Пример #2
0
void
cdbconn_doConnectComplete(SegmentDatabaseDescriptor *segdbDesc)
{
	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 &&
		gp_log_gang >= GPVARS_VERBOSITY_DEBUG)
	{
		elog(LOG, "Connected to %s motionListenerPorts=%d/%d with options %s",
			 segdbDesc->whoami,
			 (segdbDesc->motionListener & 0x0ffff),
			 ((segdbDesc->motionListener >> 16) & 0x0ffff),
			 PQoptions(segdbDesc->conn));
	}
Пример #3
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;
	char	   *dbname = name ? ecpg_strdup(name, lineno) : NULL,
			   *host = NULL,
			   *tmp,
			   *port = NULL,
			   *realname = NULL,
			   *options = NULL,
			   *connect_string = NULL;

	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 out of 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);
					*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);
						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);
				}

				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
					host = ecpg_strdup(dbname + offset, lineno);

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

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

			realname = (strlen(dbname) > 0) ? ecpg_strdup(dbname, lineno) : 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 : "");

	connect_string = ecpg_alloc(strlen_or_null(host)
								+ strlen_or_null(port)
								+ strlen_or_null(options)
								+ strlen_or_null(realname)
								+ strlen_or_null(user)
								+ strlen_or_null(passwd)
			  + sizeof(" host = port = dbname = user = password ="******"%s%s %s%s %s%s %s%s %s%s %s",
			realname ? "dbname=" : "", realname ? realname : "",
			host ? "host=" : "", host ? host : "",
			port ? "port=" : "", port ? port : "",
			(user && strlen(user) > 0) ? "user="******"", user ? user : "",
	 (passwd && strlen(passwd) > 0) ? "password="******"", passwd ? passwd : "",
			options ? options : "");

	/*
	 * this is deprecated this->connection = PQsetdbLogin(host, port, options,
	 * NULL, realname, user, passwd);
	 */
	this->connection = PQconnectdb(connect_string);

	ecpg_free(connect_string);
	if (host)
		ecpg_free(host);
	if (port)
		ecpg_free(port);
	if (options)
		ecpg_free(options);
	if (dbname)
		ecpg_free(dbname);

	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;
}
Пример #4
0
/** Create or open an PostgreSQL database
 * \param db the databse to associate with the sqlite3 database
 * \return 0 if successful, -1 otherwise
 */
int
psql_create_database(Database* db)
{
  MString *conninfo;
  MString *str;
  PGconn  *conn;
  PGresult *res = NULL;
  int ret = -1;

  loginfo ("psql:%s: Accessing database\n", db->name);

  /*
   * Make a connection to the database server -- check if the
   * requested database exists or not by connecting to the 'postgres'
   * database and querying that.
   */
  conninfo = psql_prepare_conninfo("postgres", pg_host, pg_port, pg_user, pg_pass, pg_conninfo);
  conn = PQconnectdb(mstring_buf (conninfo));

  /* Check to see that the backend connection was successfully made */
  if (PQstatus(conn) != CONNECTION_OK) {
    logerror ("psql: Could not connect to PostgreSQL database (conninfo \"%s\"): %s\n",
         mstring_buf(conninfo), PQerrorMessage (conn));
    goto cleanup_exit;
  }
  PQsetNoticeReceiver(conn, psql_receive_notice, "postgres");

  str = mstring_create();
  mstring_sprintf (str, "SELECT datname from pg_database where datname='%s';", db->name);
  res = PQexec (conn, mstring_buf (str));

  if (PQresultStatus (res) != PGRES_TUPLES_OK) {
    logerror ("psql: Could not get list of existing databases\n");
    goto cleanup_exit;
  }

  /* No result rows means database doesn't exist, so create it instead */
  if (PQntuples (res) == 0) {
    loginfo ("psql:%s: Database does not exist, creating it\n", db->name);
    mstring_set (str, "");
    mstring_sprintf (str, "CREATE DATABASE \"%s\";", db->name);

    res = PQexec (conn, mstring_buf (str));
    if (PQresultStatus (res) != PGRES_COMMAND_OK) {
      logerror ("psql:%s: Could not create database: %s\n", db->name, PQerrorMessage (conn));
      goto cleanup_exit;
    }
  }

  PQfinish (conn);
  mstring_delete(conninfo);

  /* Now that the database should exist, make a connection to the it for real */
  conninfo = psql_prepare_conninfo(db->name, pg_host, pg_port, pg_user, pg_pass, pg_conninfo);
  conn = PQconnectdb(mstring_buf (conninfo));

  /* Check to see that the backend connection was successfully made */
  if (PQstatus(conn) != CONNECTION_OK) {
    logerror ("psql:%s: Could not connect to PostgreSQL database (conninfo \"%s\"): %s\n",
        db->name, mstring_buf(conninfo), PQerrorMessage (conn));
    goto cleanup_exit;
  }
  PQsetNoticeReceiver(conn, psql_receive_notice, db->name);

  PsqlDB* self = (PsqlDB*)xmalloc(sizeof(PsqlDB));
  self->conn = conn;
  self->last_commit = time (NULL);

  db->create = psql_create_database;
  db->release = psql_release;
  db->table_create = psql_table_create;
  db->table_create_meta = psql_table_create_meta;
  db->table_free = psql_table_free;
  db->insert = psql_insert;
  db->add_sender_id = psql_add_sender_id;
  db->get_metadata = psql_get_metadata;
  db->set_metadata = psql_set_metadata;
  db->get_uri = psql_get_uri;
  db->get_table_list = psql_get_table_list;

  db->handle = self;

  begin_transaction (self);

  /* Everything was successufl, prepare for cleanup */
  ret = 0;

cleanup_exit:
  if (res) PQclear (res);
  if (ret) PQfinish (conn); /* If return !=0, cleanup connection */

  mstring_delete (str);
  mstring_delete (conninfo);
  return ret;
}
Пример #5
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;
}
Пример #6
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;
	char	   *dbname = name ? ECPGstrdup(name, lineno) : NULL,
			   *host = NULL,
			   *tmp,
			   *port = NULL,
			   *realname = NULL,
			   *options = NULL;

	ECPGinit_sqlca(sqlca);

	ECPGclear_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)
		{
			ECPGfree(dbname);
			dbname = ECPGstrdup(envname, lineno);
		}

	}

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

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

	if (dbname != NULL)
	{
		/* get the detail information out of dbname */
		if (strchr(dbname, '@') != NULL)
		{
			/* old style: dbname[@server][:port] */
			tmp = strrchr(dbname, ':');
			if (tmp != NULL)	/* port number given */
			{
				port = ECPGstrdup(tmp + 1, lineno);
				*tmp = '\0';
			}

			tmp = strrchr(dbname, '@');
			if (tmp != NULL)	/* host name given */
			{
				host = ECPGstrdup(tmp + 1, lineno);
				*tmp = '\0';
			}
			realname = ECPGstrdup(dbname, lineno);
		}
		else 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 = ECPGstrdup(tmp + 1, lineno);
					*tmp = '\0';
				}

				tmp = last_dir_separator(dbname + offset);
				if (tmp != NULL)	/* database name given */
				{
					realname = ECPGstrdup(tmp + 1, lineno);
					*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 = ECPGstrdup(tmp + 1, lineno);
						if (strncmp(dbname, "unix:", 5) != 0)
						{
							ECPGlog("connect: socketname %s given for TCP connection in line %d\n", host, lineno);
							ECPGraise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : "<DEFAULT>");
							if (host)
								ECPGfree(host);
							if (port)
								ECPGfree(port);
							if (options)
								ECPGfree(options);
							if (realname)
								ECPGfree(realname);
							if (dbname)
								ECPGfree(dbname);
							return false;
						}
					}
					else
						port = ECPGstrdup(tmp + 1, lineno);
				}

				if (strncmp(dbname, "unix:", 5) == 0)
				{
					if (strcmp(dbname + offset, "localhost") != 0 && strcmp(dbname + offset, "127.0.0.1") != 0)
					{
						ECPGlog("connect: non-localhost access via sockets in line %d\n", lineno);
						ECPGraise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : "<DEFAULT>");
						if (host)
							ECPGfree(host);
						if (port)
							ECPGfree(port);
						if (options)
							ECPGfree(options);
						if (realname)
							ECPGfree(realname);
						if (dbname)
							ECPGfree(dbname);
						ecpg_finish(this);
						return false;
					}
				}
				else
					host = ECPGstrdup(dbname + offset, lineno);

			}
			else
				realname = ECPGstrdup(dbname, lineno);
		}
		else
			realname = ECPGstrdup(dbname, lineno);
	}
	else
		realname = NULL;

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

	this->cache_head = NULL;

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

	all_connections = this;
#ifdef ENABLE_THREAD_SAFETY
	pthread_once(&actual_connection_key_once, ecpg_actual_connection_init);
	pthread_setspecific(actual_connection_key, all_connections);
#endif
	actual_connection = all_connections;

	ECPGlog("ECPGconnect: opening database %s on %s port %s %s%s%s%s\n",
			realname ? realname : "<DEFAULT>",
			host ? host : "<DEFAULT>",
			port ? port : "<DEFAULT>",
			options ? "with options " : "", options ? options : "",
			user ? "for user " : "", user ? user : "");

	this->connection = PQsetdbLogin(host, port, options, NULL, realname, user, passwd);

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

		ECPGlog("connect: could not open database %s on %s port %s %s%s%s%s in line %d\n\t%s\n",
				db,
				host ? host : "<DEFAULT>",
				port ? port : "<DEFAULT>",
				options ? "with options " : "", options ? options : "",
				user ? "for user " : "", user ? user : "",
				lineno, errmsg);

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

		ECPGraise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, db);
		if (host)
			ECPGfree(host);
		if (port)
			ECPGfree(port);
		if (options)
			ECPGfree(options);
		if (realname)
			ECPGfree(realname);
		if (dbname)
			ECPGfree(dbname);
		return false;
	}
#ifdef ENABLE_THREAD_SAFETY
	pthread_mutex_unlock(&connections_mutex);
#endif

	if (host)
		ECPGfree(host);
	if (port)
		ECPGfree(port);
	if (options)
		ECPGfree(options);
	if (realname)
		ECPGfree(realname);
	if (dbname)
		ECPGfree(dbname);

	this->committed = true;
	this->autocommit = autocommit;

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

	return true;
}
Пример #7
0
static PGconn *
connect_to_localhost(void)
{
	PGconn *conn;
	char	sql[1024];
	char   *host;
	char	dbName[1024];

	/* Also ensure backend isn't confused by this environment var. */
	setenv("PGCLIENTENCODING", GetDatabaseEncodingName(), 1);

#ifdef HAVE_UNIX_SOCKETS
	host = (UnixSocketDir == NULL || UnixSocketDir[0] == '\0') ?
				DEFAULT_PGSOCKET_DIR :
				UnixSocketDir;
#else
	host = "localhost";
#endif

	/* set dbname and disable hostaddr */
	snprintf(dbName, lengthof(dbName), "dbname='%s' hostaddr=''",
			 escape_param_str(get_database_name(MyDatabaseId)));

	conn = PQsetdbLogin(
		host,
		GetConfigOption("port", false, false),
		NULL, NULL,
		dbName,
		GetUserNameFromId(GetUserId()),
		NULL);
	if (PQstatus(conn) == CONNECTION_BAD)
	{
		ParallelWriter wr;

		wr.conn = conn;
		ereport(ERROR,
				(errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION),
				 errmsg("could not establish connection to parallel writer"),
				 errdetail("%s", finish_and_get_message(&wr)),
				 errhint("Refer to the following if it is an authentication "
						 "error.  Specifies the authentication method to "
						 "without the need for a password in pg_hba.conf (ex. "
						 "trust or ident), or specify the password to the "
						 "password file of the operating system user who ran "
						 "PostgreSQL server.  If cannot use these solution, "
						 "specify WRITER=DIRECT.")));
	}

	/* attempt to set default datestyle */
	snprintf(sql, lengthof(sql), "SET datestyle = '%s'", GetConfigOption("datestyle", false, false));
	PQexec(conn, sql);

	/* attempt to set default datestyle */
	snprintf(sql, lengthof(sql), "SET timezone = '%s'", show_timezone());
	PQexec(conn, sql);

	/* set message receiver */
	PQsetNoticeReceiver(conn, transfer_message, NULL);

	return conn;
}
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;
}
Пример #9
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);
		}
	}
}