flask-sqlalchemy icon indicating copy to clipboard operation
flask-sqlalchemy copied to clipboard

Reflect not returning respective Bind

Open sochi opened this issue 6 years ago • 0 comments

When using reflection to populate model from existing database, the bind is not populated correctly. This results in unusable model created when using non-default bind.

Using default connection, and another bind for a second database schema. However the returned Table instances are incorrectly set with bind to the default schema, i.e., None. Querying such table then apparently fails.

See minimal example below, which is based on the quick start from documentation:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config[
    "SQLALCHEMY_DATABASE_URI"
] = "postgresql://postgres:passwd@localhost:5432/ex1"
app.config["SQLALCHEMY_BINDS"] = {
    "ex2": "postgresql://postgres:passwd@localhost:5432/ex2"
}
app.config["SQLALCHEMY_POOL_RECYCLE"] = 30
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_ECHO"] = False

db = SQLAlchemy(app)
db.reflect(app=app)  # reflecting tables from database


for name, table in db.metadata.tables.items():
    print("TABLE", name, "AS", repr(table))

# prints the following:
# TABLE a1 AS Table('a1', MetaData(bind=None), Column('id', INTEGER(), table=<a1>, primary_key=True, nullable=False), Column('name', VARCHAR(length=255), table=<a1>, nullable=False), schema=None)
# TABLE a2 AS Table('a2', MetaData(bind=None), Column('id', INTEGER(), table=<a2>, primary_key=True, nullable=False), Column('name', VARCHAR(length=255), table=<a2>, nullable=False), schema=None)

# querying table from default schema first
a1 = db.metadata.tables["a1"]
records_a1 = db.session.query(a1).limit(5).all()
print("IN DATABASE ex1 IN TABLE a1", len(records_a1))

# querying table from the second schema fails!
a2 = db.metadata.tables["a2"]
records_a2 = db.session.query(a2).limit(5).all() 
print("IN DATABASE ex2 IN TABLE a2", len(records_a2))

Complete traceback:

Traceback (most recent call last):
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1193, in _execute_context
    context)
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 509, in do_execute
    cursor.execute(statement, parameters)
psycopg2.ProgrammingError: relation "a2" does not exist
LINE 2: FROM a2 
             ^

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/.../test_flask_sqlalchemy_bind.py", line 32, in <module>
    records_a2 = db.session.query(a2).limit(5).all()
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2843, in all
    return list(self)
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2995, in __iter__
    return self._execute_and_instances(context)
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 3018, in _execute_and_instances
    result = conn.execute(querycontext.statement, self._params)
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 948, in execute
    return meth(self, multiparams, params)
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 269, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1060, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1200, in _execute_context
    context)
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1413, in _handle_dbapi_exception
    exc_info
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 265, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 248, in reraise
    raise value.with_traceback(tb)
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1193, in _execute_context
    context)
  File "/home/.../venv/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 509, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) relation "a2" does not exist
LINE 2: FROM a2 
             ^
 [SQL: 'SELECT a2.id AS a2_id, a2.name AS a2_name \nFROM a2 \n LIMIT %(param_1)s'] [parameters: {'param_1': 5}] (Background on this error at: http://sqlalche.me/e/f405)

sochi avatar Dec 19 '18 11:12 sochi