Exemple #1
0
RETCODE SQL_API
SQLNativeSqlW(HDBC			hdbc,
			  SQLWCHAR	   *szSqlStrIn,
			  SQLINTEGER	cbSqlStrIn,
			  SQLWCHAR	   *szSqlStr,
			  SQLINTEGER	cbSqlStrMax,
			  SQLINTEGER   *pcbSqlStr)
{
	CSTR func = "SQLNativeSqlW";
	RETCODE		ret;
	char		*szIn, *szOut = NULL, *szOutt = NULL;
	SQLLEN		slen;
	SQLINTEGER	buflen, olen;
	ConnectionClass *conn = (ConnectionClass *) hdbc;

	mylog("[%s}", func);
	CC_examine_global_transaction(conn);
	ENTER_CONN_CS(conn);
	CC_clear_error(conn);
	CC_set_in_unicode_driver(conn);
	szIn = ucs2_to_utf8(szSqlStrIn, cbSqlStrIn, &slen, FALSE);
	buflen = 3 * cbSqlStrMax;
	if (buflen > 0)
		szOutt = malloc(buflen);
	for (;; buflen = olen + 1, szOutt = realloc(szOut, buflen))
	{
		if (!szOutt)
		{
			CC_set_error(conn, CONN_NO_MEMORY_ERROR, "Could not allocate memory for output buffer", func);
			ret = SQL_ERROR;
			break;
		}
		szOut = szOutt;
		ret = PGAPI_NativeSql(hdbc, (SQLCHAR *) szIn, (SQLINTEGER) slen,
							  (SQLCHAR *) szOut, buflen, &olen);
		if (SQL_SUCCESS_WITH_INFO != ret || olen < buflen)
			break;
	}
	if (szIn)
		free(szIn);
	if (SQL_SUCCEEDED(ret))
	{
		SQLLEN	szcount = olen;

		if (olen < buflen)
			szcount = utf8_to_ucs2(szOut, olen, szSqlStr, cbSqlStrMax);
		if (SQL_SUCCESS == ret && szcount > cbSqlStrMax)
		{
			ConnectionClass	*conn = (ConnectionClass *) hdbc;

			ret = SQL_SUCCESS_WITH_INFO;
			CC_set_error(conn, CONN_TRUNCATED, "Sql string too large", func);
		}
		if (pcbSqlStr)
			*pcbSqlStr = (SQLINTEGER) szcount;
	}
	LEAVE_CONN_CS(conn);
	free(szOut);
	return ret;
}
Exemple #2
0
/*
 *	This API allocates a Application descriptor.
 */
RETCODE SQL_API PGAPI_AllocDesc(HDBC ConnectionHandle,
					SQLHDESC *DescriptorHandle)
{
	CSTR func = "PGAPI_AllocDesc";
	ConnectionClass	*conn = (ConnectionClass *) ConnectionHandle;
	RETCODE	ret = SQL_SUCCESS;
	DescriptorClass	*desc = (DescriptorClass *) malloc(sizeof(DescriptorAlloc));

	mylog("%s: entering...\n", func);
	if (desc)
	{
		memset(desc, 0, sizeof(DescriptorAlloc));
		DC_get_conn(desc) = conn;
		if (CC_add_descriptor(conn, desc))
			*DescriptorHandle = desc;
		else
		{
			free(desc);
			CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "Maximum number of descriptors exceeded", func);
			ret = SQL_ERROR;
		} 
	}
	else
	{
		CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "No more memory ti allocate a further descriptor", func);
		ret = SQL_ERROR;
	}
	return ret;
}
Exemple #3
0
/*
 *	Returns the SQL string as modified by the driver.
 *	Currently, just copy the input string without modification
 *	observing buffer limits and truncation.
 */
RETCODE		SQL_API
PGAPI_NativeSql(
				HDBC hdbc,
				const SQLCHAR FAR * szSqlStrIn,
				SQLINTEGER cbSqlStrIn,
				SQLCHAR FAR * szSqlStr,
				SQLINTEGER cbSqlStrMax,
				SQLINTEGER FAR * pcbSqlStr)
{
	CSTR func = "PGAPI_NativeSql";
	size_t		len = 0;
	char	   *ptr;
	ConnectionClass *conn = (ConnectionClass *) hdbc;
	RETCODE		result;

	mylog("%s: entering...cbSqlStrIn=%d\n", func, cbSqlStrIn);

	ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL, 0);
	if (!ptr)
	{
		CC_set_error(conn, CONN_NO_MEMORY_ERROR, "No memory available to store native sql string", func);
		return SQL_ERROR;
	}

	result = SQL_SUCCESS;
	len = strlen(ptr);

	if (szSqlStr)
	{
		strncpy_null(szSqlStr, ptr, cbSqlStrMax);

		if (len >= cbSqlStrMax)
		{
			result = SQL_SUCCESS_WITH_INFO;
			CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for the NativeSQL.", func);
		}
	}

	if (pcbSqlStr)
		*pcbSqlStr = (SQLINTEGER) len;

	if (cbSqlStrIn)
		free(ptr);

	return result;
}
Exemple #4
0
RETCODE SQL_API PG_SQLAllocStmt(HDBC      hdbc,
			     HSTMT FAR *phstmt)
{
static char* const func="SQLAllocStmt";
ConnectionClass *conn = (ConnectionClass *) hdbc;
StatementClass *stmt;

	mylog("%s: entering...\n", func);

	if( ! conn) {
		CC_log_error(func, "", NULL);
		return SQL_INVALID_HANDLE;
	}

	stmt = SC_Constructor();

	mylog("**** SQLAllocStmt: hdbc = %u, stmt = %u\n", hdbc, stmt);

	if ( ! stmt) {
		CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "No more memory to allocate a further SQL-statement");
		*phstmt = SQL_NULL_HSTMT;
		CC_log_error(func, "", conn);
		return SQL_ERROR;
	}

    if ( ! CC_add_statement(conn, stmt)) {
	CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "Maximum number of connections exceeded.");
	CC_log_error(func, "", conn);
	SC_Destructor(stmt);
	*phstmt = SQL_NULL_HSTMT;
	return SQL_ERROR;
    }

	*phstmt = (HSTMT) stmt;

	/*	Copy default statement options based from Connection options
	*/
	stmt->options = conn->stmtOptions;

	/*	Save the handle for later */
	stmt->phstmt = phstmt;

    return SQL_SUCCESS;
}
Exemple #5
0
RETCODE SQL_API
SQLBrowseConnectW(HDBC			hdbc,
				  SQLWCHAR	   *szConnStrIn,
				  SQLSMALLINT	cbConnStrIn,
				  SQLWCHAR	   *szConnStrOut,
				  SQLSMALLINT	cbConnStrOutMax,
				  SQLSMALLINT  *pcbConnStrOut)
{
	CSTR func = "SQLBrowseConnectW";
	char	*szIn, *szOut;
	SQLLEN		inlen;
	SQLUSMALLINT	obuflen;
	SQLSMALLINT	olen;
	RETCODE	ret;
	ConnectionClass *conn = (ConnectionClass *) hdbc;

	mylog("[%s]", func);
	CC_examine_global_transaction(conn);
	ENTER_CONN_CS(conn);
	CC_clear_error(conn);
	CC_set_in_unicode_driver(conn);
	szIn = ucs2_to_utf8(szConnStrIn, cbConnStrIn, &inlen, FALSE);
	obuflen = cbConnStrOutMax + 1;
	szOut = malloc(obuflen);
	if (szOut)
		ret = PGAPI_BrowseConnect(hdbc, (SQLCHAR *) szIn, (SQLSMALLINT) inlen,
								  (SQLCHAR *) szOut, cbConnStrOutMax, &olen);
	else
	{
		CC_set_error(conn, CONN_NO_MEMORY_ERROR, "Could not allocate memory for output buffer", func);
		ret = SQL_ERROR;
	}
	LEAVE_CONN_CS(conn);
	if (ret != SQL_ERROR)
	{
		SQLLEN	outlen = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
		if (pcbConnStrOut)
			*pcbConnStrOut = (SQLSMALLINT) outlen;
	}
	free(szOut);
	if (szIn)
		free(szIn);
	return ret;
}
Exemple #6
0
RETCODE		SQL_API
PGAPI_Transact(
			   HENV henv,
			   HDBC hdbc,
			   SQLUSMALLINT fType)
{
	CSTR func = "PGAPI_Transact";
	ConnectionClass *conn;
	char		ok;
	int			lf;

	mylog("entering %s: hdbc=%p, henv=%p\n", func, hdbc, henv);

	if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV)
	{
		CC_log_error(func, "", NULL);
		return SQL_INVALID_HANDLE;
	}

	/*
	 * If hdbc is null and henv is valid, it means transact all
	 * connections on that henv.
	 */
	if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV)
	{
		ConnectionClass * const *conns = getConnList();
		const int	conn_count = getConnCount();
		for (lf = 0; lf < conn_count; lf++)
		{
			conn = conns[lf];

			if (conn && CC_get_env(conn) == henv)
				if (PGAPI_Transact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
					return SQL_ERROR;
		}
		return SQL_SUCCESS;
	}

	conn = (ConnectionClass *) hdbc;

	if (fType != SQL_COMMIT &&
	    fType != SQL_ROLLBACK)
	{
		CC_set_error(conn, CONN_INVALID_ARGUMENT_NO, "PGAPI_Transact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter", func);
		return SQL_ERROR;
	}

	/* If manual commit and in transaction, then proceed. */
	if (CC_loves_visible_trans(conn) && CC_is_in_trans(conn))
	{
		mylog("PGAPI_Transact: sending on conn %p '%d'\n", conn, fType);

		ok = (SQL_COMMIT == fType) ? CC_commit(conn) : CC_abort(conn);
		if (!ok)
		{
			/* error msg will be in the connection */
			CC_on_abort(conn, NO_TRANS);
			CC_log_error(func, "", conn);
			return SQL_ERROR;
		}
	}
	return SQL_SUCCESS;
}
Exemple #7
0
RETCODE		SQL_API
PGAPI_DriverConnect(
					HDBC hdbc,
					HWND hwnd,
					const SQLCHAR FAR * szConnStrIn,
					SQLSMALLINT cbConnStrIn,
					SQLCHAR FAR * szConnStrOut,
					SQLSMALLINT cbConnStrOutMax,
					SQLSMALLINT FAR * pcbConnStrOut,
					SQLUSMALLINT fDriverCompletion)
{
	CSTR func = "PGAPI_DriverConnect";
	ConnectionClass *conn = (ConnectionClass *) hdbc;
	ConnInfo   *ci;

#ifdef WIN32
	RETCODE		dialog_result;
#endif
	BOOL		paramRequired, didUI = FALSE;
	RETCODE		result;
	char		*connStrIn = NULL;
	char		connStrOut[MAX_CONNECT_STRING];
	int			retval;
	char		salt[5];
	char		password_required = AUTH_REQ_OK;
	ssize_t		len = 0;
	SQLSMALLINT	lenStrout;


	mylog("%s: entering...\n", func);

	if (!conn)
	{
		CC_log_error(func, "", NULL);
		return SQL_INVALID_HANDLE;
	}

	connStrIn = make_string(szConnStrIn, cbConnStrIn, NULL, 0);

#ifdef	FORCE_PASSWORD_DISPLAY
	mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, connStrIn);
	qlog("conn=%p, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, connStrIn, fDriverCompletion);
#else
	if (get_qlog() || get_mylog())
	{
		char	*hide_str = hide_password(connStrIn);

		mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, NULL_IF_NULL(hide_str));
		qlog("conn=%p, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, NULL_IF_NULL(hide_str), fDriverCompletion);
		if (hide_str)
			free(hide_str);
	}
#endif	/* FORCE_PASSWORD_DISPLAY */

	ci = &(conn->connInfo);

	/* Parse the connect string and fill in conninfo for this hdbc. */
	dconn_get_connect_attributes(connStrIn, ci);

	/*
	 * If the ConnInfo in the hdbc is missing anything, this function will
	 * fill them in from the registry (assuming of course there is a DSN
	 * given -- if not, it does nothing!)
	 */
	getDSNinfo(ci, CONN_DONT_OVERWRITE);
	dconn_get_common_attributes(connStrIn, ci);
	logs_on_off(1, ci->drivers.debug, ci->drivers.commlog);
	if (connStrIn)
	{
		free(connStrIn);
		connStrIn = NULL;
	}

	/* Fill in any default parameters if they are not there. */
	getDSNdefaults(ci);
	/* initialize pg_version */
	CC_initialize_pg_version(conn);
	memset(salt, 0, sizeof(salt));

#ifdef WIN32
dialog:
#endif
	ci->focus_password = password_required;

inolog("DriverCompletion=%d\n", fDriverCompletion);
	switch (fDriverCompletion)
	{
#ifdef WIN32
		case SQL_DRIVER_PROMPT:
			dialog_result = dconn_DoDialog(hwnd, ci);
			didUI = TRUE;
			if (dialog_result != SQL_SUCCESS)
				return dialog_result;
			break;

		case SQL_DRIVER_COMPLETE_REQUIRED:

			/* Fall through */

		case SQL_DRIVER_COMPLETE:

			paramRequired = password_required;
			/* Password is not a required parameter. */
			if (ci->database[0] == '\0')
				paramRequired = TRUE;
			else if (ci->port[0] == '\0')
				paramRequired = TRUE;
#ifdef	WIN32
			else if (ci->server[0] == '\0')
				paramRequired = TRUE;
#endif /* WIN32 */
			if (paramRequired)
			{
				dialog_result = dconn_DoDialog(hwnd, ci);
				didUI = TRUE;
				if (dialog_result != SQL_SUCCESS)
					return dialog_result;
			}
			break;
#else
		case SQL_DRIVER_PROMPT:
		case SQL_DRIVER_COMPLETE:
		case SQL_DRIVER_COMPLETE_REQUIRED:
#endif
		case SQL_DRIVER_NOPROMPT:
			break;
	}

	/*
	 * Password is not a required parameter unless authentication asks for
	 * it. For now, I think it's better to just let the application ask
	 * over and over until a password is entered (the user can always hit
	 * Cancel to get out)
	 */
	paramRequired = FALSE;
	if (ci->database[0] == '\0')
		paramRequired = TRUE;
	else if (ci->port[0] == '\0')
		paramRequired = TRUE;
#ifdef	WIN32
	else if (ci->server[0] == '\0')
		paramRequired = TRUE;
#endif /* WIN32 */
	if (paramRequired)
	{
		if (didUI)
			return SQL_NO_DATA_FOUND;
		CC_set_error(conn, CONN_OPENDB_ERROR, "connction string lacks some options", func);
		return SQL_ERROR;
	}

inolog("before CC_connect\n");
	/* do the actual connect */
	retval = CC_connect(conn, password_required, salt);
	if (retval < 0)
	{							/* need a password */
		if (fDriverCompletion == SQL_DRIVER_NOPROMPT)
		{
			CC_log_error(func, "Need password but Driver_NoPrompt", conn);
			return SQL_ERROR;	/* need a password but not allowed to
								 * prompt so error */
		}
		else
		{
#ifdef WIN32
			password_required = -retval;
			goto dialog;
#else
			return SQL_ERROR;	/* until a better solution is found. */
#endif
		}
	}
	else if (retval == 0)
	{
		/* error msg filled in above */
		CC_log_error(func, "Error from CC_Connect", conn);
		return SQL_ERROR;
	}

	/*
	 * Create the Output Connection String
	 */
	result = SQL_SUCCESS;

	lenStrout = cbConnStrOutMax;
	if (conn->ms_jet && lenStrout > 255)
		lenStrout = 255;
	makeConnectString(connStrOut, ci, lenStrout);
	len = strlen(connStrOut);

	if (szConnStrOut)
	{
		/*
		 * Return the completed string to the caller. The correct method
		 * is to only construct the connect string if a dialog was put up,
		 * otherwise, it should just copy the connection input string to
		 * the output. However, it seems ok to just always construct an
		 * output string.  There are possible bad side effects on working
		 * applications (Access) by implementing the correct behavior,
		 * anyway.
		 */
		/*strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax);*/
		strncpy(szConnStrOut, connStrOut, cbConnStrOutMax);

		if (len >= cbConnStrOutMax)
		{
			int			clen;

			for (clen = cbConnStrOutMax - 1; clen >= 0 && szConnStrOut[clen] != ';'; clen--)
				szConnStrOut[clen] = '\0';
			result = SQL_SUCCESS_WITH_INFO;
			CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for the ConnStrOut.", func);
		}
	}

	if (pcbConnStrOut)
		*pcbConnStrOut = (SQLSMALLINT) len;

#ifdef	FORCE_PASSWORD_DISPLAY
	if (cbConnStrOutMax > 0)
	{
		mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(szConnStrOut), len, cbConnStrOutMax);
		qlog("conn=%p, PGAPI_DriverConnect(out)='%s'\n", conn, NULL_IF_NULL(szConnStrOut));
	}
#else
	if (get_qlog() || get_mylog())
	{
		char	*hide_str = NULL;

		if (cbConnStrOutMax > 0)
			hide_str = hide_password(szConnStrOut);
		mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(hide_str), len, cbConnStrOutMax);
		qlog("conn=%p, PGAPI_DriverConnect(out)='%s'\n", conn, NULL_IF_NULL(hide_str));
		if (hide_str)
			free(hide_str);
	}
#endif /* FORCE_PASSWORD_DISPLAY */

	if (connStrIn)
		free(connStrIn);
	mylog("PGAPI_DriverConnect: returning %d\n", result);
	return result;
}
Exemple #8
0
void
CC_lookup_characterset(ConnectionClass *self)
{
	char	*encspec = NULL, *currenc = NULL, *tencstr;
	CSTR func = "CC_lookup_characterset";

	mylog("%s: entering...\n", func);
	if (self->original_client_encoding)
		encspec = strdup(self->original_client_encoding);
	if (self->current_client_encoding)
		currenc = strdup(self->current_client_encoding);
	else if (PG_VERSION_LT(self, 7.2))
		currenc = CC_lookup_cs_old(self);
	else
		currenc = CC_lookup_cs_new(self);
	tencstr = encspec ? encspec : currenc;
	if (self->original_client_encoding)
	{
		if (stricmp(self->original_client_encoding, tencstr))
		{
			char msg[256];

			snprintf(msg, sizeof(msg), "The client_encoding '%s' was changed to '%s'", self->original_client_encoding, tencstr);
			CC_set_error(self, CONN_OPTION_VALUE_CHANGED, msg, func);
		}
		free(self->original_client_encoding);
	}
#ifndef	UNICODE_SUPPORT
	else
	{
		const char *wenc = get_environment_encoding(self, encspec, currenc, FALSE);
		if (wenc && (!tencstr || stricmp(tencstr, wenc)))
		{
			QResultClass	*res;
			char		query[64];
			int		errnum = CC_get_errornumber(self);
			BOOL		cmd_success;

			sprintf(query, "set client_encoding to '%s'", wenc);
			res = CC_send_query(self, query, NULL, IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR, NULL);
			cmd_success = QR_command_maybe_successful(res);
			QR_Destructor(res);
			CC_set_errornumber(self, errnum);
			if (cmd_success)
			{
				self->original_client_encoding = strdup(wenc);
				self->ccsc = pg_CS_code(self->original_client_encoding);
				if (encspec)
					free(encspec);
				if (currenc)
					free(currenc);
				return;
			}
		}
	}
#endif /* UNICODE_SUPPORT */
	if (tencstr)
	{
		self->original_client_encoding = tencstr;
		if (encspec && currenc)
			free(currenc);
		self->ccsc = pg_CS_code(tencstr);
		qlog("    [ Client encoding = '%s' (code = %d) ]\n", self->original_client_encoding, self->ccsc);
		if (self->ccsc < 0)
		{
			char msg[256];

			snprintf(msg, sizeof(msg), "would handle the encoding '%s' like ASCII", tencstr);
			CC_set_error(self, CONN_OPTION_VALUE_CHANGED, msg, func); 
		}
	}
	else
	{
		self->ccsc = SQL_ASCII;
		self->original_client_encoding = NULL;
	}
	self->mb_maxbyte_per_char = pg_mb_maxlen(self->ccsc);
}
Exemple #9
0
RETCODE SQL_API
SQLDriverConnectW(HDBC hdbc,
				  HWND hwnd,
				  SQLWCHAR *szConnStrIn,
				  SQLSMALLINT cbConnStrIn,
				  SQLWCHAR *szConnStrOut,
				  SQLSMALLINT cbConnStrOutMax,
				  SQLSMALLINT *pcbConnStrOut,
				  SQLUSMALLINT fDriverCompletion)
{
	CSTR func = "SQLDriverConnectW";
	char	*szIn, *szOut = NULL;
	SQLSMALLINT	maxlen, obuflen = 0;
	SQLLEN		inlen;
	SQLSMALLINT	olen, *pCSO;
	RETCODE	ret;
	ConnectionClass *conn = (ConnectionClass *) hdbc;

	mylog("[%s]", func);
	CC_examine_global_transaction(conn);
	ENTER_CONN_CS(conn);
	CC_clear_error(conn);
	CC_set_in_unicode_driver(conn);
	szIn = ucs2_to_utf8(szConnStrIn, cbConnStrIn, &inlen, FALSE);
	maxlen = cbConnStrOutMax;
	pCSO = NULL;
	olen = 0;
	if (maxlen > 0)
	{
		obuflen = maxlen + 1;
		szOut = malloc(obuflen);
		if (!szOut)
		{
			CC_set_error(conn, CONN_NO_MEMORY_ERROR, "Could not allocate memory for output buffer", func);
			ret = SQL_ERROR;
			goto cleanup;
		}
		pCSO = &olen;
	}
	else if (pcbConnStrOut)
		pCSO = &olen;
	ret = PGAPI_DriverConnect(hdbc, hwnd,
							  (SQLCHAR *) szIn, (SQLSMALLINT) inlen,
							  (SQLCHAR *) szOut, maxlen,
							  pCSO, fDriverCompletion);
	if (ret != SQL_ERROR && NULL != pCSO)
	{
		SQLLEN outlen = olen;

		if (olen < obuflen)
			outlen = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
		else
			utf8_to_ucs2(szOut, maxlen, szConnStrOut, cbConnStrOutMax);
		if (outlen >= cbConnStrOutMax && NULL != szConnStrOut && NULL != pcbConnStrOut)
		{
inolog("cbConnstrOutMax=%d pcb=%p\n", cbConnStrOutMax, pcbConnStrOut);
			if (SQL_SUCCESS == ret)
			{
				CC_set_error(conn, CONN_TRUNCATED, "the ConnStrOut is too small", func);
				ret = SQL_SUCCESS_WITH_INFO;
			}
		}
		if (pcbConnStrOut)
			*pcbConnStrOut = (SQLSMALLINT) outlen;
	}
cleanup:
	LEAVE_CONN_CS(conn);
	if (szOut)
		free(szOut);
	if (szIn)
		free(szIn);
	return ret;
}