Guest User

Untitled

a guest
Jan 23rd, 2018
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.75 KB | None | 0 0
  1. from sqlalchemy.ext.compiler import compiles
  2. from sqlalchemy.sql.expression import FromClause, column, Select
  3.  
  4. class CommonTableExpression(FromClause):
  5. """Represent the 'inside' of a common table
  6. expression."""
  7.  
  8. def __init__(self, name, colnames):
  9. self.name = name
  10. self.colnames = colnames
  11.  
  12. def _populate_column_collection(self):
  13. self._columns.update(
  14. (name, column(name))
  15. for name in self.colnames
  16. )
  17.  
  18. @classmethod
  19. def create(cls, name, colnames):
  20. target = CommonTableExpression(name, colnames)
  21. class ctx(object):
  22. def __enter__(self):
  23. return target
  24. def __exit__(self, *arg, **kw):
  25. pass
  26. return ctx()
  27.  
  28. class SelectFromCTE(FromClause):
  29. """Represent the 'outside' of the CTE.
  30.  
  31. Ultimately this would be integrated into Select
  32. itself, since we just want a Select with an
  33. extra clause on top. "CommonTableExpression" objects
  34. would be pulled from the FROM clause
  35. and rendered on top.
  36.  
  37. """
  38. def __init__(self, inner_thing, stmt):
  39. self.inner_thing = inner_thing
  40. self.stmt = stmt
  41.  
  42. def _populate_column_collection(self):
  43. for name, c in zip(self.inner_thing.colnames, self.stmt.c):
  44. c._make_proxy(self, name)
  45.  
  46. @compiles(CommonTableExpression)
  47. def _recur_inner_thing(element, compiler, **kw):
  48. return element.name
  49.  
  50. @compiles(SelectFromCTE)
  51. def _recur_outer_thing(element, compiler, **kw):
  52. cte = (
  53. "WITH %s(%s) AS (\n"
  54. "%s\n"
  55. ")\n"% (
  56. element.inner_thing.name,
  57. ", ".join(element.inner_thing.colnames),
  58. compiler.process(element.stmt, **kw) )
  59. )
  60.  
  61. compiler._cte = cte
  62.  
  63. text = "SELECT * FROM %s" % element.inner_thing.name
  64.  
  65. # FIXME
  66. if kw.get('asfrom'):
  67. text = "(%s) as x" % text
  68.  
  69. return text
  70.  
  71. @compiles(Select)
  72. def visit_select_cte(element, compiler, **kw):
  73. text = compiler.visit_select(element)
  74.  
  75. if hasattr(compiler, '_cte') and not bool(compiler.stack):
  76. text = compiler._cte + text + "\n OPTION (MAXRECURSION 0)"
  77.  
  78. if kw.get('asfrom'):
  79. text = "(%s)" % text
  80.  
  81. return text
  82.  
  83. from sqlalchemy import select, DateTime, Integer
  84. from sqlalchemy.sql.expression import func, cast, bindparam, text
  85.  
  86. columns = ['date', 'year', 'month', 'day', 'day_of_week', 'day_of_year',
  87. 'week', 'quarter']
  88.  
  89. def column_exps(exp):
  90. return [ exp, func.YEAR(exp), func.MONTH(exp), func.DAY(exp),
  91. func.DATEPART( text('dw'), exp),
  92. func.DATEPART( text('dy'), exp),
  93. func.DATEPART( text('wk'), exp),
  94. func.DATEPART( text('q'), exp) ]
  95.  
  96. with CommonTableExpression.create('all_dates', columns) as all_dates:
  97.  
  98. start_exp = cast(bindparam('start', type_=DateTime), DateTime)
  99. stop_exp = cast(bindparam('stop', type_=DateTime), DateTime)
  100. step_exp = bindparam('step', type_=Integer)
  101.  
  102. next_exp = func.DATEADD( text('dd'), step_exp, all_dates.c.date )
  103.  
  104. s1 = select(column_exps(start_exp))
  105. s2 = select(column_exps(next_exp), from_obj=all_dates).where(next_exp <= stop_exp)
  106. s = s1.union_all(s2)
  107.  
  108. all_dates = SelectFromCTE(all_dates, s)
  109.  
  110. from sqlalchemy.orm import mapper
  111.  
  112. class Date(object):
  113. query = Session.query_property()
  114.  
  115. @classmethod
  116. def range(cls, start, stop, step=1):
  117. return cls.query.params(start=start, stop=stop, step=step)
  118.  
  119. mapper(Date, all_dates, primary_key=[all_dates.c.date])
  120.  
  121. query = Date.range('2011-01-01 00:00:00', '2012-02-01 00:00:00') \
  122. .filter(Date.day_of_week == 7) \
  123. .order_by(Date.date.desc())
  124.  
  125. for d in query:
  126. print d.date, "\t", d.year, "\t", d.month, "\t", d.day, "\t", \
  127. d.day_of_week, "\t", d.day_of_year, "\t", d.week, "\t", d.quarter
Add Comment
Please, Sign In to add comment