[pywin32-checkins] pywin32/win32/src PyWinTypes.h, 1.51, 1.52 odbc.cpp, 1.24, 1.25
OLD project page for the Python extensions for Windows
Brought to you by:
mhammond
From: Roger U. <ru...@us...> - 2008-10-20 03:22:34
|
Update of /cvsroot/pywin32/pywin32/win32/src In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv3075 Modified Files: PyWinTypes.h odbc.cpp Log Message: Fix data transfer for extremely long WCHAR fields Add error checking to bindOutputVar Move TmpPyObject into pywintypes.h Index: odbc.cpp =================================================================== RCS file: /cvsroot/pywin32/pywin32/win32/src/odbc.cpp,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** odbc.cpp 11 Oct 2008 03:22:11 -0000 1.24 --- odbc.cpp 20 Oct 2008 03:22:25 -0000 1.25 *************** *** 69,73 **** { struct _out *next; ! long rcode; void *bind_area; CopyFcn copy_fcn; --- 69,73 ---- { struct _out *next; ! SQLLEN rcode; void *bind_area; CopyFcn copy_fcn; *************** *** 75,79 **** short vtype; int pos; ! long vsize; } OutputBinding; --- 75,79 ---- short vtype; int pos; ! SQLLEN vsize; } OutputBinding; *************** *** 98,102 **** PyObject *cursorError; int n_columns; - bool bGetDataIsNeeded; } cursorObject; --- 98,101 ---- *************** *** 439,443 **** cur->max_width = 65536L; cur->my_conx = 0; - cur->bGetDataIsNeeded = false; cur->hstmt=NULL; cur->cursorError=odbcError; --- 438,441 ---- *************** *** 547,551 **** } ! static void bindOutputVar ( cursorObject *cur, --- 545,549 ---- } ! static BOOL bindOutputVar ( cursorObject *cur, *************** *** 558,561 **** --- 556,563 ---- { OutputBinding *ob = (OutputBinding *) malloc(sizeof(OutputBinding)); + if (ob==NULL){ + PyErr_NoMemory(); + return FALSE; + } OutputBinding *current = NULL; *************** *** 586,589 **** --- 588,595 ---- ob->copy_fcn = fcn; ob->bind_area = malloc(vsize); + if (ob->bind_area == NULL){ + PyErr_NoMemory(); + return FALSE; + } ob->rcode = vsize; if (ob->bGetData == false) *************** *** 595,603 **** ob->bind_area, vsize, ! (SQLLEN *)&ob->rcode))) { cursorError(cur, _T("BIND")); } } } --- 601,611 ---- ob->bind_area, vsize, ! &ob->rcode))) { cursorError(cur, _T("BIND")); + return FALSE; } } + return TRUE; } *************** *** 840,861 **** } - // Class to hold a temporary reference that decrements itself - class TmpPyObject - { - public: - PyObject *tmp; - TmpPyObject() { tmp=NULL; } - TmpPyObject(PyObject *ob) { tmp=ob; } - PyObject * operator= (PyObject *ob){ - Py_XDECREF(tmp); - tmp=ob; - return tmp; - } - - boolean operator== (PyObject *ob) { return tmp==ob; } - operator PyObject *() { return tmp; } - ~TmpPyObject() { Py_XDECREF(tmp); } - }; - static int ibindDate(cursorObject*cur, int column, PyObject *item) { --- 848,851 ---- *************** *** 1008,1012 **** strcpy(ib->bind_area, val); int sqlType = SQL_VARCHAR; /* SQL_CHAR can cause padding in some drivers.. */ ! if (len > 255) { ib->sqlBytesAvailable = SQL_LEN_DATA_AT_EXEC(ib->len); --- 998,1002 ---- strcpy(ib->bind_area, val); int sqlType = SQL_VARCHAR; /* SQL_CHAR can cause padding in some drivers.. */ ! if (len > 255) /* should remove hardcoded value and actually implement setinputsize method */ { ib->sqlBytesAvailable = SQL_LEN_DATA_AT_EXEC(ib->len); *************** *** 1217,1221 **** ! static int bindOutput(cursorObject *cur) { short vtype; --- 1207,1211 ---- ! static BOOL bindOutput(cursorObject *cur) { short vtype; *************** *** 1228,1232 **** for (pos = 1; pos <= cur->n_columns; pos++) { - PyObject *new_tuple; PyObject *typeOf; long dsize; --- 1218,1221 ---- *************** *** 1254,1258 **** case SQL_INTEGER: case SQL_TINYINT: ! bindOutputVar( cur, longCopy, --- 1243,1247 ---- case SQL_INTEGER: case SQL_TINYINT: ! if (!bindOutputVar( cur, longCopy, *************** *** 1260,1264 **** sizeof(unsigned long), pos, ! false); typeOf = DbiNumber; break; --- 1249,1254 ---- sizeof(unsigned long), pos, ! false)) ! return FALSE; typeOf = DbiNumber; break; *************** *** 1269,1273 **** case SQL_REAL: case SQL_BIGINT: ! bindOutputVar( cur, doubleCopy, --- 1259,1263 ---- case SQL_REAL: case SQL_BIGINT: ! if (!bindOutputVar( cur, doubleCopy, *************** *** 1275,1279 **** sizeof(double), pos, ! false); typeOf = DbiNumber; prec = vsize; --- 1265,1270 ---- sizeof(double), pos, ! false)) ! return FALSE; typeOf = DbiNumber; prec = vsize; *************** *** 1281,1285 **** case SQL_DATE: case SQL_TIMESTAMP: ! bindOutputVar( cur, dateCopy, --- 1272,1276 ---- case SQL_DATE: case SQL_TIMESTAMP: ! if (!bindOutputVar( cur, dateCopy, *************** *** 1287,1296 **** vsize, pos, ! false); typeOf = DbiDate; break; case SQL_LONGVARBINARY: ! cur->bGetDataIsNeeded = true; ! bindOutputVar( cur, rawCopy, --- 1278,1287 ---- vsize, pos, ! false)) ! return FALSE; typeOf = DbiDate; break; case SQL_LONGVARBINARY: ! if (!bindOutputVar( cur, rawCopy, *************** *** 1298,1350 **** cur->max_width, pos, ! true); typeOf = DbiRaw; break; case SQL_BINARY: case SQL_VARBINARY: ! bindOutputVar( ! cur, ! rawCopy, ! SQL_C_BINARY, ! cur->max_width, ! pos, ! false); typeOf = DbiRaw; break; case SQL_VARCHAR: case SQL_WVARCHAR: ! bindOutputVar(cur, wcharCopy, SQL_C_WCHAR, (vsize+1)*sizeof(WCHAR), pos, false); typeOf = DbiString; break; case SQL_LONGVARCHAR: case SQL_WLONGVARCHAR: ! bindOutputVar(cur, wcharCopy, SQL_C_WCHAR, cur->max_width, pos, true); typeOf = DbiString; break; default: ! bindOutputVar(cur, stringCopy, SQL_C_CHAR, vsize+1, pos, false); typeOf = DbiString; break; } ! if (PyErr_Occurred()) ! { ! return 0; ! } ! new_tuple = Py_BuildValue( "(NOiiiii)", PyWinObject_FromTCHAR(name), typeOf, dsize, (int)vsize, prec, scale, nullok); ! if (!new_tuple) ! { ! return 0; ! } ! ! PyList_Append(cur->description, new_tuple); ! Py_DECREF(new_tuple); } /* success */ ! return 1; } --- 1289,1333 ---- cur->max_width, pos, ! true)) ! return FALSE; typeOf = DbiRaw; break; case SQL_BINARY: case SQL_VARBINARY: ! if (!bindOutputVar(cur, rawCopy, SQL_C_BINARY, cur->max_width, pos, false)) ! return FALSE; typeOf = DbiRaw; break; case SQL_VARCHAR: case SQL_WVARCHAR: ! if (!bindOutputVar(cur, wcharCopy, SQL_C_WCHAR, (vsize+1)*sizeof(WCHAR), pos, false)) ! return FALSE; typeOf = DbiString; break; case SQL_LONGVARCHAR: case SQL_WLONGVARCHAR: ! if (!bindOutputVar(cur, wcharCopy, SQL_C_WCHAR, cur->max_width, pos, true)) ! return FALSE; typeOf = DbiString; break; default: ! if (!bindOutputVar(cur, stringCopy, SQL_C_CHAR, vsize+1, pos, false)) ! return FALSE; typeOf = DbiString; break; } ! ! TmpPyObject new_tuple = Py_BuildValue( "(NOiiiii)", PyWinObject_FromTCHAR(name), typeOf, dsize, (int)vsize, prec, scale, nullok); ! if ((new_tuple == NULL) ! || PyList_Append(cur->description, new_tuple) == -1) ! return FALSE; } /* success */ ! return TRUE; } *************** *** 1414,1418 **** { cursorObject *cur = cursor(self); - PyObject *temp = NULL; TCHAR *sql=NULL; PyObject *obsql; --- 1397,1400 ---- *************** *** 1432,1459 **** /* @pyparm string|sql||The SQL to execute */ /* @pyparm sequence|[var, ...]|[]|Input variables. */ ! if (!PyArg_ParseTuple(args, "O|O", &obsql, &inputvars)) { return NULL; } - if (!PyWinObject_AsTCHAR(obsql, &sql, FALSE)) - return NULL; ! if (inputvars && !PySequence_Check(inputvars)) ! { ! PyWinObject_FreeTCHAR(sql); ! PyErr_SetString(odbcError, "expected sequence as second parameter"); ! return NULL; ! } ! else if (inputvars && PySequence_Length(inputvars) > 0) ! { ! temp = PySequence_GetItem(inputvars, 0); ! /* Strings don't count as a list in this case. */ ! if (PySequence_Check(temp) && !PyString_Check(temp) && !PyUnicode_Check(temp)) ! { ! rows = inputvars; ! inputvars = NULL; } ! Py_DECREF(temp); ! } deleteBinding(cur); --- 1414,1443 ---- /* @pyparm string|sql||The SQL to execute */ /* @pyparm sequence|[var, ...]|[]|Input variables. */ ! /* If the first element is itself a sequence (other than a string) ! the input will be interpreted as a sequence of sequences to be ! used to execute the statement multiple times. ! */ ! if (!PyArg_ParseTuple(args, "O|O:execute", &obsql, &inputvars)) { return NULL; } ! if (inputvars){ ! if (PyString_Check(inputvars) || PyUnicode_Check(inputvars) || !PySequence_Check(inputvars)) ! return PyErr_Format(odbcError, "Values must be a sequence, not %s", inputvars->ob_type->tp_name); ! if (PySequence_Length(inputvars) > 0){ ! PyObject *temp = PySequence_GetItem(inputvars, 0); ! if (temp==NULL) ! return NULL; ! /* Strings don't count as a list in this case. */ ! if (PySequence_Check(temp) && !PyString_Check(temp) && !PyUnicode_Check(temp)){ ! rows = inputvars; ! inputvars = NULL; ! } ! Py_DECREF(temp); ! } } ! if (!PyWinObject_AsTCHAR(obsql, &sql, FALSE)) ! return NULL; deleteBinding(cur); *************** *** 1597,1603 **** while (ob) { ! long cbRequired; RETCODE rc; ! long cbRead = 0; /* Use SQLGetData to retrieve data for blob (or long varchar) type columns. */ if (ob->bGetData) --- 1581,1587 ---- while (ob) { ! SQLLEN cbRequired; RETCODE rc; ! SQLLEN cbRead = 0; /* Use SQLGetData to retrieve data for blob (or long varchar) type columns. */ if (ob->bGetData) *************** *** 1619,1636 **** if (cbRequired > ob->vsize) { ! void *pTemp; /* Some BLOBs can be huge, be paranoid about allowing other threads to run. */ Py_BEGIN_ALLOW_THREADS ! pTemp = malloc (cbRequired); ! memcpy(pTemp, ob->bind_area, ob->vsize); ! free (ob->bind_area); Py_END_ALLOW_THREADS ! ob->bind_area = pTemp; ob->vsize = cbRequired; } /* rc = GetData( ... , bind_area + offset, vsize - offset, &rcode ) */ - SQLLEN rcode; Py_BEGIN_ALLOW_THREADS rc = SQLGetData(cur->hstmt, --- 1603,1622 ---- if (cbRequired > ob->vsize) { ! void *pTemp = ob->bind_area; /* Some BLOBs can be huge, be paranoid about allowing other threads to run. */ Py_BEGIN_ALLOW_THREADS ! ob->bind_area = realloc (ob->bind_area, cbRequired); Py_END_ALLOW_THREADS ! if (ob->bind_area == NULL){ ! PyErr_NoMemory(); ! ob->bind_area = pTemp; ! Py_DECREF(row); ! return NULL; ! } ob->vsize = cbRequired; } /* rc = GetData( ... , bind_area + offset, vsize - offset, &rcode ) */ Py_BEGIN_ALLOW_THREADS rc = SQLGetData(cur->hstmt, *************** *** 1639,1678 **** (char *)ob->bind_area + cbRead, ob->vsize - cbRead, ! &rcode); ! ob->rcode = PyWin_SAFE_DOWNCAST(rcode, SQLLEN, long); Py_END_ALLOW_THREADS if (unsuccessful(rc)) { Py_DECREF(row); ! cursorError(cur, _T("FETCH")); return NULL; } ! ! if ((ob->rcode != SQL_NO_TOTAL) && (ob->rcode <= ob->vsize - cbRead)) { ! /* If we get here, then this should be the last iteration ! through the loop. */ cbRead += ob->rcode; } else { ! /* Grow buffer by (32k minus 1 byte) each for each chunk. ! If not for the SQL Anywhere 5.0 problem (driver version ! 5.05.041867), we could probably grow by 50% each time ! or the remaining size (as determined by ob->rcode). */ ! ! /*cbRequired += ob->rcode - ob->vsize; */ ! cbRequired += 32767; /* Fix that works for SQL Anywhere 5.0 driver. */ ! if (ob->vtype == SQL_C_CHAR) ! { ! /* We want to ignore the intermediate ! NULL characters SQLGetData() gives us. (silly, silly) */ cbRead = ob->vsize - 1; ! } else - { cbRead = ob->vsize; - } } --- 1625,1661 ---- (char *)ob->bind_area + cbRead, ob->vsize - cbRead, ! &ob->rcode); Py_END_ALLOW_THREADS if (unsuccessful(rc)) { Py_DECREF(row); ! cursorError(cur, _T("SQLGetData")); return NULL; } ! /* Returned length is total length remaining including current read. ! If length is not known, returns SQL_NO_TOTAL */ ! if ((ob->rcode != SQL_NO_TOTAL) && (ob->rcode <= cur->max_width)) { ! /* If we get here, then this should be the last iteration through the loop. */ cbRead += ob->rcode; } else { ! /* Grow buffer by cursor chunk size for each read. ! If not for the SQL Anywhere 5.0 problem (driver version ! 5.05.041867), we could probably grow by 50% each time ! or the remaining size (as determined by ob->rcode). ! Regarding above note, caller can now use cursor.setoutputsize ! to work around any such bug in a driver */ ! cbRequired += cur->max_width; ! /* We want to ignore the intermediate ! NULL characters SQLGetData() gives us. (silly, silly) */ + if (ob->vtype == SQL_C_CHAR) cbRead = ob->vsize - 1; ! else if (ob->vtype == SQL_C_WCHAR) ! cbRead = ob->vsize - sizeof(WCHAR); else cbRead = ob->vsize; } Index: PyWinTypes.h =================================================================== RCS file: /cvsroot/pywin32/pywin32/win32/src/PyWinTypes.h,v retrieving revision 1.51 retrieving revision 1.52 diff -C2 -d -r1.51 -r1.52 *** PyWinTypes.h 10 Feb 2008 13:44:20 -0000 1.51 --- PyWinTypes.h 20 Oct 2008 03:22:25 -0000 1.52 *************** *** 762,765 **** --- 762,784 ---- // End of exception helper macros. + + // Class to hold a temporary reference that decrements itself + class TmpPyObject + { + public: + PyObject *tmp; + TmpPyObject() { tmp=NULL; } + TmpPyObject(PyObject *ob) { tmp=ob; } + PyObject * operator= (PyObject *ob){ + Py_XDECREF(tmp); + tmp=ob; + return tmp; + } + + boolean operator== (PyObject *ob) { return tmp==ob; } + operator PyObject *() { return tmp; } + ~TmpPyObject() { Py_XDECREF(tmp); } + }; + #endif // __PYWINTYPES_H__ |