Commit 6e91d6a8 authored by peter@mysql.com's avatar peter@mysql.com

Merge mysql.com:/home/pz/mysql/mysql-4.1-root

into mysql.com:/home/pz/mysql/mysql-4.1
parents ba8c05da 40c0fd1c
This diff is collapsed.
......@@ -21,7 +21,8 @@ static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
ulong max_records);
int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
uint reclength, ulong max_records, ulong min_records)
uint reclength, ulong max_records, ulong min_records,
HP_CREATE_INFO *create_info)
{
uint i, j, key_segs, max_length, length;
HP_SHARE *share;
......@@ -120,6 +121,9 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
share->keys= keys;
share->max_key_length= max_length;
share->changed= 0;
share->auto_key= create_info->auto_key;
share->auto_key_type= create_info->auto_key_type;
share->auto_increment= create_info->auto_increment;
if (!(share->name= my_strdup(name,MYF(0))))
{
my_free((gptr) share,MYF(0));
......
......@@ -537,3 +537,51 @@ my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record)
}
return 0;
}
void heap_update_auto_increment(HP_INFO *info, const byte *record)
{
ulonglong value;
HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg;
const uchar *key= (uchar*) record + keyseg->start;
switch (info->s->auto_key_type) {
case HA_KEYTYPE_INT8:
case HA_KEYTYPE_BINARY:
value= (ulonglong) *(uchar*) key;
break;
case HA_KEYTYPE_SHORT_INT:
case HA_KEYTYPE_USHORT_INT:
value= (ulonglong) uint2korr(key);
break;
case HA_KEYTYPE_LONG_INT:
case HA_KEYTYPE_ULONG_INT:
value= (ulonglong) uint4korr(key);
break;
case HA_KEYTYPE_INT24:
case HA_KEYTYPE_UINT24:
value= (ulonglong) uint3korr(key);
break;
case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
{
float f_1;
float4get(f_1, key);
value= (ulonglong) f_1;
break;
}
case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */
{
double f_1;
float8get(f_1, key);
value= (ulonglong) f_1;
break;
}
case HA_KEYTYPE_LONGLONG:
case HA_KEYTYPE_ULONGLONG:
value= uint8korr(key);
break;
default:
value= 0; /* Error */
break;
}
set_if_bigger(info->s->auto_increment, value);
}
......@@ -55,5 +55,7 @@ int heap_info(reg1 HP_INFO *info,reg2 HEAPINFO *x,
x->index_length= info->s->index_length;
x->max_records = info->s->max_records;
x->errkey = info->errkey;
if (flag & HA_STATUS_AUTO)
x->auto_increment= info->s->auto_increment + 1;
DBUG_RETURN(0);
} /* heap_info */
......@@ -37,11 +37,14 @@ int main(int argc, char **argv)
const char *filename;
HP_KEYDEF keyinfo[10];
HA_KEYSEG keyseg[4];
HP_CREATE_INFO hp_create_info;
MY_INIT(argv[0]);
filename= "test1";
get_options(argc,argv);
bzero(&hp_create_info, sizeof(hp_create_info));
keyinfo[0].keysegs=1;
keyinfo[0].seg=keyseg;
keyinfo[0].algorithm= HA_KEY_ALG_HASH;
......@@ -55,7 +58,8 @@ int main(int argc, char **argv)
bzero((gptr) flags,sizeof(flags));
printf("- Creating heap-file\n");
if (heap_create(filename,1,keyinfo,30,(ulong) flag*100000l,10l) ||
if (heap_create(filename,1,keyinfo,30,(ulong) flag*100000l,10l,
&hp_create_info) ||
!(file= heap_open(filename, 2)))
goto err;
printf("- Writing records:s\n");
......
......@@ -63,6 +63,7 @@ int main(int argc, char *argv[])
HP_KEYDEF keyinfo[MAX_KEYS];
HA_KEYSEG keyseg[MAX_KEYS*5];
HEAP_PTR position;
HP_CREATE_INFO hp_create_info;
MY_INIT(argv[0]); /* init my_sys library & pthreads */
LINT_INIT(position);
......@@ -71,6 +72,8 @@ int main(int argc, char *argv[])
file=file2=0;
get_options(argc,argv);
bzero(&hp_create_info, sizeof(hp_create_info));
write_count=update=opt_delete=0;
key_check=0;
......@@ -122,7 +125,7 @@ int main(int argc, char *argv[])
printf("- Creating heap-file\n");
if (heap_create(filename,keys,keyinfo,reclength,(ulong) flag*100000L,
(ulong) recant/2) ||
(ulong) recant/2, &hp_create_info) ||
!(file= heap_open(filename, 2)))
goto err;
signal(SIGINT,endprog);
......@@ -557,7 +560,7 @@ int main(int argc, char *argv[])
heap_close(file2);
printf("- Creating output heap-file 2\n");
if (heap_create(filename2,1,keyinfo,reclength,0L,0L) ||
if (heap_create(filename2,1,keyinfo,reclength,0L,0L,&hp_create_info) ||
!(file2= heap_open(filename2, 2)))
goto err;
......
......@@ -22,7 +22,8 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
{
HP_KEYDEF *keydef, *end, *p_lastinx;
byte *pos;
HP_SHARE *share=info->s;
bool auto_key_changed= 0;
HP_SHARE *share= info->s;
DBUG_ENTER("heap_update");
test_active(info);
......@@ -33,20 +34,23 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
if (--(share->records) < share->blength >> 1) share->blength>>= 1;
share->changed=1;
p_lastinx = share->keydef + info->lastinx;
for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
keydef++)
p_lastinx= share->keydef + info->lastinx;
for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++)
{
if (hp_rec_key_cmp(keydef, old, heap_new))
{
if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) ||
(*keydef->write_key)(info, keydef, heap_new, pos))
goto err;
if (share->auto_key == (uint) (keydef - share->keydef + 1))
auto_key_changed= 1;
}
}
memcpy(pos,heap_new,(size_t) share->reclength);
if (++(share->records) == share->blength) share->blength+= share->blength;
if (auto_key_changed)
heap_update_auto_increment(info, heap_new);
DBUG_RETURN(0);
err:
......
......@@ -61,6 +61,8 @@ int heap_write(HP_INFO *info, const byte *record)
info->current_ptr=pos;
info->current_hash_ptr=0;
info->update|=HA_STATE_AKTIV;
if (share->auto_key)
heap_update_auto_increment(info, record);
DBUG_RETURN(0);
err:
DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef));
......
......@@ -50,6 +50,7 @@ typedef struct st_heapinfo /* Struct from heap_info */
ulong index_length;
uint reclength; /* Length of one record */
int errkey;
ulonglong auto_increment;
} HEAPINFO;
......@@ -115,6 +116,9 @@ typedef struct st_heap_share
#endif
my_bool delete_on_close;
LIST open_list;
uint auto_key;
uint auto_key_type; /* real type of the auto key segment */
ulonglong auto_increment;
} HP_SHARE;
struct st_hp_hash_info;
......@@ -140,6 +144,13 @@ typedef struct st_heap_info
LIST open_list;
} HP_INFO;
typedef struct st_heap_create_info
{
uint auto_key;
uint auto_key_type;
ulonglong auto_increment;
} HP_CREATE_INFO;
/* Prototypes for heap-functions */
extern HP_INFO *heap_open(const char *name, int mode);
......@@ -152,7 +163,8 @@ extern int heap_scan(register HP_INFO *info, byte *record);
extern int heap_delete(HP_INFO *info,const byte *buff);
extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag);
extern int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
uint reclength, ulong max_records, ulong min_records);
uint reclength, ulong max_records, ulong min_records,
HP_CREATE_INFO *create_info);
extern int heap_delete_table(const char *name);
extern int heap_extra(HP_INFO *info,enum ha_extra_function function);
extern int heap_rename(const char *old_name,const char *new_name);
......@@ -163,7 +175,7 @@ extern int heap_rprev(HP_INFO *info,byte *record);
extern int heap_rfirst(HP_INFO *info,byte *record,int inx);
extern int heap_rlast(HP_INFO *info,byte *record,int inx);
extern void heap_clear(HP_INFO *info);
extern void heap_update_auto_increment(HP_INFO *info, const byte *record);
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, const byte *start_key,
uint start_key_len,
enum ha_rkey_function start_search_flag,
......
......@@ -139,14 +139,14 @@ id parent_id level
1015 102 2
1010 102 2
explain select level from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used; Using index
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref level level 1 const 1 where used; Using index
explain select level,id from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used; Using index
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref level level 1 const 1 where used; Using index
explain select level,id,parent_id from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref level level 1 const 1 where used
select level,id from t1 where level=1;
level id
1 1002
......@@ -624,8 +624,8 @@ id parent_id level
1025 102 2
1016 102 2
explain select level from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used; Using index
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref level level 1 const 1 where used; Using index
select level,id from t1 where level=1;
level id
1 1004
......
......@@ -22,14 +22,13 @@ drop table if exists t1,t2;
create table t1 (b char(0) not null, index(b));
The used table handler can't index column 'b'
create table t1 (a int not null auto_increment,primary key (a)) type=heap;
The used table type doesn't support AUTO_INCREMENT columns
create table t1 (a int not null,b text) type=heap;
The used table type doesn't support BLOB/TEXT columns
create table t1 (a int ,primary key(a)) type=heap;
All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead
drop table if exists t1;
create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
The used table type doesn't support AUTO_INCREMENT columns
Incorrect table definition; There can only be one auto column and it must be defined as a key
create table t1 (ordid int(8), primary key (ordid));
All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead
create table not_existing_database.test (a int);
......
drop table if exists t1;
create table t1 (a int not null auto_increment,b int, primary key (a)) type=heap auto_increment=3;
insert into t1 values (1,1),(NULL,3),(NULL,4);
delete from t1 where a=4;
insert into t1 values (NULL,5),(NULL,6);
select * from t1;
a b
1 1
3 3
5 5
6 6
delete from t1 where a=6;
replace t1 values (3,1);
ALTER TABLE t1 add c int;
replace t1 values (3,3,3);
insert into t1 values (NULL,7,7);
update t1 set a=8,b=b+1,c=c+1 where a=7;
insert into t1 values (NULL,9,9);
select * from t1;
a b c
1 1 NULL
3 3 3
5 5 NULL
8 8 8
9 9 9
drop table t1;
create table t1 (
skey tinyint unsigned NOT NULL auto_increment PRIMARY KEY,
sval char(20)
) type=heap;
insert into t1 values (NULL, "hello");
insert into t1 values (NULL, "hey");
select * from t1;
skey sval
1 hello
2 hey
select _rowid,t1._rowid,skey,sval from t1;
_rowid _rowid skey sval
1 1 1 hello
2 2 2 hey
drop table t1;
select (select 2);
(select 2)
2
drop table if exists t1,t2,t3,t4,t5,attend,clinic;
drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
create table t1 (a int);
create table t2 (a int, b int);
create table t3 (a int);
......@@ -131,6 +131,8 @@ patient_uq clinic_uq
1 1
1 2
2 2
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
Column: 'a' in field list is ambiguous
drop table if exists t1,t2,t3;
CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0');
INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b');
......@@ -147,4 +149,16 @@ W 1
SELECT * FROM t3 WHERE b = (SELECT MIN(b) FROM t3);
a b
W a
drop table t1,t2,t3,t4,t5,attend,clinic;
drop table if exists inscrit;
CREATE TABLE `inscrit` (
`pseudo` varchar(35) character set latin1 NOT NULL default '',
`email` varchar(60) character set latin1 NOT NULL default '',
PRIMARY KEY (`pseudo`),
UNIQUE KEY `email` (`email`)
) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
INSERT INTO inscrit (pseudo,email) VALUES ('joce','test');
INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1');
INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1');
SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%');
Subselect returns more than 1 record
drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
......@@ -22,12 +22,12 @@ drop table if exists t1;
!$1146 create table t2 select auto+1 from t1;
drop table if exists t1,t2;
!$1167 create table t1 (b char(0) not null, index(b));
!$1164 create table t1 (a int not null auto_increment,primary key (a)) type=heap;
create table t1 (a int not null auto_increment,primary key (a)) type=heap;
!$1163 create table t1 (a int not null,b text) type=heap;
!$1171 create table t1 (a int ,primary key(a)) type=heap;
drop table if exists t1;
!$1164 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
!$1075 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
!$1171 create table t1 (ordid int(8), primary key (ordid));
-- error 1044,1
......
#
# Test of auto_increment; The test for BDB tables is in bdb.test
#
drop table if exists t1;
create table t1 (a int not null auto_increment,b int, primary key (a)) type=heap auto_increment=3;
insert into t1 values (1,1),(NULL,3),(NULL,4);
delete from t1 where a=4;
insert into t1 values (NULL,5),(NULL,6);
select * from t1;
delete from t1 where a=6;
#show table status like "t1";
replace t1 values (3,1);
ALTER TABLE t1 add c int;
replace t1 values (3,3,3);
insert into t1 values (NULL,7,7);
update t1 set a=8,b=b+1,c=c+1 where a=7;
insert into t1 values (NULL,9,9);
select * from t1;
drop table t1;
create table t1 (
skey tinyint unsigned NOT NULL auto_increment PRIMARY KEY,
sval char(20)
) type=heap;
insert into t1 values (NULL, "hello");
insert into t1 values (NULL, "hey");
select * from t1;
select _rowid,t1._rowid,skey,sval from t1;
drop table t1;
select (select 2);
drop table if exists t1,t2,t3,t4,t5,attend,clinic;
drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
create table t1 (a int);
create table t2 (a int, b int);
create table t3 (a int);
......@@ -53,6 +53,10 @@ insert into clinic values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta"
insert into attend values (1,1),(1,2),(2,2),(1,3);
select * from attend where exists (select * from clinic where uq = clinic_uq);
# not unique fields
-- error 1052
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
# different tipes & group functions
drop table if exists t1,t2,t3;
......@@ -66,4 +70,19 @@ SELECT * FROM t1 WHERE b = (SELECT MIN(b) FROM t1);
SELECT * FROM t2 WHERE b = (SELECT MIN(b) FROM t2);
SELECT * FROM t3 WHERE b = (SELECT MIN(b) FROM t3);
drop table t1,t2,t3,t4,t5,attend,clinic;
drop table if exists inscrit;
CREATE TABLE `inscrit` (
`pseudo` varchar(35) character set latin1 NOT NULL default '',
`email` varchar(60) character set latin1 NOT NULL default '',
PRIMARY KEY (`pseudo`),
UNIQUE KEY `email` (`email`)
) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
INSERT INTO inscrit (pseudo,email) VALUES ('joce','test');
INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1');
INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1');
-- error 1240
SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%');
drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
\ No newline at end of file
......@@ -35,7 +35,9 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
{
if (!(file= heap_open(name, mode)) && my_errno == ENOENT)
{
if (!create(name, table, NULL))
HA_CREATE_INFO create_info;
bzero(&create_info, sizeof(create_info));
if (!create(name, table, &create_info))
file= heap_open(name, mode);
}
return (file ? 0 : 1);
......@@ -51,6 +53,8 @@ int ha_heap::write_row(byte * buf)
statistic_increment(ha_write_count,&LOCK_status);
if (table->time_stamp)
update_timestamp(buf+table->time_stamp-1);
if (table->next_number_field && buf == table->record[0])
update_auto_increment();
return heap_write(file,buf);
}
......@@ -161,6 +165,8 @@ void ha_heap::info(uint flag)
index_file_length=info.index_length;
max_data_file_length= info.max_records* info.reclength;
delete_length= info.deleted * info.reclength;
if (flag & HA_STATUS_AUTO)
auto_increment_value= info.auto_increment;
}
int ha_heap::extra(enum ha_extra_function operation)
......@@ -234,11 +240,11 @@ ha_rows ha_heap::records_in_range(int inx,
}
}
int ha_heap::create(const char *name, TABLE *table,
HA_CREATE_INFO *create_info)
{
uint key, parts, mem_per_row= 0;
uint auto_key= 0, auto_key_type= 0;
ulong max_rows;
HP_KEYDEF *keydef;
HA_KEYSEG *seg;
......@@ -296,19 +302,42 @@ int ha_heap::create(const char *name, TABLE *table,
seg->null_bit= 0;
seg->null_pos= 0;
}
if (field->flags & AUTO_INCREMENT_FLAG)
{
auto_key= key + 1;
auto_key_type= field->key_type();
}
}
}
mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*));
max_rows = (ulong) (current_thd->variables.max_heap_table_size /
mem_per_row);
HP_CREATE_INFO hp_create_info;
hp_create_info.auto_key= auto_key;
hp_create_info.auto_key_type= auto_key_type;
hp_create_info.auto_increment= (create_info->auto_increment_value ?
create_info->auto_increment_value - 1 : 0);
error= heap_create(fn_format(buff,name,"","",4+2),
table->keys,keydef, table->reclength,
((table->max_rows < max_rows && table->max_rows) ?
table->max_rows : max_rows),
table->min_rows);
table->min_rows, &hp_create_info);
my_free((gptr) keydef, MYF(0));
if (file)
info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
ref_length= sizeof(HEAP_PTR);
return (error);
}
void ha_heap::update_create_info(HA_CREATE_INFO *create_info)
{
table->file->info(HA_STATUS_AUTO);
if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
create_info->auto_increment_value= auto_increment_value;
}
longlong ha_heap::get_auto_increment()
{
ha_heap::info(HA_STATUS_AUTO);
return auto_increment_value;
}
......@@ -40,8 +40,7 @@ class ha_heap: public handler
ulong table_flags() const
{
return (HA_READ_RND_SAME | HA_NO_INDEX | HA_KEYPOS_TO_RNDPOS |
HA_NO_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ |
HA_NO_AUTO_INCREMENT);
HA_NO_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ);
}
ulong index_flags(uint inx) const
{
......@@ -63,6 +62,7 @@ class ha_heap: public handler
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
longlong get_auto_increment();
int index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint idx, const byte * key,
......@@ -87,6 +87,7 @@ class ha_heap: public handler
int delete_table(const char *from);
int rename_table(const char * from, const char * to);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
void update_create_info(HA_CREATE_INFO *create_info);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
......
......@@ -432,7 +432,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!field) // If field is not checked
{
Field *tmp;
if (!(tmp=find_field_in_tables(thd, this, tables, 0)))
if ((tmp= find_field_in_tables(thd, this, tables, 0)) == not_found_field)
{
/*
We can't find table field in table list of current select,
......@@ -445,14 +445,18 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
*/
SELECT_LEX *last= 0;
for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !tmp;
sl;
sl= sl->outer_select())
tmp=find_field_in_tables(thd, this,
(TABLE_LIST*)(last= sl)->table_list.first,
0);
if ((tmp= find_field_in_tables(thd, this,
(TABLE_LIST*)
(last= sl)->table_list.first,
0)) != not_found_field)
break;
if (!tmp)
return -1;
else if (tmp == not_found_field)
{
// Call to produce appropriate error message
// call to return error code
find_field_in_tables(thd, this, tables, 1);
return -1;
}
......@@ -479,6 +483,9 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
}
}
else if (!tmp)
return -1;
set_field(tmp);
}
else if (thd && thd->set_query_id && field->query_id != thd->query_id)
......@@ -786,7 +793,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
if (!ref)
{
if (!(ref= find_item_in_list(this, thd->lex.select->item_list, 0)))
if ((ref= find_item_in_list(this, thd->lex.select->item_list,
REPORT_EXCEPT_NOT_FOUND)) ==
(Item **)not_found_item)
{
/*
We can't find table field in table list of current select,
......@@ -795,17 +804,25 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
of view rules. For example if both tables (outer & current) have
field 'field' it is not mistake to refer to this field without
mention of table name, but if we join tables in one list it will
cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
cause error ER_NON_UNIQ_ERROR in find_item_in_list.
*/
SELECT_LEX *last=0;
for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !ref;
sl;
sl= sl->outer_select())
ref= find_item_in_list(this, (last= sl)->item_list, 0);
if((ref= find_item_in_list(this, (last= sl)->item_list,
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item)
break;
if (!ref)
{
return 1;
}
else if (ref == (Item **)not_found_item)
{
// Call to report error
find_item_in_list(this, thd->lex.select->item_list, 1);
find_item_in_list(this, thd->lex.select->item_list, REPORT_ALL_ERRORS);
return 1;
}
else
......@@ -831,6 +848,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
}
}
}
else if (!ref)
return 1;
max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals;
......
......@@ -32,11 +32,22 @@ SUBSELECT TODO:
#include "mysql_priv.h"
#include "sql_select.h"
Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect *result):
Item_subselect::Item_subselect():
Item(), engine_owner(1), value_assigned(0)
{
DBUG_ENTER("Item_subselect::Item_subselect");
assign_null();
/*
item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned)
*/
null_value= 1;
}
void Item_subselect::init(THD *thd, st_select_lex *select_lex,
select_subselect *result)
{
DBUG_ENTER("Item_subselect::init");
DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex));
if (select_lex->next_select())
......@@ -45,12 +56,6 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
else
engine= new subselect_single_select_engine(thd, select_lex, result,
this);
assign_null();
/*
item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned)
*/
null_value= 1;
DBUG_VOID_RETURN;
}
......@@ -83,6 +88,7 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 1;
}
int res= engine->prepare();
if (!res)
fix_length_and_dec();
return res;
}
......@@ -99,8 +105,9 @@ inline table_map Item_subselect::used_tables() const
Item_singleval_subselect::Item_singleval_subselect(THD *thd,
st_select_lex *select_lex):
Item_subselect(thd, select_lex, new select_singleval_subselect(this))
Item_subselect()
{
init(thd, select_lex, new select_singleval_subselect(this));
max_columns= 1;
maybe_null= 1;
}
......@@ -119,28 +126,38 @@ Item::Type Item_subselect::type() const
double Item_singleval_subselect::val ()
{
if (engine->exec())
{
assign_null();
return 0;
}
return real_value;
}
longlong Item_singleval_subselect::val_int ()
{
if (engine->exec())
{
assign_null();
return 0;
}
return int_value;
}
String *Item_singleval_subselect::val_str (String *str)
{
if (engine->exec() || null_value)
{
assign_null();
return 0;
}
return &str_value;
}
Item_exists_subselect::Item_exists_subselect(THD *thd,
st_select_lex *select_lex):
Item_subselect(thd, select_lex, new select_exists_subselect(this))
Item_subselect()
{
init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX;
null_value= 0; //can't be NULL
maybe_null= 0; //can't be NULL
......@@ -157,21 +174,30 @@ void Item_exists_subselect::fix_length_and_dec()
double Item_exists_subselect::val ()
{
if (engine->exec())
{
assign_null();
return 0;
}
return (double) value;
}
longlong Item_exists_subselect::val_int ()
{
if (engine->exec())
{
assign_null();
return 0;
}
return value;
}
String *Item_exists_subselect::val_str(String *str)
{
if (engine->exec())
{
assign_null();
return 0;
}
str->set(value);
return str;
}
......
......@@ -39,8 +39,7 @@ class Item_subselect :public Item
uint max_columns;
public:
Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect* result);
Item_subselect();
Item_subselect(Item_subselect *item)
{
null_value= item->null_value;
......@@ -50,6 +49,14 @@ class Item_subselect :public Item
engine_owner= 0;
name= item->name;
}
/*
We need this method, because some compilers do not allow 'this'
pointer in constructor initialization list, but we need pass pointer
to subselect Item class to select_subselect classes constructor.
*/
void init (THD *thd, st_select_lex *select_lex, select_subselect *result);
~Item_subselect();
virtual void assign_null()
{
......
......@@ -457,6 +457,7 @@ bool wait_for_tables(THD *thd);
bool table_is_used(TABLE *table, bool wait_for_name_lock);
bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
extern const Field *not_found_field;
Field *find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables,
bool report_error);
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
......@@ -546,7 +547,11 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, int *error);
Item ** find_item_in_list(Item *item, List<Item> &items, bool report_error);
enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
IGNORE_ERRORS};
extern const Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items,
find_item_error_report_type report_error);
bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
List_iterator<Item> *it);
......
......@@ -1781,9 +1781,29 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
return field;
}
// Special Field pointer for find_field_in_tables returning
const Field *not_found_field= (Field*) 0x1;
/*
Find field in table list.
SYNOPSIS
find_field_in_tables()
thd - pointer to current thread structure
item - field item that should be found
tables - tables for scaning
report_error - if FALSE then do not report error if item not found and
return not_found_field;
RETURN VALUES
0 - field is not found or field is not unique, error message is
reported
not_found_field - function was called with report_error == FALSE and
field if not found, no error message reported
found field
*/
Field *
find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables,
bool report_error)
{
Field *found=0;
......@@ -1829,13 +1849,18 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
table_name=buff;
}
my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),table_name,
thd->where);
if (report_error)
my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
table_name, thd->where);
else
return (Field*) not_found_field;
}
else
if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
item->full_name(),thd->where);
else
return (Field*) not_found_field;
return (Field*) 0;
}
bool allow_rowid= tables && !tables->next; // Only one table
......@@ -1850,9 +1875,8 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
return (Field*) 0;
if (found)
{
if (!report_error) // Returns first found
if (!thd->where) // Returns first found
break;
if (report_error)
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
name,thd->where);
return (Field*) 0;
......@@ -1865,11 +1889,39 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR),
MYF(0), item->full_name(), thd->where);
else
return (Field*) not_found_field;
return (Field*) 0;
}
// Special Item pointer for find_item_in_list returning
const Item **not_found_item= (const Item**) 0x1;
/*
Find Item in list of items (find_field_in_tables analog)
SYNOPSIS
find_item_in_list()
find - item to find
items - list of items
report_error
REPORT_ALL_ERRORS - report errors, return 0 if error
REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0
IGNORE_ERRORS - do not report errors, return 0 if error
RETURN VALUES
0 - item is not found or item is not unique, error message is
reported
not_found_item - function was called with report_error ==
REPORT_EXCEPT_NOT_FOUND and item if not found, no error
message reported
found field
*/
Item **
find_item_in_list(Item *find, List<Item> &items, bool report_error)
find_item_in_list(Item *find, List<Item> &items,
find_item_error_report_type report_error)
{
List_iterator<Item> li(items);
Item **found=0,*item;
......@@ -1894,7 +1946,7 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error)
{
if ((*found)->eq(item,0))
continue; // Same field twice (Access?)
if (report_error)
if (report_error != IGNORE_ERRORS)
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
find->full_name(), current_thd->where);
return (Item**) 0;
......@@ -1917,10 +1969,17 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error)
break;
}
}
if (!found && report_error)
if (found)
return found;
else if (report_error != REPORT_EXCEPT_NOT_FOUND)
{
if (report_error == REPORT_ALL_ERRORS)
my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
find->full_name(), current_thd->where);
return found;
return (Item **) 0;
}
else
return (Item **) not_found_item;
}
/****************************************************************************
......
......@@ -6487,7 +6487,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
order->in_field_list=1;
return 0;
}
Item **item=find_item_in_list(*order->item, fields, 0);
Item **item= find_item_in_list(*order->item, fields, IGNORE_ERRORS);
if (item)
{
order->item=item; // use it
......@@ -6587,7 +6587,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
thd->set_query_id=1; // Not really needed, but...
for (; new_field ; new_field= new_field->next)
{
if ((item= find_item_in_list(*new_field->item, fields, 0)))
if ((item= find_item_in_list(*new_field->item, fields, IGNORE_ERRORS)))
new_field->item=item; /* Change to shared Item */
else
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment