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 0ef91a139f08fbcb22ee2c9f27a461bb9f60c5d9..df40f440d692ca66b83fd1ed24832963a36820cf 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;
+}
+