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   bool reset_limit= FALSE;
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= TRUE;
56   }
57   else
58   {
59     max_limit= join->unit->lim.get_select_limit();
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=
101                         join->result->send_data_with_check(*join->fields,
102                                                           join->unit,
103                                                           join->send_records))))
104           {
105             handler->end_scan();
106             DBUG_RETURN(error < 0 ? 0 : -1);
107           }
108         }
109       }
110 
111       /* limit handling */
112       if (++join->send_records >= max_limit && join->do_send_rows)
113       {
114         if (!(join->select_options & OPTION_FOUND_ROWS))
115           break;                              // LIMIT reached
116         join->do_send_rows= 0;                // Calculate FOUND_ROWS()
117         if (reset_limit)
118           join->unit->lim.set_unlimited();
119         if (reset_item)
120           *reset_item= 0;
121       }
122     }
123   }
124   if (err != 0 && err != HA_ERR_END_OF_FILE)
125     goto error;
126 
127   if ((err= handler->end_scan()))
128     goto error_2;
129   if (!store_data_in_temp_table && join->result->send_eof())
130     DBUG_RETURN(1);                              // Don't send error to client
131 
132   DBUG_RETURN(0);
133 
134 error:
135   handler->end_scan();
136 error_2:
137   handler->print_error(err, MYF(0));
138   DBUG_RETURN(-1);                              // Error not sent to client
139 }
140 
141 
print_error(int error,myf errflag)142 void group_by_handler::print_error(int error, myf errflag)
143 {
144   my_error(ER_GET_ERRNO, MYF(0), error, hton_name(ht)->str);
145 }
146