PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/mysql-workbench-gpl-5.2.40-src/ext/connector-python/python3/mysql/connector/conversion.py

#
Python | 410 lines | 311 code | 29 blank | 70 comment | 9 complexity | f02b3677bce0502cb1de15878af81a46 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, BSD-3-Clause-No-Nuclear-License-2014, BSD-3-Clause
  1. # MySQL Connector/Python - MySQL driver written in Python.
  2. # Copyright (c) 2009,2010, Oracle and/or its affiliates. All rights reserved.
  3. # Use is subject to license terms. (See COPYING)
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation.
  7. #
  8. # There are special exceptions to the terms and conditions of the GNU
  9. # General Public License as it is applied to this software. View the
  10. # full text of the exception in file EXCEPTIONS-CLIENT in the directory
  11. # of this software distribution or see the FOSS License Exception at
  12. # www.mysql.com.
  13. #
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. # GNU General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License
  20. # along with this program; if not, write to the Free Software
  21. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. """Converting MySQL and Python types
  23. """
  24. import struct
  25. import datetime
  26. import time
  27. from decimal import Decimal
  28. from . import errors
  29. from .constants import FieldType, FieldFlag
  30. class ConverterBase(object):
  31. def __init__(self, charset='utf8', use_unicode=True):
  32. self.python_types = None
  33. self.mysql_types = None
  34. self.set_charset(charset)
  35. self.set_unicode(use_unicode)
  36. def set_charset(self, charset):
  37. if charset is not None:
  38. self.charset = charset
  39. else:
  40. # default to utf8
  41. self.charset = 'utf8'
  42. def set_unicode(self, value=True):
  43. self.use_unicode = value
  44. def to_mysql(self, value):
  45. return value
  46. def to_python(self, vtype, value):
  47. return value
  48. def escape(self, buf):
  49. return buf
  50. def quote(self, buf):
  51. return str(buf)
  52. class MySQLConverter(ConverterBase):
  53. """
  54. A converted class grouping:
  55. o escape method: for escpaing values send to MySQL
  56. o quoting method: for quoting values send to MySQL in statements
  57. o conversion mapping: maps Python and MySQL data types to
  58. function for converting them.
  59. This class should be overloaded whenever one needs differences
  60. in how values are to be converted. Each MySQLConnection object
  61. has a default_converter property, which can be set like
  62. MySQL.converter(CustomMySQLConverter)
  63. """
  64. def __init__(self, charset=None, use_unicode=True):
  65. ConverterBase.__init__(self, charset, use_unicode)
  66. self.python_types = {
  67. int : int,
  68. float : float,
  69. str : self._str_to_mysql,
  70. bytes: self._bytes_to_mysql,
  71. bool : self._bool_to_mysql,
  72. type(None) : self._none_to_mysql,
  73. datetime.datetime : self._datetime_to_mysql,
  74. datetime.date : self._date_to_mysql,
  75. datetime.time : self._time_to_mysql,
  76. time.struct_time : self._struct_time_to_mysql,
  77. datetime.timedelta : self._timedelta_to_mysql,
  78. Decimal : self._decimal_to_mysql,
  79. }
  80. self.mysql_types = {
  81. FieldType.TINY : self._int,
  82. FieldType.SHORT : self._int,
  83. FieldType.INT24 : self._int,
  84. FieldType.LONG : self._long,
  85. FieldType.LONGLONG : self._long,
  86. FieldType.FLOAT : self._float,
  87. FieldType.DOUBLE : self._float,
  88. FieldType.DECIMAL : self._decimal,
  89. FieldType.NEWDECIMAL : self._decimal,
  90. FieldType.VAR_STRING : self._STRING_to_python,
  91. FieldType.STRING : self._STRING_to_python,
  92. FieldType.SET : self._SET_to_python,
  93. FieldType.TIME : self._TIME_to_python,
  94. FieldType.DATE : self._DATE_to_python,
  95. FieldType.NEWDATE : self._DATE_to_python,
  96. FieldType.DATETIME : self._DATETIME_to_python,
  97. FieldType.TIMESTAMP : self._DATETIME_to_python,
  98. FieldType.BLOB : self._STRING_to_python,
  99. FieldType.YEAR: self._YEAR_to_python,
  100. FieldType.BIT: self._BIT_to_python,
  101. }
  102. def escape(self, value):
  103. """
  104. Escapes special characters as they are expected to by when MySQL
  105. receives them.
  106. As found in MySQL source mysys/charset.c
  107. Returns the value if not a string, or the escaped string.
  108. """
  109. if value is None:
  110. return value
  111. elif isinstance(value, (int,float,Decimal)):
  112. return value
  113. res = value
  114. res = res.replace('\\','\\\\')
  115. res = res.replace('\n','\\n')
  116. res = res.replace('\r','\\r')
  117. res = res.replace('\047','\134\047') # single quotes
  118. res = res.replace('\042','\134\042') # double quotes
  119. res = res.replace('\032','\134\032') # for Win32
  120. return res
  121. def quote(self, buf):
  122. """
  123. Quote the parameters for commands. General rules:
  124. o numbers are returns as str type (because operation expect it)
  125. o None is returned as str('NULL')
  126. o String are quoted with single quotes '<string>'
  127. Returns a string.
  128. """
  129. if isinstance(buf, (int,float,Decimal)):
  130. return str(buf)
  131. elif isinstance(buf, type(None)):
  132. return "NULL"
  133. else:
  134. # Anything else would be a string
  135. return "'%s'" % buf
  136. def to_mysql(self, value):
  137. vtype = type(value)
  138. return self.python_types[vtype](value)
  139. def _str_to_mysql(self, value):
  140. return value
  141. def _bytes_to_mysql(self, value):
  142. return value.decode(self.charset)
  143. def _bool_to_mysql(self, value):
  144. if value:
  145. return 1
  146. else:
  147. return 0
  148. def _none_to_mysql(self, value):
  149. """
  150. This would return what None would be in MySQL, but instead we
  151. leave it None and return it right away. The actual convertion
  152. from None to NULL happens in the quoting functionality.
  153. Return None.
  154. """
  155. return None
  156. def _datetime_to_mysql(self, value):
  157. """
  158. Converts a datetime instance to a string suitable for MySQL.
  159. The returned string has format: %Y-%m-%d %H:%M:%S
  160. If the instance isn't a datetime.datetime type, it return None.
  161. Returns a string.
  162. """
  163. return '%d-%02d-%02d %02d:%02d:%02d' % (
  164. value.year, value.month, value.day,
  165. value.hour, value.minute, value.second)
  166. def _date_to_mysql(self, value):
  167. """
  168. Converts a date instance to a string suitable for MySQL.
  169. The returned string has format: %Y-%m-%d
  170. If the instance isn't a datetime.date type, it return None.
  171. Returns a string.
  172. """
  173. return '%d-%02d-%02d' % (value.year, value.month, value.day)
  174. def _time_to_mysql(self, value):
  175. """
  176. Converts a time instance to a string suitable for MySQL.
  177. The returned string has format: %H:%M:%S
  178. If the instance isn't a datetime.time type, it return None.
  179. Returns a string.
  180. """
  181. return value.strftime('%H:%M:%S')
  182. def _struct_time_to_mysql(self, value):
  183. """
  184. Converts a time.struct_time sequence to a string suitable
  185. for MySQL.
  186. The returned string has format: %Y-%m-%d %H:%M:%S
  187. Returns a string or None when not valid.
  188. """
  189. return time.strftime('%Y-%m-%d %H:%M:%S',value)
  190. def _timedelta_to_mysql(self, value):
  191. """
  192. Converts a timedelta instance to a string suitable for MySQL.
  193. The returned string has format: %H:%M:%S
  194. Returns a string.
  195. """
  196. (hours, r) = divmod(value.seconds, 3600)
  197. (mins, secs) = divmod(r, 60)
  198. hours = hours + (value.days * 24)
  199. return '%02d:%02d:%02d' % (hours,mins,secs)
  200. def _decimal_to_mysql(self, value):
  201. """
  202. Converts a decimal.Decimal instance to a string suitable for
  203. MySQL.
  204. Returns a string or None when not valid.
  205. """
  206. if isinstance(value, Decimal):
  207. return str(value)
  208. return None
  209. def to_python(self, flddsc, value):
  210. """
  211. Converts a given value coming from MySQL to a certain type in Python.
  212. The flddsc contains additional information for the field in the
  213. table. It's an element from MySQLCursor.description.
  214. Returns a mixed value.
  215. """
  216. res = value
  217. if value == 0 and flddsc[1] != FieldType.BIT: # \x00
  218. # Don't go further when we hit a NULL value
  219. return None
  220. if value is None:
  221. return None
  222. try:
  223. res = self.mysql_types[flddsc[1]](value, flddsc)
  224. except KeyError:
  225. # If one type is not defined, we just return the value as str
  226. return value.decode('utf-8')
  227. except ValueError as e:
  228. raise ValueError("%s (field %s)" % (e, flddsc[0]))
  229. except TypeError as e:
  230. raise TypeError("%s (field %s)" % (e, flddsc[0]))
  231. except:
  232. raise
  233. return res
  234. def _float(self, v, desc=None):
  235. """
  236. Returns v as float type.
  237. """
  238. return float(v)
  239. def _int(self, v, desc=None):
  240. """
  241. Returns v as int type.
  242. """
  243. return int(v)
  244. def _long(self, v, desc=None):
  245. """
  246. Returns v as long type.
  247. """
  248. return int(v)
  249. def _decimal(self, v, desc=None):
  250. """
  251. Returns v as a decimal.Decimal.
  252. """
  253. s = v.decode(self.charset)
  254. return Decimal(s)
  255. def _str(self, v, desc=None):
  256. """
  257. Returns v as str type.
  258. """
  259. return str(v)
  260. def _BIT_to_python(self, v, dsc=None):
  261. """Returns BIT columntype as integer"""
  262. s = v
  263. if len(s) < 8:
  264. s = b'\x00'*(8-len(s)) + s
  265. return struct.unpack('>Q', s)[0]
  266. def _DATE_to_python(self, v, dsc=None):
  267. """
  268. Returns DATE column type as datetime.date type.
  269. """
  270. pv = None
  271. try:
  272. pv = datetime.date(*[ int(s) for s in v.split(b'-')])
  273. except ValueError:
  274. return None
  275. else:
  276. return pv
  277. def _TIME_to_python(self, v, dsc=None):
  278. """
  279. Returns TIME column type as datetime.time type.
  280. """
  281. pv = None
  282. try:
  283. (h, m, s) = [ int(s) for s in v.split(b':')]
  284. pv = datetime.timedelta(hours=h,minutes=m,seconds=s)
  285. except ValueError:
  286. raise ValueError("Could not convert %s to python datetime.timedelta" % v)
  287. else:
  288. return pv
  289. def _DATETIME_to_python(self, v, dsc=None):
  290. """
  291. Returns DATETIME column type as datetime.datetime type.
  292. """
  293. pv = None
  294. try:
  295. (sd,st) = v.split(b' ')
  296. dt = [ int(v) for v in sd.split(b'-') ] +\
  297. [ int(v) for v in st.split(b':') ]
  298. pv = datetime.datetime(*dt)
  299. except ValueError:
  300. pv = None
  301. return pv
  302. def _YEAR_to_python(self, v, desc=None):
  303. """Returns YEAR column type as integer"""
  304. try:
  305. year = int(v)
  306. except ValueError:
  307. raise ValueError("Failed converting YEAR to int (%s)" % v)
  308. return year
  309. def _SET_to_python(self, v, dsc=None):
  310. """Returns SET column typs as set
  311. Actually, MySQL protocol sees a SET as a string type field. So this
  312. code isn't called directly, but used by STRING_to_python() method.
  313. Returns SET column type as a set.
  314. """
  315. pv = None
  316. s = v.decode(self.charset)
  317. try:
  318. pv = set(s.split(','))
  319. except ValueError:
  320. raise ValueError("Could not convert set %s to a sequence." % v)
  321. return pv
  322. def _STRING_to_python(self, v, dsc=None):
  323. """
  324. Note that a SET is a string too, but using the FieldFlag we can see
  325. whether we have to split it.
  326. Returns string typed columns as string type.
  327. """
  328. if dsc is not None:
  329. # Check if we deal with a SET
  330. if dsc[7] & FieldFlag.SET:
  331. return self._SET_to_python(v, dsc)
  332. if dsc[7] & FieldFlag.BINARY:
  333. return v
  334. if isinstance(v, bytes) and self.use_unicode:
  335. return v.decode(self.charset)
  336. return v
  337. def _BLOB_to_python(self, v, dsc=None):
  338. if dsc is not None:
  339. if dsc[7] & FieldFlag.BINARY:
  340. return bytes(v)
  341. return self._STRING_to_python(v, dsc)