From d3e6ccc62555688bced7d4eb463718b30db7c706 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 30 Jan 2008 21:08:11 +0000 Subject: [PATCH] - Oracle and others properly encode SQL used for defaults like sequences, etc., even if no unicode idents are used since identifier preparer may return a cached unicode identifier. --- CHANGES | 7 ++++++- lib/sqlalchemy/databases/postgres.py | 2 +- lib/sqlalchemy/engine/base.py | 2 ++ test/sql/unicode.py | 23 ++++++++++++++++++++++- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 1175065fd0..01f04acd75 100644 --- a/CHANGES +++ b/CHANGES @@ -30,7 +30,12 @@ CHANGES up their ".c." collection based on the names present in the first selectable only; corresponding_column() now works fully for all embedded selectables. - + + - Oracle and others properly encode SQL used for defaults + like sequences, etc., even if no unicode idents are used + since identifier preparer may return a cached unicode + identifier. + - orm - Every Session.begin() must now be accompanied by a corresponding commit() or rollback() unless the session diff --git a/lib/sqlalchemy/databases/postgres.py b/lib/sqlalchemy/databases/postgres.py index 220c2a487a..578ef48d0b 100644 --- a/lib/sqlalchemy/databases/postgres.py +++ b/lib/sqlalchemy/databases/postgres.py @@ -760,7 +760,7 @@ class PGDefaultRunner(base.DefaultRunner): def visit_sequence(self, seq): if not seq.optional: - return self.execute_string(("select nextval('%s')" % self.dialect.identifier_preparer.format_sequence(seq)).encode(self.dialect.encoding)) + return self.execute_string(("select nextval('%s')" % self.dialect.identifier_preparer.format_sequence(seq))) else: return None diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 7692174543..61755013b0 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -1814,6 +1814,8 @@ class DefaultRunner(schema.SchemaVisitor): """execute a string statement, using the raw cursor, and return a scalar result.""" conn = self.context._connection + if not self.dialect.supports_unicode_statements: + stmt = stmt.encode(self.dialect.encoding) conn._cursor_execute(self.context.cursor, stmt, params) return self.context.cursor.fetchone()[0] diff --git a/test/sql/unicode.py b/test/sql/unicode.py index 9f352fd09a..81b33865bc 100644 --- a/test/sql/unicode.py +++ b/test/sql/unicode.py @@ -5,7 +5,7 @@ import testenv; testenv.configure_for_tests() from sqlalchemy import * from testlib import * from testlib.engines import utf8_engine - +from sqlalchemy.sql import column class UnicodeSchemaTest(PersistTest): @testing.unsupported('maxdb', 'oracle', 'sybase') @@ -112,6 +112,27 @@ class UnicodeSchemaTest(PersistTest): meta.drop_all() metadata.create_all() + @testing.fails_on_everything_except('postgres', 'firebird', 'oracle') + def test_default_exec(self): + t1 = Table('t1', metadata, + Column(u'special_col', Integer, Sequence('special_col'), primary_key=True)) + t1.create() + + try: + engine = metadata.bind + + # reset the identifier preparer, so that we can force it to cache + # a unicode identifier + engine.dialect.identifier_preparer = engine.dialect.preparer(engine.dialect) + select([column(u'special_col')]).select_from(t1).execute() + assert isinstance(engine.dialect.identifier_preparer.format_sequence(Sequence('special_col')), unicode) + + # now execute, run the sequence. it should run in u"Special_col.nextid" or similar as + # a unicode object; cx_oracle asserts that this is None or a String (postgres lets it pass thru). + # ensure that base.DefaultRunner is encoding. + t1.insert().execute() + finally: + t1.drop() if __name__ == '__main__': -- 2.47.3