- added "batch=True" flag to mapper; if False, save_obj
will fully save one object at a time including calls
to before_XXXX and after_XXXX
+- added autoincrement=True to Column; will disable schema generation
+of SERIAL/AUTO_INCREMENT/identity seq for postgres/mysql/mssql if
+explicitly set to False
0.2.8
- cleanup on connection methods + documentation. custom DBAPI
colspec = self.preparer.format_column(column) + " " + column.type.engine_impl(self.engine).get_col_spec()
# install a IDENTITY Sequence if we have an implicit IDENTITY column
- if column.primary_key and isinstance(column.type, sqltypes.Integer):
+ if column.primary_key and column.autoincrement and isinstance(column.type, sqltypes.Integer):
if column.default is None or (isinstance(column.default, schema.Sequence) and column.default.optional):
column.sequence = schema.Sequence(column.name + '_seq')
if not column.nullable:
colspec += " NOT NULL"
if column.primary_key:
- if not column.foreign_key and first_pk and isinstance(column.type, sqltypes.Integer):
+ if not column.foreign_key and first_pk and column.autoincrement and isinstance(column.type, sqltypes.Integer):
colspec += " AUTO_INCREMENT"
return colspec
def get_column_specification(self, column, **kwargs):
colspec = self.preparer.format_column(column)
- if column.primary_key and not column.foreign_key and isinstance(column.type, sqltypes.Integer) and not isinstance(column.type, sqltypes.SmallInteger) and (column.default is None or (isinstance(column.default, schema.Sequence) and column.default.optional)):
+ if column.primary_key and not column.foreign_key and column.autoincrement and isinstance(column.type, sqltypes.Integer) and not isinstance(column.type, sqltypes.SmallInteger) and (column.default is None or (isinstance(column.default, schema.Sequence) and column.default.optional)):
colspec += " SERIAL"
else:
colspec += " " + column.type.engine_impl(self.engine).get_col_spec()
if isinstance(column.default, schema.PassiveDefault):
c = self.proxy("select %s" % column.default.arg)
return c.fetchone()[0]
- elif isinstance(column.type, sqltypes.Integer) and (column.default is None or (isinstance(column.default, schema.Sequence) and column.default.optional)):
+ elif (isinstance(column.type, sqltypes.Integer) and column.autoincrement) and (column.default is None or (isinstance(column.default, schema.Sequence) and column.default.optional)):
sch = column.table.schema
# TODO: this has to build into the Sequence object so we can get the quoting
# logic from it
Generated SQL, however, will still reference the column by its actual name.
primary_key=False : True if this column is a primary key column. Multiple columns can have this flag
- set to specify composite primary keys.
+ set to specify composite primary keys. As an alternative, the primary key of a Table can be specified
+ via an explicit PrimaryKeyConstraint instance appended to the Table's list of objects.
nullable=True : True if this column should allow nulls. Defaults to True unless this column is a primary
key column.
default=None : a scalar, python callable, or ClauseElement representing the "default value" for this column,
which will be invoked upon insert if this column is not present in the insert list or is given a value
- of None.
+ of None. The default expression will be converted into a ColumnDefault object upon initialization.
hidden=False : indicates this column should not be listed in the
table's list of columns. Used for the "oid" column, which generally
specify the same index name will all be included in the index, in the
order of their creation.
+ autoincrement=True : Indicates that integer-based primary key columns should have autoincrementing behavior,
+ if supported by the underlying database. This will affect CREATE TABLE statements such that they will
+ use the databases "auto-incrementing" keyword (such as SERIAL for postgres, AUTO_INCREMENT for mysql) and will
+ also affect the behavior of some dialects during INSERT statement execution such that they will assume primary
+ key values are created in this manner. If a Column has an explicit ColumnDefault object (such as via the
+ "default" keyword, or a Sequence or PassiveDefault), then the value of autoincrement is ignored and is assumed
+ to be False. autoincrement value is only significant for a column with a type or subtype of Integer.
+
quote=False : indicates that the Column identifier must be properly escaped and quoted before being sent
- to the database.
+ to the database. This flag should normally not be required as dialects can auto-detect conditions where quoting
+ is required.
case_sensitive=True : indicates that the identifier should be interpreted by the database in the natural case for identifiers.
Mixed case is not sufficient to cause this identifier to be quoted; it must contain an illegal character.
self.quote = kwargs.pop('quote', False)
self._set_casing_strategy(name, kwargs)
self.onupdate = kwargs.pop('onupdate', None)
+ self.autoincrement = kwargs.pop('autoincrement', True)
self.__originating_column = self
if self.index is not None and self.unique is not None:
raise exceptions.ArgumentError("Column may not define both index and unique")
l = t.select(t.c.col1==pk).execute()
l = l.fetchone()
self.assert_(l['col3'] == 55)
-
-class SequenceTest(PersistTest):
+class AutoIncrementTest(PersistTest):
+ @testbase.supported('postgres', 'mysql')
+ def testnonautoincrement(self):
+ meta = BoundMetaData(testbase.db)
+ nonai_table = Table("aitest", meta,
+ Column('id', Integer, autoincrement=False, primary_key=True),
+ Column('data', String(20)))
+ nonai_table.create()
+ try:
+ try:
+ # postgres will fail on first row, mysql fails on second row
+ nonai_table.insert().execute(data='row 1')
+ nonai_table.insert().execute(data='row 2')
+ assert False
+ except exceptions.SQLError, e:
+ print "Got exception", str(e)
+ assert True
+
+ nonai_table.insert().execute(id=1, data='row 1')
+ finally:
+ nonai_table.drop()
+
+ def testwithautoincrement(self):
+ meta = BoundMetaData(testbase.db)
+ table = Table("aitest", meta,
+ Column('id', Integer, primary_key=True),
+ Column('data', String(20)))
+ table.create()
+ try:
+ table.insert().execute(data='row 1')
+ table.insert().execute(data='row 2')
+ finally:
+ table.drop()
+
+class SequenceTest(PersistTest):
+ @testbase.supported('postgres', 'oracle')
def setUpAll(self):
- if testbase.db.engine.name != 'postgres' and testbase.db.engine.name != 'oracle':
- return
global cartitems
cartitems = Table("cartitems", db,
Column("cart_id", Integer, Sequence('cart_id_seq'), primary_key=True),
x = cartitems.c.cart_id.sequence.execute()
self.assert_(1 <= x <= 4)
+ @testbase.supported('postgres', 'oracle')
def tearDownAll(self):
- if testbase.db.engine.name != 'postgres' and testbase.db.engine.name != 'oracle':
- return
cartitems.drop()
if __name__ == "__main__":