zxjdbc.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. # mysql/zxjdbc.py
  2. # Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: http://www.opensource.org/licenses/mit-license.php
  7. """
  8. .. dialect:: mysql+zxjdbc
  9. :name: zxjdbc for Jython
  10. :dbapi: zxjdbc
  11. :connectstring: mysql+zxjdbc://<user>:<password>@<hostname>[:<port>]/\
  12. <database>
  13. :driverurl: http://dev.mysql.com/downloads/connector/j/
  14. .. note:: Jython is not supported by current versions of SQLAlchemy. The
  15. zxjdbc dialect should be considered as experimental.
  16. Character Sets
  17. --------------
  18. SQLAlchemy zxjdbc dialects pass unicode straight through to the
  19. zxjdbc/JDBC layer. To allow multiple character sets to be sent from the
  20. MySQL Connector/J JDBC driver, by default SQLAlchemy sets its
  21. ``characterEncoding`` connection property to ``UTF-8``. It may be
  22. overridden via a ``create_engine`` URL parameter.
  23. """
  24. import re
  25. from ... import types as sqltypes, util
  26. from ...connectors.zxJDBC import ZxJDBCConnector
  27. from .base import BIT, MySQLDialect, MySQLExecutionContext
  28. class _ZxJDBCBit(BIT):
  29. def result_processor(self, dialect, coltype):
  30. """Converts boolean or byte arrays from MySQL Connector/J to longs."""
  31. def process(value):
  32. if value is None:
  33. return value
  34. if isinstance(value, bool):
  35. return int(value)
  36. v = 0
  37. for i in value:
  38. v = v << 8 | (i & 0xff)
  39. value = v
  40. return value
  41. return process
  42. class MySQLExecutionContext_zxjdbc(MySQLExecutionContext):
  43. def get_lastrowid(self):
  44. cursor = self.create_cursor()
  45. cursor.execute("SELECT LAST_INSERT_ID()")
  46. lastrowid = cursor.fetchone()[0]
  47. cursor.close()
  48. return lastrowid
  49. class MySQLDialect_zxjdbc(ZxJDBCConnector, MySQLDialect):
  50. jdbc_db_name = 'mysql'
  51. jdbc_driver_name = 'com.mysql.jdbc.Driver'
  52. execution_ctx_cls = MySQLExecutionContext_zxjdbc
  53. colspecs = util.update_copy(
  54. MySQLDialect.colspecs,
  55. {
  56. sqltypes.Time: sqltypes.Time,
  57. BIT: _ZxJDBCBit
  58. }
  59. )
  60. def _detect_charset(self, connection):
  61. """Sniff out the character set in use for connection results."""
  62. # Prefer 'character_set_results' for the current connection over the
  63. # value in the driver. SET NAMES or individual variable SETs will
  64. # change the charset without updating the driver's view of the world.
  65. #
  66. # If it's decided that issuing that sort of SQL leaves you SOL, then
  67. # this can prefer the driver value.
  68. rs = connection.execute("SHOW VARIABLES LIKE 'character_set%%'")
  69. opts = dict((row[0], row[1]) for row in self._compat_fetchall(rs))
  70. for key in ('character_set_connection', 'character_set'):
  71. if opts.get(key, None):
  72. return opts[key]
  73. util.warn("Could not detect the connection character set. "
  74. "Assuming latin1.")
  75. return 'latin1'
  76. def _driver_kwargs(self):
  77. """return kw arg dict to be sent to connect()."""
  78. return dict(characterEncoding='UTF-8', yearIsDateType='false')
  79. def _extract_error_code(self, exception):
  80. # e.g.: DBAPIError: (Error) Table 'test.u2' doesn't exist
  81. # [SQLCode: 1146], [SQLState: 42S02] 'DESCRIBE `u2`' ()
  82. m = re.compile(r"\[SQLCode\: (\d+)\]").search(str(exception.args))
  83. c = m.group(1)
  84. if c:
  85. return int(c)
  86. def _get_server_version_info(self, connection):
  87. dbapi_con = connection.connection
  88. version = []
  89. r = re.compile(r'[.\-]')
  90. for n in r.split(dbapi_con.dbversion):
  91. try:
  92. version.append(int(n))
  93. except ValueError:
  94. version.append(n)
  95. return tuple(version)
  96. dialect = MySQLDialect_zxjdbc