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
- 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
"""
-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
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()
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)
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:
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_
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'
-
# 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()),
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'
+