Commit ca8be36f authored by unknown's avatar unknown
Browse files

Merge bk-internal.mysql.com:/home/bk/mysql-4.1

into mysql.com:/media/sda1/mysql/mysql-4.1-6050


sql/sql_class.h:
  Auto merged
parents 76b09dd5 4512a46e
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -375,3 +375,38 @@ rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as
-	9647622201	3845601374	6211931236
drop table t1;
deallocate prepare stmt;
create database mysqltest1;
create table t1 (a int);
create table mysqltest1.t1 (a int);
select * from t1, mysqltest1.t1;
a	a
prepare stmt from "select * from t1, mysqltest1.t1";
execute stmt;
a	a
execute stmt;
a	a
execute stmt;
a	a
drop table t1;
drop table mysqltest1.t1;
drop database mysqltest1;
deallocate prepare stmt;
select '1.1' as a, '1.2' as a UNION SELECT '2.1', '2.2';
a	a
1.1	1.2
2.1	2.2
prepare stmt from
"select '1.1' as a, '1.2' as a UNION SELECT '2.1', '2.2'";
execute stmt;
a	a
1.1	1.2
2.1	2.2
execute stmt;
a	a
1.1	1.2
2.1	2.2
execute stmt;
a	a
1.1	1.2
2.1	2.2
deallocate prepare stmt;
+1 −1
Original line number Diff line number Diff line
@@ -184,7 +184,7 @@ f3 int
);
insert into t5( f1, f2, f3) values( 9, 'recreated table', 9);
execute stmt2 ;
ERROR 42S22: Unknown column 't5.a' in 'field list'
ERROR 42S22: Unknown column 'test.t5.a' in 'field list'
drop table t5 ;
prepare stmt1 from ' select * from t1 where a <= 2 ' ;
execute stmt1 ;
+25 −0
Original line number Diff line number Diff line
@@ -390,3 +390,28 @@ set @var=3;
execute stmt using @var;
drop table t1;
deallocate prepare stmt;

#
# A test case for Bug#6050 "EXECUTE stmt reports ambiguous fieldnames with
# identical tables from different schemata"
# Check that field name resolving in prepared statements works OK.
#
create database mysqltest1;
create table t1 (a int);
create table mysqltest1.t1 (a int);
select * from t1, mysqltest1.t1;
prepare stmt from "select * from t1, mysqltest1.t1";
execute stmt;
execute stmt;
execute stmt;
drop table t1;
drop table mysqltest1.t1;
drop database mysqltest1;
deallocate prepare stmt; 
select '1.1' as a, '1.2' as a UNION SELECT '2.1', '2.2';
prepare stmt from
"select '1.1' as a, '1.2' as a UNION SELECT '2.1', '2.2'";
execute stmt;
execute stmt;
execute stmt;
deallocate prepare stmt;
+30 −9
Original line number Diff line number Diff line
@@ -348,17 +348,39 @@ Item_field::Item_field(Field *f)
  :Item_ident(NullS, f->table_name, f->field_name)
{
  set_field(f);
  collation.set(DERIVATION_IMPLICIT);
  fixed= 1;
  /*
    field_name and talbe_name should not point to garbage
    if this item is to be reused
  */
  orig_table_name= orig_field_name= "";
}

Item_field::Item_field(THD *thd, Field *f)
  :Item_ident(NullS, thd->strdup(f->table_name), 
              thd->strdup(f->field_name))
  :Item_ident(f->table->table_cache_key, f->table_name, f->field_name)
{
  /*
    We always need to provide Item_field with a fully qualified field
    name to avoid ambiguity when executing prepared statements like
    SELECT * from d1.t1, d2.t1; (assuming d1.t1 and d2.t1 have columns
    with same names).
    This is because prepared statements never deal with wildcards in
    select list ('*') and always fix fields using fully specified path
    (i.e. db.table.column).
    No check for OOM: if db_name is NULL, we'll just get
    "Field not found" error.
    We need to copy db_name, table_name and field_name because they must
    be allocated in the statement memory, not in table memory (the table
    structure can go away and pop up again between subsequent executions
    of a prepared statement).
  */
  if (thd->current_arena->is_stmt_prepare())
  {
    if (db_name)
      orig_db_name= thd->strdup(db_name);
    orig_table_name= thd->strdup(table_name);
    orig_field_name= thd->strdup(field_name);
  }
  set_field(f);
  collation.set(DERIVATION_IMPLICIT);
  fixed= 1;
}

// Constructor need to process subselect with temporary tables (see Item)
@@ -381,6 +403,7 @@ void Item_field::set_field(Field *field_par)
  db_name=field_par->table->table_cache_key;
  unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
  collation.set(field_par->charset(), DERIVATION_IMPLICIT);
  fixed= 1;
}

const char *Item_ident::full_name() const
@@ -1374,8 +1397,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
    field->query_id=thd->query_id;
    table->used_fields++;
    table->used_keys.intersect(field->part_of_key);
  }
    fixed= 1;
  }
  return 0;
}

@@ -2120,7 +2143,6 @@ bool Item_default_value::fix_fields(THD *thd,
  def_field->move_field(def_field->table->default_values -
                        def_field->table->record[0]);
  set_field(def_field);
  fixed= 1;
  return 0;
}

@@ -2178,7 +2200,6 @@ bool Item_insert_value::fix_fields(THD *thd,
    set_field(new Field_null(0, 0, Field::NONE, tmp_field->field_name,
			     tmp_field->table, &my_charset_bin));
  }
  fixed= 1;
  return 0;
}

+13 −4
Original line number Diff line number Diff line
@@ -310,6 +310,7 @@ class Item_num: public Item
class st_select_lex;
class Item_ident :public Item
{
protected:
  /* 
    We have to store initial values of db_name, table_name and field_name
    to be able to restore them during cleanup() because they can be 
@@ -347,7 +348,6 @@ class Item_ident :public Item

class Item_field :public Item_ident
{
  void set_field(Field *field);
public:
  Field *field,*result_field;

@@ -356,13 +356,21 @@ class Item_field :public Item_ident
    :Item_ident(db_par,table_name_par,field_name_par),
     field(0), result_field(0)
  { collation.set(DERIVATION_IMPLICIT); }
  // Constructor need to process subselect with temporary tables (see Item)
  /*
    Constructor needed to process subselect with temporary tables (see Item)
  */
  Item_field(THD *thd, Item_field *item);
  /*
    Constructor used inside setup_wild(), ensures that field and table
    names will live as long as Item_field (important in prep. stmt.)
    Constructor used inside setup_wild(), ensures that field, table,
    and database names will live as long as Item_field (this is important
    in prepared statements).
  */
  Item_field(THD *thd, Field *field);
  /*
    If this constructor is used, fix_fields() won't work, because
    db_name, table_name and column_name are unknown. It's necessary to call
    set_field() before fix_fields() for all fields created this way.
  */
  Item_field(Field *field);
  enum Type type() const { return FIELD_ITEM; }
  bool eq(const Item *item, bool binary_cmp) const;
@@ -373,6 +381,7 @@ class Item_field :public Item_ident
  longlong val_int_result();
  String *str_result(String* tmp);
  bool send(Protocol *protocol, String *str_arg);
  void set_field(Field *field);
  bool fix_fields(THD *, struct st_table_list *, Item **);
  void make_field(Send_field *tmp_field);
  int save_in_field(Field *field,bool no_conversions);
Loading