/gluon/contrib/pypyodbc.py

https://code.google.com/p/web2py/ · Python · 2792 lines · 2095 code · 471 blank · 226 comment · 421 complexity · 9bd98244d0eb3b60f52aeb7a540fbbea MD5 · raw file

  1. # -*- coding: utf-8 -*-
  2. # PyPyODBC is develped from RealPyODBC 0.1 beta released in 2004 by Michele Petrazzo. Thanks Michele.
  3. # The MIT License (MIT)
  4. #
  5. # Copyright (c) 2014 Henry Zhou <jiangwen365@gmail.com> and PyPyODBC contributors
  6. # Copyright (c) 2004 Michele Petrazzo
  7. # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  8. # documentation files (the "Software"), to deal in the Software without restriction, including without limitation
  9. # the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
  10. # and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in all copies or substantial portions
  13. # of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  16. # THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  18. # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  19. # DEALINGS IN THE SOFTWARE.
  20. pooling = True
  21. apilevel = '2.0'
  22. paramstyle = 'qmark'
  23. threadsafety = 1
  24. version = '1.3.0'
  25. lowercase=True
  26. DEBUG = 0
  27. # Comment out all "if DEBUG:" statements like below for production
  28. #if DEBUG:print 'DEBUGGING'
  29. import sys, os, datetime, ctypes, threading
  30. from decimal import Decimal
  31. py_ver = sys.version[:3]
  32. py_v3 = py_ver >= '3.0'
  33. if py_v3:
  34. long = int
  35. unicode = str
  36. str_8b = bytes
  37. buffer = memoryview
  38. BYTE_1 = bytes('1','ascii')
  39. use_unicode = True
  40. else:
  41. str_8b = str
  42. BYTE_1 = '1'
  43. use_unicode = False
  44. if py_ver < '2.6':
  45. bytearray = str
  46. if not hasattr(ctypes, 'c_ssize_t'):
  47. if ctypes.sizeof(ctypes.c_uint) == ctypes.sizeof(ctypes.c_void_p):
  48. ctypes.c_ssize_t = ctypes.c_int
  49. elif ctypes.sizeof(ctypes.c_ulong) == ctypes.sizeof(ctypes.c_void_p):
  50. ctypes.c_ssize_t = ctypes.c_long
  51. elif ctypes.sizeof(ctypes.c_ulonglong) == ctypes.sizeof(ctypes.c_void_p):
  52. ctypes.c_ssize_t = ctypes.c_longlong
  53. lock = threading.Lock()
  54. shared_env_h = None
  55. SQLWCHAR_SIZE = ctypes.sizeof(ctypes.c_wchar)
  56. #determin the size of Py_UNICODE
  57. #sys.maxunicode > 65536 and 'UCS4' or 'UCS2'
  58. UNICODE_SIZE = sys.maxunicode > 65536 and 4 or 2
  59. # Define ODBC constants. They are widly used in ODBC documents and programs
  60. # They are defined in cpp header files: sql.h sqlext.h sqltypes.h sqlucode.h
  61. # and you can get these files from the mingw32-runtime_3.13-1_all.deb package
  62. SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC2, SQL_OV_ODBC3 = 200, 2, 3
  63. SQL_DRIVER_NOPROMPT = 0
  64. SQL_ATTR_CONNECTION_POOLING = 201; SQL_CP_ONE_PER_HENV = 2
  65. SQL_FETCH_NEXT, SQL_FETCH_FIRST, SQL_FETCH_LAST = 0x01, 0x02, 0x04
  66. SQL_NULL_HANDLE, SQL_HANDLE_ENV, SQL_HANDLE_DBC, SQL_HANDLE_STMT = 0, 1, 2, 3
  67. SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_ERROR = 0, 1, -1
  68. SQL_NO_DATA = 100; SQL_NO_TOTAL = -4
  69. SQL_ATTR_ACCESS_MODE = SQL_ACCESS_MODE = 101
  70. SQL_ATTR_AUTOCOMMIT = SQL_AUTOCOMMIT = 102
  71. SQL_MODE_DEFAULT = SQL_MODE_READ_WRITE = 0; SQL_MODE_READ_ONLY = 1
  72. SQL_AUTOCOMMIT_OFF, SQL_AUTOCOMMIT_ON = 0, 1
  73. SQL_IS_UINTEGER = -5
  74. SQL_ATTR_LOGIN_TIMEOUT = 103; SQL_ATTR_CONNECTION_TIMEOUT = 113
  75. SQL_COMMIT, SQL_ROLLBACK = 0, 1
  76. SQL_INDEX_UNIQUE,SQL_INDEX_ALL = 0,1
  77. SQL_QUICK,SQL_ENSURE = 0,1
  78. SQL_FETCH_NEXT = 1
  79. SQL_COLUMN_DISPLAY_SIZE = 6
  80. SQL_INVALID_HANDLE = -2
  81. SQL_NO_DATA_FOUND = 100; SQL_NULL_DATA = -1; SQL_NTS = -3
  82. SQL_HANDLE_DESCR = 4
  83. SQL_TABLE_NAMES = 3
  84. SQL_PARAM_INPUT = 1; SQL_PARAM_INPUT_OUTPUT = 2
  85. SQL_PARAM_TYPE_UNKNOWN = 0
  86. SQL_RESULT_COL = 3
  87. SQL_PARAM_OUTPUT = 4
  88. SQL_RETURN_VALUE = 5
  89. SQL_PARAM_TYPE_DEFAULT = SQL_PARAM_INPUT_OUTPUT
  90. SQL_RESET_PARAMS = 3
  91. SQL_UNBIND = 2
  92. SQL_CLOSE = 0
  93. # Below defines The constants for sqlgetinfo method, and their coresponding return types
  94. SQL_QUALIFIER_LOCATION = 114
  95. SQL_QUALIFIER_NAME_SEPARATOR = 41
  96. SQL_QUALIFIER_TERM = 42
  97. SQL_QUALIFIER_USAGE = 92
  98. SQL_OWNER_TERM = 39
  99. SQL_OWNER_USAGE = 91
  100. SQL_ACCESSIBLE_PROCEDURES = 20
  101. SQL_ACCESSIBLE_TABLES = 19
  102. SQL_ACTIVE_ENVIRONMENTS = 116
  103. SQL_AGGREGATE_FUNCTIONS = 169
  104. SQL_ALTER_DOMAIN = 117
  105. SQL_ALTER_TABLE = 86
  106. SQL_ASYNC_MODE = 10021
  107. SQL_BATCH_ROW_COUNT = 120
  108. SQL_BATCH_SUPPORT = 121
  109. SQL_BOOKMARK_PERSISTENCE = 82
  110. SQL_CATALOG_LOCATION = SQL_QUALIFIER_LOCATION
  111. SQL_CATALOG_NAME = 10003
  112. SQL_CATALOG_NAME_SEPARATOR = SQL_QUALIFIER_NAME_SEPARATOR
  113. SQL_CATALOG_TERM = SQL_QUALIFIER_TERM
  114. SQL_CATALOG_USAGE = SQL_QUALIFIER_USAGE
  115. SQL_COLLATION_SEQ = 10004
  116. SQL_COLUMN_ALIAS = 87
  117. SQL_CONCAT_NULL_BEHAVIOR = 22
  118. SQL_CONVERT_FUNCTIONS = 48
  119. SQL_CONVERT_VARCHAR = 70
  120. SQL_CORRELATION_NAME = 74
  121. SQL_CREATE_ASSERTION = 127
  122. SQL_CREATE_CHARACTER_SET = 128
  123. SQL_CREATE_COLLATION = 129
  124. SQL_CREATE_DOMAIN = 130
  125. SQL_CREATE_SCHEMA = 131
  126. SQL_CREATE_TABLE = 132
  127. SQL_CREATE_TRANSLATION = 133
  128. SQL_CREATE_VIEW = 134
  129. SQL_CURSOR_COMMIT_BEHAVIOR = 23
  130. SQL_CURSOR_ROLLBACK_BEHAVIOR = 24
  131. SQL_DATABASE_NAME = 16
  132. SQL_DATA_SOURCE_NAME = 2
  133. SQL_DATA_SOURCE_READ_ONLY = 25
  134. SQL_DATETIME_LITERALS = 119
  135. SQL_DBMS_NAME = 17
  136. SQL_DBMS_VER = 18
  137. SQL_DDL_INDEX = 170
  138. SQL_DEFAULT_TXN_ISOLATION = 26
  139. SQL_DESCRIBE_PARAMETER = 10002
  140. SQL_DM_VER = 171
  141. SQL_DRIVER_NAME = 6
  142. SQL_DRIVER_ODBC_VER = 77
  143. SQL_DRIVER_VER = 7
  144. SQL_DROP_ASSERTION = 136
  145. SQL_DROP_CHARACTER_SET = 137
  146. SQL_DROP_COLLATION = 138
  147. SQL_DROP_DOMAIN = 139
  148. SQL_DROP_SCHEMA = 140
  149. SQL_DROP_TABLE = 141
  150. SQL_DROP_TRANSLATION = 142
  151. SQL_DROP_VIEW = 143
  152. SQL_DYNAMIC_CURSOR_ATTRIBUTES1 = 144
  153. SQL_DYNAMIC_CURSOR_ATTRIBUTES2 = 145
  154. SQL_EXPRESSIONS_IN_ORDERBY = 27
  155. SQL_FILE_USAGE = 84
  156. SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1 = 146
  157. SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2 = 147
  158. SQL_GETDATA_EXTENSIONS = 81
  159. SQL_GROUP_BY = 88
  160. SQL_IDENTIFIER_CASE = 28
  161. SQL_IDENTIFIER_QUOTE_CHAR = 29
  162. SQL_INDEX_KEYWORDS = 148
  163. SQL_INFO_SCHEMA_VIEWS = 149
  164. SQL_INSERT_STATEMENT = 172
  165. SQL_INTEGRITY = 73
  166. SQL_KEYSET_CURSOR_ATTRIBUTES1 = 150
  167. SQL_KEYSET_CURSOR_ATTRIBUTES2 = 151
  168. SQL_KEYWORDS = 89
  169. SQL_LIKE_ESCAPE_CLAUSE = 113
  170. SQL_MAX_ASYNC_CONCURRENT_STATEMENTS = 10022
  171. SQL_MAX_BINARY_LITERAL_LEN = 112
  172. SQL_MAX_CATALOG_NAME_LEN = 34
  173. SQL_MAX_CHAR_LITERAL_LEN = 108
  174. SQL_MAX_COLUMNS_IN_GROUP_BY = 97
  175. SQL_MAX_COLUMNS_IN_INDEX = 98
  176. SQL_MAX_COLUMNS_IN_ORDER_BY = 99
  177. SQL_MAX_COLUMNS_IN_SELECT = 100
  178. SQL_MAX_COLUMNS_IN_TABLE = 101
  179. SQL_MAX_COLUMN_NAME_LEN = 30
  180. SQL_MAX_CONCURRENT_ACTIVITIES = 1
  181. SQL_MAX_CURSOR_NAME_LEN = 31
  182. SQL_MAX_DRIVER_CONNECTIONS = 0
  183. SQL_MAX_IDENTIFIER_LEN = 10005
  184. SQL_MAX_INDEX_SIZE = 102
  185. SQL_MAX_PROCEDURE_NAME_LEN = 33
  186. SQL_MAX_ROW_SIZE = 104
  187. SQL_MAX_ROW_SIZE_INCLUDES_LONG = 103
  188. SQL_MAX_SCHEMA_NAME_LEN = 32
  189. SQL_MAX_STATEMENT_LEN = 105
  190. SQL_MAX_TABLES_IN_SELECT = 106
  191. SQL_MAX_TABLE_NAME_LEN = 35
  192. SQL_MAX_USER_NAME_LEN = 107
  193. SQL_MULTIPLE_ACTIVE_TXN = 37
  194. SQL_MULT_RESULT_SETS = 36
  195. SQL_NEED_LONG_DATA_LEN = 111
  196. SQL_NON_NULLABLE_COLUMNS = 75
  197. SQL_NULL_COLLATION = 85
  198. SQL_NUMERIC_FUNCTIONS = 49
  199. SQL_ODBC_INTERFACE_CONFORMANCE = 152
  200. SQL_ODBC_VER = 10
  201. SQL_OJ_CAPABILITIES = 65003
  202. SQL_ORDER_BY_COLUMNS_IN_SELECT = 90
  203. SQL_PARAM_ARRAY_ROW_COUNTS = 153
  204. SQL_PARAM_ARRAY_SELECTS = 154
  205. SQL_PROCEDURES = 21
  206. SQL_PROCEDURE_TERM = 40
  207. SQL_QUOTED_IDENTIFIER_CASE = 93
  208. SQL_ROW_UPDATES = 11
  209. SQL_SCHEMA_TERM = SQL_OWNER_TERM
  210. SQL_SCHEMA_USAGE = SQL_OWNER_USAGE
  211. SQL_SCROLL_OPTIONS = 44
  212. SQL_SEARCH_PATTERN_ESCAPE = 14
  213. SQL_SERVER_NAME = 13
  214. SQL_SPECIAL_CHARACTERS = 94
  215. SQL_SQL92_DATETIME_FUNCTIONS = 155
  216. SQL_SQL92_FOREIGN_KEY_DELETE_RULE = 156
  217. SQL_SQL92_FOREIGN_KEY_UPDATE_RULE = 157
  218. SQL_SQL92_GRANT = 158
  219. SQL_SQL92_NUMERIC_VALUE_FUNCTIONS = 159
  220. SQL_SQL92_PREDICATES = 160
  221. SQL_SQL92_RELATIONAL_JOIN_OPERATORS = 161
  222. SQL_SQL92_REVOKE = 162
  223. SQL_SQL92_ROW_VALUE_CONSTRUCTOR = 163
  224. SQL_SQL92_STRING_FUNCTIONS = 164
  225. SQL_SQL92_VALUE_EXPRESSIONS = 165
  226. SQL_SQL_CONFORMANCE = 118
  227. SQL_STANDARD_CLI_CONFORMANCE = 166
  228. SQL_STATIC_CURSOR_ATTRIBUTES1 = 167
  229. SQL_STATIC_CURSOR_ATTRIBUTES2 = 168
  230. SQL_STRING_FUNCTIONS = 50
  231. SQL_SUBQUERIES = 95
  232. SQL_SYSTEM_FUNCTIONS = 51
  233. SQL_TABLE_TERM = 45
  234. SQL_TIMEDATE_ADD_INTERVALS = 109
  235. SQL_TIMEDATE_DIFF_INTERVALS = 110
  236. SQL_TIMEDATE_FUNCTIONS = 52
  237. SQL_TXN_CAPABLE = 46
  238. SQL_TXN_ISOLATION_OPTION = 72
  239. SQL_UNION = 96
  240. SQL_USER_NAME = 47
  241. SQL_XOPEN_CLI_YEAR = 10000
  242. aInfoTypes = {
  243. SQL_ACCESSIBLE_PROCEDURES : 'GI_YESNO',SQL_ACCESSIBLE_TABLES : 'GI_YESNO',SQL_ACTIVE_ENVIRONMENTS : 'GI_USMALLINT',
  244. SQL_AGGREGATE_FUNCTIONS : 'GI_UINTEGER',SQL_ALTER_DOMAIN : 'GI_UINTEGER',
  245. SQL_ALTER_TABLE : 'GI_UINTEGER',SQL_ASYNC_MODE : 'GI_UINTEGER',SQL_BATCH_ROW_COUNT : 'GI_UINTEGER',
  246. SQL_BATCH_SUPPORT : 'GI_UINTEGER',SQL_BOOKMARK_PERSISTENCE : 'GI_UINTEGER',SQL_CATALOG_LOCATION : 'GI_USMALLINT',
  247. SQL_CATALOG_NAME : 'GI_YESNO',SQL_CATALOG_NAME_SEPARATOR : 'GI_STRING',SQL_CATALOG_TERM : 'GI_STRING',
  248. SQL_CATALOG_USAGE : 'GI_UINTEGER',SQL_COLLATION_SEQ : 'GI_STRING',SQL_COLUMN_ALIAS : 'GI_YESNO',
  249. SQL_CONCAT_NULL_BEHAVIOR : 'GI_USMALLINT',SQL_CONVERT_FUNCTIONS : 'GI_UINTEGER',SQL_CONVERT_VARCHAR : 'GI_UINTEGER',
  250. SQL_CORRELATION_NAME : 'GI_USMALLINT',SQL_CREATE_ASSERTION : 'GI_UINTEGER',SQL_CREATE_CHARACTER_SET : 'GI_UINTEGER',
  251. SQL_CREATE_COLLATION : 'GI_UINTEGER',SQL_CREATE_DOMAIN : 'GI_UINTEGER',SQL_CREATE_SCHEMA : 'GI_UINTEGER',
  252. SQL_CREATE_TABLE : 'GI_UINTEGER',SQL_CREATE_TRANSLATION : 'GI_UINTEGER',SQL_CREATE_VIEW : 'GI_UINTEGER',
  253. SQL_CURSOR_COMMIT_BEHAVIOR : 'GI_USMALLINT',SQL_CURSOR_ROLLBACK_BEHAVIOR : 'GI_USMALLINT',SQL_DATABASE_NAME : 'GI_STRING',
  254. SQL_DATA_SOURCE_NAME : 'GI_STRING',SQL_DATA_SOURCE_READ_ONLY : 'GI_YESNO',SQL_DATETIME_LITERALS : 'GI_UINTEGER',
  255. SQL_DBMS_NAME : 'GI_STRING',SQL_DBMS_VER : 'GI_STRING',SQL_DDL_INDEX : 'GI_UINTEGER',
  256. SQL_DEFAULT_TXN_ISOLATION : 'GI_UINTEGER',SQL_DESCRIBE_PARAMETER : 'GI_YESNO',SQL_DM_VER : 'GI_STRING',
  257. SQL_DRIVER_NAME : 'GI_STRING',SQL_DRIVER_ODBC_VER : 'GI_STRING',SQL_DRIVER_VER : 'GI_STRING',SQL_DROP_ASSERTION : 'GI_UINTEGER',
  258. SQL_DROP_CHARACTER_SET : 'GI_UINTEGER', SQL_DROP_COLLATION : 'GI_UINTEGER',SQL_DROP_DOMAIN : 'GI_UINTEGER',
  259. SQL_DROP_SCHEMA : 'GI_UINTEGER',SQL_DROP_TABLE : 'GI_UINTEGER',SQL_DROP_TRANSLATION : 'GI_UINTEGER',
  260. SQL_DROP_VIEW : 'GI_UINTEGER',SQL_DYNAMIC_CURSOR_ATTRIBUTES1 : 'GI_UINTEGER',SQL_DYNAMIC_CURSOR_ATTRIBUTES2 : 'GI_UINTEGER',
  261. SQL_EXPRESSIONS_IN_ORDERBY : 'GI_YESNO',SQL_FILE_USAGE : 'GI_USMALLINT',
  262. SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1 : 'GI_UINTEGER',SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2 : 'GI_UINTEGER',
  263. SQL_GETDATA_EXTENSIONS : 'GI_UINTEGER',SQL_GROUP_BY : 'GI_USMALLINT',SQL_IDENTIFIER_CASE : 'GI_USMALLINT',
  264. SQL_IDENTIFIER_QUOTE_CHAR : 'GI_STRING',SQL_INDEX_KEYWORDS : 'GI_UINTEGER',SQL_INFO_SCHEMA_VIEWS : 'GI_UINTEGER',
  265. SQL_INSERT_STATEMENT : 'GI_UINTEGER',SQL_INTEGRITY : 'GI_YESNO',SQL_KEYSET_CURSOR_ATTRIBUTES1 : 'GI_UINTEGER',
  266. SQL_KEYSET_CURSOR_ATTRIBUTES2 : 'GI_UINTEGER',SQL_KEYWORDS : 'GI_STRING',
  267. SQL_LIKE_ESCAPE_CLAUSE : 'GI_YESNO',SQL_MAX_ASYNC_CONCURRENT_STATEMENTS : 'GI_UINTEGER',
  268. SQL_MAX_BINARY_LITERAL_LEN : 'GI_UINTEGER',SQL_MAX_CATALOG_NAME_LEN : 'GI_USMALLINT',
  269. SQL_MAX_CHAR_LITERAL_LEN : 'GI_UINTEGER',SQL_MAX_COLUMNS_IN_GROUP_BY : 'GI_USMALLINT',
  270. SQL_MAX_COLUMNS_IN_INDEX : 'GI_USMALLINT',SQL_MAX_COLUMNS_IN_ORDER_BY : 'GI_USMALLINT',
  271. SQL_MAX_COLUMNS_IN_SELECT : 'GI_USMALLINT',SQL_MAX_COLUMNS_IN_TABLE : 'GI_USMALLINT',
  272. SQL_MAX_COLUMN_NAME_LEN : 'GI_USMALLINT',SQL_MAX_CONCURRENT_ACTIVITIES : 'GI_USMALLINT',
  273. SQL_MAX_CURSOR_NAME_LEN : 'GI_USMALLINT',SQL_MAX_DRIVER_CONNECTIONS : 'GI_USMALLINT',
  274. SQL_MAX_IDENTIFIER_LEN : 'GI_USMALLINT',SQL_MAX_INDEX_SIZE : 'GI_UINTEGER',
  275. SQL_MAX_PROCEDURE_NAME_LEN : 'GI_USMALLINT',SQL_MAX_ROW_SIZE : 'GI_UINTEGER',
  276. SQL_MAX_ROW_SIZE_INCLUDES_LONG : 'GI_YESNO',SQL_MAX_SCHEMA_NAME_LEN : 'GI_USMALLINT',
  277. SQL_MAX_STATEMENT_LEN : 'GI_UINTEGER',SQL_MAX_TABLES_IN_SELECT : 'GI_USMALLINT',
  278. SQL_MAX_TABLE_NAME_LEN : 'GI_USMALLINT',SQL_MAX_USER_NAME_LEN : 'GI_USMALLINT',
  279. SQL_MULTIPLE_ACTIVE_TXN : 'GI_YESNO',SQL_MULT_RESULT_SETS : 'GI_YESNO',
  280. SQL_NEED_LONG_DATA_LEN : 'GI_YESNO',SQL_NON_NULLABLE_COLUMNS : 'GI_USMALLINT',
  281. SQL_NULL_COLLATION : 'GI_USMALLINT',SQL_NUMERIC_FUNCTIONS : 'GI_UINTEGER',
  282. SQL_ODBC_INTERFACE_CONFORMANCE : 'GI_UINTEGER',SQL_ODBC_VER : 'GI_STRING',SQL_OJ_CAPABILITIES : 'GI_UINTEGER',
  283. SQL_ORDER_BY_COLUMNS_IN_SELECT : 'GI_YESNO',SQL_PARAM_ARRAY_ROW_COUNTS : 'GI_UINTEGER',
  284. SQL_PARAM_ARRAY_SELECTS : 'GI_UINTEGER',SQL_PROCEDURES : 'GI_YESNO',SQL_PROCEDURE_TERM : 'GI_STRING',
  285. SQL_QUOTED_IDENTIFIER_CASE : 'GI_USMALLINT',SQL_ROW_UPDATES : 'GI_YESNO',SQL_SCHEMA_TERM : 'GI_STRING',
  286. SQL_SCHEMA_USAGE : 'GI_UINTEGER',SQL_SCROLL_OPTIONS : 'GI_UINTEGER',SQL_SEARCH_PATTERN_ESCAPE : 'GI_STRING',
  287. SQL_SERVER_NAME : 'GI_STRING',SQL_SPECIAL_CHARACTERS : 'GI_STRING',SQL_SQL92_DATETIME_FUNCTIONS : 'GI_UINTEGER',
  288. SQL_SQL92_FOREIGN_KEY_DELETE_RULE : 'GI_UINTEGER',SQL_SQL92_FOREIGN_KEY_UPDATE_RULE : 'GI_UINTEGER',
  289. SQL_SQL92_GRANT : 'GI_UINTEGER',SQL_SQL92_NUMERIC_VALUE_FUNCTIONS : 'GI_UINTEGER',
  290. SQL_SQL92_PREDICATES : 'GI_UINTEGER',SQL_SQL92_RELATIONAL_JOIN_OPERATORS : 'GI_UINTEGER',
  291. SQL_SQL92_REVOKE : 'GI_UINTEGER',SQL_SQL92_ROW_VALUE_CONSTRUCTOR : 'GI_UINTEGER',
  292. SQL_SQL92_STRING_FUNCTIONS : 'GI_UINTEGER',SQL_SQL92_VALUE_EXPRESSIONS : 'GI_UINTEGER',
  293. SQL_SQL_CONFORMANCE : 'GI_UINTEGER',SQL_STANDARD_CLI_CONFORMANCE : 'GI_UINTEGER',
  294. SQL_STATIC_CURSOR_ATTRIBUTES1 : 'GI_UINTEGER',SQL_STATIC_CURSOR_ATTRIBUTES2 : 'GI_UINTEGER',
  295. SQL_STRING_FUNCTIONS : 'GI_UINTEGER',SQL_SUBQUERIES : 'GI_UINTEGER',
  296. SQL_SYSTEM_FUNCTIONS : 'GI_UINTEGER',SQL_TABLE_TERM : 'GI_STRING',SQL_TIMEDATE_ADD_INTERVALS : 'GI_UINTEGER',
  297. SQL_TIMEDATE_DIFF_INTERVALS : 'GI_UINTEGER',SQL_TIMEDATE_FUNCTIONS : 'GI_UINTEGER',
  298. SQL_TXN_CAPABLE : 'GI_USMALLINT',SQL_TXN_ISOLATION_OPTION : 'GI_UINTEGER',
  299. SQL_UNION : 'GI_UINTEGER',SQL_USER_NAME : 'GI_STRING',SQL_XOPEN_CLI_YEAR : 'GI_STRING',
  300. }
  301. #Definations for types
  302. BINARY = bytearray
  303. Binary = bytearray
  304. DATETIME = datetime.datetime
  305. Date = datetime.date
  306. Time = datetime.time
  307. Timestamp = datetime.datetime
  308. STRING = str
  309. NUMBER = float
  310. ROWID = int
  311. DateFromTicks = datetime.date.fromtimestamp
  312. TimeFromTicks = lambda x: datetime.datetime.fromtimestamp(x).time()
  313. TimestampFromTicks = datetime.datetime.fromtimestamp
  314. #Define exceptions
  315. class OdbcNoLibrary(Exception):
  316. def __init__(self, value):
  317. self.value = value
  318. def __str__(self):
  319. return repr(self.value)
  320. class OdbcLibraryError(Exception):
  321. def __init__(self, value):
  322. self.value = value
  323. def __str__(self):
  324. return repr(self.value)
  325. class OdbcInvalidHandle(Exception):
  326. def __init__(self, value):
  327. self.value = value
  328. def __str__(self):
  329. return repr(self.value)
  330. class OdbcGenericError(Exception):
  331. def __init__(self, value):
  332. self.value = value
  333. def __str__(self):
  334. return repr(self.value)
  335. class Warning(Exception):
  336. def __init__(self, error_code, error_desc):
  337. self.value = (error_code, error_desc)
  338. self.args = (error_code, error_desc)
  339. class Error(Exception):
  340. def __init__(self, error_code, error_desc):
  341. self.value = (error_code, error_desc)
  342. self.args = (error_code, error_desc)
  343. class InterfaceError(Error):
  344. def __init__(self, error_code, error_desc):
  345. self.value = (error_code, error_desc)
  346. self.args = (error_code, error_desc)
  347. class DatabaseError(Error):
  348. def __init__(self, error_code, error_desc):
  349. self.value = (error_code, error_desc)
  350. self.args = (error_code, error_desc)
  351. class InternalError(DatabaseError):
  352. def __init__(self, error_code, error_desc):
  353. self.value = (error_code, error_desc)
  354. self.args = (error_code, error_desc)
  355. class ProgrammingError(DatabaseError):
  356. def __init__(self, error_code, error_desc):
  357. self.value = (error_code, error_desc)
  358. self.args = (error_code, error_desc)
  359. class DataError(DatabaseError):
  360. def __init__(self, error_code, error_desc):
  361. self.value = (error_code, error_desc)
  362. self.args = (error_code, error_desc)
  363. class IntegrityError(DatabaseError):
  364. def __init__(self, error_code, error_desc):
  365. self.value = (error_code, error_desc)
  366. self.args = (error_code, error_desc)
  367. class NotSupportedError(Error):
  368. def __init__(self, error_code, error_desc):
  369. self.value = (error_code, error_desc)
  370. self.args = (error_code, error_desc)
  371. class OperationalError(DatabaseError):
  372. def __init__(self, error_code, error_desc):
  373. self.value = (error_code, error_desc)
  374. self.args = (error_code, error_desc)
  375. ############################################################################
  376. #
  377. # Find the ODBC library on the platform and connect to it using ctypes
  378. #
  379. ############################################################################
  380. # Get the References of the platform's ODBC functions via ctypes
  381. odbc_decoding = 'utf_16'
  382. odbc_encoding = 'utf_16_le'
  383. ucs_length = 2
  384. if sys.platform in ('win32','cli'):
  385. ODBC_API = ctypes.windll.odbc32
  386. # On Windows, the size of SQLWCHAR is hardcoded to 2-bytes.
  387. SQLWCHAR_SIZE = ctypes.sizeof(ctypes.c_ushort)
  388. else:
  389. # Set load the library on linux
  390. try:
  391. # First try direct loading libodbc.so
  392. ODBC_API = ctypes.cdll.LoadLibrary('libodbc.so')
  393. except:
  394. # If direct loading libodbc.so failed
  395. # We try finding the libodbc.so by using find_library
  396. from ctypes.util import find_library
  397. library = find_library('odbc')
  398. if library is None:
  399. # If find_library still can not find the library
  400. # we try finding it manually from where libodbc.so usually appears
  401. lib_paths = ("/usr/lib/libodbc.so","/usr/lib/i386-linux-gnu/libodbc.so","/usr/lib/x86_64-linux-gnu/libodbc.so","/usr/lib/libiodbc.dylib")
  402. lib_paths = [path for path in lib_paths if os.path.exists(path)]
  403. if len(lib_paths) == 0 :
  404. raise OdbcNoLibrary('ODBC Library is not found. Is LD_LIBRARY_PATH set?')
  405. else:
  406. library = lib_paths[0]
  407. # Then we try loading the found libodbc.so again
  408. try:
  409. ODBC_API = ctypes.cdll.LoadLibrary(library)
  410. except:
  411. # If still fail loading, abort.
  412. raise OdbcLibraryError('Error while loading ' + library)
  413. # only iODBC uses utf-32 / UCS4 encoding data, others normally use utf-16 / UCS2
  414. # So we set those for handling.
  415. if 'libiodbc.dylib' in library:
  416. odbc_decoding = 'utf_32'
  417. odbc_encoding = 'utf_32_le'
  418. ucs_length = 4
  419. # unixODBC defaults to 2-bytes SQLWCHAR, unless "-DSQL_WCHART_CONVERT" was
  420. # added to CFLAGS, in which case it will be the size of wchar_t.
  421. # Note that using 4-bytes SQLWCHAR will break most ODBC drivers, as driver
  422. # development mostly targets the Windows platform.
  423. if py_v3:
  424. from subprocess import getstatusoutput
  425. else:
  426. from commands import getstatusoutput
  427. status, output = getstatusoutput('odbc_config --cflags')
  428. if status == 0 and 'SQL_WCHART_CONVERT' in output:
  429. SQLWCHAR_SIZE = ctypes.sizeof(ctypes.c_wchar)
  430. else:
  431. SQLWCHAR_SIZE = ctypes.sizeof(ctypes.c_ushort)
  432. create_buffer_u = ctypes.create_unicode_buffer
  433. create_buffer = ctypes.create_string_buffer
  434. wchar_pointer = ctypes.c_wchar_p
  435. UCS_buf = lambda s: s
  436. def UCS_dec(buffer):
  437. i = 0
  438. uchars = []
  439. while True:
  440. uchar = buffer.raw[i:i + ucs_length].decode(odbc_decoding)
  441. if uchar == unicode('\x00'):
  442. break
  443. uchars.append(uchar)
  444. i += ucs_length
  445. return ''.join(uchars)
  446. from_buffer_u = lambda buffer: buffer.value
  447. # This is the common case on Linux, which uses wide Python build together with
  448. # the default unixODBC without the "-DSQL_WCHART_CONVERT" CFLAGS.
  449. if sys.platform not in ('win32','cli'):
  450. if UNICODE_SIZE >= SQLWCHAR_SIZE:
  451. # We can only use unicode buffer if the size of wchar_t (UNICODE_SIZE) is
  452. # the same as the size expected by the driver manager (SQLWCHAR_SIZE).
  453. create_buffer_u = create_buffer
  454. wchar_pointer = ctypes.c_char_p
  455. def UCS_buf(s):
  456. return s.encode(odbc_encoding)
  457. from_buffer_u = UCS_dec
  458. # Exoteric case, don't really care.
  459. elif UNICODE_SIZE < SQLWCHAR_SIZE:
  460. raise OdbcLibraryError('Using narrow Python build with ODBC library '
  461. 'expecting wide unicode is not supported.')
  462. ############################################################
  463. # Database value to Python data type mappings
  464. SQL_TYPE_NULL = 0
  465. SQL_DECIMAL = 3
  466. SQL_FLOAT = 6
  467. SQL_DATE = 9
  468. SQL_TIME = 10
  469. SQL_TIMESTAMP = 11
  470. SQL_VARCHAR = 12
  471. SQL_LONGVARCHAR = -1
  472. SQL_VARBINARY = -3
  473. SQL_LONGVARBINARY = -4
  474. SQL_BIGINT = -5
  475. SQL_WVARCHAR = -9
  476. SQL_WLONGVARCHAR = -10
  477. SQL_ALL_TYPES = 0
  478. SQL_SIGNED_OFFSET = -20
  479. SQL_SS_VARIANT = -150
  480. SQL_SS_UDT = -151
  481. SQL_SS_XML = -152
  482. SQL_SS_TIME2 = -154
  483. SQL_C_CHAR = SQL_CHAR = 1
  484. SQL_C_NUMERIC = SQL_NUMERIC = 2
  485. SQL_C_LONG = SQL_INTEGER = 4
  486. SQL_C_SLONG = SQL_C_LONG + SQL_SIGNED_OFFSET
  487. SQL_C_SHORT = SQL_SMALLINT = 5
  488. SQL_C_FLOAT = SQL_REAL = 7
  489. SQL_C_DOUBLE = SQL_DOUBLE = 8
  490. SQL_C_TYPE_DATE = SQL_TYPE_DATE = 91
  491. SQL_C_TYPE_TIME = SQL_TYPE_TIME = 92
  492. SQL_C_BINARY = SQL_BINARY = -2
  493. SQL_C_SBIGINT = SQL_BIGINT + SQL_SIGNED_OFFSET
  494. SQL_C_TINYINT = SQL_TINYINT = -6
  495. SQL_C_BIT = SQL_BIT = -7
  496. SQL_C_WCHAR = SQL_WCHAR = -8
  497. SQL_C_GUID = SQL_GUID = -11
  498. SQL_C_TYPE_TIMESTAMP = SQL_TYPE_TIMESTAMP = 93
  499. SQL_C_DEFAULT = 99
  500. SQL_DESC_DISPLAY_SIZE = SQL_COLUMN_DISPLAY_SIZE
  501. def dttm_cvt(x):
  502. if py_v3:
  503. x = x.decode('ascii')
  504. if x == '': return None
  505. else: return datetime.datetime(int(x[0:4]),int(x[5:7]),int(x[8:10]),int(x[10:13]),int(x[14:16]),int(x[17:19]),int(x[20:].ljust(6,'0')))
  506. def tm_cvt(x):
  507. if py_v3:
  508. x = x.decode('ascii')
  509. if x == '': return None
  510. else: return datetime.time(int(x[0:2]),int(x[3:5]),int(x[6:8]),int(x[9:].ljust(6,'0')))
  511. def dt_cvt(x):
  512. if py_v3:
  513. x = x.decode('ascii')
  514. if x == '': return None
  515. else: return datetime.date(int(x[0:4]),int(x[5:7]),int(x[8:10]))
  516. def Decimal_cvt(x):
  517. if py_v3:
  518. x = x.decode('ascii')
  519. return Decimal(x)
  520. bytearray_cvt = bytearray
  521. if sys.platform == 'cli':
  522. bytearray_cvt = lambda x: bytearray(buffer(x))
  523. # Below Datatype mappings referenced the document at
  524. # http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.sdk_12.5.1.aseodbc/html/aseodbc/CACFDIGH.htm
  525. SQL_data_type_dict = { \
  526. #SQL Data TYPE 0.Python Data Type 1.Default Output Converter 2.Buffer Type 3.Buffer Allocator 4.Default Size 5.Variable Length
  527. SQL_TYPE_NULL : (None, lambda x: None, SQL_C_CHAR, create_buffer, 2 , False ),
  528. SQL_CHAR : (str, lambda x: x, SQL_C_CHAR, create_buffer, 2048 , False ),
  529. SQL_NUMERIC : (Decimal, Decimal_cvt, SQL_C_CHAR, create_buffer, 150 , False ),
  530. SQL_DECIMAL : (Decimal, Decimal_cvt, SQL_C_CHAR, create_buffer, 150 , False ),
  531. SQL_INTEGER : (int, int, SQL_C_CHAR, create_buffer, 150 , False ),
  532. SQL_SMALLINT : (int, int, SQL_C_CHAR, create_buffer, 150 , False ),
  533. SQL_FLOAT : (float, float, SQL_C_CHAR, create_buffer, 150 , False ),
  534. SQL_REAL : (float, float, SQL_C_CHAR, create_buffer, 150 , False ),
  535. SQL_DOUBLE : (float, float, SQL_C_CHAR, create_buffer, 200 , False ),
  536. SQL_DATE : (datetime.date, dt_cvt, SQL_C_CHAR, create_buffer, 30 , False ),
  537. SQL_TIME : (datetime.time, tm_cvt, SQL_C_CHAR, create_buffer, 20 , False ),
  538. SQL_SS_TIME2 : (datetime.time, tm_cvt, SQL_C_CHAR, create_buffer, 20 , False ),
  539. SQL_TIMESTAMP : (datetime.datetime, dttm_cvt, SQL_C_CHAR, create_buffer, 30 , False ),
  540. SQL_VARCHAR : (str, lambda x: x, SQL_C_CHAR, create_buffer, 2048 , False ),
  541. SQL_LONGVARCHAR : (str, lambda x: x, SQL_C_CHAR, create_buffer, 20500 , True ),
  542. SQL_BINARY : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 5120 , True ),
  543. SQL_VARBINARY : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 5120 , True ),
  544. SQL_LONGVARBINARY : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 20500 , True ),
  545. SQL_BIGINT : (long, long, SQL_C_CHAR, create_buffer, 150 , False ),
  546. SQL_TINYINT : (int, int, SQL_C_CHAR, create_buffer, 150 , False ),
  547. SQL_BIT : (bool, lambda x:x == BYTE_1, SQL_C_CHAR, create_buffer, 2 , False ),
  548. SQL_WCHAR : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 2048 , False ),
  549. SQL_WVARCHAR : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 2048 , False ),
  550. SQL_GUID : (str, str, SQL_C_CHAR, create_buffer, 2048 , False ),
  551. SQL_WLONGVARCHAR : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 20500 , True ),
  552. SQL_TYPE_DATE : (datetime.date, dt_cvt, SQL_C_CHAR, create_buffer, 30 , False ),
  553. SQL_TYPE_TIME : (datetime.time, tm_cvt, SQL_C_CHAR, create_buffer, 20 , False ),
  554. SQL_TYPE_TIMESTAMP : (datetime.datetime, dttm_cvt, SQL_C_CHAR, create_buffer, 30 , False ),
  555. SQL_SS_VARIANT : (str, lambda x: x, SQL_C_CHAR, create_buffer, 2048 , True ),
  556. SQL_SS_XML : (unicode, lambda x: x, SQL_C_WCHAR, create_buffer_u, 20500 , True ),
  557. SQL_SS_UDT : (bytearray, bytearray_cvt, SQL_C_BINARY, create_buffer, 5120 , True ),
  558. }
  559. """
  560. Types mapping, applicable for 32-bit and 64-bit Linux / Windows / Mac OS X.
  561. SQLPointer -> ctypes.c_void_p
  562. SQLCHAR * -> ctypes.c_char_p
  563. SQLWCHAR * -> ctypes.c_wchar_p on Windows, ctypes.c_char_p with unixODBC
  564. SQLINT -> ctypes.c_int
  565. SQLSMALLINT -> ctypes.c_short
  566. SQMUSMALLINT -> ctypes.c_ushort
  567. SQLLEN -> ctypes.c_ssize_t
  568. SQLULEN -> ctypes.c_size_t
  569. SQLRETURN -> ctypes.c_short
  570. """
  571. # Define the python return type for ODBC functions with ret result.
  572. funcs_with_ret = [
  573. "SQLAllocHandle",
  574. "SQLBindParameter",
  575. "SQLBindCol",
  576. "SQLCloseCursor",
  577. "SQLColAttribute",
  578. "SQLColumns",
  579. "SQLColumnsW",
  580. "SQLConnect",
  581. "SQLConnectW",
  582. "SQLDataSources",
  583. "SQLDataSourcesW",
  584. "SQLDescribeCol",
  585. "SQLDescribeColW",
  586. "SQLDescribeParam",
  587. "SQLDisconnect",
  588. "SQLDriverConnect",
  589. "SQLDriverConnectW",
  590. "SQLDrivers",
  591. "SQLDriversW",
  592. "SQLEndTran",
  593. "SQLExecDirect",
  594. "SQLExecDirectW",
  595. "SQLExecute",
  596. "SQLFetch",
  597. "SQLFetchScroll",
  598. "SQLForeignKeys",
  599. "SQLForeignKeysW",
  600. "SQLFreeHandle",
  601. "SQLFreeStmt",
  602. "SQLGetData",
  603. "SQLGetDiagRec",
  604. "SQLGetDiagRecW",
  605. "SQLGetInfo",
  606. "SQLGetInfoW",
  607. "SQLGetTypeInfo",
  608. "SQLMoreResults",
  609. "SQLNumParams",
  610. "SQLNumResultCols",
  611. "SQLPrepare",
  612. "SQLPrepareW",
  613. "SQLPrimaryKeys",
  614. "SQLPrimaryKeysW",
  615. "SQLProcedureColumns",
  616. "SQLProcedureColumnsW",
  617. "SQLProcedures",
  618. "SQLProceduresW",
  619. "SQLRowCount",
  620. "SQLSetConnectAttr",
  621. "SQLSetEnvAttr",
  622. "SQLStatistics",
  623. "SQLStatisticsW",
  624. "SQLTables",
  625. "SQLTablesW",
  626. ]
  627. for func_name in funcs_with_ret:
  628. getattr(ODBC_API, func_name).restype = ctypes.c_short
  629. if sys.platform not in ('cli'):
  630. #Seems like the IronPython can not declare ctypes.POINTER type arguments
  631. ODBC_API.SQLAllocHandle.argtypes = [
  632. ctypes.c_short, ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p),
  633. ]
  634. ODBC_API.SQLBindParameter.argtypes = [
  635. ctypes.c_void_p, ctypes.c_ushort, ctypes.c_short,
  636. ctypes.c_short, ctypes.c_short, ctypes.c_size_t,
  637. ctypes.c_short, ctypes.c_void_p, ctypes.c_ssize_t, ctypes.POINTER(ctypes.c_ssize_t),
  638. ]
  639. ODBC_API.SQLColAttribute.argtypes = [
  640. ctypes.c_void_p, ctypes.c_ushort, ctypes.c_ushort,
  641. ctypes.c_void_p, ctypes.c_short, ctypes.POINTER(ctypes.c_short), ctypes.POINTER(ctypes.c_ssize_t),
  642. ]
  643. ODBC_API.SQLDataSources.argtypes = [
  644. ctypes.c_void_p, ctypes.c_ushort, ctypes.c_char_p,
  645. ctypes.c_short, ctypes.POINTER(ctypes.c_short),
  646. ctypes.c_char_p, ctypes.c_short, ctypes.POINTER(ctypes.c_short),
  647. ]
  648. ODBC_API.SQLDescribeCol.argtypes = [
  649. ctypes.c_void_p, ctypes.c_ushort, ctypes.c_char_p, ctypes.c_short,
  650. ctypes.POINTER(ctypes.c_short), ctypes.POINTER(ctypes.c_short),
  651. ctypes.POINTER(ctypes.c_size_t), ctypes.POINTER(ctypes.c_short), ctypes.POINTER(ctypes.c_short),
  652. ]
  653. ODBC_API.SQLDescribeParam.argtypes = [
  654. ctypes.c_void_p, ctypes.c_ushort,
  655. ctypes.POINTER(ctypes.c_short), ctypes.POINTER(ctypes.c_size_t),
  656. ctypes.POINTER(ctypes.c_short), ctypes.POINTER(ctypes.c_short),
  657. ]
  658. ODBC_API.SQLDriverConnect.argtypes = [
  659. ctypes.c_void_p, ctypes.c_void_p, ctypes.c_char_p,
  660. ctypes.c_short, ctypes.c_char_p, ctypes.c_short,
  661. ctypes.POINTER(ctypes.c_short), ctypes.c_ushort,
  662. ]
  663. ODBC_API.SQLDrivers.argtypes = [
  664. ctypes.c_void_p, ctypes.c_ushort,
  665. ctypes.c_char_p, ctypes.c_short, ctypes.POINTER(ctypes.c_short),
  666. ctypes.c_char_p, ctypes.c_short, ctypes.POINTER(ctypes.c_short),
  667. ]
  668. ODBC_API.SQLGetData.argtypes = [
  669. ctypes.c_void_p, ctypes.c_ushort, ctypes.c_short,
  670. ctypes.c_void_p, ctypes.c_ssize_t, ctypes.POINTER(ctypes.c_ssize_t),
  671. ]
  672. ODBC_API.SQLGetDiagRec.argtypes = [
  673. ctypes.c_short, ctypes.c_void_p, ctypes.c_short,
  674. ctypes.c_char_p, ctypes.POINTER(ctypes.c_int),
  675. ctypes.c_char_p, ctypes.c_short, ctypes.POINTER(ctypes.c_short),
  676. ]
  677. ODBC_API.SQLGetInfo.argtypes = [
  678. ctypes.c_void_p, ctypes.c_ushort, ctypes.c_void_p,
  679. ctypes.c_short, ctypes.POINTER(ctypes.c_short),
  680. ]
  681. ODBC_API.SQLRowCount.argtypes = [
  682. ctypes.c_void_p, ctypes.POINTER(ctypes.c_ssize_t),
  683. ]
  684. ODBC_API.SQLNumParams.argtypes = [
  685. ctypes.c_void_p, ctypes.POINTER(ctypes.c_short),
  686. ]
  687. ODBC_API.SQLNumResultCols.argtypes = [
  688. ctypes.c_void_p, ctypes.POINTER(ctypes.c_short),
  689. ]
  690. ODBC_API.SQLCloseCursor.argtypes = [ctypes.c_void_p]
  691. ODBC_API.SQLColumns.argtypes = [
  692. ctypes.c_void_p, ctypes.c_char_p, ctypes.c_short,
  693. ctypes.c_char_p, ctypes.c_short, ctypes.c_char_p,
  694. ctypes.c_short, ctypes.c_char_p, ctypes.c_short,
  695. ]
  696. ODBC_API.SQLConnect.argtypes = [
  697. ctypes.c_void_p, ctypes.c_char_p, ctypes.c_short,
  698. ctypes.c_char_p, ctypes.c_short, ctypes.c_char_p, ctypes.c_short,
  699. ]
  700. ODBC_API.SQLDisconnect.argtypes = [ctypes.c_void_p]
  701. ODBC_API.SQLEndTran.argtypes = [
  702. ctypes.c_short, ctypes.c_void_p, ctypes.c_short,
  703. ]
  704. ODBC_API.SQLExecute.argtypes = [ctypes.c_void_p]
  705. ODBC_API.SQLExecDirect.argtypes = [
  706. ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int,
  707. ]
  708. ODBC_API.SQLFetch.argtypes = [ctypes.c_void_p]
  709. ODBC_API.SQLFetchScroll.argtypes = [
  710. ctypes.c_void_p, ctypes.c_short, ctypes.c_ssize_t,
  711. ]
  712. ODBC_API.SQLForeignKeys.argtypes = [
  713. ctypes.c_void_p, ctypes.c_char_p, ctypes.c_short,
  714. ctypes.c_char_p, ctypes.c_short, ctypes.c_char_p,
  715. ctypes.c_short, ctypes.c_char_p, ctypes.c_short,
  716. ctypes.c_char_p, ctypes.c_short, ctypes.c_char_p, ctypes.c_short,
  717. ]
  718. ODBC_API.SQLFreeHandle.argtypes = [
  719. ctypes.c_short, ctypes.c_void_p,
  720. ]
  721. ODBC_API.SQLFreeStmt.argtypes = [
  722. ctypes.c_void_p, ctypes.c_ushort,
  723. ]
  724. ODBC_API.SQLGetTypeInfo.argtypes = [
  725. ctypes.c_void_p, ctypes.c_short,
  726. ]
  727. ODBC_API.SQLMoreResults.argtypes = [ctypes.c_void_p]
  728. ODBC_API.SQLPrepare.argtypes = [
  729. ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int,
  730. ]
  731. ODBC_API.SQLPrimaryKeys.argtypes = [
  732. ctypes.c_void_p, ctypes.c_char_p, ctypes.c_short,
  733. ctypes.c_char_p, ctypes.c_short, ctypes.c_char_p, ctypes.c_short,
  734. ]
  735. ODBC_API.SQLProcedureColumns.argtypes = [
  736. ctypes.c_void_p, ctypes.c_char_p, ctypes.c_short,
  737. ctypes.c_char_p, ctypes.c_short, ctypes.c_char_p,
  738. ctypes.c_short, ctypes.c_char_p, ctypes.c_short,
  739. ]
  740. ODBC_API.SQLProcedures.argtypes = [
  741. ctypes.c_void_p, ctypes.c_char_p, ctypes.c_short,
  742. ctypes.c_char_p, ctypes.c_short, ctypes.c_char_p, ctypes.c_short,
  743. ]
  744. ODBC_API.SQLSetConnectAttr.argtypes = [
  745. ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int,
  746. ]
  747. ODBC_API.SQLSetEnvAttr.argtypes = [
  748. ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int,
  749. ]
  750. ODBC_API.SQLStatistics.argtypes = [
  751. ctypes.c_void_p, ctypes.c_char_p, ctypes.c_short,
  752. ctypes.c_char_p, ctypes.c_short, ctypes.c_char_p,
  753. ctypes.c_short, ctypes.c_ushort, ctypes.c_ushort,
  754. ]
  755. ODBC_API.SQLTables.argtypes = [
  756. ctypes.c_void_p, ctypes.c_char_p, ctypes.c_short,
  757. ctypes.c_char_p, ctypes.c_short, ctypes.c_char_p,
  758. ctypes.c_short, ctypes.c_char_p, ctypes.c_short,
  759. ]
  760. def to_wchar(argtypes):
  761. if argtypes: # Under IronPython some argtypes are not declared
  762. result = []
  763. for x in argtypes:
  764. if x == ctypes.c_char_p:
  765. result.append(wchar_pointer)
  766. else:
  767. result.append(x)
  768. return result
  769. else:
  770. return argtypes
  771. ODBC_API.SQLColumnsW.argtypes = to_wchar(ODBC_API.SQLColumns.argtypes)
  772. ODBC_API.SQLConnectW.argtypes = to_wchar(ODBC_API.SQLConnect.argtypes)
  773. ODBC_API.SQLDataSourcesW.argtypes = to_wchar(ODBC_API.SQLDataSources.argtypes)
  774. ODBC_API.SQLDescribeColW.argtypes = to_wchar(ODBC_API.SQLDescribeCol.argtypes)
  775. ODBC_API.SQLDriverConnectW.argtypes = to_wchar(ODBC_API.SQLDriverConnect.argtypes)
  776. ODBC_API.SQLDriversW.argtypes = to_wchar(ODBC_API.SQLDrivers.argtypes)
  777. ODBC_API.SQLExecDirectW.argtypes = to_wchar(ODBC_API.SQLExecDirect.argtypes)
  778. ODBC_API.SQLForeignKeysW.argtypes = to_wchar(ODBC_API.SQLForeignKeys.argtypes)
  779. ODBC_API.SQLPrepareW.argtypes = to_wchar(ODBC_API.SQLPrepare.argtypes)
  780. ODBC_API.SQLPrimaryKeysW.argtypes = to_wchar(ODBC_API.SQLPrimaryKeys.argtypes)
  781. ODBC_API.SQLProcedureColumnsW.argtypes = to_wchar(ODBC_API.SQLProcedureColumns.argtypes)
  782. ODBC_API.SQLProceduresW.argtypes = to_wchar(ODBC_API.SQLProcedures.argtypes)
  783. ODBC_API.SQLStatisticsW.argtypes = to_wchar(ODBC_API.SQLStatistics.argtypes)
  784. ODBC_API.SQLTablesW.argtypes = to_wchar(ODBC_API.SQLTables.argtypes)
  785. ODBC_API.SQLGetDiagRecW.argtypes = to_wchar(ODBC_API.SQLGetDiagRec.argtypes)
  786. ODBC_API.SQLGetInfoW.argtypes = to_wchar(ODBC_API.SQLGetInfo.argtypes)
  787. # Set the alias for the ctypes functions for beter code readbility or performance.
  788. ADDR = ctypes.byref
  789. c_short = ctypes.c_short
  790. c_ssize_t = ctypes.c_ssize_t
  791. SQLFetch = ODBC_API.SQLFetch
  792. SQLExecute = ODBC_API.SQLExecute
  793. SQLBindParameter = ODBC_API.SQLBindParameter
  794. SQLGetData = ODBC_API.SQLGetData
  795. SQLRowCount = ODBC_API.SQLRowCount
  796. SQLNumResultCols = ODBC_API.SQLNumResultCols
  797. SQLEndTran = ODBC_API.SQLEndTran
  798. # Set alias for beter code readbility or performance.
  799. NO_FREE_STATEMENT = 0
  800. FREE_STATEMENT = 1
  801. BLANK_BYTE = str_8b()
  802. def ctrl_err(ht, h, val_ret, ansi):
  803. """Classify type of ODBC error from (type of handle, handle, return value)
  804. , and raise with a list"""
  805. if ansi:
  806. state = create_buffer(22)
  807. Message = create_buffer(1024*4)
  808. ODBC_func = ODBC_API.SQLGetDiagRec
  809. if py_v3:
  810. raw_s = lambda s: bytes(s,'ascii')
  811. else:
  812. raw_s = str_8b
  813. else:
  814. state = create_buffer_u(22)
  815. Message = create_buffer_u(1024*4)
  816. ODBC_func = ODBC_API.SQLGetDiagRecW
  817. raw_s = unicode
  818. NativeError = ctypes.c_int()
  819. Buffer_len = c_short()
  820. err_list = []
  821. number_errors = 1
  822. while 1:
  823. ret = ODBC_func(ht, h, number_errors, state, \
  824. ADDR(NativeError), Message, 1024, ADDR(Buffer_len))
  825. if ret == SQL_NO_DATA_FOUND:
  826. #No more data, I can raise
  827. #print(err_list[0][1])
  828. state = err_list[0][0]
  829. err_text = raw_s('[')+state+raw_s('] ')+err_list[0][1]
  830. if state[:2] in (raw_s('24'),raw_s('25'),raw_s('42')):
  831. raise ProgrammingError(state,err_text)
  832. elif state[:2] in (raw_s('22')):
  833. raise DataError(state,err_text)
  834. elif state[:2] in (raw_s('23')) or state == raw_s('40002'):
  835. raise IntegrityError(state,err_text)
  836. elif state == raw_s('0A000'):
  837. raise NotSupportedError(state,err_text)
  838. elif state in (raw_s('HYT00'),raw_s('HYT01')):
  839. raise OperationalError(state,err_text)
  840. elif state[:2] in (raw_s('IM'),raw_s('HY')):
  841. raise Error(state,err_text)
  842. else:
  843. raise DatabaseError(state,err_text)
  844. break
  845. elif ret == SQL_INVALID_HANDLE:
  846. #The handle passed is an invalid handle
  847. raise ProgrammingError('', 'SQL_INVALID_HANDLE')
  848. elif ret == SQL_SUCCESS:
  849. if ansi:
  850. err_list.append((state.value, Message.value, NativeError.value))
  851. else:
  852. err_list.append((from_buffer_u(state), from_buffer_u(Message), NativeError.value))
  853. number_errors += 1
  854. elif ret == SQL_ERROR:
  855. raise ProgrammingError('', 'SQL_ERROR')
  856. def check_success(ODBC_obj, ret):
  857. """ Validate return value, if not success, raise exceptions based on the handle """
  858. if ret not in (SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NO_DATA):
  859. if isinstance(ODBC_obj, Cursor):
  860. ctrl_err(SQL_HANDLE_STMT, ODBC_obj.stmt_h, ret, ODBC_obj.ansi)
  861. elif isinstance(ODBC_obj, Connection):
  862. ctrl_err(SQL_HANDLE_DBC, ODBC_obj.dbc_h, ret, ODBC_obj.ansi)
  863. else:
  864. ctrl_err(SQL_HANDLE_ENV, ODBC_obj, ret, False)
  865. def AllocateEnv():
  866. if pooling:
  867. ret = ODBC_API.SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, SQL_CP_ONE_PER_HENV, SQL_IS_UINTEGER)
  868. check_success(SQL_NULL_HANDLE, ret)
  869. '''
  870. Allocate an ODBC environment by initializing the handle shared_env_h
  871. ODBC enviroment needed to be created, so connections can be created under it
  872. connections pooling can be shared under one environment
  873. '''
  874. global shared_env_h
  875. shared_env_h = ctypes.c_void_p()
  876. ret = ODBC_API.SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, ADDR(shared_env_h))
  877. check_success(shared_env_h, ret)
  878. # Set the ODBC environment's compatibil leve to ODBC 3.0
  879. ret = ODBC_API.SQLSetEnvAttr(shared_env_h, SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3, 0)
  880. check_success(shared_env_h, ret)
  881. """
  882. Here, we have a few callables that determine how a result row is returned.
  883. A new one can be added by creating a callable that:
  884. - accepts a cursor as its parameter.
  885. - returns a callable that accepts an iterable containing the row values.
  886. """
  887. def TupleRow(cursor):
  888. """Normal tuple with added attribute `cursor_description`, as in pyodbc.
  889. This is the default.
  890. """
  891. class Row(tuple):
  892. cursor_description = cursor.description
  893. def get(self, field):
  894. if not hasattr(self, 'field_dict'):
  895. self.field_dict = {}
  896. for i,item in enumerate(self):
  897. self.field_dict[self.cursor_description[i][0]] = item
  898. return self.field_dict.get(field)
  899. def __getitem__(self, field):
  900. if isinstance(field, (unicode,str)):
  901. return self.get(field)
  902. else:
  903. return tuple.__getitem__(self,field)
  904. return Row
  905. def NamedTupleRow(cursor):
  906. """Named tuple to allow attribute lookup by name.
  907. Requires py2.6 or above.
  908. """
  909. from collections import namedtuple
  910. attr_names = [x[0] for x in cursor._ColBufferList]
  911. class Row(namedtuple('Row', attr_names, rename=True)):
  912. cursor_description = cursor.description
  913. def __new__(cls, iterable):
  914. return super(Row, cls).__new__(cls, *iterable)
  915. return Row
  916. def MutableNamedTupleRow(cursor):
  917. """Mutable named tuple to allow attribute to be replaced. This should be
  918. compatible with pyodbc's Row type.
  919. Requires 3rd-party library "recordtype".
  920. """
  921. from recordtype import recordtype
  922. attr_names = [x[0] for x in cursor._ColBufferList]
  923. class Row(recordtype('Row', attr_names, rename=True)):
  924. cursor_description = cursor.description
  925. def __init__(self, iterable):
  926. super(Row, self).__init__(*iterable)
  927. def __iter__(self):
  928. for field_name in self.__slots__:
  929. yield getattr(self, field_name)
  930. def __getitem__(self, index):
  931. if isinstance(index, slice):
  932. return tuple(getattr(self, x) for x in self.__slots__[index])
  933. return getattr(self, self.__slots__[index])
  934. def __setitem__(self, index, value):
  935. setattr(self, self.__slots__[index], value)
  936. return Row
  937. # When Null is used in a binary parameter, database usually would not
  938. # accept the None for a binary field, so the work around is to use a
  939. # Specical None that the pypyodbc moudle would know this NULL is for
  940. # a binary field.
  941. class BinaryNullType(): pass
  942. BinaryNull = BinaryNullType()
  943. # The get_type function is used to determine if parameters need to be re-binded
  944. # against the changed parameter types
  945. # 'b' for bool, 'U' for long unicode string, 'u' for short unicode string
  946. # 'S' for long 8 bit string, 's' for short 8 bit string, 'l' for big integer, 'i' for normal integer
  947. # 'f' for float, 'D' for Decimal, 't' for datetime.time, 'd' for datetime.datetime, 'dt' for datetime.datetime
  948. # 'bi' for binary
  949. def get_type(v):
  950. if isinstance(v, bool):
  951. return ('b',)
  952. elif isinstance(v, unicode):
  953. if len(v) >= 255:
  954. return ('U',(len(v)//1000+1)*1000)
  955. else:
  956. return ('u',)
  957. elif isinstance(v, (str_8b,str)):
  958. if len(v) >= 255:
  959. return ('S',(len(v)//1000+1)*1000)
  960. else:
  961. return ('s',)
  962. elif isinstance(v, (int, long)):
  963. #SQL_BIGINT defination: http://msdn.microsoft.com/en-us/library/ms187745.aspx
  964. if v > 2147483647 or v < -2147483648:
  965. return ('l',)
  966. else:
  967. return ('i',)
  968. elif isinstance(v, float):
  969. return ('f',)
  970. elif isinstance(v, BinaryNullType):
  971. return ('BN',)
  972. elif v is None:
  973. return ('N',)
  974. elif isinstance(v, Decimal):
  975. t = v.as_tuple() #1.23 -> (1,2,3),-2 , 1.23*E7 -> (1,2,3),5
  976. return ('D',(len(t[1]),0 - t[2])) # number of digits, and number of decimal digits
  977. elif isinstance (v, datetime.datetime):
  978. return ('dt',)
  979. elif isinstance (v, datetime.date):
  980. return ('d',)
  981. elif isinstance(v, datetime.time):
  982. return ('t',)
  983. elif isinstance (v, (bytearray, buffer)):
  984. return ('bi',(len(v)//1000+1)*1000)
  985. return type(v)
  986. # The Cursor Class.
  987. class Cursor:
  988. def __init__(self, conx, row_type_callable=None):
  989. """ Initialize self.stmt_h, which is the handle of a statement
  990. A statement is actually the basis of a python"cursor" object
  991. """
  992. self.stmt_h = ctypes.c_void_p()
  993. self.connection = conx
  994. self.ansi = conx.ansi
  995. self.row_type_callable = row_type_callable or TupleRow
  996. self.statement = None
  997. self._last_param_types = None
  998. self._ParamBufferList = []
  999. self._ColBufferList = []
  1000. self._row_type = None
  1001. self._buf_cvt_func = []
  1002. self.rowcount = -1
  1003. self.description = None
  1004. self.autocommit = None
  1005. self._ColTypeCodeList = []
  1006. self._outputsize = {}
  1007. self._inputsizers = []
  1008. self.arraysize = 1
  1009. ret = ODBC_API.SQLAllocHandle(SQL_HANDLE_STMT, self.connection.dbc_h, ADDR(self.stmt_h))
  1010. check_success(self, ret)
  1011. self._PARAM_SQL_TYPE_LIST = []
  1012. self.closed = False
  1013. def prepare(self, query_string):
  1014. """prepare a query"""
  1015. #self._free_results(FREE_STATEMENT)
  1016. if not self.connection:
  1017. self.close()
  1018. if type(query_string) == unicode:
  1019. c_query_string = wchar_pointer(UCS_buf(query_string))
  1020. ret = ODBC_API.SQLPrepareW(self.stmt_h, c_query_string, len(query_string))
  1021. else:
  1022. c_query_string = ctypes.c_char_p(query_string)
  1023. ret = ODBC_API.SQLPrepare(self.stmt_h, c_query_string, len(query_string))
  1024. if ret != SQL_SUCCESS:
  1025. check_success(self, ret)
  1026. self._PARAM_SQL_TYPE_LIST = []
  1027. if self.connection.support_SQLDescribeParam:
  1028. # SQLServer's SQLDescribeParam only supports DML SQL, so avoid the SELECT statement
  1029. if True:# 'SELECT' not in query_string.upper():
  1030. #self._free_results(NO_FREE_STATEMENT)
  1031. NumParams = c_short()
  1032. ret = ODBC_API.SQLNumParams(self.stmt_h, ADDR(NumParams))
  1033. if ret != SQL_SUCCESS:
  1034. check_success(self, ret)
  1035. for col_num in range(NumParams.value):
  1036. ParameterNumber = ctypes.c_ushort(col_num + 1)
  1037. DataType = c_short()
  1038. ParameterSize = ctypes.c_size_t()
  1039. DecimalDigits = c_short()
  1040. Nullable = c_short()
  1041. ret = ODBC_API.SQLDescribeParam(
  1042. self.stmt_h,
  1043. ParameterNumber,
  1044. ADDR(DataType),
  1045. ADDR(ParameterSize),
  1046. ADDR(DecimalDigits),
  1047. ADDR(Nullable),
  1048. )
  1049. if ret != SQL_SUCCESS:
  1050. try:
  1051. check_success(self, ret)
  1052. except DatabaseError:
  1053. if sys.exc_info()[1].value[0] == '07009':
  1054. self._PARAM_SQL_TYPE_LIST = []
  1055. break
  1056. else:
  1057. raise sys.exc_info()[1]
  1058. except:
  1059. raise sys.exc_info()[1]
  1060. self._PARAM_SQL_TYPE_LIST.append((DataType.value,DecimalDigits.value))
  1061. self.statement = query_string
  1062. def _BindParams(self, param_types, pram_io_list = []):
  1063. """Create parameter buffers based on param types, and bind them to the statement"""
  1064. # Clear the old Parameters
  1065. if not self.connection:
  1066. self.close()
  1067. #self._free_results(NO_FREE_STATEMENT)
  1068. # Get the number of query parameters judged by database.
  1069. NumParams = c_short()
  1070. ret = ODBC_API.SQLNumParams(self.stmt_h, ADDR(NumParams))
  1071. if ret != SQL_SUCCESS:
  1072. check_success(self, ret)
  1073. if len(param_types) != NumParams.value:
  1074. # In case number of parameters provided do not same as number required
  1075. error_desc = "The SQL contains %d parameter markers, but %d parameters were supplied" \
  1076. %(NumParams.value,len(param_types))
  1077. raise ProgrammingError('HY000',error_desc)
  1078. # Every parameter needs to be binded to a buffer
  1079. ParamBufferList = []
  1080. # Temporary holder since we can only call SQLDescribeParam before
  1081. # calling SQLBindParam.
  1082. temp_holder = []
  1083. for col_num in range(NumParams.value):
  1084. dec_num = 0
  1085. buf_size = 512
  1086. if param_types[col_num][0] == 'u':
  1087. sql_c_type = SQL_C_WCHAR
  1088. sql_type = SQL_WVARCHAR
  1089. buf_size = 255
  1090. ParameterBuffer = create_buffer_u(buf_size)
  1091. elif param_types[col_num][0] == 's':
  1092. sql_c_type = SQL_C_CHAR
  1093. sql_type = SQL_VARCHAR
  1094. buf_size = 255
  1095. ParameterBuffer = create_buffer(buf_size)
  1096. elif param_types[col_num][0] == 'U':
  1097. sql_c_type = SQL_C_WCHAR
  1098. sql_type = SQL_WLONGVARCHAR
  1099. buf_size = param_types[col_num][1]#len(self._inputsizers)>col_num and self._inputsizers[col_num] or 20500
  1100. ParameterBuffer = create_buffer_u(buf_size)
  1101. elif param_types[col_num][0] == 'S':
  1102. sql_c_type = SQL_C_CHAR
  1103. sql_type = SQL_LONGVARCHAR
  1104. buf_size = param_types[col_num][1]#len(self._inputsizers)>col_num and self._inputsizers[col_num] or 20500
  1105. ParameterBuffer = create_buffer(buf_size)
  1106. # bool subclasses int, thus has to go first
  1107. elif param_types[col_num][0] == 'b':
  1108. sql_c_type = SQL_C_CHAR
  1109. sql_type = SQL_BIT
  1110. buf_size = SQL_data_type_dict[sql_type][4]
  1111. ParameterBuffer = create_buffer(buf_size)
  1112. elif param_types[col_num][0] == 'i':
  1113. sql_c_type = SQL_C_CHAR
  1114. sql_type = SQL_INTEGER
  1115. buf_size = SQL_data_type_dict[sql_type][4]
  1116. ParameterBuffer = create_buffer(buf_size)
  1117. elif param_types[col_num][0] == 'l':
  1118. sql_c_type = SQL_C_CHAR
  1119. sql_type = SQL_BIGINT
  1120. buf_size = SQL_data_type_dict[sql_type][4]
  1121. ParameterBuffer = create_buffer(buf_size)
  1122. elif param_types[col_num][0] == 'D': #Decimal
  1123. sql_c_type = SQL_C_CHAR
  1124. sql_type = SQL_NUMERIC
  1125. digit_num, dec_num = param_types[col_num][1]
  1126. if dec_num > 0:
  1127. # has decimal
  1128. buf_size = digit_num
  1129. dec_num = dec_num
  1130. else:
  1131. # no decimal
  1132. buf_size = digit_num - dec_num
  1133. dec_num = 0
  1134. ParameterBuffer = create_buffer(buf_size + 4)# add extra length for sign and dot
  1135. elif param_types[col_num][0] == 'f':
  1136. sql_c_type = SQL_C_CHAR
  1137. sql_type = SQL_DOUBLE
  1138. buf_size = SQL_data_type_dict[sql_type][4]
  1139. ParameterBuffer = create_buffer(buf_size)
  1140. # datetime subclasses date, thus has to go first
  1141. elif param_types[col_num][0] == 'dt':
  1142. sql_c_type = SQL_C_CHAR
  1143. sql_type = SQL_TYPE_TIMESTAMP
  1144. buf_size = self.connection.type_size_dic[SQL_TYPE_TIMESTAMP][0]
  1145. ParameterBuffer = create_buffer(buf_size)
  1146. dec_num = self.connection.type_size_dic[SQL_TYPE_TIMESTAMP][1]
  1147. elif param_types[col_num][0] == 'd':
  1148. sql_c_type = SQL_C_CHAR
  1149. if SQL_TYPE_DATE in self.connection.type_size_dic:
  1150. #if DEBUG:print('conx.type_size_dic.has_key(SQL_TYPE_DATE)')
  1151. sql_type = SQL_TYPE_DATE
  1152. buf_size = self.connection.type_size_dic[SQL_TYPE_DATE][0]
  1153. ParameterBuffer = create_buffer(buf_size)
  1154. dec_num = self.connection.type_size_dic[SQL_TYPE_DATE][1]
  1155. else:
  1156. # SQL Sever <2008 doesn't have a DATE type.
  1157. sql_type = SQL_TYPE_TIMESTAMP
  1158. buf_size = 10
  1159. ParameterBuffer = create_buffer(buf_size)
  1160. elif param_types[col_num][0] == 't':
  1161. sql_c_type = SQL_C_CHAR
  1162. if SQL_TYPE_TIME in self.connection.type_size_dic:
  1163. sql_type = SQL_TYPE_TIME
  1164. buf_size = self.connection.type_size_dic[SQL_TYPE_TIME][0]
  1165. ParameterBuffer = create_buffer(buf_size)
  1166. dec_num = self.connection.type_size_dic[SQL_TYPE_TIME][1]
  1167. elif SQL_SS_TIME2 in self.connection.type_size_dic:
  1168. # TIME type added in SQL Server 2008
  1169. sql_type = SQL_SS_TIME2
  1170. buf_size = self.connection.type_size_dic[SQL_SS_TIME2][0]
  1171. ParameterBuffer = create_buffer(buf_size)
  1172. dec_num = self.connection.type_size_dic[SQL_SS_TIME2][1]
  1173. else:
  1174. # SQL Sever <2008 doesn't have a TIME type.
  1175. sql_type = SQL_TYPE_TIMESTAMP
  1176. buf_size = self.connection.type_size_dic[SQL_TYPE_TIMESTAMP][0]
  1177. ParameterBuffer = create_buffer(buf_size)
  1178. dec_num = 3
  1179. elif param_types[col_num][0] == 'BN':
  1180. sql_c_type = SQL_C_BINARY
  1181. sql_type = SQL_VARBINARY
  1182. buf_size = 1
  1183. ParameterBuffer = create_buffer(buf_size)
  1184. elif param_types[col_num][0] == 'N':
  1185. if len(self._PARAM_SQL_TYPE_LIST) > 0:
  1186. sql_c_type = SQL_C_DEFAULT
  1187. sql_type = self._PARAM_SQL_TYPE_LIST[col_num][0]
  1188. buf_size = 1
  1189. ParameterBuffer = create_buffer(buf_size)
  1190. else:
  1191. sql_c_type = SQL_C_CHAR
  1192. sql_type = SQL_CHAR
  1193. buf_size = 1
  1194. ParameterBuffer = create_buffer(buf_size)
  1195. elif param_types[col_num][0] == 'bi':
  1196. sql_c_type = SQL_C_BINARY
  1197. sql_type = SQL_LONGVARBINARY
  1198. buf_size = param_types[col_num][1]#len(self._inputsizers)>col_num and self._inputsizers[col_num] or 20500
  1199. ParameterBuffer = create_buffer(buf_size)
  1200. else:
  1201. sql_c_type = SQL_C_CHAR
  1202. sql_type = SQL_LONGVARCHAR
  1203. buf_size = len(self._inputsizers)>col_num and self._inputsizers[col_num] or 20500
  1204. ParameterBuffer = create_buffer(buf_size)
  1205. temp_holder.append((sql_c_type, sql_type, buf_size, dec_num, ParameterBuffer))
  1206. for col_num, (sql_c_type, sql_type, buf_size, dec_num, ParameterBuffer) in enumerate(temp_holder):
  1207. BufferLen = c_ssize_t(buf_size)
  1208. LenOrIndBuf = c_ssize_t()
  1209. InputOutputType = SQL_PARAM_INPUT
  1210. if len(pram_io_list) > col_num:
  1211. InputOutputType = pram_io_list[col_num]
  1212. ret = SQLBindParameter(self.stmt_h, col_num + 1, InputOutputType, sql_c_type, sql_type, buf_size,\
  1213. dec_num, ADDR(ParameterBuffer), BufferLen,ADDR(LenOrIndBuf))
  1214. if ret != SQL_SUCCESS:
  1215. check_success(self, ret)
  1216. # Append the value buffer and the length buffer to the array
  1217. ParamBufferList.append((ParameterBuffer,LenOrIndBuf,sql_type))
  1218. self._last_param_types = param_types
  1219. self._ParamBufferList = ParamBufferList
  1220. def execute(self, query_string, params=None, many_mode=False, call_mode=False):
  1221. """ Execute the query string, with optional parameters.
  1222. If parameters are provided, the query would first be prepared, then executed with parameters;
  1223. If parameters are not provided, only th query sting, it would be executed directly
  1224. """
  1225. if not self.connection:
  1226. self.close()
  1227. self._free_stmt(SQL_CLOSE)
  1228. if params:
  1229. # If parameters exist, first prepare the query then executed with parameters
  1230. if not isinstance(params, (tuple, list)):
  1231. raise TypeError("Params must be in a list, tuple, or Row")
  1232. if query_string != self.statement:
  1233. # if the query is not same as last query, then it is not prepared
  1234. self.prepare(query_string)
  1235. param_types = list(map(get_type, params))
  1236. if call_mode:
  1237. self._free_stmt(SQL_RESET_PARAMS)
  1238. self._BindParams(param_types, self._pram_io_list)
  1239. else:
  1240. if self._last_param_types is None:
  1241. self._free_stmt(SQL_RESET_PARAMS)
  1242. self._BindParams(param_types)
  1243. elif len(param_types) != len(self._last_param_types):
  1244. self._free_stmt(SQL_RESET_PARAMS)
  1245. self._BindParams(param_types)
  1246. elif sum([p_type[0] != 'N' and p_type != self._last_param_types[i] for i,p_type in enumerate(param_types)]) > 0:
  1247. self._free_stmt(SQL_RESET_PARAMS)
  1248. self._BindParams(param_types)
  1249. # With query prepared, now put parameters into buffers
  1250. col_num = 0
  1251. for param_buffer, param_buffer_len, sql_type in self._ParamBufferList:
  1252. c_char_buf, c_buf_len = '', 0
  1253. param_val = params[col_num]
  1254. if param_types[col_num][0] in ('N','BN'):
  1255. param_buffer_len.value = SQL_NULL_DATA
  1256. col_num += 1
  1257. continue
  1258. elif param_types[col_num][0] in ('i','l','f'):
  1259. if py_v3:
  1260. c_char_buf = bytes(str(param_val),'ascii')
  1261. else:
  1262. c_char_buf = str(param_val)
  1263. c_buf_len = len(c_char_buf)
  1264. elif param_types[col_num][0] in ('s','S'):
  1265. c_char_buf = param_val
  1266. c_buf_len = len(c_char_buf)
  1267. elif param_types[col_num][0] in ('u','U'):
  1268. c_char_buf = UCS_buf(param_val)
  1269. c_buf_len = len(c_char_buf)
  1270. elif param_types[col_num][0] == 'dt':
  1271. max_len = self.connection.type_size_dic[SQL_TYPE_TIMESTAMP][0]
  1272. datetime_str = param_val.strftime('%Y-%m-%d %H:%M:%S.%f')
  1273. c_char_buf = datetime_str[:max_len]
  1274. if py_v3:
  1275. c_char_buf = bytes(c_char_buf,'ascii')
  1276. c_buf_len = len(c_char_buf)
  1277. # print c_buf_len, c_char_buf
  1278. elif param_types[col_num][0] == 'd':
  1279. if SQL_TYPE_DATE in self.connection.type_size_dic:
  1280. max_len = self.connection.type_size_dic[SQL_TYPE_DATE][0]
  1281. else:
  1282. max_len = 10
  1283. c_char_buf = param_val.isoformat()[:max_len]
  1284. if py_v3:
  1285. c_char_buf = bytes(c_char_buf,'ascii')
  1286. c_buf_len = len(c_char_buf)
  1287. #print c_char_buf
  1288. elif param_types[col_num][0] == 't':
  1289. if SQL_TYPE_TIME in self.connection.type_size_dic:
  1290. max_len = self.connection.type_size_dic[SQL_TYPE_TIME][0]
  1291. c_char_buf = param_val.isoformat()[:max_len]
  1292. c_buf_len = len(c_char_buf)
  1293. elif SQL_SS_TIME2 in self.connection.type_size_dic:
  1294. max_len = self.connection.type_size_dic[SQL_SS_TIME2][0]
  1295. c_char_buf = param_val.isoformat()[:max_len]
  1296. c_buf_len = len(c_char_buf)
  1297. else:
  1298. c_buf_len = self.connection.type_size_dic[SQL_TYPE_TIMESTAMP][0]
  1299. time_str = param_val.isoformat()
  1300. if len(time_str) == 8:
  1301. time_str += '.000'
  1302. c_char_buf = '1900-01-01 '+time_str[0:c_buf_len - 11]
  1303. if py_v3:
  1304. c_char_buf = bytes(c_char_buf,'ascii')
  1305. #print c_buf_len, c_char_buf
  1306. elif param_types[col_num][0] == 'b':
  1307. if param_val == True:
  1308. c_char_buf = '1'
  1309. else:
  1310. c_char_buf = '0'
  1311. if py_v3:
  1312. c_char_buf = bytes(c_char_buf,'ascii')
  1313. c_buf_len = 1
  1314. elif param_types[col_num][0] == 'D': #Decimal
  1315. sign = param_val.as_tuple()[0] == 0 and '+' or '-'
  1316. digit_string = ''.join([str(x) for x in param_val.as_tuple()[1]])
  1317. digit_num, dec_num = param_types[col_num][1]
  1318. if dec_num > 0:
  1319. # has decimal
  1320. left_part = digit_string[:digit_num - dec_num]
  1321. right_part = digit_string[0-dec_num:]
  1322. else:
  1323. # no decimal
  1324. left_part = digit_string + '0'*(0-dec_num)
  1325. right_part = ''
  1326. v = ''.join((sign, left_part,'.', right_part))
  1327. if py_v3:
  1328. c_char_buf = bytes(v,'ascii')
  1329. else:
  1330. c_char_buf = v
  1331. c_buf_len = len(c_char_buf)
  1332. elif param_types[col_num][0] == 'bi':
  1333. c_char_buf = str_8b(param_val)
  1334. c_buf_len = len(c_char_buf)
  1335. else:
  1336. c_char_buf = param_val
  1337. if param_types[col_num][0] == 'bi':
  1338. param_buffer.raw = str_8b(param_val)
  1339. else:
  1340. #print (type(param_val),param_buffer, param_buffer.value)
  1341. param_buffer.value = c_char_buf
  1342. if param_types[col_num][0] in ('U','u','S','s'):
  1343. #ODBC driver will find NUL in unicode and string to determine their length
  1344. param_buffer_len.value = SQL_NTS
  1345. else:
  1346. param_buffer_len.value = c_buf_len
  1347. col_num += 1
  1348. ret = SQLExecute(self.stmt_h)
  1349. if ret != SQL_SUCCESS:
  1350. #print param_valparam_buffer, param_buffer.value
  1351. check_success(self, ret)
  1352. if not many_mode:
  1353. self._NumOfRows()
  1354. self._UpdateDesc()
  1355. #self._BindCols()
  1356. else:
  1357. self.execdirect(query_string)
  1358. return self
  1359. def _SQLExecute(self):
  1360. if not self.connection:
  1361. self.close()
  1362. ret = SQLExecute(self.stmt_h)
  1363. if ret != SQL_SUCCESS:
  1364. check_success(self, ret)
  1365. def execdirect(self, query_string):
  1366. """Execute a query directly"""
  1367. if not self.connection:
  1368. self.close()
  1369. self._free_stmt()
  1370. self._last_param_types = None
  1371. self.statement = None
  1372. if type(query_string) == unicode:
  1373. c_query_string = wchar_pointer(UCS_buf(query_string))
  1374. ret = ODBC_API.SQLExecDirectW(self.stmt_h, c_query_string, len(query_string))
  1375. else:
  1376. c_query_string = ctypes.c_char_p(query_string)
  1377. ret = ODBC_API.SQLExecDirect(self.stmt_h, c_query_string, len(query_string))
  1378. check_success(self, ret)
  1379. self._NumOfRows()
  1380. self._UpdateDesc()
  1381. #self._BindCols()
  1382. return self
  1383. def callproc(self, procname, args):
  1384. if not self.connection:
  1385. self.close()
  1386. raise Warning('', 'Still not fully implemented')
  1387. 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)]
  1388. print('pram_io_list: '+str(self._pram_io_list))
  1389. call_escape = '{CALL '+procname
  1390. if args:
  1391. call_escape += '(' + ','.join(['?' for params in args]) + ')'
  1392. call_escape += '}'
  1393. self.execute(call_escape, args, call_mode = True)
  1394. result = []
  1395. for buf, buf_len, sql_type in self._ParamBufferList:
  1396. if buf_len.value == -1:
  1397. result.append(None)
  1398. else:
  1399. result.append(self.connection.output_converter[sql_type](buf.value))
  1400. return result
  1401. def executemany(self, query_string, params_list = [None]):
  1402. if not self.connection:
  1403. self.close()
  1404. for params in params_list:
  1405. self.execute(query_string, params, many_mode = True)
  1406. self._NumOfRows()
  1407. self.rowcount = -1
  1408. self._UpdateDesc()
  1409. #self._BindCols()
  1410. def _CreateColBuf(self):
  1411. if not self.connection:
  1412. self.close()
  1413. self._free_stmt(SQL_UNBIND)
  1414. NOC = self._NumOfCols()
  1415. self._ColBufferList = []
  1416. bind_data = True
  1417. for col_num in range(NOC):
  1418. col_name = self.description[col_num][0]
  1419. col_size = self.description[col_num][2]
  1420. col_sql_data_type = self._ColTypeCodeList[col_num]
  1421. target_type = SQL_data_type_dict[col_sql_data_type][2]
  1422. dynamic_length = SQL_data_type_dict[col_sql_data_type][5]
  1423. # set default size base on the column's sql data type
  1424. total_buf_len = SQL_data_type_dict[col_sql_data_type][4]
  1425. # over-write if there's pre-set size value for "large columns"
  1426. if total_buf_len > 20500:
  1427. total_buf_len = self._outputsize.get(None,total_buf_len)
  1428. # over-write if there's pre-set size value for the "col_num" column
  1429. total_buf_len = self._outputsize.get(col_num, total_buf_len)
  1430. # if the size of the buffer is very long, do not bind
  1431. # because a large buffer decrease performance, and sometimes you only get a NULL value.
  1432. # in that case use sqlgetdata instead.
  1433. if col_size >= 1024:
  1434. dynamic_length = True
  1435. alloc_buffer = SQL_data_type_dict[col_sql_data_type][3](total_buf_len)
  1436. used_buf_len = c_ssize_t()
  1437. force_unicode = self.connection.unicode_results
  1438. if force_unicode and col_sql_data_type in (SQL_CHAR,SQL_VARCHAR,SQL_LONGVARCHAR):
  1439. target_type = SQL_C_WCHAR
  1440. alloc_buffer = create_buffer_u(total_buf_len)
  1441. buf_cvt_func = self.connection.output_converter[self._ColTypeCodeList[col_num]]
  1442. if bind_data:
  1443. if dynamic_length:
  1444. bind_data = False
  1445. 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])
  1446. if bind_data:
  1447. ret = ODBC_API.SQLBindCol(self.stmt_h, col_num + 1, target_type, ADDR(alloc_buffer), total_buf_len, ADDR(used_buf_len))
  1448. if ret != SQL_SUCCESS:
  1449. check_success(self, ret)
  1450. def _UpdateDesc(self):
  1451. "Get the information of (name, type_code, display_size, internal_size, col_precision, scale, null_ok)"
  1452. if not self.connection:
  1453. self.close()
  1454. force_unicode = self.connection.unicode_results
  1455. if force_unicode:
  1456. Cname = create_buffer_u(1024)
  1457. else:
  1458. Cname = create_buffer(1024)
  1459. Cname_ptr = c_short()
  1460. Ctype_code = c_short()
  1461. Csize = ctypes.c_size_t()
  1462. Cdisp_size = c_ssize_t(0)
  1463. CDecimalDigits = c_short()
  1464. Cnull_ok = c_short()
  1465. ColDescr = []
  1466. self._ColTypeCodeList = []
  1467. NOC = self._NumOfCols()
  1468. for col in range(1, NOC+1):
  1469. ret = ODBC_API.SQLColAttribute(self.stmt_h, col, SQL_DESC_DISPLAY_SIZE, ADDR(create_buffer(10)),
  1470. 10, ADDR(c_short()),ADDR(Cdisp_size))
  1471. if ret != SQL_SUCCESS:
  1472. check_success(self, ret)
  1473. if force_unicode:
  1474. ret = ODBC_API.SQLDescribeColW(self.stmt_h, col, Cname, len(Cname), ADDR(Cname_ptr),\
  1475. ADDR(Ctype_code),ADDR(Csize),ADDR(CDecimalDigits), ADDR(Cnull_ok))
  1476. if ret != SQL_SUCCESS:
  1477. check_success(self, ret)
  1478. else:
  1479. ret = ODBC_API.SQLDescribeCol(self.stmt_h, col, Cname, len(Cname), ADDR(Cname_ptr),\
  1480. ADDR(Ctype_code),ADDR(Csize),ADDR(CDecimalDigits), ADDR(Cnull_ok))
  1481. if ret != SQL_SUCCESS:
  1482. check_success(self, ret)
  1483. col_name = Cname.value
  1484. if lowercase:
  1485. col_name = col_name.lower()
  1486. #(name, type_code, display_size,
  1487. ColDescr.append((col_name, SQL_data_type_dict.get(Ctype_code.value,(Ctype_code.value,))[0],Cdisp_size.value,\
  1488. Csize.value, Csize.value,CDecimalDigits.value,Cnull_ok.value == 1 and True or False))
  1489. self._ColTypeCodeList.append(Ctype_code.value)
  1490. if len(ColDescr) > 0:
  1491. self.description = ColDescr
  1492. # Create the row type before fetching.
  1493. self._row_type = self.row_type_callable(self)
  1494. else:
  1495. self.description = None
  1496. self._CreateColBuf()
  1497. def _NumOfRows(self):
  1498. """Get the number of rows"""
  1499. if not self.connection:
  1500. self.close()
  1501. NOR = c_ssize_t()
  1502. ret = SQLRowCount(self.stmt_h, ADDR(NOR))
  1503. if ret != SQL_SUCCESS:
  1504. check_success(self, ret)
  1505. self.rowcount = NOR.value
  1506. return self.rowcount
  1507. def _NumOfCols(self):
  1508. """Get the number of cols"""
  1509. if not self.connection:
  1510. self.close()
  1511. NOC = c_short()
  1512. ret = SQLNumResultCols(self.stmt_h, ADDR(NOC))
  1513. if ret != SQL_SUCCESS:
  1514. check_success(self, ret)
  1515. return NOC.value
  1516. def fetchall(self):
  1517. if not self.connection:
  1518. self.close()
  1519. rows = []
  1520. while True:
  1521. row = self.fetchone()
  1522. if row is None:
  1523. break
  1524. rows.append(row)
  1525. return rows
  1526. def fetchmany(self, num = None):
  1527. if not self.connection:
  1528. self.close()
  1529. if num is None:
  1530. num = self.arraysize
  1531. rows = []
  1532. while len(rows) < num:
  1533. row = self.fetchone()
  1534. if row is None:
  1535. break
  1536. rows.append(row)
  1537. return rows
  1538. def fetchone(self):
  1539. if not self.connection:
  1540. self.close()
  1541. ret = SQLFetch(self.stmt_h)
  1542. if ret in (SQL_SUCCESS,SQL_SUCCESS_WITH_INFO):
  1543. '''Bind buffers for the record set columns'''
  1544. value_list = []
  1545. col_num = 1
  1546. 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:
  1547. raw_data_parts = []
  1548. while 1:
  1549. if bind_data:
  1550. ret = SQL_SUCCESS
  1551. else:
  1552. ret = SQLGetData(self.stmt_h, col_num, target_type, ADDR_alloc_buffer, total_buf_len, ADDR_used_buf_len)
  1553. if ret == SQL_SUCCESS:
  1554. if used_buf_len.value == SQL_NULL_DATA:
  1555. value_list.append(None)
  1556. else:
  1557. if raw_data_parts == []:
  1558. # Means no previous data, no need to combine
  1559. if target_type == SQL_C_BINARY:
  1560. value_list.append(buf_cvt_func(alloc_buffer.raw[:used_buf_len.value]))
  1561. elif target_type == SQL_C_WCHAR:
  1562. value_list.append(buf_cvt_func(from_buffer_u(alloc_buffer)))
  1563. else:
  1564. value_list.append(buf_cvt_func(alloc_buffer.value))
  1565. else:
  1566. # There are previous fetched raw data to combine
  1567. if target_type == SQL_C_BINARY:
  1568. raw_data_parts.append(alloc_buffer.raw[:used_buf_len.value])
  1569. elif target_type == SQL_C_WCHAR:
  1570. raw_data_parts.append(from_buffer_u(alloc_buffer))
  1571. else:
  1572. raw_data_parts.append(alloc_buffer.value)
  1573. break
  1574. elif ret == SQL_SUCCESS_WITH_INFO:
  1575. # Means the data is only partial
  1576. if target_type == SQL_C_BINARY:
  1577. raw_data_parts.append(alloc_buffer.raw)
  1578. else:
  1579. raw_data_parts.append(alloc_buffer.value)
  1580. elif ret == SQL_NO_DATA:
  1581. # Means all data has been transmitted
  1582. break
  1583. else:
  1584. check_success(self, ret)
  1585. if raw_data_parts != []:
  1586. if py_v3:
  1587. if target_type != SQL_C_BINARY:
  1588. raw_value = ''.join(raw_data_parts)
  1589. else:
  1590. raw_value = BLANK_BYTE.join(raw_data_parts)
  1591. else:
  1592. raw_value = ''.join(raw_data_parts)
  1593. value_list.append(buf_cvt_func(raw_value))
  1594. col_num += 1
  1595. return self._row_type(value_list)
  1596. else:
  1597. if ret == SQL_NO_DATA_FOUND:
  1598. return None
  1599. else:
  1600. check_success(self, ret)
  1601. def __next__(self):
  1602. return self.next()
  1603. def next(self):
  1604. row = self.fetchone()
  1605. if row is None:
  1606. raise(StopIteration)
  1607. return row
  1608. def __iter__(self):
  1609. return self
  1610. def skip(self, count = 0):
  1611. if not self.connection:
  1612. self.close()
  1613. for i in range(count):
  1614. ret = ODBC_API.SQLFetchScroll(self.stmt_h, SQL_FETCH_NEXT, 0)
  1615. if ret != SQL_SUCCESS:
  1616. check_success(self, ret)
  1617. return None
  1618. def nextset(self):
  1619. if not self.connection:
  1620. self.close()
  1621. ret = ODBC_API.SQLMoreResults(self.stmt_h)
  1622. if ret not in (SQL_SUCCESS, SQL_NO_DATA):
  1623. check_success(self, ret)
  1624. if ret == SQL_NO_DATA:
  1625. self._free_stmt()
  1626. return False
  1627. else:
  1628. self._NumOfRows()
  1629. self._UpdateDesc()
  1630. #self._BindCols()
  1631. return True
  1632. def _free_stmt(self, free_type = None):
  1633. if not self.connection:
  1634. self.close()
  1635. if not self.connection.connected:
  1636. raise ProgrammingError('HY000','Attempt to use a closed connection.')
  1637. #self.description = None
  1638. #self.rowcount = -1
  1639. if free_type in (SQL_CLOSE, None):
  1640. ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_CLOSE)
  1641. if ret != SQL_SUCCESS:
  1642. check_success(self, ret)
  1643. if free_type in (SQL_UNBIND, None):
  1644. ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_UNBIND)
  1645. if ret != SQL_SUCCESS:
  1646. check_success(self, ret)
  1647. if free_type in (SQL_RESET_PARAMS, None):
  1648. ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_RESET_PARAMS)
  1649. if ret != SQL_SUCCESS:
  1650. check_success(self, ret)
  1651. def getTypeInfo(self, sqlType = None):
  1652. if not self.connection:
  1653. self.close()
  1654. if sqlType is None:
  1655. type = SQL_ALL_TYPES
  1656. else:
  1657. type = sqlType
  1658. ret = ODBC_API.SQLGetTypeInfo(self.stmt_h, type)
  1659. if ret in (SQL_SUCCESS, SQL_SUCCESS_WITH_INFO):
  1660. self._NumOfRows()
  1661. self._UpdateDesc()
  1662. #self._BindCols()
  1663. return self.fetchone()
  1664. def tables(self, table=None, catalog=None, schema=None, tableType=None):
  1665. """Return a list with all tables"""
  1666. if not self.connection:
  1667. self.close()
  1668. l_catalog = l_schema = l_table = l_tableType = 0
  1669. if unicode in [type(x) for x in (table, catalog, schema,tableType)]:
  1670. string_p = lambda x:wchar_pointer(UCS_buf(x))
  1671. API_f = ODBC_API.SQLTablesW
  1672. else:
  1673. string_p = ctypes.c_char_p
  1674. API_f = ODBC_API.SQLTables
  1675. if catalog is not None:
  1676. l_catalog = len(catalog)
  1677. catalog = string_p(catalog)
  1678. if schema is not None:
  1679. l_schema = len(schema)
  1680. schema = string_p(schema)
  1681. if table is not None:
  1682. l_table = len(table)
  1683. table = string_p(table)
  1684. if tableType is not None:
  1685. l_tableType = len(tableType)
  1686. tableType = string_p(tableType)
  1687. self._free_stmt()
  1688. self._last_param_types = None
  1689. self.statement = None
  1690. ret = API_f(self.stmt_h,
  1691. catalog, l_catalog,
  1692. schema, l_schema,
  1693. table, l_table,
  1694. tableType, l_tableType)
  1695. check_success(self, ret)
  1696. self._NumOfRows()
  1697. self._UpdateDesc()
  1698. #self._BindCols()
  1699. return self
  1700. def columns(self, table=None, catalog=None, schema=None, column=None):
  1701. """Return a list with all columns"""
  1702. if not self.connection:
  1703. self.close()
  1704. l_catalog = l_schema = l_table = l_column = 0
  1705. if unicode in [type(x) for x in (table, catalog, schema,column)]:
  1706. string_p = lambda x:wchar_pointer(UCS_buf(x))
  1707. API_f = ODBC_API.SQLColumnsW
  1708. else:
  1709. string_p = ctypes.c_char_p
  1710. API_f = ODBC_API.SQLColumns
  1711. if catalog is not None:
  1712. l_catalog = len(catalog)
  1713. catalog = string_p(catalog)
  1714. if schema is not None:
  1715. l_schema = len(schema)
  1716. schema = string_p(schema)
  1717. if table is not None:
  1718. l_table = len(table)
  1719. table = string_p(table)
  1720. if column is not None:
  1721. l_column = len(column)
  1722. column = string_p(column)
  1723. self._free_stmt()
  1724. self._last_param_types = None
  1725. self.statement = None
  1726. ret = API_f(self.stmt_h,
  1727. catalog, l_catalog,
  1728. schema, l_schema,
  1729. table, l_table,
  1730. column, l_column)
  1731. check_success(self, ret)
  1732. self._NumOfRows()
  1733. self._UpdateDesc()
  1734. #self._BindCols()
  1735. return self
  1736. def primaryKeys(self, table=None, catalog=None, schema=None):
  1737. if not self.connection:
  1738. self.close()
  1739. l_catalog = l_schema = l_table = 0
  1740. if unicode in [type(x) for x in (table, catalog, schema)]:
  1741. string_p = lambda x:wchar_pointer(UCS_buf(x))
  1742. API_f = ODBC_API.SQLPrimaryKeysW
  1743. else:
  1744. string_p = ctypes.c_char_p
  1745. API_f = ODBC_API.SQLPrimaryKeys
  1746. if catalog is not None:
  1747. l_catalog = len(catalog)
  1748. catalog = string_p(catalog)
  1749. if schema is not None:
  1750. l_schema = len(schema)
  1751. schema = string_p(schema)
  1752. if table is not None:
  1753. l_table = len(table)
  1754. table = string_p(table)
  1755. self._free_stmt()
  1756. self._last_param_types = None
  1757. self.statement = None
  1758. ret = API_f(self.stmt_h,
  1759. catalog, l_catalog,
  1760. schema, l_schema,
  1761. table, l_table)
  1762. check_success(self, ret)
  1763. self._NumOfRows()
  1764. self._UpdateDesc()
  1765. #self._BindCols()
  1766. return self
  1767. def foreignKeys(self, table=None, catalog=None, schema=None, foreignTable=None, foreignCatalog=None, foreignSchema=None):
  1768. if not self.connection:
  1769. self.close()
  1770. l_catalog = l_schema = l_table = l_foreignTable = l_foreignCatalog = l_foreignSchema = 0
  1771. if unicode in [type(x) for x in (table, catalog, schema,foreignTable,foreignCatalog,foreignSchema)]:
  1772. string_p = lambda x:wchar_pointer(UCS_buf(x))
  1773. API_f = ODBC_API.SQLForeignKeysW
  1774. else:
  1775. string_p = ctypes.c_char_p
  1776. API_f = ODBC_API.SQLForeignKeys
  1777. if catalog is not None:
  1778. l_catalog = len(catalog)
  1779. catalog = string_p(catalog)
  1780. if schema is not None:
  1781. l_schema = len(schema)
  1782. schema = string_p(schema)
  1783. if table is not None:
  1784. l_table = len(table)
  1785. table = string_p(table)
  1786. if foreignTable is not None:
  1787. l_foreignTable = len(foreignTable)
  1788. foreignTable = string_p(foreignTable)
  1789. if foreignCatalog is not None:
  1790. l_foreignCatalog = len(foreignCatalog)
  1791. foreignCatalog = string_p(foreignCatalog)
  1792. if foreignSchema is not None:
  1793. l_foreignSchema = len(foreignSchema)
  1794. foreignSchema = string_p(foreignSchema)
  1795. self._free_stmt()
  1796. self._last_param_types = None
  1797. self.statement = None
  1798. ret = API_f(self.stmt_h,
  1799. catalog, l_catalog,
  1800. schema, l_schema,
  1801. table, l_table,
  1802. foreignCatalog, l_foreignCatalog,
  1803. foreignSchema, l_foreignSchema,
  1804. foreignTable, l_foreignTable)
  1805. check_success(self, ret)
  1806. self._NumOfRows()
  1807. self._UpdateDesc()
  1808. #self._BindCols()
  1809. return self
  1810. def procedurecolumns(self, procedure=None, catalog=None, schema=None, column=None):
  1811. if not self.connection:
  1812. self.close()
  1813. l_catalog = l_schema = l_procedure = l_column = 0
  1814. if unicode in [type(x) for x in (procedure, catalog, schema,column)]:
  1815. string_p = lambda x:wchar_pointer(UCS_buf(x))
  1816. API_f = ODBC_API.SQLProcedureColumnsW
  1817. else:
  1818. string_p = ctypes.c_char_p
  1819. API_f = ODBC_API.SQLProcedureColumns
  1820. if catalog is not None:
  1821. l_catalog = len(catalog)
  1822. catalog = string_p(catalog)
  1823. if schema is not None:
  1824. l_schema = len(schema)
  1825. schema = string_p(schema)
  1826. if procedure is not None:
  1827. l_procedure = len(procedure)
  1828. procedure = string_p(procedure)
  1829. if column is not None:
  1830. l_column = len(column)
  1831. column = string_p(column)
  1832. self._free_stmt()
  1833. self._last_param_types = None
  1834. self.statement = None
  1835. ret = API_f(self.stmt_h,
  1836. catalog, l_catalog,
  1837. schema, l_schema,
  1838. procedure, l_procedure,
  1839. column, l_column)
  1840. check_success(self, ret)
  1841. self._NumOfRows()
  1842. self._UpdateDesc()
  1843. return self
  1844. def procedures(self, procedure=None, catalog=None, schema=None):
  1845. if not self.connection:
  1846. self.close()
  1847. l_catalog = l_schema = l_procedure = 0
  1848. if unicode in [type(x) for x in (procedure, catalog, schema)]:
  1849. string_p = lambda x:wchar_pointer(UCS_buf(x))
  1850. API_f = ODBC_API.SQLProceduresW
  1851. else:
  1852. string_p = ctypes.c_char_p
  1853. API_f = ODBC_API.SQLProcedures
  1854. if catalog is not None:
  1855. l_catalog = len(catalog)
  1856. catalog = string_p(catalog)
  1857. if schema is not None:
  1858. l_schema = len(schema)
  1859. schema = string_p(schema)
  1860. if procedure is not None:
  1861. l_procedure = len(procedure)
  1862. procedure = string_p(procedure)
  1863. self._free_stmt()
  1864. self._last_param_types = None
  1865. self.statement = None
  1866. ret = API_f(self.stmt_h,
  1867. catalog, l_catalog,
  1868. schema, l_schema,
  1869. procedure, l_procedure)
  1870. check_success(self, ret)
  1871. self._NumOfRows()
  1872. self._UpdateDesc()
  1873. return self
  1874. def statistics(self, table, catalog=None, schema=None, unique=False, quick=True):
  1875. if not self.connection:
  1876. self.close()
  1877. l_table = l_catalog = l_schema = 0
  1878. if unicode in [type(x) for x in (table, catalog, schema)]:
  1879. string_p = lambda x:wchar_pointer(UCS_buf(x))
  1880. API_f = ODBC_API.SQLStatisticsW
  1881. else:
  1882. string_p = ctypes.c_char_p
  1883. API_f = ODBC_API.SQLStatistics
  1884. if catalog is not None:
  1885. l_catalog = len(catalog)
  1886. catalog = string_p(catalog)
  1887. if schema is not None:
  1888. l_schema = len(schema)
  1889. schema = string_p(schema)
  1890. if table is not None:
  1891. l_table = len(table)
  1892. table = string_p(table)
  1893. if unique:
  1894. Unique = SQL_INDEX_UNIQUE
  1895. else:
  1896. Unique = SQL_INDEX_ALL
  1897. if quick:
  1898. Reserved = SQL_QUICK
  1899. else:
  1900. Reserved = SQL_ENSURE
  1901. self._free_stmt()
  1902. self._last_param_types = None
  1903. self.statement = None
  1904. ret = API_f(self.stmt_h,
  1905. catalog, l_catalog,
  1906. schema, l_schema,
  1907. table, l_table,
  1908. Unique, Reserved)
  1909. check_success(self, ret)
  1910. self._NumOfRows()
  1911. self._UpdateDesc()
  1912. #self._BindCols()
  1913. return self
  1914. def commit(self):
  1915. if not self.connection:
  1916. self.close()
  1917. self.connection.commit()
  1918. def rollback(self):
  1919. if not self.connection:
  1920. self.close()
  1921. self.connection.rollback()
  1922. def setoutputsize(self, size, column = None):
  1923. if not self.connection:
  1924. self.close()
  1925. self._outputsize[column] = size
  1926. def setinputsizes(self, sizes):
  1927. if not self.connection:
  1928. self.close()
  1929. self._inputsizers = [size for size in sizes]
  1930. def close(self):
  1931. """ Call SQLCloseCursor API to free the statement handle"""
  1932. # ret = ODBC_API.SQLCloseCursor(self.stmt_h)
  1933. # check_success(self, ret)
  1934. #
  1935. if self.connection.connected:
  1936. ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_CLOSE)
  1937. check_success(self, ret)
  1938. ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_UNBIND)
  1939. check_success(self, ret)
  1940. ret = ODBC_API.SQLFreeStmt(self.stmt_h, SQL_RESET_PARAMS)
  1941. check_success(self, ret)
  1942. ret = ODBC_API.SQLFreeHandle(SQL_HANDLE_STMT, self.stmt_h)
  1943. check_success(self, ret)
  1944. self.closed = True
  1945. def __del__(self):
  1946. if not self.closed:
  1947. self.close()
  1948. def __exit__(self, type, value, traceback):
  1949. if not self.connection:
  1950. self.close()
  1951. if value:
  1952. self.rollback()
  1953. else:
  1954. self.commit()
  1955. self.close()
  1956. def __enter__(self):
  1957. return self
  1958. # This class implement a odbc connection.
  1959. #
  1960. #
  1961. class Connection:
  1962. def __init__(self, connectString = '', autocommit = False, ansi = False, timeout = 0, unicode_results = use_unicode, readonly = False, **kargs):
  1963. """Init variables and connect to the engine"""
  1964. self.connected = 0
  1965. self.type_size_dic = {}
  1966. self.ansi = False
  1967. self.unicode_results = False
  1968. self.dbc_h = ctypes.c_void_p()
  1969. self.autocommit = autocommit
  1970. self.readonly = False
  1971. self.timeout = 0
  1972. # self._cursors = []
  1973. for key, value in list(kargs.items()):
  1974. connectString = connectString + key + '=' + value + ';'
  1975. self.connectString = connectString
  1976. self.clear_output_converters()
  1977. try:
  1978. lock.acquire()
  1979. if shared_env_h is None:
  1980. #Initialize an enviroment if it is not created.
  1981. AllocateEnv()
  1982. finally:
  1983. lock.release()
  1984. # Allocate an DBC handle self.dbc_h under the environment shared_env_h
  1985. # This DBC handle is actually the basis of a "connection"
  1986. # The handle of self.dbc_h will be used to connect to a certain source
  1987. # in the self.connect and self.ConnectByDSN method
  1988. ret = ODBC_API.SQLAllocHandle(SQL_HANDLE_DBC, shared_env_h, ADDR(self.dbc_h))
  1989. check_success(self, ret)
  1990. self.connect(connectString, autocommit, ansi, timeout, unicode_results, readonly)
  1991. def connect(self, connectString = '', autocommit = False, ansi = False, timeout = 0, unicode_results = use_unicode, readonly = False):
  1992. """Connect to odbc, using connect strings and set the connection's attributes like autocommit and timeout
  1993. by calling SQLSetConnectAttr
  1994. """
  1995. # Before we establish the connection by the connection string
  1996. # Set the connection's attribute of "timeout" (Actully LOGIN_TIMEOUT)
  1997. if timeout != 0:
  1998. self.settimeout(timeout)
  1999. ret = ODBC_API.SQLSetConnectAttr(self.dbc_h, SQL_ATTR_LOGIN_TIMEOUT, timeout, SQL_IS_UINTEGER);
  2000. check_success(self, ret)
  2001. # Create one connection with a connect string by calling SQLDriverConnect
  2002. # and make self.dbc_h the handle of this connection
  2003. # Convert the connetsytring to encoded string
  2004. # so it can be converted to a ctypes c_char array object
  2005. self.ansi = ansi
  2006. if not ansi:
  2007. c_connectString = wchar_pointer(UCS_buf(self.connectString))
  2008. odbc_func = ODBC_API.SQLDriverConnectW
  2009. else:
  2010. c_connectString = ctypes.c_char_p(self.connectString)
  2011. odbc_func = ODBC_API.SQLDriverConnect
  2012. # With unixODBC, SQLDriverConnect will intermittently fail with error:
  2013. # [01000] [unixODBC][Driver Manager]Can't open lib '/path/to/so' : file not found"
  2014. # or:
  2015. # [01000] [unixODBC][Driver Manager]Can't open lib '/path/to/so' : (null)"
  2016. # when called concurrently by more than one threads. So, we have to
  2017. # use a lock to serialize the calls. By the way, the error is much
  2018. # less likely to happen if ODBC Tracing is enabled, likely due to the
  2019. # implicit serialization caused by writing to trace file.
  2020. if ODBC_API._name != 'odbc32':
  2021. try:
  2022. lock.acquire()
  2023. ret = odbc_func(self.dbc_h, 0, c_connectString, len(self.connectString), None, 0, None, SQL_DRIVER_NOPROMPT)
  2024. finally:
  2025. lock.release()
  2026. else:
  2027. ret = odbc_func(self.dbc_h, 0, c_connectString, len(self.connectString), None, 0, None, SQL_DRIVER_NOPROMPT)
  2028. check_success(self, ret)
  2029. # Set the connection's attribute of "autocommit"
  2030. #
  2031. self.autocommit = autocommit
  2032. if self.autocommit == True:
  2033. ret = ODBC_API.SQLSetConnectAttr(self.dbc_h, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, SQL_IS_UINTEGER)
  2034. else:
  2035. ret = ODBC_API.SQLSetConnectAttr(self.dbc_h, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER)
  2036. check_success(self, ret)
  2037. # Set the connection's attribute of "readonly"
  2038. #
  2039. self.readonly = readonly
  2040. ret = ODBC_API.SQLSetConnectAttr(self.dbc_h, SQL_ATTR_ACCESS_MODE, self.readonly and SQL_MODE_READ_ONLY or SQL_MODE_READ_WRITE, SQL_IS_UINTEGER)
  2041. check_success(self, ret)
  2042. self.unicode_results = unicode_results
  2043. self.connected = 1
  2044. self.update_db_special_info()
  2045. def clear_output_converters(self):
  2046. self.output_converter = {}
  2047. for sqltype, profile in SQL_data_type_dict.items():
  2048. self.output_converter[sqltype] = profile[1]
  2049. def add_output_converter(self, sqltype, func):
  2050. self.output_converter[sqltype] = func
  2051. def settimeout(self, timeout):
  2052. ret = ODBC_API.SQLSetConnectAttr(self.dbc_h, SQL_ATTR_CONNECTION_TIMEOUT, timeout, SQL_IS_UINTEGER);
  2053. check_success(self, ret)
  2054. self.timeout = timeout
  2055. def ConnectByDSN(self, dsn, user, passwd = ''):
  2056. """Connect to odbc, we need dsn, user and optionally password"""
  2057. self.dsn = dsn
  2058. self.user = user
  2059. self.passwd = passwd
  2060. sn = create_buffer(dsn)
  2061. un = create_buffer(user)
  2062. pw = create_buffer(passwd)
  2063. ret = ODBC_API.SQLConnect(self.dbc_h, sn, len(sn), un, len(un), pw, len(pw))
  2064. check_success(self, ret)
  2065. self.update_db_special_info()
  2066. self.connected = 1
  2067. def cursor(self, row_type_callable=None):
  2068. #self.settimeout(self.timeout)
  2069. if not self.connected:
  2070. raise ProgrammingError('HY000','Attempt to use a closed connection.')
  2071. cur = Cursor(self, row_type_callable=row_type_callable)
  2072. # self._cursors.append(cur)
  2073. return cur
  2074. def update_db_special_info(self):
  2075. for sql_type in (
  2076. SQL_TYPE_TIMESTAMP,
  2077. SQL_TYPE_DATE,
  2078. SQL_TYPE_TIME,
  2079. SQL_SS_TIME2,
  2080. ):
  2081. cur = Cursor(self)
  2082. try:
  2083. info_tuple = cur.getTypeInfo(sql_type)
  2084. if info_tuple is not None:
  2085. self.type_size_dic[sql_type] = info_tuple[2], info_tuple[14]
  2086. except:
  2087. pass
  2088. cur.close()
  2089. self.support_SQLDescribeParam = False
  2090. try:
  2091. driver_name = self.getinfo(SQL_DRIVER_NAME)
  2092. if any(x in driver_name for x in ('SQLSRV','ncli','libsqlncli')):
  2093. self.support_SQLDescribeParam = True
  2094. except:
  2095. pass
  2096. def commit(self):
  2097. if not self.connected:
  2098. raise ProgrammingError('HY000','Attempt to use a closed connection.')
  2099. ret = SQLEndTran(SQL_HANDLE_DBC, self.dbc_h, SQL_COMMIT)
  2100. if ret != SQL_SUCCESS:
  2101. check_success(self, ret)
  2102. def rollback(self):
  2103. if not self.connected:
  2104. raise ProgrammingError('HY000','Attempt to use a closed connection.')
  2105. ret = SQLEndTran(SQL_HANDLE_DBC, self.dbc_h, SQL_ROLLBACK)
  2106. if ret != SQL_SUCCESS:
  2107. check_success(self, ret)
  2108. def getinfo(self,infotype):
  2109. if infotype not in list(aInfoTypes.keys()):
  2110. raise ProgrammingError('HY000','Invalid getinfo value: '+str(infotype))
  2111. if aInfoTypes[infotype] == 'GI_UINTEGER':
  2112. total_buf_len = 1000
  2113. alloc_buffer = ctypes.c_ulong()
  2114. used_buf_len = c_short()
  2115. ret = ODBC_API.SQLGetInfo(self.dbc_h,infotype,ADDR(alloc_buffer), total_buf_len,\
  2116. ADDR(used_buf_len))
  2117. check_success(self, ret)
  2118. result = alloc_buffer.value
  2119. elif aInfoTypes[infotype] == 'GI_USMALLINT':
  2120. total_buf_len = 1000
  2121. alloc_buffer = ctypes.c_ushort()
  2122. used_buf_len = c_short()
  2123. ret = ODBC_API.SQLGetInfo(self.dbc_h,infotype,ADDR(alloc_buffer), total_buf_len,\
  2124. ADDR(used_buf_len))
  2125. check_success(self, ret)
  2126. result = alloc_buffer.value
  2127. else:
  2128. total_buf_len = 1000
  2129. alloc_buffer = create_buffer(total_buf_len)
  2130. used_buf_len = c_short()
  2131. if self.ansi:
  2132. API_f = ODBC_API.SQLGetInfo
  2133. else:
  2134. API_f = ODBC_API.SQLGetInfoW
  2135. ret = API_f(self.dbc_h,infotype,ADDR(alloc_buffer), total_buf_len,\
  2136. ADDR(used_buf_len))
  2137. check_success(self, ret)
  2138. if self.ansi:
  2139. result = alloc_buffer.value
  2140. else:
  2141. result = UCS_dec(alloc_buffer)
  2142. if aInfoTypes[infotype] == 'GI_YESNO':
  2143. if unicode(result[0]) == unicode('Y'):
  2144. result = True
  2145. else:
  2146. result = False
  2147. return result
  2148. def __exit__(self, type, value, traceback):
  2149. if value:
  2150. self.rollback()
  2151. else:
  2152. self.commit()
  2153. if self.connected:
  2154. self.close()
  2155. def __enter__(self):
  2156. return self
  2157. def __del__(self):
  2158. if self.connected:
  2159. self.close()
  2160. def close(self):
  2161. if not self.connected:
  2162. raise ProgrammingError('HY000','Attempt to close a closed connection.')
  2163. # for cur in self._cursors:
  2164. # if not cur is None:
  2165. # if not cur.closed:
  2166. # cur.close()
  2167. if self.connected:
  2168. #if DEBUG:print 'disconnect'
  2169. if not self.autocommit:
  2170. self.rollback()
  2171. ret = ODBC_API.SQLDisconnect(self.dbc_h)
  2172. check_success(self, ret)
  2173. #if DEBUG:print 'free dbc'
  2174. ret = ODBC_API.SQLFreeHandle(SQL_HANDLE_DBC, self.dbc_h)
  2175. check_success(self, ret)
  2176. # if shared_env_h.value:
  2177. # #if DEBUG:print 'env'
  2178. # ret = ODBC_API.SQLFreeHandle(SQL_HANDLE_ENV, shared_env_h)
  2179. # check_success(shared_env_h, ret)
  2180. self.connected = 0
  2181. odbc = Connection
  2182. connect = odbc
  2183. '''
  2184. def connect(connectString = '', autocommit = False, ansi = False, timeout = 0, unicode_results = False, readonly = False, **kargs):
  2185. return odbc(connectString, autocommit, ansi, timeout, unicode_results, readonly, kargs)
  2186. '''
  2187. def drivers():
  2188. if sys.platform not in ('win32','cli'):
  2189. raise Exception('This function is available for use in Windows only.')
  2190. try:
  2191. lock.acquire()
  2192. if shared_env_h is None:
  2193. AllocateEnv()
  2194. finally:
  2195. lock.release()
  2196. DriverDescription = create_buffer_u(1000)
  2197. BufferLength1 = c_short(1000)
  2198. DescriptionLength = c_short()
  2199. DriverAttributes = create_buffer_u(1000)
  2200. BufferLength2 = c_short(1000)
  2201. AttributesLength = c_short()
  2202. ret = SQL_SUCCESS
  2203. DriverList = []
  2204. Direction = SQL_FETCH_FIRST
  2205. while ret != SQL_NO_DATA:
  2206. ret = ODBC_API.SQLDriversW(shared_env_h, Direction , DriverDescription , BufferLength1
  2207. , ADDR(DescriptionLength), DriverAttributes, BufferLength2, ADDR(AttributesLength))
  2208. check_success(shared_env_h, ret)
  2209. DriverList.append(DriverDescription.value)
  2210. if Direction == SQL_FETCH_FIRST:
  2211. Direction = SQL_FETCH_NEXT
  2212. return DriverList
  2213. def win_create_mdb(mdb_path, sort_order = "General\0\0"):
  2214. if sys.platform not in ('win32','cli'):
  2215. raise Exception('This function is available for use in Windows only.')
  2216. mdb_driver = [d for d in drivers() if 'Microsoft Access Driver (*.mdb' in d]
  2217. if mdb_driver == []:
  2218. raise Exception('Access Driver is not found.')
  2219. else:
  2220. driver_name = mdb_driver[0].encode('mbcs')
  2221. #CREATE_DB=<path name> <sort order>
  2222. ctypes.windll.ODBCCP32.SQLConfigDataSource.argtypes = [ctypes.c_void_p,ctypes.c_ushort,ctypes.c_char_p,ctypes.c_char_p]
  2223. if py_v3:
  2224. c_Path = bytes("CREATE_DB=" + mdb_path + " " + sort_order,'mbcs')
  2225. else:
  2226. c_Path = "CREATE_DB=" + mdb_path + " " + sort_order
  2227. ODBC_ADD_SYS_DSN = 1
  2228. ret = ctypes.windll.ODBCCP32.SQLConfigDataSource(None,ODBC_ADD_SYS_DSN,driver_name, c_Path)
  2229. if not ret:
  2230. raise Exception('Failed to create Access mdb file - "%s". Please check file path, permission and Access driver readiness.' %mdb_path)
  2231. def win_connect_mdb(mdb_path):
  2232. if sys.platform not in ('win32','cli'):
  2233. raise Exception('This function is available for use in Windows only.')
  2234. mdb_driver = [d for d in drivers() if 'Microsoft Access Driver (*.mdb' in d]
  2235. if mdb_driver == []:
  2236. raise Exception('Access Driver is not found.')
  2237. else:
  2238. driver_name = mdb_driver[0]
  2239. return connect('Driver={'+driver_name+"};DBQ="+mdb_path, unicode_results = use_unicode, readonly = False)
  2240. def win_compact_mdb(mdb_path, compacted_mdb_path, sort_order = "General\0\0"):
  2241. if sys.platform not in ('win32','cli'):
  2242. raise Exception('This function is available for use in Windows only.')
  2243. mdb_driver = [d for d in drivers() if 'Microsoft Access Driver (*.mdb' in d]
  2244. if mdb_driver == []:
  2245. raise Exception('Access Driver is not found.')
  2246. else:
  2247. driver_name = mdb_driver[0].encode('mbcs')
  2248. #COMPACT_DB=<source path> <destination path> <sort order>
  2249. ctypes.windll.ODBCCP32.SQLConfigDataSource.argtypes = [ctypes.c_void_p,ctypes.c_ushort,ctypes.c_char_p,ctypes.c_char_p]
  2250. #driver_name = "Microsoft Access Driver (*.mdb)"
  2251. if py_v3:
  2252. c_Path = bytes("COMPACT_DB=" + mdb_path + " " + compacted_mdb_path + " " + sort_order,'mbcs')
  2253. #driver_name = bytes(driver_name,'mbcs')
  2254. else:
  2255. c_Path = "COMPACT_DB=" + mdb_path + " " + compacted_mdb_path + " " + sort_order
  2256. ODBC_ADD_SYS_DSN = 1
  2257. ret = ctypes.windll.ODBCCP32.SQLConfigDataSource(None,ODBC_ADD_SYS_DSN,driver_name, c_Path)
  2258. if not ret:
  2259. raise Exception('Failed to compact Access mdb file - "%s". Please check file path, permission and Access driver readiness.' %compacted_mdb_path)
  2260. def dataSources():
  2261. """Return a list with [name, descrition]"""
  2262. dsn = create_buffer(1024)
  2263. desc = create_buffer(1024)
  2264. dsn_len = c_short()
  2265. desc_len = c_short()
  2266. dsn_list = {}
  2267. try:
  2268. lock.acquire()
  2269. if shared_env_h is None:
  2270. AllocateEnv()
  2271. finally:
  2272. lock.release()
  2273. while 1:
  2274. ret = ODBC_API.SQLDataSources(shared_env_h, SQL_FETCH_NEXT, \
  2275. dsn, len(dsn), ADDR(dsn_len), desc, len(desc), ADDR(desc_len))
  2276. if ret == SQL_NO_DATA_FOUND:
  2277. break
  2278. elif not ret in (SQL_SUCCESS, SQL_SUCCESS_WITH_INFO):
  2279. ctrl_err(SQL_HANDLE_ENV, shared_env_h, ret)
  2280. else:
  2281. dsn_list[dsn.value] = desc.value
  2282. return dsn_list
  2283. def monkey_patch_for_gevent():
  2284. import functools, gevent
  2285. apply_e = gevent.get_hub().threadpool.apply_e
  2286. def monkey_patch(func):
  2287. @functools.wraps(func)
  2288. def wrap(*args, **kwargs):
  2289. #if DEBUG:print('%s called with %s %s' % (func, args, kwargs))
  2290. return apply_e(Exception, func, args, kwargs)
  2291. return wrap
  2292. for attr in dir(ODBC_API):
  2293. if attr.startswith('SQL') and hasattr(getattr(ODBC_API, attr), 'argtypes'):
  2294. setattr(ODBC_API, attr, monkey_patch(getattr(ODBC_API, attr)))