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