My favorites | Sign in
Project Home Downloads Wiki
READ-ONLY: This project has been archived. For more information see this post.
Search
for
  Advanced search   Search tips   Subscriptions

Issue 296 attachment: xmlcol.patch (3.2 KB)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
--- src\getdata.h.orig 2013-04-13 08:28:44.000000000 -0400
+++ src\getdata.h 2013-04-13 12:55:40.000000000 -0400
@@ -4,6 +4,8 @@

void GetData_init();

+extern SQLLEN cbGetDataStrSize;
+
PyObject* GetData(Cursor* cur, Py_ssize_t iCol);

/**
--- src\getdata.cpp.orig 2012-06-24 17:49:34.000000000 -0400
+++ src\getdata.cpp 2013-04-24 09:26:58.000000000 -0400
@@ -265,6 +265,8 @@
};


+SQLLEN cbGetDataStrSize = 4 * 1024; // default buffer size
+
static PyObject* GetDataString(Cursor* cur, Py_ssize_t iCol)
{
// Returns a string, unicode, or bytearray object for character and binary data.
@@ -297,6 +299,7 @@
pinfo->column_size = 36;

SQLSMALLINT nTargetType;
+ SQLLEN cbBufIncrement = cbGetDataStrSize;

switch (pinfo->sql_type)
{
@@ -327,10 +330,13 @@
break;
}

- char tempBuffer[1024];
- DataBuffer buffer(nTargetType, tempBuffer, sizeof(tempBuffer));
+ char *pTempBuffer = (char *) _alloca((size_t)cbBufIncrement);
+ DataBuffer buffer(nTargetType, pTempBuffer, cbBufIncrement);
+
+ const int max_resizes = 10;
+ TRACE("starting bufsize %d\n", buffer.GetRemaining());

- for (int iDbg = 0; iDbg < 10; iDbg++) // failsafe
+ for (int iDbg = 0; iDbg < max_resizes; iDbg++) // failsafe, large reads fail with MemoryError
{
SQLRETURN ret;
SQLLEN cbData = 0;
@@ -374,7 +380,9 @@
{
// We don't know how much more, so just guess.
cbRead = cbBuffer - buffer.null_size;
- cbMore = 2048;
+ cbBufIncrement *= 2; // double previously used buffer increment
+ TRACE("increasing bufsize by %d\n", cbBufIncrement);
+ cbMore = cbBufIncrement;
}
else if (cbData >= cbBuffer)
{
@@ -391,9 +399,17 @@
cbMore = 0;
}

+ if(iDbg+1 == max_resizes)
+ {
+ PyErr_SetString(PyExc_MemoryError, "multi-megabyte string, see connect function's getdata_str_size keyword");
+ return 0 /* NULL */;
+ }
+
buffer.AddUsed(cbRead);
if (!buffer.AllocateMore(cbMore))
return PyErr_NoMemory();
+
+ TRACE("bufsize remaining after realloc %d\n", buffer.GetRemaining());
}
else if (ret == SQL_SUCCESS)
{
--- src\pyodbcmodule.cpp.orig 2012-02-14 10:14:30.000000000 -0500
+++ src\pyodbcmodule.cpp 2013-04-22 11:44:11.000000000 -0400
@@ -323,6 +323,20 @@
fReadOnly = PyObject_IsTrue(value);
continue;
}
+ if (Text_EqualsI(key, "getdata_str_size"))
+ {
+ cbGetDataStrSize = PyInt_AsLong(value);
+
+ if (PyErr_Occurred())
+ return 0;
+
+ if (cbGetDataStrSize < 1024)
+ cbGetDataStrSize = 1024; // set floor
+ else if (cbGetDataStrSize > 1024 * 128)
+ cbGetDataStrSize = 1024 * 128; // set ceiling
+
+ continue;
+ }

// Map DB API recommended names to ODBC names (e.g. user --> uid).

Powered by Google Project Hosting