The last time I asked about a deficiency in the contributed libraries I
received several replies which indicated that patches are welcome from
the user community.  Taking this feedback at face value, I have attached
a patch for the odbc module, which I believe brings it a step closer to
full support for Unicode values.

The file is from ActivePython-2.2.1-222/src/PyWin32/win32/src in the
source distribution.  The patch is in universal diff output format.

I have attempted to emulate the coding style of the original, overlong
lines and all, though I had some difficulty in determining consistent
patterns in the conventions used.

There are still some warts in this module which need to be addressed,
but I believe my changes are a step in the right direction and don't
break anything that was working properly before.  Some of the remaining
deficiences include the inability to handle SQL NULL values properly,
and a limit on the length of data which can be retrieved (hardcoded to
65536 bytes).  I didn't want to proceed further until I got some
feedback confirming that there's interest and that such patches will
eventually be incorporated into the module, and until what I have gets
some additional testing beyond what I've been able to do myself.

All my changes are bracketed by a preprocessor test for a version of
Python which understands Unicode (#ifdef Py_USING_UNICODE).

Cheers.

-- 
Bob Kline
mailto:bkline@;rksystems.com
http://www.rksystems.com
--- odbc.cpp-original   Mon Apr 15 15:44:36 2002

+++ odbc.cpp    Sun Oct 20 15:37:16 2002

@@ -70,7 +70,11 @@

        long len;

        long sqlBytesAvailable;

        bool bPutData;

+#ifdef Py_USING_UNICODE

+       char bind_area[Py_UNICODE_SIZE];

+#else

        char bind_area[1];

+#endif

 } InputBinding;

 

 typedef struct

@@ -529,6 +533,14 @@

 {

        return Py_BuildValue("s", v);

 }

+

+#ifdef Py_USING_UNICODE

+static PyObject *wstringCopy(const void *v, int)

+{

+       return Py_BuildValue("u", v);

+}

+#endif

+

 static PyObject *longCopy(const void *v, int sz)

 {

        return PyInt_FromLong(*(unsigned long *)v);

@@ -881,6 +893,51 @@

   return 1;

 }

 

+#ifdef Py_USING_UNICODE

+static int ibindWString(cursorObject *cur, int column, PyObject *item)

+{

+  const Py_UNICODE *val = PyUnicode_AsUnicode(item);

+  int len = (int)wcslen(val);

+

+  InputBinding *ib = initInputBinding(cur, len * Py_UNICODE_SIZE);

+  if (!ib)

+      return 0;

+

+  wcscpy((wchar_t*)ib->bind_area, val);

+  int sqlType = SQL_WVARCHAR;

+  if (len > 255)

+  {

+         ib->sqlBytesAvailable = SQL_LEN_DATA_AT_EXEC(ib->len);

+         sqlType = SQL_WLONGVARCHAR;

+         ib->bPutData = true;

+  }

+  else

+  {

+         ib->sqlBytesAvailable = ib->len;

+         ib->bPutData = false;

+  }

+

+  RETCODE rc = SQLBindParameter(

+         cur->hstmt,

+         column,

+         SQL_PARAM_INPUT,

+         SQL_C_WCHAR, 

+         sqlType,

+         len,

+         0, 

+         ib->bind_area,

+         0,

+         &NTS);

+  if (unsuccessful(rc))

+  {

+      cursorError(cur, "input-binding");

+      return 0;

+  }

+

+  return 1;

+}

+#endif

+

 static int rewriteQuery

 (

        char *out,

@@ -936,6 +993,12 @@

                {

                        rv = ibindString(cur, iCol, item);

                }

+#ifdef Py_USING_UNICODE

+               else if (PyUnicode_Check(item))

+               {

+                       rv = ibindWString(cur, iCol, item);

+               }

+#endif

                else if (item==Py_None)

                {

                        rv = ibindNull(cur, iCol);

@@ -967,6 +1030,10 @@

     {

     case SQL_CHAR:

     case SQL_VARCHAR:

+#ifdef Py_USING_UNICODE

+    case SQL_WCHAR:

+    case SQL_WVARCHAR:

+#endif

     case SQL_DATE:

     case SQL_TIMESTAMP:

     case SQL_BIT:

@@ -987,6 +1054,9 @@

       return(max(2*collen, (int)strlen(colname)));

     case SQL_LONGVARBINARY:

     case SQL_LONGVARCHAR:

+#ifdef Py_USING_UNICODE

+    case SQL_WLONGVARCHAR:

+#endif

     default:

       return (0);

     } 

@@ -1092,6 +1162,17 @@

                        bindOutputVar(cur, stringCopy, SQL_C_CHAR, cur->max_width, 
pos, true);

                        typeOf = DbiString;

                        break;

+#ifdef Py_USING_UNICODE

+               case SQL_WCHAR:

+                       bindOutputVar(cur, wstringCopy, SQL_C_WCHAR, 
+vsize*Py_UNICODE_SIZE+Py_UNICODE_SIZE, pos, false);

+                       typeOf = DbiString;

+                       break;

+               case SQL_WVARCHAR:

+               case SQL_WLONGVARCHAR:

+                       bindOutputVar(cur, wstringCopy, SQL_C_WCHAR, cur->max_width, 
+pos, true);

+                       typeOf = DbiString;

+                       break;

+#endif

                default:

                        bindOutputVar(cur, stringCopy, SQL_C_CHAR, vsize+1, pos, 
false);

                        typeOf = DbiString;

@@ -1214,8 +1295,11 @@

        {

                temp = PySequence_GetItem(inputvars, 0);

                // Strings don't count as a list in this case.

-               if (PySequence_Check(temp) && !PyString_Check(temp))

-               {

+               if (PySequence_Check(temp) && !PyString_Check(temp)

+#ifdef Py_USING_UNICODE

+                && !PyUnicode_Check(temp)

+#endif

+               ) {

                        rows = inputvars;

                        inputvars = NULL;

                }

@@ -1431,6 +1515,12 @@

                                                // (silly, silly)

                                                cbRead = ob->vsize - 1;

                                        }

+#ifdef Py_USING_UNICODE

+                    else if (ob->vtype == SQL_C_CHAR)

+                                       {

+                                               cbRead = ob->vsize - Py_UNICODE_SIZE;

+                                       }

+#endif

                                        else

                                        {

                                                cbRead = ob->vsize;

Reply via email to