On Fri, May 10, 2019 at 7:09 AM Diego Quintana <
daqui...@gmail.com> wrote:
>
> Hello! I'm trying to seed my database using my first migration script, and I have trouble understanding what `op.get_bind()` returns, and mainly the difference between `Connection` and `engine.connection()`. Say I have a migration script that creates a table called `cities` and then it performs a `COPY FROM CSV` using `engine.raw_connection`.
>
> The method `insert_default_csv` is failing in (note that line might not be the exact one)
>
> File "/src/app/migrations/versions/d054d8692328_initial_migration.py", line 91, in insert_default_csv
> cursor.copy_expert(cmd, f)
> psycopg2.ProgrammingError: relation "cities" does not exist
>
> This is probably due to the fact that the `bind` object the class `City` was created with and `bind.engine` used in that method are pointing to different places. This can be tested with the bit
>
>
logger.info(bind.engine.connect() == bind) # INFO [alembic] False
>
logger.info(bind.engine.dialect.has_table(bind.engine.connect(), "cities")) # INFO [alembic] False
>
logger.info(bind.engine.dialect.has_table(bind, "cities")) # INFO [alembic] True
>
>
> In short what are the differences between these two objects and how can I access a working engine in Alembic from the context or the bind?
in your alembic environment, there's an env.py that Alembic creates
for you, which we encourage you to modify to suit the needs of your
project. Inside of this file, there is a transaction block created
which you can see an example at
https://github.com/sqlalchemy/alembic/blob/master/alembic/templates/generic/env.py#L63,
where it checks out a Connection from an Engine, and then calls an
Alembic-specific block called "begin_transaction()" that ensures the
Connection has a transaction started which will commit at the end of
the block. For background on what Connection and Engine are, see
https://docs.sqlalchemy.org/en/13/core/connections.html.
So once you get into your migration script, op.get_bind() gives you
that Connection object, the one we made on line 63 of the env.py
example above. In virtually all cases, in a migration script this
would be the thing you use to work with the database connection
directly.
when OTOH we do the bit wtih "bind.engine.connect()", basically "bind"
here is the Connection that's in a transaction; it has an .engine
attribute which is, "the Engine object which I came from". Easy
enough, but then what you're doing is making *another* Connection by
calling connect() again on that engine. This Connection will run SQL
in a separate transaction than the one in which your migration script
was set up to run within from your env.py file. So if you do things
like work with the table you just created, if your database supports
what's called "transactional DDL", meaning a "CREATE TABLE" will not
be visible until the transaction is committed, this second Connection
will not be able to see that new table because it isn't committed to
the database yet.
hope this helps!
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
>
http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See
http://stackoverflow.com/help/mcve for a full description.
> ---
> You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to
sqlalchemy+...@googlegroups.com.
> To post to this group, send email to
sqlal...@googlegroups.com.
> Visit this group at
https://groups.google.com/group/sqlalchemy.
> To view this discussion on the web visit
https://groups.google.com/d/msgid/sqlalchemy/cc4d5a88-a8b6-496b-9b18-9d96722d2ed1%40googlegroups.com.
> For more options, visit
https://groups.google.com/d/optout.