Ejemplo n.º 1
0
/* print out an error message */
void
sqlprint(void)
{
	struct sqlca_t *sqlca = ECPGget_sqlca();

	sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml] = '\0';
	fprintf(stderr, ecpg_gettext("SQL error: %s\n"), sqlca->sqlerrm.sqlerrmc);
}
Ejemplo n.º 2
0
void
ecpg_raise_backend(int line, PGresult *result, PGconn *conn, int compat)
{
	struct sqlca_t *sqlca = ECPGget_sqlca();
	char	   *sqlstate;
	char	   *message;

	if (result)
	{
		sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
		if (sqlstate == NULL)
			sqlstate = ECPG_SQLSTATE_ECPG_INTERNAL_ERROR;
		message = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
	}
	else
	{
		sqlstate = ECPG_SQLSTATE_ECPG_INTERNAL_ERROR;
		message = PQerrorMessage(conn);
	}

	if (strcmp(sqlstate, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR) == 0)
	{
		/* we might get here if the connection breaks down, so let's
		 * check for this instead of giving just the generic internal error */
		if (PQstatus(conn) == CONNECTION_BAD)
		{
			sqlstate = "57P02";
			message = ecpg_gettext("the connection to the server was lost");
		}
	}

	/* copy error message */
	snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "%s on line %d", message, line);
	sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);

	/* copy SQLSTATE */
	strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate));

	/* assign SQLCODE for backward compatibility */
	if (strncmp(sqlca->sqlstate, "23505", sizeof(sqlca->sqlstate)) == 0)
		sqlca->sqlcode = INFORMIX_MODE(compat) ? ECPG_INFORMIX_DUPLICATE_KEY : ECPG_DUPLICATE_KEY;
	else if (strncmp(sqlca->sqlstate, "21000", sizeof(sqlca->sqlstate)) == 0)
		sqlca->sqlcode = INFORMIX_MODE(compat) ? ECPG_INFORMIX_SUBSELECT_NOT_ONE : ECPG_SUBSELECT_NOT_ONE;
	else
		sqlca->sqlcode = ECPG_PGSQL;

	/* %.*s is safe here as long as sqlstate is all-ASCII */
	ecpg_log("raising sqlstate %.*s (sqlcode %d): %s\n",
			 sizeof(sqlca->sqlstate), sqlca->sqlstate, sqlca->sqlcode, sqlca->sqlerrm.sqlerrmc);

	/* free all memory we have allocated for the user */
	ECPGfree_auto_mem();
}
Ejemplo n.º 3
0
void
ecpg_log(const char *format,...)
{
	va_list		ap;
	struct sqlca_t *sqlca = ECPGget_sqlca();
	const char *intl_format;
	int			bufsize;
	char	   *fmt;

	if (!simple_debug)
		return;

	/* internationalize the error message string */
	intl_format = ecpg_gettext(format);

	/*
	 * Insert PID into the format, unless ecpg_internal_regression_mode is set
	 * (regression tests want unchanging output).
	 */
	bufsize = strlen(intl_format) + 100;
	fmt = (char *) malloc(bufsize);
	if (fmt == NULL)
		return;

	if (ecpg_internal_regression_mode)
		snprintf(fmt, bufsize, "[NO_PID]: %s", intl_format);
	else
		snprintf(fmt, bufsize, "[%d]: %s", (int) getpid(), intl_format);

#ifdef ENABLE_THREAD_SAFETY
	pthread_mutex_lock(&debug_mutex);
#endif

	va_start(ap, format);
	vfprintf(debugstream, fmt, ap);
	va_end(ap);

	/* dump out internal sqlca variables */
	if (ecpg_internal_regression_mode && sqlca != NULL)
	{
		fprintf(debugstream, "[NO_PID]: sqlca: code: %ld, state: %s\n",
				sqlca->sqlcode, sqlca->sqlstate);
	}

	fflush(debugstream);

#ifdef ENABLE_THREAD_SAFETY
	pthread_mutex_unlock(&debug_mutex);
#endif

	free(fmt);
}
Ejemplo n.º 4
0
/* print out an error message */
void
sqlprint(void)
{
	struct sqlca_t *sqlca = ECPGget_sqlca();

	if (sqlca == NULL)
	{
		ecpg_log("out of memory");
		return;
	}

	sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml] = '\0';
	fprintf(stderr, ecpg_gettext("SQL error: %s\n"), sqlca->sqlerrm.sqlerrmc);
}
Ejemplo n.º 5
0
static void
ECPGnoticeReceiver(void *arg, const PGresult *result)
{
	char	   *sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
	char	   *message = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
	struct sqlca_t *sqlca = ECPGget_sqlca();
	int			sqlcode;

	if (sqlca == NULL)
	{
		ecpg_log("out of memory");
		return;
	}

	(void) arg;					/* keep the compiler quiet */
	if (sqlstate == NULL)
		sqlstate = ECPG_SQLSTATE_ECPG_INTERNAL_ERROR;

	if (message == NULL)		/* Shouldn't happen, but need to be sure */
		message = ecpg_gettext("empty message text");

	/* these are not warnings */
	if (strncmp(sqlstate, "00", 2) == 0)
		return;

	ecpg_log("ECPGnoticeReceiver: %s\n", message);

	/* map to SQLCODE for backward compatibility */
	if (strcmp(sqlstate, ECPG_SQLSTATE_INVALID_CURSOR_NAME) == 0)
		sqlcode = ECPG_WARNING_UNKNOWN_PORTAL;
	else if (strcmp(sqlstate, ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION) == 0)
		sqlcode = ECPG_WARNING_IN_TRANSACTION;
	else if (strcmp(sqlstate, ECPG_SQLSTATE_NO_ACTIVE_SQL_TRANSACTION) == 0)
		sqlcode = ECPG_WARNING_NO_TRANSACTION;
	else if (strcmp(sqlstate, ECPG_SQLSTATE_DUPLICATE_CURSOR) == 0)
		sqlcode = ECPG_WARNING_PORTAL_EXISTS;
	else
		sqlcode = 0;

	strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate));
	sqlca->sqlcode = sqlcode;
	sqlca->sqlwarn[2] = 'W';
	sqlca->sqlwarn[0] = 'W';

	strncpy(sqlca->sqlerrm.sqlerrmc, message, sizeof(sqlca->sqlerrm.sqlerrmc));
	sqlca->sqlerrm.sqlerrmc[sizeof(sqlca->sqlerrm.sqlerrmc) - 1] = 0;
	sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);

	ecpg_log("raising sqlcode %d\n", sqlcode);
}
Ejemplo n.º 6
0
bool
ecpg_init(const struct connection * con, const char *connection_name, const int lineno)
{
	struct sqlca_t *sqlca = ECPGget_sqlca();

	ecpg_init_sqlca(sqlca);
	if (con == NULL)
	{
		ecpg_raise(lineno, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
				   connection_name ? connection_name : ecpg_gettext("NULL"));
		return (false);
	}

	return (true);
}
Ejemplo n.º 7
0
void
ecpg_raise(int line, int code, const char *sqlstate, const char *str)
{
	struct sqlca_t *sqlca = ECPGget_sqlca();

	sqlca->sqlcode = code;
	strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate));

	switch (code)
	{
		case ECPG_NOT_FOUND:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("no data found on line %d"), line);
			break;

		case ECPG_OUT_OF_MEMORY:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("out of memory on line %d"), line);
			break;

		case ECPG_UNSUPPORTED:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
			  ecpg_gettext("unsupported type \"%s\" on line %d"), str, line);
			break;

		case ECPG_TOO_MANY_ARGUMENTS:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("too many arguments on line %d"), line);
			break;

		case ECPG_TOO_FEW_ARGUMENTS:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("too few arguments on line %d"), line);
			break;

		case ECPG_INT_FORMAT:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("invalid input syntax for type int: \"%s\", on line %d"), str, line);
			break;

		case ECPG_UINT_FORMAT:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("invalid input syntax for type unsigned int: \"%s\", on line %d"), str, line);
			break;

		case ECPG_FLOAT_FORMAT:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("invalid input syntax for floating-point type: \"%s\", on line %d"), str, line);
			break;

		case ECPG_CONVERT_BOOL:
			if (str)
				snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

				/*
				 * translator: this string will be truncated at 149 characters
				 * expanded.
				 */
						 ecpg_gettext("invalid syntax for type boolean: \"%s\", on line %d"), str, line);
			else
				snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

				/*
				 * translator: this string will be truncated at 149 characters
				 * expanded.
				 */
						 ecpg_gettext("could not convert boolean value: size mismatch, on line %d"), line);
			break;

		case ECPG_EMPTY:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("empty query on line %d"), line);
			break;

		case ECPG_MISSING_INDICATOR:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
			  ecpg_gettext("null value without indicator on line %d"), line);
			break;

		case ECPG_NO_ARRAY:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("variable does not have an array type on line %d"), line);
			break;

		case ECPG_DATA_NOT_ARRAY:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("data read from server is not an array on line %d"), line);
			break;

		case ECPG_ARRAY_INSERT:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("inserting an array of variables is not supported on line %d"), line);
			break;

		case ECPG_NO_CONN:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("connection \"%s\" does not exist on line %d"), str, line);
			break;

		case ECPG_NOT_CONN:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("not connected to connection \"%s\" on line %d"), str, line);
			break;

		case ECPG_INVALID_STMT:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("invalid statement name \"%s\" on line %d"), str, line);
			break;

		case ECPG_UNKNOWN_DESCRIPTOR:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("descriptor \"%s\" not found on line %d"), str, line);
			break;

		case ECPG_INVALID_DESCRIPTOR_INDEX:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
			 ecpg_gettext("descriptor index out of range on line %d"), line);
			break;

		case ECPG_UNKNOWN_DESCRIPTOR_ITEM:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("unrecognized descriptor item \"%s\" on line %d"), str, line);
			break;

		case ECPG_VAR_NOT_NUMERIC:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("variable does not have a numeric type on line %d"), line);
			break;

		case ECPG_VAR_NOT_CHAR:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("variable does not have a character type on line %d"), line);
			break;

		case ECPG_TRANS:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
			ecpg_gettext("error in transaction processing on line %d"), line);
			break;

		case ECPG_CONNECT:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("could not connect to database \"%s\" on line %d"), str, line);
			break;

		default:
			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),

			/*
			 * translator: this string will be truncated at 149 characters
			 * expanded.
			 */
					 ecpg_gettext("SQL error %d on line %d"), code, line);
			break;
	}

	sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
	ecpg_log("raising sqlcode %d on line %d: %s\n", code, line, sqlca->sqlerrm.sqlerrmc);

	/* free all memory we have allocated for the user */
	ECPGfree_auto_mem();
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
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;
}