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