/* questionmarks is not needed but remains in there for the time being to not change the API */ bool ECPGprepare(int lineno, const char *connection_name, const bool questionmarks, const char *name, const char *variable) { struct connection *con; struct prepared_statement *this, *prev; const char *real_connection_name = NULL; (void) questionmarks; /* quiet the compiler */ real_connection_name = ecpg_get_con_name_by_declared_name(name); if (real_connection_name == NULL) { /* * If can't get the connection name by declared name then using connection name * coming from the parameter connection_name */ real_connection_name = connection_name; } con = ecpg_get_connection(real_connection_name); if (!ecpg_init(con, real_connection_name, lineno)) return false; /* check if we already have prepared this statement */ this = ecpg_find_prepared_statement(name, con, &prev); if (this && !deallocate_one(lineno, ECPG_COMPAT_PGSQL, con, prev, this)) return false; return prepare_common(lineno, con, name, variable); }
PGconn * ECPGget_PGconn(const char *connection_name) { struct connection *con; con = ecpg_get_connection(connection_name); if (con == NULL) return NULL; return con->connection; }
PGTransactionStatusType ECPGtransactionStatus(const char *connection_name) { const struct connection *con; con = ecpg_get_connection(connection_name); if (con == NULL) { /* transaction status is unknown */ return PQTRANS_UNKNOWN; } return PQtransactionStatus(con->connection); }
bool ECPGsetconn(int lineno, const char *connection_name) { struct connection *con = ecpg_get_connection(connection_name); if (!ecpg_init(con, connection_name, lineno)) return (false); #ifdef ENABLE_THREAD_SAFETY pthread_setspecific(actual_connection_key, con); #else actual_connection = con; #endif return true; }
bool ECPGstatus(int lineno, const char *connection_name) { struct connection *con = ecpg_get_connection(connection_name); if (!ecpg_init(con, connection_name, lineno)) return (false); /* are we connected? */ if (con->connection == NULL) { ecpg_raise(lineno, ECPG_NOT_CONN, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, con->name); return false; } return (true); }
bool ECPGtrans(int lineno, const char *connection_name, const char *transaction) { PGresult *res; struct connection *con = ecpg_get_connection(connection_name); if (!ecpg_init(con, connection_name, lineno)) return false; ecpg_log("ECPGtrans on line %d: action \"%s\"; connection \"%s\"\n", lineno, transaction, con ? con->name : "null"); /* if we have no connection we just simulate the command */ if (con && con->connection) { /* * If we got a transaction command but have no open transaction, we * have to start one, unless we are in autocommit, where the * developers have to take care themselves. However, if the command is * a begin statement, we just execute it once. And if the command is * commit or rollback prepared, we don't execute it. */ if (PQtransactionStatus(con->connection) == PQTRANS_IDLE && !con->autocommit && strncmp(transaction, "begin", 5) != 0 && strncmp(transaction, "start", 5) != 0 && strncmp(transaction, "commit prepared", 15) != 0 && strncmp(transaction, "rollback prepared", 17) != 0) { res = PQexec(con->connection, "begin transaction"); if (!ecpg_check_PQresult(res, lineno, con->connection, ECPG_COMPAT_PGSQL)) return false; PQclear(res); } res = PQexec(con->connection, transaction); if (!ecpg_check_PQresult(res, lineno, con->connection, ECPG_COMPAT_PGSQL)) return false; PQclear(res); } return true; }
/* questionmarks is not needed but remains in there for the time being to not change the API */ bool ECPGprepare(int lineno, const char *connection_name, const bool questionmarks, const char *name, const char *variable) { struct connection *con; struct prepared_statement *this, *prev; (void) questionmarks; /* quiet the compiler */ con = ecpg_get_connection(connection_name); if (!ecpg_init(con, connection_name, lineno)) return false; /* check if we already have prepared this statement */ this = ecpg_find_prepared_statement(name, con, &prev); if (this && !deallocate_one(lineno, ECPG_COMPAT_PGSQL, con, prev, this)) return false; return prepare_common(lineno, con, name, variable); }
bool ECPGsetcommit(int lineno, const char *mode, const char *connection_name) { struct connection *con = ecpg_get_connection(connection_name); PGresult *results; if (!ecpg_init(con, connection_name, lineno)) return (false); ecpg_log("ECPGsetcommit on line %d: action \"%s\"; connection \"%s\"\n", lineno, mode, con->name); if (con->autocommit == true && strncmp(mode, "off", strlen("off")) == 0) { if (con->committed) { results = PQexec(con->connection, "begin transaction"); if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL)) return false; PQclear(results); con->committed = false; } con->autocommit = false; } else if (con->autocommit == false && strncmp(mode, "on", strlen("on")) == 0) { if (!con->committed) { results = PQexec(con->connection, "commit"); if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL)) return false; PQclear(results); con->committed = true; } con->autocommit = true; } 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; 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; }
/* 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; }