Commit message: MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order...

When doing condition pushdown from HAVING into WHERE,
Item_equal::create_pushable_equalities() calls
item->set_extraction_flag(IMMUTABLE_FL) for constant items.
Then, Item::cleanup_excluding_immutables_processor() checks for this flag
to see if it should call item->cleanup() or leave the item as-is.

The failure happens when a constant item has a non-constant one inside it,
like:

   (tbl.col=0 AND impossible_cond)

item->walk(cleanup_excluding_immutables_processor) works in a bottom-up
way so it
1. will call Item_func_eq(tbl.col=0)->cleanup()
2. will not call Item_cond_and->cleanup (as the AND is constant)

This creates an item tree where a fixed Item has an un-fixed Item inside
it which eventually causes an assertion failure.

Fixed by introducing this rule: instead of just calling

  item->set_extraction_flag(IMMUTABLE_FL);

we call Item::walk() to set the flag for all sub-items of the item.
CVE: CVE-2022-27382
CWE: CWE-617
Vulnerability description: MariaDB Server v10.7 and below was discovered to contain a segmentation fault via the component Item_field::used_tables/update_depend_map_for_order.

Project: server

cmp_item* cmp_item_decimal::make_same()
{
  return new cmp_item_decimal();
}

Project: server

void Item_equal::update_const(THD *thd)
{
  List_iterator<Item> it(equal_items);
  if (with_const)
    it++;
  Item *item;
  while ((item= it++))
  {
    if (item->const_item() && !item->is_expensive() &&
        /*
          Don't propagate constant status of outer-joined column.
          Such a constant status here is a result of:
            a) empty outer-joined table: in this case such a column has a
               value of NULL; but at the same time other arguments of
               Item_equal don't have to be NULLs and the value of the whole
               multiple equivalence expression doesn't have to be NULL or FALSE
               because of the outer join nature;
          or
            b) outer-joined table contains only 1 row: the result of
               this column is equal to a row field value *or* NULL.
          Both values are inacceptable as Item_equal constants.
        */
        !item->is_outer_field())
    {
      if (item == equal_items.head())
        with_const= TRUE;
      else
      {
        it.remove();
        add_const(thd, item);
      }
    } 
  }
}

Project: server

Item_cond::Item_cond(THD *thd, Item *i1, Item *i2):
  Item_bool_func(thd), abort_on_null(0)
{
  list.push_back(i1, thd->mem_root);
  list.push_back(i2, thd->mem_root);
}

Project: server

inline void TABLE::use_all_stored_columns()
{
  bitmap_set_all(read_set);
  if (Field **vf= vfield)
    for (; *vf; vf++)
      bitmap_clear_bit(read_set, (*vf)->field_index);
}

Project: server

  bool group() const { return m_group; }

Project: server

  String *val_str(String *to)
  {
    return has_value() ? Date(this).to_string(to) : NULL;
  }

Project: server

Item_func_in::eval_not_null_tables(void *opt_arg)
{
  Item **arg, **arg_end;

  if (Item_func_opt_neg::eval_not_null_tables(NULL))
    return 1;

  /* not_null_tables_cache == union(T1(e),union(T1(ei))) */
  if (pred_level && negated)
    return 0;

  /* not_null_tables_cache = union(T1(e),intersection(T1(ei))) */
  not_null_tables_cache= ~(table_map) 0;
  for (arg= args + 1, arg_end= args + arg_count; arg != arg_end; arg++)
    not_null_tables_cache&= (*arg)->not_null_tables();
  not_null_tables_cache|= (*args)->not_null_tables();
  return 0;
}

Project: server

longlong Item_func_dyncol_exists::val_int()
{
  char buff[STRING_BUFFER_USUAL_SIZE], nmstrbuf[11];
  String tmp(buff, sizeof(buff), &my_charset_bin),
         nmbuf(nmstrbuf, sizeof(nmstrbuf), system_charset_info);
  DYNAMIC_COLUMN col;
  String *str;
  LEX_STRING buf, *name= NULL;
  ulonglong num= 0;
  enum enum_dyncol_func_result rc;

  if (args[1]->result_type() == INT_RESULT)
    num= args[1]->val_int();
  else
  {
    String *nm= args[1]->val_str(&nmbuf);
    if (!nm || args[1]->null_value)
    {
      null_value= 1;
      return 1;
    }
    if (my_charset_same(nm->charset(), DYNCOL_UTF))
    {
      buf.str= (char *) nm->ptr();
      buf.length= nm->length();
    }
    else
    {
      uint strlen= nm->length() * DYNCOL_UTF->mbmaxlen + 1;
      uint dummy_errors;
      buf.str= (char *) current_thd->alloc(strlen);
      if (buf.str)
      {
        buf.length=
          copy_and_convert(buf.str, strlen, DYNCOL_UTF,
                           nm->ptr(), nm->length(), nm->charset(),
                           &dummy_errors);
      }
      else
        buf.length= 0;
    }
    name= &buf;
  }
  str= args[0]->val_str(&tmp);
  if (args[0]->null_value || args[1]->null_value || num > UINT_MAX16)
    goto null;
  col.length= str->length();
  /* We do not change the string, so could do this trick */
  col.str= (char *)str->ptr();
  rc= ((name == NULL) ?
       mariadb_dyncol_exists_num(&col, (uint) num) :
       mariadb_dyncol_exists_named(&col, name));
  if (rc < 0)
  {
    dynamic_column_error_message(rc);
    goto null;
  }
  null_value= FALSE;
  return rc == ER_DYNCOL_YES;

null:
  null_value= TRUE;
  return 0;
}

Project: server

  longlong val_int() { return value; }

Project: server

  longlong val_time_packed(THD *thd)
  {
    if (check_null_ref())
      return 0;
    else
      return Item_direct_ref::val_time_packed(thd);
  }

Project: server

int cmp_item_time::cmp(Item *arg)
{
  const bool rc= value != arg->val_time_packed(current_thd);
  return (m_null_value || arg->null_value) ? UNKNOWN : rc;
}

Project: server

  bool fix_fields_if_needed(THD *thd, Item **ref)
  {
    return is_fixed() ? false : fix_fields(thd, ref);
  }

Project: server

  my_decimal *val_decimal(my_decimal *to)
  {
    DBUG_ASSERT(sane());
    return null_value ? NULL :
           m_value.to_datetime(current_thd).to_decimal(to);
  }

Project: server

  double val_real()
  {
    DBUG_ASSERT(sane());
    return null_value ? 0e0 :
           m_value.to_datetime(current_thd).to_double();
  }

Project: server

  Item *get_copy(THD *thd)
  { return get_item_copy<Item_copy_string>(thd, this); }

Project: server

Item *Item_cond_and::neg_transformer(THD *thd)	/* NOT(a AND b AND ...)  -> */
					/* NOT a OR NOT b OR ... */
{
  neg_arguments(thd);
  Item *item= new (thd->mem_root) Item_cond_or(thd, list);
  return item;
}

Project: server

  Item_result_field(THD *thd): Item_fixed_hybrid(thd), result_field(0) {}

Project: server

Item *in_decimal::create_item(THD *thd)
{ 
  return new (thd->mem_root) Item_decimal(thd, 0, FALSE);
}

Project: server

Item_cond::eval_not_null_tables(void *opt_arg)
{
  Item *item;
  bool is_and_cond= functype() == Item_func::COND_AND_FUNC;
  List_iterator<Item> li(list);
  not_null_tables_cache= (table_map) 0;
  and_tables_cache= ~(table_map) 0;
  while ((item=li++))
  {
    table_map tmp_table_map;
    if (item->const_item() && !item->with_param &&
        !item->is_expensive() && !cond_has_datetime_is_null(item))
    {
      if (item->eval_const_cond() == is_and_cond && top_level())
      {
        /* 
          a. This is "... AND true_cond AND ..."
          In this case, true_cond  has no effect on cond_and->not_null_tables()
          b. This is "... OR false_cond/null cond OR ..." 
          In this case, false_cond has no effect on cond_or->not_null_tables()
        */
      }
      else
      {
        /* 
          a. This is "... AND false_cond/null_cond AND ..."
          The whole condition is FALSE/UNKNOWN.
          b. This is  "... OR const_cond OR ..."
          In this case, cond_or->not_null_tables()=0, because the condition
          const_cond might evaluate to true (regardless of whether some tables
          were NULL-complemented).
        */
        not_null_tables_cache= (table_map) 0;
        and_tables_cache= (table_map) 0;
      }
    }
    else
    {
      tmp_table_map= item->not_null_tables();
      not_null_tables_cache|= tmp_table_map;
      and_tables_cache&= tmp_table_map;
    }
  }
  return 0;
}

Project: server

  my_decimal *val_decimal(my_decimal *to)
  {
    return update_null() ? 0 : cached_time.to_decimal(to);
  }

Project: server

  String *val_str(String *to)
  {
    return has_value() ? Time(this).to_string(to, decimals) : NULL;
  }

Project: server

bool Item_in_optimizer::is_expensive()
{
  DBUG_ASSERT(fixed);
  return args[0]->is_expensive() || args[1]->is_expensive();
}

Project: server

  Item_outer_ref(THD *thd, Name_resolution_context *context_arg,
                 Item_field *outer_field_arg):
    Item_direct_ref(thd, context_arg, 0, outer_field_arg->table_name,
                    &outer_field_arg->field_name),
    outer_ref(outer_field_arg), in_sum_func(0),
    found_in_select_list(0), found_in_group_by(0)
  {
    ref= &outer_ref;
    set_properties();
    fixed= 0;                     /* reset flag set in set_properties() */
  }

Project: server

  bool make_copy_field() const { return m_make_copy_field; }

Project: server

  const Type_handler *type_handler() const
  { return Type_handler_hybrid_field_type::type_handler(); }

Project: server

void Item_func_between::print(String *str, enum_query_type query_type)
{
  args[0]->print_parenthesised(str, query_type, higher_precedence());
  if (negated)
    str->append(STRING_WITH_LEN(" not"));
  str->append(STRING_WITH_LEN(" between "));
  args[1]->print_parenthesised(str, query_type, precedence());
  str->append(STRING_WITH_LEN(" and "));
  args[2]->print_parenthesised(str, query_type, precedence());
}

Project: server

  String *val_str(String *to)
  {
    return has_value() ? Datetime(this).to_string(to, decimals) : NULL;
  }

Project: server

  Item_cache_timestamp(THD *thd)
   :Item_cache(thd, &type_handler_timestamp2) { }

Project: server

bool Item_cond::excl_dep_on_grouping_fields(st_select_lex *sel)
{
  if (has_rand_bit())
    return false;
  List_iterator_fast<Item> li(list);
  Item *item;
  while ((item= li++))
  {
    if (!item->excl_dep_on_grouping_fields(sel))
      return false;
  }
  return true;
}

Project: server

  Item_temporal_literal(THD *thd, uint dec_arg):
    Item_literal(thd)
  {
    collation.set(&my_charset_numeric, DERIVATION_NUMERIC, MY_REPERTOIRE_ASCII);
    decimals= dec_arg;
  }

Project: server

void in_timestamp::value_to_item(uint pos, Item *item)
{
  const Timestamp_or_zero_datetime &buff= (((Timestamp_or_zero_datetime*) base)[pos]);
  static_cast<Item_timestamp_literal*>(item)->set_value(buff);
}

Project: server

Item *in_temporal::create_item(THD *thd)
{ 
  return new (thd->mem_root) Item_datetime(thd);
}

Project: server

  my_decimal *val_decimal(my_decimal *to)
  {
    return m_value.to_datetime(current_thd).to_decimal(to);
  }

Project: server

  Item_copy(THD *thd, Item *i): Item(thd)
  {
    DBUG_ASSERT(i->is_fixed());
    item= i;
    null_value=maybe_null=item->maybe_null;
    Type_std_attributes::set(item);
    name= item->name;
    set_handler(item->type_handler());
  }

Project: server

bool Item_func_ifnull::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
  DBUG_ASSERT(fixed == 1);
  for (uint i= 0; i < 2; i++)
  {
    Datetime_truncation_not_needed dt(thd, args[i],
                                      fuzzydate & ~TIME_FUZZY_DATES);
    if (!(dt.copy_to_mysql_time(ltime, mysql_timestamp_type())))
      return (null_value= false);
  }
  return (null_value= true);
}

Project: server

Item *Item_cond::transform(THD *thd, Item_transformer transformer, uchar *arg)
{
  DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare());

  List_iterator<Item> li(list);
  Item *item;
  while ((item= li++))
  {
    Item *new_item= item->transform(thd, transformer, arg);
    if (!new_item)
      return 0;

    /*
      THD::change_item_tree() should be called only if the tree was
      really transformed, i.e. when a new item has been created.
      Otherwise we'll be allocating a lot of unnecessary memory for
      change records at each execution.
    */
    if (new_item != item)
      thd->change_item_tree(li.ref(), new_item);
  }
  return Item_func::transform(thd, transformer, arg);
}

Project: server

in_string::~in_string()
{
  if (base)
  {
    // base was allocated on THD::mem_root => following is OK
    for (uint i=0 ; i < count ; i++)
      ((String*) base)[i].free();
  }
}

Project: server

Item_func_regexp_instr::fix_length_and_dec()
{
  if (agg_arg_charsets_for_comparison(cmp_collation, args, 2))
    return TRUE;

  re.init(cmp_collation.collation, 0);
  re.fix_owner(this, args[0], args[1]);
  max_length= MY_INT32_NUM_DECIMAL_DIGITS; // See also Item_func_locate
  return FALSE;
}

Project: server

  Type_geometry_attributes()
   :m_geometry_type(m_geometry_type_unknown)
  { }

Project: server

Item *Item_func_xor::neg_transformer(THD *thd)
{
  Item *neg_operand;
  Item_func_xor *new_item;
  if ((neg_operand= args[0]->neg_transformer(thd)))
    // args[0] has neg_tranformer
    new_item= new(thd->mem_root) Item_func_xor(thd, neg_operand, args[1]);
  else if ((neg_operand= args[1]->neg_transformer(thd)))
    // args[1] has neg_tranformer
    new_item= new(thd->mem_root) Item_func_xor(thd, args[0], neg_operand);
  else
  {
    neg_operand= new(thd->mem_root) Item_func_not(thd, args[0]);
    new_item= new(thd->mem_root) Item_func_xor(thd, neg_operand, args[1]);
  }
  return new_item;
}

Project: server

  virtual bool is_fixed() const { return true; }

Project: server

int Arg_comparator::compare_datetime()
{
  THD *thd= current_thd;
  longlong val1= (*a)->val_datetime_packed(thd);
  if (!(*a)->null_value)
  {
    longlong val2= (*b)->val_datetime_packed(thd);
    if (!(*b)->null_value)
      return compare_not_null_values(val1, val2);
  }
  if (set_null)
    owner->null_value= true;
  return -1;
}

Project: server

longlong Item_func_between::val_int_cmp_int()
{
  Longlong_hybrid value= args[0]->to_longlong_hybrid();
  if ((null_value= args[0]->null_value))
    return 0;					/* purecov: inspected */
  Longlong_hybrid a= args[1]->to_longlong_hybrid();
  Longlong_hybrid b= args[2]->to_longlong_hybrid();
  if (!args[1]->null_value && !args[2]->null_value)
    return (longlong) ((value.cmp(a) >= 0 && value.cmp(b) <= 0) != negated);
  if (args[1]->null_value && args[2]->null_value)
    null_value= true;
  else if (args[1]->null_value)
    null_value= value.cmp(b) <= 0;              // not null if false range.
  else
    null_value= value.cmp(a) >= 0;
  return (longlong) (!null_value && negated);
}

Project: server

  Item_null(THD *thd, const char *name_par=0, CHARSET_INFO *cs= &my_charset_bin):
    Item_basic_constant(thd)
  {
    maybe_null= null_value= TRUE;
    max_length= 0;
    name.str= name_par ? name_par : "NULL";
    name.length= strlen(name.str);
    collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII);
  }

Project: server

  Field *create_field_for_create_select(TABLE *table)
  { return tmp_table_field_from_field_type(table); }

Project: server

  void fix_charset_and_length(CHARSET_INFO *cs,
                              Derivation dv, Metadata metadata)
  {
    /*
      We have to have a different max_length than 'length' here to
      ensure that we get the right length if we do use the item
      to create a new table. In this case max_length must be the maximum
      number of chars for a string of this type because we in Create_field::
      divide the max_length with mbmaxlen).
    */
    collation.set(cs, dv, metadata.repertoire());
    fix_char_length(metadata.char_length());
    decimals= NOT_FIXED_DEC;
  }

Project: server

inline Item* get_item_copy (THD *thd, T* item)
{
  Item *copy= new (get_thd_memroot(thd)) T(*item);
  if (likely(copy))
    copy->register_in(thd);
  return copy;
}

Project: server

  double val_real_from_item(Item *item)
  {
    DBUG_ASSERT(is_fixed());
    double value= item->val_real();
    null_value= item->null_value;
    return value;
  }

Project: server

bool Item_func_in::value_list_convert_const_to_int(THD *thd)
{
  if (args[0]->real_item()->type() == FIELD_ITEM &&
      !thd->lex->is_view_context_analysis())
  {
    Item_field *field_item= (Item_field*) (args[0]->real_item());
    if (field_item->field_type() == MYSQL_TYPE_LONGLONG ||
        field_item->field_type() == MYSQL_TYPE_YEAR)
    {
      bool all_converted= true;
      Item **arg, **arg_end;
      for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
      {
          /*
            Explicit NULLs should not affect data cmp_type resolution:
            - we ignore NULLs when calling collect_cmp_type()
            - we ignore NULLs here
            So this expression:
              year_column IN (DATE'2001-01-01', NULL)
            switches from TIME_RESULT to INT_RESULT.
          */
          if (arg[0]->type() != Item::NULL_ITEM &&
              !convert_const_to_int(thd, field_item, &arg[0]))
           all_converted= false;
      }
      if (all_converted)
        m_comparator.set_handler(&type_handler_longlong);
    }
  }
  return thd->is_fatal_error; // Catch errrors in convert_const_to_int
}

Project: server

  Item_type_holder(THD *thd, Item *item)
   :Item(thd, item),
    Type_handler_hybrid_field_type(item->real_type_handler()),
    enum_set_typelib(0)
  {
    DBUG_ASSERT(item->is_fixed());
    maybe_null= item->maybe_null;
  }

Project: server

  bool is_string() const { return m_type == DYN_COL_STRING; }

Project: server

  Item_int(THD *thd, const char *str_arg,longlong i,size_t length):
    Item_num(thd), value(i)
    {
      max_length=(uint32)length;
      name.str= str_arg; name.length= safe_strlen(name.str);
    }

Project: server

String *Item_func_coalesce::str_op(String *str)
{
  DBUG_ASSERT(fixed == 1);
  null_value=0;
  for (uint i=0 ; i < arg_count ; i++)
  {
    String *res;
    if ((res=args[i]->val_str(str)))
      return res;
  }
  null_value=1;
  return 0;
}

Project: server

  void set_item_result_field(Item_result_field *item)
  { m_item_result_field= item; }

Project: server

bool Predicant_to_list_comparator::add_value_skip_null(const char *funcname,
                                                       Item_args *args,
                                                       uint value_index,
                                                       bool *nulls_found)
{
  /*
    Skip explicit NULL constant items.
    Using real_item() to correctly detect references to explicit NULLs
    in HAVING clause, e.g. in this example "b" is skipped:
      SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A');
  */
  if (args->arguments()[value_index]->real_item()->type() == Item::NULL_ITEM)
  {
    *nulls_found= true;
    return false;
  }
  return add_value(funcname, args, value_index);
}

Project: server

void Item_func_in::fix_in_vector()
{
  DBUG_ASSERT(array);
  uint j=0;
  for (uint i=1 ; i < arg_count ; i++)
  {
    array->set(j,args[i]);
    if (!args[i]->null_value)
      j++; // include this cell in the array.
    else
    {
      /*
        We don't put NULL values in array, to avoid erronous matches in
        bisection.
      */
      have_null= 1;
    }
  }
  if ((array->used_count= j))
    array->sort();
}

Project: server

  longlong val_int()
  {
    return to_datetime(current_thd).to_longlong();
  }

Project: server

  const Type_handler *type_handler() const
  {
    return Type_handler_hybrid_field_type::type_handler()->
             type_handler_for_item_field();
  }

Project: server

bool Regexp_processor_pcre::exec(const char *str, size_t length, size_t offset)
{
  m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra, str, (int)length, (int)offset, 0,
                                      m_SubStrVec, array_elements(m_SubStrVec));
  return false;
}

Project: server

  bool with_sum_func() const { return m_with_sum_func; }

Project: server

  my_decimal *val_decimal(my_decimal *decimal_value)
  {
    DBUG_ASSERT(0); // never should be called
    null_value= true;
    return 0;
  }

Project: server

  Item *get_copy(THD *thd)
  { return get_item_copy<Item_cache_time>(thd, this); }

Project: server

  virtual const Type_handler *real_type_handler() const
  {
    return type_handler();
  }

Project: server

cmp_item* cmp_item_int::make_same()
{
  return new cmp_item_int();
}

Project: server

longlong Item_func_ge::val_int()
{
  DBUG_ASSERT(fixed == 1);
  int value= cmp.compare();
  return value >= 0 ? 1 : 0;
}

Project: server

void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item)
{
  List_iterator_fast<Item> li(item->list);
  while (Item *it= li++)
    list.push_back(it->copy_andor_structure(thd), thd->mem_root);
}

Project: server

int Arg_comparator::compare_int_signed()
{
  longlong val1= (*a)->val_int();
  if (!(*a)->null_value)
  {
    longlong val2= (*b)->val_int();
    if (!(*b)->null_value)
      return compare_not_null_values(val1, val2);
  }
  if (set_null)
    owner->null_value= 1;
  return -1;
}

Project: server

  Item_string(THD *thd, const char *name_par, const char *str, size_t length,
              CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
   :Item_literal(thd)
  {
    str_value.set_or_copy_aligned(str, length, cs);
    fix_from_value(dv, Metadata(&str_value));
    set_name(thd, name_par,safe_strlen(name_par), system_charset_info);
  }

Project: server

Item_func_regex::fix_length_and_dec()
{
  if (Item_bool_func::fix_length_and_dec() ||
      agg_arg_charsets_for_comparison(cmp_collation, args, 2))
    return TRUE;

  re.init(cmp_collation.collation, 0);
  re.fix_owner(this, args[0], args[1]);
  return FALSE;
}

Project: server

  Field::geometry_type get_geometry_type() const
  {
    return m_geometry_type == m_geometry_type_unknown ?
           Field::GEOM_GEOMETRY :
           (Field::geometry_type) m_geometry_type;
  }

Project: server

  bool is_decimal() const { return m_type == DYN_COL_DECIMAL; }

Project: server

in_row::~in_row()
{
  if (base)
    delete [] (cmp_item_row*) base;
}

Project: server

bool Item_func_coalesce::native_op(THD *thd, Native *to)
{
  DBUG_ASSERT(fixed == 1);
  for (uint i= 0; i < arg_count; i++)
  {
    if (!val_native_with_conversion_from_item(thd, args[i], to, type_handler()))
      return false;
  }
  return (null_value= true);
}

Project: server

  bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
  {
    if (check_null_ref())
    {
      bzero((char*) ltime,sizeof(*ltime));
      return 1;
    }
    return Item_direct_ref::get_date(thd, ltime, fuzzydate);
  }

Project: server

  Item_ref(THD *thd, Item_ref *item)
    :Item_ident(thd, item), With_sum_func_cache(*item),
     set_properties_only(0), ref(item->ref) {}

Project: server

  Item_int(THD *thd, ulonglong i, size_t length= MY_INT64_NUM_DECIMAL_DIGITS):
    Item_num(thd), value((longlong)i)
    { max_length=(uint32)length; unsigned_flag= 1; }

Project: server

  String* val_str(String *to)
  {
    return to_datetime(current_thd).to_string(to, decimals);
  }

Project: server

bool Item_func_ifnull::time_op(THD *thd, MYSQL_TIME *ltime)
{
  DBUG_ASSERT(fixed == 1);
  for (uint i= 0; i < 2; i++)
  {
    if (!Time(thd, args[i]).copy_to_mysql_time(ltime))
      return (null_value= false);
  }
  return (null_value= true);
}

Project: server

bool Item_func_case_simple::aggregate_switch_and_when_arguments(THD *thd,
                                                                bool nulls_eq)
{
  uint ncases= when_count();
  m_found_types= 0;
  if (prepare_predicant_and_values(thd, &m_found_types, nulls_eq))
  {
    /*
      If Predicant_to_list_comparator() fails to prepare components,
      it must put an error into the diagnostics area. This is needed
      to make fix_fields() catches such errors.
    */
    DBUG_ASSERT(thd->is_error());
    return true;
  }

  if (!(m_found_types= collect_cmp_types(args, ncases + 1)))
    return true;

  if (m_found_types & (1U << STRING_RESULT))
  {
    /*
      If we'll do string comparison, we also need to aggregate
      character set and collation for first/WHEN items and
      install converters for some of them to cmp_collation when necessary.
      This is done because cmp_item compatators cannot compare
      strings in two different character sets.
      Some examples when we install converters:

      1. Converter installed for the first expression:

         CASE         latin1_item              WHEN utf16_item THEN ... END

      is replaced to:

         CASE CONVERT(latin1_item USING utf16) WHEN utf16_item THEN ... END

      2. Converter installed for the left WHEN item:

        CASE utf16_item WHEN         latin1_item              THEN ... END

      is replaced to:

         CASE utf16_item WHEN CONVERT(latin1_item USING utf16) THEN ... END
    */
    if (agg_arg_charsets_for_comparison(cmp_collation, args, ncases + 1))
      return true;
  }

  if (make_unique_cmp_items(thd, cmp_collation.collation))
    return true;

  return false;
}

Project: server

longlong Item_func_nop_all::val_int()
{
  DBUG_ASSERT(fixed == 1);
  longlong value= args[0]->val_int();

  /*
    return FALSE if there was records in underlying select in max/min
    optimization (SAME/ANY subquery)
  */
  if (empty_underlying_subquery())
    return 0;

  null_value= args[0]->null_value;
  return (null_value || value == 0) ? 0 : 1;
}

Project: server

  uint time_precision(THD *thd)
  {
    return const_item() ? type_handler()->Item_time_precision(thd, this) :
                          MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
  }

Project: server

  void cleanup()
  {
    clear();
    Item::cleanup();
  }

Project: server

Item_bool_rowready_func2* Eq_creator::create_swap(THD *thd, Item *a, Item *b) const
{
  return new(thd->mem_root) Item_func_eq(thd, b, a);
}

Project: server

Item *Item_cond_or::neg_transformer(THD *thd)	/* NOT(a OR b OR ...)  -> */
					/* NOT a AND NOT b AND ... */
{
  neg_arguments(thd);
  Item *item= new (thd->mem_root) Item_cond_and(thd, list);
  return item;
}

Project: server

void in_timestamp::set(uint pos, Item *item)
{
  Timestamp_or_zero_datetime *buff= &((Timestamp_or_zero_datetime *) base)[pos];
  Timestamp_or_zero_datetime_native_null native(current_thd, item, true);
  if (native.is_null())
    *buff= Timestamp_or_zero_datetime();
  else
    *buff= Timestamp_or_zero_datetime(native);
}

Project: server

longlong Item_func_regex::val_int()
{
  DBUG_ASSERT(fixed == 1);
  if ((null_value= re.recompile(args[1])))
    return 0;

  if ((null_value= re.exec(args[0], 0, 0)))
    return 0;

  return re.match();
}

Project: server

Item_bool_rowready_func2* Gt_creator::create(THD *thd, Item *a, Item *b) const
{
  return new(thd->mem_root) Item_func_gt(thd, a, b);
}

Project: server

  longlong val_int()
  {
    return can_return_value() ? value.val_int(this) : 0;
  }

Project: server

  const my_decimal *const_ptr_my_decimal() const { return &decimal_value; }

Project: server

  virtual bool set_extraction_flag_processor(void *arg)
  {
    set_extraction_flag(*(int*)arg);
    return 0;
  }

Project: server

  const Type_handler *real_type_handler() const
  {
    return Type_handler_hybrid_field_type::type_handler();
  }

Project: server

  virtual const longlong *const_ptr_longlong() const { return NULL; }

Project: server

  Item_return_date_time(THD *thd, const char *name_arg, uint length_arg,
                        enum_field_types field_type_arg, uint dec_arg= 0):
    Item_partition_func_safe_string(thd, name_arg, length_arg, &my_charset_bin),
    date_time_field_type(field_type_arg)
  { decimals= dec_arg; }

Project: server

Item *Item_cond_or::copy_andor_structure(THD *thd)
{
  Item_cond_or *item;
  if ((item= new (thd->mem_root) Item_cond_or(thd, this)))
    item->copy_andor_arguments(thd, this);
  return item;
}

Project: server

  bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
  {
    cached_time.copy_to_mysql_time(ltime);
    return (null_value= false);
  }

Project: server

  Item_cache* get_cache(THD *thd) const
  {
    return type_handler()->Item_get_cache(thd, this);
  }

Project: server

  Item_direct_ref(THD *thd, TABLE_LIST *view_arg, Item **item,
                  const LEX_CSTRING *field_name_arg,
                  bool alias_name_used_arg= FALSE):
    Item_ref(thd, view_arg, item, field_name_arg,
             alias_name_used_arg)
  {}

Project: server

bool Item_bool_func2::count_sargable_conds(void *arg)
{
  ((SELECT_LEX*) arg)->cond_count++;
  return 0;
}

Project: server

  Item *get_copy(THD *thd)
  { return get_item_copy<Item_field>(thd, this); }

Project: server

uchar *in_decimal::get_value(Item *item)
{
  my_decimal *result= item->val_decimal(&val);
  if (item->null_value)
    return 0;
  return (uchar *)result;
}

Project: server

Item *Item_func_eq::negated_item(THD *thd) /* a = b  ->  a != b */
{
  return new (thd->mem_root) Item_func_ne(thd, args[0], args[1]);
}

Project: server

  Item *get_copy(THD *thd)
  { return get_item_copy<Item_hex_string>(thd, this); }

Project: server

  Item_cache_int(THD *thd): Item_cache(thd, &type_handler_longlong),
    value(0) {}

Project: server

void cmp_item_decimal::store_value(Item *item)
{
  my_decimal *val= item->val_decimal(&value);
  /* val may be zero if item is nnull */
  if (val && val != &value)
    my_decimal2decimal(val, &value);
  m_null_value= item->null_value;
}

Project: server

  bool fix_fields_if_needed_for_bool(THD *thd, Item **ref)
  {
    return fix_fields_if_needed_for_scalar(thd, ref);
  }

Project: server

  void reset_with_sum_func() { m_with_sum_func= false; }

Project: server

  virtual const double *const_ptr_double() const { return NULL; }

Project: server

int Arg_comparator::compare_string()
{
  String *res1,*res2;
  if ((res1= (*a)->val_str(&value1)))
  {
    if ((res2= (*b)->val_str(&value2)))
    {
      if (set_null)
        owner->null_value= 0;
      return sortcmp(res1, res2, compare_collation());
    }
  }
  if (set_null)
    owner->null_value= 1;
  return -1;
}

Project: server

  bool val_native_with_conversion(THD *thd, Native *to, const Type_handler *th)
  {
    return th->Item_val_native_with_conversion(thd, this, to);
  }

Project: server

  Item *get_copy(THD *thd)
  { return get_item_copy<Item_uint>(thd, this); }

Project: server

int Arg_comparator::compare_json_str()
{
  return compare_json_str_basic(*a, *b);
}

Project: server

  virtual Item *make_odbc_literal(THD *thd, const LEX_CSTRING *typestr)
  {
    return this;
  }

Project: server

  Item_int(THD *thd, int32 i,size_t length= MY_INT32_NUM_DECIMAL_DIGITS):
    Item_num(thd), value((longlong) i)
    { max_length=(uint32)length; }

Project: server

  Item *remove_item_direct_ref()
  { return (*ref)->remove_item_direct_ref(); }

Project: server

  bool val_native_from_field(Field *field, Native *to)
  {
    if ((null_value= field->is_null()))
      return true;
    return (null_value= field->val_native(to));
  }

Project: server

  Item *get_copy(THD *thd)
  { return get_item_copy<Item_cache_str_for_nullif>(thd, this); }

Project: server

  const Type_handler *type_handler() const
  {
    return value_item->type_handler();
  }

Project: server

  void set_field(Field *field) { m_field= field; }

Project: server

void Item_in_optimizer::keep_top_level_cache()
{
  cache->keep_array();
  save_cache= 1;
}

Project: server

int Regexp_processor_pcre::pcre_exec_with_warn(const pcre *code,
                                               const pcre_extra *extra,
                                               const char *subject,
                                               int length, int startoffset,
                                               int options, int *ovector,
                                               int ovecsize)
{
  int rc= pcre_exec(code, extra, subject, length,
                    startoffset, options, ovector, ovecsize);
  DBUG_EXECUTE_IF("pcre_exec_error_123", rc= -123;);
  if (unlikely(rc < PCRE_ERROR_NOMATCH))
    pcre_exec_warn(rc);
  return rc;
}

Project: server

  bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
  { return get_date_from_int(thd, ltime, fuzzydate); }

Project: server

bool Item_func_coalesce::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
  DBUG_ASSERT(fixed == 1);
  for (uint i= 0; i < arg_count; i++)
  {
    Datetime_truncation_not_needed dt(thd, args[i],
                                      fuzzydate & ~TIME_FUZZY_DATES);
    if (!dt.copy_to_mysql_time(ltime, mysql_timestamp_type()))
      return (null_value= false);
  }
  return (null_value= true);
}

Project: server

cmp_item_row::~cmp_item_row()
{
  DBUG_ENTER("~cmp_item_row");
  DBUG_PRINT("enter",("this: %p", this));
  if (comparators)
  {
    for (uint i= 0; i < n; i++)
    {
      if (comparators[i])
	delete comparators[i];
    }
  }
  DBUG_VOID_RETURN;
}

Project: server

  Item_cache_time(THD *thd)
   :Item_cache_temporal(thd, &type_handler_time2) { }

Project: server

Item_equal::Item_equal(THD *thd, Item_equal *item_equal):
  Item_bool_func(thd), eval_item(0), cond_false(0), cond_true(0),
  context_field(NULL), link_equal_fields(FALSE),
  m_compare_handler(item_equal->m_compare_handler),
  m_compare_collation(item_equal->m_compare_collation)
{
  const_item_cache= 0;
  List_iterator_fast<Item> li(item_equal->equal_items);
  Item *item;
  while ((item= li++))
  {
    equal_items.push_back(item, thd->mem_root);
  }
  with_const= item_equal->with_const;
  cond_false= item_equal->cond_false;
  upper_levels= item_equal->upper_levels;
}

Project: server

  const Type_handler *string_type_handler() const
  {
    return Type_handler::string_type_handler(max_length);
  }

Project: server

Item_bool_rowready_func2* Le_creator::create_swap(THD *thd, Item *a, Item *b) const
{
  return new(thd->mem_root) Item_func_ge(thd, b, a);
}

Project: server

int Arg_comparator::compare_e_time()
{
  THD *thd= current_thd;
  longlong val1= (*a)->val_time_packed(thd);
  longlong val2= (*b)->val_time_packed(thd);
  if ((*a)->null_value || (*b)->null_value)
    return MY_TEST((*a)->null_value && (*b)->null_value);
  return MY_TEST(val1 == val2);
}

Project: server

  longlong val_datetime_packed(THD *thd)
  {
    return update_null() ? 0 : cached_time.valid_datetime_to_packed();
  }

Project: server

  Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e)
  {
    arg_count= 5;
    if (likely((args= (Item**) thd_alloc(thd, sizeof(Item*) * 5))))
    {
      arg_count= 5;
      args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
    }
  }

Project: server

Type_handler_hybrid_field_type::aggregate_for_comparison(const char *funcname,
                                                         Item **items,
                                                         uint nitems,
                                                         bool int_uint_as_dec)
{
  uint unsigned_count= items[0]->unsigned_flag;
  /*
    Convert sub-type to super-type (e.g. DATE to DATETIME, INT to BIGINT, etc).
    Otherwise Predicant_to_list_comparator will treat sub-types of the same
    super-type as different data types and won't be able to use bisection in
    many cases.
  */
  set_handler(items[0]->type_handler()->type_handler_for_comparison());
  for (uint i= 1 ; i < nitems ; i++)
  {
    unsigned_count+= items[i]->unsigned_flag;
    if (aggregate_for_comparison(items[i]->type_handler()->
                                 type_handler_for_comparison()))
    {
      /*
        For more precise error messages if aggregation failed on the first pair
        {items[0],items[1]}, use the name of items[0]->data_handler().
        Otherwise use the name of this->type_handler(), which is already a
        result of aggregation for items[0]..items[i-1].
      */
      my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
               i == 1 ? items[0]->type_handler()->name().ptr() :
                        type_handler()->name().ptr(),
               items[i]->type_handler()->name().ptr(),
               funcname);
      return true;
    }
    /*
      When aggregating types of two row expressions we have to check
      that they have the same cardinality and that each component
      of the first row expression has a compatible row signature with
      the signature of the corresponding component of the second row
      expression.
    */ 
    if (cmp_type() == ROW_RESULT && cmp_row_type(items[0], items[i]))
      return true;     // error found: invalid usage of rows
  }
  /**
    If all arguments are of INT type but have different unsigned_flag values,
    switch to DECIMAL_RESULT.
  */
  if (int_uint_as_dec &&
      cmp_type() == INT_RESULT &&
      unsigned_count != nitems && unsigned_count != 0)
    set_handler(&type_handler_newdecimal);
  return 0;
}

Project: server

  TYPELIB *get_typelib() const
  {
    return ref ? (*ref)->get_typelib() : NULL;
  }

Project: server

longlong Item_cond_and::val_int()
{
  DBUG_ASSERT(fixed == 1);
  List_iterator_fast<Item> li(list);
  Item *item;
  null_value= 0;
  while ((item=li++))
  {
    if (!item->val_bool())
    {
      if (abort_on_null || !(null_value= item->null_value))
	return 0;				// return FALSE
    }
  }
  return null_value ? 0 : 1;
}

Project: server

  virtual Item_param *get_item_param() { return 0; }

Project: server

  Item_ref(THD *thd, Name_resolution_context *context_arg,
           const char *db_arg, const char *table_name_arg,
           const LEX_CSTRING *field_name_arg):
    Item_ident(thd, context_arg, db_arg, table_name_arg, field_name_arg),
    set_properties_only(0), ref(0), reference_trough_name(1) {}

Project: server

  virtual longlong val_int_signed_typecast()
  {
    return cast_to_int_type_handler()->Item_val_int_signed_typecast(this);
  }

Project: server

bool Item_in_optimizer::eval_not_null_tables(void *opt_arg)
{
  not_null_tables_cache= 0;
  if (is_top_level_item())
  {
    /*
      It is possible to determine NULL-rejectedness of the left arguments
      of IN only if it is a top-level predicate.
    */
    not_null_tables_cache= args[0]->not_null_tables();
  }
  return FALSE;
}

Project: server

  void copy()
  {
    Timestamp_or_zero_datetime_native_null tmp(current_thd, item, false);
    null_value= tmp.is_null();
    m_value= tmp.is_null() ? Timestamp_or_zero_datetime() :
                             Timestamp_or_zero_datetime(tmp);
  }

Project: server

bool Item_equal::fix_length_and_dec()
{
  Item *item= get_first(NO_PARTICULAR_TAB, NULL);
  const Type_handler *handler= item->type_handler();
  eval_item= handler->make_cmp_item(current_thd, item->collation.collation);
  return eval_item == NULL;
}

Project: server

  bool update_null()
  {
    return maybe_null &&
           (null_value= cached_time.check_date_with_warn(current_thd));
  }

Project: server

  Item_param *get_item_param() { return this; }

Project: server

Item *in_double::create_item(THD *thd)
{ 
  return new (thd->mem_root) Item_float(thd, 0.0, 0);
}

Project: server

  bool send(Protocol *protocol, st_value *buffer)
  {
    return value_item->send(protocol, buffer);
  }

Project: server

  bool check_vcol_func_processor(void *arg)
  {
    context= 0;
    if (field && (field->unireg_check == Field::NEXT_NUMBER))
    {
      // Auto increment fields are unsupported
      return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF | VCOL_AUTO_INC);
    }
    return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF);
  }

Project: server

  Item_float(THD *thd, const char *str, double val_arg, uint decimal_par,
             uint length): Item_num(thd), value(val_arg)
  {
    presentation= name.str= str;
    name.length= safe_strlen(str);
    decimals=(uint8) decimal_par;
    max_length= length;
  }

Project: server

static int cmp_row_type(Item* item1, Item* item2)
{
  uint n= item1->cols();
  if (item2->check_cols(n))
    return 1;
  for (uint i=0; i<n; i++)
  {
    if (item2->element_index(i)->check_cols(item1->element_index(i)->cols()) ||
        (item1->element_index(i)->result_type() == ROW_RESULT &&
         cmp_row_type(item1->element_index(i), item2->element_index(i))))
      return 1;
  }
  return 0;
}

Project: server

  virtual Item *field_transformer_for_having_pushdown(THD *thd, uchar *arg)
  { return this; }

Project: server

  Item_hex_hybrid(THD *thd, const char *str, size_t str_length):
    Item_hex_constant(thd, str, str_length) {}

Project: server

  void print(String *str, enum_query_type query_type)
  {
    str->append(STRING_WITH_LEN("ignore"));
  }

Project: server

  virtual bool check_index_dependence(void *arg) { return 0; }

Project: server

  bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
  { return (*ref)->excl_dep_on_in_subq_left_part(subq_pred); }

Project: server

  Item *get_copy(THD *thd)
  { return get_item_copy<Item_copy_timestamp>(thd, this); }

Project: server

int Arg_comparator::compare_decimal()
{
  VDec val1(*a);
  if (!val1.is_null())
  {
    VDec val2(*b);
    if (!val2.is_null())
    {
      if (set_null)
        owner->null_value= 0;
      val1.round_self_if_needed((*a)->decimals, HALF_UP);
      val2.round_self_if_needed((*b)->decimals, HALF_UP);
      return val1.cmp(val2);
    }
  }
  if (set_null)
    owner->null_value= 1;
  return -1;
}

Project: server

  virtual Item_basic_constant *make_string_literal_concat(THD *thd,
                                                          const LEX_CSTRING *)
  {
    DBUG_ASSERT(0);
    return this;
  }

Project: server

static int cmp_timestamp(void *cmp_arg,
                         Timestamp_or_zero_datetime *a,
                         Timestamp_or_zero_datetime *b)
{
  return a->cmp(*b);
}

Project: server

void Item_func_isnotnull::print(String *str, enum_query_type query_type)
{
  args[0]->print_parenthesised(str, query_type, precedence());
  str->append(STRING_WITH_LEN(" is not null"));
}

Project: server

void cmp_item_timestamp::store_value(Item *item)
{
  item->val_native_with_conversion(current_thd, &m_native,
                                   &type_handler_timestamp2);
  m_null_value= item->null_value;
}

Project: server

  virtual ~Item_const() {}

Project: server

int cmp_item_datetime::cmp(Item *arg)
{
  const bool rc= value != arg->val_datetime_packed(current_thd);
  return (m_null_value || arg->null_value) ? UNKNOWN : rc;
}

Project: server

void Regexp_processor_pcre::pcre_exec_warn(int rc) const
{
  char buf[64];
  const char *errmsg= NULL;
  THD *thd= current_thd;

  /*
    Make a descriptive message only for those pcre_exec() error codes
    that can actually happen in MariaDB.
  */
  switch (rc)
  {
  case PCRE_ERROR_NULL:
    errmsg= "pcre_exec: null argument passed";
    break;
  case PCRE_ERROR_BADOPTION:
    errmsg= "pcre_exec: bad option";
    break;
  case PCRE_ERROR_BADMAGIC:
    errmsg= "pcre_exec: bad magic - not a compiled regex";
    break;
  case PCRE_ERROR_UNKNOWN_OPCODE:
    errmsg= "pcre_exec: error in compiled regex";
    break;
  case PCRE_ERROR_NOMEMORY:
    errmsg= "pcre_exec: Out of memory";
    break;
  case PCRE_ERROR_NOSUBSTRING:
    errmsg= "pcre_exec: no substring";
    break;
  case PCRE_ERROR_MATCHLIMIT:
    errmsg= "pcre_exec: match limit exceeded";
    break;
  case PCRE_ERROR_CALLOUT:
    errmsg= "pcre_exec: callout error";
    break;
  case PCRE_ERROR_BADUTF8:
    errmsg= "pcre_exec: Invalid utf8 byte sequence in the subject string";
    break;
  case PCRE_ERROR_BADUTF8_OFFSET:
    errmsg= "pcre_exec: Started at invalid location within utf8 byte sequence";
    break;
  case PCRE_ERROR_PARTIAL:
    errmsg= "pcre_exec: partial match";
    break;
  case PCRE_ERROR_INTERNAL:
    errmsg= "pcre_exec: internal error";
    break;
  case PCRE_ERROR_BADCOUNT:
    errmsg= "pcre_exec: ovesize is negative";
    break;
  case PCRE_ERROR_RECURSIONLIMIT:
    my_snprintf(buf, sizeof(buf), "pcre_exec: recursion limit of %ld exceeded",
                m_pcre_extra.match_limit_recursion);
    errmsg= buf;
    break;
  case PCRE_ERROR_BADNEWLINE:
    errmsg= "pcre_exec: bad newline options";
    break;
  case PCRE_ERROR_BADOFFSET:
    errmsg= "pcre_exec: start offset negative or greater than string length";
    break;
  case PCRE_ERROR_SHORTUTF8:
    errmsg= "pcre_exec: ended in middle of utf8 sequence";
    break;
  case PCRE_ERROR_JIT_STACKLIMIT:
    errmsg= "pcre_exec: insufficient stack memory for JIT compile";
    break;
  case PCRE_ERROR_RECURSELOOP:
    errmsg= "pcre_exec: Recursion loop detected";
    break;
  case PCRE_ERROR_BADMODE:
    errmsg= "pcre_exec: compiled pattern passed to wrong bit library function";
    break;
  case PCRE_ERROR_BADENDIANNESS:
    errmsg= "pcre_exec: compiled pattern passed to wrong endianness processor";
    break;
  case PCRE_ERROR_JIT_BADOPTION:
    errmsg= "pcre_exec: bad jit option";
    break;
  case PCRE_ERROR_BADLENGTH:
    errmsg= "pcre_exec: negative length";
    break;
  default:
    /*
      As other error codes should normally not happen,
      we just report the error code without textual description
      of the code.
    */
    my_snprintf(buf, sizeof(buf), "pcre_exec: Internal error (%d)", rc);
    errmsg= buf;
  }
  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
                      ER_REGEXP_ERROR, ER_THD(thd, ER_REGEXP_ERROR), errmsg);
}

Project: server

void Item_in_optimizer::print(String *str, enum_query_type query_type)
{
  if (query_type & QT_PARSABLE)
    args[1]->print(str, query_type);
  else
  {
     restore_first_argument();
     Item_func::print(str, query_type);
  }
}

Project: server

  void quick_fix_field()
  {
    /*
      We can get here when Item_bool is created instead of a constant
      predicate at various condition optimization stages in sql_select.
    */
  }

Project: server

void Item_func_not_all::print(String *str, enum_query_type query_type)
{
  if (show)
    Item_func::print(str, query_type);
  else
    args[0]->print(str, query_type);
}

Project: server

bool cmp_item_row::
      aggregate_row_elements_for_comparison(THD *thd,
                                            Type_handler_hybrid_field_type *cmp,
                                            Item_args *tmp,
                                            const char *funcname,
                                            uint col,
                                            uint level)
{
  DBUG_EXECUTE_IF("cmp_item",
  {
    for (uint i= 0 ; i < tmp->argument_count(); i++)
    {
      Item *arg= tmp->arguments()[i];
      push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
                          ER_UNKNOWN_ERROR, "DBUG: %s[%d,%d] handler=%s",
                          String_space(level).c_ptr(), col, i,
                          arg->type_handler()->name().ptr());
    }
  }
  );
  bool err= cmp->aggregate_for_comparison(funcname, tmp->arguments(),
                                          tmp->argument_count(), true);
  DBUG_EXECUTE_IF("cmp_item",
  {
    if (!err)
      push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
                          ER_UNKNOWN_ERROR, "DBUG: %s=> handler=%s",
                          String_space(level).c_ptr(),
                          cmp->type_handler()->name().ptr());
  }
  );
  return err;
}

Project: server

bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
{
  DBUG_ASSERT(fixed == 0);
  Item_subselect *sub= 0;
  uint col;

  /*
     MAX/MIN optimization can convert the subquery into
     expr + Item_singlerow_subselect
   */
  if (args[1]->type() == Item::SUBSELECT_ITEM)
    sub= (Item_subselect *)args[1];

  if (fix_left(thd))
    return TRUE;
  if (args[0]->maybe_null)
    maybe_null=1;

  if (args[1]->fix_fields_if_needed(thd, args + 1))
    return TRUE;
  if (!invisible_mode() &&
      ((sub && ((col= args[0]->cols()) != sub->engine->cols())) ||
       (!sub && (args[1]->cols() != (col= 1)))))
  {
    my_error(ER_OPERAND_COLUMNS, MYF(0), col);
    return TRUE;
  }
  if (args[1]->maybe_null)
    maybe_null=1;
  m_with_subquery= true;
  join_with_sum_func(args[1]);
  with_window_func= args[0]->with_window_func;
  // The subquery cannot have window functions aggregated in this select
  DBUG_ASSERT(!args[1]->with_window_func);
  with_field= with_field || args[1]->with_field;
  with_param= args[0]->with_param || args[1]->with_param; 
  used_tables_and_const_cache_join(args[1]);
  fixed= 1;
  return FALSE;
}

Project: server

uchar *in_time::get_value(Item *item)
{
  tmp.val= item->val_time_packed(current_thd);
  if (item->null_value)
    return 0;
  tmp.unsigned_flag= 1L;
  return (uchar*) &tmp;
}

Project: server

  const Type_handler *cast_to_int_type_handler() const
  {
    return real_type_handler()->cast_to_int_type_handler();
  }

Project: server

uchar *in_string::get_value(Item *item)
{
  return (uchar*) item->val_str(&tmp);
}

Project: server

bool Arg_comparator::set_cmp_func_int()
{
  THD *thd= current_thd;
  func= is_owner_equal_func() ? &Arg_comparator::compare_e_int :
                                &Arg_comparator::compare_int_signed;
  if ((*a)->field_type() == MYSQL_TYPE_YEAR &&
      (*b)->field_type() == MYSQL_TYPE_YEAR)
  {
    func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime :
                                  &Arg_comparator::compare_datetime;
  }
  else if (func == &Arg_comparator::compare_int_signed)
  {
    if ((*a)->unsigned_flag)
      func= (((*b)->unsigned_flag)?
             &Arg_comparator::compare_int_unsigned :
             &Arg_comparator::compare_int_unsigned_signed);
    else if ((*b)->unsigned_flag)
      func= &Arg_comparator::compare_int_signed_unsigned;
  }
  else if (func== &Arg_comparator::compare_e_int)
  {
    if ((*a)->unsigned_flag ^ (*b)->unsigned_flag)
      func= &Arg_comparator::compare_e_int_diff_signedness;
  }
  a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
  b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
  return false;
}

Project: server

void Item_in_optimizer::cleanup()
{
  DBUG_ENTER("Item_in_optimizer::cleanup");
  Item_bool_func::cleanup();
  if (!save_cache)
    cache= 0;
  expr_cache= 0;
  DBUG_VOID_RETURN;
}

Project: server

  bool is_longlong() const
  {
    return m_type == DYN_COL_UINT || m_type == DYN_COL_INT;
  }

Project: server

  const my_decimal *const_ptr_my_decimal() const
  { return can_return_const_value(DECIMAL_RESULT) ? &value.m_decimal : NULL; }

Project: server

  String *val_str(String *to)
  {
    return m_value.to_datetime(current_thd).to_string(to, decimals);
  }

Project: server

  With_sum_func_cache* get_with_sum_func_cache() { return this; }

Project: server

  Item *get_copy(THD *thd)
  { return get_item_copy<Item_time_literal>(thd, this); }

Project: server

  double val_real() { return value; }

Project: server

  bool has_int_value() const
  {
    return state == SHORT_DATA_VALUE &&
           value.type_handler()->cmp_type() == INT_RESULT;
  }

Project: server

  bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
  {
    return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
  }

Project: server

  virtual longlong val_time_packed(THD *thd)
  {
    return Time(thd, this, Time::Options_cmp(thd)).to_packed();
  }

Project: server

int Arg_comparator::compare_real()
{
  /*
    Fix yet another manifestation of Bug#2338. 'Volatile' will instruct
    gcc to flush double values out of 80-bit Intel FPU registers before
    performing the comparison.
  */
  volatile double val1, val2;
  val1= (*a)->val_real();
  if (!(*a)->null_value)
  {
    val2= (*b)->val_real();
    if (!(*b)->null_value)
    {
      if (set_null)
        owner->null_value= 0;
      if (val1 < val2)	return -1;
      if (val1 == val2) return 0;
      return 1;
    }
  }
  if (set_null)
    owner->null_value= 1;
  return -1;
}

Project: server

  With_sum_func_cache()
   :m_with_sum_func(false)
  { }

Project: server

  longlong val_datetime_packed(THD *thd)
  {
    return update_null() ? 0 : cached_time.valid_date_to_packed();
  }

Project: server

  bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
  {
    illegal_method_call((const char*)"val_decimal");
    return true;
  }

Project: server

  Item *get_copy(THD *thd)
  { return get_item_copy<Item_ref>(thd, this); }

Project: server

  String *val_str(String *to) { return decimal_value.to_string(to); }

Project: server

  bool is_double() const { return m_type == DYN_COL_DOUBLE; }

Project: server

  Item_hex_constant(THD *thd): Item_literal(thd)
  {
    hex_string_init(thd, "", 0);
  }

Project: server

int Item_func_nullif::compare()
{
  if (m_cache)
    m_cache->cache_value();
  return cmp.compare();
}

Project: server

bool cmp_item_row::prepare_comparators(THD *thd, const char *funcname,
                                       const Item_args *args, uint level)
{
  DBUG_EXECUTE_IF("cmp_item",
                  push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
                  ER_UNKNOWN_ERROR, "DBUG: %sROW(%d args) level=%d",
                  String_space(level).c_ptr(),
                  args->argument_count(), level););
  DBUG_ASSERT(args->argument_count() > 0);
  if (alloc_comparators(thd, args->arguments()[0]->cols()))
    return true;
  DBUG_ASSERT(n == args->arguments()[0]->cols());
  for (uint col= 0; col < n; col++)
  {
    Item_args tmp;
    Type_handler_hybrid_field_type cmp;

    if (tmp.alloc_and_extract_row_elements(thd, args, col) ||
        aggregate_row_elements_for_comparison(thd, &cmp, &tmp,
                                              funcname, col, level + 1))
      return true;

    /*
      There is a legacy bug (MDEV-11511) in the code below,
      which should be fixed eventually.
      When performing:
       (predicant0,predicant1) IN ((value00,value01),(value10,value11))
      It uses only the data type and the collation of the predicant
      elements only. It should be fixed to take into account the data type and
      the collation for all elements at the N-th positions of the
      predicate and all values:
      - predicate0, value00, value01
      - predicate1, value10, value11
    */
    Item *item0= args->arguments()[0]->element_index(col);
    CHARSET_INFO *collation= item0->collation.collation;
    if (!(comparators[col]= cmp.type_handler()->make_cmp_item(thd, collation)))
      return true;
    if (cmp.type_handler() == &type_handler_row)
    {
      // Prepare comparators for ROW elements recursively
      cmp_item_row *row= static_cast<cmp_item_row*>(comparators[col]);
      if (row->prepare_comparators(thd, funcname, &tmp, level + 1))
        return true;
    }
  }
  return false;
}

Project: server

void Item_func_isnull::print(String *str, enum_query_type query_type)
{
  if (const_item() && !args[0]->maybe_null &&
      !(query_type & (QT_NO_DATA_EXPANSION | QT_VIEW_INTERNAL)))
    str->append("/*always not null*/ 1");
  else
    args[0]->print_parenthesised(str, query_type, precedence());
  str->append(STRING_WITH_LEN(" is null"));
}

Project: server

  With_subquery_cache(): m_with_subquery(false) { }

Project: server

Item_func_nullif::int_op()
{
  DBUG_ASSERT(fixed == 1);
  longlong value;
  if (!compare())
  {
    null_value=1;
    return 0;
  }
  value= args[2]->val_int();
  null_value= args[2]->null_value;
  return value;
}

Project: server

  virtual Item *get_item() { return example; }

Project: server

  void set_geometry_type(uint type)
  {
    DBUG_ASSERT(type <= m_geometry_type_unknown);
    m_geometry_type= type;
  }

Project: server

  Field *field() const { return m_field; }

Project: server

  Field *create_field_for_create_select(TABLE *table)
  { return create_table_field_from_handler(table); }

Project: server

in_string::in_string(THD *thd, uint elements, qsort2_cmp cmp_func,
                     CHARSET_INFO *cs)
  :in_vector(thd, elements, sizeof(String), cmp_func, cs),
   tmp(buff, sizeof(buff), &my_charset_bin)
{}

Project: server

  my_decimal *val_decimal(my_decimal *to) { return cached_time.to_decimal(to); }

Project: server

void Item_func_not::print(String *str, enum_query_type query_type)
{
  str->append('!');
  args[0]->print_parenthesised(str, query_type, precedence());
}

Project: server

  With_sum_func_cache(const Item *a, const Item *b, const Item *c)
   :m_with_sum_func(a->with_sum_func() || b->with_sum_func() ||
                    c->with_sum_func())
  { }

Project: server

  const Type_handler *type_handler() const
  {
    DBUG_ASSERT(0);
    return &type_handler_null;
  }

Project: server

  uint decimal_scale() const
  {
    return type_handler()->Item_decimal_scale(this);
  }

Project: server

  Type_geometry_attributes(const Type_handler *handler,
                           const Type_all_attributes *gattr)
   :m_geometry_type(m_geometry_type_unknown)
  {
    copy(handler, gattr);
  }

Project: server

  const Type_handler *type_handler() const { return (*ref)->type_handler(); }

Project: server

Item_bool_rowready_func2 *Eq_creator::create(THD *thd, Item *a, Item *b) const
{
  return new(thd->mem_root) Item_func_eq(thd, a, b);
}

Project: server

longlong Item_func_between::val_int_cmp_datetime()
{
  THD *thd= current_thd;
  longlong value= args[0]->val_datetime_packed(thd), a, b;
  if ((null_value= args[0]->null_value))
    return 0;
  a= args[1]->val_datetime_packed(thd);
  b= args[2]->val_datetime_packed(thd);
  return val_int_cmp_int_finalize(value, a, b);
}

Project: server

inline void TABLE::mark_virtual_column_deps(Field *field)
{
  DBUG_ASSERT(field->vcol_info);
  DBUG_ASSERT(field->vcol_info->expr);
  field->vcol_info->expr->walk(&Item::register_field_in_read_map, 1, 0);
}

Project: server

int cmp_item_timestamp::compare(cmp_item *arg)
{
  cmp_item_timestamp *tmp= static_cast<cmp_item_timestamp*>(arg);
  return type_handler_timestamp2.cmp_native(m_native, tmp->m_native);
}

Project: server

  void copy(const Type_handler *handler, const Type_all_attributes *gattr)
  {
    // Ignore implicit NULLs
    m_geometry_type= handler == &type_handler_geometry ?
                     gattr->uint_geometry_type() :
                     m_geometry_type_unknown;
  }

Project: server

bool Item_func_in::fix_for_row_comparison_using_bisection(THD *thd)
{
  if (unlikely(!(array= new (thd->mem_root) in_row(thd, arg_count-1, 0))))
    return true;
  cmp_item_row *cmp= &((in_row*)array)->tmp;
  if (cmp->prepare_comparators(thd, func_name(), this, 0))
    return true;
  fix_in_vector();
  return false;
}

Project: server

int Arg_comparator::compare_int_signed_unsigned()
{
  longlong sval1= (*a)->val_int();
  if (!(*a)->null_value)
  {
    ulonglong uval2= (ulonglong)(*b)->val_int();
    if (!(*b)->null_value)
    {
      if (set_null)
        owner->null_value= 0;
      if (sval1 < 0 || (ulonglong)sval1 < uval2)
        return -1;
      if ((ulonglong)sval1 == uval2)
        return 0;
      return 1;
    }
  }
  if (set_null)
    owner->null_value= 1;
  return -1;
}

Project: server

  virtual Item* build_clone(THD *thd) { return get_copy(thd); }