From e1716475e40c3305550fbf3b59ff47e551545036 Mon Sep 17 00:00:00 2001 From: Hiroshi Inoue Date: Fri, 1 Mar 2002 07:18:34 +0000 Subject: [PATCH] Add files for Unicode support. --- src/interfaces/odbc/connection.h | 1 + src/interfaces/odbc/odbcapi25w.c | 75 +++++ src/interfaces/odbc/odbcapi30w.c | 122 +++++++++ src/interfaces/odbc/odbcapiw.c | 562 ++++++++++++++++++++++++++++++++++++++ src/interfaces/odbc/pgapi30.c | 495 +++++++++++++++++++++++++++++++++ src/interfaces/odbc/win_unicode.c | 137 ++++++++++ 6 files changed, 1392 insertions(+) create mode 100644 src/interfaces/odbc/odbcapi25w.c create mode 100644 src/interfaces/odbc/odbcapi30w.c create mode 100755 src/interfaces/odbc/odbcapiw.c create mode 100644 src/interfaces/odbc/pgapi30.c create mode 100644 src/interfaces/odbc/win_unicode.c diff --git a/src/interfaces/odbc/connection.h b/src/interfaces/odbc/connection.h index 0ef91a139f..df40f440d6 100644 --- a/src/interfaces/odbc/connection.h +++ b/src/interfaces/odbc/connection.h @@ -266,6 +266,7 @@ struct ConnectionClass_ Int2 pg_version_major; Int2 pg_version_minor; char ms_jet; + char unicode; #ifdef MULTIBYTE char *client_encoding; char *server_encoding; diff --git a/src/interfaces/odbc/odbcapi25w.c b/src/interfaces/odbc/odbcapi25w.c new file mode 100644 index 0000000000..0bebf5d128 --- /dev/null +++ b/src/interfaces/odbc/odbcapi25w.c @@ -0,0 +1,75 @@ +/*------- + * Module: odbcapi25w.c + * + * Description: This module contains UNICODE routines + * + * Classes: n/a + * + * API functions: SQLColAttributesW, SQLErrorW, SQLGetConnectOptionW, + SQLSetConnectOptionW + *------- + */ + +#include "psqlodbc.h" +#include +#include + +#include "pgapifunc.h" +#include "connection.h" +#include "statement.h" + +RETCODE SQL_API SQLErrorW(HENV EnvironmentHandle, + HDBC ConnectionHandle, HSTMT StatementHandle, + SQLWCHAR *Sqlstate, SQLINTEGER *NativeError, + SQLWCHAR *MessageText, SQLSMALLINT BufferLength, + SQLSMALLINT *TextLength) +{ + RETCODE ret; + SWORD tlen; + char *qst = NULL, *mtxt = NULL; + + mylog("[SQLErrorW]"); + if (Sqlstate) + qst = malloc(8); + if (MessageText) + mtxt = malloc(BufferLength); + ret = PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle, + qst, NativeError, mtxt, BufferLength, &tlen); + if (qst) + utf8_to_ucs2(qst, strlen(qst), Sqlstate, 5); + if (TextLength) + *TextLength = utf8_to_ucs2(mtxt, tlen, MessageText, BufferLength); + free(qst); + free(mtxt); + return ret; +} + +RETCODE SQL_API SQLGetConnectOptionW(HDBC ConnectionHandle, + SQLUSMALLINT Option, PTR Value) +{ + mylog("[SQLGetConnectOptionW]"); + ((ConnectionClass *) ConnectionHandle)->unicode = 1; + return PGAPI_GetConnectOption(ConnectionHandle, Option, Value); +} + +RETCODE SQL_API SQLSetConnectOptionW(HDBC ConnectionHandle, + SQLUSMALLINT Option, SQLUINTEGER Value) +{ + mylog("[SQLSetConnectionOptionW]"); + ((ConnectionClass *) ConnectionHandle)->unicode = 1; + return PGAPI_SetConnectOption(ConnectionHandle, Option, Value); +} + +RETCODE SQL_API SQLColAttributesW( + HSTMT hstmt, + SQLUSMALLINT icol, + SQLUSMALLINT fDescType, + PTR rgbDesc, + SQLSMALLINT cbDescMax, + SQLSMALLINT *pcbDesc, + SQLINTEGER *pfDesc) +{ + mylog("[SQLColAttributesW]"); + return PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc, + cbDescMax, pcbDesc, pfDesc); +} diff --git a/src/interfaces/odbc/odbcapi30w.c b/src/interfaces/odbc/odbcapi30w.c new file mode 100644 index 0000000000..d2a2005c1b --- /dev/null +++ b/src/interfaces/odbc/odbcapi30w.c @@ -0,0 +1,122 @@ +/*------- + * Module: odbcapi30w.c + * + * Description: This module contains UNICODE routines + * + * Classes: n/a + * + * API functions: SQLColAttributeW, SQLGetStmtW, SQLSetStmtW, + SQLSetConnectAttrW, SQLGetConnectAttrW, + SQLGetDescFieldW, SQLGetDescRecW, SQLGetDiagFieldW, + SQLGetDiagRecW, + *------- + */ + +#include "psqlodbc.h" +#include +#include + +#include "pgapifunc.h" +#include "connection.h" +#include "statement.h" + + +RETCODE SQL_API SQLGetStmtAttrW(SQLHSTMT hstmt, + SQLINTEGER fAttribute, + PTR rgbValue, + SQLINTEGER cbValueMax, + SQLINTEGER *pcbValue) +{ + RETCODE ret; + + mylog("[SQLGetStmtAttrW]"); + ret = PGAPI_GetStmtAttr(hstmt, fAttribute, rgbValue, + cbValueMax, pcbValue); + return ret; +} + +RETCODE SQL_API SQLSetStmtAttrW(SQLHSTMT hstmt, + SQLINTEGER fAttribute, + PTR rgbValue, + SQLINTEGER cbValueMax) +{ + RETCODE ret; + + mylog("[SQLSetStmtAttrW]"); + ret = PGAPI_SetStmtAttr(hstmt, fAttribute, rgbValue, + cbValueMax); + return ret; +} + +RETCODE SQL_API SQLGetConnectAttrW(HDBC hdbc, + SQLINTEGER fAttribute, + PTR rgbValue, + SQLINTEGER cbValueMax, + SQLINTEGER *pcbValue) +{ + RETCODE ret; + + mylog("[SQLGetConnectAttrW]"); + ret = PGAPI_GetConnectAttr(hdbc, fAttribute, rgbValue, + cbValueMax, pcbValue); + return ret; +} + +RETCODE SQL_API SQLSetConnectAttrW(HDBC hdbc, + SQLINTEGER fAttribute, + PTR rgbValue, + SQLINTEGER cbValue) +{ + RETCODE ret; + + mylog("[SQLSetConnectAttrW]"); + ret = PGAPI_SetConnectAttr(hdbc, fAttribute, rgbValue, + cbValue); + return ret; +} + +RETCODE SQL_API SQLGetDiagRecW(SWORD fHandleType, + SQLHANDLE handle, + SQLSMALLINT iRecord, + SQLWCHAR *szSqlState, + SQLINTEGER *pfNativeError, + SQLWCHAR *szErrorMsg, + SQLSMALLINT cbErrorMsgMax, + SQLSMALLINT *pcbErrorMsg) +{ + RETCODE ret; + SWORD tlen; + char *qst = NULL, *mtxt = NULL; + + mylog("[SQLGetDiagRecW]"); + if (szSqlState) + qst = malloc(8); + if (szErrorMsg) + mtxt = malloc(cbErrorMsgMax); + ret = PGAPI_GetDiagRec(fHandleType, handle, iRecord, qst, + pfNativeError, mtxt, cbErrorMsgMax, &tlen); + if (qst) + utf8_to_ucs2(qst, strlen(qst), szSqlState, 5); + if (pcbErrorMsg) + *pcbErrorMsg = utf8_to_ucs2(mtxt, tlen, szErrorMsg, cbErrorMsgMax); + free(qst); + free(mtxt); + return ret; +} + +RETCODE SQL_API SQLColAttributeW( + HSTMT hstmt, + SQLUSMALLINT icol, + SQLUSMALLINT fDescType, + PTR rgbDesc, + SQLSMALLINT cbDescMax, + SQLSMALLINT *pcbDesc, + SQLINTEGER *pfDesc) +{ + RETCODE ret; + + mylog("[SQLColAttributeW]"); + ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc, + cbDescMax, pcbDesc, pfDesc); + return ret; +} diff --git a/src/interfaces/odbc/odbcapiw.c b/src/interfaces/odbc/odbcapiw.c new file mode 100755 index 0000000000..637f69f969 --- /dev/null +++ b/src/interfaces/odbc/odbcapiw.c @@ -0,0 +1,562 @@ +/*------- + * Module: odbcapiw.c + * + * Description: This module contains UNICODE routines + * + * Classes: n/a + * + * API functions: SQLColumnPrivilegesW, SQLColumnsW, + SQLConnectW, SQLDataSourcesW, SQLDescribeColW, + SQLDriverConnectW, SQLExecDirectW, + SQLForeignKeysW, + SQLGetCursorNameW, SQLGetInfoW, SQLNativeSqlW, + SQLPrepareW, SQLPrimaryKeysW, SQLProcedureColumnsW, + SQLProceduresW, SQLSetCursorNameW, + SQLSpecialColumnsW, SQLStatisticsW, SQLTablesW, + SQLTablePrivilegesW + *------- + */ + +#include "psqlodbc.h" +#include +#include + +#include "pgapifunc.h" +#include "connection.h" +#include "statement.h" + +RETCODE SQL_API SQLColumnsW(HSTMT StatementHandle, + SQLWCHAR *CatalogName, SQLSMALLINT NameLength1, + SQLWCHAR *SchemaName, SQLSMALLINT NameLength2, + SQLWCHAR *TableName, SQLSMALLINT NameLength3, + SQLWCHAR *ColumnName, SQLSMALLINT NameLength4) +{ + RETCODE ret; + char *ctName, *scName, *tbName, *clName; + UInt4 nmlen1, nmlen2, nmlen3, nmlen4; + + mylog("[SQLColumnsW]"); + ctName = ucs2_to_utf8(CatalogName, NameLength1, &nmlen1); + scName = ucs2_to_utf8(SchemaName, NameLength2, &nmlen2); + tbName = ucs2_to_utf8(TableName, NameLength3, &nmlen3); + clName = ucs2_to_utf8(ColumnName, NameLength4, &nmlen4); + ret = PGAPI_Columns(StatementHandle, ctName, (SWORD) nmlen1, + scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3, + clName, (SWORD) nmlen4, 0); + if (ctName) + free(ctName); + if (scName); + free(scName); + if (tbName) + free(tbName); + if (clName); + free(clName); + return ret; +} + + +RETCODE SQL_API SQLConnectW(HDBC ConnectionHandle, + SQLWCHAR *ServerName, SQLSMALLINT NameLength1, + SQLWCHAR *UserName, SQLSMALLINT NameLength2, + SQLWCHAR *Authentication, SQLSMALLINT NameLength3) +{ + char *svName, *usName, *auth; + UInt4 nmlen1, nmlen2, nmlen3; + RETCODE ret; + + mylog("[SQLConnectW]"); + ((ConnectionClass *) ConnectionHandle)->unicode = 1; + svName = ucs2_to_utf8(ServerName, NameLength1, &nmlen1); + usName = ucs2_to_utf8(UserName, NameLength2, &nmlen2); + auth = ucs2_to_utf8(Authentication, NameLength3, &nmlen3); + ret = PGAPI_Connect(ConnectionHandle, svName, (SWORD) nmlen1, + usName, (SWORD) nmlen2, auth, (SWORD) nmlen3); + if (svName); + free(svName); + if (usName); + free(usName); + if (auth); + free(auth); + return ret; +} + +RETCODE SQL_API SQLDriverConnectW(HDBC hdbc, + HWND hwnd, + SQLWCHAR *szConnStrIn, + SWORD cbConnStrIn, + SQLWCHAR *szConnStrOut, + SWORD cbConnStrOutMax, + SWORD FAR *pcbConnStrOut, + UWORD fDriverCompletion) +{ + char *szIn, *szOut; + UInt4 inlen, obuflen; + SWORD olen; + RETCODE ret; + + mylog("[SQLDriverConnectW]"); + ((ConnectionClass *) hdbc)->unicode = 1; + szIn = ucs2_to_utf8(szConnStrIn, cbConnStrIn, &inlen); + obuflen = cbConnStrOutMax + 1; + szOut = malloc(obuflen); + ret = PGAPI_DriverConnect(hdbc, hwnd, szIn, (SWORD) inlen, + szOut, cbConnStrOutMax, &olen, fDriverCompletion); + if (ret != SQL_ERROR) + *pcbConnStrOut = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax); + free(szOut); + if (szIn); + free(szIn); + return ret; +} +RETCODE SQL_API SQLBrowseConnectW( + HDBC hdbc, + SQLWCHAR *szConnStrIn, + SQLSMALLINT cbConnStrIn, + SQLWCHAR *szConnStrOut, + SQLSMALLINT cbConnStrOutMax, + SQLSMALLINT *pcbConnStrOut) +{ + char *szIn, *szOut; + UInt4 inlen, obuflen; + SWORD olen; + RETCODE ret; + + mylog("[SQLBrowseConnectW]"); + ((ConnectionClass *) hdbc)->unicode = 1; + szIn = ucs2_to_utf8(szConnStrIn, cbConnStrIn, &inlen); + obuflen = cbConnStrOutMax + 1; + szOut = malloc(obuflen); + ret = PGAPI_BrowseConnect(hdbc, szIn, (SWORD) inlen, + szOut, cbConnStrOutMax, &olen); + if (ret != SQL_ERROR) + *pcbConnStrOut = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax); + free(szOut); + if (szIn); + free(szIn); + return ret; +} + +RETCODE SQL_API SQLDataSourcesW(HENV EnvironmentHandle, + SQLUSMALLINT Direction, SQLWCHAR *ServerName, + SQLSMALLINT BufferLength1, SQLSMALLINT *NameLength1, + SQLWCHAR *Description, SQLSMALLINT BufferLength2, + SQLSMALLINT *NameLength2) +{ + mylog("[SQLDataSourcesW]"); + /* + return PGAPI_DataSources(EnvironmentHandle, Direction, ServerName, + BufferLength1, NameLength1, Description, BufferLength2, + NameLength2); + */ + return SQL_ERROR; +} + +RETCODE SQL_API SQLDescribeColW(HSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLWCHAR *ColumnName, + SQLSMALLINT BufferLength, SQLSMALLINT *NameLength, + SQLSMALLINT *DataType, SQLUINTEGER *ColumnSize, + SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable) +{ + RETCODE ret; + SWORD nmlen; + char *clName; + + mylog("[SQLDescribeColW]"); + clName = malloc(BufferLength); + ret = PGAPI_DescribeCol(StatementHandle, ColumnNumber, + clName, BufferLength, &nmlen, + DataType, ColumnSize, DecimalDigits, Nullable); + *NameLength = utf8_to_ucs2(clName, nmlen, ColumnName, BufferLength); + free(clName); + return ret; +} + +RETCODE SQL_API SQLExecDirectW(HSTMT StatementHandle, + SQLWCHAR *StatementText, SQLINTEGER TextLength) +{ + RETCODE ret; + char *stxt; + UInt4 slen; + + mylog("[SQLExecDirectW]"); + stxt = ucs2_to_utf8(StatementText, TextLength, &slen); + ret = PGAPI_ExecDirect(StatementHandle, stxt, slen); + if (stxt); + free(stxt); + return ret; +} + +RETCODE SQL_API SQLGetCursorNameW(HSTMT StatementHandle, + SQLWCHAR *CursorName, SQLSMALLINT BufferLength, + SQLSMALLINT *NameLength) +{ + RETCODE ret; + char *crName; + SWORD clen; + + mylog("[SQLGetCursorNameW]"); + crName = malloc(BufferLength); + ret = PGAPI_GetCursorName(StatementHandle, crName, BufferLength, + &clen); + *NameLength = utf8_to_ucs2(crName, (Int4) clen, CursorName, BufferLength); + free(crName); + return ret; +} + +RETCODE SQL_API SQLGetInfoW(HDBC ConnectionHandle, + SQLUSMALLINT InfoType, PTR InfoValue, + SQLSMALLINT BufferLength, SQLSMALLINT *StringLength) +{ + RETCODE ret; + ((ConnectionClass *) ConnectionHandle)->unicode = 1; +#if (ODBCVER >= 0x0300) + mylog("[SQLGetInfoW(30)]"); + if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue, + BufferLength, StringLength)) == SQL_ERROR) + { + if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x0300) + return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue, + BufferLength, StringLength); + } + return ret; +#else + mylog("[SQLGetInfoW]"); + return PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue, + BufferLength, StringLength); +#endif +} + +RETCODE SQL_API SQLPrepareW(HSTMT StatementHandle, + SQLWCHAR *StatementText, SQLINTEGER TextLength) +{ + RETCODE ret; + char *stxt; + UInt4 slen; + + mylog("[SQLPrepareW]"); + stxt = ucs2_to_utf8(StatementText, TextLength, &slen); + ret = PGAPI_Prepare(StatementHandle, stxt, slen); + if (stxt); + free(stxt); + return ret; +} + +RETCODE SQL_API SQLSetCursorNameW(HSTMT StatementHandle, + SQLWCHAR *CursorName, SQLSMALLINT NameLength) +{ + RETCODE ret; + char *crName; + UInt4 nlen; + + mylog("[SQLSetCursorNameW]"); + crName = ucs2_to_utf8(CursorName, NameLength, &nlen); + ret = PGAPI_SetCursorName(StatementHandle, crName, (SWORD) nlen); + if (crName); + free(crName); + return ret; +} + +RETCODE SQL_API SQLSpecialColumnsW(HSTMT StatementHandle, + SQLUSMALLINT IdentifierType, SQLWCHAR *CatalogName, + SQLSMALLINT NameLength1, SQLWCHAR *SchemaName, + SQLSMALLINT NameLength2, SQLWCHAR *TableName, + SQLSMALLINT NameLength3, SQLUSMALLINT Scope, + SQLUSMALLINT Nullable) +{ + RETCODE ret; + char *ctName, *scName, *tbName; + UInt4 nmlen1, nmlen2, nmlen3; + + mylog("[SQLSpecialColumnsW]"); + ctName = ucs2_to_utf8(CatalogName, NameLength1, &nmlen1); + scName = ucs2_to_utf8(SchemaName, NameLength2, &nmlen2); + tbName = ucs2_to_utf8(TableName, NameLength3, &nmlen3); + ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, ctName, + (SWORD) nmlen1, scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3, + Scope, Nullable); + if (ctName); + free(ctName); + if (scName); + free(scName); + if (tbName); + free(tbName); + return ret; +} + +RETCODE SQL_API SQLStatisticsW(HSTMT StatementHandle, + SQLWCHAR *CatalogName, SQLSMALLINT NameLength1, + SQLWCHAR *SchemaName, SQLSMALLINT NameLength2, + SQLWCHAR *TableName, SQLSMALLINT NameLength3, + SQLUSMALLINT Unique, SQLUSMALLINT Reserved) +{ + RETCODE ret; + char *ctName, *scName, *tbName; + UInt4 nmlen1, nmlen2, nmlen3; + + mylog("[SQLStatisticsW]"); + ctName = ucs2_to_utf8(CatalogName, NameLength1, &nmlen1); + scName = ucs2_to_utf8(SchemaName, NameLength2, &nmlen2); + tbName = ucs2_to_utf8(TableName, NameLength3, &nmlen3); + return PGAPI_Statistics(StatementHandle, ctName, (SWORD) nmlen1, + scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3, Unique, + Reserved); + if (ctName); + free(ctName); + if (scName); + free(scName); + if (tbName); + free(tbName); + return ret; +} + +RETCODE SQL_API SQLTablesW(HSTMT StatementHandle, + SQLWCHAR *CatalogName, SQLSMALLINT NameLength1, + SQLWCHAR *SchemaName, SQLSMALLINT NameLength2, + SQLWCHAR *TableName, SQLSMALLINT NameLength3, + SQLWCHAR *TableType, SQLSMALLINT NameLength4) +{ + RETCODE ret; + char *ctName, *scName, *tbName, *tbType; + UInt4 nmlen1, nmlen2, nmlen3, nmlen4; + + mylog("[SQLTablesW]"); + ctName = ucs2_to_utf8(CatalogName, NameLength1, &nmlen1); + scName = ucs2_to_utf8(SchemaName, NameLength2, &nmlen2); + tbName = ucs2_to_utf8(TableName, NameLength3, &nmlen3); + tbType = ucs2_to_utf8(TableType, NameLength4, &nmlen4); + return PGAPI_Tables(StatementHandle, ctName, (SWORD) nmlen1, + scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3, + tbType, (SWORD) nmlen4); + if (ctName); + free(ctName); + if (scName); + free(scName); + if (tbName); + free(tbName); + if (tbType); + free(tbType); + return ret; +} + +RETCODE SQL_API SQLColumnPrivilegesW( + HSTMT hstmt, + SQLWCHAR *szCatalogName, + SQLSMALLINT cbCatalogName, + SQLWCHAR *szSchemaName, + SQLSMALLINT cbSchemaName, + SQLWCHAR *szTableName, + SQLSMALLINT cbTableName, + SQLWCHAR *szColumnName, + SQLSMALLINT cbColumnName) +{ + RETCODE ret; + char *ctName, *scName, *tbName, *clName; + UInt4 nmlen1, nmlen2, nmlen3, nmlen4; + + mylog("[SQLColumnPrivilegesW]"); + ctName = ucs2_to_utf8(szCatalogName, cbCatalogName, &nmlen1); + scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2); + tbName = ucs2_to_utf8(szTableName, cbTableName, &nmlen3); + clName = ucs2_to_utf8(szColumnName, cbColumnName, &nmlen4); + ret = PGAPI_ColumnPrivileges(hstmt, ctName, (SWORD) nmlen1, + scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3, + clName, (SWORD) nmlen4); + if (ctName); + free(ctName); + if (scName); + free(scName); + if (tbName); + free(tbName); + if (clName); + free(clName); + return ret; +} + +RETCODE SQL_API SQLForeignKeysW( + HSTMT hstmt, + SQLWCHAR *szPkCatalogName, + SQLSMALLINT cbPkCatalogName, + SQLWCHAR *szPkSchemaName, + SQLSMALLINT cbPkSchemaName, + SQLWCHAR *szPkTableName, + SQLSMALLINT cbPkTableName, + SQLWCHAR *szFkCatalogName, + SQLSMALLINT cbFkCatalogName, + SQLWCHAR *szFkSchemaName, + SQLSMALLINT cbFkSchemaName, + SQLWCHAR *szFkTableName, + SQLSMALLINT cbFkTableName) +{ + RETCODE ret; + char *ctName, *scName, *tbName, *fkctName, *fkscName, *fktbName; + UInt4 nmlen1, nmlen2, nmlen3, nmlen4, nmlen5, nmlen6; + + mylog("[SQLForeignKeysW]"); + ctName = ucs2_to_utf8(szPkCatalogName, cbPkCatalogName, &nmlen1); + scName = ucs2_to_utf8(szPkSchemaName, cbPkSchemaName, &nmlen2); + tbName = ucs2_to_utf8(szPkTableName, cbPkTableName, &nmlen3); + fkctName = ucs2_to_utf8(szFkCatalogName, cbFkCatalogName, &nmlen4); + fkscName = ucs2_to_utf8(szFkSchemaName, cbFkSchemaName, &nmlen5); + fktbName = ucs2_to_utf8(szFkTableName, cbFkTableName, &nmlen6); + ret = PGAPI_ForeignKeys(hstmt, ctName, (SWORD) nmlen1, + scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3, + fkctName, (SWORD) nmlen4, fkscName, (SWORD) nmlen5, + fktbName, (SWORD) nmlen6); + if (ctName); + free(ctName); + if (scName); + free(scName); + if (tbName); + free(tbName); + if (fkctName); + free(fkctName); + if (fkscName); + free(fkscName); + if (fktbName); + free(fktbName); + return ret; +} + +RETCODE SQL_API SQLNativeSqlW( + HDBC hdbc, + SQLWCHAR *szSqlStrIn, + SQLINTEGER cbSqlStrIn, + SQLWCHAR *szSqlStr, + SQLINTEGER cbSqlStrMax, + SQLINTEGER *pcbSqlStr) +{ + RETCODE ret; + char *szIn, *szOut; + UInt4 slen; + SQLINTEGER olen; + + mylog("[SQLNativeSqlW]"); + ((ConnectionClass *) hdbc)->unicode = 1; + szIn = ucs2_to_utf8(szSqlStrIn, cbSqlStrIn, &slen); + szOut = malloc(cbSqlStrMax); + ret = PGAPI_NativeSql(hdbc, szIn, (SQLINTEGER) slen, + szOut, cbSqlStrMax, &olen); + if (szIn); + free(szIn); + *pcbSqlStr = utf8_to_ucs2(szOut, olen, szSqlStr, cbSqlStrMax); + free(szOut); + return ret; +} + +RETCODE SQL_API SQLPrimaryKeysW( + HSTMT hstmt, + SQLWCHAR *szCatalogName, + SQLSMALLINT cbCatalogName, + SQLWCHAR *szSchemaName, + SQLSMALLINT cbSchemaName, + SQLWCHAR *szTableName, + SQLSMALLINT cbTableName) +{ + RETCODE ret; + char *ctName, *scName, *tbName; + UInt4 nmlen1, nmlen2, nmlen3; + + mylog("[SQLPrimaryKeysW]"); + ctName = ucs2_to_utf8(szCatalogName, cbCatalogName, &nmlen1); + scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2); + tbName = ucs2_to_utf8(szTableName, cbTableName, &nmlen3); + return PGAPI_PrimaryKeys(hstmt, ctName, (SWORD) nmlen1, + scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3); + if (ctName); + free(ctName); + if (scName); + free(scName); + if (tbName); + free(tbName); + return ret; +} + +RETCODE SQL_API SQLProcedureColumnsW( + HSTMT hstmt, + SQLWCHAR *szCatalogName, + SQLSMALLINT cbCatalogName, + SQLWCHAR *szSchemaName, + SQLSMALLINT cbSchemaName, + SQLWCHAR *szProcName, + SQLSMALLINT cbProcName, + SQLWCHAR *szColumnName, + SQLSMALLINT cbColumnName) +{ + RETCODE ret; + char *ctName, *scName, *prName, *clName; + UInt4 nmlen1, nmlen2, nmlen3, nmlen4; + + mylog("[SQLProcedureColumnsW]"); + ctName = ucs2_to_utf8(szCatalogName, cbCatalogName, &nmlen1); + scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2); + prName = ucs2_to_utf8(szProcName, cbProcName, &nmlen3); + clName = ucs2_to_utf8(szColumnName, cbColumnName, &nmlen4); + ret = PGAPI_ProcedureColumns(hstmt, ctName, (SWORD) nmlen1, + scName, (SWORD) nmlen2, prName, (SWORD) nmlen3, + clName, (SWORD) nmlen4); + if (ctName); + free(ctName); + if (scName); + free(scName); + if (prName); + free(prName); + if (clName); + free(clName); + return ret; +} + +RETCODE SQL_API SQLProceduresW( + HSTMT hstmt, + SQLWCHAR *szCatalogName, + SQLSMALLINT cbCatalogName, + SQLWCHAR *szSchemaName, + SQLSMALLINT cbSchemaName, + SQLWCHAR *szProcName, + SQLSMALLINT cbProcName) +{ + RETCODE ret; + char *ctName, *scName, *prName; + UInt4 nmlen1, nmlen2, nmlen3; + + mylog("[SQLProceduresW]"); + ctName = ucs2_to_utf8(szCatalogName, cbCatalogName, &nmlen1); + scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2); + prName = ucs2_to_utf8(szProcName, cbProcName, &nmlen3); + ret = PGAPI_Procedures(hstmt, ctName, (SWORD) nmlen1, + scName, (SWORD) nmlen2, prName, (SWORD) nmlen3); + if (ctName); + free(ctName); + if (scName); + free(scName); + if (prName); + free(prName); + return ret; +} + +RETCODE SQL_API SQLTablePrivilegesW( + HSTMT hstmt, + SQLWCHAR *szCatalogName, + SQLSMALLINT cbCatalogName, + SQLWCHAR *szSchemaName, + SQLSMALLINT cbSchemaName, + SQLWCHAR *szTableName, + SQLSMALLINT cbTableName) +{ + RETCODE ret; + char *ctName, *scName, *tbName; + UInt4 nmlen1, nmlen2, nmlen3; + + mylog("[SQLTablePrivilegesW]"); + ctName = ucs2_to_utf8(szCatalogName, cbCatalogName, &nmlen1); + scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2); + tbName = ucs2_to_utf8(szTableName, cbTableName, &nmlen3); + ret = PGAPI_TablePrivileges(hstmt, ctName, (SWORD) nmlen1, + scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3, 0); + if (ctName); + free(ctName); + if (scName); + free(scName); + if (tbName); + free(tbName); + return ret; +} diff --git a/src/interfaces/odbc/pgapi30.c b/src/interfaces/odbc/pgapi30.c new file mode 100644 index 0000000000..9ee8c58983 --- /dev/null +++ b/src/interfaces/odbc/pgapi30.c @@ -0,0 +1,495 @@ +/*------- + * Module: pgapi30.c + * + * Description: This module contains routines related to ODBC 3.0 + * most of their implementations are temporary + * and must be rewritten properly. + * 2001/07/23 inoue + * + * Classes: n/a + * + * API functions: PGAPI_ColAttribute, PGAPI_GetDiagRec, + PGAPI_GetConnectAttr, PGAPI_GetStmtAttr, + PGAPI_SetConnectAttr, PGAPI_SetStmtAttr + *------- + */ + +#ifndef ODBCVER +#define ODBCVER 0x0300 +#endif +#include "psqlodbc.h" +#include +#include + +#include "environ.h" +#include "connection.h" +#include "statement.h" +#include "pgapifunc.h" + +/* SQLError -> SQLDiagRec */ +RETCODE SQL_API +PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, + SQLSMALLINT RecNumber, SQLCHAR *Sqlstate, + SQLINTEGER *NativeError, SQLCHAR *MessageText, + SQLSMALLINT BufferLength, SQLSMALLINT *TextLength) +{ + RETCODE ret; + static const char *func = "PGAPI_GetDiagRec"; + + mylog("%s entering ", func); + switch (HandleType) + { + case SQL_HANDLE_ENV: + ret = PGAPI_Error(Handle, NULL, NULL, Sqlstate, NativeError, + MessageText, BufferLength, TextLength); + break; + case SQL_HANDLE_DBC: + ret = PGAPI_Error(NULL, Handle, NULL, Sqlstate, NativeError, + MessageText, BufferLength, TextLength); + break; + case SQL_HANDLE_STMT: + ret = PGAPI_Error(NULL, NULL, Handle, Sqlstate, NativeError, + MessageText, BufferLength, TextLength); + break; + default: + ret = SQL_ERROR; + } + if (ret == SQL_SUCCESS_WITH_INFO && + BufferLength == 0 && + *TextLength) + { + SQLSMALLINT BufferLength = *TextLength + 4; + SQLCHAR *MessageText = malloc(BufferLength); + + ret = PGAPI_GetDiagRec(HandleType, Handle, RecNumber, Sqlstate, + NativeError, MessageText, BufferLength, + TextLength); + free(MessageText); + } +mylog("%s exiting\n", func); + return ret; +} + +/* SQLGetConnectOption -> SQLGetconnectAttr */ +RETCODE SQL_API +PGAPI_GetConnectAttr(HDBC ConnectionHandle, + SQLINTEGER Attribute, PTR Value, + SQLINTEGER BufferLength, SQLINTEGER *StringLength) +{ + ConnectionClass *conn = (ConnectionClass *) ConnectionHandle; + + mylog("PGAPI_GetConnectAttr %d\n", Attribute); + switch (Attribute) + { + case SQL_ATTR_ASYNC_ENABLE: + case SQL_ATTR_AUTO_IPD: + case SQL_ATTR_CONNECTION_DEAD: + case SQL_ATTR_CONNECTION_TIMEOUT: + case SQL_ATTR_METADATA_ID: + conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + conn->errormsg = "Unsupported connection option (Set)"; + return SQL_ERROR; + } + return PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value); +} + +static HSTMT +descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType) +{ + switch (descType) + { + case SQL_ATTR_APP_ROW_DESC: /* 10010 */ + return StatementHandle; /* this is bogus */ + case SQL_ATTR_APP_PARAM_DESC: /* 10011 */ + return (HSTMT) ((SQLUINTEGER) StatementHandle + 1) ; /* this is bogus */ + case SQL_ATTR_IMP_ROW_DESC: /* 10012 */ + return (HSTMT) ((SQLUINTEGER) StatementHandle + 2); /* this is bogus */ + case SQL_ATTR_IMP_PARAM_DESC: /* 10013 */ + return (HSTMT) ((SQLUINTEGER) StatementHandle + 3); /* this is bogus */ + } + return (HSTMT) 0; +} +static HSTMT +statementHandleFromDescHandle(HSTMT DescHandle, SQLINTEGER *descType) +{ + SQLUINTEGER res = (SQLUINTEGER) DescHandle % 4; + switch (res) + { + case 0: *descType = SQL_ATTR_APP_ROW_DESC; /* 10010 */ + break; + case 1: *descType = SQL_ATTR_APP_PARAM_DESC; /* 10011 */ + break; + case 2: *descType = SQL_ATTR_IMP_ROW_DESC; /* 10012 */ + break; + case 3: *descType = SQL_ATTR_IMP_PARAM_DESC; /* 10013 */ + break; + } + return (HSTMT) ((SQLUINTEGER) DescHandle - res); +} + +static RETCODE SQL_API +ARDSetField(StatementClass *stmt, SQLSMALLINT RecNumber, + SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength) +{ + RETCODE ret = SQL_SUCCESS; + PTR tptr; + switch (FieldIdentifier) + { + case SQL_DESC_ARRAY_SIZE: + stmt->options.rowset_size = (SQLUINTEGER) Value; + break; + case SQL_DESC_ARRAY_STATUS_PTR: + stmt->options.row_operation_ptr = Value; + break; + case SQL_DESC_BIND_OFFSET_PTR: + stmt->options.row_offset_ptr = Value; + break; + case SQL_DESC_BIND_TYPE: + stmt->options.bind_size = (SQLUINTEGER) Value; + break; + + case SQL_DESC_DATA_PTR: + if (!RecNumber) + stmt->bookmark.buffer = Value; + else + stmt->bindings[RecNumber - 1].buffer = Value; + break; + case SQL_DESC_INDICATOR_PTR: + if (!RecNumber) + tptr = stmt->bookmark.used; + else + tptr = stmt->bindings[RecNumber - 1].used; + if (Value != tptr) + { + ret = SQL_ERROR; + stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR"; + } + break; + case SQL_DESC_OCTET_LENGTH_PTR: + if (!RecNumber) + stmt->bookmark.used = Value; + else + stmt->bindings[RecNumber - 1].used = Value; + break; + default:ret = SQL_ERROR; + stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + stmt->errormsg = "not implemedted yet"; + } + return ret; +} + +static RETCODE SQL_API +APDSetField(StatementClass *stmt, SQLSMALLINT RecNumber, + SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength) +{ + RETCODE ret = SQL_SUCCESS; + switch (FieldIdentifier) + { + case SQL_DESC_ARRAY_SIZE: + stmt->options.paramset_size = (SQLUINTEGER) Value; + break; + case SQL_DESC_ARRAY_STATUS_PTR: + stmt->options.param_operation_ptr = Value; + break; + case SQL_DESC_BIND_OFFSET_PTR: + stmt->options.param_offset_ptr = Value; + break; + case SQL_DESC_BIND_TYPE: + stmt->options.param_bind_type = (SQLUINTEGER) Value; + break; + + case SQL_DESC_DATA_PTR: + if (stmt->parameters_allocated < RecNumber) + PGAPI_BindParameter(stmt, RecNumber, 0, 0, 0, 0, 0, 0, 0, 0); + stmt->parameters[RecNumber - 1].buffer = Value; + break; + case SQL_DESC_INDICATOR_PTR: + if (stmt->parameters_allocated < RecNumber || + Value != stmt->parameters[RecNumber - 1].used) + { + ret = SQL_ERROR; + stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR"; + } + break; + case SQL_DESC_OCTET_LENGTH_PTR: + if (stmt->parameters_allocated < RecNumber) + PGAPI_BindParameter(stmt, RecNumber, 0, 0, 0, 0, 0, 0, 0, 0); + stmt->parameters[RecNumber - 1].used = Value; + break; + default:ret = SQL_ERROR; + stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + } + return ret; +} + +static RETCODE SQL_API +IRDSetField(StatementClass *stmt, SQLSMALLINT RecNumber, + SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength) +{ + RETCODE ret = SQL_SUCCESS; + switch (FieldIdentifier) + { + case SQL_DESC_ARRAY_STATUS_PTR: + stmt->options.rowStatusArray = (SQLUSMALLINT *) Value; + break; + case SQL_DESC_ROWS_PROCESSED_PTR: + stmt->options.rowsFetched = (SQLUINTEGER *) Value; + break; + default:ret = SQL_ERROR; + stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + } + return ret; +} + +static RETCODE SQL_API +IPDSetField(StatementClass *stmt, SQLSMALLINT RecNumber, + SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength) +{ + RETCODE ret = SQL_SUCCESS; + switch (FieldIdentifier) + { + case SQL_DESC_ARRAY_STATUS_PTR: + stmt->options.param_status_ptr = (SQLUSMALLINT *) Value; + break; + case SQL_DESC_ROWS_PROCESSED_PTR: + stmt->options.param_processed_ptr = (SQLUINTEGER *) Value; + break; + default:ret = SQL_ERROR; + stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + } + return ret; +} + +/* SQLGetStmtOption -> SQLGetStmtAttr */ +RETCODE SQL_API +PGAPI_GetStmtAttr(HSTMT StatementHandle, + SQLINTEGER Attribute, PTR Value, + SQLINTEGER BufferLength, SQLINTEGER *StringLength) +{ + static char *func = "PGAPI_GetStmtAttr"; + StatementClass *stmt = (StatementClass *) StatementHandle; + RETCODE ret = SQL_SUCCESS; + int len = 0; + + mylog("%s Handle=%u %d\n", func, StatementHandle, Attribute); + switch (Attribute) + { + case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */ + Value = stmt->options.bookmark_ptr; + len = 4; + break; + case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */ + Value = stmt->options.param_offset_ptr; + len = 4; + break; + case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */ + *((SQLUINTEGER *) Value) = stmt->options.param_bind_type; + len = 4; + break; + case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */ + Value = stmt->options.param_operation_ptr; + len = 4; + break; + case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */ + Value = stmt->options.param_status_ptr; + len = 4; + break; + case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */ + Value = stmt->options.param_processed_ptr; + len = 4; + break; + case SQL_ATTR_PARAMSET_SIZE: /* 22 */ + *((SQLUINTEGER *) Value) = stmt->options.paramset_size; + len = 4; + break; + case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */ + Value = stmt->options.row_offset_ptr; + len = 4; + break; + case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */ + Value = stmt->options.row_operation_ptr; + len = 4; + break; + case SQL_ATTR_ROW_STATUS_PTR: /* 25 */ + Value = stmt->options.rowStatusArray; + len = 4; + break; + case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */ + Value = stmt->options.rowsFetched; + len = 4; + break; + case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */ + *((SQLUINTEGER *) Value) = stmt->options.rowset_size; + len = 4; + break; + case SQL_ATTR_APP_ROW_DESC: /* 10010 */ + case SQL_ATTR_APP_PARAM_DESC: /* 10011 */ + case SQL_ATTR_IMP_ROW_DESC: /* 10012 */ + case SQL_ATTR_IMP_PARAM_DESC: /* 10013 */ + len = 4; + *((HSTMT *) Value) = descHandleFromStatementHandle(StatementHandle, Attribute); + break; + case SQL_ATTR_AUTO_IPD: /* 10001 */ + /* case SQL_ATTR_ROW_BIND_TYPE: ** == SQL_BIND_TYPE(ODBC2.0) */ + + case SQL_ATTR_CURSOR_SCROLLABLE: /* -1 */ + case SQL_ATTR_CURSOR_SENSITIVITY: /* -2 */ + case SQL_ATTR_ENABLE_AUTO_IPD: /* 15 */ + case SQL_ATTR_METADATA_ID: /* 10014 */ + + /* + * case SQL_ATTR_PREDICATE_PTR: case + * SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR: + */ + stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + stmt->errormsg = "Unsupported statement option (Get)"; + SC_log_error(func, "", stmt); + return SQL_ERROR; + default: + len = 4; + ret = PGAPI_GetStmtOption(StatementHandle, (UWORD) Attribute, Value); + } + if (ret == SQL_SUCCESS && StringLength) + *StringLength = len; + return ret; +} + +/* SQLSetConnectOption -> SQLSetConnectAttr */ +RETCODE SQL_API +PGAPI_SetConnectAttr(HDBC ConnectionHandle, + SQLINTEGER Attribute, PTR Value, + SQLINTEGER StringLength) +{ + ConnectionClass *conn = (ConnectionClass *) ConnectionHandle; + + mylog("PGAPI_SetConnectAttr %d\n", Attribute); + switch (Attribute) + { + case SQL_ATTR_ASYNC_ENABLE: + case SQL_ATTR_AUTO_IPD: + case SQL_ATTR_CONNECTION_DEAD: + case SQL_ATTR_CONNECTION_TIMEOUT: + case SQL_ATTR_METADATA_ID: + conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + conn->errormsg = "Unsupported connection option (Set)"; + return SQL_ERROR; + } + return PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value); +} + +/* new function */ +RETCODE SQL_API +PGAPI_SetDescField(SQLHDESC DescriptorHandle, + SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier, + PTR Value, SQLINTEGER BufferLength) +{ + RETCODE ret = SQL_SUCCESS; + HSTMT hstmt; + SQLUINTEGER descType; + StatementClass *stmt; + static const char *func = "PGAPI_SetDescField"; + + mylog("%s h=%u rec=%d field=%d val=%x\n", func, DescriptorHandle, RecNumber, FieldIdentifier, Value); + hstmt = statementHandleFromDescHandle(DescriptorHandle, &descType); + mylog("stmt=%x type=%d\n", hstmt, descType); + stmt = (StatementClass *) hstmt; + switch (descType) + { + case SQL_ATTR_APP_ROW_DESC: + ret = ARDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength); + break; + case SQL_ATTR_APP_PARAM_DESC: + ret = APDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength); + break; + case SQL_ATTR_IMP_ROW_DESC: + ret = IRDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength); + break; + case SQL_ATTR_IMP_PARAM_DESC: + ret = IPDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength); + break; + default:ret = SQL_ERROR; + stmt->errornumber = STMT_INTERNAL_ERROR; + stmt->errormsg = "Error not implemented"; + } + if (ret == SQL_ERROR) + SC_log_error(func, "", stmt); + return ret; +} + +/* SQLSet(Param/Scroll/Stmt)Option -> SQLSetStmtAttr */ +RETCODE SQL_API +PGAPI_SetStmtAttr(HSTMT StatementHandle, + SQLINTEGER Attribute, PTR Value, + SQLINTEGER StringLength) +{ + static char *func = "PGAPI_SetStmtAttr"; + StatementClass *stmt = (StatementClass *) StatementHandle; + + mylog("%s Handle=%u %d,%u\n", func, StatementHandle, Attribute, Value); + switch (Attribute) + { + case SQL_ATTR_CURSOR_SCROLLABLE: /* -1 */ + case SQL_ATTR_CURSOR_SENSITIVITY: /* -2 */ + + case SQL_ATTR_ENABLE_AUTO_IPD: /* 15 */ + + case SQL_ATTR_APP_ROW_DESC: /* 10010 */ + case SQL_ATTR_APP_PARAM_DESC: /* 10011 */ + case SQL_ATTR_AUTO_IPD: /* 10001 */ + /* case SQL_ATTR_ROW_BIND_TYPE: ** == SQL_BIND_TYPE(ODBC2.0) */ + case SQL_ATTR_IMP_ROW_DESC: /* 10012 (read-only) */ + case SQL_ATTR_IMP_PARAM_DESC: /* 10013 (read-only) */ + case SQL_ATTR_METADATA_ID: /* 10014 */ + + /* + * case SQL_ATTR_PREDICATE_PTR: case + * SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR: + */ + stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + stmt->errormsg = "Unsupported statement option (Set)"; + SC_log_error(func, "", stmt); + return SQL_ERROR; + + case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */ + stmt->options.bookmark_ptr = Value; + break; + case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */ + stmt->options.param_offset_ptr = (SQLUINTEGER *) Value; + break; + case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */ + stmt->options.param_bind_type = (SQLUINTEGER) Value; + break; + case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */ + stmt->options.param_operation_ptr = Value; + break; + case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */ + stmt->options.param_status_ptr = (SQLUSMALLINT *) Value; + break; + case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */ + stmt->options.param_processed_ptr = (SQLUINTEGER *) Value; + break; + case SQL_ATTR_PARAMSET_SIZE: /* 22 */ + stmt->options.paramset_size = (SQLUINTEGER) Value; + break; + case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */ + stmt->options.row_offset_ptr = (SQLUINTEGER *) Value; + break; + case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */ + stmt->options.row_operation_ptr = Value; + break; + case SQL_ATTR_ROW_STATUS_PTR: /* 25 */ + stmt->options.rowStatusArray = (SQLUSMALLINT *) Value; + break; + case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */ + stmt->options.rowsFetched = (SQLUINTEGER *) Value; + break; + case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */ + stmt->options.rowset_size = (SQLUINTEGER) Value; + break; + default: + return PGAPI_SetStmtOption(StatementHandle, (UWORD) Attribute, (UDWORD) Value); + } + return SQL_SUCCESS; +} diff --git a/src/interfaces/odbc/win_unicode.c b/src/interfaces/odbc/win_unicode.c new file mode 100644 index 0000000000..11a8e396a5 --- /dev/null +++ b/src/interfaces/odbc/win_unicode.c @@ -0,0 +1,137 @@ +/*------- + * Module: win_unicode.c + * + * Description: This module contains utf8 <-> ucs2 conversion routines + * under WIndows + * + *------- + */ + +#include "psqlodbc.h" +#include +#include + +#define byte3check 0xf800 +#define byte2_base 0x80c0 +#define byte2_mask1 0x07c0 +#define byte2_mask2 0x003f +#define byte3_base 0x8080e0 +#define byte3_mask1 0xf000 +#define byte3_mask2 0x0fc0 +#define byte3_mask3 0x003f + +char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen) +{ + char * utf8str; +/*mylog("ucs2_to_utf8 %x ilen=%d ", ucs2str, ilen);*/ + + if (!ucs2str) + return NULL; + if (ilen < 0) + { + for (ilen = 0; ucs2str[ilen]; ilen++) + ; + } +/*mylog(" newlen=%d", ilen);*/ + utf8str = (char *) malloc(ilen * 3 + 1); + if (utf8str) + { + int i, len = 0; + Int2 byte2code; + Int4 byte4code; + + const SQLWCHAR *wstr; + for (i = 0, wstr = ucs2str; i < ilen; i++, wstr++) + { + if (!*wstr) + break; + else if (iswascii(*wstr)) + utf8str[len++] = (char) *wstr; + else if ((*wstr & byte3check) == 0) + { + byte2code = byte2_base | + ((byte2_mask1 & *wstr) >> 6) | + ((byte2_mask2 & *wstr) << 8); + memcpy(utf8str + len, (char *) &byte2code, sizeof(byte2code)); + len += 2; + } + else + { + byte4code = byte3_base | + ((byte3_mask1 & *wstr) >> 12) | + ((byte3_mask2 & *wstr) << 2) | + ((byte3_mask3 & *wstr) << 16); + memcpy(utf8str + len, (char *) &byte4code, 3); + len += 3; + } + } + utf8str[len] = '\0'; + *olen = len; + } +/*mylog(" olen=%d %s\n", *olen, utf8str ? utf8str : "");*/ + return utf8str; +} + +#define byte3_m1 0x0f +#define byte3_m2 0x3f +#define byte3_m3 0x3f +#define byte2_m1 0x1f +#define byte2_m2 0x3f +UInt4 utf8_to_ucs2(const char *utf8str, Int4 ilen, SQLWCHAR *ucs2str, UInt4 bufcount) +{ + int i; + UInt4 ocount, wcode; + const unsigned char *str; + +/*mylog("utf8_to_ucs2 ilen=%d bufcount=%d", ilen, bufcount);*/ + if (!utf8str || !ilen) + return 0; +/*mylog(" string=%s\n", utf8str);*/ + if (!bufcount) + ucs2str = NULL; + else if (!ucs2str) + bufcount = 0; + if (ilen < 0) + ilen = strlen(utf8str); + for (i = 0, ocount = 0, str = utf8str; i < ilen;) + { + if (iswascii(*str)) + { + if (ocount < bufcount) + ucs2str[ocount] = *str; + ocount++; + i++; + str++; + } + else if (0xe0 == (*str & 0xe0)) /* 3 byte code */ + { + if (ocount < bufcount) + { + wcode = ((((UInt4) *str) & byte3_m1) << 12) | + ((((UInt4) str[1]) & byte3_m2) << 6) | + ((UInt4) str[2]) & byte3_m3; + ucs2str[ocount] = (SQLWCHAR) wcode; + } + ocount++; + i += 3; + str += 3; + } + else + { + if (ocount < bufcount) + { + wcode = ((((UInt4) *str) & byte2_m1) << 6) | + ((UInt4) str[1]) & byte2_m2; + ucs2str[ocount] = (SQLWCHAR) wcode; + } + ocount++; + i += 2; + str += 2; + } + } + if (ocount && ocount < bufcount && ucs2str) + ucs2str[ocount] = 0; +/*mylog(" ocount=%d\n", ocount);*/ + return ocount; +} + -- 2.11.0