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 02110-1335 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 
execute(JOIN * join)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       handler->end_scan();
69       DBUG_RETURN(-1);
70     }
71 
72     /* Check if we can accept the row */
73     if (!having || having->val_bool())
74     {
75       if (store_data_in_temp_table)
76       {
77         if ((err= table->file->ha_write_tmp_row(table->record[0])))
78         {
79           bool is_duplicate;
80           if (likely(!table->file->is_fatal_error(err, HA_CHECK_DUP)))
81             continue;                           // Distinct elimination
82 
83           if (create_internal_tmp_table_from_heap(thd, table,
84                                                   join->tmp_table_param.
85                                                   start_recinfo,
86                                                   &join->tmp_table_param.
87                                                   recinfo,
88                                                   err, 1, &is_duplicate))
89             DBUG_RETURN(1);
90           if (is_duplicate)
91             continue;
92         }
93       }
94       else
95       {
96         if (join->do_send_rows)
97         {
98           int error;
99           /* result < 0 if row was not accepted and should not be counted */
100           if (unlikely((error= join->result->send_data(*join->fields))))
101           {
102             handler->end_scan();
103             DBUG_RETURN(error < 0 ? 0 : -1);
104           }
105         }
106       }
107 
108       /* limit handling */
109       if (++join->send_records >= max_limit && join->do_send_rows)
110       {
111         if (!(join->select_options & OPTION_FOUND_ROWS))
112           break;                              // LIMIT reached
113         join->do_send_rows= 0;                // Calculate FOUND_ROWS()
114         if (reset_limit)
115           *reset_limit= HA_POS_ERROR;
116         if (reset_item)
117           *reset_item= 0;
118       }
119     }
120   }
121   if (err != 0 && err != HA_ERR_END_OF_FILE)
122     goto error;
123 
124   if ((err= handler->end_scan()))
125     goto error_2;
126   if (!store_data_in_temp_table && join->result->send_eof())
127     DBUG_RETURN(1);                              // Don't send error to client
128 
129   DBUG_RETURN(0);
130 
131 error:
132   handler->end_scan();
133 error_2:
134   handler->print_error(err, MYF(0));
135   DBUG_RETURN(-1);                              // Error not sent to client
136 }
137 
138 
print_error(int error,myf errflag)139 void group_by_handler::print_error(int error, myf errflag)
140 {
141   my_error(ER_GET_ERRNO, MYF(0), error, hton_name(ht)->str);
142 }
143