On Sat, Nov 25, 2017 at 12:54 PM, Jacob Hunsaker
<jacob.r.hunsa...@gmail.com> wrote:
> Hi all,
>
> I'm working on a way to perform migrations entirely within my python
> application using the alembic API. I do not envision any complex DB changes
> for this project (at most adding a new table) so I figure autogenerate
> should be completely sufficient. At the moment, I can successfully detect
> schema changes between the application and the DB as it is written on disk
> (sqlite3), however I cannot seem to perform the actual upgrade to the DB.
>
> This is what I have thus far, with the 'fn=self.do_upgrade()' bit coming
> from this StackOverflow post as without that I was hitting the same
> exception as the poster there:
>         self.alembic_cfg = Config()
>         self.alembic_cfg.set_main_option("script_location", "migrations")
>         self.alembic_cfg.set_main_option("url", "sqlite://mydb.db")
>         self.alembic_script = ScriptDirectory.from_config(self.alembic_cfg)
>         self.alembic_env = EnvironmentContext(self.alembic_cfg,
> self.alembic_script)
>         self.migrate()
>
>
>     def migrate(self):
>         conn = engine.connect()
>         metadata = Base.metadata
>         self.alembic_env.configure(connection=conn,
> target_metadata=metadata, fn=self.do_upgrade)
>         self.alembic_context = self.alembic_env.get_context()
>         autogenerate.compare_metadata(self.alembic_context, metadata)
>         autogenerate.produce_migrations(self.alembic_context, metadata)
>
>         with self.alembic_env.begin_transaction():
>             self.alembic_env.run_migrations()
>
>
>     def do_upgrade(self, revision, context):
>         return
> self.alembic_script._upgrade_revs(self.alembic_script.get_heads(), revision)
>
>
> Assume I have this table to start:
>
> Base = declarative_base()
>
>
> class Events(Base):
>
>     __tablename__ = 'events'
>     id = Column(Integer, primary_key=True)
>     name = Column(String(100), nullable=False)
>
> [...]
>
> engine = create_engine("sqlite:///mydb.db")
>
> Base.metadata.create_all(engine)
>
> Base.metadata.bind = engine
>
> And I want to add an arbitrary column:
>     test = Column(String(10), default='test')
>
>
> As said earlier, the above will detect the change, as seen by
> autogenerate.compare_metadata(self.alembic_context, metadata):
>
> [('add_column', None, 'events', Column('test', String(length=10),
> table=<events>, default=ColumnDefault('test')))]
>
>
> However, even though run_migrations() appears to run without issue (no
> exceptions or similar), the written DB is not updated, and I cannot access
> the 'test' column for any entry in the 'events' table with this exception:

the run_migrations() method as called above does nothing because it
hasn't been set up correctly, which involves steps that normally occur
in the alembic.command package, which you aren't using here.    When
the alembic.command does set things up, it sets up run_migrations()
such that it's going to load in your versions/ files and run them,
which you aren't using here.   Based on what you're trying to do I
wouldn't use run_migrations() at all since this is an integration
point between your env.py and the commands set up by alembic.command.

if you're doing this kind of tinkering you need to turn on SQL
logging, either via echo=True in your create_engine() or by
configuring sqlalchemy.engine logger to INFO or DEBUG in your
alembic.ini, so that you can see what SQL is and is not being emitted.

the produce_migrations() function in particular has a return value.
calling it without looking at the return value is not going to help
you much.

what would be needed here would be a system to take the
MigrationScript you get back and then feed it directly to get the
"impl" for each directive and run it, without generating any Python
code in between since you are invoking directly.    I'd have to dig
into the API to see how this could be done, this is not a pattern
that's been developed as of yet.  Assuming the API can do it without
any changes (which I think is probable) this could be made into a
cookbook recipe.   I'd have to find some time to work on it.   Feel
free to ping me with a support ticket on bitbucket if I haven't
responded here in a few days.





>
> sqlite3.OperationalError: no such column: events.test
>
>
>
> I have noticed that within do_upgrade(), that both get_heads() and revision
> are empty. I assume this is because I have not done a previous migration on
> this existing DB, but I'm not sure how to proceed there. I have only run
> `alembic --init` in the project directory (with mydb.db being in the
> top-level directory).
>
>
> I have a feeling I'm missing something that is probably incredibly obvious,
> so any help here would be very much appreciated.
>
> --
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy-alembic" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sqlalchemy-alembic+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy-alembic" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy-alembic+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to