]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Oracle assembles the correct columns in the result set
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 19 Jan 2008 20:11:29 +0000 (20:11 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 19 Jan 2008 20:11:29 +0000 (20:11 +0000)
  column mapping when generating a LIMIT/OFFSET subquery,
  allows columns to map properly to result sets even
  if long-name truncation kicks in [ticket:941]

CHANGES
lib/sqlalchemy/databases/oracle.py
lib/sqlalchemy/sql/compiler.py
test/dialect/oracle.py
test/sql/labels.py

diff --git a/CHANGES b/CHANGES
index 7087bcc84a300529e55dfabf69eab903be195c84..5d2d83375428473915dee32fad389d329036da8a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -84,6 +84,11 @@ CHANGES
     - reflect the sequence associated to a PK field (tipically
       with a BEFORE INSERT trigger) under Firebird
 
+    - Oracle assembles the correct columns in the result set
+      column mapping when generating a LIMIT/OFFSET subquery,
+      allows columns to map properly to result sets even
+      if long-name truncation kicks in [ticket:941]
+
 0.4.2p3
 ------
 - general
index c7ab134417496598fd2bb5ea738ffb38b1e6964e..55bdf74b1ff7fb3c4272bbd4ad02476003a2c9b8 100644 (file)
@@ -675,7 +675,7 @@ class OracleCompiler(compiler.DefaultCompiler):
                     limitselect.append_whereclause("ora_rn<=%d" % (select._limit + select._offset))
             else:
                 limitselect.append_whereclause("ora_rn<=%d" % select._limit)
-            return self.process(limitselect, **kwargs)
+            return self.process(limitselect, iswrapper=True, **kwargs)
         else:
             return compiler.DefaultCompiler.visit_select(self, select, **kwargs)
 
index 666a38d397c8ae69122e32fcf57d798460d5cd25..71bfd17658f8cc2ea4618dd01b931b27e9104f9b 100644 (file)
@@ -468,13 +468,20 @@ class DefaultCompiler(engine.Compiled):
         else:
             return column
 
-    def visit_select(self, select, asfrom=False, parens=True, **kwargs):
+    def visit_select(self, select, asfrom=False, parens=True, iswrapper=False, **kwargs):
 
         stack_entry = {'select':select}
-        
-        if asfrom or (self.stack and 'select' in self.stack[-1]):
+        prev_entry = self.stack and self.stack[-1] or None
+
+        if asfrom or (prev_entry and 'select' in prev_entry):
             stack_entry['is_subquery'] = True
+            if prev_entry and 'iswrapper' in prev_entry:
+                column_clause_args = {'result_map':self.result_map}
+            else:
+                column_clause_args = {}
+        elif iswrapper:
             column_clause_args = {}
+            stack_entry['iswrapper'] = True
         else:
             column_clause_args = {'result_map':self.result_map}
             
index cc171af5f9d382f68e32434aab393c7856a5e466..9436d1915a6ad630e425ffaf5c7d311e75de8cd3 100644 (file)
@@ -41,12 +41,21 @@ class CompileTest(SQLCompileTest):
     def test_limit(self):
         t = table('sometable', column('col1'), column('col2'))
 
+        s = select([t])
+        c = s.compile(dialect=oracle.OracleDialect())
+        assert t.c.col1 in set(c.result_map['col1'][1])
+        
         s = select([t]).limit(10).offset(20)
 
         self.assert_compile(s, "SELECT col1, col2 FROM (SELECT sometable.col1 AS col1, sometable.col2 AS col2, "
             "ROW_NUMBER() OVER (ORDER BY sometable.rowid) AS ora_rn FROM sometable) WHERE ora_rn>20 AND ora_rn<=30"
         )
 
+        # assert that despite the subquery, the columns from the table,
+        # not the select, get put into the "result_map"
+        c = s.compile(dialect=oracle.OracleDialect())
+        assert t.c.col1 in set(c.result_map['col1'][1])
+        
         s = select([s.c.col1, s.c.col2])
 
         self.assert_compile(s, "SELECT col1, col2 FROM (SELECT col1, col2 FROM (SELECT sometable.col1 AS col1, "
index 3d4f0adde5f84a5c493a806e861c1e3bd33b4784..8164d7f7787dc4f803696bb2cfb9fc5f5e9286cb 100644 (file)
@@ -44,7 +44,8 @@ class LongLabelsTest(SQLCompileTest):
         table1.insert().execute(**{"this_is_the_primarykey_column":3, "this_is_the_data_column":"data3"})
         table1.insert().execute(**{"this_is_the_primarykey_column":4, "this_is_the_data_column":"data4"})
 
-        r = table1.select(use_labels=True, order_by=[table1.c.this_is_the_primarykey_column]).execute()
+        s = table1.select(use_labels=True, order_by=[table1.c.this_is_the_primarykey_column])
+        r = s.execute()
         result = []
         for row in r:
             result.append((row[table1.c.this_is_the_primarykey_column], row[table1.c.this_is_the_data_column]))
@@ -55,6 +56,28 @@ class LongLabelsTest(SQLCompileTest):
             (4, "data4"),
         ], repr(result)
 
+        # some dialects such as oracle (and possibly ms-sql in a future version)
+        # generate a subquery for limits/offsets.
+        # ensure that the generated result map corresponds to the selected table, not
+        # the select query
+        r = s.limit(2).execute()
+        result = []
+        for row in r:
+            result.append((row[table1.c.this_is_the_primarykey_column], row[table1.c.this_is_the_data_column]))
+        assert result == [
+            (1, "data1"),
+            (2, "data2"),
+        ], repr(result)
+  
+        r = s.limit(2).offset(1).execute()
+        result = []
+        for row in r:
+            result.append((row[table1.c.this_is_the_primarykey_column], row[table1.c.this_is_the_data_column]))
+        assert result == [
+            (2, "data2"),
+            (3, "data3"),
+        ], repr(result)
+
     def test_colbinds(self):
         table1.insert().execute(**{"this_is_the_primarykey_column":1, "this_is_the_data_column":"data1"})
         table1.insert().execute(**{"this_is_the_primarykey_column":2, "this_is_the_data_column":"data2"})