item_row.cc 4.24 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/* Copyright (C) 2000 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "mysql_priv.h"

19 20 21 22 23 24 25 26 27
/*
  Row items used for comparing rows and IN operations on rows:

  (a, b, c) > (10, 10, 30)
  (a, b, c) = (select c, d, e, from t1 where x=12)
  (a, b, c) IN ((1,2,2), (3,4,5), (6,7,8)
  (a, b, c) IN (select c, d, e, from t1)
*/

unknown's avatar
unknown committed
28
Item_row::Item_row(List<Item> &arg):
unknown's avatar
unknown committed
29
  Item(), used_tables_cache(0), array_holder(1), const_item_cache(1), with_null(0)
unknown's avatar
unknown committed
30
{
unknown's avatar
unknown committed
31 32

  //TODO: think placing 2-3 component items in item (as it done for function)
unknown's avatar
unknown committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
  if ((arg_count= arg.elements))
    items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
  else
    items= 0;
  List_iterator<Item> li(arg);
  uint i= 0;
  Item *item;
  while ((item= li++))
  {
    items[i]= item;
    i++;    
  }
}

void Item_row::illegal_method_call(const char *method)
{
  DBUG_ENTER("Item_row::illegal_method_call");
  DBUG_PRINT("error", ("!!! %s method was called for row item", method));
  DBUG_ASSERT(0);
unknown's avatar
unknown committed
52
  my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
unknown's avatar
unknown committed
53 54 55 56 57
  DBUG_VOID_RETURN;
}

bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
{
58
  DBUG_ASSERT(fixed == 0);
unknown's avatar
unknown committed
59 60
  null_value= 0;
  maybe_null= 0;
61 62
  Item **arg, **arg_end;
  for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
unknown's avatar
unknown committed
63
  {
64
    if ((*arg)->fix_fields(thd, tabl, arg))
unknown's avatar
unknown committed
65
      return TRUE;
66 67 68
    // we can't assign 'item' before, because fix_fields() can change arg
    Item *item= *arg;
    used_tables_cache |= item->used_tables();
unknown's avatar
unknown committed
69 70
    const_item_cache&= item->const_item() && !with_null;
    if (const_item_cache)
unknown's avatar
unknown committed
71
    {
72 73
      if (item->cols() > 1)
	with_null|= item->null_inside();
unknown's avatar
unknown committed
74 75
      else
      {
76 77
	item->val_int();
	with_null|= item->null_value;
unknown's avatar
unknown committed
78
      }
unknown's avatar
unknown committed
79
    }
80 81
    maybe_null|= item->maybe_null;
    with_sum_func= with_sum_func || item->with_sum_func;
unknown's avatar
unknown committed
82
  }
83
  fixed= 1;
unknown's avatar
unknown committed
84
  return FALSE;
unknown's avatar
unknown committed
85 86
}

87 88
void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array,
                              List<Item> &fields)
89 90 91 92 93
{
  Item **arg, **arg_end;
  for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
  {
    if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM)
94
      (*arg)->split_sum_func(thd, ref_pointer_array, fields);
95 96 97
    else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM)
    {
      uint el= fields.elements;
98
      ref_pointer_array[el]=*arg;
99
      Item *new_item= new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
100 101
      fields.push_front(*arg);
      ref_pointer_array[el]= *arg;
102
      thd->change_item_tree(arg, new_item);
103 104 105 106
    }
  }
}

unknown's avatar
unknown committed
107 108 109 110 111 112 113 114 115 116 117 118
void Item_row::update_used_tables()
{
  used_tables_cache= 0;
  const_item_cache= 1;
  for (uint i= 0; i < arg_count; i++)
  {
    items[i]->update_used_tables();
    used_tables_cache|= items[i]->used_tables();
    const_item_cache&= items[i]->const_item();
  }
}

unknown's avatar
unknown committed
119 120 121 122
bool Item_row::check_cols(uint c)
{
  if (c != arg_count)
  {
unknown's avatar
unknown committed
123
    my_error(ER_OPERAND_COLUMNS, MYF(0), c);
unknown's avatar
unknown committed
124 125 126 127
    return 1;
  }
  return 0;
}
unknown's avatar
unknown committed
128

129 130 131 132 133 134 135 136 137 138 139 140
void Item_row::print(String *str)
{
  str->append('(');
  for (uint i= 0; i < arg_count; i++)
  {
    if (i)
      str->append(',');
    items[i]->print(str);
  }
  str->append(')');
}

unknown's avatar
unknown committed
141 142 143 144 145 146 147 148 149 150
bool Item_row::walk(Item_processor processor, byte *arg)
{
  for (uint i= 0; i < arg_count; i++)
  {
    if (items[i]->walk(processor, arg))
      return 1;
  }
  return (this->*processor)(arg);
}

unknown's avatar
unknown committed
151
Item *Item_row::transform(Item_transformer transformer, byte *arg)
152 153 154
{
  for (uint i= 0; i < arg_count; i++)
  {
unknown's avatar
unknown committed
155
    Item *new_item= items[i]->transform(transformer, arg);
156 157 158 159
    if (!new_item)
      return 0;
    items[i]= new_item;
  }
unknown's avatar
unknown committed
160
  return (this->*transformer)(arg);
161 162
}

unknown's avatar
unknown committed
163 164 165 166
void Item_row::bring_value()
{
  for (uint i= 0; i < arg_count; i++)
    items[i]->bring_value();
167
}