| 1 | #ifndef ITEM_SUM_INCLUDED |
| 2 | #define ITEM_SUM_INCLUDED |
| 3 | /* Copyright (c) 2000, 2013 Oracle and/or its affiliates. |
| 4 | Copyright (c) 2008, 2013 Monty Program Ab. |
| 5 | |
| 6 | This program is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; version 2 of the License. |
| 9 | |
| 10 | This program is distributed in the hope that it will be useful, |
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | GNU General Public License for more details. |
| 14 | |
| 15 | You should have received a copy of the GNU General Public License |
| 16 | along with this program; if not, write to the Free Software |
| 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
| 18 | |
| 19 | |
| 20 | /* classes for sum functions */ |
| 21 | |
| 22 | #ifdef USE_PRAGMA_INTERFACE |
| 23 | #pragma interface /* gcc class implementation */ |
| 24 | #endif |
| 25 | |
| 26 | #include <my_tree.h> |
| 27 | #include "sql_udf.h" /* udf_handler */ |
| 28 | |
| 29 | class Item_sum; |
| 30 | class Aggregator_distinct; |
| 31 | class Aggregator_simple; |
| 32 | |
| 33 | /** |
| 34 | The abstract base class for the Aggregator_* classes. |
| 35 | It implements the data collection functions (setup/add/clear) |
| 36 | as either pass-through to the real functionality or |
| 37 | as collectors into an Unique (for distinct) structure. |
| 38 | |
| 39 | Note that update_field/reset_field are not in that |
| 40 | class, because they're simply not called when |
| 41 | GROUP BY/DISTINCT can be handled with help of index on grouped |
| 42 | fields (quick_group = 0); |
| 43 | */ |
| 44 | |
| 45 | class Aggregator : public Sql_alloc |
| 46 | { |
| 47 | friend class Item_sum; |
| 48 | friend class Item_sum_sum; |
| 49 | friend class Item_sum_count; |
| 50 | friend class Item_sum_avg; |
| 51 | |
| 52 | /* |
| 53 | All members are protected as this class is not usable outside of an |
| 54 | Item_sum descendant. |
| 55 | */ |
| 56 | protected: |
| 57 | /* the aggregate function class to act on */ |
| 58 | Item_sum *item_sum; |
| 59 | |
| 60 | public: |
| 61 | Aggregator (Item_sum *arg): item_sum(arg) {} |
| 62 | virtual ~Aggregator () {} /* Keep gcc happy */ |
| 63 | |
| 64 | enum Aggregator_type { SIMPLE_AGGREGATOR, DISTINCT_AGGREGATOR }; |
| 65 | virtual Aggregator_type Aggrtype() = 0; |
| 66 | |
| 67 | /** |
| 68 | Called before adding the first row. |
| 69 | Allocates and sets up the internal aggregation structures used, |
| 70 | e.g. the Unique instance used to calculate distinct. |
| 71 | */ |
| 72 | virtual bool setup(THD *) = 0; |
| 73 | |
| 74 | /** |
| 75 | Called when we need to wipe out all the data from the aggregator : |
| 76 | all the values acumulated and all the state. |
| 77 | Cleans up the internal structures and resets them to their initial state. |
| 78 | */ |
| 79 | virtual void clear() = 0; |
| 80 | |
| 81 | /** |
| 82 | Called when there's a new value to be aggregated. |
| 83 | Updates the internal state of the aggregator to reflect the new value. |
| 84 | */ |
| 85 | virtual bool add() = 0; |
| 86 | |
| 87 | /** |
| 88 | Called when there are no more data and the final value is to be retrieved. |
| 89 | Finalises the state of the aggregator, so the final result can be retrieved. |
| 90 | */ |
| 91 | virtual void endup() = 0; |
| 92 | |
| 93 | /** Decimal value of being-aggregated argument */ |
| 94 | virtual my_decimal *arg_val_decimal(my_decimal * value) = 0; |
| 95 | /** Floating point value of being-aggregated argument */ |
| 96 | virtual double arg_val_real() = 0; |
| 97 | /** |
| 98 | NULLness of being-aggregated argument. |
| 99 | |
| 100 | @param use_null_value Optimization: to determine if the argument is NULL |
| 101 | we must, in the general case, call is_null() on it, which itself might |
| 102 | call val_*() on it, which might be costly. If you just have called |
| 103 | arg_val*(), you can pass use_null_value=true; this way, arg_is_null() |
| 104 | might avoid is_null() and instead do a cheap read of the Item's null_value |
| 105 | (updated by arg_val*()). |
| 106 | */ |
| 107 | virtual bool arg_is_null(bool use_null_value) = 0; |
| 108 | }; |
| 109 | |
| 110 | |
| 111 | class st_select_lex; |
| 112 | class Window_spec; |
| 113 | |
| 114 | /** |
| 115 | Class Item_sum is the base class used for special expressions that SQL calls |
| 116 | 'set functions'. These expressions are formed with the help of aggregate |
| 117 | functions such as SUM, MAX, GROUP_CONCAT etc. |
| 118 | |
| 119 | GENERAL NOTES |
| 120 | |
| 121 | A set function cannot be used in certain positions where expressions are |
| 122 | accepted. There are some quite explicable restrictions for the usage of |
| 123 | set functions. |
| 124 | |
| 125 | In the query: |
| 126 | SELECT AVG(b) FROM t1 WHERE SUM(b) > 20 GROUP by a |
| 127 | the usage of the set function AVG(b) is legal, while the usage of SUM(b) |
| 128 | is illegal. A WHERE condition must contain expressions that can be |
| 129 | evaluated for each row of the table. Yet the expression SUM(b) can be |
| 130 | evaluated only for each group of rows with the same value of column a. |
| 131 | In the query: |
| 132 | SELECT AVG(b) FROM t1 WHERE c > 30 GROUP BY a HAVING SUM(b) > 20 |
| 133 | both set function expressions AVG(b) and SUM(b) are legal. |
| 134 | |
| 135 | We can say that in a query without nested selects an occurrence of a |
| 136 | set function in an expression of the SELECT list or/and in the HAVING |
| 137 | clause is legal, while in the WHERE clause it's illegal. |
| 138 | |
| 139 | The general rule to detect whether a set function is legal in a query with |
| 140 | nested subqueries is much more complicated. |
| 141 | |
| 142 | Consider the the following query: |
| 143 | SELECT t1.a FROM t1 GROUP BY t1.a |
| 144 | HAVING t1.a > ALL (SELECT t2.c FROM t2 WHERE SUM(t1.b) < t2.c). |
| 145 | The set function SUM(b) is used here in the WHERE clause of the subquery. |
| 146 | Nevertheless it is legal since it is under the HAVING clause of the query |
| 147 | to which this function relates. The expression SUM(t1.b) is evaluated |
| 148 | for each group defined in the main query, not for groups of the subquery. |
| 149 | |
| 150 | The problem of finding the query where to aggregate a particular |
| 151 | set function is not so simple as it seems to be. |
| 152 | |
| 153 | In the query: |
| 154 | SELECT t1.a FROM t1 GROUP BY t1.a |
| 155 | HAVING t1.a > ALL(SELECT t2.c FROM t2 GROUP BY t2.c |
| 156 | HAVING SUM(t1.a) < t2.c) |
| 157 | the set function can be evaluated for both outer and inner selects. |
| 158 | If we evaluate SUM(t1.a) for the outer query then we get the value of t1.a |
| 159 | multiplied by the cardinality of a group in table t1. In this case |
| 160 | in each correlated subquery SUM(t1.a) is used as a constant. But we also |
| 161 | can evaluate SUM(t1.a) for the inner query. In this case t1.a will be a |
| 162 | constant for each correlated subquery and summation is performed |
| 163 | for each group of table t2. |
| 164 | (Here it makes sense to remind that the query |
| 165 | SELECT c FROM t GROUP BY a HAVING SUM(1) < a |
| 166 | is quite legal in our SQL). |
| 167 | |
| 168 | So depending on what query we assign the set function to we |
| 169 | can get different result sets. |
| 170 | |
| 171 | The general rule to detect the query where a set function is to be |
| 172 | evaluated can be formulated as follows. |
| 173 | Consider a set function S(E) where E is an expression with occurrences |
| 174 | of column references C1, ..., CN. Resolve these column references against |
| 175 | subqueries that contain the set function S(E). Let Q be the innermost |
| 176 | subquery of those subqueries. (It should be noted here that S(E) |
| 177 | in no way can be evaluated in the subquery embedding the subquery Q, |
| 178 | otherwise S(E) would refer to at least one unbound column reference) |
| 179 | If S(E) is used in a construct of Q where set functions are allowed then |
| 180 | we evaluate S(E) in Q. |
| 181 | Otherwise we look for a innermost subquery containing S(E) of those where |
| 182 | usage of S(E) is allowed. |
| 183 | |
| 184 | Let's demonstrate how this rule is applied to the following queries. |
| 185 | |
| 186 | 1. SELECT t1.a FROM t1 GROUP BY t1.a |
| 187 | HAVING t1.a > ALL(SELECT t2.b FROM t2 GROUP BY t2.b |
| 188 | HAVING t2.b > ALL(SELECT t3.c FROM t3 GROUP BY t3.c |
| 189 | HAVING SUM(t1.a+t2.b) < t3.c)) |
| 190 | For this query the set function SUM(t1.a+t2.b) depends on t1.a and t2.b |
| 191 | with t1.a defined in the outermost query, and t2.b defined for its |
| 192 | subquery. The set function is in the HAVING clause of the subquery and can |
| 193 | be evaluated in this subquery. |
| 194 | |
| 195 | 2. SELECT t1.a FROM t1 GROUP BY t1.a |
| 196 | HAVING t1.a > ALL(SELECT t2.b FROM t2 |
| 197 | WHERE t2.b > ALL (SELECT t3.c FROM t3 GROUP BY t3.c |
| 198 | HAVING SUM(t1.a+t2.b) < t3.c)) |
| 199 | Here the set function SUM(t1.a+t2.b)is in the WHERE clause of the second |
| 200 | subquery - the most upper subquery where t1.a and t2.b are defined. |
| 201 | If we evaluate the function in this subquery we violate the context rules. |
| 202 | So we evaluate the function in the third subquery (over table t3) where it |
| 203 | is used under the HAVING clause. |
| 204 | |
| 205 | 3. SELECT t1.a FROM t1 GROUP BY t1.a |
| 206 | HAVING t1.a > ALL(SELECT t2.b FROM t2 |
| 207 | WHERE t2.b > ALL (SELECT t3.c FROM t3 |
| 208 | WHERE SUM(t1.a+t2.b) < t3.c)) |
| 209 | In this query evaluation of SUM(t1.a+t2.b) is not legal neither in the second |
| 210 | nor in the third subqueries. So this query is invalid. |
| 211 | |
| 212 | Mostly set functions cannot be nested. In the query |
| 213 | SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20 |
| 214 | the expression SUM(b) is not acceptable, though it is under a HAVING clause. |
| 215 | Yet it is acceptable in the query: |
| 216 | SELECT t.1 FROM t1 GROUP BY t1.a HAVING SUM(t1.b) > 20. |
| 217 | |
| 218 | An argument of a set function does not have to be a reference to a table |
| 219 | column as we saw it in examples above. This can be a more complex expression |
| 220 | SELECT t1.a FROM t1 GROUP BY t1.a HAVING SUM(t1.b+1) > 20. |
| 221 | The expression SUM(t1.b+1) has a very clear semantics in this context: |
| 222 | we sum up the values of t1.b+1 where t1.b varies for all values within a |
| 223 | group of rows that contain the same t1.a value. |
| 224 | |
| 225 | A set function for an outer query yields a constant within a subquery. So |
| 226 | the semantics of the query |
| 227 | SELECT t1.a FROM t1 GROUP BY t1.a |
| 228 | HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c |
| 229 | HAVING AVG(t2.c+SUM(t1.b)) > 20) |
| 230 | is still clear. For a group of the rows with the same t1.a values we |
| 231 | calculate the value of SUM(t1.b). This value 's' is substituted in the |
| 232 | the subquery: |
| 233 | SELECT t2.c FROM t2 GROUP BY t2.c HAVING AVG(t2.c+s) |
| 234 | than returns some result set. |
| 235 | |
| 236 | By the same reason the following query with a subquery |
| 237 | SELECT t1.a FROM t1 GROUP BY t1.a |
| 238 | HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c |
| 239 | HAVING AVG(SUM(t1.b)) > 20) |
| 240 | is also acceptable. |
| 241 | |
| 242 | IMPLEMENTATION NOTES |
| 243 | |
| 244 | Three methods were added to the class to check the constraints specified |
| 245 | in the previous section. These methods utilize several new members. |
| 246 | |
| 247 | The field 'nest_level' contains the number of the level for the subquery |
| 248 | containing the set function. The main SELECT is of level 0, its subqueries |
| 249 | are of levels 1, the subqueries of the latter are of level 2 and so on. |
| 250 | |
| 251 | The field 'aggr_level' is to contain the nest level of the subquery |
| 252 | where the set function is aggregated. |
| 253 | |
| 254 | The field 'max_arg_level' is for the maximun of the nest levels of the |
| 255 | unbound column references occurred in the set function. A column reference |
| 256 | is unbound within a set function if it is not bound by any subquery |
| 257 | used as a subexpression in this function. A column reference is bound by |
| 258 | a subquery if it is a reference to the column by which the aggregation |
| 259 | of some set function that is used in the subquery is calculated. |
| 260 | For the set function used in the query |
| 261 | SELECT t1.a FROM t1 GROUP BY t1.a |
| 262 | HAVING t1.a > ALL(SELECT t2.b FROM t2 GROUP BY t2.b |
| 263 | HAVING t2.b > ALL(SELECT t3.c FROM t3 GROUP BY t3.c |
| 264 | HAVING SUM(t1.a+t2.b) < t3.c)) |
| 265 | the value of max_arg_level is equal to 1 since t1.a is bound in the main |
| 266 | query, and t2.b is bound by the first subquery whose nest level is 1. |
| 267 | Obviously a set function cannot be aggregated in the subquery whose |
| 268 | nest level is less than max_arg_level. (Yet it can be aggregated in the |
| 269 | subqueries whose nest level is greater than max_arg_level.) |
| 270 | In the query |
| 271 | SELECT t.a FROM t1 HAVING AVG(t1.a+(SELECT MIN(t2.c) FROM t2)) |
| 272 | the value of the max_arg_level for the AVG set function is 0 since |
| 273 | the reference t2.c is bound in the subquery. |
| 274 | |
| 275 | The field 'max_sum_func_level' is to contain the maximum of the |
| 276 | nest levels of the set functions that are used as subexpressions of |
| 277 | the arguments of the given set function, but not aggregated in any |
| 278 | subquery within this set function. A nested set function s1 can be |
| 279 | used within set function s0 only if s1.max_sum_func_level < |
| 280 | s0.max_sum_func_level. Set function s1 is considered as nested |
| 281 | for set function s0 if s1 is not calculated in any subquery |
| 282 | within s0. |
| 283 | |
| 284 | A set function that is used as a subexpression in an argument of another |
| 285 | set function refers to the latter via the field 'in_sum_func'. |
| 286 | |
| 287 | The condition imposed on the usage of set functions are checked when |
| 288 | we traverse query subexpressions with the help of the recursive method |
| 289 | fix_fields. When we apply this method to an object of the class |
| 290 | Item_sum, first, on the descent, we call the method init_sum_func_check |
| 291 | that initialize members used at checking. Then, on the ascent, we |
| 292 | call the method check_sum_func that validates the set function usage |
| 293 | and reports an error if it is illegal. |
| 294 | The method register_sum_func serves to link the items for the set functions |
| 295 | that are aggregated in the embedding (sub)queries. Circular chains of such |
| 296 | functions are attached to the corresponding st_select_lex structures |
| 297 | through the field inner_sum_func_list. |
| 298 | |
| 299 | Exploiting the fact that the members mentioned above are used in one |
| 300 | recursive function we could have allocated them on the thread stack. |
| 301 | Yet we don't do it now. |
| 302 | |
| 303 | We assume that the nesting level of subquries does not exceed 127. |
| 304 | TODO: to catch queries where the limit is exceeded to make the |
| 305 | code clean here. |
| 306 | |
| 307 | @note |
| 308 | The implementation takes into account the used strategy: |
| 309 | - Items resolved at optimization phase return 0 from Item_sum::used_tables(). |
| 310 | - Items that depend on the number of join output records, but not columns of |
| 311 | any particular table (like COUNT(*)), returm 0 from Item_sum::used_tables(), |
| 312 | but still return false from Item_sum::const_item(). |
| 313 | */ |
| 314 | |
| 315 | class Item_sum :public Item_func_or_sum |
| 316 | { |
| 317 | friend class Aggregator_distinct; |
| 318 | friend class Aggregator_simple; |
| 319 | |
| 320 | protected: |
| 321 | /** |
| 322 | Aggregator class instance. Not set initially. Allocated only after |
| 323 | it is determined if the incoming data are already distinct. |
| 324 | */ |
| 325 | Aggregator *aggr; |
| 326 | |
| 327 | private: |
| 328 | /** |
| 329 | Used in making ROLLUP. Set for the ROLLUP copies of the original |
| 330 | Item_sum and passed to create_tmp_field() to cause it to work |
| 331 | over the temp table buffer that is referenced by |
| 332 | Item_result_field::result_field. |
| 333 | */ |
| 334 | bool force_copy_fields; |
| 335 | |
| 336 | /** |
| 337 | Indicates how the aggregate function was specified by the parser : |
| 338 | 1 if it was written as AGGREGATE(DISTINCT), |
| 339 | 0 if it was AGGREGATE() |
| 340 | */ |
| 341 | bool with_distinct; |
| 342 | |
| 343 | /* TRUE if this is aggregate function of a window function */ |
| 344 | bool window_func_sum_expr_flag; |
| 345 | |
| 346 | public: |
| 347 | |
| 348 | bool has_force_copy_fields() const { return force_copy_fields; } |
| 349 | bool has_with_distinct() const { return with_distinct; } |
| 350 | |
| 351 | enum Sumfunctype |
| 352 | { COUNT_FUNC, COUNT_DISTINCT_FUNC, SUM_FUNC, SUM_DISTINCT_FUNC, AVG_FUNC, |
| 353 | AVG_DISTINCT_FUNC, MIN_FUNC, MAX_FUNC, STD_FUNC, |
| 354 | VARIANCE_FUNC, SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC, |
| 355 | ROW_NUMBER_FUNC, RANK_FUNC, DENSE_RANK_FUNC, PERCENT_RANK_FUNC, |
| 356 | CUME_DIST_FUNC, NTILE_FUNC, FIRST_VALUE_FUNC, LAST_VALUE_FUNC, |
| 357 | NTH_VALUE_FUNC, LEAD_FUNC, LAG_FUNC, PERCENTILE_CONT_FUNC, |
| 358 | PERCENTILE_DISC_FUNC, SP_AGGREGATE_FUNC |
| 359 | }; |
| 360 | |
| 361 | Item **ref_by; /* pointer to a ref to the object used to register it */ |
| 362 | Item_sum *next; /* next in the circular chain of registered objects */ |
| 363 | Item_sum *in_sum_func; /* embedding set function if any */ |
| 364 | st_select_lex * aggr_sel; /* select where the function is aggregated */ |
| 365 | int8 nest_level; /* number of the nesting level of the set function */ |
| 366 | int8 aggr_level; /* nesting level of the aggregating subquery */ |
| 367 | int8 max_arg_level; /* max level of unbound column references */ |
| 368 | int8 max_sum_func_level;/* max level of aggregation for embedded functions */ |
| 369 | bool quick_group; /* If incremental update of fields */ |
| 370 | /* |
| 371 | This list is used by the check for mixing non aggregated fields and |
| 372 | sum functions in the ONLY_FULL_GROUP_BY_MODE. We save all outer fields |
| 373 | directly or indirectly used under this function it as it's unclear |
| 374 | at the moment of fixing outer field whether it's aggregated or not. |
| 375 | */ |
| 376 | List<Item_field> outer_fields; |
| 377 | |
| 378 | protected: |
| 379 | /* |
| 380 | Copy of the arguments list to hold the original set of arguments. |
| 381 | Used in EXPLAIN EXTENDED instead of the current argument list because |
| 382 | the current argument list can be altered by usage of temporary tables. |
| 383 | */ |
| 384 | Item **orig_args, *tmp_orig_args[2]; |
| 385 | |
| 386 | static size_t ram_limitation(THD *thd); |
| 387 | |
| 388 | public: |
| 389 | |
| 390 | void mark_as_sum_func(); |
| 391 | Item_sum(THD *thd): Item_func_or_sum(thd), quick_group(1) |
| 392 | { |
| 393 | mark_as_sum_func(); |
| 394 | init_aggregator(); |
| 395 | } |
| 396 | Item_sum(THD *thd, Item *a): Item_func_or_sum(thd, a), quick_group(1), |
| 397 | orig_args(tmp_orig_args) |
| 398 | { |
| 399 | mark_as_sum_func(); |
| 400 | init_aggregator(); |
| 401 | } |
| 402 | Item_sum(THD *thd, Item *a, Item *b): Item_func_or_sum(thd, a, b), |
| 403 | quick_group(1), orig_args(tmp_orig_args) |
| 404 | { |
| 405 | mark_as_sum_func(); |
| 406 | init_aggregator(); |
| 407 | } |
| 408 | Item_sum(THD *thd, List<Item> &list); |
| 409 | //Copy constructor, need to perform subselects with temporary tables |
| 410 | Item_sum(THD *thd, Item_sum *item); |
| 411 | enum Type type() const { return SUM_FUNC_ITEM; } |
| 412 | virtual enum Sumfunctype sum_func () const=0; |
| 413 | bool is_aggr_sum_func() |
| 414 | { |
| 415 | switch (sum_func()) { |
| 416 | case COUNT_FUNC: |
| 417 | case COUNT_DISTINCT_FUNC: |
| 418 | case SUM_FUNC: |
| 419 | case SUM_DISTINCT_FUNC: |
| 420 | case AVG_FUNC: |
| 421 | case AVG_DISTINCT_FUNC: |
| 422 | case MIN_FUNC: |
| 423 | case MAX_FUNC: |
| 424 | case STD_FUNC: |
| 425 | case VARIANCE_FUNC: |
| 426 | case SUM_BIT_FUNC: |
| 427 | case UDF_SUM_FUNC: |
| 428 | case GROUP_CONCAT_FUNC: |
| 429 | return true; |
| 430 | default: |
| 431 | return false; |
| 432 | } |
| 433 | } |
| 434 | /** |
| 435 | Resets the aggregate value to its default and aggregates the current |
| 436 | value of its attribute(s). |
| 437 | */ |
| 438 | inline bool reset_and_add() |
| 439 | { |
| 440 | aggregator_clear(); |
| 441 | return aggregator_add(); |
| 442 | }; |
| 443 | |
| 444 | /* |
| 445 | Called when new group is started and results are being saved in |
| 446 | a temporary table. Similarly to reset_and_add() it resets the |
| 447 | value to its default and aggregates the value of its |
| 448 | attribute(s), but must also store it in result_field. |
| 449 | This set of methods (result_item(), reset_field, update_field()) of |
| 450 | Item_sum is used only if quick_group is not null. Otherwise |
| 451 | copy_or_same() is used to obtain a copy of this item. |
| 452 | */ |
| 453 | virtual void reset_field()=0; |
| 454 | /* |
| 455 | Called for each new value in the group, when temporary table is in use. |
| 456 | Similar to add(), but uses temporary table field to obtain current value, |
| 457 | Updated value is then saved in the field. |
| 458 | */ |
| 459 | virtual void update_field()=0; |
| 460 | virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } |
| 461 | virtual Item *result_item(THD *thd, Field *field); |
| 462 | |
| 463 | void update_used_tables (); |
| 464 | COND *build_equal_items(THD *thd, COND_EQUAL *inherited, |
| 465 | bool link_item_fields, |
| 466 | COND_EQUAL **cond_equal_ref) |
| 467 | { |
| 468 | /* |
| 469 | Item_sum (and derivants) of the original WHERE/HAVING clauses |
| 470 | should already be replaced to Item_aggregate_ref by the time when |
| 471 | build_equal_items() is called. See Item::split_sum_func2(). |
| 472 | */ |
| 473 | DBUG_ASSERT(0); |
| 474 | return Item::build_equal_items(thd, inherited, link_item_fields, |
| 475 | cond_equal_ref); |
| 476 | } |
| 477 | bool is_null() { return null_value; } |
| 478 | /** |
| 479 | make_const() |
| 480 | Called if we've managed to calculate the value of this Item in |
| 481 | opt_sum_query(), hence it can be considered constant at all subsequent |
| 482 | steps. |
| 483 | */ |
| 484 | void make_const () |
| 485 | { |
| 486 | used_tables_cache= 0; |
| 487 | const_item_cache= true; |
| 488 | } |
| 489 | void reset_forced_const() { const_item_cache= false; } |
| 490 | virtual bool const_during_execution() const { return false; } |
| 491 | virtual void print(String *str, enum_query_type query_type); |
| 492 | void fix_num_length_and_dec(); |
| 493 | |
| 494 | /** |
| 495 | Mark an aggregate as having no rows. |
| 496 | |
| 497 | This function is called by the execution engine to assign 'NO ROWS |
| 498 | FOUND' value to an aggregate item, when the underlying result set |
| 499 | has no rows. Such value, in a general case, may be different from |
| 500 | the default value of the item after 'clear()': e.g. a numeric item |
| 501 | may be initialized to 0 by clear() and to NULL by |
| 502 | no_rows_in_result(). |
| 503 | */ |
| 504 | virtual void no_rows_in_result() |
| 505 | { |
| 506 | set_aggregator(with_distinct ? |
| 507 | Aggregator::DISTINCT_AGGREGATOR : |
| 508 | Aggregator::SIMPLE_AGGREGATOR); |
| 509 | aggregator_clear(); |
| 510 | } |
| 511 | virtual void make_unique() { force_copy_fields= TRUE; } |
| 512 | Item *get_tmp_table_item(THD *thd); |
| 513 | Field *create_tmp_field(bool group, TABLE *table); |
| 514 | virtual bool collect_outer_ref_processor(void *param); |
| 515 | bool init_sum_func_check(THD *thd); |
| 516 | bool check_sum_func(THD *thd, Item **ref); |
| 517 | bool register_sum_func(THD *thd, Item **ref); |
| 518 | st_select_lex *depended_from() |
| 519 | { return (nest_level == aggr_level ? 0 : aggr_sel); } |
| 520 | |
| 521 | Item *get_arg(uint i) const { return args[i]; } |
| 522 | Item *set_arg(uint i, THD *thd, Item *new_val); |
| 523 | uint get_arg_count() const { return arg_count; } |
| 524 | virtual Item **get_args() { return fixed ? orig_args : args; } |
| 525 | |
| 526 | /* Initialization of distinct related members */ |
| 527 | void init_aggregator() |
| 528 | { |
| 529 | aggr= NULL; |
| 530 | with_distinct= FALSE; |
| 531 | force_copy_fields= FALSE; |
| 532 | } |
| 533 | |
| 534 | /** |
| 535 | Called to initialize the aggregator. |
| 536 | */ |
| 537 | |
| 538 | inline bool aggregator_setup(THD *thd) { return aggr->setup(thd); }; |
| 539 | |
| 540 | /** |
| 541 | Called to cleanup the aggregator. |
| 542 | */ |
| 543 | |
| 544 | inline void aggregator_clear() { aggr->clear(); } |
| 545 | |
| 546 | /** |
| 547 | Called to add value to the aggregator. |
| 548 | */ |
| 549 | |
| 550 | inline bool aggregator_add() { return aggr->add(); }; |
| 551 | |
| 552 | /* stores the declared DISTINCT flag (from the parser) */ |
| 553 | void set_distinct(bool distinct) |
| 554 | { |
| 555 | with_distinct= distinct; |
| 556 | quick_group= with_distinct ? 0 : 1; |
| 557 | } |
| 558 | |
| 559 | /* |
| 560 | Set the type of aggregation : DISTINCT or not. |
| 561 | |
| 562 | May be called multiple times. |
| 563 | */ |
| 564 | |
| 565 | int set_aggregator(Aggregator::Aggregator_type aggregator); |
| 566 | |
| 567 | virtual void clear()= 0; |
| 568 | virtual bool add()= 0; |
| 569 | virtual bool setup(THD *thd) { return false; } |
| 570 | |
| 571 | virtual bool supports_removal() const { return false; } |
| 572 | virtual void remove() { DBUG_ASSERT(0); } |
| 573 | |
| 574 | virtual void cleanup(); |
| 575 | bool check_vcol_func_processor(void *arg); |
| 576 | virtual void setup_window_func(THD *thd, Window_spec *window_spec) {} |
| 577 | void mark_as_window_func_sum_expr() { window_func_sum_expr_flag= true; } |
| 578 | bool is_window_func_sum_expr() { return window_func_sum_expr_flag; } |
| 579 | virtual void setup_caches(THD *thd) {}; |
| 580 | }; |
| 581 | |
| 582 | |
| 583 | class Unique; |
| 584 | |
| 585 | |
| 586 | /** |
| 587 | The distinct aggregator. |
| 588 | Implements AGGFN (DISTINCT ..) |
| 589 | Collects all the data into an Unique (similarly to what Item_sum |
| 590 | does currently when with_distinct=true) and then (if applicable) iterates over |
| 591 | the list of unique values and pumps them back into its object |
| 592 | */ |
| 593 | |
| 594 | class Aggregator_distinct : public Aggregator |
| 595 | { |
| 596 | friend class Item_sum_sum; |
| 597 | |
| 598 | /* |
| 599 | flag to prevent consecutive runs of endup(). Normally in endup there are |
| 600 | expensive calculations (like walking the distinct tree for example) |
| 601 | which we must do only once if there are no data changes. |
| 602 | We can re-use the data for the second and subsequent val_xxx() calls. |
| 603 | endup_done set to TRUE also means that the calculated values for |
| 604 | the aggregate functions are correct and don't need recalculation. |
| 605 | */ |
| 606 | bool endup_done; |
| 607 | |
| 608 | /* |
| 609 | Used depending on the type of the aggregate function and the presence of |
| 610 | blob columns in it: |
| 611 | - For COUNT(DISTINCT) and no blob fields this points to a real temporary |
| 612 | table. It's used as a hash table. |
| 613 | - For AVG/SUM(DISTINCT) or COUNT(DISTINCT) with blob fields only the |
| 614 | in-memory data structure of a temporary table is constructed. |
| 615 | It's used by the Field classes to transform data into row format. |
| 616 | */ |
| 617 | TABLE *table; |
| 618 | |
| 619 | /* |
| 620 | An array of field lengths on row allocated and used only for |
| 621 | COUNT(DISTINCT) with multiple columns and no blobs. Used in |
| 622 | Aggregator_distinct::composite_key_cmp (called from Unique to compare |
| 623 | nodes |
| 624 | */ |
| 625 | uint32 *field_lengths; |
| 626 | |
| 627 | /* |
| 628 | Used in conjunction with 'table' to support the access to Field classes |
| 629 | for COUNT(DISTINCT). Needed by copy_fields()/copy_funcs(). |
| 630 | */ |
| 631 | TMP_TABLE_PARAM *tmp_table_param; |
| 632 | |
| 633 | /* |
| 634 | If there are no blobs in the COUNT(DISTINCT) arguments, we can use a tree, |
| 635 | which is faster than heap table. In that case, we still use the table |
| 636 | to help get things set up, but we insert nothing in it. |
| 637 | For AVG/SUM(DISTINCT) we always use this tree (as it takes a single |
| 638 | argument) to get the distinct rows. |
| 639 | */ |
| 640 | Unique *tree; |
| 641 | |
| 642 | /* |
| 643 | The length of the temp table row. Must be a member of the class as it |
| 644 | gets passed down to simple_raw_key_cmp () as a compare function argument |
| 645 | to Unique. simple_raw_key_cmp () is used as a fast comparison function |
| 646 | when the entire row can be binary compared. |
| 647 | */ |
| 648 | uint tree_key_length; |
| 649 | |
| 650 | /* |
| 651 | Set to true if the result is known to be always NULL. |
| 652 | If set deactivates creation and usage of the temporary table (in the |
| 653 | 'table' member) and the Unique instance (in the 'tree' member) as well as |
| 654 | the calculation of the final value on the first call to |
| 655 | Item_[sum|avg|count]::val_xxx(). |
| 656 | */ |
| 657 | bool always_null; |
| 658 | |
| 659 | /** |
| 660 | When feeding back the data in endup() from Unique/temp table back to |
| 661 | Item_sum::add() methods we must read the data from Unique (and not |
| 662 | recalculate the functions that are given as arguments to the aggregate |
| 663 | function. |
| 664 | This flag is to tell the arg_*() methods to take the data from the Unique |
| 665 | instead of calling the relevant val_..() method. |
| 666 | */ |
| 667 | bool use_distinct_values; |
| 668 | |
| 669 | public: |
| 670 | Aggregator_distinct (Item_sum *sum) : |
| 671 | Aggregator(sum), table(NULL), tmp_table_param(NULL), tree(NULL), |
| 672 | always_null(false), use_distinct_values(false) {} |
| 673 | virtual ~Aggregator_distinct (); |
| 674 | Aggregator_type Aggrtype() { return DISTINCT_AGGREGATOR; } |
| 675 | |
| 676 | bool setup(THD *); |
| 677 | void clear(); |
| 678 | bool add(); |
| 679 | void endup(); |
| 680 | virtual my_decimal *arg_val_decimal(my_decimal * value); |
| 681 | virtual double arg_val_real(); |
| 682 | virtual bool arg_is_null(bool use_null_value); |
| 683 | |
| 684 | bool unique_walk_function(void *element); |
| 685 | bool unique_walk_function_for_count(void *element); |
| 686 | static int composite_key_cmp(void* arg, uchar* key1, uchar* key2); |
| 687 | }; |
| 688 | |
| 689 | |
| 690 | /** |
| 691 | The pass-through aggregator. |
| 692 | Implements AGGFN (DISTINCT ..) by knowing it gets distinct data on input. |
| 693 | So it just pumps them back to the Item_sum descendant class. |
| 694 | */ |
| 695 | class Aggregator_simple : public Aggregator |
| 696 | { |
| 697 | public: |
| 698 | |
| 699 | Aggregator_simple (Item_sum *sum) : |
| 700 | Aggregator(sum) {} |
| 701 | Aggregator_type Aggrtype() { return Aggregator::SIMPLE_AGGREGATOR; } |
| 702 | |
| 703 | bool setup(THD * thd) { return item_sum->setup(thd); } |
| 704 | void clear() { item_sum->clear(); } |
| 705 | bool add() { return item_sum->add(); } |
| 706 | void endup() {}; |
| 707 | virtual my_decimal *arg_val_decimal(my_decimal * value); |
| 708 | virtual double arg_val_real(); |
| 709 | virtual bool arg_is_null(bool use_null_value); |
| 710 | }; |
| 711 | |
| 712 | |
| 713 | class Item_sum_num :public Item_sum |
| 714 | { |
| 715 | protected: |
| 716 | /* |
| 717 | val_xxx() functions may be called several times during the execution of a |
| 718 | query. Derived classes that require extensive calculation in val_xxx() |
| 719 | maintain cache of aggregate value. This variable governs the validity of |
| 720 | that cache. |
| 721 | */ |
| 722 | bool is_evaluated; |
| 723 | public: |
| 724 | Item_sum_num(THD *thd): Item_sum(thd), is_evaluated(FALSE) {} |
| 725 | Item_sum_num(THD *thd, Item *item_par): |
| 726 | Item_sum(thd, item_par), is_evaluated(FALSE) {} |
| 727 | Item_sum_num(THD *thd, Item *a, Item* b): |
| 728 | Item_sum(thd, a, b), is_evaluated(FALSE) {} |
| 729 | Item_sum_num(THD *thd, List<Item> &list): |
| 730 | Item_sum(thd, list), is_evaluated(FALSE) {} |
| 731 | Item_sum_num(THD *thd, Item_sum_num *item): |
| 732 | Item_sum(thd, item),is_evaluated(item->is_evaluated) {} |
| 733 | bool fix_fields(THD *, Item **); |
| 734 | longlong val_int() { return val_int_from_real(); /* Real as default */ } |
| 735 | String *val_str(String*str); |
| 736 | my_decimal *val_decimal(my_decimal *); |
| 737 | bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) |
| 738 | { |
| 739 | return type_handler()->Item_get_date(this, ltime, fuzzydate); |
| 740 | } |
| 741 | void reset_field(); |
| 742 | }; |
| 743 | |
| 744 | |
| 745 | class Item_sum_int :public Item_sum_num |
| 746 | { |
| 747 | public: |
| 748 | Item_sum_int(THD *thd): Item_sum_num(thd) {} |
| 749 | Item_sum_int(THD *thd, Item *item_par): Item_sum_num(thd, item_par) {} |
| 750 | Item_sum_int(THD *thd, List<Item> &list): Item_sum_num(thd, list) {} |
| 751 | Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {} |
| 752 | double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); } |
| 753 | String *val_str(String*str); |
| 754 | my_decimal *val_decimal(my_decimal *); |
| 755 | const Type_handler *type_handler() const { return &type_handler_longlong; } |
| 756 | void fix_length_and_dec() |
| 757 | { decimals=0; max_length=21; maybe_null=null_value=0; } |
| 758 | }; |
| 759 | |
| 760 | |
| 761 | class Item_sum_sum :public Item_sum_num, |
| 762 | public Type_handler_hybrid_field_type |
| 763 | { |
| 764 | protected: |
| 765 | bool direct_added; |
| 766 | bool direct_reseted_field; |
| 767 | bool direct_sum_is_null; |
| 768 | double direct_sum_real; |
| 769 | double sum; |
| 770 | my_decimal direct_sum_decimal; |
| 771 | my_decimal dec_buffs[2]; |
| 772 | uint curr_dec_buff; |
| 773 | void fix_length_and_dec(); |
| 774 | |
| 775 | public: |
| 776 | Item_sum_sum(THD *thd, Item *item_par, bool distinct): |
| 777 | Item_sum_num(thd, item_par), direct_added(FALSE), |
| 778 | direct_reseted_field(FALSE) |
| 779 | { |
| 780 | set_distinct(distinct); |
| 781 | } |
| 782 | Item_sum_sum(THD *thd, Item_sum_sum *item); |
| 783 | enum Sumfunctype sum_func () const |
| 784 | { |
| 785 | return has_with_distinct() ? SUM_DISTINCT_FUNC : SUM_FUNC; |
| 786 | } |
| 787 | void cleanup(); |
| 788 | void direct_add(my_decimal *add_sum_decimal); |
| 789 | void direct_add(double add_sum_real, bool add_sum_is_null); |
| 790 | void clear(); |
| 791 | bool add(); |
| 792 | double val_real(); |
| 793 | longlong val_int(); |
| 794 | String *val_str(String*str); |
| 795 | my_decimal *val_decimal(my_decimal *); |
| 796 | const Type_handler *type_handler() const |
| 797 | { return Type_handler_hybrid_field_type::type_handler(); } |
| 798 | void fix_length_and_dec_double(); |
| 799 | void fix_length_and_dec_decimal(); |
| 800 | void reset_field(); |
| 801 | void update_field(); |
| 802 | void no_rows_in_result() {} |
| 803 | const char *func_name() const |
| 804 | { |
| 805 | return has_with_distinct() ? "sum(distinct " : "sum(" ; |
| 806 | } |
| 807 | Item *copy_or_same(THD* thd); |
| 808 | void remove(); |
| 809 | Item *get_copy(THD *thd) |
| 810 | { return get_item_copy<Item_sum_sum>(thd, this); } |
| 811 | |
| 812 | bool supports_removal() const |
| 813 | { |
| 814 | return true; |
| 815 | } |
| 816 | |
| 817 | private: |
| 818 | void add_helper(bool perform_removal); |
| 819 | ulonglong count; |
| 820 | }; |
| 821 | |
| 822 | |
| 823 | class Item_sum_count :public Item_sum_int |
| 824 | { |
| 825 | bool direct_counted; |
| 826 | bool direct_reseted_field; |
| 827 | longlong direct_count; |
| 828 | longlong count; |
| 829 | |
| 830 | friend class Aggregator_distinct; |
| 831 | |
| 832 | void clear(); |
| 833 | bool add(); |
| 834 | void cleanup(); |
| 835 | void remove(); |
| 836 | |
| 837 | public: |
| 838 | Item_sum_count(THD *thd, Item *item_par): |
| 839 | Item_sum_int(thd, item_par), direct_counted(FALSE), |
| 840 | direct_reseted_field(FALSE), count(0) |
| 841 | {} |
| 842 | |
| 843 | /** |
| 844 | Constructs an instance for COUNT(DISTINCT) |
| 845 | |
| 846 | @param list a list of the arguments to the aggregate function |
| 847 | |
| 848 | This constructor is called by the parser only for COUNT (DISTINCT). |
| 849 | */ |
| 850 | |
| 851 | Item_sum_count(THD *thd, List<Item> &list): |
| 852 | Item_sum_int(thd, list), direct_counted(FALSE), |
| 853 | direct_reseted_field(FALSE), count(0) |
| 854 | { |
| 855 | set_distinct(TRUE); |
| 856 | } |
| 857 | Item_sum_count(THD *thd, Item_sum_count *item): |
| 858 | Item_sum_int(thd, item), direct_counted(FALSE), |
| 859 | direct_reseted_field(FALSE), count(item->count) |
| 860 | {} |
| 861 | enum Sumfunctype sum_func () const |
| 862 | { |
| 863 | return has_with_distinct() ? COUNT_DISTINCT_FUNC : COUNT_FUNC; |
| 864 | } |
| 865 | void no_rows_in_result() { count=0; } |
| 866 | void make_const(longlong count_arg) |
| 867 | { |
| 868 | count=count_arg; |
| 869 | Item_sum::make_const(); |
| 870 | } |
| 871 | longlong val_int(); |
| 872 | void reset_field(); |
| 873 | void update_field(); |
| 874 | void direct_add(longlong add_count); |
| 875 | const char *func_name() const |
| 876 | { |
| 877 | return has_with_distinct() ? "count(distinct " : "count(" ; |
| 878 | } |
| 879 | Item *copy_or_same(THD* thd); |
| 880 | Item *get_copy(THD *thd) |
| 881 | { return get_item_copy<Item_sum_count>(thd, this); } |
| 882 | |
| 883 | bool supports_removal() const |
| 884 | { |
| 885 | return true; |
| 886 | } |
| 887 | }; |
| 888 | |
| 889 | |
| 890 | class Item_sum_avg :public Item_sum_sum |
| 891 | { |
| 892 | public: |
| 893 | // TODO-cvicentiu given that Item_sum_sum now uses a counter of its own, in |
| 894 | // order to implement remove(), it is possible to remove this member. |
| 895 | ulonglong count; |
| 896 | uint prec_increment; |
| 897 | uint f_precision, f_scale, dec_bin_size; |
| 898 | |
| 899 | Item_sum_avg(THD *thd, Item *item_par, bool distinct): |
| 900 | Item_sum_sum(thd, item_par, distinct), count(0) |
| 901 | {} |
| 902 | Item_sum_avg(THD *thd, Item_sum_avg *item) |
| 903 | :Item_sum_sum(thd, item), count(item->count), |
| 904 | prec_increment(item->prec_increment) {} |
| 905 | |
| 906 | void fix_length_and_dec_double(); |
| 907 | void fix_length_and_dec_decimal(); |
| 908 | void fix_length_and_dec(); |
| 909 | enum Sumfunctype sum_func () const |
| 910 | { |
| 911 | return has_with_distinct() ? AVG_DISTINCT_FUNC : AVG_FUNC; |
| 912 | } |
| 913 | void clear(); |
| 914 | bool add(); |
| 915 | void remove(); |
| 916 | double val_real(); |
| 917 | // In SPs we might force the "wrong" type with select into a declare variable |
| 918 | longlong val_int() { return val_int_from_real(); } |
| 919 | my_decimal *val_decimal(my_decimal *); |
| 920 | String *val_str(String *str); |
| 921 | void reset_field(); |
| 922 | void update_field(); |
| 923 | Item *result_item(THD *thd, Field *field); |
| 924 | void no_rows_in_result() {} |
| 925 | const char *func_name() const |
| 926 | { |
| 927 | return has_with_distinct() ? "avg(distinct " : "avg(" ; |
| 928 | } |
| 929 | Item *copy_or_same(THD* thd); |
| 930 | Field *create_tmp_field(bool group, TABLE *table); |
| 931 | void cleanup() |
| 932 | { |
| 933 | count= 0; |
| 934 | Item_sum_sum::cleanup(); |
| 935 | } |
| 936 | Item *get_copy(THD *thd) |
| 937 | { return get_item_copy<Item_sum_avg>(thd, this); } |
| 938 | |
| 939 | bool supports_removal() const |
| 940 | { |
| 941 | return true; |
| 942 | } |
| 943 | }; |
| 944 | |
| 945 | |
| 946 | /* |
| 947 | variance(a) = |
| 948 | |
| 949 | = sum (ai - avg(a))^2 / count(a) ) |
| 950 | = sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a) |
| 951 | = (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) = |
| 952 | = (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) = |
| 953 | = (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) = |
| 954 | = (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) = |
| 955 | = (sum(ai^2) - sum(a)^2/count(a))/count(a) |
| 956 | |
| 957 | But, this falls prey to catastrophic cancellation. Instead, use the recurrence formulas |
| 958 | |
| 959 | M_{1} = x_{1}, ~ M_{k} = M_{k-1} + (x_{k} - M_{k-1}) / k newline |
| 960 | S_{1} = 0, ~ S_{k} = S_{k-1} + (x_{k} - M_{k-1}) times (x_{k} - M_{k}) newline |
| 961 | for 2 <= k <= n newline |
| 962 | ital variance = S_{n} / (n-1) |
| 963 | |
| 964 | */ |
| 965 | |
| 966 | class Item_sum_variance : public Item_sum_num |
| 967 | { |
| 968 | void fix_length_and_dec(); |
| 969 | |
| 970 | public: |
| 971 | double recurrence_m, recurrence_s; /* Used in recurrence relation. */ |
| 972 | ulonglong count; |
| 973 | uint sample; |
| 974 | uint prec_increment; |
| 975 | |
| 976 | Item_sum_variance(THD *thd, Item *item_par, uint sample_arg): |
| 977 | Item_sum_num(thd, item_par), count(0), |
| 978 | sample(sample_arg) |
| 979 | {} |
| 980 | Item_sum_variance(THD *thd, Item_sum_variance *item); |
| 981 | enum Sumfunctype sum_func () const { return VARIANCE_FUNC; } |
| 982 | void fix_length_and_dec_double(); |
| 983 | void fix_length_and_dec_decimal(); |
| 984 | void clear(); |
| 985 | bool add(); |
| 986 | double val_real(); |
| 987 | my_decimal *val_decimal(my_decimal *); |
| 988 | void reset_field(); |
| 989 | void update_field(); |
| 990 | Item *result_item(THD *thd, Field *field); |
| 991 | void no_rows_in_result() {} |
| 992 | const char *func_name() const |
| 993 | { return sample ? "var_samp(" : "variance(" ; } |
| 994 | Item *copy_or_same(THD* thd); |
| 995 | Field *create_tmp_field(bool group, TABLE *table); |
| 996 | const Type_handler *type_handler() const { return &type_handler_double; } |
| 997 | void cleanup() |
| 998 | { |
| 999 | count= 0; |
| 1000 | Item_sum_num::cleanup(); |
| 1001 | } |
| 1002 | Item *get_copy(THD *thd) |
| 1003 | { return get_item_copy<Item_sum_variance>(thd, this); } |
| 1004 | }; |
| 1005 | |
| 1006 | /* |
| 1007 | standard_deviation(a) = sqrt(variance(a)) |
| 1008 | */ |
| 1009 | |
| 1010 | class Item_sum_std :public Item_sum_variance |
| 1011 | { |
| 1012 | public: |
| 1013 | Item_sum_std(THD *thd, Item *item_par, uint sample_arg): |
| 1014 | Item_sum_variance(thd, item_par, sample_arg) {} |
| 1015 | Item_sum_std(THD *thd, Item_sum_std *item) |
| 1016 | :Item_sum_variance(thd, item) |
| 1017 | {} |
| 1018 | enum Sumfunctype sum_func () const { return STD_FUNC; } |
| 1019 | double val_real(); |
| 1020 | Item *result_item(THD *thd, Field *field); |
| 1021 | const char *func_name() const { return "std(" ; } |
| 1022 | Item *copy_or_same(THD* thd); |
| 1023 | Item *get_copy(THD *thd) |
| 1024 | { return get_item_copy<Item_sum_std>(thd, this); } |
| 1025 | }; |
| 1026 | |
| 1027 | // This class is a string or number function depending on num_func |
| 1028 | class Arg_comparator; |
| 1029 | class Item_cache; |
| 1030 | class Item_sum_hybrid :public Item_sum, public Type_handler_hybrid_field_type |
| 1031 | { |
| 1032 | protected: |
| 1033 | bool direct_added; |
| 1034 | Item *direct_item; |
| 1035 | Item_cache *value, *arg_cache; |
| 1036 | Arg_comparator *cmp; |
| 1037 | int cmp_sign; |
| 1038 | bool was_values; // Set if we have found at least one row (for max/min only) |
| 1039 | bool was_null_value; |
| 1040 | |
| 1041 | public: |
| 1042 | Item_sum_hybrid(THD *thd, Item *item_par,int sign): |
| 1043 | Item_sum(thd, item_par), |
| 1044 | Type_handler_hybrid_field_type(&type_handler_longlong), |
| 1045 | direct_added(FALSE), value(0), arg_cache(0), cmp(0), |
| 1046 | cmp_sign(sign), was_values(TRUE) |
| 1047 | { collation.set(&my_charset_bin); } |
| 1048 | Item_sum_hybrid(THD *thd, Item_sum_hybrid *item) |
| 1049 | :Item_sum(thd, item), |
| 1050 | Type_handler_hybrid_field_type(item), |
| 1051 | direct_added(FALSE), value(item->value), arg_cache(0), |
| 1052 | cmp_sign(item->cmp_sign), was_values(item->was_values) |
| 1053 | { } |
| 1054 | bool fix_fields(THD *, Item **); |
| 1055 | void fix_length_and_dec(); |
| 1056 | void setup_hybrid(THD *thd, Item *item, Item *value_arg); |
| 1057 | void clear(); |
| 1058 | void direct_add(Item *item); |
| 1059 | double val_real(); |
| 1060 | longlong val_int(); |
| 1061 | my_decimal *val_decimal(my_decimal *); |
| 1062 | bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); |
| 1063 | void reset_field(); |
| 1064 | String *val_str(String *); |
| 1065 | const Type_handler *real_type_handler() const |
| 1066 | { |
| 1067 | return get_arg(0)->real_type_handler(); |
| 1068 | } |
| 1069 | const Type_handler *type_handler() const |
| 1070 | { return Type_handler_hybrid_field_type::type_handler(); } |
| 1071 | TYPELIB *get_typelib() const { return args[0]->get_typelib(); } |
| 1072 | void update_field(); |
| 1073 | void min_max_update_str_field(); |
| 1074 | void min_max_update_real_field(); |
| 1075 | void min_max_update_int_field(); |
| 1076 | void min_max_update_decimal_field(); |
| 1077 | void cleanup(); |
| 1078 | bool any_value() { return was_values; } |
| 1079 | void no_rows_in_result(); |
| 1080 | void restore_to_before_no_rows_in_result(); |
| 1081 | Field *create_tmp_field(bool group, TABLE *table); |
| 1082 | void setup_caches(THD *thd) { setup_hybrid(thd, arguments()[0], NULL); } |
| 1083 | }; |
| 1084 | |
| 1085 | |
| 1086 | class Item_sum_min :public Item_sum_hybrid |
| 1087 | { |
| 1088 | public: |
| 1089 | Item_sum_min(THD *thd, Item *item_par): Item_sum_hybrid(thd, item_par, 1) {} |
| 1090 | Item_sum_min(THD *thd, Item_sum_min *item) :Item_sum_hybrid(thd, item) {} |
| 1091 | enum Sumfunctype sum_func () const {return MIN_FUNC;} |
| 1092 | |
| 1093 | bool add(); |
| 1094 | const char *func_name() const { return "min(" ; } |
| 1095 | Item *copy_or_same(THD* thd); |
| 1096 | Item *get_copy(THD *thd) |
| 1097 | { return get_item_copy<Item_sum_min>(thd, this); } |
| 1098 | }; |
| 1099 | |
| 1100 | |
| 1101 | class Item_sum_max :public Item_sum_hybrid |
| 1102 | { |
| 1103 | public: |
| 1104 | Item_sum_max(THD *thd, Item *item_par): Item_sum_hybrid(thd, item_par, -1) {} |
| 1105 | Item_sum_max(THD *thd, Item_sum_max *item) :Item_sum_hybrid(thd, item) {} |
| 1106 | enum Sumfunctype sum_func () const {return MAX_FUNC;} |
| 1107 | |
| 1108 | bool add(); |
| 1109 | const char *func_name() const { return "max(" ; } |
| 1110 | Item *copy_or_same(THD* thd); |
| 1111 | Item *get_copy(THD *thd) |
| 1112 | { return get_item_copy<Item_sum_max>(thd, this); } |
| 1113 | }; |
| 1114 | |
| 1115 | |
| 1116 | class Item_sum_bit :public Item_sum_int |
| 1117 | { |
| 1118 | public: |
| 1119 | Item_sum_bit(THD *thd, Item *item_par, ulonglong reset_arg): |
| 1120 | Item_sum_int(thd, item_par), reset_bits(reset_arg), bits(reset_arg), |
| 1121 | as_window_function(FALSE), num_values_added(0) {} |
| 1122 | Item_sum_bit(THD *thd, Item_sum_bit *item): |
| 1123 | Item_sum_int(thd, item), reset_bits(item->reset_bits), bits(item->bits), |
| 1124 | as_window_function(item->as_window_function), |
| 1125 | num_values_added(item->num_values_added) |
| 1126 | { |
| 1127 | if (as_window_function) |
| 1128 | memcpy(bit_counters, item->bit_counters, sizeof(bit_counters)); |
| 1129 | } |
| 1130 | enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;} |
| 1131 | void clear(); |
| 1132 | longlong val_int(); |
| 1133 | void reset_field(); |
| 1134 | void update_field(); |
| 1135 | void fix_length_and_dec() |
| 1136 | { decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; } |
| 1137 | void cleanup() |
| 1138 | { |
| 1139 | bits= reset_bits; |
| 1140 | if (as_window_function) |
| 1141 | clear_as_window(); |
| 1142 | Item_sum_int::cleanup(); |
| 1143 | } |
| 1144 | void setup_window_func(THD *thd __attribute__((unused)), |
| 1145 | Window_spec *window_spec __attribute__((unused))) |
| 1146 | { |
| 1147 | as_window_function= TRUE; |
| 1148 | clear_as_window(); |
| 1149 | } |
| 1150 | void remove() |
| 1151 | { |
| 1152 | if (as_window_function) |
| 1153 | { |
| 1154 | remove_as_window(args[0]->val_int()); |
| 1155 | return; |
| 1156 | } |
| 1157 | // Unless we're counting bits, we can not remove anything. |
| 1158 | DBUG_ASSERT(0); |
| 1159 | } |
| 1160 | |
| 1161 | bool supports_removal() const |
| 1162 | { |
| 1163 | return true; |
| 1164 | } |
| 1165 | |
| 1166 | protected: |
| 1167 | enum bit_counters { NUM_BIT_COUNTERS= 64 }; |
| 1168 | ulonglong reset_bits,bits; |
| 1169 | /* |
| 1170 | Marks whether the function is to be computed as a window function. |
| 1171 | */ |
| 1172 | bool as_window_function; |
| 1173 | // When used as an aggregate window function, we need to store |
| 1174 | // this additional information. |
| 1175 | ulonglong num_values_added; |
| 1176 | ulonglong bit_counters[NUM_BIT_COUNTERS]; |
| 1177 | bool add_as_window(ulonglong value); |
| 1178 | bool remove_as_window(ulonglong value); |
| 1179 | bool clear_as_window(); |
| 1180 | virtual void set_bits_from_counters()= 0; |
| 1181 | }; |
| 1182 | |
| 1183 | |
| 1184 | class Item_sum_or :public Item_sum_bit |
| 1185 | { |
| 1186 | public: |
| 1187 | Item_sum_or(THD *thd, Item *item_par): Item_sum_bit(thd, item_par, 0) {} |
| 1188 | Item_sum_or(THD *thd, Item_sum_or *item) :Item_sum_bit(thd, item) {} |
| 1189 | bool add(); |
| 1190 | const char *func_name() const { return "bit_or(" ; } |
| 1191 | Item *copy_or_same(THD* thd); |
| 1192 | Item *get_copy(THD *thd) |
| 1193 | { return get_item_copy<Item_sum_or>(thd, this); } |
| 1194 | |
| 1195 | private: |
| 1196 | void set_bits_from_counters(); |
| 1197 | }; |
| 1198 | |
| 1199 | |
| 1200 | class Item_sum_and :public Item_sum_bit |
| 1201 | { |
| 1202 | public: |
| 1203 | Item_sum_and(THD *thd, Item *item_par): |
| 1204 | Item_sum_bit(thd, item_par, ULONGLONG_MAX) {} |
| 1205 | Item_sum_and(THD *thd, Item_sum_and *item) :Item_sum_bit(thd, item) {} |
| 1206 | bool add(); |
| 1207 | const char *func_name() const { return "bit_and(" ; } |
| 1208 | Item *copy_or_same(THD* thd); |
| 1209 | Item *get_copy(THD *thd) |
| 1210 | { return get_item_copy<Item_sum_and>(thd, this); } |
| 1211 | |
| 1212 | private: |
| 1213 | void set_bits_from_counters(); |
| 1214 | }; |
| 1215 | |
| 1216 | class Item_sum_xor :public Item_sum_bit |
| 1217 | { |
| 1218 | public: |
| 1219 | Item_sum_xor(THD *thd, Item *item_par): Item_sum_bit(thd, item_par, 0) {} |
| 1220 | Item_sum_xor(THD *thd, Item_sum_xor *item) :Item_sum_bit(thd, item) {} |
| 1221 | bool add(); |
| 1222 | const char *func_name() const { return "bit_xor(" ; } |
| 1223 | Item *copy_or_same(THD* thd); |
| 1224 | Item *get_copy(THD *thd) |
| 1225 | { return get_item_copy<Item_sum_xor>(thd, this); } |
| 1226 | |
| 1227 | private: |
| 1228 | void set_bits_from_counters(); |
| 1229 | }; |
| 1230 | |
| 1231 | class sp_head; |
| 1232 | class sp_name; |
| 1233 | class Query_arena; |
| 1234 | struct st_sp_security_context; |
| 1235 | |
| 1236 | /* |
| 1237 | Item_sum_sp handles STORED AGGREGATE FUNCTIONS |
| 1238 | |
| 1239 | Each Item_sum_sp represents a custom aggregate function. Inside the |
| 1240 | function's body, we require at least one occurence of FETCH GROUP NEXT ROW |
| 1241 | instruction. This cursor is what makes custom stored aggregates possible. |
| 1242 | |
| 1243 | During computation the function's add method is called. This in turn performs |
| 1244 | an execution of the function. The function will execute from the current |
| 1245 | function context (and instruction), if one exists, or from the start if not. |
| 1246 | See Item_sp for more details. |
| 1247 | |
| 1248 | Upon encounter of FETCH GROUP NEXT ROW instruction, the function will pause |
| 1249 | execution. We assume that the user has performed the necessary additions for |
| 1250 | a row, between two encounters of FETCH GROUP NEXT ROW. |
| 1251 | |
| 1252 | Example: |
| 1253 | create aggregate function f1(x INT) returns int |
| 1254 | begin |
| 1255 | declare continue handler for not found return s; |
| 1256 | declare s int default 0 |
| 1257 | loop |
| 1258 | fetch group next row; |
| 1259 | set s = s + x; |
| 1260 | end loop; |
| 1261 | end |
| 1262 | |
| 1263 | The function will always stop after an encounter of FETCH GROUP NEXT ROW, |
| 1264 | except (!) on first encounter, as the value for the first row in the |
| 1265 | group is already set in the argument x. This behaviour is done so when |
| 1266 | a user writes a function, he should "logically" include FETCH GROUP NEXT ROW |
| 1267 | before any "add" instructions in the stored function. This means however that |
| 1268 | internally, the first occurence doesn't stop the function. See the |
| 1269 | implementation of FETCH GROUP NEXT ROW for details as to how it happens. |
| 1270 | |
| 1271 | Either way, one should assume that after calling "Item_sum_sp::add()" that |
| 1272 | the values for that particular row have been added to the aggregation. |
| 1273 | |
| 1274 | To produce values for val_xxx methods we need an extra syntactic construct. |
| 1275 | We require a continue handler when "no more rows are available". val_xxx |
| 1276 | methods force a function return by executing the function again, while |
| 1277 | setting a server flag that no more rows have been found. This implies |
| 1278 | that val_xxx methods should only be called once per group however. |
| 1279 | |
| 1280 | Example: |
| 1281 | DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN ret_val; |
| 1282 | */ |
| 1283 | class Item_sum_sp :public Item_sum, |
| 1284 | public Item_sp |
| 1285 | { |
| 1286 | private: |
| 1287 | bool execute(); |
| 1288 | |
| 1289 | public: |
| 1290 | Item_sum_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name, |
| 1291 | sp_head *sp); |
| 1292 | |
| 1293 | Item_sum_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name, |
| 1294 | sp_head *sp, List<Item> &list); |
| 1295 | Item_sum_sp(THD *thd, Item_sum_sp *item); |
| 1296 | |
| 1297 | enum Sumfunctype sum_func () const |
| 1298 | { |
| 1299 | return SP_AGGREGATE_FUNC; |
| 1300 | } |
| 1301 | Field *create_field_for_create_select(TABLE *table) |
| 1302 | { |
| 1303 | return create_table_field_from_handler(table); |
| 1304 | } |
| 1305 | void fix_length_and_dec(); |
| 1306 | bool fix_fields(THD *thd, Item **ref); |
| 1307 | const char *func_name() const; |
| 1308 | const Type_handler *type_handler() const; |
| 1309 | bool add(); |
| 1310 | |
| 1311 | /* val_xx functions */ |
| 1312 | longlong val_int() |
| 1313 | { |
| 1314 | if(execute()) |
| 1315 | return 0; |
| 1316 | return sp_result_field->val_int(); |
| 1317 | } |
| 1318 | |
| 1319 | double val_real() |
| 1320 | { |
| 1321 | if(execute()) |
| 1322 | return 0.0; |
| 1323 | return sp_result_field->val_real(); |
| 1324 | } |
| 1325 | |
| 1326 | my_decimal *val_decimal(my_decimal *dec_buf) |
| 1327 | { |
| 1328 | if(execute()) |
| 1329 | return NULL; |
| 1330 | return sp_result_field->val_decimal(dec_buf); |
| 1331 | } |
| 1332 | |
| 1333 | String *val_str(String *str) |
| 1334 | { |
| 1335 | String buf; |
| 1336 | char buff[20]; |
| 1337 | buf.set(buff, 20, str->charset()); |
| 1338 | buf.length(0); |
| 1339 | if (execute()) |
| 1340 | return NULL; |
| 1341 | /* |
| 1342 | result_field will set buf pointing to internal buffer |
| 1343 | of the resul_field. Due to this it will change any time |
| 1344 | when SP is executed. In order to prevent occasional |
| 1345 | corruption of returned value, we make here a copy. |
| 1346 | */ |
| 1347 | sp_result_field->val_str(&buf); |
| 1348 | str->copy(buf); |
| 1349 | return str; |
| 1350 | } |
| 1351 | void reset_field(){DBUG_ASSERT(0);} |
| 1352 | void update_field(){DBUG_ASSERT(0);} |
| 1353 | void clear(); |
| 1354 | void cleanup(); |
| 1355 | bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) |
| 1356 | { |
| 1357 | return execute() || sp_result_field->get_date(ltime, fuzzydate); |
| 1358 | } |
| 1359 | inline Field *get_sp_result_field() |
| 1360 | { |
| 1361 | return sp_result_field; |
| 1362 | } |
| 1363 | Item *get_copy(THD *thd) |
| 1364 | { return get_item_copy<Item_sum_sp>(thd, this); } |
| 1365 | Item *copy_or_same(THD *thd); |
| 1366 | }; |
| 1367 | |
| 1368 | /* Items to get the value of a stored sum function */ |
| 1369 | |
| 1370 | class Item_sum_field :public Item |
| 1371 | { |
| 1372 | protected: |
| 1373 | Field *field; |
| 1374 | public: |
| 1375 | Item_sum_field(THD *thd, Item_sum *item) |
| 1376 | :Item(thd), field(item->result_field) |
| 1377 | { |
| 1378 | name= item->name; |
| 1379 | maybe_null= true; |
| 1380 | decimals= item->decimals; |
| 1381 | max_length= item->max_length; |
| 1382 | unsigned_flag= item->unsigned_flag; |
| 1383 | fixed= true; |
| 1384 | } |
| 1385 | table_map used_tables() const { return (table_map) 1L; } |
| 1386 | void save_in_result_field(bool no_conversions) { DBUG_ASSERT(0); } |
| 1387 | bool check_vcol_func_processor(void *arg) |
| 1388 | { |
| 1389 | return mark_unsupported_function(name.str, arg, VCOL_IMPOSSIBLE); |
| 1390 | } |
| 1391 | bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) |
| 1392 | { |
| 1393 | return type_handler()->Item_get_date(this, ltime, fuzzydate); |
| 1394 | } |
| 1395 | }; |
| 1396 | |
| 1397 | |
| 1398 | class Item_avg_field :public Item_sum_field |
| 1399 | { |
| 1400 | protected: |
| 1401 | uint prec_increment; |
| 1402 | public: |
| 1403 | Item_avg_field(THD *thd, Item_sum_avg *item) |
| 1404 | :Item_sum_field(thd, item), prec_increment(item->prec_increment) |
| 1405 | { } |
| 1406 | enum Type type() const { return FIELD_AVG_ITEM; } |
| 1407 | bool is_null() { update_null_value(); return null_value; } |
| 1408 | }; |
| 1409 | |
| 1410 | |
| 1411 | class Item_avg_field_double :public Item_avg_field |
| 1412 | { |
| 1413 | public: |
| 1414 | Item_avg_field_double(THD *thd, Item_sum_avg *item) |
| 1415 | :Item_avg_field(thd, item) |
| 1416 | { } |
| 1417 | const Type_handler *type_handler() const { return &type_handler_double; } |
| 1418 | longlong val_int() { return val_int_from_real(); } |
| 1419 | my_decimal *val_decimal(my_decimal *dec) { return val_decimal_from_real(dec); } |
| 1420 | String *val_str(String *str) { return val_string_from_real(str); } |
| 1421 | double val_real(); |
| 1422 | Item *get_copy(THD *thd) |
| 1423 | { return get_item_copy<Item_avg_field_double>(thd, this); } |
| 1424 | }; |
| 1425 | |
| 1426 | |
| 1427 | class Item_avg_field_decimal :public Item_avg_field |
| 1428 | { |
| 1429 | uint f_precision, f_scale, dec_bin_size; |
| 1430 | public: |
| 1431 | Item_avg_field_decimal(THD *thd, Item_sum_avg *item) |
| 1432 | :Item_avg_field(thd, item), |
| 1433 | f_precision(item->f_precision), |
| 1434 | f_scale(item->f_scale), |
| 1435 | dec_bin_size(item->dec_bin_size) |
| 1436 | { } |
| 1437 | const Type_handler *type_handler() const { return &type_handler_newdecimal; } |
| 1438 | double val_real() { return val_real_from_decimal(); } |
| 1439 | longlong val_int() { return val_int_from_decimal(); } |
| 1440 | String *val_str(String *str) { return val_string_from_decimal(str); } |
| 1441 | my_decimal *val_decimal(my_decimal *); |
| 1442 | Item *get_copy(THD *thd) |
| 1443 | { return get_item_copy<Item_avg_field_decimal>(thd, this); } |
| 1444 | }; |
| 1445 | |
| 1446 | |
| 1447 | class Item_variance_field :public Item_sum_field |
| 1448 | { |
| 1449 | uint sample; |
| 1450 | public: |
| 1451 | Item_variance_field(THD *thd, Item_sum_variance *item) |
| 1452 | :Item_sum_field(thd, item), sample(item->sample) |
| 1453 | { } |
| 1454 | enum Type type() const {return FIELD_VARIANCE_ITEM; } |
| 1455 | double val_real(); |
| 1456 | longlong val_int() { return val_int_from_real(); } |
| 1457 | String *val_str(String *str) |
| 1458 | { return val_string_from_real(str); } |
| 1459 | my_decimal *val_decimal(my_decimal *dec_buf) |
| 1460 | { return val_decimal_from_real(dec_buf); } |
| 1461 | bool is_null() { update_null_value(); return null_value; } |
| 1462 | const Type_handler *type_handler() const { return &type_handler_double; } |
| 1463 | Item *get_copy(THD *thd) |
| 1464 | { return get_item_copy<Item_variance_field>(thd, this); } |
| 1465 | }; |
| 1466 | |
| 1467 | |
| 1468 | class Item_std_field :public Item_variance_field |
| 1469 | { |
| 1470 | public: |
| 1471 | Item_std_field(THD *thd, Item_sum_std *item) |
| 1472 | :Item_variance_field(thd, item) |
| 1473 | { } |
| 1474 | enum Type type() const { return FIELD_STD_ITEM; } |
| 1475 | double val_real(); |
| 1476 | Item *get_copy(THD *thd) |
| 1477 | { return get_item_copy<Item_std_field>(thd, this); } |
| 1478 | }; |
| 1479 | |
| 1480 | |
| 1481 | /* |
| 1482 | User defined aggregates |
| 1483 | */ |
| 1484 | |
| 1485 | #ifdef HAVE_DLOPEN |
| 1486 | |
| 1487 | class Item_udf_sum : public Item_sum |
| 1488 | { |
| 1489 | protected: |
| 1490 | udf_handler udf; |
| 1491 | |
| 1492 | public: |
| 1493 | Item_udf_sum(THD *thd, udf_func *udf_arg): |
| 1494 | Item_sum(thd), udf(udf_arg) |
| 1495 | { quick_group=0; } |
| 1496 | Item_udf_sum(THD *thd, udf_func *udf_arg, List<Item> &list): |
| 1497 | Item_sum(thd, list), udf(udf_arg) |
| 1498 | { quick_group=0;} |
| 1499 | Item_udf_sum(THD *thd, Item_udf_sum *item) |
| 1500 | :Item_sum(thd, item), udf(item->udf) |
| 1501 | { udf.not_original= TRUE; } |
| 1502 | const char *func_name() const { return udf.name(); } |
| 1503 | bool fix_fields(THD *thd, Item **ref) |
| 1504 | { |
| 1505 | DBUG_ASSERT(fixed == 0); |
| 1506 | |
| 1507 | if (init_sum_func_check(thd)) |
| 1508 | return TRUE; |
| 1509 | |
| 1510 | fixed= 1; |
| 1511 | /* |
| 1512 | We set const_item_cache to false in constructors. |
| 1513 | It can be later changed to "true", in a Item_sum::make_const() call. |
| 1514 | No make_const() calls should have happened so far. |
| 1515 | */ |
| 1516 | DBUG_ASSERT(!const_item_cache); |
| 1517 | if (udf.fix_fields(thd, this, this->arg_count, this->args)) |
| 1518 | return TRUE; |
| 1519 | /** |
| 1520 | The above call for udf.fix_fields() updates |
| 1521 | the Used_tables_and_const_cache part of "this" as if it was a regular |
| 1522 | non-aggregate UDF function and can change both const_item_cache and |
| 1523 | used_tables_cache members. |
| 1524 | - The used_tables_cache will be re-calculated in update_used_tables() |
| 1525 | which is called from check_sum_func() below. So we don't care about |
| 1526 | its current value. |
| 1527 | - The const_item_cache must stay "false" until a Item_sum::make_const() |
| 1528 | call happens, if ever. So we need to reset const_item_cache back to |
| 1529 | "false" here. |
| 1530 | */ |
| 1531 | const_item_cache= false; |
| 1532 | memcpy (orig_args, args, sizeof (Item *) * arg_count); |
| 1533 | return check_sum_func(thd, ref); |
| 1534 | } |
| 1535 | enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } |
| 1536 | virtual bool have_field_update(void) const { return 0; } |
| 1537 | |
| 1538 | void clear(); |
| 1539 | bool add(); |
| 1540 | void reset_field() {}; |
| 1541 | void update_field() {}; |
| 1542 | void cleanup(); |
| 1543 | virtual void print(String *str, enum_query_type query_type); |
| 1544 | bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) |
| 1545 | { |
| 1546 | return type_handler()->Item_get_date(this, ltime, fuzzydate); |
| 1547 | } |
| 1548 | }; |
| 1549 | |
| 1550 | |
| 1551 | class Item_sum_udf_float :public Item_udf_sum |
| 1552 | { |
| 1553 | public: |
| 1554 | Item_sum_udf_float(THD *thd, udf_func *udf_arg): |
| 1555 | Item_udf_sum(thd, udf_arg) {} |
| 1556 | Item_sum_udf_float(THD *thd, udf_func *udf_arg, List<Item> &list): |
| 1557 | Item_udf_sum(thd, udf_arg, list) {} |
| 1558 | Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) |
| 1559 | :Item_udf_sum(thd, item) {} |
| 1560 | longlong val_int() { return val_int_from_real(); } |
| 1561 | double val_real(); |
| 1562 | String *val_str(String*str); |
| 1563 | my_decimal *val_decimal(my_decimal *); |
| 1564 | const Type_handler *type_handler() const { return &type_handler_double; } |
| 1565 | void fix_length_and_dec() { fix_num_length_and_dec(); } |
| 1566 | Item *copy_or_same(THD* thd); |
| 1567 | Item *get_copy(THD *thd) |
| 1568 | { return get_item_copy<Item_sum_udf_float>(thd, this); } |
| 1569 | }; |
| 1570 | |
| 1571 | |
| 1572 | class Item_sum_udf_int :public Item_udf_sum |
| 1573 | { |
| 1574 | public: |
| 1575 | Item_sum_udf_int(THD *thd, udf_func *udf_arg): |
| 1576 | Item_udf_sum(thd, udf_arg) {} |
| 1577 | Item_sum_udf_int(THD *thd, udf_func *udf_arg, List<Item> &list): |
| 1578 | Item_udf_sum(thd, udf_arg, list) {} |
| 1579 | Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) |
| 1580 | :Item_udf_sum(thd, item) {} |
| 1581 | longlong val_int(); |
| 1582 | double val_real() |
| 1583 | { DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::val_int(); } |
| 1584 | String *val_str(String*str); |
| 1585 | my_decimal *val_decimal(my_decimal *); |
| 1586 | const Type_handler *type_handler() const { return &type_handler_longlong; } |
| 1587 | void fix_length_and_dec() { decimals=0; max_length=21; } |
| 1588 | Item *copy_or_same(THD* thd); |
| 1589 | Item *get_copy(THD *thd) |
| 1590 | { return get_item_copy<Item_sum_udf_int>(thd, this); } |
| 1591 | }; |
| 1592 | |
| 1593 | |
| 1594 | class Item_sum_udf_str :public Item_udf_sum |
| 1595 | { |
| 1596 | public: |
| 1597 | Item_sum_udf_str(THD *thd, udf_func *udf_arg): |
| 1598 | Item_udf_sum(thd, udf_arg) {} |
| 1599 | Item_sum_udf_str(THD *thd, udf_func *udf_arg, List<Item> &list): |
| 1600 | Item_udf_sum(thd, udf_arg, list) {} |
| 1601 | Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) |
| 1602 | :Item_udf_sum(thd, item) {} |
| 1603 | String *val_str(String *); |
| 1604 | double val_real() |
| 1605 | { |
| 1606 | int err_not_used; |
| 1607 | char *end_not_used; |
| 1608 | String *res; |
| 1609 | res=val_str(&str_value); |
| 1610 | return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(), |
| 1611 | &end_not_used, &err_not_used) : 0.0; |
| 1612 | } |
| 1613 | longlong val_int() |
| 1614 | { |
| 1615 | int err_not_used; |
| 1616 | char *end; |
| 1617 | String *res; |
| 1618 | CHARSET_INFO *cs; |
| 1619 | |
| 1620 | if (!(res= val_str(&str_value))) |
| 1621 | return 0; /* Null value */ |
| 1622 | cs= res->charset(); |
| 1623 | end= (char*) res->ptr()+res->length(); |
| 1624 | return cs->cset->strtoll10(cs, res->ptr(), &end, &err_not_used); |
| 1625 | } |
| 1626 | my_decimal *val_decimal(my_decimal *dec); |
| 1627 | const Type_handler *type_handler() const { return string_type_handler(); } |
| 1628 | void fix_length_and_dec(); |
| 1629 | Item *copy_or_same(THD* thd); |
| 1630 | Item *get_copy(THD *thd) |
| 1631 | { return get_item_copy<Item_sum_udf_str>(thd, this); } |
| 1632 | }; |
| 1633 | |
| 1634 | |
| 1635 | class Item_sum_udf_decimal :public Item_udf_sum |
| 1636 | { |
| 1637 | public: |
| 1638 | Item_sum_udf_decimal(THD *thd, udf_func *udf_arg): |
| 1639 | Item_udf_sum(thd, udf_arg) {} |
| 1640 | Item_sum_udf_decimal(THD *thd, udf_func *udf_arg, List<Item> &list): |
| 1641 | Item_udf_sum(thd, udf_arg, list) {} |
| 1642 | Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item) |
| 1643 | :Item_udf_sum(thd, item) {} |
| 1644 | String *val_str(String *); |
| 1645 | double val_real(); |
| 1646 | longlong val_int(); |
| 1647 | my_decimal *val_decimal(my_decimal *); |
| 1648 | const Type_handler *type_handler() const { return &type_handler_newdecimal; } |
| 1649 | void fix_length_and_dec() { fix_num_length_and_dec(); } |
| 1650 | Item *copy_or_same(THD* thd); |
| 1651 | Item *get_copy(THD *thd) |
| 1652 | { return get_item_copy<Item_sum_udf_decimal>(thd, this); } |
| 1653 | }; |
| 1654 | |
| 1655 | #else /* Dummy functions to get sql_yacc.cc compiled */ |
| 1656 | |
| 1657 | class Item_sum_udf_float :public Item_sum_num |
| 1658 | { |
| 1659 | public: |
| 1660 | Item_sum_udf_float(THD *thd, udf_func *udf_arg): |
| 1661 | Item_sum_num(thd) {} |
| 1662 | Item_sum_udf_float(THD *thd, udf_func *udf_arg, List<Item> &list): |
| 1663 | Item_sum_num(thd) {} |
| 1664 | Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) |
| 1665 | :Item_sum_num(thd, item) {} |
| 1666 | enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } |
| 1667 | double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; } |
| 1668 | void clear() {} |
| 1669 | bool add() { return 0; } |
| 1670 | void update_field() {} |
| 1671 | }; |
| 1672 | |
| 1673 | |
| 1674 | class Item_sum_udf_int :public Item_sum_num |
| 1675 | { |
| 1676 | public: |
| 1677 | Item_sum_udf_int(THD *thd, udf_func *udf_arg): |
| 1678 | Item_sum_num(thd) {} |
| 1679 | Item_sum_udf_int(THD *thd, udf_func *udf_arg, List<Item> &list): |
| 1680 | Item_sum_num(thd) {} |
| 1681 | Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) |
| 1682 | :Item_sum_num(thd, item) {} |
| 1683 | enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } |
| 1684 | longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; } |
| 1685 | double val_real() { DBUG_ASSERT(fixed == 1); return 0; } |
| 1686 | void clear() {} |
| 1687 | bool add() { return 0; } |
| 1688 | void update_field() {} |
| 1689 | }; |
| 1690 | |
| 1691 | |
| 1692 | class Item_sum_udf_decimal :public Item_sum_num |
| 1693 | { |
| 1694 | public: |
| 1695 | Item_sum_udf_decimal(THD *thd, udf_func *udf_arg): |
| 1696 | Item_sum_num(thd) {} |
| 1697 | Item_sum_udf_decimal(THD *thd, udf_func *udf_arg, List<Item> &list): |
| 1698 | Item_sum_num(thd) {} |
| 1699 | Item_sum_udf_decimal(THD *thd, Item_sum_udf_float *item) |
| 1700 | :Item_sum_num(thd, item) {} |
| 1701 | enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } |
| 1702 | double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; } |
| 1703 | my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; } |
| 1704 | void clear() {} |
| 1705 | bool add() { return 0; } |
| 1706 | void update_field() {} |
| 1707 | }; |
| 1708 | |
| 1709 | |
| 1710 | class Item_sum_udf_str :public Item_sum_num |
| 1711 | { |
| 1712 | public: |
| 1713 | Item_sum_udf_str(THD *thd, udf_func *udf_arg): |
| 1714 | Item_sum_num(thd) {} |
| 1715 | Item_sum_udf_str(THD *thd, udf_func *udf_arg, List<Item> &list): |
| 1716 | Item_sum_num(thd) {} |
| 1717 | Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) |
| 1718 | :Item_sum_num(thd, item) {} |
| 1719 | String *val_str(String *) |
| 1720 | { DBUG_ASSERT(fixed == 1); null_value=1; return 0; } |
| 1721 | double val_real() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; } |
| 1722 | longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; } |
| 1723 | void fix_length_and_dec() { maybe_null=1; max_length=0; } |
| 1724 | enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } |
| 1725 | void clear() {} |
| 1726 | bool add() { return 0; } |
| 1727 | void update_field() {} |
| 1728 | }; |
| 1729 | |
| 1730 | #endif /* HAVE_DLOPEN */ |
| 1731 | |
| 1732 | C_MODE_START |
| 1733 | int group_concat_key_cmp_with_distinct(void* arg, const void* key1, |
| 1734 | const void* key2); |
| 1735 | int group_concat_key_cmp_with_order(void* arg, const void* key1, |
| 1736 | const void* key2); |
| 1737 | int dump_leaf_key(void* key_arg, |
| 1738 | element_count count __attribute__((unused)), |
| 1739 | void* item_arg); |
| 1740 | C_MODE_END |
| 1741 | |
| 1742 | class Item_func_group_concat : public Item_sum |
| 1743 | { |
| 1744 | TMP_TABLE_PARAM *tmp_table_param; |
| 1745 | String result; |
| 1746 | String *separator; |
| 1747 | TREE tree_base; |
| 1748 | TREE *tree; |
| 1749 | Item **ref_pointer_array; |
| 1750 | |
| 1751 | /** |
| 1752 | If DISTINCT is used with this GROUP_CONCAT, this member is used to filter |
| 1753 | out duplicates. |
| 1754 | @see Item_func_group_concat::setup |
| 1755 | @see Item_func_group_concat::add |
| 1756 | @see Item_func_group_concat::clear |
| 1757 | */ |
| 1758 | Unique *unique_filter; |
| 1759 | TABLE *table; |
| 1760 | ORDER **order; |
| 1761 | Name_resolution_context *context; |
| 1762 | /** The number of ORDER BY items. */ |
| 1763 | uint arg_count_order; |
| 1764 | /** The number of selected items, aka the expr list. */ |
| 1765 | uint arg_count_field; |
| 1766 | uint row_count; |
| 1767 | bool distinct; |
| 1768 | bool warning_for_row; |
| 1769 | bool always_null; |
| 1770 | bool force_copy_fields; |
| 1771 | bool no_appended; |
| 1772 | /** Limits the rows in the result */ |
| 1773 | Item *row_limit; |
| 1774 | /** Skips a particular number of rows in from the result*/ |
| 1775 | Item *offset_limit; |
| 1776 | bool limit_clause; |
| 1777 | /* copy of the offset limit */ |
| 1778 | ulonglong copy_offset_limit; |
| 1779 | /*copy of the row limit */ |
| 1780 | ulonglong copy_row_limit; |
| 1781 | |
| 1782 | /* |
| 1783 | Following is 0 normal object and pointer to original one for copy |
| 1784 | (to correctly free resources) |
| 1785 | */ |
| 1786 | Item_func_group_concat *original; |
| 1787 | |
| 1788 | friend int group_concat_key_cmp_with_distinct(void* arg, const void* key1, |
| 1789 | const void* key2); |
| 1790 | friend int group_concat_key_cmp_with_order(void* arg, const void* key1, |
| 1791 | const void* key2); |
| 1792 | friend int dump_leaf_key(void* key_arg, |
| 1793 | element_count count __attribute__((unused)), |
| 1794 | void* item_arg); |
| 1795 | public: |
| 1796 | Item_func_group_concat(THD *thd, Name_resolution_context *context_arg, |
| 1797 | bool is_distinct, List<Item> *is_select, |
| 1798 | const SQL_I_List<ORDER> &is_order, String *is_separator, |
| 1799 | bool limit_clause, Item *row_limit, Item *offset_limit); |
| 1800 | |
| 1801 | Item_func_group_concat(THD *thd, Item_func_group_concat *item); |
| 1802 | ~Item_func_group_concat(); |
| 1803 | void cleanup(); |
| 1804 | |
| 1805 | enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} |
| 1806 | const char *func_name() const { return "group_concat(" ; } |
| 1807 | const Type_handler *type_handler() const |
| 1808 | { |
| 1809 | if (too_big_for_varchar()) |
| 1810 | return &type_handler_blob; |
| 1811 | return &type_handler_varchar; |
| 1812 | } |
| 1813 | void clear(); |
| 1814 | bool add(); |
| 1815 | void reset_field() { DBUG_ASSERT(0); } // not used |
| 1816 | void update_field() { DBUG_ASSERT(0); } // not used |
| 1817 | bool fix_fields(THD *,Item **); |
| 1818 | bool setup(THD *thd); |
| 1819 | void make_unique(); |
| 1820 | double val_real() |
| 1821 | { |
| 1822 | int error; |
| 1823 | const char *end; |
| 1824 | String *res; |
| 1825 | if (!(res= val_str(&str_value))) |
| 1826 | return 0.0; |
| 1827 | end= res->ptr() + res->length(); |
| 1828 | return (my_strtod(res->ptr(), (char**) &end, &error)); |
| 1829 | } |
| 1830 | longlong val_int() |
| 1831 | { |
| 1832 | String *res; |
| 1833 | char *end_ptr; |
| 1834 | int error; |
| 1835 | if (!(res= val_str(&str_value))) |
| 1836 | return (longlong) 0; |
| 1837 | end_ptr= (char*) res->ptr()+ res->length(); |
| 1838 | return my_strtoll10(res->ptr(), &end_ptr, &error); |
| 1839 | } |
| 1840 | my_decimal *val_decimal(my_decimal *decimal_value) |
| 1841 | { |
| 1842 | return val_decimal_from_string(decimal_value); |
| 1843 | } |
| 1844 | bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) |
| 1845 | { |
| 1846 | return get_date_from_string(ltime, fuzzydate); |
| 1847 | } |
| 1848 | String* val_str(String* str); |
| 1849 | Item *copy_or_same(THD* thd); |
| 1850 | void no_rows_in_result() {} |
| 1851 | virtual void print(String *str, enum_query_type query_type); |
| 1852 | virtual bool change_context_processor(void *cntx) |
| 1853 | { context= (Name_resolution_context *)cntx; return FALSE; } |
| 1854 | Item *get_copy(THD *thd) |
| 1855 | { return get_item_copy<Item_func_group_concat>(thd, this); } |
| 1856 | }; |
| 1857 | |
| 1858 | #endif /* ITEM_SUM_INCLUDED */ |
| 1859 | |