where.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. """
  2. Code to manage the creation and SQL rendering of 'where' constraints.
  3. """
  4. import collections
  5. import datetime
  6. from itertools import repeat
  7. import warnings
  8. from django.conf import settings
  9. from django.db.models.fields import DateTimeField, Field
  10. from django.db.models.sql.datastructures import EmptyResultSet, Empty
  11. from django.db.models.sql.aggregates import Aggregate
  12. from django.utils.deprecation import RemovedInDjango19Warning
  13. from django.utils.six.moves import xrange
  14. from django.utils import timezone
  15. from django.utils import tree
  16. # Connection types
  17. AND = 'AND'
  18. OR = 'OR'
  19. class EmptyShortCircuit(Exception):
  20. """
  21. Internal exception used to indicate that a "matches nothing" node should be
  22. added to the where-clause.
  23. """
  24. pass
  25. class WhereNode(tree.Node):
  26. """
  27. Used to represent the SQL where-clause.
  28. The class is tied to the Query class that created it (in order to create
  29. the correct SQL).
  30. A child is usually a tuple of:
  31. (Constraint(alias, targetcol, field), lookup_type, value)
  32. where value can be either raw Python value, or Query, ExpressionNode or
  33. something else knowing how to turn itself into SQL.
  34. However, a child could also be any class with as_sql() and either
  35. relabeled_clone() method or relabel_aliases() and clone() methods. The
  36. second alternative should be used if the alias is not the only mutable
  37. variable.
  38. """
  39. default = AND
  40. def _prepare_data(self, data):
  41. """
  42. Prepare data for addition to the tree. If the data is a list or tuple,
  43. it is expected to be of the form (obj, lookup_type, value), where obj
  44. is a Constraint object, and is then slightly munged before being
  45. stored (to avoid storing any reference to field objects). Otherwise,
  46. the 'data' is stored unchanged and can be any class with an 'as_sql()'
  47. method.
  48. """
  49. if not isinstance(data, (list, tuple)):
  50. return data
  51. obj, lookup_type, value = data
  52. if isinstance(value, collections.Iterator):
  53. # Consume any generators immediately, so that we can determine
  54. # emptiness and transform any non-empty values correctly.
  55. value = list(value)
  56. # The "value_annotation" parameter is used to pass auxiliary information
  57. # about the value(s) to the query construction. Specifically, datetime
  58. # and empty values need special handling. Other types could be used
  59. # here in the future (using Python types is suggested for consistency).
  60. if (isinstance(value, datetime.datetime)
  61. or (isinstance(obj.field, DateTimeField) and lookup_type != 'isnull')):
  62. value_annotation = datetime.datetime
  63. elif hasattr(value, 'value_annotation'):
  64. value_annotation = value.value_annotation
  65. else:
  66. value_annotation = bool(value)
  67. if hasattr(obj, "prepare"):
  68. value = obj.prepare(lookup_type, value)
  69. return (obj, lookup_type, value_annotation, value)
  70. def as_sql(self, qn, connection):
  71. """
  72. Returns the SQL version of the where clause and the value to be
  73. substituted in. Returns '', [] if this node matches everything,
  74. None, [] if this node is empty, and raises EmptyResultSet if this
  75. node can't match anything.
  76. """
  77. # Note that the logic here is made slightly more complex than
  78. # necessary because there are two kind of empty nodes: Nodes
  79. # containing 0 children, and nodes that are known to match everything.
  80. # A match-everything node is different than empty node (which also
  81. # technically matches everything) for backwards compatibility reasons.
  82. # Refs #5261.
  83. result = []
  84. result_params = []
  85. everything_childs, nothing_childs = 0, 0
  86. non_empty_childs = len(self.children)
  87. for child in self.children:
  88. try:
  89. if hasattr(child, 'as_sql'):
  90. sql, params = qn.compile(child)
  91. else:
  92. # A leaf node in the tree.
  93. sql, params = self.make_atom(child, qn, connection)
  94. except EmptyResultSet:
  95. nothing_childs += 1
  96. else:
  97. if sql:
  98. result.append(sql)
  99. result_params.extend(params)
  100. else:
  101. if sql is None:
  102. # Skip empty childs totally.
  103. non_empty_childs -= 1
  104. continue
  105. everything_childs += 1
  106. # Check if this node matches nothing or everything.
  107. # First check the amount of full nodes and empty nodes
  108. # to make this node empty/full.
  109. if self.connector == AND:
  110. full_needed, empty_needed = non_empty_childs, 1
  111. else:
  112. full_needed, empty_needed = 1, non_empty_childs
  113. # Now, check if this node is full/empty using the
  114. # counts.
  115. if empty_needed - nothing_childs <= 0:
  116. if self.negated:
  117. return '', []
  118. else:
  119. raise EmptyResultSet
  120. if full_needed - everything_childs <= 0:
  121. if self.negated:
  122. raise EmptyResultSet
  123. else:
  124. return '', []
  125. if non_empty_childs == 0:
  126. # All the child nodes were empty, so this one is empty, too.
  127. return None, []
  128. conn = ' %s ' % self.connector
  129. sql_string = conn.join(result)
  130. if sql_string:
  131. if self.negated:
  132. # Some backends (Oracle at least) need parentheses
  133. # around the inner SQL in the negated case, even if the
  134. # inner SQL contains just a single expression.
  135. sql_string = 'NOT (%s)' % sql_string
  136. elif len(result) > 1:
  137. sql_string = '(%s)' % sql_string
  138. return sql_string, result_params
  139. def get_group_by_cols(self):
  140. cols = []
  141. for child in self.children:
  142. if hasattr(child, 'get_group_by_cols'):
  143. cols.extend(child.get_group_by_cols())
  144. else:
  145. if isinstance(child[0], Constraint):
  146. cols.append((child[0].alias, child[0].col))
  147. if hasattr(child[3], 'get_group_by_cols'):
  148. cols.extend(child[3].get_group_by_cols())
  149. return cols
  150. def make_atom(self, child, qn, connection):
  151. """
  152. Turn a tuple (Constraint(table_alias, column_name, db_type),
  153. lookup_type, value_annotation, params) into valid SQL.
  154. The first item of the tuple may also be an Aggregate.
  155. Returns the string for the SQL fragment and the parameters to use for
  156. it.
  157. """
  158. warnings.warn(
  159. "The make_atom() method will be removed in Django 1.9. Use Lookup class instead.",
  160. RemovedInDjango19Warning)
  161. lvalue, lookup_type, value_annotation, params_or_value = child
  162. field_internal_type = lvalue.field.get_internal_type() if lvalue.field else None
  163. if isinstance(lvalue, Constraint):
  164. try:
  165. lvalue, params = lvalue.process(lookup_type, params_or_value, connection)
  166. except EmptyShortCircuit:
  167. raise EmptyResultSet
  168. elif isinstance(lvalue, Aggregate):
  169. params = lvalue.field.get_db_prep_lookup(lookup_type, params_or_value, connection)
  170. else:
  171. raise TypeError("'make_atom' expects a Constraint or an Aggregate "
  172. "as the first item of its 'child' argument.")
  173. if isinstance(lvalue, tuple):
  174. # A direct database column lookup.
  175. field_sql, field_params = self.sql_for_columns(lvalue, qn, connection, field_internal_type), []
  176. else:
  177. # A smart object with an as_sql() method.
  178. field_sql, field_params = qn.compile(lvalue)
  179. is_datetime_field = value_annotation is datetime.datetime
  180. cast_sql = connection.ops.datetime_cast_sql() if is_datetime_field else '%s'
  181. if hasattr(params, 'as_sql'):
  182. extra, params = qn.compile(params)
  183. cast_sql = ''
  184. else:
  185. extra = ''
  186. params = field_params + params
  187. if (len(params) == 1 and params[0] == '' and lookup_type == 'exact'
  188. and connection.features.interprets_empty_strings_as_nulls):
  189. lookup_type = 'isnull'
  190. value_annotation = True
  191. if lookup_type in connection.operators:
  192. format = "%s %%s %%s" % (connection.ops.lookup_cast(lookup_type),)
  193. return (format % (field_sql,
  194. connection.operators[lookup_type] % cast_sql,
  195. extra), params)
  196. if lookup_type == 'in':
  197. if not value_annotation:
  198. raise EmptyResultSet
  199. if extra:
  200. return ('%s IN %s' % (field_sql, extra), params)
  201. max_in_list_size = connection.ops.max_in_list_size()
  202. if max_in_list_size and len(params) > max_in_list_size:
  203. # Break up the params list into an OR of manageable chunks.
  204. in_clause_elements = ['(']
  205. for offset in xrange(0, len(params), max_in_list_size):
  206. if offset > 0:
  207. in_clause_elements.append(' OR ')
  208. in_clause_elements.append('%s IN (' % field_sql)
  209. group_size = min(len(params) - offset, max_in_list_size)
  210. param_group = ', '.join(repeat('%s', group_size))
  211. in_clause_elements.append(param_group)
  212. in_clause_elements.append(')')
  213. in_clause_elements.append(')')
  214. return ''.join(in_clause_elements), params
  215. else:
  216. return ('%s IN (%s)' % (field_sql,
  217. ', '.join(repeat('%s', len(params)))),
  218. params)
  219. elif lookup_type in ('range', 'year'):
  220. return ('%s BETWEEN %%s and %%s' % field_sql, params)
  221. elif is_datetime_field and lookup_type in ('month', 'day', 'week_day',
  222. 'hour', 'minute', 'second'):
  223. tzname = timezone.get_current_timezone_name() if settings.USE_TZ else None
  224. sql, tz_params = connection.ops.datetime_extract_sql(lookup_type, field_sql, tzname)
  225. return ('%s = %%s' % sql, tz_params + params)
  226. elif lookup_type in ('month', 'day', 'week_day'):
  227. return ('%s = %%s'
  228. % connection.ops.date_extract_sql(lookup_type, field_sql), params)
  229. elif lookup_type == 'isnull':
  230. assert value_annotation in (True, False), "Invalid value_annotation for isnull"
  231. return ('%s IS %sNULL' % (field_sql, ('' if value_annotation else 'NOT ')), ())
  232. elif lookup_type == 'search':
  233. return (connection.ops.fulltext_search_sql(field_sql), params)
  234. elif lookup_type in ('regex', 'iregex'):
  235. return connection.ops.regex_lookup(lookup_type) % (field_sql, cast_sql), params
  236. raise TypeError('Invalid lookup_type: %r' % lookup_type)
  237. def sql_for_columns(self, data, qn, connection, internal_type=None):
  238. """
  239. Returns the SQL fragment used for the left-hand side of a column
  240. constraint (for example, the "T1.foo" portion in the clause
  241. "WHERE ... T1.foo = 6") and a list of parameters.
  242. """
  243. table_alias, name, db_type = data
  244. if table_alias:
  245. lhs = '%s.%s' % (qn(table_alias), qn(name))
  246. else:
  247. lhs = qn(name)
  248. return connection.ops.field_cast_sql(db_type, internal_type) % lhs
  249. def relabel_aliases(self, change_map):
  250. """
  251. Relabels the alias values of any children. 'change_map' is a dictionary
  252. mapping old (current) alias values to the new values.
  253. """
  254. for pos, child in enumerate(self.children):
  255. if hasattr(child, 'relabel_aliases'):
  256. # For example another WhereNode
  257. child.relabel_aliases(change_map)
  258. elif hasattr(child, 'relabeled_clone'):
  259. self.children[pos] = child.relabeled_clone(change_map)
  260. elif isinstance(child, (list, tuple)):
  261. # tuple starting with Constraint
  262. child = (child[0].relabeled_clone(change_map),) + child[1:]
  263. if hasattr(child[3], 'relabeled_clone'):
  264. child = (child[0], child[1], child[2]) + (
  265. child[3].relabeled_clone(change_map),)
  266. self.children[pos] = child
  267. def clone(self):
  268. """
  269. Creates a clone of the tree. Must only be called on root nodes (nodes
  270. with empty subtree_parents). Childs must be either (Contraint, lookup,
  271. value) tuples, or objects supporting .clone().
  272. """
  273. clone = self.__class__._new_instance(
  274. children=[], connector=self.connector, negated=self.negated)
  275. for child in self.children:
  276. if hasattr(child, 'clone'):
  277. clone.children.append(child.clone())
  278. else:
  279. clone.children.append(child)
  280. return clone
  281. class EmptyWhere(WhereNode):
  282. def add(self, data, connector):
  283. return
  284. def as_sql(self, qn=None, connection=None):
  285. raise EmptyResultSet
  286. class EverythingNode(object):
  287. """
  288. A node that matches everything.
  289. """
  290. def as_sql(self, qn=None, connection=None):
  291. return '', []
  292. class NothingNode(object):
  293. """
  294. A node that matches nothing.
  295. """
  296. def as_sql(self, qn=None, connection=None):
  297. raise EmptyResultSet
  298. class ExtraWhere(object):
  299. def __init__(self, sqls, params):
  300. self.sqls = sqls
  301. self.params = params
  302. def as_sql(self, qn=None, connection=None):
  303. sqls = ["(%s)" % sql for sql in self.sqls]
  304. return " AND ".join(sqls), list(self.params or ())
  305. class Constraint(object):
  306. """
  307. An object that can be passed to WhereNode.add() and knows how to
  308. pre-process itself prior to including in the WhereNode.
  309. """
  310. def __init__(self, alias, col, field):
  311. warnings.warn(
  312. "The Constraint class will be removed in Django 1.9. Use Lookup class instead.",
  313. RemovedInDjango19Warning)
  314. self.alias, self.col, self.field = alias, col, field
  315. def prepare(self, lookup_type, value):
  316. if self.field and not hasattr(value, 'as_sql'):
  317. return self.field.get_prep_lookup(lookup_type, value)
  318. return value
  319. def process(self, lookup_type, value, connection):
  320. """
  321. Returns a tuple of data suitable for inclusion in a WhereNode
  322. instance.
  323. """
  324. # Because of circular imports, we need to import this here.
  325. from django.db.models.base import ObjectDoesNotExist
  326. try:
  327. if self.field:
  328. params = self.field.get_db_prep_lookup(lookup_type, value,
  329. connection=connection, prepared=True)
  330. db_type = self.field.db_type(connection=connection)
  331. else:
  332. # This branch is used at times when we add a comparison to NULL
  333. # (we don't really want to waste time looking up the associated
  334. # field object at the calling location).
  335. params = Field().get_db_prep_lookup(lookup_type, value,
  336. connection=connection, prepared=True)
  337. db_type = None
  338. except ObjectDoesNotExist:
  339. raise EmptyShortCircuit
  340. return (self.alias, self.col, db_type), params
  341. def relabeled_clone(self, change_map):
  342. if self.alias not in change_map:
  343. return self
  344. else:
  345. new = Empty()
  346. new.__class__ = self.__class__
  347. new.alias, new.col, new.field = change_map[self.alias], self.col, self.field
  348. return new
  349. class SubqueryConstraint(object):
  350. def __init__(self, alias, columns, targets, query_object):
  351. self.alias = alias
  352. self.columns = columns
  353. self.targets = targets
  354. self.query_object = query_object
  355. def as_sql(self, qn, connection):
  356. query = self.query_object
  357. # QuerySet was sent
  358. if hasattr(query, 'values'):
  359. if query._db and connection.alias != query._db:
  360. raise ValueError("Can't do subqueries with queries on different DBs.")
  361. # Do not override already existing values.
  362. if not hasattr(query, 'field_names'):
  363. query = query.values(*self.targets)
  364. else:
  365. query = query._clone()
  366. query = query.query
  367. if query.can_filter():
  368. # If there is no slicing in use, then we can safely drop all ordering
  369. query.clear_ordering(True)
  370. query_compiler = query.get_compiler(connection=connection)
  371. return query_compiler.as_subquery_condition(self.alias, self.columns, qn)
  372. def relabel_aliases(self, change_map):
  373. self.alias = change_map.get(self.alias, self.alias)
  374. def clone(self):
  375. return self.__class__(
  376. self.alias, self.columns, self.targets,
  377. self.query_object)