-
-
Notifications
You must be signed in to change notification settings - Fork 18k
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
Support sqlalchemy.Executable in pandas.read_sql(sql) #10846
Comments
I think this is a good idea. In practice, wouldn't this only be a |
Yes it should only be a Select or Text object. I especially like sqlalchemy's way to standardize parameters with text(). For example, I can just write text('select * from tbl where name=:value') regardless of actual backends. |
I'm going to look at this for EuroSciPy sprints. Maybe get some tests in place at least. |
I've got a test describing what I think we want at stephenpascoe@2a0bfff |
I have read the above link. It is not the same as what I was thinking. SQLAlchemy allows us to create statements using objects, similar to creating ASTs. One example of executing the 'select' statement can be found in the SQLAlchemy document. The above code is found here: http://docs.sqlalchemy.org/en/rel_1_0/core/tutorial.html If we could pass the object s into pd.read_sql() as parameter sql, that would be very nice. In addtion to the select object, it is also possible to pass the text object.
Note in the above code, we could always pass parameters in the syntax of ":myid" in the sql statement, regardless of the actual backend. SQLAlchemy will do the conversion to the proper db specific format inside. Now if we could write something like:
That would be great, |
I like this idea of What could happened if
? I think according http://stackoverflow.com/questions/19314342/python-sqlalchemy-pass-parameters-in-connection-execute that it's safer than |
I won't be
but
|
@scls19fr , regarding the SQL injection problem, I think the text() object idea will in fact prevent the SQL injection attack. If you pass in myid="1; DROP table test_table" , the execution will fail. The reason is that the parameter :myid in "select * from mytable where id=:myid" is a real parameter for the underlying DBAPI. For example, in the case of SQL Server, the above will be translated to "select * from mytable where id=?", this statement is then passed to MS SQL Server, along with the value of the parameter. This is very different from "select * from mytable where id=%s" % (my_id), which suffers the SQL injection problem. The stackoverflow article you cited in fact talks about how to prevent SQL Inject attack using the text() object instead of raw string. text() is way safer than raw string. |
I think so. Doc should also be improved accordingly. The use of prepared statement / bind variable should be shown in doc to avoid SQL Injection. |
I believe we can already do this. E.g. see stephenpascoe@bebc6a6. These tests pass on my system. I.e. this should work:
The tests show we can also make this work for |
I would avoid bindparam() if at all possible. If we use bindparam(), sqlalchemy will try to 'bind the parameters' to SQL, whereas if we don't use it, the underlying SQL database will do the work. The latter will be faster and possibly safer. |
I don't understand this. In the example tests these two sqlalchemy objects are equivalent:
They both generate virtually the same SQL. I think there may be a way of adding |
If |
@stephenpascoe , I mean Without losing generality, let's say If we just do the following, without calling bindparam(),
then sqlalchemy will translate the SQL statement to DB specific format along with the unbound parameters. For example, in the case of Microsoft SQL Server, the above will be translated to
and the value 1 will be passed to Microsoft SQL server along with the above sql statement. Microsoft SQL server will then bind the parameter to the SQL statement. In comparison, with bindparam(), sqlalchemy will try to bind the parameters itself. if we do bindparam(), the sqlahcmely statement
will be translated to something like
BEFORE passing to MS SQL server.. In addition, So the approach without using |
@zyzhu2000 I'm sorry but I think you are mistaken. If you look at the documentation for [bindparam] it explains that it's purpose is exactly what you want: to allow a value to be bound to a parameter at execution time (and by the database when supported). Either way, I don't think this ticket is the right place for debating sqlalchemy internals. I've played around with adding |
@stephenpascoe , I think you are right about |
TST/DOC #10846 Test and document use of SQLAlchemy expressions in read_sql()
Since pandas.read_sql() can always use sqlalchemy.Engine or Connection, it would be great if the sql parameter can accept sqlalchemy.Executable in addition to a string. sqlalchemy.Executable provides a standardized way of binding parameters and generating sql for different kinds of DB.
The text was updated successfully, but these errors were encountered: