Update sqlalchemy

This commit is contained in:
Ruud
2012-05-05 01:13:50 +02:00
parent dcaca7294c
commit 710c2aa05f
38 changed files with 2292 additions and 1025 deletions
+101 -15
View File
@@ -84,6 +84,23 @@ all lower case both within SQLAlchemy as well as on the MySQL
database itself, especially if database reflection features are
to be used.
Transaction Isolation Level
---------------------------
:func:`.create_engine` accepts an ``isolation_level``
parameter which results in the command ``SET SESSION
TRANSACTION ISOLATION LEVEL <level>`` being invoked for
every new connection. Valid values for this parameter are
``READ COMMITTED``, ``READ UNCOMMITTED``,
``REPEATABLE READ``, and ``SERIALIZABLE``::
engine = create_engine(
"mysql://scott:tiger@localhost/test",
isolation_level="READ UNCOMMITTED"
)
(new in 0.7.6)
Keys
----
@@ -221,8 +238,29 @@ simply passed through to the underlying CREATE INDEX command, so it *must* be
an integer. MySQL only allows a length for an index if it is for a CHAR,
VARCHAR, TEXT, BINARY, VARBINARY and BLOB.
Index Types
~~~~~~~~~~~~~
Some MySQL storage engines permit you to specify an index type when creating
an index or primary key constraint. SQLAlchemy provides this feature via the
``mysql_using`` parameter on :class:`.Index`::
Index('my_index', my_table.c.data, mysql_using='hash')
As well as the ``mysql_using`` parameter on :class:`.PrimaryKeyConstraint`::
PrimaryKeyConstraint("data", mysql_using='hash')
The value passed to the keyword argument will be simply passed through to the
underlying CREATE INDEX or PRIMARY KEY clause, so it *must* be a valid index
type for your MySQL storage engine.
More information can be found at:
http://dev.mysql.com/doc/refman/5.0/en/create-index.html
http://dev.mysql.com/doc/refman/5.0/en/create-table.html
"""
import datetime, inspect, re, sys
@@ -1331,7 +1369,8 @@ class MySQLCompiler(compiler.SQLCompiler):
return ', '.join(t._compiler_dispatch(self, asfrom=True, **kw)
for t in [from_table] + list(extra_froms))
def update_from_clause(self, update_stmt, from_table, extra_froms, **kw):
def update_from_clause(self, update_stmt, from_table,
extra_froms, from_hints, **kw):
return None
@@ -1421,35 +1460,50 @@ class MySQLDDLCompiler(compiler.DDLCompiler):
table_opts.append(joiner.join((opt, arg)))
return ' '.join(table_opts)
def visit_create_index(self, create):
index = create.element
preparer = self.preparer
table = preparer.format_table(index.table)
columns = [preparer.quote(c.name, c.quote) for c in index.columns]
name = preparer.quote(
self._index_identifier(index.name),
index.quote)
text = "CREATE "
if index.unique:
text += "UNIQUE "
text += "INDEX %s ON %s " \
% (preparer.quote(self._index_identifier(index.name),
index.quote),preparer.format_table(index.table))
text += "INDEX %s ON %s " % (name, table)
columns = ', '.join(columns)
if 'mysql_length' in index.kwargs:
length = index.kwargs['mysql_length']
text += "(%s(%d))" % (columns, length)
else:
length = None
if length is not None:
text+= "(%s(%d))" \
% (', '.join(preparer.quote(c.name, c.quote)
for c in index.columns), length)
else:
text+= "(%s)" \
% (', '.join(preparer.quote(c.name, c.quote)
for c in index.columns))
text += "(%s)" % (columns)
if 'mysql_using' in index.kwargs:
using = index.kwargs['mysql_using']
text += " USING %s" % (preparer.quote(using, index.quote))
return text
def visit_primary_key_constraint(self, constraint):
text = super(MySQLDDLCompiler, self).\
visit_primary_key_constraint(constraint)
if "mysql_using" in constraint.kwargs:
using = constraint.kwargs['mysql_using']
text += " USING %s" % (
self.preparer.quote(using, constraint.quote))
return text
def visit_drop_index(self, drop):
index = drop.element
return "\nDROP INDEX %s ON %s" % \
(self.preparer.quote(self._index_identifier(index.name), index.quote),
(self.preparer.quote(
self._index_identifier(index.name), index.quote
),
self.preparer.format_table(index.table))
def visit_drop_constraint(self, drop):
@@ -1768,8 +1822,40 @@ class MySQLDialect(default.DefaultDialect):
_backslash_escapes = True
_server_ansiquotes = False
def __init__(self, use_ansiquotes=None, **kwargs):
def __init__(self, use_ansiquotes=None, isolation_level=None, **kwargs):
default.DefaultDialect.__init__(self, **kwargs)
self.isolation_level = isolation_level
def on_connect(self):
if self.isolation_level is not None:
def connect(conn):
self.set_isolation_level(conn, self.isolation_level)
return connect
else:
return None
_isolation_lookup = set(['SERIALIZABLE',
'READ UNCOMMITTED', 'READ COMMITTED', 'REPEATABLE READ'])
def set_isolation_level(self, connection, level):
level = level.replace('_', ' ')
if level not in self._isolation_lookup:
raise exc.ArgumentError(
"Invalid value '%s' for isolation_level. "
"Valid isolation levels for %s are %s" %
(level, self.name, ", ".join(self._isolation_lookup))
)
cursor = connection.cursor()
cursor.execute("SET SESSION TRANSACTION ISOLATION LEVEL %s" % level)
cursor.execute("COMMIT")
cursor.close()
def get_isolation_level(self, connection):
cursor = connection.cursor()
cursor.execute('SELECT @@tx_isolation')
val = cursor.fetchone()[0]
cursor.close()
return val.upper().replace("-", " ")
def do_commit(self, connection):
"""Execute a COMMIT."""