Skip to content
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

adds support for expandable parameters #19

Merged
merged 4 commits into from
May 21, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions cs50/sql.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import re
import sqlalchemy
import sqlparse

class SQL(object):
"""Wrap SQLAlchemy to provide a simple SQL API."""
@@ -20,8 +22,45 @@ def execute(self, text, *multiparams, **params):
"""
Execute a SQL statement.
"""

# parse text
parsed = sqlparse.parse(text)
if len(parsed) == 0:
raise RuntimeError("missing statement")
elif len(parsed) > 1:
raise RuntimeError("too many statements")
statement = parsed[0]
if statement.get_type() == "UNKNOWN":
raise RuntimeError("unknown type of statement")

# infer paramstyle
# https://www.python.org/dev/peps/pep-0249/#paramstyle
paramstyle = None
for token in statement.flatten():
if sqlparse.utils.imt(token.ttype, t=sqlparse.tokens.Token.Name.Placeholder):
_paramstyle = None
if re.search(r"^\?$", token.value):
_paramstyle = "qmark"
elif re.search(r"^:\d+$", token.value):
_paramstyle = "numeric"
elif re.search(r"^:\w+$", token.value):
_paramstyle = "named"
elif re.search(r"^%s$", token.value):
_paramstyle = "format"
elif re.search(r"^%\(\w+\)s$", token.value):
_paramstyle = "pyformat"
else:
raise RuntimeError("unknown paramstyle")
if paramstyle and paramstyle != _paramstyle:
raise RuntimeError("inconsistent paramstyle")
paramstyle = _paramstyle

try:

parsed = sqlparse.split("SELECT * FROM cs50 WHERE id IN (SELECT id FROM cs50); SELECT 1; CREATE TABLE foo")
print(parsed)
return 0

# bind parameters before statement reaches database, so that bound parameters appear in exceptions
# http://docs.sqlalchemy.org/en/latest/core/sqlelement.html#sqlalchemy.sql.expression.text
# https://groups.google.com/forum/#!topic/sqlalchemy/FfLwKT1yQlg