1 /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software Foundation,
21    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22 
23 #include "sql_priv.h"
24 /*
25   It is necessary to include set_var.h instead of item.h because there
26   are dependencies on include order for set_var.h and item.h. This
27   will be resolved later.
28 */
29 #include "sql_class.h"                          // THD, set_var.h: THD
30 #include "set_var.h"
31 
32 /**
33   Row items used for comparing rows and IN operations on rows:
34 
35   @verbatim
36   (a, b, c) > (10, 10, 30)
37   (a, b, c) = (select c, d, e, from t1 where x=12)
38   (a, b, c) IN ((1,2,2), (3,4,5), (6,7,8)
39   (a, b, c) IN (select c, d, e, from t1)
40   @endverbatim
41 
42   @todo
43     think placing 2-3 component items in item (as it done for function
44 */
45 
Item_row(List<Item> & arg)46 Item_row::Item_row(List<Item> &arg):
47   Item(), used_tables_cache(0), not_null_tables_cache(0),
48   const_item_cache(1), with_null(0)
49 {
50 
51   //TODO: think placing 2-3 component items in item (as it done for function)
52   if ((arg_count= arg.elements))
53     items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
54   else
55     items= 0;
56   List_iterator<Item> li(arg);
57   uint i= 0;
58   Item *item;
59   while ((item= li++))
60   {
61     items[i]= item;
62     i++;
63   }
64 }
65 
Item_row(Item * head,List<Item> & tail)66 Item_row::Item_row(Item *head, List<Item> &tail):
67   used_tables_cache(0), not_null_tables_cache(0),
68   const_item_cache(1), with_null(0)
69 {
70 
71   //TODO: think placing 2-3 component items in item (as it done for function)
72   arg_count= 1 + tail.elements;
73   items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
74   if (items == NULL)
75   {
76     arg_count= 0;
77     return; // OOM
78   }
79   items[0]= head;
80   List_iterator<Item> li(tail);
81   uint i= 1;
82   Item *item;
83   while ((item= li++))
84   {
85     items[i]= item;
86     i++;
87   }
88 }
89 
illegal_method_call(const char * method)90 void Item_row::illegal_method_call(const char *method)
91 {
92   DBUG_ENTER("Item_row::illegal_method_call");
93   DBUG_PRINT("error", ("!!! %s method was called for row item", method));
94   DBUG_ASSERT(0);
95   my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
96   DBUG_VOID_RETURN;
97 }
98 
fix_fields(THD * thd,Item ** ref)99 bool Item_row::fix_fields(THD *thd, Item **ref)
100 {
101   DBUG_ASSERT(fixed == 0);
102   null_value= 0;
103   maybe_null= 0;
104   Item **arg, **arg_end;
105   for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
106   {
107     if (!(*arg)->fixed && (*arg)->fix_fields(thd, arg))
108       return TRUE;
109     // we can't assign 'item' before, because fix_fields() can change arg
110     Item *item= *arg;
111     used_tables_cache |= item->used_tables();
112     const_item_cache&= item->const_item() && !with_null;
113     not_null_tables_cache|= item->not_null_tables();
114 
115     if (const_item_cache)
116     {
117       if (item->cols() > 1)
118 	with_null|= item->null_inside();
119       else
120       {
121 	if (item->is_null())
122           with_null|= 1;
123       }
124     }
125     maybe_null|= item->maybe_null;
126     with_sum_func|= item->with_sum_func;
127     with_subselect|= item->has_subquery();
128   }
129   fixed= 1;
130   return FALSE;
131 }
132 
133 
cleanup()134 void Item_row::cleanup()
135 {
136   DBUG_ENTER("Item_row::cleanup");
137 
138   Item::cleanup();
139   /* Reset to the original values */
140   used_tables_cache= 0;
141   const_item_cache= 1;
142   with_null= 0;
143 
144   DBUG_VOID_RETURN;
145 }
146 
147 
split_sum_func(THD * thd,Ref_ptr_array ref_pointer_array,List<Item> & fields)148 void Item_row::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
149                               List<Item> &fields)
150 {
151   Item **arg, **arg_end;
152   for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
153     (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE);
154 }
155 
156 
update_used_tables()157 void Item_row::update_used_tables()
158 {
159   used_tables_cache= 0;
160   const_item_cache= true;
161   with_subselect= false;
162   with_stored_program= false;
163   for (uint i= 0; i < arg_count; i++)
164   {
165     items[i]->update_used_tables();
166     used_tables_cache|= items[i]->used_tables();
167     const_item_cache&= items[i]->const_item();
168     with_subselect|= items[i]->has_subquery();
169     with_stored_program|= items[i]->has_stored_program();
170   }
171 }
172 
fix_after_pullout(st_select_lex * parent_select,st_select_lex * removed_select)173 void Item_row::fix_after_pullout(st_select_lex *parent_select,
174                                  st_select_lex *removed_select)
175 {
176   used_tables_cache= 0;
177   not_null_tables_cache= 0;
178   const_item_cache= true;
179   for (uint i= 0; i < arg_count; i++)
180   {
181     items[i]->fix_after_pullout(parent_select, removed_select);
182     used_tables_cache|= items[i]->used_tables();
183     not_null_tables_cache|= items[i]->not_null_tables();
184     const_item_cache&= items[i]->const_item();
185   }
186 }
187 
check_cols(uint c)188 bool Item_row::check_cols(uint c)
189 {
190   if (c != arg_count)
191   {
192     my_error(ER_OPERAND_COLUMNS, MYF(0), c);
193     return 1;
194   }
195   return 0;
196 }
197 
print(String * str,enum_query_type query_type)198 void Item_row::print(String *str, enum_query_type query_type)
199 {
200   str->append('(');
201   for (uint i= 0; i < arg_count; i++)
202   {
203     if (i)
204       str->append(',');
205     items[i]->print(str, query_type);
206   }
207   str->append(')');
208 }
209 
210 
walk(Item_processor processor,bool walk_subquery,uchar * arg)211 bool Item_row::walk(Item_processor processor, bool walk_subquery, uchar *arg)
212 {
213   for (uint i= 0; i < arg_count; i++)
214   {
215     if (items[i]->walk(processor, walk_subquery, arg))
216       return 1;
217   }
218   return (this->*processor)(arg);
219 }
220 
221 
transform(Item_transformer transformer,uchar * arg)222 Item *Item_row::transform(Item_transformer transformer, uchar *arg)
223 {
224   DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
225 
226   for (uint i= 0; i < arg_count; i++)
227   {
228     Item *new_item= items[i]->transform(transformer, arg);
229     if (!new_item)
230       return 0;
231 
232     /*
233       THD::change_item_tree() should be called only if the tree was
234       really transformed, i.e. when a new item has been created.
235       Otherwise we'll be allocating a lot of unnecessary memory for
236       change records at each execution.
237     */
238     if (items[i] != new_item)
239       current_thd->change_item_tree(&items[i], new_item);
240   }
241   return (this->*transformer)(arg);
242 }
243 
bring_value()244 void Item_row::bring_value()
245 {
246   for (uint i= 0; i < arg_count; i++)
247     items[i]->bring_value();
248 }
249