OSDN Git Service

Add files for Unicode support.
authorHiroshi Inoue <inoue@tpf.co.jp>
Fri, 1 Mar 2002 07:18:34 +0000 (07:18 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Fri, 1 Mar 2002 07:18:34 +0000 (07:18 +0000)
src/interfaces/odbc/connection.h
src/interfaces/odbc/odbcapi25w.c [new file with mode: 0644]
src/interfaces/odbc/odbcapi30w.c [new file with mode: 0644]
src/interfaces/odbc/odbcapiw.c [new file with mode: 0755]
src/interfaces/odbc/pgapi30.c [new file with mode: 0644]
src/interfaces/odbc/win_unicode.c [new file with mode: 0644]

index 0ef91a1..df40f44 100644 (file)
@@ -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 (file)
index 0000000..0bebf5d
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+
+#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 (file)
index 0000000..d2a2005
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+
+#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 (executable)
index 0000000..637f69f
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+
+#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 (file)
index 0000000..9ee8c58
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+
+#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 (file)
index 0000000..11a8e39
--- /dev/null
@@ -0,0 +1,137 @@
+/*-------
+ * Module:                     win_unicode.c
+ *
+ * Description:                This module contains utf8 <-> ucs2 conversion routines
+ *                                     under WIndows
+ *
+ *-------
+ */
+
+#include "psqlodbc.h"
+#include <stdio.h>
+#include <string.h>
+
+#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;
+}
+