upgraded pypyodbc.py
This commit is contained in:
@@ -1 +1 @@
|
|||||||
Version 2.9.9-stable+timestamp.2014.09.14.16.37.05
|
Version 2.9.9-stable+timestamp.2014.09.14.16.41.44
|
||||||
|
|||||||
+205
-96
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
# The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
#
|
#
|
||||||
# Copyright (c) 2013 Henry Zhou <jiangwen365@gmail.com> and PyPyODBC contributors
|
# Copyright (c) 2014 Henry Zhou <jiangwen365@gmail.com> and PyPyODBC contributors
|
||||||
# Copyright (c) 2004 Michele Petrazzo
|
# Copyright (c) 2004 Michele Petrazzo
|
||||||
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# of the Software.
|
# of the Software.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||||
# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO #EVENT SHALL THE
|
# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
# DEALINGS IN THE SOFTWARE.
|
# DEALINGS IN THE SOFTWARE.
|
||||||
@@ -25,7 +25,7 @@ pooling = True
|
|||||||
apilevel = '2.0'
|
apilevel = '2.0'
|
||||||
paramstyle = 'qmark'
|
paramstyle = 'qmark'
|
||||||
threadsafety = 1
|
threadsafety = 1
|
||||||
version = '1.2.0'
|
version = '1.3.0'
|
||||||
lowercase=True
|
lowercase=True
|
||||||
|
|
||||||
DEBUG = 0
|
DEBUG = 0
|
||||||
@@ -592,38 +592,38 @@ if sys.platform == 'cli':
|
|||||||
# http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.sdk_12.5.1.aseodbc/html/aseodbc/CACFDIGH.htm
|
# http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.sdk_12.5.1.aseodbc/html/aseodbc/CACFDIGH.htm
|
||||||
|
|
||||||
SQL_data_type_dict = { \
|
SQL_data_type_dict = { \
|
||||||
#SQL Data TYPE 0.Python Data Type 1.Default Output Converter 2.Buffer Type 3.Buffer Allocator 4.Default Buffer Size
|
#SQL Data TYPE 0.Python Data Type 1.Default Output Converter 2.Buffer Type 3.Buffer Allocator 4.Default Size 5.Variable Length
|
||||||
SQL_TYPE_NULL : (None, lambda x: None, SQL_C_CHAR, create_buffer, 2 ),
|
SQL_TYPE_NULL : (None, lambda x: None, SQL_C_CHAR, create_buffer, 2 , False ),
|
||||||
SQL_CHAR : (str, lambda x: x, SQL_C_CHAR, create_buffer, 2048 ),
|
SQL_CHAR : (str, lambda x: x, SQL_C_CHAR, create_buffer, 2048 , False ),
|
||||||
SQL_NUMERIC : (Decimal, Decimal_cvt, SQL_C_CHAR, create_buffer, 150 ),
|
SQL_NUMERIC : (Decimal, Decimal_cvt, SQL_C_CHAR, create_buffer, 150 , False ),
|
||||||
SQL_DECIMAL : (Decimal, Decimal_cvt, SQL_C_CHAR, create_buffer, 150 ),
|
SQL_DECIMAL : (Decimal, Decimal_cvt, SQL_C_CHAR, create_buffer, 150 , False ),
|
||||||
SQL_INTEGER : (int, int, SQL_C_CHAR, create_buffer, 150 ),
|
SQL_INTEGER : (int, int, SQL_C_CHAR, create_buffer, 150 , False ),
|
||||||
SQL_SMALLINT : (int, int, SQL_C_CHAR, create_buffer, 150 ),
|
SQL_SMALLINT : (int, int, SQL_C_CHAR, create_buffer, 150 , False ),
|
||||||
SQL_FLOAT : (float, float, SQL_C_CHAR, create_buffer, 150 ),
|
SQL_FLOAT : (float, float, SQL_C_CHAR, create_buffer, 150 , False ),
|
||||||
SQL_REAL : (float, float, SQL_C_CHAR, create_buffer, 150 ),
|
SQL_REAL : (float, float, SQL_C_CHAR, create_buffer, 150 , False ),
|
||||||
SQL_DOUBLE : (float, float, SQL_C_CHAR, create_buffer, 200 ),
|
SQL_DOUBLE : (float, float, SQL_C_CHAR, create_buffer, 200 , False ),
|
||||||
SQL_DATE : (datetime.date, dt_cvt, SQL_C_CHAR , create_buffer, 30 ),
|
SQL_DATE : (datetime.date, dt_cvt, SQL_C_CHAR, create_buffer, 30 , False ),
|
||||||
SQL_TIME : (datetime.time, tm_cvt, SQL_C_CHAR, create_buffer, 20 ),
|
SQL_TIME : (datetime.time, tm_cvt, SQL_C_CHAR, create_buffer, 20 , False ),
|
||||||
SQL_SS_TIME2 : (datetime.time, tm_cvt, SQL_C_CHAR, create_buffer, 20 ),
|
SQL_SS_TIME2 : (datetime.time, tm_cvt, SQL_C_CHAR, create_buffer, 20 , False ),
|
||||||
SQL_TIMESTAMP : (datetime.datetime, dttm_cvt, SQL_C_CHAR, create_buffer, 30 ),
|
SQL_TIMESTAMP : (datetime.datetime, dttm_cvt, SQL_C_CHAR, create_buffer, 30 , False ),
|
||||||
SQL_VARCHAR : (str, lambda x: x, SQL_C_CHAR, create_buffer, 2048 ),
|
SQL_VARCHAR : (str, lambda x: x, SQL_C_CHAR, create_buffer, 2048 , False ),
|
||||||
SQL_LONGVARCHAR : (str, lambda x: x, SQL_C_CHAR, create_buffer, 20500 ),
|
SQL_LONGVARCHAR : (str, lambda x: x, SQL_C_CHAR, create_buffer, 20500 , True ),
|
||||||
SQL_BINARY : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 5120 ),
|
SQL_BINARY : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 5120 , True ),
|
||||||
SQL_VARBINARY : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 5120 ),
|
SQL_VARBINARY : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 5120 , True ),
|
||||||
SQL_LONGVARBINARY : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 20500 ),
|
SQL_LONGVARBINARY : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 20500 , True ),
|
||||||
SQL_BIGINT : (long, long, SQL_C_CHAR, create_buffer, 150 ),
|
SQL_BIGINT : (long, long, SQL_C_CHAR, create_buffer, 150 , False ),
|
||||||
SQL_TINYINT : (int, int, SQL_C_CHAR, create_buffer, 150 ),
|
SQL_TINYINT : (int, int, SQL_C_CHAR, create_buffer, 150 , False ),
|
||||||
SQL_BIT : (bool, lambda x:x == BYTE_1, SQL_C_CHAR, create_buffer, 2 ),
|
SQL_BIT : (bool, lambda x:x == BYTE_1, SQL_C_CHAR, create_buffer, 2 , False ),
|
||||||
SQL_WCHAR : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 2048 ),
|
SQL_WCHAR : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 2048 , False ),
|
||||||
SQL_WVARCHAR : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 2048 ),
|
SQL_WVARCHAR : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 2048 , False ),
|
||||||
SQL_GUID : (str, str, SQL_C_CHAR, create_buffer, 50 ),
|
SQL_GUID : (str, str, SQL_C_CHAR, create_buffer, 2048 , False ),
|
||||||
SQL_WLONGVARCHAR : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 20500 ),
|
SQL_WLONGVARCHAR : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 20500 , True ),
|
||||||
SQL_TYPE_DATE : (datetime.date, dt_cvt, SQL_C_CHAR, create_buffer, 30 ),
|
SQL_TYPE_DATE : (datetime.date, dt_cvt, SQL_C_CHAR, create_buffer, 30 , False ),
|
||||||
SQL_TYPE_TIME : (datetime.time, tm_cvt, SQL_C_CHAR, create_buffer, 20 ),
|
SQL_TYPE_TIME : (datetime.time, tm_cvt, SQL_C_CHAR, create_buffer, 20 , False ),
|
||||||
SQL_TYPE_TIMESTAMP : (datetime.datetime, dttm_cvt, SQL_C_CHAR, create_buffer, 30 ),
|
SQL_TYPE_TIMESTAMP : (datetime.datetime, dttm_cvt, SQL_C_CHAR, create_buffer, 30 , False ),
|
||||||
SQL_SS_VARIANT : (str, lambda x: x, SQL_C_CHAR, create_buffer, 2048 ),
|
SQL_SS_VARIANT : (str, lambda x: x, SQL_C_CHAR, create_buffer, 2048 , True ),
|
||||||
SQL_SS_XML : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 20500 ),
|
SQL_SS_XML : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 20500 , True ),
|
||||||
SQL_SS_UDT : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 5120 ),
|
SQL_SS_UDT : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 5120 , True ),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -645,6 +645,7 @@ SQLRETURN -> ctypes.c_short
|
|||||||
funcs_with_ret = [
|
funcs_with_ret = [
|
||||||
"SQLAllocHandle",
|
"SQLAllocHandle",
|
||||||
"SQLBindParameter",
|
"SQLBindParameter",
|
||||||
|
"SQLBindCol",
|
||||||
"SQLCloseCursor",
|
"SQLCloseCursor",
|
||||||
"SQLColAttribute",
|
"SQLColAttribute",
|
||||||
"SQLColumns",
|
"SQLColumns",
|
||||||
@@ -1175,7 +1176,9 @@ class Cursor:
|
|||||||
"""prepare a query"""
|
"""prepare a query"""
|
||||||
|
|
||||||
#self._free_results(FREE_STATEMENT)
|
#self._free_results(FREE_STATEMENT)
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
if type(query_string) == unicode:
|
if type(query_string) == unicode:
|
||||||
c_query_string = wchar_pointer(UCS_buf(query_string))
|
c_query_string = wchar_pointer(UCS_buf(query_string))
|
||||||
ret = ODBC_API.SQLPrepareW(self.stmt_h, c_query_string, len(query_string))
|
ret = ODBC_API.SQLPrepareW(self.stmt_h, c_query_string, len(query_string))
|
||||||
@@ -1231,6 +1234,8 @@ class Cursor:
|
|||||||
def _BindParams(self, param_types, pram_io_list = []):
|
def _BindParams(self, param_types, pram_io_list = []):
|
||||||
"""Create parameter buffers based on param types, and bind them to the statement"""
|
"""Create parameter buffers based on param types, and bind them to the statement"""
|
||||||
# Clear the old Parameters
|
# Clear the old Parameters
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
#self._free_results(NO_FREE_STATEMENT)
|
#self._free_results(NO_FREE_STATEMENT)
|
||||||
|
|
||||||
# Get the number of query parameters judged by database.
|
# Get the number of query parameters judged by database.
|
||||||
@@ -1414,7 +1419,7 @@ class Cursor:
|
|||||||
dec_num, ADDR(ParameterBuffer), BufferLen,ADDR(LenOrIndBuf))
|
dec_num, ADDR(ParameterBuffer), BufferLen,ADDR(LenOrIndBuf))
|
||||||
if ret != SQL_SUCCESS:
|
if ret != SQL_SUCCESS:
|
||||||
check_success(self, ret)
|
check_success(self, ret)
|
||||||
# Append the value buffer and the lenth buffer to the array
|
# Append the value buffer and the length buffer to the array
|
||||||
ParamBufferList.append((ParameterBuffer,LenOrIndBuf,sql_type))
|
ParamBufferList.append((ParameterBuffer,LenOrIndBuf,sql_type))
|
||||||
|
|
||||||
self._last_param_types = param_types
|
self._last_param_types = param_types
|
||||||
@@ -1426,6 +1431,9 @@ class Cursor:
|
|||||||
If parameters are provided, the query would first be prepared, then executed with parameters;
|
If parameters are provided, the query would first be prepared, then executed with parameters;
|
||||||
If parameters are not provided, only th query sting, it would be executed directly
|
If parameters are not provided, only th query sting, it would be executed directly
|
||||||
"""
|
"""
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
self._free_stmt(SQL_CLOSE)
|
self._free_stmt(SQL_CLOSE)
|
||||||
if params:
|
if params:
|
||||||
# If parameters exist, first prepare the query then executed with parameters
|
# If parameters exist, first prepare the query then executed with parameters
|
||||||
@@ -1549,7 +1557,7 @@ class Cursor:
|
|||||||
c_buf_len = len(c_char_buf)
|
c_buf_len = len(c_char_buf)
|
||||||
|
|
||||||
elif param_types[col_num][0] == 'bi':
|
elif param_types[col_num][0] == 'bi':
|
||||||
c_char_buf = str(param_val)
|
c_char_buf = str_8b(param_val)
|
||||||
c_buf_len = len(c_char_buf)
|
c_buf_len = len(c_char_buf)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@@ -1587,6 +1595,8 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def _SQLExecute(self):
|
def _SQLExecute(self):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
ret = SQLExecute(self.stmt_h)
|
ret = SQLExecute(self.stmt_h)
|
||||||
if ret != SQL_SUCCESS:
|
if ret != SQL_SUCCESS:
|
||||||
check_success(self, ret)
|
check_success(self, ret)
|
||||||
@@ -1594,6 +1604,9 @@ class Cursor:
|
|||||||
|
|
||||||
def execdirect(self, query_string):
|
def execdirect(self, query_string):
|
||||||
"""Execute a query directly"""
|
"""Execute a query directly"""
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
self._free_stmt()
|
self._free_stmt()
|
||||||
self._last_param_types = None
|
self._last_param_types = None
|
||||||
self.statement = None
|
self.statement = None
|
||||||
@@ -1611,6 +1624,8 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def callproc(self, procname, args):
|
def callproc(self, procname, args):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
raise Warning('', 'Still not fully implemented')
|
raise Warning('', 'Still not fully implemented')
|
||||||
self._pram_io_list = [row[4] for row in self.procedurecolumns(procedure = procname).fetchall() if row[4] not in (SQL_RESULT_COL, SQL_RETURN_VALUE)]
|
self._pram_io_list = [row[4] for row in self.procedurecolumns(procedure = procname).fetchall() if row[4] not in (SQL_RESULT_COL, SQL_RETURN_VALUE)]
|
||||||
|
|
||||||
@@ -1637,6 +1652,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def executemany(self, query_string, params_list = [None]):
|
def executemany(self, query_string, params_list = [None]):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
for params in params_list:
|
for params in params_list:
|
||||||
self.execute(query_string, params, many_mode = True)
|
self.execute(query_string, params, many_mode = True)
|
||||||
self._NumOfRows()
|
self._NumOfRows()
|
||||||
@@ -1647,28 +1665,38 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def _CreateColBuf(self):
|
def _CreateColBuf(self):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
self._free_stmt(SQL_UNBIND)
|
self._free_stmt(SQL_UNBIND)
|
||||||
NOC = self._NumOfCols()
|
NOC = self._NumOfCols()
|
||||||
self._ColBufferList = []
|
self._ColBufferList = []
|
||||||
|
bind_data = True
|
||||||
for col_num in range(NOC):
|
for col_num in range(NOC):
|
||||||
col_name = self.description[col_num][0]
|
col_name = self.description[col_num][0]
|
||||||
|
col_size = self.description[col_num][2]
|
||||||
col_sql_data_type = self._ColTypeCodeList[col_num]
|
col_sql_data_type = self._ColTypeCodeList[col_num]
|
||||||
|
|
||||||
|
target_type = SQL_data_type_dict[col_sql_data_type][2]
|
||||||
|
dynamic_length = SQL_data_type_dict[col_sql_data_type][5]
|
||||||
# set default size base on the column's sql data type
|
# set default size base on the column's sql data type
|
||||||
total_buf_len = SQL_data_type_dict[col_sql_data_type][4]
|
total_buf_len = SQL_data_type_dict[col_sql_data_type][4]
|
||||||
# over-write if there's preset size value for "large columns"
|
|
||||||
if total_buf_len >= 20500:
|
# over-write if there's pre-set size value for "large columns"
|
||||||
|
if total_buf_len > 20500:
|
||||||
total_buf_len = self._outputsize.get(None,total_buf_len)
|
total_buf_len = self._outputsize.get(None,total_buf_len)
|
||||||
# over-write if there's preset size value for the "col_num" column
|
# over-write if there's pre-set size value for the "col_num" column
|
||||||
total_buf_len = self._outputsize.get(col_num, total_buf_len)
|
total_buf_len = self._outputsize.get(col_num, total_buf_len)
|
||||||
|
|
||||||
|
# if the size of the buffer is very long, do not bind
|
||||||
|
# because a large buffer decrease performance, and sometimes you only get a NULL value.
|
||||||
|
# in that case use sqlgetdata instead.
|
||||||
|
if col_size >= 1024:
|
||||||
|
dynamic_length = True
|
||||||
|
|
||||||
alloc_buffer = SQL_data_type_dict[col_sql_data_type][3](total_buf_len)
|
alloc_buffer = SQL_data_type_dict[col_sql_data_type][3](total_buf_len)
|
||||||
|
|
||||||
used_buf_len = c_ssize_t()
|
used_buf_len = c_ssize_t()
|
||||||
|
|
||||||
target_type = SQL_data_type_dict[col_sql_data_type][2]
|
|
||||||
force_unicode = self.connection.unicode_results
|
force_unicode = self.connection.unicode_results
|
||||||
|
|
||||||
if force_unicode and col_sql_data_type in (SQL_CHAR,SQL_VARCHAR,SQL_LONGVARCHAR):
|
if force_unicode and col_sql_data_type in (SQL_CHAR,SQL_VARCHAR,SQL_LONGVARCHAR):
|
||||||
@@ -1676,14 +1704,22 @@ class Cursor:
|
|||||||
alloc_buffer = create_buffer_u(total_buf_len)
|
alloc_buffer = create_buffer_u(total_buf_len)
|
||||||
|
|
||||||
buf_cvt_func = self.connection.output_converter[self._ColTypeCodeList[col_num]]
|
buf_cvt_func = self.connection.output_converter[self._ColTypeCodeList[col_num]]
|
||||||
ADDR(alloc_buffer)
|
|
||||||
ADDR(used_buf_len)
|
if bind_data:
|
||||||
self._ColBufferList.append([col_name, target_type, used_buf_len, ADDR(used_buf_len), alloc_buffer, ADDR(alloc_buffer), total_buf_len, buf_cvt_func])
|
if dynamic_length:
|
||||||
|
bind_data = False
|
||||||
|
self._ColBufferList.append([col_name, target_type, used_buf_len, ADDR(used_buf_len), alloc_buffer, ADDR(alloc_buffer), total_buf_len, buf_cvt_func, bind_data])
|
||||||
|
|
||||||
|
if bind_data:
|
||||||
|
ret = ODBC_API.SQLBindCol(self.stmt_h, col_num + 1, target_type, ADDR(alloc_buffer), total_buf_len, ADDR(used_buf_len))
|
||||||
|
if ret != SQL_SUCCESS:
|
||||||
|
check_success(self, ret)
|
||||||
|
|
||||||
def _UpdateDesc(self):
|
def _UpdateDesc(self):
|
||||||
"Get the information of (name, type_code, display_size, internal_size, col_precision, scale, null_ok)"
|
"Get the information of (name, type_code, display_size, internal_size, col_precision, scale, null_ok)"
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
force_unicode = self.connection.unicode_results
|
force_unicode = self.connection.unicode_results
|
||||||
if force_unicode:
|
if force_unicode:
|
||||||
Cname = create_buffer_u(1024)
|
Cname = create_buffer_u(1024)
|
||||||
@@ -1739,6 +1775,9 @@ class Cursor:
|
|||||||
|
|
||||||
def _NumOfRows(self):
|
def _NumOfRows(self):
|
||||||
"""Get the number of rows"""
|
"""Get the number of rows"""
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
NOR = c_ssize_t()
|
NOR = c_ssize_t()
|
||||||
ret = SQLRowCount(self.stmt_h, ADDR(NOR))
|
ret = SQLRowCount(self.stmt_h, ADDR(NOR))
|
||||||
if ret != SQL_SUCCESS:
|
if ret != SQL_SUCCESS:
|
||||||
@@ -1749,6 +1788,9 @@ class Cursor:
|
|||||||
|
|
||||||
def _NumOfCols(self):
|
def _NumOfCols(self):
|
||||||
"""Get the number of cols"""
|
"""Get the number of cols"""
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
NOC = c_short()
|
NOC = c_short()
|
||||||
ret = SQLNumResultCols(self.stmt_h, ADDR(NOC))
|
ret = SQLNumResultCols(self.stmt_h, ADDR(NOC))
|
||||||
if ret != SQL_SUCCESS:
|
if ret != SQL_SUCCESS:
|
||||||
@@ -1757,6 +1799,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def fetchall(self):
|
def fetchall(self):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
rows = []
|
rows = []
|
||||||
while True:
|
while True:
|
||||||
row = self.fetchone()
|
row = self.fetchone()
|
||||||
@@ -1767,6 +1812,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def fetchmany(self, num = None):
|
def fetchmany(self, num = None):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
if num is None:
|
if num is None:
|
||||||
num = self.arraysize
|
num = self.arraysize
|
||||||
rows = []
|
rows = []
|
||||||
@@ -1780,74 +1828,83 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def fetchone(self):
|
def fetchone(self):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
ret = SQLFetch(self.stmt_h)
|
ret = SQLFetch(self.stmt_h)
|
||||||
if ret == SQL_SUCCESS:
|
|
||||||
|
if ret in (SQL_SUCCESS,SQL_SUCCESS_WITH_INFO):
|
||||||
'''Bind buffers for the record set columns'''
|
'''Bind buffers for the record set columns'''
|
||||||
|
|
||||||
value_list = []
|
value_list = []
|
||||||
col_num = 1
|
col_num = 1
|
||||||
for col_name, target_type, used_buf_len, ADDR_used_buf_len, alloc_buffer, ADDR_alloc_buffer, total_buf_len, buf_cvt_func in self._ColBufferList:
|
for col_name, target_type, used_buf_len, ADDR_used_buf_len, alloc_buffer, ADDR_alloc_buffer, total_buf_len, buf_cvt_func, bind_data in self._ColBufferList:
|
||||||
|
raw_data_parts = []
|
||||||
blocks = []
|
|
||||||
while 1:
|
while 1:
|
||||||
ret = SQLGetData(self.stmt_h, col_num, target_type, ADDR_alloc_buffer, total_buf_len, ADDR_used_buf_len)
|
if bind_data:
|
||||||
|
ret = SQL_SUCCESS
|
||||||
|
else:
|
||||||
|
ret = SQLGetData(self.stmt_h, col_num, target_type, ADDR_alloc_buffer, total_buf_len, ADDR_used_buf_len)
|
||||||
if ret == SQL_SUCCESS:
|
if ret == SQL_SUCCESS:
|
||||||
if used_buf_len.value == SQL_NULL_DATA:
|
if used_buf_len.value == SQL_NULL_DATA:
|
||||||
value_list.append(None)
|
value_list.append(None)
|
||||||
else:
|
else:
|
||||||
if blocks == []:
|
if raw_data_parts == []:
|
||||||
|
# Means no previous data, no need to combine
|
||||||
if target_type == SQL_C_BINARY:
|
if target_type == SQL_C_BINARY:
|
||||||
value_list.append(buf_cvt_func(alloc_buffer.raw[:used_buf_len.value]))
|
value_list.append(buf_cvt_func(alloc_buffer.raw[:used_buf_len.value]))
|
||||||
elif target_type == SQL_C_WCHAR:
|
elif target_type == SQL_C_WCHAR:
|
||||||
value_list.append(buf_cvt_func(from_buffer_u(alloc_buffer)))
|
value_list.append(buf_cvt_func(from_buffer_u(alloc_buffer)))
|
||||||
else:
|
else:
|
||||||
#print col_name, target_type, alloc_buffer.value
|
|
||||||
value_list.append(buf_cvt_func(alloc_buffer.value))
|
value_list.append(buf_cvt_func(alloc_buffer.value))
|
||||||
else:
|
else:
|
||||||
|
# There are previous fetched raw data to combine
|
||||||
if target_type == SQL_C_BINARY:
|
if target_type == SQL_C_BINARY:
|
||||||
blocks.append(alloc_buffer.raw[:used_buf_len.value])
|
raw_data_parts.append(alloc_buffer.raw[:used_buf_len.value])
|
||||||
elif target_type == SQL_C_WCHAR:
|
elif target_type == SQL_C_WCHAR:
|
||||||
blocks.append(from_buffer_u(alloc_buffer))
|
raw_data_parts.append(from_buffer_u(alloc_buffer))
|
||||||
else:
|
else:
|
||||||
#print col_name, target_type, alloc_buffer.value
|
raw_data_parts.append(alloc_buffer.value)
|
||||||
blocks.append(alloc_buffer.value)
|
|
||||||
break
|
break
|
||||||
|
|
||||||
elif ret == SQL_SUCCESS_WITH_INFO:
|
elif ret == SQL_SUCCESS_WITH_INFO:
|
||||||
|
# Means the data is only partial
|
||||||
if target_type == SQL_C_BINARY:
|
if target_type == SQL_C_BINARY:
|
||||||
blocks.append(alloc_buffer.raw)
|
raw_data_parts.append(alloc_buffer.raw)
|
||||||
else:
|
else:
|
||||||
blocks.append(alloc_buffer.value)
|
raw_data_parts.append(alloc_buffer.value)
|
||||||
|
|
||||||
elif ret == SQL_NO_DATA:
|
elif ret == SQL_NO_DATA:
|
||||||
|
# Means all data has been transmitted
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
check_success(self, ret)
|
check_success(self, ret)
|
||||||
|
|
||||||
if blocks != []:
|
if raw_data_parts != []:
|
||||||
if py_v3:
|
if py_v3:
|
||||||
if target_type != SQL_C_BINARY:
|
if target_type != SQL_C_BINARY:
|
||||||
raw_value = ''.join(blocks)
|
raw_value = ''.join(raw_data_parts)
|
||||||
else:
|
else:
|
||||||
raw_value = BLANK_BYTE.join(blocks)
|
raw_value = BLANK_BYTE.join(raw_data_parts)
|
||||||
else:
|
else:
|
||||||
raw_value = ''.join(blocks)
|
raw_value = ''.join(raw_data_parts)
|
||||||
|
|
||||||
value_list.append(buf_cvt_func(raw_value))
|
value_list.append(buf_cvt_func(raw_value))
|
||||||
col_num += 1
|
col_num += 1
|
||||||
|
|
||||||
return self._row_type(value_list)
|
return self._row_type(value_list)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if ret == SQL_NO_DATA_FOUND:
|
if ret == SQL_NO_DATA_FOUND:
|
||||||
|
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
check_success(self, ret)
|
check_success(self, ret)
|
||||||
|
|
||||||
def __next__(self):
|
def __next__(self):
|
||||||
self.next()
|
return self.next()
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
row = self.fetchone()
|
row = self.fetchone()
|
||||||
if row is None:
|
if row is None:
|
||||||
raise(StopIteration)
|
raise(StopIteration)
|
||||||
@@ -1858,6 +1915,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def skip(self, count = 0):
|
def skip(self, count = 0):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
ret = ODBC_API.SQLFetchScroll(self.stmt_h, SQL_FETCH_NEXT, 0)
|
ret = ODBC_API.SQLFetchScroll(self.stmt_h, SQL_FETCH_NEXT, 0)
|
||||||
if ret != SQL_SUCCESS:
|
if ret != SQL_SUCCESS:
|
||||||
@@ -1867,6 +1927,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def nextset(self):
|
def nextset(self):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
ret = ODBC_API.SQLMoreResults(self.stmt_h)
|
ret = ODBC_API.SQLMoreResults(self.stmt_h)
|
||||||
if ret not in (SQL_SUCCESS, SQL_NO_DATA):
|
if ret not in (SQL_SUCCESS, SQL_NO_DATA):
|
||||||
check_success(self, ret)
|
check_success(self, ret)
|
||||||
@@ -1882,6 +1945,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def _free_stmt(self, free_type = None):
|
def _free_stmt(self, free_type = None):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
if not self.connection.connected:
|
if not self.connection.connected:
|
||||||
raise ProgrammingError('HY000','Attempt to use a closed connection.')
|
raise ProgrammingError('HY000','Attempt to use a closed connection.')
|
||||||
|
|
||||||
@@ -1903,6 +1969,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def getTypeInfo(self, sqlType = None):
|
def getTypeInfo(self, sqlType = None):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
if sqlType is None:
|
if sqlType is None:
|
||||||
type = SQL_ALL_TYPES
|
type = SQL_ALL_TYPES
|
||||||
else:
|
else:
|
||||||
@@ -1917,6 +1986,9 @@ class Cursor:
|
|||||||
|
|
||||||
def tables(self, table=None, catalog=None, schema=None, tableType=None):
|
def tables(self, table=None, catalog=None, schema=None, tableType=None):
|
||||||
"""Return a list with all tables"""
|
"""Return a list with all tables"""
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
l_catalog = l_schema = l_table = l_tableType = 0
|
l_catalog = l_schema = l_table = l_tableType = 0
|
||||||
|
|
||||||
if unicode in [type(x) for x in (table, catalog, schema,tableType)]:
|
if unicode in [type(x) for x in (table, catalog, schema,tableType)]:
|
||||||
@@ -1961,7 +2033,10 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def columns(self, table=None, catalog=None, schema=None, column=None):
|
def columns(self, table=None, catalog=None, schema=None, column=None):
|
||||||
"""Return a list with all columns"""
|
"""Return a list with all columns"""
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
l_catalog = l_schema = l_table = l_column = 0
|
l_catalog = l_schema = l_table = l_column = 0
|
||||||
|
|
||||||
if unicode in [type(x) for x in (table, catalog, schema,column)]:
|
if unicode in [type(x) for x in (table, catalog, schema,column)]:
|
||||||
@@ -2004,6 +2079,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def primaryKeys(self, table=None, catalog=None, schema=None):
|
def primaryKeys(self, table=None, catalog=None, schema=None):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
l_catalog = l_schema = l_table = 0
|
l_catalog = l_schema = l_table = 0
|
||||||
|
|
||||||
if unicode in [type(x) for x in (table, catalog, schema)]:
|
if unicode in [type(x) for x in (table, catalog, schema)]:
|
||||||
@@ -2044,6 +2122,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def foreignKeys(self, table=None, catalog=None, schema=None, foreignTable=None, foreignCatalog=None, foreignSchema=None):
|
def foreignKeys(self, table=None, catalog=None, schema=None, foreignTable=None, foreignCatalog=None, foreignSchema=None):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
l_catalog = l_schema = l_table = l_foreignTable = l_foreignCatalog = l_foreignSchema = 0
|
l_catalog = l_schema = l_table = l_foreignTable = l_foreignCatalog = l_foreignSchema = 0
|
||||||
|
|
||||||
if unicode in [type(x) for x in (table, catalog, schema,foreignTable,foreignCatalog,foreignSchema)]:
|
if unicode in [type(x) for x in (table, catalog, schema,foreignTable,foreignCatalog,foreignSchema)]:
|
||||||
@@ -2092,6 +2173,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def procedurecolumns(self, procedure=None, catalog=None, schema=None, column=None):
|
def procedurecolumns(self, procedure=None, catalog=None, schema=None, column=None):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
l_catalog = l_schema = l_procedure = l_column = 0
|
l_catalog = l_schema = l_procedure = l_column = 0
|
||||||
if unicode in [type(x) for x in (procedure, catalog, schema,column)]:
|
if unicode in [type(x) for x in (procedure, catalog, schema,column)]:
|
||||||
string_p = lambda x:wchar_pointer(UCS_buf(x))
|
string_p = lambda x:wchar_pointer(UCS_buf(x))
|
||||||
@@ -2132,6 +2216,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def procedures(self, procedure=None, catalog=None, schema=None):
|
def procedures(self, procedure=None, catalog=None, schema=None):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
l_catalog = l_schema = l_procedure = 0
|
l_catalog = l_schema = l_procedure = 0
|
||||||
|
|
||||||
if unicode in [type(x) for x in (procedure, catalog, schema)]:
|
if unicode in [type(x) for x in (procedure, catalog, schema)]:
|
||||||
@@ -2170,6 +2257,9 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def statistics(self, table, catalog=None, schema=None, unique=False, quick=True):
|
def statistics(self, table, catalog=None, schema=None, unique=False, quick=True):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
l_table = l_catalog = l_schema = 0
|
l_table = l_catalog = l_schema = 0
|
||||||
|
|
||||||
if unicode in [type(x) for x in (table, catalog, schema)]:
|
if unicode in [type(x) for x in (table, catalog, schema)]:
|
||||||
@@ -2217,15 +2307,23 @@ class Cursor:
|
|||||||
|
|
||||||
|
|
||||||
def commit(self):
|
def commit(self):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
self.connection.commit()
|
self.connection.commit()
|
||||||
|
|
||||||
def rollback(self):
|
def rollback(self):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
self.connection.rollback()
|
self.connection.rollback()
|
||||||
|
|
||||||
def setoutputsize(self, size, column = None):
|
def setoutputsize(self, size, column = None):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
self._outputsize[column] = size
|
self._outputsize[column] = size
|
||||||
|
|
||||||
def setinputsizes(self, sizes):
|
def setinputsizes(self, sizes):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
self._inputsizers = [size for size in sizes]
|
self._inputsizers = [size for size in sizes]
|
||||||
|
|
||||||
|
|
||||||
@@ -2234,35 +2332,31 @@ class Cursor:
|
|||||||
# ret = ODBC_API.SQLCloseCursor(self.stmt_h)
|
# ret = ODBC_API.SQLCloseCursor(self.stmt_h)
|
||||||
# check_success(self, ret)
|
# check_success(self, ret)
|
||||||
#
|
#
|
||||||
ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_CLOSE)
|
if self.connection.connected:
|
||||||
check_success(self, ret)
|
ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_CLOSE)
|
||||||
|
check_success(self, ret)
|
||||||
|
|
||||||
ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_UNBIND)
|
ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_UNBIND)
|
||||||
check_success(self, ret)
|
check_success(self, ret)
|
||||||
|
|
||||||
ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_RESET_PARAMS)
|
ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_RESET_PARAMS)
|
||||||
check_success(self, ret)
|
check_success(self, ret)
|
||||||
|
|
||||||
ret = ODBC_API.SQLFreeHandle(SQL_HANDLE_STMT, self.stmt_h)
|
ret = ODBC_API.SQLFreeHandle(SQL_HANDLE_STMT, self.stmt_h)
|
||||||
check_success(self, ret)
|
check_success(self, ret)
|
||||||
|
|
||||||
|
|
||||||
self.closed = True
|
self.closed = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if not self.closed:
|
if not self.closed:
|
||||||
#if DEBUG:print 'auto closing cursor: ',
|
self.close()
|
||||||
try:
|
|
||||||
self.close()
|
|
||||||
except:
|
|
||||||
#if DEBUG:print 'failed'
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
#if DEBUG:print 'succeed'
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __exit__(self, type, value, traceback):
|
def __exit__(self, type, value, traceback):
|
||||||
|
if not self.connection:
|
||||||
|
self.close()
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
self.rollback()
|
self.rollback()
|
||||||
else:
|
else:
|
||||||
@@ -2291,7 +2385,7 @@ class Connection:
|
|||||||
self.autocommit = autocommit
|
self.autocommit = autocommit
|
||||||
self.readonly = False
|
self.readonly = False
|
||||||
self.timeout = 0
|
self.timeout = 0
|
||||||
self._cursors = []
|
# self._cursors = []
|
||||||
for key, value in list(kargs.items()):
|
for key, value in list(kargs.items()):
|
||||||
connectString = connectString + key + '=' + value + ';'
|
connectString = connectString + key + '=' + value + ';'
|
||||||
self.connectString = connectString
|
self.connectString = connectString
|
||||||
@@ -2425,7 +2519,7 @@ class Connection:
|
|||||||
if not self.connected:
|
if not self.connected:
|
||||||
raise ProgrammingError('HY000','Attempt to use a closed connection.')
|
raise ProgrammingError('HY000','Attempt to use a closed connection.')
|
||||||
cur = Cursor(self, row_type_callable=row_type_callable)
|
cur = Cursor(self, row_type_callable=row_type_callable)
|
||||||
self._cursors.append(cur)
|
# self._cursors.append(cur)
|
||||||
return cur
|
return cur
|
||||||
|
|
||||||
def update_db_special_info(self):
|
def update_db_special_info(self):
|
||||||
@@ -2436,6 +2530,7 @@ class Connection:
|
|||||||
SQL_SS_TIME2,
|
SQL_SS_TIME2,
|
||||||
):
|
):
|
||||||
cur = Cursor(self)
|
cur = Cursor(self)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
info_tuple = cur.getTypeInfo(sql_type)
|
info_tuple = cur.getTypeInfo(sql_type)
|
||||||
if info_tuple is not None:
|
if info_tuple is not None:
|
||||||
@@ -2534,10 +2629,10 @@ class Connection:
|
|||||||
def close(self):
|
def close(self):
|
||||||
if not self.connected:
|
if not self.connected:
|
||||||
raise ProgrammingError('HY000','Attempt to close a closed connection.')
|
raise ProgrammingError('HY000','Attempt to close a closed connection.')
|
||||||
for cur in self._cursors:
|
# for cur in self._cursors:
|
||||||
if not cur is None:
|
# if not cur is None:
|
||||||
if not cur.closed:
|
# if not cur.closed:
|
||||||
cur.close()
|
# cur.close()
|
||||||
|
|
||||||
if self.connected:
|
if self.connected:
|
||||||
#if DEBUG:print 'disconnect'
|
#if DEBUG:print 'disconnect'
|
||||||
@@ -2680,4 +2775,18 @@ def dataSources():
|
|||||||
ctrl_err(SQL_HANDLE_ENV, shared_env_h, ret)
|
ctrl_err(SQL_HANDLE_ENV, shared_env_h, ret)
|
||||||
else:
|
else:
|
||||||
dsn_list[dsn.value] = desc.value
|
dsn_list[dsn.value] = desc.value
|
||||||
return dsn_list
|
return dsn_list
|
||||||
|
|
||||||
|
|
||||||
|
def monkey_patch_for_gevent():
|
||||||
|
import functools, gevent
|
||||||
|
apply_e = gevent.get_hub().threadpool.apply_e
|
||||||
|
def monkey_patch(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrap(*args, **kwargs):
|
||||||
|
#if DEBUG:print('%s called with %s %s' % (func, args, kwargs))
|
||||||
|
return apply_e(Exception, func, args, kwargs)
|
||||||
|
return wrap
|
||||||
|
for attr in dir(ODBC_API):
|
||||||
|
if attr.startswith('SQL') and hasattr(getattr(ODBC_API, attr), 'argtypes'):
|
||||||
|
setattr(ODBC_API, attr, monkey_patch(getattr(ODBC_API, attr)))
|
||||||
|
|||||||
Reference in New Issue
Block a user