|
| 1 | +/* |
| 2 | + Copyright (c) 2014, SkySQL Ab & MariaDB Foundation |
| 3 | +
|
| 4 | + This program is free software; you can redistribute it and/or modify |
| 5 | + it under the terms of the GNU General Public License as published by |
| 6 | + the Free Software Foundation; version 2 of the License. |
| 7 | +
|
| 8 | + This program is distributed in the hope that it will be useful, |
| 9 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | + GNU General Public License for more details. |
| 12 | +
|
| 13 | + You should have received a copy of the GNU General Public License |
| 14 | + along with this program; if not, write to the Free Software |
| 15 | + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
| 16 | + |
| 17 | +/* |
| 18 | + This file implements the group_by_handler interface. This interface |
| 19 | + can be used by storage handlers that can intercept summary or GROUP |
| 20 | + BY queries from MariaDB and itself return the result to the user or |
| 21 | + upper level. |
| 22 | +
|
| 23 | + Both main and sub queries are supported. Here are some examples of what the |
| 24 | + storage engine could intersept: |
| 25 | +
|
| 26 | + SELECT count(*) FROM t1; |
| 27 | + SELECT a,count(*) FROM t1 group by a; |
| 28 | + SELECT a,count(*) as sum FROM t1 where b > 10 group by a, order by sum; |
| 29 | + SELECT a,count(*) FROM t1,t2; |
| 30 | + SELECT a, (select sum(*) from t2 where t1.a=t2.a) from t2; |
| 31 | +
|
| 32 | + See https://mariadb.atlassian.net/browse/MDEV-6080 for more information. |
| 33 | +*/ |
| 34 | + |
| 35 | +class JOIN; |
| 36 | + |
| 37 | +class group_by_handler |
| 38 | +{ |
| 39 | +public: |
| 40 | + /* Arguments for group_by_handler, for usage later */ |
| 41 | + THD *thd; |
| 42 | + SELECT_LEX *select_lex; |
| 43 | + List<Item> *fields; |
| 44 | + TABLE_LIST *table_list; |
| 45 | + ORDER *group_by, *order_by; |
| 46 | + Item *where, *having; |
| 47 | + handlerton *ht; /* storage engine of this handler */ |
| 48 | + |
| 49 | + /* |
| 50 | + Bit's of things the storage engine can do for this query. |
| 51 | + Should be initialized on object creation. |
| 52 | + */ |
| 53 | + /* Temporary table where all results should be stored in record[0] */ |
| 54 | + TABLE *table; |
| 55 | + |
| 56 | + bool store_data_in_temp_table; /* Set by mariadb */ |
| 57 | + |
| 58 | + group_by_handler(THD *thd_arg, SELECT_LEX *select_lex_arg, |
| 59 | + List<Item> *fields_arg, |
| 60 | + TABLE_LIST *table_list_arg, ORDER *group_by_arg, |
| 61 | + ORDER *order_by_arg, Item *where_arg, |
| 62 | + Item *having_arg, handlerton *ht_arg) |
| 63 | + : thd(thd_arg), select_lex(select_lex_arg), fields(fields_arg), |
| 64 | + table_list(table_list_arg), group_by(group_by_arg), |
| 65 | + order_by(order_by_arg), where(where_arg), having(having_arg), |
| 66 | + ht(ht_arg), table(0), store_data_in_temp_table(0) |
| 67 | + {} |
| 68 | + virtual ~group_by_handler() {} |
| 69 | + |
| 70 | + /* |
| 71 | + Store pointer to temporary table and objects modified to point to |
| 72 | + the temporary table. This will happen during the optimize phase. |
| 73 | +
|
| 74 | + We provide new 'having' and 'order_by' elements here. The differ from the |
| 75 | + original ones in that these are modified to point to fields in the |
| 76 | + temporary table 'table'. |
| 77 | +
|
| 78 | + Return 1 if the storage handler cannot handle the GROUP BY after all, |
| 79 | + in which case we have to give an error to the end user for the query. |
| 80 | + This is becasue we can't revert back the old having and order_by elements. |
| 81 | + */ |
| 82 | + |
| 83 | + virtual bool init(TABLE *temporary_table, Item *having_arg, |
| 84 | + ORDER *order_by_arg) |
| 85 | + { |
| 86 | + table= temporary_table; |
| 87 | + having= having_arg; |
| 88 | + order_by= order_by_arg; |
| 89 | + return 0; |
| 90 | + } |
| 91 | + |
| 92 | + /* |
| 93 | + Result data is sorted by the storage engine according to order_by (if it |
| 94 | + exists) else according to the group_by. If this is not specified, |
| 95 | + MariaDB will store the result set into the temporary table and sort the |
| 96 | + result. |
| 97 | + */ |
| 98 | + #define GROUP_BY_ORDER_BY 1 |
| 99 | + /* The storage engine can handle DISTINCT */ |
| 100 | + #define GROUP_BY_DISTINCT 2 |
| 101 | + virtual uint flags() { return 0; } |
| 102 | + |
| 103 | + /* |
| 104 | + Functions to scan data. All these returns 0 if ok, error code in case |
| 105 | + of error |
| 106 | + */ |
| 107 | + |
| 108 | + /* |
| 109 | + Initialize group_by scan, prepare for next_row(). |
| 110 | + If this is a sub query with group by, this can be called many times for |
| 111 | + a query. |
| 112 | + */ |
| 113 | + virtual int init_scan()= 0; |
| 114 | + |
| 115 | + /* |
| 116 | + Return next group by result in table->record[0]. |
| 117 | + Return 0 if row found, HA_ERR_END_OF_FILE if last row and other error |
| 118 | + number in case of fatal error. |
| 119 | + */ |
| 120 | + virtual int next_row()= 0; |
| 121 | + |
| 122 | + /* End scanning */ |
| 123 | + virtual int end_scan()=0; |
| 124 | + |
| 125 | + /* Information for optimizer (used by EXPLAIN) */ |
| 126 | + virtual int info(uint flag, ha_statistics *stats)= 0; |
| 127 | + |
| 128 | + /* Function that calls the above scan functions */ |
| 129 | + int execute(JOIN *join); |
| 130 | + |
| 131 | + /* Report errors */ |
| 132 | + virtual void print_error(int error, myf errflag); |
| 133 | +}; |
0 commit comments