From: Jason Kirtland Date: Tue, 16 Oct 2007 23:59:05 +0000 (+0000) Subject: - Added support for UPDATE with LIMIT on mysql. X-Git-Tag: rel_0_4_0~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5154d304181ec7f2203e9c02db3c7d41dafc79b5;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - Added support for UPDATE with LIMIT on mysql. - Added mysql dialect tests for SET columns and the in_ operator. --- diff --git a/CHANGES b/CHANGES index d40df7be6c..40825634ed 100644 --- a/CHANGES +++ b/CHANGES @@ -63,6 +63,8 @@ CHANGES - fixed sqlite reflection of BOOL/BOOLEAN [ticket:808] +- Added support for UPDATE with LIMIT on mysql. + - null foreign key on a m2o doesn't trigger a lazyload [ticket:803] - oracle does not implicitly convert to unicode for non-typed result diff --git a/lib/sqlalchemy/databases/mysql.py b/lib/sqlalchemy/databases/mysql.py index 50923fe926..66b62c215e 100644 --- a/lib/sqlalchemy/databases/mysql.py +++ b/lib/sqlalchemy/databases/mysql.py @@ -117,10 +117,30 @@ mapping to Python classes. If you're using these types and have opinions about how OpenGIS can be smartly integrated into SQLAlchemy please join the mailing list! +Many of the MySQL SQL extensions are handled through SQLAlchemy's generic +function and operator support:: + + table.select(table.c.password==func.md5('plaintext')) + table.select(table.c.username.op('regexp')('^[a-d]')) + +And of course any valid statement can be executed as a string rather than +through the SQL expression language. + +Some limited support for MySQL extensions to SQL expressions is currently +available. + + * SELECT pragma:: + + select(..., prefixes=['HIGH_PRIORITY', 'SQL_SMALL_RESULT']) + + * UPDATE with LIMIT:: + + update(..., mysql_limit=10) + If you have problems that seem server related, first check that you are using the most recent stable MySQL-Python package available. The Database -Notes page on the wiki at http://sqlalchemy.org is a good resource for timely -information affecting MySQL in SQLAlchemy. +Notes page on the wiki at http://www.sqlalchemy.org is a good resource for +timely information affecting MySQL in SQLAlchemy. """ import re, datetime, inspect, warnings, sys @@ -1834,6 +1854,24 @@ class MySQLCompiler(compiler.DefaultCompiler): # No offset provided, so just use the limit return ' \n LIMIT %s' % (limit,) + def visit_update(self, update_stmt): + self.stack.append({'from':util.Set([update_stmt.table])}) + + self.isupdate = True + colparams = self._get_colparams(update_stmt) + + text = "UPDATE " + self.preparer.format_table(update_stmt.table) + " SET " + ', '.join(["%s=%s" % (self.preparer.format_column(c[0]), c[1]) for c in colparams]) + + if update_stmt._whereclause: + text += " WHERE " + self.process(update_stmt._whereclause) + + limit = update_stmt.kwargs.get('mysql_limit', None) + if limit: + text += " LIMIT %s" % limit + + self.stack.pop(-1) + + return text # ug. "InnoDB needs indexes on foreign keys and referenced keys [...]. # Starting with MySQL 4.1.2, these indexes are created automatically. diff --git a/test/dialect/mysql.py b/test/dialect/mysql.py index 92d93b8d53..d43f5cd169 100644 --- a/test/dialect/mysql.py +++ b/test/dialect/mysql.py @@ -496,6 +496,17 @@ class TypesTest(AssertMixin): roundtrip([1, 1, 1], [set(['dq']), set(['a']), set(['5'])]) roundtrip([set(['dq', 'sq']), None, set(['9', '5', '7'])]) + + set_table.insert().execute({'s3':set(['5'])}, + {'s3':set(['5', '7'])}, + {'s3':set(['5', '7', '9'])}, + {'s3':set(['7', '9'])}) + rows = list(select( + [set_table.c.s3], + set_table.c.s3.in_([set(['5']), set(['5', '7'])])).execute()) + found = set([frozenset(row[0]) for row in rows]) + self.assertEquals(found, + set([frozenset(['5']), frozenset(['5', '7'])])) finally: meta.drop_all() @@ -783,6 +794,26 @@ class SQLTest(SQLCompileTest): "SELECT t.col1, t.col2 FROM t LIMIT 10, 18446744073709551615" ) + @testing.supported('mysql') + def test_update_limit(self): + t = sql.table('t', sql.column('col1'), sql.column('col2')) + + self.assert_compile( + t.update(values={'col1':123}), + "UPDATE t SET col1=%s" + ) + self.assert_compile( + t.update(values={'col1':123}, mysql_limit=5), + "UPDATE t SET col1=%s LIMIT 5" + ) + self.assert_compile( + t.update(values={'col1':123}, mysql_limit=None), + "UPDATE t SET col1=%s" + ) + self.assert_compile( + t.update(t.c.col2==456, values={'col1':123}, mysql_limit=1), + "UPDATE t SET col1=%s WHERE t.col2 = %s LIMIT 1" + ) def colspec(c): return testbase.db.dialect.schemagenerator(testbase.db.dialect,