-
-
Notifications
You must be signed in to change notification settings - Fork 899
Fix #26 Use unique MetaData object for each bind #222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I would love to see this merged. Is there anything left to do in order to merge it? |
We need to consider how this will fit with #255 and other issues related to more flexible metadata and base models. |
Unfortunately, passing a custom MetaData object to the
If you merged this PR and then merged #255 after you would essentially get If you would prefer options |
This pull request is also a solution to a show-stopping bug for us. We are using from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_BINDS'] = {
'postgres': 'postgresql+psycopg2://[email protected]/test',
'mysql': 'mysql://[email protected]/test',
}
db = SQLAlchemy(app)
class PostgresModel(db.Model):
__tablename__ = 'postgres_model'
__bind_key__ = 'postgres'
id = db.Column(db.Integer, primary_key=True)
class MySQLModel(db.Model):
__tablename__ = 'mysql_model'
__bind_key__ = 'mysql'
id = db.Column(db.Integer, primary_key=True)
my_enum = db.Column(db.Enum('A', 'B'))
db.create_all() Executing this script will give you the error:
I installed the Flask-SQLAlchemy proposed in this pull request, and all was fine. |
I'd love to see this merged as well (or a variant of it). Any update on this? |
This would be a major upgrade for our use case as well, anything we can do to help get this merged? |
any progress of this merge? I have same object name in two db with binds. Now, it tells me: |
IMHO this is a hack adding breakage on top of a wrong assumption if one needs objects of different databases potentially sharing the same identity key one should always use a different session object to begin with instead of just declaring the same table twice and throwing things together in some way |
@RonnyPfannschmidt Does flask-sqlalchemy support multiple sessions? I can not find any document about it. how it deal with db config? I know I can get my answer by reading code.. |
You can use them manually, but its not explicitly supported and integrated |
I started building a webapp using Flask a month ago and now I'm facing this same issue. I think that the patch is not a hack. It does what I expect to happen when using binds. |
An InvalidRequestError occurs when subclassing db.Model with two objects that have the same __tablename__ but different __bind_key__. sqlalchemy.exc.InvalidRequestError: Table 'users' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object. This could happen, for example, if you had a `users` table in two different databases that you needed to access. This patch creates a unique MetaData object for each bind_key which stops this error from happening and allows access to tables with the same name in different databases. It also includes a test to verify the error is fixed.
I have updated and slightly improved this pull request on top of the current codebase. It seems like this is causing issues for a lot of people. Previously, there was a concern how this pull request would fit with other open pull requests that were also making changes to metadata but they've all been merged into the project now and none of them fixed this issue. It would be really nice to get this merged so we can stop having to keep modified flask-sqlalchemy library in our projects' repos. |
I definitely want to get this in 3.0. There are a lot of customization things that have built up, and it's hard to keep track of them all and make sure they all form a consistent api. If any of you have input on #357 (subclassing vs
|
if not bind: | ||
return self.metadata | ||
if bind not in self.Model._metadata: | ||
self.Model._metadata[bind] = MetaData() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use copy/deepcopy here for not throwing customized metadata away?
self.Model._metadata[bind] = copy(self.metadata)
I don't know much about the Flask and its extensions' internals as I just started. For me the |
So what do you think? Would the copy of metadata class solve the concern of throwing the customized metadata away? |
So this issue exists for about 3 years, any update to it? |
I will have more time to work on this after PyCon; my current focus is Flask. Or during PyCon, if anyone who wants to work on Flask-SQLAlchemy will be at the sprints. Unfortunately, there are only two maintainers of this project, and we're both volunteering our limited free time. Conceptually, I'm ok with this, but I need to find time to thoroughly review it and consider how it will interact with other parts of the library and other features that need to get in, as stated above. |
Here is another way to trigger this error
class MyModel(db.Model):
__tablename__ = 'mymodel'
id = db.Column(db.Integer, primary_key=True)
anotherModel = db.relationship("AnotherModel")
class MyModelSchema(ma.ModelSchema):
class Meta:
model = MyModel
mymodel_schema = MyModelSchema()
class AnotherModel(db.Model):
__tablename__ = 'anothermodel'
id = db.Column(db.Integer, primary_key=True)
mymodel_id = db.Column(db.Integer, db.ForeignKey('mymodel.id')) If sorry if this doesn't relate to the PR ... this is where i land when i google for this error .. |
Is there any good workaround for this issue for the time being? It'd be really awesome to be able to use SQLAlchemy again and this is the only thing preventing it from working. EDIT: |
This comment has been minimized.
This comment has been minimized.
While this was a pretty clever solution, it doesn't handle |
An InvalidRequestError occurs when subclassing db.Model with two objects
that have the same
__tablename__
but different__bind_key__
.This could happen, for example, if you had a
users
table in twodifferent databases that you needed to access. This patch creates a
unique MetaData object for each bind_key which stops this error from
happening and allows access to tables with the same name in different
databases. It also includes a test to verify the error is
fixed.