]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- "out" parameters require a type that is supported by
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 23 Feb 2010 22:15:09 +0000 (22:15 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 23 Feb 2010 22:15:09 +0000 (22:15 +0000)
cx_oracle.  An error will be raised if no cx_oracle
type can be found.
- Column() requires a type if it has no foreign keys (this is
not new).  An error is now raised if a Column() has no type
and no foreign keys.  [ticket:1705]

CHANGES
lib/sqlalchemy/dialects/oracle/cx_oracle.py
lib/sqlalchemy/schema.py
test/engine/test_metadata.py
test/sql/test_columns.py

diff --git a/CHANGES b/CHANGES
index 5c5f91581d5c6f0987c1126048fb7e9b421ca92c..9c22270bfa8ceb1a8168488fcb086114501b95a9 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -160,6 +160,10 @@ CHANGES
     VALUES clause of an update/insert generates a compile error.
     This reduces call counts and eliminates some cases where
     undesirable name conflicts could still occur.
+
+  - Column() requires a type if it has no foreign keys (this is 
+    not new).  An error is now raised if a Column() has no type
+    and no foreign keys.  [ticket:1705]
     
 - engines
   - Added an optional C extension to speed up the sql layer by
@@ -207,6 +211,11 @@ CHANGES
 
   - Removed the text_as_varchar option.
 
+- oracle
+   - "out" parameters require a type that is supported by
+     cx_oracle.  An error will be raised if no cx_oracle
+     type can be found.
+     
 - sqlite
    - Added "native_datetime=True" flag to create_engine().
      This will cause the DATE and TIMESTAMP types to skip 
index cfa5ba45b4aaefb9e810f1fcdf51fc86909544c0..854eb875a8fa71257bf3d4217bef060cc13e030d 100644 (file)
@@ -74,10 +74,11 @@ with this feature but it should be regarded as experimental.
 
 """
 
-from sqlalchemy.dialects.oracle.base import OracleCompiler, OracleDialect, RESERVED_WORDS, OracleExecutionContext
+from sqlalchemy.dialects.oracle.base import OracleCompiler, OracleDialect, \
+                                        RESERVED_WORDS, OracleExecutionContext
 from sqlalchemy.dialects.oracle import base as oracle
 from sqlalchemy.engine import base
-from sqlalchemy import types as sqltypes, util
+from sqlalchemy import types as sqltypes, util, exc
 from datetime import datetime
 import random
 
@@ -219,11 +220,19 @@ class Oracle_cx_oracleExecutionContext(OracleExecutionContext):
                 name = self.compiled.bind_names[bindparam]
                 value = self.compiled_parameters[0][name]
                 if bindparam.isoutparam:
-                    dbtype = bindparam.type.dialect_impl(self.dialect).get_dbapi_type(self.dialect.dbapi)
+                    dbtype = bindparam.type.dialect_impl(self.dialect).\
+                                    get_dbapi_type(self.dialect.dbapi)
                     if not hasattr(self, 'out_parameters'):
                         self.out_parameters = {}
+                    if dbtype is None:
+                        raise exc.InvalidRequestError("Cannot create out parameter for parameter "
+                                                        "%r - it's type %r is not supported by"
+                                                        " cx_oracle" %
+                                                        (name, bindparam.type)
+                                                        )
                     self.out_parameters[name] = self.cursor.var(dbtype)
-                    self.parameters[0][quoted_bind_names.get(name, name)] = self.out_parameters[name]
+                    self.parameters[0][quoted_bind_names.get(name, name)] = \
+                                                        self.out_parameters[name]
         
     def create_cursor(self):
         c = self._connection.connection.cursor()
index c68d1f1354caeb480bcfb84b41808494688d773e..80c03bbbaf506331eb8af6eeea235c0b8b4e1bf1 100644 (file)
@@ -636,7 +636,9 @@ class Column(SchemaItem, expression.ColumnClause):
                     raise exc.ArgumentError(
                         "May not pass type_ positionally and as a keyword.")
                 type_ = args.pop(0)
-
+        
+        no_type = type_ is None
+        
         super(Column, self).__init__(name, None, type_)
         self.key = kwargs.pop('key', name)
         self.primary_key = kwargs.pop('primary_key', False)
@@ -686,6 +688,9 @@ class Column(SchemaItem, expression.ColumnClause):
                                             for_update=True))
         self._init_items(*args)
 
+        if not self.foreign_keys and no_type:
+            raise exc.ArgumentError("'type' is required on Column objects "
+                                        "which have no foreign keys.")
         util.set_creation_order(self)
 
         if 'info' in kwargs:
index 2fadfe27269636d9a1547092c2c655ce8668e0c7..50109e15a91ee0673b99e58b584b69fbde18a80a 100644 (file)
@@ -4,7 +4,7 @@ from sqlalchemy import Integer, String, UniqueConstraint, CheckConstraint,\
                         ForeignKey, MetaData, Sequence, ForeignKeyConstraint,\
                         ColumnDefault
 from sqlalchemy.test.schema import Table, Column
-from sqlalchemy import schema
+from sqlalchemy import schema, exc
 import sqlalchemy as tsa
 from sqlalchemy.test import TestBase, ComparesTables, AssertsCompiledSQL, testing, engines
 from sqlalchemy.test.testing import eq_
@@ -242,26 +242,3 @@ class TableOptionsTest(TestBase, AssertsCompiledSQL):
             t.info['bar'] = 'zip'
             assert t.info['bar'] == 'zip'
 
-class ColumnOptionsTest(TestBase):
-    
-    def test_default_generators(self):
-        g1, g2 = Sequence('foo_id_seq'), ColumnDefault('f5')
-        assert Column(default=g1).default is g1
-        assert Column(onupdate=g1).onupdate is g1
-        assert Column(default=g2).default is g2
-        assert Column(onupdate=g2).onupdate is g2
-        
-        
-    def test_column_info(self):
-        
-        c1 = Column('foo', info={'x':'y'})
-        c2 = Column('bar', info={})
-        c3 = Column('bat')
-        assert c1.info == {'x':'y'}
-        assert c2.info == {}
-        assert c3.info == {}
-        
-        for c in (c1, c2, c3):
-            c.info['bar'] = 'zip'
-            assert c.info['bar'] == 'zip'
-
index e9dabe1421fb391516d76286f58a8fb956c3a5e7..3cbb01943a9105360e83468177c25272358cff49 100644 (file)
@@ -11,11 +11,11 @@ class ColumnDefinitionTest(TestBase):
     # flesh this out with explicit coverage...
 
     def columns(self):
-        return [ Column(),
-                 Column('b'),
+        return [ Column(Integer),
+                 Column('b', Integer),
                  Column(Integer),
                  Column('d', Integer),
-                 Column(name='e'),
+                 Column(Integer, name='e'),
                  Column(type_=Integer),
                  Column(Integer()),
                  Column('h', Integer()),
@@ -56,3 +56,40 @@ class ColumnDefinitionTest(TestBase):
         assert_raises(exc.ArgumentError, Column, 'foo', Integer,
                           type_=Integer())
 
+
+class ColumnOptionsTest(TestBase):
+
+    def test_default_generators(self):
+        g1, g2 = Sequence('foo_id_seq'), ColumnDefault('f5')
+        assert Column(String, default=g1).default is g1
+        assert Column(String, onupdate=g1).onupdate is g1
+        assert Column(String, default=g2).default is g2
+        assert Column(String, onupdate=g2).onupdate is g2
+
+    def test_type_required(self):
+        assert_raises(exc.ArgumentError, Column)
+        assert_raises(exc.ArgumentError, Column, "foo")
+        assert_raises(exc.ArgumentError, Column, default="foo")
+        assert_raises(exc.ArgumentError, Column, Sequence("a"))
+        assert_raises(exc.ArgumentError, Column, "foo", default="foo")
+        assert_raises(exc.ArgumentError, Column, "foo", Sequence("a"))
+        Column(ForeignKey('bar.id'))
+        Column("foo", ForeignKey('bar.id'))
+        Column(ForeignKey('bar.id'), default="foo")
+        Column(ForeignKey('bar.id'), Sequence("a"))
+        Column("foo", ForeignKey('bar.id'), default="foo")
+        Column("foo", ForeignKey('bar.id'), Sequence("a"))
+
+    def test_column_info(self):
+
+        c1 = Column('foo', String, info={'x':'y'})
+        c2 = Column('bar', String, info={})
+        c3 = Column('bat', String)
+        assert c1.info == {'x':'y'}
+        assert c2.info == {}
+        assert c3.info == {}
+
+        for c in (c1, c2, c3):
+            c.info['bar'] = 'zip'
+            assert c.info['bar'] == 'zip'
+