~ubuntu-branches/ubuntu/trusty/mariadb-5.5/trusty-proposed

« back to all changes in this revision

Viewing changes to sql/item_row.cc

  • Committer: Package Import Robot
  • Author(s): Otto Kekäläinen
  • Date: 2013-12-22 10:27:05 UTC
  • Revision ID: package-import@ubuntu.com-20131222102705-mndw7s12mz0szrcn
Tags: upstream-5.5.32
Import upstream version 5.5.32

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright (c) 2002, 2011, Oracle and/or its affiliates.
 
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 St, Fifth Floor, Boston, MA 02110-1301  USA */
 
16
 
 
17
#include "sql_priv.h"
 
18
/*
 
19
  It is necessary to include set_var.h instead of item.h because there
 
20
  are dependencies on include order for set_var.h and item.h. This
 
21
  will be resolved later.
 
22
*/
 
23
#include "sql_class.h"                          // THD, set_var.h: THD
 
24
#include "set_var.h"
 
25
 
 
26
/**
 
27
  Row items used for comparing rows and IN operations on rows:
 
28
 
 
29
  @verbatim
 
30
  (a, b, c) > (10, 10, 30)
 
31
  (a, b, c) = (select c, d, e, from t1 where x=12)
 
32
  (a, b, c) IN ((1,2,2), (3,4,5), (6,7,8)
 
33
  (a, b, c) IN (select c, d, e, from t1)
 
34
  @endverbatim
 
35
 
 
36
  @todo
 
37
    think placing 2-3 component items in item (as it done for function
 
38
*/
 
39
 
 
40
Item_row::Item_row(List<Item> &arg):
 
41
  Item(), used_tables_cache(0), not_null_tables_cache(0),
 
42
  const_item_cache(1), with_null(0)
 
43
{
 
44
 
 
45
  //TODO: think placing 2-3 component items in item (as it done for function)
 
46
  if ((arg_count= arg.elements))
 
47
    items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
 
48
  else
 
49
    items= 0;
 
50
  List_iterator<Item> li(arg);
 
51
  uint i= 0;
 
52
  Item *item;
 
53
  while ((item= li++))
 
54
  {
 
55
    items[i]= item;
 
56
    i++;    
 
57
  }
 
58
}
 
59
 
 
60
void Item_row::illegal_method_call(const char *method)
 
61
{
 
62
  DBUG_ENTER("Item_row::illegal_method_call");
 
63
  DBUG_PRINT("error", ("!!! %s method was called for row item", method));
 
64
  DBUG_ASSERT(0);
 
65
  my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
 
66
  DBUG_VOID_RETURN;
 
67
}
 
68
 
 
69
bool Item_row::fix_fields(THD *thd, Item **ref)
 
70
{
 
71
  DBUG_ASSERT(fixed == 0);
 
72
  null_value= 0;
 
73
  maybe_null= 0;
 
74
  Item **arg, **arg_end;
 
75
  for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
 
76
  {
 
77
    if (!(*arg)->fixed &&
 
78
        (*arg)->fix_fields(thd, arg))
 
79
      return TRUE;
 
80
    // we can't assign 'item' before, because fix_fields() can change arg
 
81
    Item *item= *arg;
 
82
    used_tables_cache |= item->used_tables();
 
83
    const_item_cache&= item->const_item() && !with_null;
 
84
    not_null_tables_cache|= item->not_null_tables();
 
85
 
 
86
    if (const_item_cache)
 
87
    {
 
88
      if (item->cols() > 1)
 
89
        with_null|= item->null_inside();
 
90
      else
 
91
      {
 
92
        if (item->is_null())
 
93
          with_null|= 1;
 
94
      }
 
95
    }
 
96
    maybe_null|= item->maybe_null;
 
97
    with_sum_func= with_sum_func || item->with_sum_func;
 
98
    with_field= with_field || item->with_field;
 
99
    with_subselect|= item->with_subselect;
 
100
  }
 
101
  fixed= 1;
 
102
  return FALSE;
 
103
}
 
104
 
 
105
 
 
106
bool
 
107
Item_row::eval_not_null_tables(uchar *opt_arg)
 
108
{
 
109
  Item **arg,**arg_end;
 
110
  not_null_tables_cache= 0;
 
111
  if (arg_count)
 
112
  {             
 
113
    for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
 
114
    {
 
115
      not_null_tables_cache|= (*arg)->not_null_tables();
 
116
    }
 
117
  }
 
118
  return FALSE;
 
119
}
 
120
 
 
121
 
 
122
void Item_row::cleanup()
 
123
{
 
124
  DBUG_ENTER("Item_row::cleanup");
 
125
 
 
126
  Item::cleanup();
 
127
  /* Reset to the original values */
 
128
  used_tables_cache= 0;
 
129
  const_item_cache= 1;
 
130
  with_null= 0;
 
131
 
 
132
  DBUG_VOID_RETURN;
 
133
}
 
134
 
 
135
 
 
136
void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array,
 
137
                              List<Item> &fields)
 
138
{
 
139
  Item **arg, **arg_end;
 
140
  for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
 
141
    (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE);
 
142
}
 
143
 
 
144
 
 
145
void Item_row::update_used_tables()
 
146
{
 
147
  used_tables_cache= 0;
 
148
  const_item_cache= 1;
 
149
  maybe_null= 0;
 
150
  for (uint i= 0; i < arg_count; i++)
 
151
  {
 
152
    items[i]->update_used_tables();
 
153
    used_tables_cache|= items[i]->used_tables();
 
154
    const_item_cache&= items[i]->const_item();
 
155
    maybe_null|= items[i]->maybe_null;
 
156
  }
 
157
}
 
158
 
 
159
 
 
160
void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref)
 
161
{
 
162
  used_tables_cache= 0;
 
163
  const_item_cache= 1;
 
164
  not_null_tables_cache= 0;
 
165
  for (uint i= 0; i < arg_count; i++)
 
166
  {
 
167
    items[i]->fix_after_pullout(new_parent, &items[i]);
 
168
    used_tables_cache|= items[i]->used_tables();
 
169
    const_item_cache&= items[i]->const_item();
 
170
    not_null_tables_cache|= items[i]->not_null_tables();
 
171
  }
 
172
}
 
173
 
 
174
 
 
175
bool Item_row::check_cols(uint c)
 
176
{
 
177
  if (c != arg_count)
 
178
  {
 
179
    my_error(ER_OPERAND_COLUMNS, MYF(0), c);
 
180
    return 1;
 
181
  }
 
182
  return 0;
 
183
}
 
184
 
 
185
void Item_row::print(String *str, enum_query_type query_type)
 
186
{
 
187
  str->append('(');
 
188
  for (uint i= 0; i < arg_count; i++)
 
189
  {
 
190
    if (i)
 
191
      str->append(',');
 
192
    items[i]->print(str, query_type);
 
193
  }
 
194
  str->append(')');
 
195
}
 
196
 
 
197
 
 
198
bool Item_row::walk(Item_processor processor, bool walk_subquery, uchar *arg)
 
199
{
 
200
  for (uint i= 0; i < arg_count; i++)
 
201
  {
 
202
    if (items[i]->walk(processor, walk_subquery, arg))
 
203
      return 1;
 
204
  }
 
205
  return (this->*processor)(arg);
 
206
}
 
207
 
 
208
 
 
209
Item *Item_row::transform(Item_transformer transformer, uchar *arg)
 
210
{
 
211
  DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
 
212
 
 
213
  for (uint i= 0; i < arg_count; i++)
 
214
  {
 
215
    Item *new_item= items[i]->transform(transformer, arg);
 
216
    if (!new_item)
 
217
      return 0;
 
218
 
 
219
    /*
 
220
      THD::change_item_tree() should be called only if the tree was
 
221
      really transformed, i.e. when a new item has been created.
 
222
      Otherwise we'll be allocating a lot of unnecessary memory for
 
223
      change records at each execution.
 
224
    */
 
225
    if (items[i] != new_item)
 
226
      current_thd->change_item_tree(&items[i], new_item);
 
227
  }
 
228
  return (this->*transformer)(arg);
 
229
}
 
230
 
 
231
void Item_row::bring_value()
 
232
{
 
233
  for (uint i= 0; i < arg_count; i++)
 
234
    items[i]->bring_value();
 
235
}