11from itertools import chain
22
33from django .db .models .aggregates import Avg , Count , StdDev , Variance
4- from django .db .models .expressions import Ref , Value
4+ from django .db .models .expressions import OrderBy , Ref , Value
55from django .db .models .functions import ConcatPair , Greatest , Least , Length , Substr
66from django .db .models .sql import compiler
77from django .db .transaction import TransactionManagementError
@@ -39,6 +39,14 @@ def _as_sql_least(self, compiler, connection):
3939def _as_sql_length (self , compiler , connection ):
4040 return self .as_sql (compiler , connection , function = 'LEN' )
4141
42+ def _as_sql_order_by (self , compiler , connection ):
43+ template = None
44+ if self .nulls_last :
45+ template = 'CASE WHEN %(expression)s IS NULL THEN 1 ELSE 0 END, %(expression)s %(ordering)s'
46+ if self .nulls_first :
47+ template = 'CASE WHEN %(expression)s IS NULL THEN 0 ELSE 1 END, %(expression)s %(ordering)s'
48+ return self .as_sql (compiler , connection , template = template )
49+
4250def _as_sql_stddev (self , compiler , connection ):
4351 function = 'STDEV'
4452 if self .function == 'STDDEV_POP' :
@@ -59,15 +67,14 @@ def _as_sql_variance(self, compiler, connection):
5967
6068class SQLCompiler (compiler .SQLCompiler ):
6169
62- def as_sql (self , with_limits = True , with_col_aliases = False , subquery = False ):
70+ def as_sql (self , with_limits = True , with_col_aliases = False ):
6371 """
6472 Creates the SQL for this query. Returns the SQL string and list of
6573 parameters.
6674
6775 If 'with_limits' is False, any limit/offset information is not included
6876 in the query.
6977 """
70- self .subquery = subquery
7178 refcounts_before = self .query .alias_refcount .copy ()
7279 try :
7380 extra_select , order_by , group_by = self .pre_sql_setup ()
@@ -88,94 +95,107 @@ def as_sql(self, with_limits=True, with_col_aliases=False, subquery=False):
8895 # docstring of get_from_clause() for details.
8996 from_ , f_params = self .get_from_clause ()
9097
98+ for_update_part = None
9199 where , w_params = self .compile (self .where ) if self .where is not None else ("" , [])
92100 having , h_params = self .compile (self .having ) if self .having is not None else ("" , [])
93- params = []
94- result = ['SELECT' ]
95-
96- if self .query .distinct :
97- result .append (self .connection .ops .distinct_sql (distinct_fields ))
98-
99- # SQL Server requires the keword for limitting at the begenning
100- if do_limit and not do_offset :
101- result .append ('TOP %d' % high_mark )
102-
103- out_cols = []
104- col_idx = 1
105- for _ , (s_sql , s_params ), alias in self .select + extra_select :
106- if alias :
107- s_sql = '%s AS %s' % (s_sql , self .connection .ops .quote_name (alias ))
108- elif with_col_aliases or do_offset_emulation :
109- s_sql = '%s AS %s' % (s_sql , 'Col%d' % col_idx )
110- col_idx += 1
111- params .extend (s_params )
112- out_cols .append (s_sql )
113-
114- # SQL Server requires an order-by clause for offsetting
115- if do_offset :
116- meta = self .query .get_meta ()
117- qn = self .quote_name_unless_alias
118- offsetting_order_by = '%s.%s' % (qn (meta .db_table ), qn (meta .pk .db_column or meta .pk .column ))
119- if do_offset_emulation :
120- if order_by :
121- ordering = []
122- for expr , (o_sql , o_params , _ ) in order_by :
123- # value_expression in OVER clause cannot refer to
124- # expressions or aliases in the select list. See:
125- # http://msdn.microsoft.com/en-us/library/ms189461.aspx
126- src = next (iter (expr .get_source_expressions ()))
127- if isinstance (src , Ref ):
128- src = next (iter (src .get_source_expressions ()))
129- o_sql , _ = src .as_sql (self , self .connection )
130- odir = 'DESC' if expr .descending else 'ASC'
131- o_sql = '%s %s' % (o_sql , odir )
132- ordering .append (o_sql )
133- params .extend (o_params )
134- offsetting_order_by = ', ' .join (ordering )
135- order_by = []
136- out_cols .append ('ROW_NUMBER() OVER (ORDER BY %s) AS [rn]' % offsetting_order_by )
137- elif not order_by :
138- order_by .append (((None , ('%s ASC' % offsetting_order_by , [], None ))))
139-
140- result .append (', ' .join (out_cols ))
141-
142- if self .query .select_for_update and self .connection .features .has_select_for_update :
143- if self .connection .get_autocommit ():
144- raise TransactionManagementError (
145- "select_for_update cannot be used outside of a transaction."
146- )
147-
148- # If we've been asked for a NOWAIT query but the backend does
149- # not support it, raise a DatabaseError otherwise we could get
150- # an unexpected deadlock.
151- nowait = self .query .select_for_update_nowait
152- if nowait and not self .connection .features .has_select_for_update_nowait :
153- raise DatabaseError ('NOWAIT is not supported on this database backend.' )
154- from_ .insert (1 , self .connection .ops .for_update_sql (nowait = nowait ))
155-
156- result .append ('FROM' )
157- result .extend (from_ )
158- params .extend (f_params )
159-
160- if where :
161- result .append ('WHERE %s' % where )
162- params .extend (w_params )
163-
164- grouping = []
165- for g_sql , g_params in group_by :
166- grouping .append (g_sql )
167- params .extend (g_params )
168- if grouping :
169- if distinct_fields :
170- raise NotImplementedError (
171- "annotate() + distinct(fields) is not implemented." )
172- if not order_by :
173- order_by = self .connection .ops .force_no_ordering ()
174- result .append ('GROUP BY %s' % ', ' .join (grouping ))
175-
176- if having :
177- result .append ('HAVING %s' % having )
178- params .extend (h_params )
101+
102+ combinator = self .query .combinator
103+ features = self .connection .features
104+ if combinator :
105+ if not getattr (features , 'supports_select_{}' .format (combinator )):
106+ raise DatabaseError ('{} not supported on this database backend.' .format (combinator ))
107+ result , params = self .get_combinator_sql (combinator , self .query .combinator_all )
108+ else :
109+ params = []
110+ result = ['SELECT' ]
111+
112+ if self .query .distinct :
113+ result .append (self .connection .ops .distinct_sql (distinct_fields ))
114+
115+ # SQL Server requires the keword for limitting at the begenning
116+ if do_limit and not do_offset :
117+ result .append ('TOP %d' % high_mark )
118+
119+ out_cols = []
120+ col_idx = 1
121+ for _ , (s_sql , s_params ), alias in self .select + extra_select :
122+ if alias :
123+ s_sql = '%s AS %s' % (s_sql , self .connection .ops .quote_name (alias ))
124+ elif with_col_aliases or do_offset_emulation :
125+ s_sql = '%s AS %s' % (s_sql , 'Col%d' % col_idx )
126+ col_idx += 1
127+ params .extend (s_params )
128+ out_cols .append (s_sql )
129+
130+ # SQL Server requires an order-by clause for offsetting
131+ if do_offset :
132+ meta = self .query .get_meta ()
133+ qn = self .quote_name_unless_alias
134+ offsetting_order_by = '%s.%s' % (qn (meta .db_table ), qn (meta .pk .db_column or meta .pk .column ))
135+ if do_offset_emulation :
136+ if order_by :
137+ ordering = []
138+ for expr , (o_sql , o_params , _ ) in order_by :
139+ # value_expression in OVER clause cannot refer to
140+ # expressions or aliases in the select list. See:
141+ # http://msdn.microsoft.com/en-us/library/ms189461.aspx
142+ src = next (iter (expr .get_source_expressions ()))
143+ if isinstance (src , Ref ):
144+ src = next (iter (src .get_source_expressions ()))
145+ o_sql , _ = src .as_sql (self , self .connection )
146+ odir = 'DESC' if expr .descending else 'ASC'
147+ o_sql = '%s %s' % (o_sql , odir )
148+ ordering .append (o_sql )
149+ params .extend (o_params )
150+ offsetting_order_by = ', ' .join (ordering )
151+ order_by = []
152+ out_cols .append ('ROW_NUMBER() OVER (ORDER BY %s) AS [rn]' % offsetting_order_by )
153+ elif not order_by :
154+ order_by .append (((None , ('%s ASC' % offsetting_order_by , [], None ))))
155+
156+ result .append (', ' .join (out_cols ))
157+
158+ if self .query .select_for_update and self .connection .features .has_select_for_update :
159+ if self .connection .get_autocommit ():
160+ raise TransactionManagementError ('select_for_update cannot be used outside of a transaction.' )
161+
162+ nowait = self .query .select_for_update_nowait
163+ skip_locked = self .query .select_for_update_skip_locked
164+ # If it's a NOWAIT/SKIP LOCKED query but the backend
165+ # doesn't support it, raise a DatabaseError to prevent a
166+ # possible deadlock.
167+ if nowait and not self .connection .features .has_select_for_update_nowait :
168+ raise DatabaseError ('NOWAIT is not supported on this database backend.' )
169+ elif skip_locked and not self .connection .features .has_select_for_update_skip_locked :
170+ raise DatabaseError ('SKIP LOCKED is not supported on this database backend.' )
171+ for_update_part = self .connection .ops .for_update_sql (nowait = nowait , skip_locked = skip_locked )
172+
173+ if for_update_part and self .connection .features .for_update_after_from :
174+ from_ .insert (1 , for_update_part )
175+
176+ result .append ('FROM' )
177+ result .extend (from_ )
178+ params .extend (f_params )
179+
180+ if where :
181+ result .append ('WHERE %s' % where )
182+ params .extend (w_params )
183+
184+ grouping = []
185+ for g_sql , g_params in group_by :
186+ grouping .append (g_sql )
187+ params .extend (g_params )
188+ if grouping :
189+ if distinct_fields :
190+ raise NotImplementedError (
191+ "annotate() + distinct(fields) is not implemented." )
192+ if not order_by :
193+ order_by = self .connection .ops .force_no_ordering ()
194+ result .append ('GROUP BY %s' % ', ' .join (grouping ))
195+
196+ if having :
197+ result .append ('HAVING %s' % having )
198+ params .extend (h_params )
179199
180200 if order_by :
181201 ordering = []
@@ -196,7 +216,7 @@ def as_sql(self, with_limits=True, with_col_aliases=False, subquery=False):
196216 result .append ('BETWEEN %d AND %d' % (low_mark + 1 , high_mark ))
197217 else :
198218 result .append ('>= %d' % (low_mark + 1 ))
199- if not subquery :
219+ if not self . query . subquery :
200220 result .append ('ORDER BY X.rn' )
201221 else :
202222 result .append ('OFFSET %d ROWS' % low_mark )
@@ -226,6 +246,8 @@ def _as_microsoft(self, node):
226246 as_microsoft = _as_sql_least
227247 elif isinstance (node , Length ):
228248 as_microsoft = _as_sql_length
249+ elif isinstance (node , OrderBy ):
250+ as_microsoft = _as_sql_order_by
229251 elif isinstance (node , StdDev ):
230252 as_microsoft = _as_sql_stddev
231253 elif isinstance (node , Substr ):
@@ -288,7 +310,7 @@ def as_sql(self):
288310 ]
289311
290312 if has_fields :
291- if opts .has_auto_field :
313+ if opts .auto_field is not None :
292314 # db_column is None if not explicitly specified by model field
293315 auto_field_column = opts .auto_field .db_column or opts .auto_field .column
294316 columns = [f .column for f in fields ]
0 commit comments