1 | /* |
2 | Copyright (c) 2014, 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ |
16 | |
17 | /* |
18 | This file implements the group_by_handler code. 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 | |
24 | #include "mariadb.h" |
25 | #include "sql_priv.h" |
26 | #include "sql_select.h" |
27 | |
28 | /* |
29 | Same return values as do_select(); |
30 | |
31 | @retval |
32 | 0 if ok |
33 | @retval |
34 | 1 if error is sent |
35 | @retval |
36 | -1 if error should be sent |
37 | */ |
38 | |
39 | int Pushdown_query::execute(JOIN *join) |
40 | { |
41 | int err; |
42 | ha_rows max_limit; |
43 | ha_rows *reset_limit= 0; |
44 | Item **reset_item= 0; |
45 | THD *thd= handler->thd; |
46 | TABLE *table= handler->table; |
47 | DBUG_ENTER("Pushdown_query::execute" ); |
48 | |
49 | if ((err= handler->init_scan())) |
50 | goto error; |
51 | |
52 | if (store_data_in_temp_table) |
53 | { |
54 | max_limit= join->tmp_table_param.end_write_records; |
55 | reset_limit= &join->unit->select_limit_cnt; |
56 | } |
57 | else |
58 | { |
59 | max_limit= join->unit->select_limit_cnt; |
60 | if (join->unit->fake_select_lex) |
61 | reset_item= &join->unit->fake_select_lex->select_limit; |
62 | } |
63 | |
64 | while (!(err= handler->next_row())) |
65 | { |
66 | if (unlikely(thd->check_killed())) |
67 | { |
68 | thd->send_kill_message(); |
69 | handler->end_scan(); |
70 | DBUG_RETURN(-1); |
71 | } |
72 | |
73 | /* Check if we can accept the row */ |
74 | if (!having || having->val_bool()) |
75 | { |
76 | if (store_data_in_temp_table) |
77 | { |
78 | if ((err= table->file->ha_write_tmp_row(table->record[0]))) |
79 | { |
80 | bool is_duplicate; |
81 | if (likely(!table->file->is_fatal_error(err, HA_CHECK_DUP))) |
82 | continue; // Distinct elimination |
83 | |
84 | if (create_internal_tmp_table_from_heap(thd, table, |
85 | join->tmp_table_param. |
86 | start_recinfo, |
87 | &join->tmp_table_param. |
88 | recinfo, |
89 | err, 1, &is_duplicate)) |
90 | DBUG_RETURN(1); |
91 | if (is_duplicate) |
92 | continue; |
93 | } |
94 | } |
95 | else |
96 | { |
97 | if (join->do_send_rows) |
98 | { |
99 | int error; |
100 | /* result < 0 if row was not accepted and should not be counted */ |
101 | if (unlikely((error= join->result->send_data(*join->fields)))) |
102 | { |
103 | handler->end_scan(); |
104 | DBUG_RETURN(error < 0 ? 0 : -1); |
105 | } |
106 | } |
107 | } |
108 | |
109 | /* limit handling */ |
110 | if (++join->send_records >= max_limit && join->do_send_rows) |
111 | { |
112 | if (!(join->select_options & OPTION_FOUND_ROWS)) |
113 | break; // LIMIT reached |
114 | join->do_send_rows= 0; // Calculate FOUND_ROWS() |
115 | if (reset_limit) |
116 | *reset_limit= HA_POS_ERROR; |
117 | if (reset_item) |
118 | *reset_item= 0; |
119 | } |
120 | } |
121 | } |
122 | if (err != 0 && err != HA_ERR_END_OF_FILE) |
123 | goto error; |
124 | |
125 | if ((err= handler->end_scan())) |
126 | goto error_2; |
127 | if (!store_data_in_temp_table && join->result->send_eof()) |
128 | DBUG_RETURN(1); // Don't send error to client |
129 | |
130 | DBUG_RETURN(0); |
131 | |
132 | error: |
133 | handler->end_scan(); |
134 | error_2: |
135 | handler->print_error(err, MYF(0)); |
136 | DBUG_RETURN(-1); // Error not sent to client |
137 | } |
138 | |
139 | |
140 | void group_by_handler::print_error(int error, myf errflag) |
141 | { |
142 | my_error(ER_GET_ERRNO, MYF(0), error, hton_name(ht)->str); |
143 | } |
144 | |