1
by brian
clean slate |
1 |
/* Copyright (C) 2000-2006 MySQL AB
|
2 |
||
3 |
This program is free software; you can redistribute it and/or modify
|
|
4 |
it under the terms of the GNU General Public License as published by
|
|
5 |
the Free Software Foundation; version 2 of the License.
|
|
6 |
||
7 |
This program is distributed in the hope that it will be useful,
|
|
8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10 |
GNU General Public License for more details.
|
|
11 |
||
12 |
You should have received a copy of the GNU General Public License
|
|
13 |
along with this program; if not, write to the Free Software
|
|
14 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
15 |
||
16 |
||
17 |
/* classes for sum functions */
|
|
18 |
||
19 |
#ifdef USE_PRAGMA_INTERFACE
|
|
20 |
#pragma interface /* gcc class implementation */ |
|
21 |
#endif
|
|
22 |
||
23 |
#include <my_tree.h> |
|
24 |
||
25 |
/*
|
|
26 |
Class Item_sum is the base class used for special expressions that SQL calls
|
|
27 |
'set functions'. These expressions are formed with the help of aggregate
|
|
28 |
functions such as SUM, MAX, GROUP_CONCAT etc.
|
|
29 |
||
30 |
GENERAL NOTES
|
|
31 |
||
32 |
A set function cannot be used in certain positions where expressions are
|
|
33 |
accepted. There are some quite explicable restrictions for the usage of
|
|
34 |
set functions.
|
|
35 |
||
36 |
In the query:
|
|
37 |
SELECT AVG(b) FROM t1 WHERE SUM(b) > 20 GROUP by a
|
|
38 |
the usage of the set function AVG(b) is legal, while the usage of SUM(b)
|
|
39 |
is illegal. A WHERE condition must contain expressions that can be
|
|
40 |
evaluated for each row of the table. Yet the expression SUM(b) can be
|
|
41 |
evaluated only for each group of rows with the same value of column a.
|
|
42 |
In the query:
|
|
43 |
SELECT AVG(b) FROM t1 WHERE c > 30 GROUP BY a HAVING SUM(b) > 20
|
|
44 |
both set function expressions AVG(b) and SUM(b) are legal.
|
|
45 |
||
46 |
We can say that in a query without nested selects an occurrence of a
|
|
47 |
set function in an expression of the SELECT list or/and in the HAVING
|
|
48 |
clause is legal, while in the WHERE clause it's illegal.
|
|
49 |
||
50 |
The general rule to detect whether a set function is legal in a query with
|
|
51 |
nested subqueries is much more complicated.
|
|
52 |
||
53 |
Consider the the following query:
|
|
54 |
SELECT t1.a FROM t1 GROUP BY t1.a
|
|
55 |
HAVING t1.a > ALL (SELECT t2.c FROM t2 WHERE SUM(t1.b) < t2.c).
|
|
56 |
The set function SUM(b) is used here in the WHERE clause of the subquery.
|
|
57 |
Nevertheless it is legal since it is under the HAVING clause of the query
|
|
58 |
to which this function relates. The expression SUM(t1.b) is evaluated
|
|
59 |
for each group defined in the main query, not for groups of the subquery.
|
|
60 |
||
61 |
The problem of finding the query where to aggregate a particular
|
|
62 |
set function is not so simple as it seems to be.
|
|
63 |
||
64 |
In the query:
|
|
65 |
SELECT t1.a FROM t1 GROUP BY t1.a
|
|
66 |
HAVING t1.a > ALL(SELECT t2.c FROM t2 GROUP BY t2.c
|
|
67 |
HAVING SUM(t1.a) < t2.c)
|
|
68 |
the set function can be evaluated for both outer and inner selects.
|
|
69 |
If we evaluate SUM(t1.a) for the outer query then we get the value of t1.a
|
|
70 |
multiplied by the cardinality of a group in table t1. In this case
|
|
71 |
in each correlated subquery SUM(t1.a) is used as a constant. But we also
|
|
72 |
can evaluate SUM(t1.a) for the inner query. In this case t1.a will be a
|
|
73 |
constant for each correlated subquery and summation is performed
|
|
74 |
for each group of table t2.
|
|
75 |
(Here it makes sense to remind that the query
|
|
76 |
SELECT c FROM t GROUP BY a HAVING SUM(1) < a
|
|
77 |
is quite legal in our SQL).
|
|
78 |
||
79 |
So depending on what query we assign the set function to we
|
|
80 |
can get different result sets.
|
|
81 |
||
82 |
The general rule to detect the query where a set function is to be
|
|
83 |
evaluated can be formulated as follows.
|
|
84 |
Consider a set function S(E) where E is an expression with occurrences
|
|
85 |
of column references C1, ..., CN. Resolve these column references against
|
|
86 |
subqueries that contain the set function S(E). Let Q be the innermost
|
|
87 |
subquery of those subqueries. (It should be noted here that S(E)
|
|
88 |
in no way can be evaluated in the subquery embedding the subquery Q,
|
|
89 |
otherwise S(E) would refer to at least one unbound column reference)
|
|
90 |
If S(E) is used in a construct of Q where set functions are allowed then
|
|
91 |
we evaluate S(E) in Q.
|
|
92 |
Otherwise we look for a innermost subquery containing S(E) of those where
|
|
93 |
usage of S(E) is allowed.
|
|
94 |
||
95 |
Let's demonstrate how this rule is applied to the following queries.
|
|
96 |
||
97 |
1. SELECT t1.a FROM t1 GROUP BY t1.a
|
|
98 |
HAVING t1.a > ALL(SELECT t2.b FROM t2 GROUP BY t2.b
|
|
99 |
HAVING t2.b > ALL(SELECT t3.c FROM t3 GROUP BY t3.c
|
|
100 |
HAVING SUM(t1.a+t2.b) < t3.c))
|
|
101 |
For this query the set function SUM(t1.a+t2.b) depends on t1.a and t2.b
|
|
102 |
with t1.a defined in the outermost query, and t2.b defined for its
|
|
103 |
subquery. The set function is in the HAVING clause of the subquery and can
|
|
104 |
be evaluated in this subquery.
|
|
105 |
||
106 |
2. SELECT t1.a FROM t1 GROUP BY t1.a
|
|
107 |
HAVING t1.a > ALL(SELECT t2.b FROM t2
|
|
108 |
WHERE t2.b > ALL (SELECT t3.c FROM t3 GROUP BY t3.c
|
|
109 |
HAVING SUM(t1.a+t2.b) < t3.c))
|
|
110 |
Here the set function SUM(t1.a+t2.b)is in the WHERE clause of the second
|
|
111 |
subquery - the most upper subquery where t1.a and t2.b are defined.
|
|
112 |
If we evaluate the function in this subquery we violate the context rules.
|
|
113 |
So we evaluate the function in the third subquery (over table t3) where it
|
|
114 |
is used under the HAVING clause.
|
|
115 |
||
116 |
3. SELECT t1.a FROM t1 GROUP BY t1.a
|
|
117 |
HAVING t1.a > ALL(SELECT t2.b FROM t2
|
|
118 |
WHERE t2.b > ALL (SELECT t3.c FROM t3
|
|
119 |
WHERE SUM(t1.a+t2.b) < t3.c))
|
|
120 |
In this query evaluation of SUM(t1.a+t2.b) is not legal neither in the second
|
|
121 |
nor in the third subqueries. So this query is invalid.
|
|
122 |
||
123 |
Mostly set functions cannot be nested. In the query
|
|
124 |
SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20
|
|
125 |
the expression SUM(b) is not acceptable, though it is under a HAVING clause.
|
|
126 |
Yet it is acceptable in the query:
|
|
127 |
SELECT t.1 FROM t1 GROUP BY t1.a HAVING SUM(t1.b) > 20.
|
|
128 |
||
129 |
An argument of a set function does not have to be a reference to a table
|
|
130 |
column as we saw it in examples above. This can be a more complex expression
|
|
131 |
SELECT t1.a FROM t1 GROUP BY t1.a HAVING SUM(t1.b+1) > 20.
|
|
132 |
The expression SUM(t1.b+1) has a very clear semantics in this context:
|
|
133 |
we sum up the values of t1.b+1 where t1.b varies for all values within a
|
|
134 |
group of rows that contain the same t1.a value.
|
|
135 |
||
136 |
A set function for an outer query yields a constant within a subquery. So
|
|
137 |
the semantics of the query
|
|
138 |
SELECT t1.a FROM t1 GROUP BY t1.a
|
|
139 |
HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c
|
|
140 |
HAVING AVG(t2.c+SUM(t1.b)) > 20)
|
|
141 |
is still clear. For a group of the rows with the same t1.a values we
|
|
142 |
calculate the value of SUM(t1.b). This value 's' is substituted in the
|
|
143 |
the subquery:
|
|
144 |
SELECT t2.c FROM t2 GROUP BY t2.c HAVING AVG(t2.c+s)
|
|
145 |
than returns some result set.
|
|
146 |
||
147 |
By the same reason the following query with a subquery
|
|
148 |
SELECT t1.a FROM t1 GROUP BY t1.a
|
|
149 |
HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c
|
|
150 |
HAVING AVG(SUM(t1.b)) > 20)
|
|
151 |
is also acceptable.
|
|
152 |
||
153 |
IMPLEMENTATION NOTES
|
|
154 |
||
155 |
Three methods were added to the class to check the constraints specified
|
|
156 |
in the previous section. These methods utilize several new members.
|
|
157 |
||
158 |
The field 'nest_level' contains the number of the level for the subquery
|
|
159 |
containing the set function. The main SELECT is of level 0, its subqueries
|
|
160 |
are of levels 1, the subqueries of the latter are of level 2 and so on.
|
|
161 |
||
162 |
The field 'aggr_level' is to contain the nest level of the subquery
|
|
163 |
where the set function is aggregated.
|
|
164 |
||
165 |
The field 'max_arg_level' is for the maximun of the nest levels of the
|
|
166 |
unbound column references occurred in the set function. A column reference
|
|
167 |
is unbound within a set function if it is not bound by any subquery
|
|
168 |
used as a subexpression in this function. A column reference is bound by
|
|
169 |
a subquery if it is a reference to the column by which the aggregation
|
|
170 |
of some set function that is used in the subquery is calculated.
|
|
171 |
For the set function used in the query
|
|
172 |
SELECT t1.a FROM t1 GROUP BY t1.a
|
|
173 |
HAVING t1.a > ALL(SELECT t2.b FROM t2 GROUP BY t2.b
|
|
174 |
HAVING t2.b > ALL(SELECT t3.c FROM t3 GROUP BY t3.c
|
|
175 |
HAVING SUM(t1.a+t2.b) < t3.c))
|
|
176 |
the value of max_arg_level is equal to 1 since t1.a is bound in the main
|
|
177 |
query, and t2.b is bound by the first subquery whose nest level is 1.
|
|
178 |
Obviously a set function cannot be aggregated in the subquery whose
|
|
179 |
nest level is less than max_arg_level. (Yet it can be aggregated in the
|
|
180 |
subqueries whose nest level is greater than max_arg_level.)
|
|
181 |
In the query
|
|
182 |
SELECT t.a FROM t1 HAVING AVG(t1.a+(SELECT MIN(t2.c) FROM t2))
|
|
183 |
the value of the max_arg_level for the AVG set function is 0 since
|
|
184 |
the reference t2.c is bound in the subquery.
|
|
185 |
||
186 |
The field 'max_sum_func_level' is to contain the maximum of the
|
|
187 |
nest levels of the set functions that are used as subexpressions of
|
|
188 |
the arguments of the given set function, but not aggregated in any
|
|
189 |
subquery within this set function. A nested set function s1 can be
|
|
190 |
used within set function s0 only if s1.max_sum_func_level <
|
|
191 |
s0.max_sum_func_level. Set function s1 is considered as nested
|
|
192 |
for set function s0 if s1 is not calculated in any subquery
|
|
193 |
within s0.
|
|
194 |
||
195 |
A set function that is used as a subexpression in an argument of another
|
|
196 |
set function refers to the latter via the field 'in_sum_func'.
|
|
197 |
||
198 |
The condition imposed on the usage of set functions are checked when
|
|
199 |
we traverse query subexpressions with the help of the recursive method
|
|
200 |
fix_fields. When we apply this method to an object of the class
|
|
201 |
Item_sum, first, on the descent, we call the method init_sum_func_check
|
|
202 |
that initialize members used at checking. Then, on the ascent, we
|
|
203 |
call the method check_sum_func that validates the set function usage
|
|
204 |
and reports an error if it is illegal.
|
|
205 |
The method register_sum_func serves to link the items for the set functions
|
|
206 |
that are aggregated in the embedding (sub)queries. Circular chains of such
|
|
207 |
functions are attached to the corresponding st_select_lex structures
|
|
208 |
through the field inner_sum_func_list.
|
|
209 |
||
210 |
Exploiting the fact that the members mentioned above are used in one
|
|
211 |
recursive function we could have allocated them on the thread stack.
|
|
212 |
Yet we don't do it now.
|
|
213 |
|
|
214 |
We assume that the nesting level of subquries does not exceed 127.
|
|
215 |
TODO: to catch queries where the limit is exceeded to make the
|
|
216 |
code clean here.
|
|
217 |
|
|
218 |
*/
|
|
219 |
||
220 |
class st_select_lex; |
|
221 |
||
222 |
class Item_sum :public Item_result_field |
|
223 |
{
|
|
224 |
public: |
|
225 |
enum Sumfunctype |
|
226 |
{ COUNT_FUNC, COUNT_DISTINCT_FUNC, SUM_FUNC, SUM_DISTINCT_FUNC, AVG_FUNC, |
|
227 |
AVG_DISTINCT_FUNC, MIN_FUNC, MAX_FUNC, STD_FUNC, |
|
228 |
VARIANCE_FUNC, SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC |
|
229 |
};
|
|
230 |
||
231 |
Item **args, *tmp_args[2]; |
|
232 |
Item **ref_by; /* pointer to a ref to the object used to register it */ |
|
233 |
Item_sum *next; /* next in the circular chain of registered objects */ |
|
234 |
uint arg_count; |
|
235 |
Item_sum *in_sum_func; /* embedding set function if any */ |
|
236 |
st_select_lex * aggr_sel; /* select where the function is aggregated */ |
|
237 |
int8 nest_level; /* number of the nesting level of the set function */ |
|
238 |
int8 aggr_level; /* nesting level of the aggregating subquery */ |
|
239 |
int8 max_arg_level; /* max level of unbound column references */ |
|
240 |
int8 max_sum_func_level;/* max level of aggregation for embedded functions */ |
|
241 |
bool quick_group; /* If incremental update of fields */ |
|
242 |
/*
|
|
243 |
This list is used by the check for mixing non aggregated fields and
|
|
244 |
sum functions in the ONLY_FULL_GROUP_BY_MODE. We save all outer fields
|
|
245 |
directly or indirectly used under this function it as it's unclear
|
|
246 |
at the moment of fixing outer field whether it's aggregated or not.
|
|
247 |
*/
|
|
248 |
List<Item_field> outer_fields; |
|
249 |
||
250 |
protected: |
|
251 |
table_map used_tables_cache; |
|
252 |
bool forced_const; |
|
253 |
||
254 |
public: |
|
255 |
||
256 |
void mark_as_sum_func(); |
|
257 |
Item_sum() :arg_count(0), quick_group(1), forced_const(FALSE) |
|
258 |
{
|
|
259 |
mark_as_sum_func(); |
|
260 |
}
|
|
261 |
Item_sum(Item *a) :args(tmp_args), arg_count(1), quick_group(1), |
|
262 |
forced_const(FALSE) |
|
263 |
{
|
|
264 |
args[0]=a; |
|
265 |
mark_as_sum_func(); |
|
266 |
}
|
|
267 |
Item_sum( Item *a, Item *b ) :args(tmp_args), arg_count(2), quick_group(1), |
|
268 |
forced_const(FALSE) |
|
269 |
{
|
|
270 |
args[0]=a; args[1]=b; |
|
271 |
mark_as_sum_func(); |
|
272 |
}
|
|
273 |
Item_sum(List<Item> &list); |
|
274 |
//Copy constructor, need to perform subselects with temporary tables
|
|
275 |
Item_sum(THD *thd, Item_sum *item); |
|
276 |
enum Type type() const { return SUM_FUNC_ITEM; } |
|
277 |
virtual enum Sumfunctype sum_func () const=0; |
|
278 |
||
279 |
/*
|
|
280 |
This method is similar to add(), but it is called when the current
|
|
281 |
aggregation group changes. Thus it performs a combination of
|
|
282 |
clear() and add().
|
|
283 |
*/
|
|
284 |
inline bool reset() { clear(); return add(); }; |
|
285 |
||
286 |
/*
|
|
287 |
Prepare this item for evaluation of an aggregate value. This is
|
|
288 |
called by reset() when a group changes, or, for correlated
|
|
289 |
subqueries, between subquery executions. E.g. for COUNT(), this
|
|
290 |
method should set count= 0;
|
|
291 |
*/
|
|
292 |
virtual void clear()= 0; |
|
293 |
||
294 |
/*
|
|
295 |
This method is called for the next row in the same group. Its
|
|
296 |
purpose is to aggregate the new value to the previous values in
|
|
297 |
the group (i.e. since clear() was called last time). For example,
|
|
298 |
for COUNT(), do count++.
|
|
299 |
*/
|
|
300 |
virtual bool add()=0; |
|
301 |
||
302 |
/*
|
|
303 |
Called when new group is started and results are being saved in
|
|
304 |
a temporary table. Similar to reset(), but must also store value in
|
|
305 |
result_field. Like reset() it is supposed to reset start value to
|
|
306 |
default.
|
|
307 |
This set of methods (reult_field(), reset_field, update_field()) of
|
|
308 |
Item_sum is used only if quick_group is not null. Otherwise
|
|
309 |
copy_or_same() is used to obtain a copy of this item.
|
|
310 |
*/
|
|
311 |
virtual void reset_field()=0; |
|
312 |
/*
|
|
313 |
Called for each new value in the group, when temporary table is in use.
|
|
314 |
Similar to add(), but uses temporary table field to obtain current value,
|
|
315 |
Updated value is then saved in the field.
|
|
316 |
*/
|
|
317 |
virtual void update_field()=0; |
|
318 |
virtual bool keep_field_type(void) const { return 0; } |
|
319 |
virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } |
|
320 |
/*
|
|
321 |
This method is used for debug purposes to print the name of an
|
|
322 |
item to the debug log. The second use of this method is as
|
|
323 |
a helper function of print(), where it is applicable.
|
|
324 |
To suit both goals it should return a meaningful,
|
|
325 |
distinguishable and sintactically correct string. This method
|
|
326 |
should not be used for runtime type identification, use enum
|
|
327 |
{Sum}Functype and Item_func::functype()/Item_sum::sum_func()
|
|
328 |
instead.
|
|
329 |
||
330 |
NOTE: for Items inherited from Item_sum, func_name() return part of
|
|
331 |
function name till first argument (including '(') to make difference in
|
|
332 |
names for functions with 'distinct' clause and without 'distinct' and
|
|
333 |
also to make printing of items inherited from Item_sum uniform.
|
|
334 |
*/
|
|
335 |
virtual const char *func_name() const= 0; |
|
336 |
virtual Item *result_item(Field *field) |
|
337 |
{ return new Item_field(field); } |
|
338 |
table_map used_tables() const { return used_tables_cache; } |
|
339 |
void update_used_tables (); |
|
340 |
void cleanup() |
|
341 |
{
|
|
342 |
Item::cleanup(); |
|
343 |
forced_const= FALSE; |
|
344 |
}
|
|
345 |
bool is_null() { return null_value; } |
|
346 |
void make_const () |
|
347 |
{
|
|
348 |
used_tables_cache= 0; |
|
349 |
forced_const= TRUE; |
|
350 |
}
|
|
351 |
virtual bool const_item() const { return forced_const; } |
|
352 |
void make_field(Send_field *field); |
|
353 |
virtual void print(String *str, enum_query_type query_type); |
|
354 |
void fix_num_length_and_dec(); |
|
355 |
||
356 |
/*
|
|
357 |
This function is called by the execution engine to assign 'NO ROWS
|
|
358 |
FOUND' value to an aggregate item, when the underlying result set
|
|
359 |
has no rows. Such value, in a general case, may be different from
|
|
360 |
the default value of the item after 'clear()': e.g. a numeric item
|
|
361 |
may be initialized to 0 by clear() and to NULL by
|
|
362 |
no_rows_in_result().
|
|
363 |
*/
|
|
364 |
void no_rows_in_result() { clear(); } |
|
365 |
||
366 |
virtual bool setup(THD *thd) {return 0;} |
|
367 |
virtual void make_unique() {} |
|
368 |
Item *get_tmp_table_item(THD *thd); |
|
369 |
virtual Field *create_tmp_field(bool group, TABLE *table, |
|
370 |
uint convert_blob_length); |
|
371 |
bool walk(Item_processor processor, bool walk_subquery, uchar *argument); |
|
372 |
bool init_sum_func_check(THD *thd); |
|
373 |
bool check_sum_func(THD *thd, Item **ref); |
|
374 |
bool register_sum_func(THD *thd, Item **ref); |
|
375 |
st_select_lex *depended_from() |
|
376 |
{ return (nest_level == aggr_level ? 0 : aggr_sel); } |
|
377 |
};
|
|
378 |
||
379 |
||
380 |
class Item_sum_num :public Item_sum |
|
381 |
{
|
|
382 |
protected: |
|
383 |
/*
|
|
384 |
val_xxx() functions may be called several times during the execution of a
|
|
385 |
query. Derived classes that require extensive calculation in val_xxx()
|
|
386 |
maintain cache of aggregate value. This variable governs the validity of
|
|
387 |
that cache.
|
|
388 |
*/
|
|
389 |
bool is_evaluated; |
|
390 |
public: |
|
391 |
Item_sum_num() :Item_sum(),is_evaluated(FALSE) {} |
|
392 |
Item_sum_num(Item *item_par) |
|
393 |
:Item_sum(item_par), is_evaluated(FALSE) {} |
|
394 |
Item_sum_num(Item *a, Item* b) :Item_sum(a,b),is_evaluated(FALSE) {} |
|
395 |
Item_sum_num(List<Item> &list) |
|
396 |
:Item_sum(list), is_evaluated(FALSE) {} |
|
397 |
Item_sum_num(THD *thd, Item_sum_num *item) |
|
398 |
:Item_sum(thd, item),is_evaluated(item->is_evaluated) {} |
|
399 |
bool fix_fields(THD *, Item **); |
|
400 |
longlong val_int() |
|
401 |
{
|
|
402 |
DBUG_ASSERT(fixed == 1); |
|
403 |
return (longlong) rint(val_real()); /* Real as default */ |
|
404 |
}
|
|
405 |
String *val_str(String*str); |
|
406 |
my_decimal *val_decimal(my_decimal *); |
|
407 |
void reset_field(); |
|
408 |
};
|
|
409 |
||
410 |
||
411 |
class Item_sum_int :public Item_sum_num |
|
412 |
{
|
|
413 |
public: |
|
414 |
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {} |
|
415 |
Item_sum_int(List<Item> &list) :Item_sum_num(list) {} |
|
416 |
Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {} |
|
417 |
double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); } |
|
418 |
String *val_str(String*str); |
|
419 |
my_decimal *val_decimal(my_decimal *); |
|
420 |
enum Item_result result_type () const { return INT_RESULT; } |
|
421 |
void fix_length_and_dec() |
|
422 |
{ decimals=0; max_length=21; maybe_null=null_value=0; } |
|
423 |
};
|
|
424 |
||
425 |
||
426 |
class Item_sum_sum :public Item_sum_num |
|
427 |
{
|
|
428 |
protected: |
|
429 |
Item_result hybrid_type; |
|
430 |
double sum; |
|
431 |
my_decimal dec_buffs[2]; |
|
432 |
uint curr_dec_buff; |
|
433 |
void fix_length_and_dec(); |
|
434 |
||
435 |
public: |
|
436 |
Item_sum_sum(Item *item_par) :Item_sum_num(item_par) {} |
|
437 |
Item_sum_sum(THD *thd, Item_sum_sum *item); |
|
438 |
enum Sumfunctype sum_func () const {return SUM_FUNC;} |
|
439 |
void clear(); |
|
440 |
bool add(); |
|
441 |
double val_real(); |
|
442 |
longlong val_int(); |
|
443 |
String *val_str(String*str); |
|
444 |
my_decimal *val_decimal(my_decimal *); |
|
445 |
enum Item_result result_type () const { return hybrid_type; } |
|
446 |
void reset_field(); |
|
447 |
void update_field(); |
|
448 |
void no_rows_in_result() {} |
|
449 |
const char *func_name() const { return "sum("; } |
|
450 |
Item *copy_or_same(THD* thd); |
|
451 |
};
|
|
452 |
||
453 |
||
454 |
||
455 |
/* Common class for SUM(DISTINCT), AVG(DISTINCT) */
|
|
456 |
||
457 |
class Unique; |
|
458 |
||
459 |
class Item_sum_distinct :public Item_sum_num |
|
460 |
{
|
|
461 |
protected: |
|
462 |
/* storage for the summation result */
|
|
463 |
ulonglong count; |
|
464 |
Hybrid_type val; |
|
465 |
/* storage for unique elements */
|
|
466 |
Unique *tree; |
|
467 |
TABLE *table; |
|
468 |
enum enum_field_types table_field_type; |
|
469 |
uint tree_key_length; |
|
470 |
protected: |
|
471 |
Item_sum_distinct(THD *thd, Item_sum_distinct *item); |
|
472 |
public: |
|
473 |
Item_sum_distinct(Item *item_par); |
|
474 |
~Item_sum_distinct(); |
|
475 |
||
476 |
bool setup(THD *thd); |
|
477 |
void clear(); |
|
478 |
void cleanup(); |
|
479 |
bool add(); |
|
480 |
double val_real(); |
|
481 |
my_decimal *val_decimal(my_decimal *); |
|
482 |
longlong val_int(); |
|
483 |
String *val_str(String *str); |
|
484 |
||
485 |
/* XXX: does it need make_unique? */
|
|
486 |
||
487 |
enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; } |
|
488 |
void reset_field() {} // not used |
|
489 |
void update_field() {} // not used |
|
490 |
virtual void no_rows_in_result() {} |
|
491 |
void fix_length_and_dec(); |
|
492 |
enum Item_result result_type () const { return val.traits->type(); } |
|
493 |
virtual void calculate_val_and_count(); |
|
494 |
virtual bool unique_walk_function(void *elem); |
|
495 |
};
|
|
496 |
||
497 |
||
498 |
/*
|
|
499 |
Item_sum_sum_distinct - implementation of SUM(DISTINCT expr).
|
|
500 |
See also: MySQL manual, chapter 'Adding New Functions To MySQL'
|
|
501 |
and comments in item_sum.cc.
|
|
502 |
*/
|
|
503 |
||
504 |
class Item_sum_sum_distinct :public Item_sum_distinct |
|
505 |
{
|
|
506 |
private: |
|
507 |
Item_sum_sum_distinct(THD *thd, Item_sum_sum_distinct *item) |
|
508 |
:Item_sum_distinct(thd, item) {} |
|
509 |
public: |
|
510 |
Item_sum_sum_distinct(Item *item_arg) :Item_sum_distinct(item_arg) {} |
|
511 |
||
512 |
enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; } |
|
513 |
const char *func_name() const { return "sum(distinct "; } |
|
514 |
Item *copy_or_same(THD* thd) { return new Item_sum_sum_distinct(thd, this); } |
|
515 |
};
|
|
516 |
||
517 |
||
518 |
/* Item_sum_avg_distinct - SELECT AVG(DISTINCT expr) FROM ... */
|
|
519 |
||
520 |
class Item_sum_avg_distinct: public Item_sum_distinct |
|
521 |
{
|
|
522 |
private: |
|
523 |
Item_sum_avg_distinct(THD *thd, Item_sum_avg_distinct *original) |
|
524 |
:Item_sum_distinct(thd, original) {} |
|
525 |
public: |
|
526 |
uint prec_increment; |
|
527 |
Item_sum_avg_distinct(Item *item_arg) : Item_sum_distinct(item_arg) {} |
|
528 |
||
529 |
void fix_length_and_dec(); |
|
530 |
virtual void calculate_val_and_count(); |
|
531 |
enum Sumfunctype sum_func () const { return AVG_DISTINCT_FUNC; } |
|
532 |
const char *func_name() const { return "avg(distinct "; } |
|
533 |
Item *copy_or_same(THD* thd) { return new Item_sum_avg_distinct(thd, this); } |
|
534 |
};
|
|
535 |
||
536 |
||
537 |
class Item_sum_count :public Item_sum_int |
|
538 |
{
|
|
539 |
longlong count; |
|
540 |
||
541 |
public: |
|
542 |
Item_sum_count(Item *item_par) |
|
543 |
:Item_sum_int(item_par),count(0) |
|
544 |
{}
|
|
545 |
Item_sum_count(THD *thd, Item_sum_count *item) |
|
546 |
:Item_sum_int(thd, item), count(item->count) |
|
547 |
{}
|
|
548 |
enum Sumfunctype sum_func () const { return COUNT_FUNC; } |
|
549 |
void clear(); |
|
550 |
void no_rows_in_result() { count=0; } |
|
551 |
bool add(); |
|
552 |
void make_const(longlong count_arg) |
|
553 |
{
|
|
554 |
count=count_arg; |
|
555 |
Item_sum::make_const(); |
|
556 |
}
|
|
557 |
longlong val_int(); |
|
558 |
void reset_field(); |
|
559 |
void cleanup(); |
|
560 |
void update_field(); |
|
561 |
const char *func_name() const { return "count("; } |
|
562 |
Item *copy_or_same(THD* thd); |
|
563 |
};
|
|
564 |
||
565 |
||
566 |
class TMP_TABLE_PARAM; |
|
567 |
||
568 |
class Item_sum_count_distinct :public Item_sum_int |
|
569 |
{
|
|
570 |
TABLE *table; |
|
571 |
uint32 *field_lengths; |
|
572 |
TMP_TABLE_PARAM *tmp_table_param; |
|
573 |
bool force_copy_fields; |
|
574 |
/*
|
|
575 |
If there are no blobs, we can use a tree, which
|
|
576 |
is faster than heap table. In that case, we still use the table
|
|
577 |
to help get things set up, but we insert nothing in it
|
|
578 |
*/
|
|
579 |
Unique *tree; |
|
580 |
/*
|
|
581 |
Storage for the value of count between calls to val_int() so val_int()
|
|
582 |
will not recalculate on each call. Validitiy of the value is stored in
|
|
583 |
is_evaluated.
|
|
584 |
*/
|
|
585 |
longlong count; |
|
586 |
/*
|
|
587 |
Following is 0 normal object and pointer to original one for copy
|
|
588 |
(to correctly free resources)
|
|
589 |
*/
|
|
590 |
Item_sum_count_distinct *original; |
|
591 |
uint tree_key_length; |
|
592 |
||
593 |
||
594 |
bool always_null; // Set to 1 if the result is always NULL |
|
595 |
||
596 |
||
597 |
friend int composite_key_cmp(void* arg, uchar* key1, uchar* key2); |
|
598 |
friend int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2); |
|
599 |
||
600 |
public: |
|
601 |
Item_sum_count_distinct(List<Item> &list) |
|
602 |
:Item_sum_int(list), table(0), field_lengths(0), tmp_table_param(0), |
|
603 |
force_copy_fields(0), tree(0), count(0), |
|
604 |
original(0), always_null(FALSE) |
|
605 |
{ quick_group= 0; } |
|
606 |
Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item) |
|
607 |
:Item_sum_int(thd, item), table(item->table), |
|
608 |
field_lengths(item->field_lengths), |
|
609 |
tmp_table_param(item->tmp_table_param), |
|
610 |
force_copy_fields(0), tree(item->tree), count(item->count), |
|
611 |
original(item), tree_key_length(item->tree_key_length), |
|
612 |
always_null(item->always_null) |
|
613 |
{}
|
|
614 |
~Item_sum_count_distinct(); |
|
615 |
||
616 |
void cleanup(); |
|
617 |
||
618 |
enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; } |
|
619 |
void clear(); |
|
620 |
bool add(); |
|
621 |
longlong val_int(); |
|
622 |
void reset_field() { return ;} // Never called |
|
623 |
void update_field() { return ; } // Never called |
|
624 |
const char *func_name() const { return "count(distinct "; } |
|
625 |
bool setup(THD *thd); |
|
626 |
void make_unique(); |
|
627 |
Item *copy_or_same(THD* thd); |
|
628 |
void no_rows_in_result() {} |
|
629 |
};
|
|
630 |
||
631 |
||
632 |
/* Item to get the value of a stored sum function */
|
|
633 |
||
634 |
class Item_sum_avg; |
|
635 |
||
636 |
class Item_avg_field :public Item_result_field |
|
637 |
{
|
|
638 |
public: |
|
639 |
Field *field; |
|
640 |
Item_result hybrid_type; |
|
641 |
uint f_precision, f_scale, dec_bin_size; |
|
642 |
uint prec_increment; |
|
643 |
Item_avg_field(Item_result res_type, Item_sum_avg *item); |
|
644 |
enum Type type() const { return FIELD_AVG_ITEM; } |
|
645 |
double val_real(); |
|
646 |
longlong val_int(); |
|
647 |
my_decimal *val_decimal(my_decimal *); |
|
648 |
bool is_null() { update_null_value(); return null_value; } |
|
649 |
String *val_str(String*); |
|
650 |
enum_field_types field_type() const |
|
651 |
{
|
|
652 |
return hybrid_type == DECIMAL_RESULT ? |
|
653 |
MYSQL_TYPE_NEWDECIMAL : MYSQL_TYPE_DOUBLE; |
|
654 |
}
|
|
655 |
void fix_length_and_dec() {} |
|
656 |
enum Item_result result_type () const { return hybrid_type; } |
|
657 |
};
|
|
658 |
||
659 |
||
660 |
class Item_sum_avg :public Item_sum_sum |
|
661 |
{
|
|
662 |
public: |
|
663 |
ulonglong count; |
|
664 |
uint prec_increment; |
|
665 |
uint f_precision, f_scale, dec_bin_size; |
|
666 |
||
667 |
Item_sum_avg(Item *item_par) :Item_sum_sum(item_par), count(0) {} |
|
668 |
Item_sum_avg(THD *thd, Item_sum_avg *item) |
|
669 |
:Item_sum_sum(thd, item), count(item->count), |
|
670 |
prec_increment(item->prec_increment) {} |
|
671 |
||
672 |
void fix_length_and_dec(); |
|
673 |
enum Sumfunctype sum_func () const {return AVG_FUNC;} |
|
674 |
void clear(); |
|
675 |
bool add(); |
|
676 |
double val_real(); |
|
677 |
// In SPs we might force the "wrong" type with select into a declare variable
|
|
678 |
longlong val_int() { return (longlong) rint(val_real()); } |
|
679 |
my_decimal *val_decimal(my_decimal *); |
|
680 |
String *val_str(String *str); |
|
681 |
void reset_field(); |
|
682 |
void update_field(); |
|
683 |
Item *result_item(Field *field) |
|
684 |
{ return new Item_avg_field(hybrid_type, this); } |
|
685 |
void no_rows_in_result() {} |
|
686 |
const char *func_name() const { return "avg("; } |
|
687 |
Item *copy_or_same(THD* thd); |
|
688 |
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); |
|
689 |
void cleanup() |
|
690 |
{
|
|
691 |
count= 0; |
|
692 |
Item_sum_sum::cleanup(); |
|
693 |
}
|
|
694 |
};
|
|
695 |
||
696 |
class Item_sum_variance; |
|
697 |
||
698 |
class Item_variance_field :public Item_result_field |
|
699 |
{
|
|
700 |
public: |
|
701 |
Field *field; |
|
702 |
Item_result hybrid_type; |
|
703 |
uint f_precision0, f_scale0; |
|
704 |
uint f_precision1, f_scale1; |
|
705 |
uint dec_bin_size0, dec_bin_size1; |
|
706 |
uint sample; |
|
707 |
uint prec_increment; |
|
708 |
Item_variance_field(Item_sum_variance *item); |
|
709 |
enum Type type() const {return FIELD_VARIANCE_ITEM; } |
|
710 |
double val_real(); |
|
711 |
longlong val_int() |
|
712 |
{ /* can't be fix_fields()ed */ return (longlong) rint(val_real()); } |
|
713 |
String *val_str(String *str) |
|
714 |
{ return val_string_from_real(str); } |
|
715 |
my_decimal *val_decimal(my_decimal *dec_buf) |
|
716 |
{ return val_decimal_from_real(dec_buf); } |
|
717 |
bool is_null() { update_null_value(); return null_value; } |
|
718 |
enum_field_types field_type() const |
|
719 |
{
|
|
720 |
return hybrid_type == DECIMAL_RESULT ? |
|
721 |
MYSQL_TYPE_NEWDECIMAL : MYSQL_TYPE_DOUBLE; |
|
722 |
}
|
|
723 |
void fix_length_and_dec() {} |
|
724 |
enum Item_result result_type () const { return hybrid_type; } |
|
725 |
};
|
|
726 |
||
727 |
||
728 |
/*
|
|
729 |
variance(a) =
|
|
730 |
||
731 |
= sum (ai - avg(a))^2 / count(a) )
|
|
732 |
= sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a)
|
|
733 |
= (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) =
|
|
734 |
= (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) =
|
|
735 |
= (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) =
|
|
736 |
= (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) =
|
|
737 |
= (sum(ai^2) - sum(a)^2/count(a))/count(a)
|
|
738 |
||
739 |
But, this falls prey to catastrophic cancellation. Instead, use the recurrence formulas
|
|
740 |
||
741 |
M_{1} = x_{1}, ~ M_{k} = M_{k-1} + (x_{k} - M_{k-1}) / k newline
|
|
742 |
S_{1} = 0, ~ S_{k} = S_{k-1} + (x_{k} - M_{k-1}) times (x_{k} - M_{k}) newline
|
|
743 |
for 2 <= k <= n newline
|
|
744 |
ital variance = S_{n} / (n-1)
|
|
745 |
||
746 |
*/
|
|
747 |
||
748 |
class Item_sum_variance : public Item_sum_num |
|
749 |
{
|
|
750 |
void fix_length_and_dec(); |
|
751 |
||
752 |
public: |
|
753 |
Item_result hybrid_type; |
|
754 |
int cur_dec; |
|
755 |
double recurrence_m, recurrence_s; /* Used in recurrence relation. */ |
|
756 |
ulonglong count; |
|
757 |
uint f_precision0, f_scale0; |
|
758 |
uint f_precision1, f_scale1; |
|
759 |
uint dec_bin_size0, dec_bin_size1; |
|
760 |
uint sample; |
|
761 |
uint prec_increment; |
|
762 |
||
763 |
Item_sum_variance(Item *item_par, uint sample_arg) :Item_sum_num(item_par), |
|
764 |
hybrid_type(REAL_RESULT), count(0), sample(sample_arg) |
|
765 |
{}
|
|
766 |
Item_sum_variance(THD *thd, Item_sum_variance *item); |
|
767 |
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; } |
|
768 |
void clear(); |
|
769 |
bool add(); |
|
770 |
double val_real(); |
|
771 |
my_decimal *val_decimal(my_decimal *); |
|
772 |
void reset_field(); |
|
773 |
void update_field(); |
|
774 |
Item *result_item(Field *field) |
|
775 |
{ return new Item_variance_field(this); } |
|
776 |
void no_rows_in_result() {} |
|
777 |
const char *func_name() const |
|
778 |
{ return sample ? "var_samp(" : "variance("; } |
|
779 |
Item *copy_or_same(THD* thd); |
|
780 |
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); |
|
781 |
enum Item_result result_type () const { return REAL_RESULT; } |
|
782 |
void cleanup() |
|
783 |
{
|
|
784 |
count= 0; |
|
785 |
Item_sum_num::cleanup(); |
|
786 |
}
|
|
787 |
};
|
|
788 |
||
789 |
class Item_sum_std; |
|
790 |
||
791 |
class Item_std_field :public Item_variance_field |
|
792 |
{
|
|
793 |
public: |
|
794 |
Item_std_field(Item_sum_std *item); |
|
795 |
enum Type type() const { return FIELD_STD_ITEM; } |
|
796 |
double val_real(); |
|
797 |
my_decimal *val_decimal(my_decimal *); |
|
798 |
enum Item_result result_type () const { return REAL_RESULT; } |
|
799 |
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;} |
|
800 |
};
|
|
801 |
||
802 |
/*
|
|
803 |
standard_deviation(a) = sqrt(variance(a))
|
|
804 |
*/
|
|
805 |
||
806 |
class Item_sum_std :public Item_sum_variance |
|
807 |
{
|
|
808 |
public: |
|
809 |
Item_sum_std(Item *item_par, uint sample_arg) |
|
810 |
:Item_sum_variance(item_par, sample_arg) {} |
|
811 |
Item_sum_std(THD *thd, Item_sum_std *item) |
|
812 |
:Item_sum_variance(thd, item) |
|
813 |
{}
|
|
814 |
enum Sumfunctype sum_func () const { return STD_FUNC; } |
|
815 |
double val_real(); |
|
816 |
Item *result_item(Field *field) |
|
817 |
{ return new Item_std_field(this); } |
|
818 |
const char *func_name() const { return "std("; } |
|
819 |
Item *copy_or_same(THD* thd); |
|
820 |
enum Item_result result_type () const { return REAL_RESULT; } |
|
821 |
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;} |
|
822 |
};
|
|
823 |
||
824 |
// This class is a string or number function depending on num_func
|
|
825 |
||
826 |
class Item_sum_hybrid :public Item_sum |
|
827 |
{
|
|
828 |
protected: |
|
829 |
String value,tmp_value; |
|
830 |
double sum; |
|
831 |
longlong sum_int; |
|
832 |
my_decimal sum_dec; |
|
833 |
Item_result hybrid_type; |
|
834 |
enum_field_types hybrid_field_type; |
|
835 |
int cmp_sign; |
|
836 |
bool was_values; // Set if we have found at least one row (for max/min only) |
|
837 |
||
838 |
public: |
|
839 |
Item_sum_hybrid(Item *item_par,int sign) |
|
840 |
:Item_sum(item_par), sum(0.0), sum_int(0), |
|
841 |
hybrid_type(INT_RESULT), hybrid_field_type(MYSQL_TYPE_LONGLONG), |
|
842 |
cmp_sign(sign), was_values(TRUE) |
|
843 |
{ collation.set(&my_charset_bin); } |
|
844 |
Item_sum_hybrid(THD *thd, Item_sum_hybrid *item); |
|
845 |
bool fix_fields(THD *, Item **); |
|
846 |
void clear(); |
|
847 |
double val_real(); |
|
848 |
longlong val_int(); |
|
849 |
my_decimal *val_decimal(my_decimal *); |
|
850 |
void reset_field(); |
|
851 |
String *val_str(String *); |
|
852 |
bool keep_field_type(void) const { return 1; } |
|
853 |
enum Item_result result_type () const { return hybrid_type; } |
|
854 |
enum enum_field_types field_type() const { return hybrid_field_type; } |
|
855 |
void update_field(); |
|
856 |
void min_max_update_str_field(); |
|
857 |
void min_max_update_real_field(); |
|
858 |
void min_max_update_int_field(); |
|
859 |
void min_max_update_decimal_field(); |
|
860 |
void cleanup(); |
|
861 |
bool any_value() { return was_values; } |
|
862 |
void no_rows_in_result(); |
|
863 |
Field *create_tmp_field(bool group, TABLE *table, |
|
864 |
uint convert_blob_length); |
|
865 |
};
|
|
866 |
||
867 |
||
868 |
class Item_sum_min :public Item_sum_hybrid |
|
869 |
{
|
|
870 |
public: |
|
871 |
Item_sum_min(Item *item_par) :Item_sum_hybrid(item_par,1) {} |
|
872 |
Item_sum_min(THD *thd, Item_sum_min *item) :Item_sum_hybrid(thd, item) {} |
|
873 |
enum Sumfunctype sum_func () const {return MIN_FUNC;} |
|
874 |
||
875 |
bool add(); |
|
876 |
const char *func_name() const { return "min("; } |
|
877 |
Item *copy_or_same(THD* thd); |
|
878 |
};
|
|
879 |
||
880 |
||
881 |
class Item_sum_max :public Item_sum_hybrid |
|
882 |
{
|
|
883 |
public: |
|
884 |
Item_sum_max(Item *item_par) :Item_sum_hybrid(item_par,-1) {} |
|
885 |
Item_sum_max(THD *thd, Item_sum_max *item) :Item_sum_hybrid(thd, item) {} |
|
886 |
enum Sumfunctype sum_func () const {return MAX_FUNC;} |
|
887 |
||
888 |
bool add(); |
|
889 |
const char *func_name() const { return "max("; } |
|
890 |
Item *copy_or_same(THD* thd); |
|
891 |
};
|
|
892 |
||
893 |
||
894 |
class Item_sum_bit :public Item_sum_int |
|
895 |
{
|
|
896 |
protected: |
|
897 |
ulonglong reset_bits,bits; |
|
898 |
||
899 |
public: |
|
900 |
Item_sum_bit(Item *item_par,ulonglong reset_arg) |
|
901 |
:Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {} |
|
902 |
Item_sum_bit(THD *thd, Item_sum_bit *item): |
|
903 |
Item_sum_int(thd, item), reset_bits(item->reset_bits), bits(item->bits) {} |
|
904 |
enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;} |
|
905 |
void clear(); |
|
906 |
longlong val_int(); |
|
907 |
void reset_field(); |
|
908 |
void update_field(); |
|
909 |
void fix_length_and_dec() |
|
910 |
{ decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; } |
|
911 |
void cleanup() |
|
912 |
{
|
|
913 |
bits= reset_bits; |
|
914 |
Item_sum_int::cleanup(); |
|
915 |
}
|
|
916 |
};
|
|
917 |
||
918 |
||
919 |
class Item_sum_or :public Item_sum_bit |
|
920 |
{
|
|
921 |
public: |
|
922 |
Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} |
|
923 |
Item_sum_or(THD *thd, Item_sum_or *item) :Item_sum_bit(thd, item) {} |
|
924 |
bool add(); |
|
925 |
const char *func_name() const { return "bit_or("; } |
|
926 |
Item *copy_or_same(THD* thd); |
|
927 |
};
|
|
928 |
||
929 |
||
930 |
class Item_sum_and :public Item_sum_bit |
|
931 |
{
|
|
932 |
public: |
|
933 |
Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {} |
|
934 |
Item_sum_and(THD *thd, Item_sum_and *item) :Item_sum_bit(thd, item) {} |
|
935 |
bool add(); |
|
936 |
const char *func_name() const { return "bit_and("; } |
|
937 |
Item *copy_or_same(THD* thd); |
|
938 |
};
|
|
939 |
||
940 |
class Item_sum_xor :public Item_sum_bit |
|
941 |
{
|
|
942 |
public: |
|
943 |
Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} |
|
944 |
Item_sum_xor(THD *thd, Item_sum_xor *item) :Item_sum_bit(thd, item) {} |
|
945 |
bool add(); |
|
946 |
const char *func_name() const { return "bit_xor("; } |
|
947 |
Item *copy_or_same(THD* thd); |
|
948 |
};
|
|
949 |
||
950 |
||
951 |
/*
|
|
952 |
User defined aggregates
|
|
953 |
*/
|
|
954 |
||
955 |
#ifdef HAVE_DLOPEN
|
|
956 |
||
957 |
class Item_udf_sum : public Item_sum |
|
958 |
{
|
|
959 |
protected: |
|
960 |
udf_handler udf; |
|
961 |
||
962 |
public: |
|
963 |
Item_udf_sum(udf_func *udf_arg) |
|
964 |
:Item_sum(), udf(udf_arg) |
|
965 |
{ quick_group=0; } |
|
966 |
Item_udf_sum(udf_func *udf_arg, List<Item> &list) |
|
967 |
:Item_sum(list), udf(udf_arg) |
|
968 |
{ quick_group=0;} |
|
969 |
Item_udf_sum(THD *thd, Item_udf_sum *item) |
|
970 |
:Item_sum(thd, item), udf(item->udf) |
|
971 |
{ udf.not_original= TRUE; } |
|
972 |
const char *func_name() const { return udf.name(); } |
|
973 |
bool fix_fields(THD *thd, Item **ref) |
|
974 |
{
|
|
975 |
DBUG_ASSERT(fixed == 0); |
|
976 |
||
977 |
if (init_sum_func_check(thd)) |
|
978 |
return TRUE; |
|
979 |
||
980 |
fixed= 1; |
|
981 |
if (udf.fix_fields(thd, this, this->arg_count, this->args)) |
|
982 |
return TRUE; |
|
983 |
||
984 |
return check_sum_func(thd, ref); |
|
985 |
}
|
|
986 |
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } |
|
987 |
virtual bool have_field_update(void) const { return 0; } |
|
988 |
||
989 |
void clear(); |
|
990 |
bool add(); |
|
991 |
void reset_field() {}; |
|
992 |
void update_field() {}; |
|
993 |
void cleanup(); |
|
994 |
virtual void print(String *str, enum_query_type query_type); |
|
995 |
};
|
|
996 |
||
997 |
||
998 |
class Item_sum_udf_float :public Item_udf_sum |
|
999 |
{
|
|
1000 |
public: |
|
1001 |
Item_sum_udf_float(udf_func *udf_arg) |
|
1002 |
:Item_udf_sum(udf_arg) {} |
|
1003 |
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) |
|
1004 |
:Item_udf_sum(udf_arg, list) {} |
|
1005 |
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) |
|
1006 |
:Item_udf_sum(thd, item) {} |
|
1007 |
longlong val_int() |
|
1008 |
{
|
|
1009 |
DBUG_ASSERT(fixed == 1); |
|
1010 |
return (longlong) rint(Item_sum_udf_float::val_real()); |
|
1011 |
}
|
|
1012 |
double val_real(); |
|
1013 |
String *val_str(String*str); |
|
1014 |
my_decimal *val_decimal(my_decimal *); |
|
1015 |
void fix_length_and_dec() { fix_num_length_and_dec(); } |
|
1016 |
Item *copy_or_same(THD* thd); |
|
1017 |
};
|
|
1018 |
||
1019 |
||
1020 |
class Item_sum_udf_int :public Item_udf_sum |
|
1021 |
{
|
|
1022 |
public: |
|
1023 |
Item_sum_udf_int(udf_func *udf_arg) |
|
1024 |
:Item_udf_sum(udf_arg) {} |
|
1025 |
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) |
|
1026 |
:Item_udf_sum(udf_arg, list) {} |
|
1027 |
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) |
|
1028 |
:Item_udf_sum(thd, item) {} |
|
1029 |
longlong val_int(); |
|
1030 |
double val_real() |
|
1031 |
{ DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::val_int(); } |
|
1032 |
String *val_str(String*str); |
|
1033 |
my_decimal *val_decimal(my_decimal *); |
|
1034 |
enum Item_result result_type () const { return INT_RESULT; } |
|
1035 |
void fix_length_and_dec() { decimals=0; max_length=21; } |
|
1036 |
Item *copy_or_same(THD* thd); |
|
1037 |
};
|
|
1038 |
||
1039 |
||
1040 |
class Item_sum_udf_str :public Item_udf_sum |
|
1041 |
{
|
|
1042 |
public: |
|
1043 |
Item_sum_udf_str(udf_func *udf_arg) |
|
1044 |
:Item_udf_sum(udf_arg) {} |
|
1045 |
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) |
|
1046 |
:Item_udf_sum(udf_arg,list) {} |
|
1047 |
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) |
|
1048 |
:Item_udf_sum(thd, item) {} |
|
1049 |
String *val_str(String *); |
|
1050 |
double val_real() |
|
1051 |
{
|
|
1052 |
int err_not_used; |
|
1053 |
char *end_not_used; |
|
1054 |
String *res; |
|
1055 |
res=val_str(&str_value); |
|
1056 |
return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(), |
|
1057 |
&end_not_used, &err_not_used) : 0.0; |
|
1058 |
}
|
|
1059 |
longlong val_int() |
|
1060 |
{
|
|
1061 |
int err_not_used; |
|
1062 |
char *end; |
|
1063 |
String *res; |
|
1064 |
CHARSET_INFO *cs; |
|
1065 |
||
1066 |
if (!(res= val_str(&str_value))) |
|
1067 |
return 0; /* Null value */ |
|
1068 |
cs= res->charset(); |
|
1069 |
end= (char*) res->ptr()+res->length(); |
|
1070 |
return cs->cset->strtoll10(cs, res->ptr(), &end, &err_not_used); |
|
1071 |
}
|
|
1072 |
my_decimal *val_decimal(my_decimal *dec); |
|
1073 |
enum Item_result result_type () const { return STRING_RESULT; } |
|
1074 |
void fix_length_and_dec(); |
|
1075 |
Item *copy_or_same(THD* thd); |
|
1076 |
};
|
|
1077 |
||
1078 |
||
1079 |
class Item_sum_udf_decimal :public Item_udf_sum |
|
1080 |
{
|
|
1081 |
public: |
|
1082 |
Item_sum_udf_decimal(udf_func *udf_arg) |
|
1083 |
:Item_udf_sum(udf_arg) {} |
|
1084 |
Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list) |
|
1085 |
:Item_udf_sum(udf_arg, list) {} |
|
1086 |
Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item) |
|
1087 |
:Item_udf_sum(thd, item) {} |
|
1088 |
String *val_str(String *); |
|
1089 |
double val_real(); |
|
1090 |
longlong val_int(); |
|
1091 |
my_decimal *val_decimal(my_decimal *); |
|
1092 |
enum Item_result result_type () const { return DECIMAL_RESULT; } |
|
1093 |
void fix_length_and_dec() { fix_num_length_and_dec(); } |
|
1094 |
Item *copy_or_same(THD* thd); |
|
1095 |
};
|
|
1096 |
||
1097 |
#else /* Dummy functions to get sql_yacc.cc compiled */ |
|
1098 |
||
1099 |
class Item_sum_udf_float :public Item_sum_num |
|
1100 |
{
|
|
1101 |
public: |
|
1102 |
Item_sum_udf_float(udf_func *udf_arg) |
|
1103 |
:Item_sum_num() {} |
|
1104 |
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {} |
|
1105 |
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) |
|
1106 |
:Item_sum_num(thd, item) {} |
|
1107 |
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } |
|
1108 |
double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; } |
|
1109 |
void clear() {} |
|
1110 |
bool add() { return 0; } |
|
1111 |
void update_field() {} |
|
1112 |
};
|
|
1113 |
||
1114 |
||
1115 |
class Item_sum_udf_int :public Item_sum_num |
|
1116 |
{
|
|
1117 |
public: |
|
1118 |
Item_sum_udf_int(udf_func *udf_arg) |
|
1119 |
:Item_sum_num() {} |
|
1120 |
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {} |
|
1121 |
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) |
|
1122 |
:Item_sum_num(thd, item) {} |
|
1123 |
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } |
|
1124 |
longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; } |
|
1125 |
double val_real() { DBUG_ASSERT(fixed == 1); return 0; } |
|
1126 |
void clear() {} |
|
1127 |
bool add() { return 0; } |
|
1128 |
void update_field() {} |
|
1129 |
};
|
|
1130 |
||
1131 |
||
1132 |
class Item_sum_udf_decimal :public Item_sum_num |
|
1133 |
{
|
|
1134 |
public: |
|
1135 |
Item_sum_udf_decimal(udf_func *udf_arg) |
|
1136 |
:Item_sum_num() {} |
|
1137 |
Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list) |
|
1138 |
:Item_sum_num() {} |
|
1139 |
Item_sum_udf_decimal(THD *thd, Item_sum_udf_float *item) |
|
1140 |
:Item_sum_num(thd, item) {} |
|
1141 |
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } |
|
1142 |
double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; } |
|
1143 |
my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; } |
|
1144 |
void clear() {} |
|
1145 |
bool add() { return 0; } |
|
1146 |
void update_field() {} |
|
1147 |
};
|
|
1148 |
||
1149 |
||
1150 |
class Item_sum_udf_str :public Item_sum_num |
|
1151 |
{
|
|
1152 |
public: |
|
1153 |
Item_sum_udf_str(udf_func *udf_arg) |
|
1154 |
:Item_sum_num() {} |
|
1155 |
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) |
|
1156 |
:Item_sum_num() {} |
|
1157 |
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) |
|
1158 |
:Item_sum_num(thd, item) {} |
|
1159 |
String *val_str(String *) |
|
1160 |
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; } |
|
1161 |
double val_real() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; } |
|
1162 |
longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; } |
|
1163 |
enum Item_result result_type () const { return STRING_RESULT; } |
|
1164 |
void fix_length_and_dec() { maybe_null=1; max_length=0; } |
|
1165 |
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } |
|
1166 |
void clear() {} |
|
1167 |
bool add() { return 0; } |
|
1168 |
void update_field() {} |
|
1169 |
};
|
|
1170 |
||
1171 |
#endif /* HAVE_DLOPEN */ |
|
1172 |
||
1173 |
class MYSQL_ERROR; |
|
1174 |
||
1175 |
class Item_func_group_concat : public Item_sum |
|
1176 |
{
|
|
1177 |
TMP_TABLE_PARAM *tmp_table_param; |
|
1178 |
MYSQL_ERROR *warning; |
|
1179 |
String result; |
|
1180 |
String *separator; |
|
1181 |
TREE tree_base; |
|
1182 |
TREE *tree; |
|
1183 |
||
1184 |
/**
|
|
1185 |
If DISTINCT is used with this GROUP_CONCAT, this member is used to filter
|
|
1186 |
out duplicates.
|
|
1187 |
@see Item_func_group_concat::setup
|
|
1188 |
@see Item_func_group_concat::add
|
|
1189 |
@see Item_func_group_concat::clear
|
|
1190 |
*/
|
|
1191 |
Unique *unique_filter; |
|
1192 |
TABLE *table; |
|
1193 |
ORDER **order; |
|
1194 |
Name_resolution_context *context; |
|
1195 |
/** The number of ORDER BY items. */
|
|
1196 |
uint arg_count_order; |
|
1197 |
/** The number of selected items, aka the expr list. */
|
|
1198 |
uint arg_count_field; |
|
1199 |
uint count_cut_values; |
|
1200 |
bool distinct; |
|
1201 |
bool warning_for_row; |
|
1202 |
bool always_null; |
|
1203 |
bool force_copy_fields; |
|
1204 |
bool no_appended; |
|
1205 |
/*
|
|
1206 |
Following is 0 normal object and pointer to original one for copy
|
|
1207 |
(to correctly free resources)
|
|
1208 |
*/
|
|
1209 |
Item_func_group_concat *original; |
|
1210 |
||
1211 |
friend int group_concat_key_cmp_with_distinct(void* arg, const void* key1, |
|
1212 |
const void* key2); |
|
1213 |
friend int group_concat_key_cmp_with_order(void* arg, const void* key1, |
|
1214 |
const void* key2); |
|
1215 |
friend int dump_leaf_key(uchar* key, |
|
1216 |
element_count count __attribute__((unused)), |
|
1217 |
Item_func_group_concat *group_concat_item); |
|
1218 |
||
1219 |
public: |
|
1220 |
Item_func_group_concat(Name_resolution_context *context_arg, |
|
1221 |
bool is_distinct, List<Item> *is_select, |
|
1222 |
SQL_LIST *is_order, String *is_separator); |
|
1223 |
||
1224 |
Item_func_group_concat(THD *thd, Item_func_group_concat *item); |
|
1225 |
~Item_func_group_concat(); |
|
1226 |
void cleanup(); |
|
1227 |
||
1228 |
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} |
|
1229 |
const char *func_name() const { return "group_concat"; } |
|
1230 |
virtual Item_result result_type () const { return STRING_RESULT; } |
|
1231 |
enum_field_types field_type() const |
|
1232 |
{
|
|
1233 |
if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB ) |
|
1234 |
return MYSQL_TYPE_BLOB; |
|
1235 |
else
|
|
1236 |
return MYSQL_TYPE_VARCHAR; |
|
1237 |
}
|
|
1238 |
void clear(); |
|
1239 |
bool add(); |
|
1240 |
void reset_field() { DBUG_ASSERT(0); } // not used |
|
1241 |
void update_field() { DBUG_ASSERT(0); } // not used |
|
1242 |
bool fix_fields(THD *,Item **); |
|
1243 |
bool setup(THD *thd); |
|
1244 |
void make_unique(); |
|
1245 |
double val_real() |
|
1246 |
{
|
|
1247 |
String *res; res=val_str(&str_value); |
|
1248 |
return res ? my_atof(res->c_ptr()) : 0.0; |
|
1249 |
}
|
|
1250 |
longlong val_int() |
|
1251 |
{
|
|
1252 |
String *res; |
|
1253 |
char *end_ptr; |
|
1254 |
int error; |
|
1255 |
if (!(res= val_str(&str_value))) |
|
1256 |
return (longlong) 0; |
|
1257 |
end_ptr= (char*) res->ptr()+ res->length(); |
|
1258 |
return my_strtoll10(res->ptr(), &end_ptr, &error); |
|
1259 |
}
|
|
1260 |
my_decimal *val_decimal(my_decimal *decimal_value) |
|
1261 |
{
|
|
1262 |
return val_decimal_from_string(decimal_value); |
|
1263 |
}
|
|
1264 |
String* val_str(String* str); |
|
1265 |
Item *copy_or_same(THD* thd); |
|
1266 |
void no_rows_in_result() {} |
|
1267 |
virtual void print(String *str, enum_query_type query_type); |
|
1268 |
virtual bool change_context_processor(uchar *cntx) |
|
1269 |
{ context= (Name_resolution_context *)cntx; return FALSE; } |
|
1270 |
};
|