-
-
Notifications
You must be signed in to change notification settings - Fork 18.1k
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
BUG/ENH: to_sql fails to detect tables via if_exists on mysql with capitalised table names #7815
Comments
So this specific error has been fixed in 0.14.1 as def has_table(self, name):
if self.meta.tables.get(name) is not None:
return True
else:
return False was changed in 0.14.1 to def has_table(self, name):
return self.engine.has_table(name) However in general there seems to be an assumption that you can C:\Anaconda\lib\site-packages\pandas\io\sql.pyc in drop_table(self, table_name)
854 def drop_table(self, table_name):
855 if self.engine.has_table(table_name):
--> 856 self.meta.reflect(only=[table_name])
857 self.get_table(table_name).drop()
858 self.meta.clear() because it can't find the table. From the SQLAlchemy docs,
Rather than mark this CANTFIX WONTFIX, could we fetch the correct table name by changing def get_table(self, table_name):
return self.meta.tables.get(table_name) to search through To answer my own question, from the mysql docs it seems like you'd have to know the value of lower_case_table_names before knowing whether this was a safe thing to do:
Seems fairly involved! Seems like it would be easier to write 'DROP TABLE %s' :) Thoughts on what direction to take this? |
How about this. If the table exists and the engine is mysql but |
While I think about it, here's my proposed code def drop_table(self, table_name):
if self.engine.has_table(table_name):
if self.engine.dialect=='mysql' and self.get_table(table_name) is None and self.get_table(table_name.lower()) is not None:
table_name=table_name.lower()
self.meta.reflect(only=[table_name])
self.get_table(table_name).drop()
self.meta.clear() However, that just fixes it in |
Hmm, what a mess this case sensitivity .. :-) But thanks for reporting and digging into this, @maxgrenderjones Your fix looks reasonable (in the sense it looks like solving the problem), but on the other hand, if we have to do this for every where for some flavor something is not working, it can become tedious (that was the reason for using sqlalchemy). |
Agree, it's a bit of a nightmare, so I'm just hoping that the issue is that we're not using SQLAlchemy correctly, rather than that even after SQLAlchemy-ing our code, we still have loads of edge cases. You could probably call it a bug that >>> model.Engine
Engine(mysql+oursql://username:***@hostname/database)
>>> meta=MetaData(bind=model.Engine)
>>> meta.reflect(only=['OnlineTransactions'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Anaconda\lib\site-packages\sqlalchemy\sql\schema.py", line 3246, in reflect
(bind.engine.url, s, ', '.join(missing)))
sqlalchemy.exc.InvalidRequestError: Could not reflect: requested table(s) not available in mysql+oursql://username:***@hostname/database: (OnlineTransactions)
>>> meta.reflect(only=['onlinetransactions'])
>>> but I can't believe that the difference between
(There's a partial solution on #7422, but if we're going to fix some of it, would be good to fix the whole thing while we're at it) |
@maxgrenderjones I started implementing |
@maxgrenderjones Coming back to this. I don't feel like putting in the fix you proposed above, as this seems a bit too specifi. Furthermore, eg on linux you can have a difference between 'Foo' and 'foo' (it depends on your mysql settings, and the default values differ between operating system). And I also don't want to do more on this issue as SQLAlchemy does, relying on them that they do the best as possible wihtout getting lost in this rabbit hole. Further, for this specific case, with MySQL on Windows, all tables names are converted to lower case, so you really shouldn't use upper case. But, I was thinking, what we can do, is trying to detect such a case like this and raise a warning if possible. Eg in the case that the user provided table name (here 'Foo') does not match the actually created table name (in this case 'foo'). If such a case is detected, we could raise a warning like "The table name 'Foo' you provided is not used exactly in the database, possibly due to case sensitivity issues. Consider using lower case table names" See also discussion in sqlalchemy issue tracker: https://bitbucket.org/zzzeek/sqlalchemy/issue/3181/metadatareflect-with-only-keyword-fails |
Thanks @jorisvandenbossche, seems a fair resolution of a problem with no clean answers |
Demonstration code, running on windows (so case insensitive) with pandas 0.14.0
Fails with:
I haven't poked around the code to see if this is a SQLAlchemy issue or a pandas issue, but I'd hope it shouldn't be too difficult to fix
The text was updated successfully, but these errors were encountered: