1 /* Copyright (c) 2002, 2021, Oracle and/or its affiliates.
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 "item_row.h"
24 
25 #include "sql_class.h"  // THD
26 
Item_row(const POS & pos,Item * head,List<Item> & tail)27 Item_row::Item_row(const POS &pos, Item *head, List<Item> &tail):
28   super(pos), used_tables_cache(0), not_null_tables_cache(0),
29   const_item_cache(1), with_null(0)
30 {
31 
32   //TODO: think placing 2-3 component items in item (as it done for function)
33   arg_count= 1 + tail.elements;
34   items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
35   if (items == NULL)
36   {
37     arg_count= 0;
38     return; // OOM
39   }
40   items[0]= head;
41   List_iterator<Item> li(tail);
42   uint i= 1;
43   Item *item;
44   while ((item= li++))
45   {
46     items[i]= item;
47     i++;
48   }
49 }
50 
Item_row(Item * head,List<Item> & tail)51 Item_row::Item_row(Item *head, List<Item> &tail):
52   used_tables_cache(0), not_null_tables_cache(0),
53   const_item_cache(1), with_null(0)
54 {
55 
56   //TODO: think placing 2-3 component items in item (as it done for function)
57   arg_count= 1 + tail.elements;
58   items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
59   if (items == NULL)
60   {
61     arg_count= 0;
62     return; // OOM
63   }
64   items[0]= head;
65   List_iterator<Item> li(tail);
66   uint i= 1;
67   Item *item;
68   while ((item= li++))
69   {
70     items[i]= item;
71     i++;
72   }
73 }
74 
itemize(Parse_context * pc,Item ** res)75 bool Item_row::itemize(Parse_context *pc, Item **res)
76 {
77   if (skip_itemize(res))
78     return false;
79   if (super::itemize(pc, res))
80     return true;
81   for (uint i= 0; i < arg_count; i++)
82   {
83     if (items[i]->itemize(pc, &items[i]))
84       return true;
85   }
86   return false;
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   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   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,enum_walk walk,uchar * arg)211 bool Item_row::walk(Item_processor processor, enum_walk walk, uchar *arg)
212 {
213   if ((walk & WALK_PREFIX) && (this->*processor)(arg))
214     return true;
215 
216   for (uint i= 0; i < arg_count; i++)
217   {
218     if (items[i]->walk(processor, walk, arg))
219       return true;
220   }
221   return (walk & WALK_POSTFIX) && (this->*processor)(arg);
222 }
223 
224 
transform(Item_transformer transformer,uchar * arg)225 Item *Item_row::transform(Item_transformer transformer, uchar *arg)
226 {
227   assert(!current_thd->stmt_arena->is_stmt_prepare());
228 
229   for (uint i= 0; i < arg_count; i++)
230   {
231     Item *new_item= items[i]->transform(transformer, arg);
232     if (!new_item)
233       return 0;
234 
235     /*
236       THD::change_item_tree() should be called only if the tree was
237       really transformed, i.e. when a new item has been created.
238       Otherwise we'll be allocating a lot of unnecessary memory for
239       change records at each execution.
240     */
241     if (items[i] != new_item)
242       current_thd->change_item_tree(&items[i], new_item);
243   }
244   return (this->*transformer)(arg);
245 }
246 
bring_value()247 void Item_row::bring_value()
248 {
249   for (uint i= 0; i < arg_count; i++)
250     items[i]->bring_value();
251 }
252