RETCODE		SQL_API
SQLExecDirect(HSTMT StatementHandle,
			  SQLCHAR *StatementText, SQLINTEGER TextLength)
{
	CSTR func = "SQLExecDirect";
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) StatementHandle;
	UWORD	flag = 0;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	if (PG_VERSION_GE(SC_get_conn(stmt), 7.4))
		flag |= PODBC_WITH_HOLD;
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
	{
		StartRollbackState(stmt);
		ret = PGAPI_ExecDirect(StatementHandle, StatementText, TextLength, flag);
		ret = DiscardStatementSvp(stmt, ret, FALSE);
	}
	LEAVE_STMT_CS(stmt);
	return ret;
}
RETCODE  SQL_API SQLExecDirectW(HSTMT StatementHandle,
           SQLWCHAR *StatementText, SQLINTEGER TextLength)
{
    CSTR    func = "SQLExecDirectW";
    RETCODE ret;
    char    *stxt;
    SQLLEN  slen;
    StatementClass  *stmt = (StatementClass *) StatementHandle;
    UWORD   flag = 0;

    mylog("[%s]", func);
    stxt = ucs2_to_utf8(StatementText, TextLength, &slen, FALSE);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
    if (PG_VERSION_GE(SC_get_conn(stmt), 7.4))
        flag |= PODBC_WITH_HOLD;
    StartRollbackState(stmt);
    if (SC_opencheck(stmt, func))
        ret = SQL_ERROR;
    else
        ret = PGAPI_ExecDirect(StatementHandle, stxt, (SQLINTEGER) slen, flag);
    ret = DiscardStatementSvp(stmt, ret, FALSE);
    LEAVE_STMT_CS(stmt);
    if (stxt)
        free(stxt);
    return ret;
}
Beispiel #3
0
RETCODE		SQL_API
SQLExecute(HSTMT StatementHandle)
{
	CSTR func = "SQLExecute";
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) StatementHandle;
	UWORD	flag = 0;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	if (PG_VERSION_GE(SC_get_conn(stmt), 7.4))
		flag |= PODBC_WITH_HOLD;
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
	{
		StartRollbackState(stmt);
		stmt->exec_current_row = -1;
		ret = PGAPI_Execute(StatementHandle, flag);
		ret = DiscardStatementSvp(stmt, ret, FALSE);
	}
	LEAVE_STMT_CS(stmt);
	return ret;
}
Beispiel #4
0
/*
 *	Transfer octet length.
 */
Int4
pgtype_transfer_octet_length(StatementClass *stmt, OID type, int column_size)
{
	ConnectionClass	*conn = SC_get_conn(stmt);

	int	coef = 1;
	Int4	maxvarc;
	switch (type)
	{
		case PG_TYPE_VARCHAR:
		case PG_TYPE_BPCHAR:
		case PG_TYPE_TEXT:
			if (SQL_NO_TOTAL == column_size)
				return column_size;
#ifdef	UNICODE_SUPPORT
			if (CC_is_in_unicode_driver(conn))
				return column_size * WCLEN;
#endif /* UNICODE_SUPPORT */
			/* after 7.2 */
			if (PG_VERSION_GE(conn, 7.2))
				coef = conn->mb_maxbyte_per_char;
			if (coef < 2 && (conn->connInfo).lf_conversion)
				/* CR -> CR/LF */
				coef = 2;
			if (coef == 1)
				return column_size;
			maxvarc = conn->connInfo.drivers.max_varchar_size;
			if (column_size <= maxvarc && column_size * coef > maxvarc)
				return maxvarc;
			return coef * column_size;
		case PG_TYPE_BYTEA:
			return column_size;
		default:
			if (type == conn->lobj_type)
				return column_size;
	}
	return -1;
}
Beispiel #5
0
int
StartRollbackState(StatementClass *stmt)
{
	CSTR	func = "StartRollbackState";
	int	ret;
	ConnectionClass	*conn;
	ConnInfo	*ci = NULL;
	
inolog("%s:%p->internal=%d\n", func, stmt, stmt->internal);
	conn = SC_get_conn(stmt);
	if (conn)
		ci = &conn->connInfo;
	ret = 0;
	if (!ci || ci->rollback_on_error < 0) /* default */
	{
		if (conn && PG_VERSION_GE(conn, 8.0))
			ret = 2; /* statement rollback */
		else
			ret = 1; /* transaction rollback */
	}
	else
	{
		ret = ci->rollback_on_error;
		if (2 == ret && PG_VERSION_LT(conn, 8.0))
			ret = 1;
	}
	switch (ret)
	{
		case 1:
			SC_start_tc_stmt(stmt);
			break;
		case 2:
			SC_start_rb_stmt(stmt);
			break;
	}
	return	ret;
}
Beispiel #6
0
void
SC_setInsertedTable(StatementClass *stmt, RETCODE retval)
{
	const char *cmd = stmt->statement, *ptr;
	ConnectionClass	*conn;
	size_t	len;

	if (STMT_TYPE_INSERT != stmt->statement_type)
		return;
	if (SQL_NEED_DATA == retval)
		return;
	conn = SC_get_conn(stmt);
#ifdef	NOT_USED /* give up the use of lastval() */	
	if (PG_VERSION_GE(conn, 8.1)) /* lastval() is available */
		return;
#endif /* NOT_USED */
	/*if (!CC_fake_mss(conn))
		return;*/
	while (isspace((UCHAR) *cmd)) cmd++;
	if (!*cmd)
        	return;
	len = 6;
	if (strnicmp(cmd, "insert", len))
        	return;
	cmd += len;
	while (isspace((UCHAR) *(++cmd)));
	if (!*cmd)
        	return;
	len = 4;
	if (strnicmp(cmd, "into", len))
        	return;
	cmd += len;
	while (isspace((UCHAR) *(++cmd)));
	if (!*cmd)
        	return;
	NULL_THE_NAME(conn->schemaIns);
	NULL_THE_NAME(conn->tableIns);
	if (!SQL_SUCCEEDED(retval))
		return;
	ptr = NULL;
	if (IDENTIFIER_QUOTE == *cmd)
	{
		if (ptr = strchr(cmd + 1, IDENTIFIER_QUOTE), NULL == ptr)
			return;
		if ('.' == ptr[1])
		{
			len = ptr - cmd - 1;
			STRN_TO_NAME(conn->schemaIns, cmd + 1, len);
			cmd = ptr + 2;
			ptr = NULL;
		}
	}
	else
	{
		if (ptr = strchr(cmd + 1, '.'), NULL != ptr)
		{
			len = ptr - cmd;
			STRN_TO_NAME(conn->schemaIns, cmd, len);
			cmd = ptr + 1;
			ptr = NULL; 
		}
	}
	if (IDENTIFIER_QUOTE == *cmd && NULL == ptr)
	{
		if (ptr = strchr(cmd + 1, IDENTIFIER_QUOTE), NULL == ptr)
			return;
	}
	if (IDENTIFIER_QUOTE == *cmd)
	{
		len = ptr - cmd - 1;
		STRN_TO_NAME(conn->tableIns, cmd + 1, len);
	}
	else
	{
		ptr = cmd;
		while (*ptr && !isspace((UCHAR) *ptr)) ptr++;
		len = ptr - cmd;
		STRN_TO_NAME(conn->tableIns, cmd, len);
	}
}
Beispiel #7
0
/*
 *	Must be in a transaction or the subsequent execution
 *	invokes a transaction.
 */
RETCODE
SetStatementSvp(StatementClass *stmt)
{
	CSTR	func = "SetStatementSvp";
	char	esavepoint[32], cmd[64];
	ConnectionClass	*conn = SC_get_conn(stmt);
	QResultClass *res;
	RETCODE	ret = SQL_SUCCESS_WITH_INFO;

	if (CC_is_in_error_trans(conn))
		return ret;

	if (0 == stmt->lock_CC_for_rb)
	{
		ENTER_CONN_CS(conn);
		stmt->lock_CC_for_rb++;
	}
	switch (stmt->statement_type)
	{
		case STMT_TYPE_SPECIAL:
		case STMT_TYPE_TRANSACTION:
			return ret;
	}
	if (!SC_accessed_db(stmt))
	{
		BOOL	need_savep = FALSE;

		if (stmt->internal)
		{
			if (PG_VERSION_GE(conn, 8.0))
				SC_start_rb_stmt(stmt);
			else
				SC_start_tc_stmt(stmt);
		}
		if (SC_is_rb_stmt(stmt))
		{
			if (CC_is_in_trans(conn))
			{
				need_savep = TRUE;
			}
		}
		if (need_savep)
		{
			sprintf(esavepoint, "_EXEC_SVP_%p", stmt);
			snprintf(cmd, sizeof(cmd), "SAVEPOINT %s", esavepoint);
			res = CC_send_query(conn, cmd, NULL, 0, NULL);
			if (QR_command_maybe_successful(res))
			{
				SC_set_accessed_db(stmt);
				SC_start_rbpoint(stmt);
				ret = SQL_SUCCESS;
			}
			else
			{
				SC_set_error(stmt, STMT_INTERNAL_ERROR, "internal SAVEPOINT failed", func);
				ret = SQL_ERROR;
			}
			QR_Destructor(res);
		}
		else
			SC_set_accessed_db(stmt);
	}
inolog("%s:%p->accessed=%d\n", func, stmt, SC_accessed_db(stmt));
	return ret;
}
Beispiel #8
0
/*
 *	This function works under Windows or Unicode case only.
 *	Simply returns NULL under other OSs.
 */
const char * get_environment_encoding(const ConnectionClass *conn, const char *setenc, const char *currenc, BOOL bStartup)
{
	const char *wenc = NULL;
#ifdef	WIN32
	int	acp;
#endif /* WIN32 */

#ifdef	UNICODE_SUPPORT
	if (CC_is_in_unicode_driver(conn))
		return "UTF8";
#endif /* UNICODE_SUPPORT */
	if (setenc && stricmp(setenc, OTHER_STRING))
		return setenc;
#ifdef	WIN32
	acp = GetACP();
	if (acp >= 1251 && acp <= 1258)
	{
		if (bStartup ||
		    stricmp(currenc, "SQL_ASCII") == 0)
			return wenc;
	}
	switch (acp)
	{
		case 932:
			wenc = "SJIS";
			break;
		case 936:
			if (!bStartup && PG_VERSION_GT(conn, 7.2))
				wenc = "GBK";
			break;
		case 949:
			if (!bStartup && PG_VERSION_GT(conn, 7.2))  
				wenc = "UHC";
			break;
		case 950:
			wenc = "BIG5";
			break;
		case 1250:
			wenc = "WIN1250";
			break;
		case 1251:
			wenc = "WIN1251";
			break;
		case 1256:
			if (PG_VERSION_GE(conn, 7.3))
				wenc = "WIN1256";
			break;
		case 1252:
			if (strnicmp(currenc, "LATIN", 5) == 0)
				break;
			if (PG_VERSION_GE(conn, 8.1))
				wenc = "WIN1252";
			else
				wenc = "LATIN1";
			break;
		case 1258:
			if (PG_VERSION_GE(conn, 8.1))
				wenc = "WIN1258";
			break;
		case 1253:
			if (PG_VERSION_GE(conn, 8.2))
				wenc = "WIN1253";
			break;
		case 1254:
			if (PG_VERSION_GE(conn, 8.2))
				wenc = "WIN1254";
			break;
		case 1255:
			if (PG_VERSION_GE(conn, 8.2))
				wenc = "WIN1255";
			break;
		case 1257:
			if (PG_VERSION_GE(conn, 8.2))
				wenc = "WIN1257";
			break;
	}
#endif /* WIN32 */
	return wenc;
}
Beispiel #9
0
/*
 *	This corresponds to "precision" in ODBC 2.x.
 *
 *	For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
 *	override this length with the atttypmod length from pg_attribute .
 *
 *	If col >= 0, then will attempt to get the info from the result set.
 *	This is used for functions SQLDescribeCol and SQLColAttributes.
 */
Int4	/* PostgreSQL restriction */
pgtype_column_size(StatementClass *stmt, OID type, int col, int handle_unknown_size_as)
{
	ConnectionClass *conn = SC_get_conn(stmt);
	ConnInfo	*ci = &(conn->connInfo);

	if (handle_unknown_size_as == UNKNOWNS_AS_DEFAULT)
		handle_unknown_size_as = ci->drivers.unknown_sizes; 
	switch (type)
	{
		case PG_TYPE_CHAR:
			return 1;
		case PG_TYPE_CHAR2:
			return 2;
		case PG_TYPE_CHAR4:
			return 4;
		case PG_TYPE_CHAR8:
			return 8;

		case PG_TYPE_NAME:
			{
				int	value = 0;
				if (PG_VERSION_GT(conn, 7.4))
					value = CC_get_max_idlen(conn);
#ifdef	NAME_FIELD_SIZE
				else
					value = NAME_FIELD_SIZE;
#endif /* NAME_FIELD_SIZE */
				if (0 == value)
				{
					if (PG_VERSION_GE(conn, 7.3))
						value = NAMEDATALEN_V73;
					else
						value = NAMEDATALEN_V72;
				}
				return value;
			}

		case PG_TYPE_INT2:
			return 5;

		case PG_TYPE_OID:
		case PG_TYPE_XID:
		case PG_TYPE_INT4:
			return 10;

		case PG_TYPE_INT8:
			return 19;			/* signed */

		case PG_TYPE_NUMERIC:
			return getNumericColumnSize(stmt, type, col);

		case PG_TYPE_FLOAT4:
		case PG_TYPE_MONEY:
			return 7;

		case PG_TYPE_FLOAT8:
			return 15;

		case PG_TYPE_DATE:
			return 10;
		case PG_TYPE_TIME:
			return 8;

		case PG_TYPE_ABSTIME:
		case PG_TYPE_TIMESTAMP:
			return 22;
		case PG_TYPE_DATETIME:
		case PG_TYPE_TIMESTAMP_NO_TMZONE:
			/* return 22; */
			return getTimestampColumnSize(stmt, type, col);

		case PG_TYPE_BOOL:
			return ci->true_is_minus1 ? 2 : 1;

		case PG_TYPE_MACADDR:
			return 17;

		case PG_TYPE_INET:
		case PG_TYPE_CIDR:
			return sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128");
		case PG_TYPE_UUID:
			return sizeof("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");

		case PG_TYPE_LO_UNDEFINED:
			return SQL_NO_TOTAL;

		default:

			if (type == stmt->hdbc->lobj_type)	/* hack until permanent
												 * type is available */
				return SQL_NO_TOTAL;
			if (PG_TYPE_BYTEA == type && ci->bytea_as_longvarbinary)
				return SQL_NO_TOTAL;

			/* Handle Character types and unknown types */
			return getCharColumnSize(stmt, type, col, handle_unknown_size_as);
	}
}
Beispiel #10
0
Int4
getCharColumnSize(StatementClass *stmt, OID type, int col, int handle_unknown_size_as)
{
	CSTR	func = "getCharColumnSize";
	int		p = -1, attlen = -1, adtsize = -1, maxsize;
	QResultClass	*result;
	ConnectionClass	*conn = SC_get_conn(stmt);
	ConnInfo	*ci = &(conn->connInfo);

	mylog("%s: type=%d, col=%d, unknown = %d\n", func, type, col, handle_unknown_size_as);

	/* Assign Maximum size based on parameters */
	switch (type)
	{
		case PG_TYPE_TEXT:
			if (ci->drivers.text_as_longvarchar)
				maxsize = ci->drivers.max_longvarchar_size;
			else
				maxsize = ci->drivers.max_varchar_size;
			break;

		case PG_TYPE_VARCHAR:
		case PG_TYPE_BPCHAR:
			maxsize = ci->drivers.max_varchar_size;
			break;

		default:
			if (ci->drivers.unknowns_as_longvarchar)
				maxsize = ci->drivers.max_longvarchar_size;
			else
				maxsize = ci->drivers.max_varchar_size;
			break;
	}
#ifdef	UNICODE_SUPPORT
	if (CC_is_in_unicode_driver(conn) &&
	    isSqlServr() &&
	    maxsize > 4000)
		maxsize = 4000;
#endif /* UNICODE_SUPPORT */

	if (maxsize == TEXT_FIELD_SIZE + 1) /* magic length for testing */
	{
		if (PG_VERSION_GE(SC_get_conn(stmt), 7.1))
			maxsize = 0;
		else
			maxsize = TEXT_FIELD_SIZE;
	}
	/*
	 * Static ColumnSize (i.e., the Maximum ColumnSize of the datatype) This
	 * has nothing to do with a result set.
	 */
	if (col < 0)
		return maxsize;

	if (result = SC_get_Curres(stmt), NULL == result)
		return maxsize;

	/*
	 * Catalog Result Sets -- use assigned column width (i.e., from
	 * set_tuplefield_string)
	 */
	adtsize = QR_get_fieldsize(result, col);
	if (stmt->catalog_result)
	{
		if (adtsize > 0)
			return adtsize;
		return maxsize;
	}

	p = QR_get_display_size(result, col); /* longest */
	attlen = QR_get_atttypmod(result, col);
	/* Size is unknown -- handle according to parameter */
	if (attlen > 0)	/* maybe the length is known */
	{
		if (attlen >= p)
			return attlen;
		switch (type)
		{
			case PG_TYPE_VARCHAR:
			case PG_TYPE_BPCHAR:
#if (ODBCVER >= 0x0300)
				return attlen;
#else
				if (CC_is_in_unicode_driver(conn) || conn->ms_jet)
					return attlen;
				return p;
#endif /* ODBCVER */
		}
	}

	/* The type is really unknown */
	switch (handle_unknown_size_as)
	{
		case UNKNOWNS_AS_DONTKNOW:
			return -1;
		case UNKNOWNS_AS_LONGEST:
			mylog("%s: LONGEST: p = %d\n", func, p);
			if (p > 0)
				return p;
			break;
		case UNKNOWNS_AS_MAX:
			break;
		default:
			return -1;
	}
	if (maxsize <= 0)
		return maxsize;
	switch (type)
	{
		case PG_TYPE_BPCHAR:
		case PG_TYPE_VARCHAR:
		case PG_TYPE_TEXT:
			return maxsize;
	}

	if (p > maxsize)
		maxsize = p;
	return maxsize;
}
Beispiel #11
0
OID
sqltype_to_pgtype(StatementClass *stmt, SQLSMALLINT fSqlType)
{
	OID		pgType;
	ConnectionClass	*conn = SC_get_conn(stmt);
	ConnInfo	*ci = &(conn->connInfo);

	pgType = 0; /* ??? */
	switch (fSqlType)
	{
		case SQL_BINARY:
			pgType = PG_TYPE_BYTEA;
			break;

		case SQL_CHAR:
			pgType = PG_TYPE_BPCHAR;
			break;

#ifdef	UNICODE_SUPPORT
		case SQL_WCHAR:
			pgType = PG_TYPE_BPCHAR;
			break;
#endif /* UNICODE_SUPPORT */

		case SQL_BIT:
			pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
			break;

#if (ODBCVER >= 0x0300)
		case SQL_TYPE_DATE:
#endif /* ODBCVER */
		case SQL_DATE:
			pgType = PG_TYPE_DATE;
			break;

		case SQL_DOUBLE:
		case SQL_FLOAT:
			pgType = PG_TYPE_FLOAT8;
			break;

		case SQL_DECIMAL:
		case SQL_NUMERIC:
			pgType = PG_TYPE_NUMERIC;
			break;

		case SQL_BIGINT:
			pgType = PG_TYPE_INT8;
			break;

		case SQL_INTEGER:
			pgType = PG_TYPE_INT4;
			break;

		case SQL_LONGVARBINARY:
			if (ci->bytea_as_longvarbinary)
				pgType = PG_TYPE_BYTEA;
			else
				pgType = conn->lobj_type;
			break;

		case SQL_LONGVARCHAR:
			pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
			break;

#ifdef	UNICODE_SUPPORT
		case SQL_WLONGVARCHAR:
			pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
			break;
#endif /* UNICODE_SUPPORT */

		case SQL_REAL:
			pgType = PG_TYPE_FLOAT4;
			break;

		case SQL_SMALLINT:
		case SQL_TINYINT:
			pgType = PG_TYPE_INT2;
			break;

		case SQL_TIME:
#if (ODBCVER >= 0x0300)
		case SQL_TYPE_TIME:
#endif /* ODBCVER */
			pgType = PG_TYPE_TIME;
			break;

		case SQL_TIMESTAMP:
#if (ODBCVER >= 0x0300)
		case SQL_TYPE_TIMESTAMP:
#endif /* ODBCVER */
			pgType = PG_TYPE_DATETIME;
			break;

		case SQL_VARBINARY:
			pgType = PG_TYPE_BYTEA;
			break;

		case SQL_VARCHAR:
			pgType = PG_TYPE_VARCHAR;
			break;

#if	UNICODE_SUPPORT
		case SQL_WVARCHAR:
			pgType = PG_TYPE_VARCHAR;
			break;
#endif /* UNICODE_SUPPORT */

#if (ODBCVER >= 0x0350)
		case SQL_GUID:
			if (PG_VERSION_GE(conn, 8.3))
				pgType = PG_TYPE_UUID;
			break;
#endif /* ODBCVER */

	}

	return pgType;
}
Beispiel #12
0
/*
 *	The length in bytes of data transferred on an SQLGetData, SQLFetch,
 *	or SQLFetchScroll operation if SQL_C_DEFAULT is specified.
 */
Int4
pgtype_buffer_length(StatementClass *stmt, OID type, int col, int handle_unknown_size_as)
{
	ConnectionClass	*conn = SC_get_conn(stmt);

	switch (type)
	{
		case PG_TYPE_INT2:
			return 2; /* sizeof(SQLSMALLINT) */

		case PG_TYPE_OID:
		case PG_TYPE_XID:
		case PG_TYPE_INT4:
			return 4; /* sizeof(SQLINTEGER) */

		case PG_TYPE_INT8:
			if (SQL_C_CHAR == pgtype_to_ctype(stmt, type))
				return 20;			/* signed: 19 digits + sign */
			return 8; /* sizeof(SQLSBININT) */

		case PG_TYPE_NUMERIC:
			return getNumericColumnSize(stmt, type, col) + 2;

		case PG_TYPE_FLOAT4:
		case PG_TYPE_MONEY:
			return 4; /* sizeof(SQLREAL) */

		case PG_TYPE_FLOAT8:
			return 8; /* sizeof(SQLFLOAT) */

		case PG_TYPE_DATE:
		case PG_TYPE_TIME:
			return 6;		/* sizeof(DATE(TIME)_STRUCT) */

		case PG_TYPE_ABSTIME:
		case PG_TYPE_DATETIME:
		case PG_TYPE_TIMESTAMP:
		case PG_TYPE_TIMESTAMP_NO_TMZONE:
			return 16;		/* sizeof(TIMESTAMP_STRUCT) */

		case PG_TYPE_UUID:
			return 16;		/* sizeof(SQLGUID) */

			/* Character types use the default precision */
		case PG_TYPE_VARCHAR:
		case PG_TYPE_BPCHAR:
			{
			int	coef = 1;
			Int4	prec = pgtype_column_size(stmt, type, col, handle_unknown_size_as), maxvarc;
			if (SQL_NO_TOTAL == prec)
				return prec;
#ifdef	UNICODE_SUPPORT
			if (CC_is_in_unicode_driver(conn))
				return prec * WCLEN;
#endif /* UNICODE_SUPPORT */
			/* after 7.2 */
			if (PG_VERSION_GE(conn, 7.2))
				coef = conn->mb_maxbyte_per_char;
			if (coef < 2 && (conn->connInfo).lf_conversion)
				/* CR -> CR/LF */
				coef = 2;
			if (coef == 1)
				return prec;
			maxvarc = conn->connInfo.drivers.max_varchar_size;
			if (prec <= maxvarc && prec * coef > maxvarc)
				return maxvarc;
			return coef * prec;
			}
		default:
			return pgtype_column_size(stmt, type, col, handle_unknown_size_as);
	}
}
Beispiel #13
0
static const char *
get_environment_encoding(const ConnectionClass *conn, const char *setenc, const char *currenc)
{
	const char *wenc = NULL;
#ifdef	WIN32
	int	acp;
#endif /* WIN32 */

	if (setenc && stricmp(setenc, "OTHER"))
		return setenc;
	if (wenc = getenv("PGCLIENTENCODING"), NULL != wenc)
		return wenc;
#ifdef	WIN32
	acp = GetACP();
	if (acp >= 1251 && acp <= 1258)
	{
		if (stricmp(currenc, "SQL_ASCII") == 0)
			return wenc;
	}
	switch (acp)
	{
		case 932:
			wenc = "SJIS";
			break;
		case 936:
			wenc = "GBK";
			break;
		case 949:
			wenc = "UHC";
			break;
		case 950:
			wenc = "BIG5";
			break;
		case 1250:
			wenc = "WIN1250";
			break;
		case 1251:
			wenc = "WIN1251";
			break;
		case 1256:
			wenc = "WIN1256";
			break;
		case 1252:
			if (strnicmp(currenc, "LATIN", 5) == 0)
				break;
			if (PG_VERSION_GE(conn, 8.1))
				wenc = "WIN1252";
			else
				wenc = "LATIN1";
			break;
		case 1258:
			if (PG_VERSION_GE(conn, 8.1))
				wenc = "WIN1258";
			break;
		case 1253:
			if (PG_VERSION_GE(conn, 8.2))
				wenc = "WIN1253";
			break;
		case 1254:
			if (PG_VERSION_GE(conn, 8.2))
				wenc = "WIN1254";
			break;
		case 1255:
			if (PG_VERSION_GE(conn, 8.2))
				wenc = "WIN1255";
			break;
		case 1257:
			if (PG_VERSION_GE(conn, 8.2))
				wenc = "WIN1257";
			break;
	}
#endif /* WIN32 */
	return wenc;
}
Beispiel #14
0
/*
 *	Read in field descriptions.
 *	If self is not null, then also store the information.
 *	If self is null, then just read, don't store.
 */
char
CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
{
	CSTR		func = "CI_read_fields";
	Int2		lf;
	int			new_num_fields;
	OID		new_adtid, new_relid = 0, new_attid = 0;
	Int2		new_adtsize;
	Int4		new_atttypmod = -1;

	/* COLUMN_NAME_STORAGE_LEN may be sufficient but for safety */
	char		new_field_name[2 * COLUMN_NAME_STORAGE_LEN + 1];
	SocketClass *sock;
	ConnInfo   *ci;

	sock = CC_get_socket(conn);
	ci = &conn->connInfo;

	/* at first read in the number of fields that are in the query */
	new_num_fields = (Int2) SOCK_get_int(sock, sizeof(Int2));

	mylog("num_fields = %d\n", new_num_fields);

	if (self)
		/* according to that allocate memory */
		CI_set_num_fields(self, new_num_fields, PROTOCOL_74(ci));

	/* now read in the descriptions */
	for (lf = 0; lf < new_num_fields; lf++)
	{
		SOCK_get_string(sock, new_field_name, 2 * COLUMN_NAME_STORAGE_LEN);
		if (PROTOCOL_74(ci))	/* tableid & columnid */
		{
			new_relid = SOCK_get_int(sock, sizeof(Int4));
			new_attid = SOCK_get_int(sock, sizeof(Int2));
		}
		new_adtid = (OID) SOCK_get_int(sock, 4);
		new_adtsize = (Int2) SOCK_get_int(sock, 2);

		/* If 6.4 protocol, then read the atttypmod field */
		if (PG_VERSION_GE(conn, 6.4))
		{
			mylog("READING ATTTYPMOD\n");
			new_atttypmod = (Int4) SOCK_get_int(sock, 4);

			/* Subtract the header length */
			switch (new_adtid)
			{
				case PG_TYPE_DATETIME:
				case PG_TYPE_TIMESTAMP_NO_TMZONE:
				case PG_TYPE_TIME:
				case PG_TYPE_TIME_WITH_TMZONE:
					break;
				default:
					new_atttypmod -= 4;
			}
			if (new_atttypmod < 0)
				new_atttypmod = -1;
			if (PROTOCOL_74(ci))	/* format */
				SOCK_get_int(sock, sizeof(Int2));

		}

		mylog("%s: fieldname='%s', adtid=%d, adtsize=%d, atttypmod=%d (rel,att)=(%d,%d)\n", func, new_field_name, new_adtid, new_adtsize, new_atttypmod, new_relid, new_attid);

		if (self)
			CI_set_field_info(self, lf, new_field_name, new_adtid, new_adtsize, new_atttypmod, new_relid, new_attid);
	}

	return (SOCK_get_errcode(sock) == 0);
}
Beispiel #15
0
OID
sqltype_to_pgtype(const ConnectionClass *conn, SQLSMALLINT fSqlType)
{
	OID		pgType;
	const ConnInfo	*ci = &(conn->connInfo);

	pgType = 0; /* ??? */
	switch (fSqlType)
	{
		case SQL_BINARY:
			pgType = PG_TYPE_BYTEA;
			break;

		case SQL_CHAR:
			pgType = PG_TYPE_BPCHAR;
			break;

#ifdef	UNICODE_SUPPORT
		case SQL_WCHAR:
			pgType = PG_TYPE_BPCHAR;
			break;
#endif /* UNICODE_SUPPORT */

		case SQL_BIT:
			pgType = PG_TYPE_BOOL;
			break;

		case SQL_TYPE_DATE:
		case SQL_DATE:
			pgType = PG_TYPE_DATE;
			break;

		case SQL_DOUBLE:
		case SQL_FLOAT:
			pgType = PG_TYPE_FLOAT8;
			break;

		case SQL_DECIMAL:
		case SQL_NUMERIC:
			pgType = PG_TYPE_NUMERIC;
			break;

		case SQL_BIGINT:
			pgType = PG_TYPE_INT8;
			break;

		case SQL_INTEGER:
			pgType = PG_TYPE_INT4;
			break;

		case SQL_LONGVARBINARY:
			if (ci->bytea_as_longvarbinary)
				pgType = PG_TYPE_BYTEA;
			else
				pgType = conn->lobj_type;
			break;

		case SQL_LONGVARCHAR:
			pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
			break;

#ifdef	UNICODE_SUPPORT
		case SQL_WLONGVARCHAR:
			pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
			break;
#endif /* UNICODE_SUPPORT */

		case SQL_REAL:
			pgType = PG_TYPE_FLOAT4;
			break;

		case SQL_SMALLINT:
		case SQL_TINYINT:
			pgType = PG_TYPE_INT2;
			break;

		case SQL_TIME:
		case SQL_TYPE_TIME:
			pgType = PG_TYPE_TIME;
			break;

		case SQL_TIMESTAMP:
		case SQL_TYPE_TIMESTAMP:
			pgType = PG_TYPE_DATETIME;
			break;

		case SQL_VARBINARY:
			pgType = PG_TYPE_BYTEA;
			break;

		case SQL_VARCHAR:
			pgType = PG_TYPE_VARCHAR;
			break;

#ifdef	UNICODE_SUPPORT
		case SQL_WVARCHAR:
			pgType = PG_TYPE_VARCHAR;
			break;
#endif /* UNICODE_SUPPORT */

		case SQL_GUID:
			if (PG_VERSION_GE(conn, 8.3))
				pgType = PG_TYPE_UUID;
			break;

		case SQL_INTERVAL_MONTH:
		case SQL_INTERVAL_YEAR:
		case SQL_INTERVAL_YEAR_TO_MONTH:
		case SQL_INTERVAL_DAY:
		case SQL_INTERVAL_HOUR:
		case SQL_INTERVAL_MINUTE:
		case SQL_INTERVAL_SECOND:
		case SQL_INTERVAL_DAY_TO_HOUR:
		case SQL_INTERVAL_DAY_TO_MINUTE:
		case SQL_INTERVAL_DAY_TO_SECOND:
		case SQL_INTERVAL_HOUR_TO_MINUTE:
		case SQL_INTERVAL_HOUR_TO_SECOND:
		case SQL_INTERVAL_MINUTE_TO_SECOND:
			pgType = PG_TYPE_INTERVAL;
			break;
	}

	return pgType;
}
Beispiel #16
0
/*
 * Casting parameters e.g. ?::timestamp is much more flexible
 * than specifying parameter datatype oids determined by
 * sqltype_to_bind_pgtype() via parse message.
 */
const char *
sqltype_to_pgcast(const ConnectionClass *conn, SQLSMALLINT fSqlType)
{
	const char *pgCast = NULL_STRING;

	switch (fSqlType)
	{
		case SQL_BINARY:
		case SQL_VARBINARY:
			pgCast = "::bytea";
			break;
		case SQL_TYPE_DATE:
		case SQL_DATE:
			pgCast = "::date";
			break;
		case SQL_DECIMAL:
		case SQL_NUMERIC:
			pgCast = "::numeric";
			break;
		case SQL_BIGINT:
			pgCast = "::int8";
			break;
		case SQL_INTEGER:
			pgCast = "::int4";
			break;
		case SQL_REAL:
			pgCast = "::float4";
			break;
		case SQL_SMALLINT:
		case SQL_TINYINT:
			pgCast = "::int2";
			break;
		case SQL_TIME:
		case SQL_TYPE_TIME:
			pgCast = "::time";
			break;
		case SQL_TIMESTAMP:
		case SQL_TYPE_TIMESTAMP:
			pgCast = "::timestamp";
			break;
		case SQL_GUID:
			if (PG_VERSION_GE(conn, 8.3))
				pgCast = "::uuid";
			break;
		case SQL_INTERVAL_MONTH:
		case SQL_INTERVAL_YEAR:
		case SQL_INTERVAL_YEAR_TO_MONTH:
		case SQL_INTERVAL_DAY:
		case SQL_INTERVAL_HOUR:
		case SQL_INTERVAL_MINUTE:
		case SQL_INTERVAL_SECOND:
		case SQL_INTERVAL_DAY_TO_HOUR:
		case SQL_INTERVAL_DAY_TO_MINUTE:
		case SQL_INTERVAL_DAY_TO_SECOND:
		case SQL_INTERVAL_HOUR_TO_MINUTE:
		case SQL_INTERVAL_HOUR_TO_SECOND:
		case SQL_INTERVAL_MINUTE_TO_SECOND:
			pgCast = "::interval";
			break;
	}

	return pgCast;
}