Skip to content

Commit

Permalink
Fix double escaping of dttm expressions (#744) (#1103)
Browse files Browse the repository at this point in the history
If ddtm_expr is an expression with special characters then timestamp_grain escapes
the special characters already escaped.

Solution discussed with sqlalchemy upstream:
https://bitbucket.org/zzzeek/sqlalchemy/issues/3737/literal_column-given-a-specific-sql

Fix #617
  • Loading branch information
xrmx authored and mistercrunch committed Sep 17, 2016
1 parent b62d7e3 commit 69d37d8
Showing 1 changed file with 19 additions and 2 deletions.
21 changes: 19 additions & 2 deletions caravel/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@
DateTime, Date, Table, Numeric,
create_engine, MetaData, desc, asc, select, and_, func
)
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.orm import relationship
from sqlalchemy.sql import table, literal_column, text, column
from sqlalchemy.sql.expression import TextAsFrom
from sqlalchemy.sql.expression import ColumnClause, TextAsFrom
from sqlalchemy_utils import EncryptedType

from werkzeug.datastructures import ImmutableMultiDict
Expand Down Expand Up @@ -805,6 +806,22 @@ def query( # sqla
metrics_exprs = []

if granularity:

# TODO: sqlalchemy 1.2 release should be doing this on its own.
# Patch only if the column clause is specific for DateTime set and
# granularity is selected.
@compiles(ColumnClause)
def _(element, compiler, **kw):
text = compiler.visit_column(element, **kw)
try:
if element.is_literal and hasattr(element.type, 'python_type') and \
type(element.type) is DateTime:

text = text.replace('%%', '%')
except NotImplementedError:
pass # Some elements raise NotImplementedError for python_type
return text

dttm_col = cols[granularity]
dttm_expr = dttm_col.sqla_col.label('timestamp')
timestamp = dttm_expr
Expand All @@ -820,7 +837,7 @@ def query( # sqla
col=dttm_expr)
udf = self.database.grains_dict().get(time_grain_sqla, '{col}')
timestamp_grain = literal_column(
udf.function.format(col=dttm_expr)).label('timestamp')
udf.function.format(col=dttm_expr), type_=DateTime).label('timestamp')
else:
timestamp_grain = timestamp

Expand Down

0 comments on commit 69d37d8

Please sign in to comment.