From: Mike Bayer Date: Sat, 8 Nov 2014 23:06:26 +0000 (-0500) Subject: - The :class:`~sqlalchemy.schema.Table` object is now returned when X-Git-Tag: rel_0_7_0~47^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8272c85faadb234af25e5a4f029a8c24879ef67d;p=thirdparty%2Fsqlalchemy%2Falembic.git - The :class:`~sqlalchemy.schema.Table` object is now returned when the :meth:`.Operations.create_table` method is used. This ``Table`` is suitable for use in subsequent SQL operations, in particular the :meth:`.Operations.bulk_insert` operation. fixes #205 --- diff --git a/alembic/operations.py b/alembic/operations.py index 11319f73..390764c2 100644 --- a/alembic/operations.py +++ b/alembic/operations.py @@ -749,7 +749,7 @@ class Operations(object): 'account', Column('id', INTEGER, primary_key=True), Column('name', VARCHAR(50), nullable=False), - Column('description', NVARCHAR(200)) + Column('description', NVARCHAR(200)), Column('timestamp', TIMESTAMP, server_default=func.now()) ) @@ -769,6 +769,33 @@ class Operations(object): Column('timestamp', TIMESTAMP, server_default=func.now()) ) + The function also returns a newly created + :class:`~sqlalchemy.schema.Table` object, corresponding to the table + specification given, which is suitable for + immediate SQL operations, in particular + :meth:`.Operations.bulk_insert`:: + + from sqlalchemy import INTEGER, VARCHAR, NVARCHAR, Column + from alembic import op + + account_table = op.create_table( + 'account', + Column('id', INTEGER, primary_key=True), + Column('name', VARCHAR(50), nullable=False), + Column('description', NVARCHAR(200)), + Column('timestamp', TIMESTAMP, server_default=func.now()) + ) + + op.bulk_insert( + account_table, + [ + {"name": "A1", "description": "account 1"}, + {"name": "A2", "description": "account 2"}, + ] + ) + + .. versionadded:: 0.7.0 + :param name: Name of the table :param \*columns: collection of :class:`~sqlalchemy.schema.Column` objects within @@ -787,10 +814,16 @@ class Operations(object): :param \**kw: Other keyword arguments are passed to the underlying :class:`sqlalchemy.schema.Table` object created for the command. + :return: the :class:`~sqlalchemy.schema.Table` object corresponding + to the parameters given. + + .. versionadded:: 0.7.0 - the :class:`~sqlalchemy.schema.Table` + object is returned. + """ - self.impl.create_table( - self._table(name, *columns, **kw) - ) + table = self._table(name, *columns, **kw) + self.impl.create_table(table) + return table def drop_table(self, name, **kw): """Issue a "drop table" instruction using the current diff --git a/docs/build/changelog.rst b/docs/build/changelog.rst index 560cc6d8..9222a6bf 100644 --- a/docs/build/changelog.rst +++ b/docs/build/changelog.rst @@ -5,6 +5,15 @@ Changelog .. changelog:: :version: 0.7.0 + .. change:: + :tags: feature, operations + :tickets: 205 + + The :class:`~sqlalchemy.schema.Table` object is now returned when + the :meth:`.Operations.create_table` method is used. This ``Table`` + is suitable for use in subsequent SQL operations, in particular + the :meth:`.Operations.bulk_insert` operation. + .. change:: :tags: feature, autogenerate :tickets: 203 diff --git a/tests/test_bulk_insert.py b/tests/test_bulk_insert.py index 97a8dd83..5121e907 100644 --- a/tests/test_bulk_insert.py +++ b/tests/test_bulk_insert.py @@ -176,6 +176,26 @@ class BulkInsertTest(TestBase): 'SET IDENTITY_INSERT ins_table OFF' ) + def test_bulk_insert_from_new_table(self): + context = op_fixture("postgresql", True) + t1 = op.create_table( + "ins_table", + Column('id', Integer), + Column('v1', String()), + Column('v2', String()), + ) + op.bulk_insert(t1, [ + {'id': 1, 'v1': 'row v1', 'v2': 'row v5'}, + {'id': 2, 'v1': 'row v2', 'v2': 'row v6'}, + ]) + context.assert_( + 'CREATE TABLE ins_table (id INTEGER, v1 VARCHAR, v2 VARCHAR)', + "INSERT INTO ins_table (id, v1, v2) VALUES " + "(1, 'row v1', 'row v5')", + "INSERT INTO ins_table (id, v1, v2) VALUES " + "(2, 'row v2', 'row v6')" + ) + def test_invalid_format(self): context, t1 = self._table_fixture("sqlite", False) assert_raises_message( @@ -263,3 +283,20 @@ class RoundTripTest(TestBase): (2, "d2"), ] ) + + def test_bulk_insert_from_new_table(self): + t1 = self.op.create_table( + "ins_table", + Column('id', Integer), + Column('v1', String()), + Column('v2', String()), + ) + self.op.bulk_insert(t1, [ + {'id': 1, 'v1': 'row v1', 'v2': 'row v5'}, + {'id': 2, 'v1': 'row v2', 'v2': 'row v6'}, + ]) + eq_( + self.conn.execute( + "select id, v1, v2 from ins_table order by id").fetchall(), + [(1, u'row v1', u'row v5'), (2, u'row v2', u'row v6')] + ) \ No newline at end of file diff --git a/tests/test_op.py b/tests/test_op.py index 835183eb..789eefb8 100644 --- a/tests/test_op.py +++ b/tests/test_op.py @@ -699,7 +699,7 @@ class OpTest(TestBase): def test_create_table_fk_and_schema(self): context = op_fixture() - op.create_table( + t1 = op.create_table( "some_table", Column('id', Integer, primary_key=True), Column('foo_id', Integer, ForeignKey('foo.id')), @@ -712,10 +712,12 @@ class OpTest(TestBase): "PRIMARY KEY (id), " "FOREIGN KEY(foo_id) REFERENCES foo (id))" ) + eq_(t1.c.id.name, "id") + eq_(t1.schema, "schema") def test_create_table_no_pk(self): context = op_fixture() - op.create_table( + t1 = op.create_table( "some_table", Column('x', Integer), Column('y', Integer), @@ -724,6 +726,7 @@ class OpTest(TestBase): context.assert_( "CREATE TABLE some_table (x INTEGER, y INTEGER, z INTEGER)" ) + assert not t1.primary_key def test_create_table_two_fk(self): context = op_fixture()