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, ...@@ -21,7 +21,8 @@ static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
ulong max_records); ulong max_records);
int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, 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; uint i, j, key_segs, max_length, length;
HP_SHARE *share; HP_SHARE *share;
...@@ -120,6 +121,9 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, ...@@ -120,6 +121,9 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
share->keys= keys; share->keys= keys;
share->max_key_length= max_length; share->max_key_length= max_length;
share->changed= 0; 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)))) if (!(share->name= my_strdup(name,MYF(0))))
{ {
my_free((gptr) share,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) ...@@ -537,3 +537,51 @@ my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record)
} }
return 0; 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, ...@@ -55,5 +55,7 @@ int heap_info(reg1 HP_INFO *info,reg2 HEAPINFO *x,
x->index_length= info->s->index_length; x->index_length= info->s->index_length;
x->max_records = info->s->max_records; x->max_records = info->s->max_records;
x->errkey = info->errkey; x->errkey = info->errkey;
if (flag & HA_STATUS_AUTO)
x->auto_increment= info->s->auto_increment + 1;
DBUG_RETURN(0); DBUG_RETURN(0);
} /* heap_info */ } /* heap_info */
...@@ -37,11 +37,14 @@ int main(int argc, char **argv) ...@@ -37,11 +37,14 @@ int main(int argc, char **argv)
const char *filename; const char *filename;
HP_KEYDEF keyinfo[10]; HP_KEYDEF keyinfo[10];
HA_KEYSEG keyseg[4]; HA_KEYSEG keyseg[4];
HP_CREATE_INFO hp_create_info;
MY_INIT(argv[0]); MY_INIT(argv[0]);
filename= "test1"; filename= "test1";
get_options(argc,argv); get_options(argc,argv);
bzero(&hp_create_info, sizeof(hp_create_info));
keyinfo[0].keysegs=1; keyinfo[0].keysegs=1;
keyinfo[0].seg=keyseg; keyinfo[0].seg=keyseg;
keyinfo[0].algorithm= HA_KEY_ALG_HASH; keyinfo[0].algorithm= HA_KEY_ALG_HASH;
...@@ -55,7 +58,8 @@ int main(int argc, char **argv) ...@@ -55,7 +58,8 @@ int main(int argc, char **argv)
bzero((gptr) flags,sizeof(flags)); bzero((gptr) flags,sizeof(flags));
printf("- Creating heap-file\n"); 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))) !(file= heap_open(filename, 2)))
goto err; goto err;
printf("- Writing records:s\n"); printf("- Writing records:s\n");
......
...@@ -63,6 +63,7 @@ int main(int argc, char *argv[]) ...@@ -63,6 +63,7 @@ int main(int argc, char *argv[])
HP_KEYDEF keyinfo[MAX_KEYS]; HP_KEYDEF keyinfo[MAX_KEYS];
HA_KEYSEG keyseg[MAX_KEYS*5]; HA_KEYSEG keyseg[MAX_KEYS*5];
HEAP_PTR position; HEAP_PTR position;
HP_CREATE_INFO hp_create_info;
MY_INIT(argv[0]); /* init my_sys library & pthreads */ MY_INIT(argv[0]); /* init my_sys library & pthreads */
LINT_INIT(position); LINT_INIT(position);
...@@ -70,6 +71,8 @@ int main(int argc, char *argv[]) ...@@ -70,6 +71,8 @@ int main(int argc, char *argv[])
filename2= "test2_2"; filename2= "test2_2";
file=file2=0; file=file2=0;
get_options(argc,argv); get_options(argc,argv);
bzero(&hp_create_info, sizeof(hp_create_info));
write_count=update=opt_delete=0; write_count=update=opt_delete=0;
key_check=0; key_check=0;
...@@ -122,7 +125,7 @@ int main(int argc, char *argv[]) ...@@ -122,7 +125,7 @@ int main(int argc, char *argv[])
printf("- Creating heap-file\n"); printf("- Creating heap-file\n");
if (heap_create(filename,keys,keyinfo,reclength,(ulong) flag*100000L, if (heap_create(filename,keys,keyinfo,reclength,(ulong) flag*100000L,
(ulong) recant/2) || (ulong) recant/2, &hp_create_info) ||
!(file= heap_open(filename, 2))) !(file= heap_open(filename, 2)))
goto err; goto err;
signal(SIGINT,endprog); signal(SIGINT,endprog);
...@@ -557,7 +560,7 @@ int main(int argc, char *argv[]) ...@@ -557,7 +560,7 @@ int main(int argc, char *argv[])
heap_close(file2); heap_close(file2);
printf("- Creating output heap-file 2\n"); 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))) !(file2= heap_open(filename2, 2)))
goto err; goto err;
......
...@@ -22,7 +22,8 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new) ...@@ -22,7 +22,8 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
{ {
HP_KEYDEF *keydef, *end, *p_lastinx; HP_KEYDEF *keydef, *end, *p_lastinx;
byte *pos; byte *pos;
HP_SHARE *share=info->s; bool auto_key_changed= 0;
HP_SHARE *share= info->s;
DBUG_ENTER("heap_update"); DBUG_ENTER("heap_update");
test_active(info); test_active(info);
...@@ -33,20 +34,23 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new) ...@@ -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; if (--(share->records) < share->blength >> 1) share->blength>>= 1;
share->changed=1; share->changed=1;
p_lastinx = share->keydef + info->lastinx; p_lastinx= share->keydef + info->lastinx;
for (keydef = share->keydef, end = keydef + share->keys; keydef < end; for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++)
keydef++)
{ {
if (hp_rec_key_cmp(keydef, old, heap_new)) if (hp_rec_key_cmp(keydef, old, heap_new))
{ {
if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) || if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) ||
(*keydef->write_key)(info, keydef, heap_new, pos)) (*keydef->write_key)(info, keydef, heap_new, pos))
goto err; goto err;
if (share->auto_key == (uint) (keydef - share->keydef + 1))
auto_key_changed= 1;
} }
} }
memcpy(pos,heap_new,(size_t) share->reclength); memcpy(pos,heap_new,(size_t) share->reclength);
if (++(share->records) == share->blength) share->blength+= share->blength; if (++(share->records) == share->blength) share->blength+= share->blength;
if (auto_key_changed)
heap_update_auto_increment(info, heap_new);
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
......
...@@ -61,6 +61,8 @@ int heap_write(HP_INFO *info, const byte *record) ...@@ -61,6 +61,8 @@ int heap_write(HP_INFO *info, const byte *record)
info->current_ptr=pos; info->current_ptr=pos;
info->current_hash_ptr=0; info->current_hash_ptr=0;
info->update|=HA_STATE_AKTIV; info->update|=HA_STATE_AKTIV;
if (share->auto_key)
heap_update_auto_increment(info, record);
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef)); DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef));
......
...@@ -50,6 +50,7 @@ typedef struct st_heapinfo /* Struct from heap_info */ ...@@ -50,6 +50,7 @@ typedef struct st_heapinfo /* Struct from heap_info */
ulong index_length; ulong index_length;
uint reclength; /* Length of one record */ uint reclength; /* Length of one record */
int errkey; int errkey;
ulonglong auto_increment;
} HEAPINFO; } HEAPINFO;
...@@ -115,6 +116,9 @@ typedef struct st_heap_share ...@@ -115,6 +116,9 @@ typedef struct st_heap_share
#endif #endif
my_bool delete_on_close; my_bool delete_on_close;
LIST open_list; LIST open_list;
uint auto_key;
uint auto_key_type; /* real type of the auto key segment */
ulonglong auto_increment;
} HP_SHARE; } HP_SHARE;
struct st_hp_hash_info; struct st_hp_hash_info;
...@@ -140,6 +144,13 @@ typedef struct st_heap_info ...@@ -140,6 +144,13 @@ typedef struct st_heap_info
LIST open_list; LIST open_list;
} HP_INFO; } 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 */ /* Prototypes for heap-functions */
extern HP_INFO *heap_open(const char *name, int mode); extern HP_INFO *heap_open(const char *name, int mode);
...@@ -152,7 +163,8 @@ extern int heap_scan(register HP_INFO *info, byte *record); ...@@ -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_delete(HP_INFO *info,const byte *buff);
extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag); extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag);
extern int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, 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_delete_table(const char *name);
extern int heap_extra(HP_INFO *info,enum ha_extra_function function); extern int heap_extra(HP_INFO *info,enum ha_extra_function function);
extern int heap_rename(const char *old_name,const char *new_name); 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); ...@@ -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_rfirst(HP_INFO *info,byte *record,int inx);
extern int heap_rlast(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_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, ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, const byte *start_key,
uint start_key_len, uint start_key_len,
enum ha_rkey_function start_search_flag, enum ha_rkey_function start_search_flag,
......
...@@ -139,14 +139,14 @@ id parent_id level ...@@ -139,14 +139,14 @@ id parent_id level
1015 102 2 1015 102 2
1010 102 2 1010 102 2
explain select level from t1 where level=1; explain select level from t1 where level=1;
table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used; Using index 1 SIMPLE t1 ref level level 1 const 1 where used; Using index
explain select level,id from t1 where level=1; explain select level,id from t1 where level=1;
table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used; Using index 1 SIMPLE t1 ref level level 1 const 1 where used; Using index
explain select level,id,parent_id from t1 where level=1; explain select level,id,parent_id from t1 where level=1;
table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used 1 SIMPLE t1 ref level level 1 const 1 where used
select level,id from t1 where level=1; select level,id from t1 where level=1;
level id level id
1 1002 1 1002
...@@ -624,8 +624,8 @@ id parent_id level ...@@ -624,8 +624,8 @@ id parent_id level
1025 102 2 1025 102 2
1016 102 2 1016 102 2
explain select level from t1 where level=1; explain select level from t1 where level=1;
table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used; Using index 1 SIMPLE t1 ref level level 1 const 1 where used; Using index
select level,id from t1 where level=1; select level,id from t1 where level=1;
level id level id
1 1004 1 1004
......
...@@ -22,14 +22,13 @@ drop table if exists t1,t2; ...@@ -22,14 +22,13 @@ drop table if exists t1,t2;
create table t1 (b char(0) not null, index(b)); create table t1 (b char(0) not null, index(b));
The used table handler can't index column 'b' The used table handler can't index column 'b'
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;
The used table type doesn't support AUTO_INCREMENT columns
create table t1 (a int not null,b text) type=heap; create table t1 (a int not null,b text) type=heap;
The used table type doesn't support BLOB/TEXT columns The used table type doesn't support BLOB/TEXT columns
create table t1 (a int ,primary key(a)) type=heap; 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 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; 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; 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)); 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 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); 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 (select 2);
(select 2) (select 2)
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 t1 (a int);
create table t2 (a int, b int); create table t2 (a int, b int);
create table t3 (a int); create table t3 (a int);
...@@ -131,6 +131,8 @@ patient_uq clinic_uq ...@@ -131,6 +131,8 @@ patient_uq clinic_uq
1 1 1 1
1 2 1 2
2 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; drop table if exists t1,t2,t3;
CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0'); CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0');
INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b'); INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b');
...@@ -147,4 +149,16 @@ W 1 ...@@ -147,4 +149,16 @@ W 1
SELECT * FROM t3 WHERE b = (SELECT MIN(b) FROM t3); SELECT * FROM t3 WHERE b = (SELECT MIN(b) FROM t3);
a b a b
W a 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; ...@@ -22,12 +22,12 @@ drop table if exists t1;
!$1146 create table t2 select auto+1 from t1; !$1146 create table t2 select auto+1 from t1;
drop table if exists t1,t2; drop table if exists t1,t2;
!$1167 create table t1 (b char(0) not null, index(b)); !$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; !$1163 create table t1 (a int not null,b text) type=heap;
!$1171 create table t1 (a int ,primary key(a)) type=heap; !$1171 create table t1 (a int ,primary key(a)) type=heap;
drop table if exists t1; 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)); !$1171 create table t1 (ordid int(8), primary key (ordid));
-- error 1044,1 -- 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); 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 t1 (a int);
create table t2 (a int, b int); create table t2 (a int, b int);
create table t3 (a int); create table t3 (a int);
...@@ -53,6 +53,10 @@ insert into clinic values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta" ...@@ -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); insert into attend values (1,1),(1,2),(2,2),(1,3);
select * from attend where exists (select * from clinic where uq = clinic_uq); 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 # different tipes & group functions
drop table if exists t1,t2,t3; drop table if exists t1,t2,t3;
...@@ -66,4 +70,19 @@ SELECT * FROM t1 WHERE b = (SELECT MIN(b) FROM t1); ...@@ -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 t2 WHERE b = (SELECT MIN(b) FROM t2);
SELECT * FROM t3 WHERE b = (SELECT MIN(b) FROM t3); 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) ...@@ -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 (!(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); file= heap_open(name, mode);
} }
return (file ? 0 : 1); return (file ? 0 : 1);
...@@ -51,6 +53,8 @@ int ha_heap::write_row(byte * buf) ...@@ -51,6 +53,8 @@ int ha_heap::write_row(byte * buf)
statistic_increment(ha_write_count,&LOCK_status); statistic_increment(ha_write_count,&LOCK_status);
if (table->time_stamp) if (table->time_stamp)
update_timestamp(buf+table->time_stamp-1); update_timestamp(buf+table->time_stamp-1);
if (table->next_number_field && buf == table->record[0])
update_auto_increment();
return heap_write(file,buf); return heap_write(file,buf);
} }
...@@ -161,6 +165,8 @@ void ha_heap::info(uint flag) ...@@ -161,6 +165,8 @@ void ha_heap::info(uint flag)
index_file_length=info.index_length; index_file_length=info.index_length;
max_data_file_length= info.max_records* info.reclength; max_data_file_length= info.max_records* info.reclength;
delete_length= info.deleted * 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) int ha_heap::extra(enum ha_extra_function operation)
...@@ -234,11 +240,11 @@ ha_rows ha_heap::records_in_range(int inx, ...@@ -234,11 +240,11 @@ ha_rows ha_heap::records_in_range(int inx,
} }
} }
int ha_heap::create(const char *name, TABLE *table, int ha_heap::create(const char *name, TABLE *table,
HA_CREATE_INFO *create_info) HA_CREATE_INFO *create_info)
{ {
uint key, parts, mem_per_row= 0; uint key, parts, mem_per_row= 0;
uint auto_key= 0, auto_key_type= 0;
ulong max_rows; ulong max_rows;
HP_KEYDEF *keydef; HP_KEYDEF *keydef;
HA_KEYSEG *seg; HA_KEYSEG *seg;
...@@ -296,19 +302,42 @@ int ha_heap::create(const char *name, TABLE *table, ...@@ -296,19 +302,42 @@ int ha_heap::create(const char *name, TABLE *table,
seg->null_bit= 0; seg->null_bit= 0;
seg->null_pos= 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*)); mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*));
max_rows = (ulong) (current_thd->variables.max_heap_table_size / max_rows = (ulong) (current_thd->variables.max_heap_table_size /
mem_per_row); 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), error= heap_create(fn_format(buff,name,"","",4+2),
table->keys,keydef, table->reclength, table->keys,keydef, table->reclength,
((table->max_rows < max_rows && table->max_rows) ? ((table->max_rows < max_rows && table->max_rows) ?
table->max_rows : max_rows), table->max_rows : max_rows),
table->min_rows); table->min_rows, &hp_create_info);
my_free((gptr) keydef, MYF(0)); my_free((gptr) keydef, MYF(0));
if (file) if (file)
info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE); info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
ref_length= sizeof(HEAP_PTR); ref_length= sizeof(HEAP_PTR);
return (error); 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 ...@@ -40,8 +40,7 @@ class ha_heap: public handler
ulong table_flags() const ulong table_flags() const
{ {
return (HA_READ_RND_SAME | HA_NO_INDEX | HA_KEYPOS_TO_RNDPOS | 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_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ);
HA_NO_AUTO_INCREMENT);
} }
ulong index_flags(uint inx) const ulong index_flags(uint inx) const
{ {
...@@ -63,6 +62,7 @@ class ha_heap: public handler ...@@ -63,6 +62,7 @@ class ha_heap: public handler
int write_row(byte * buf); int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data); int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf); int delete_row(const byte * buf);
longlong get_auto_increment();
int index_read(byte * buf, const byte * key, int index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag); uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint idx, const byte * key, int index_read_idx(byte * buf, uint idx, const byte * key,
...@@ -87,6 +87,7 @@ class ha_heap: public handler ...@@ -87,6 +87,7 @@ class ha_heap: public handler
int delete_table(const char *from); int delete_table(const char *from);
int rename_table(const char * from, const char * to); int rename_table(const char * from, const char * to);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); 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, THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); enum thr_lock_type lock_type);
......
...@@ -432,7 +432,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -432,7 +432,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!field) // If field is not checked if (!field) // If field is not checked
{ {
Field *tmp; 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, 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) ...@@ -445,14 +445,18 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
*/ */
SELECT_LEX *last= 0; SELECT_LEX *last= 0;
for (SELECT_LEX *sl= thd->lex.select->outer_select(); for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !tmp; sl;
sl= sl->outer_select()) sl= sl->outer_select())
tmp=find_field_in_tables(thd, this, if ((tmp= find_field_in_tables(thd, this,
(TABLE_LIST*)(last= sl)->table_list.first, (TABLE_LIST*)
0); (last= sl)->table_list.first,
0)) != not_found_field)
break;
if (!tmp) 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); find_field_in_tables(thd, this, tables, 1);
return -1; return -1;
} }
...@@ -478,7 +482,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -478,7 +482,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
tbl->shared= 1; tbl->shared= 1;
} }
} }
} }
else if (!tmp)
return -1;
set_field(tmp); set_field(tmp);
} }
else if (thd && thd->set_query_id && field->query_id != thd->query_id) 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) ...@@ -786,7 +793,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{ {
if (!ref) 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, 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) ...@@ -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 of view rules. For example if both tables (outer & current) have
field 'field' it is not mistake to refer to this field without 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 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; SELECT_LEX *last=0;
for (SELECT_LEX *sl= thd->lex.select->outer_select(); for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !ref; sl;
sl= sl->outer_select()) 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) if (!ref)
{
return 1;
}
else if (ref == (Item **)not_found_item)
{ {
// Call to report error // 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; return 1;
} }
else else
...@@ -831,6 +848,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -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; max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null; maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals; decimals= (*ref)->decimals;
......
...@@ -32,11 +32,22 @@ SUBSELECT TODO: ...@@ -32,11 +32,22 @@ SUBSELECT TODO:
#include "mysql_priv.h" #include "mysql_priv.h"
#include "sql_select.h" #include "sql_select.h"
Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex, Item_subselect::Item_subselect():
select_subselect *result):
Item(), engine_owner(1), value_assigned(0) 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)); DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex));
if (select_lex->next_select()) if (select_lex->next_select())
...@@ -45,12 +56,6 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex, ...@@ -45,12 +56,6 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
else else
engine= new subselect_single_select_engine(thd, select_lex, result, engine= new subselect_single_select_engine(thd, select_lex, result,
this); 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; DBUG_VOID_RETURN;
} }
...@@ -83,7 +88,8 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -83,7 +88,8 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 1; return 1;
} }
int res= engine->prepare(); int res= engine->prepare();
fix_length_and_dec(); if (!res)
fix_length_and_dec();
return res; return res;
} }
...@@ -99,8 +105,9 @@ inline table_map Item_subselect::used_tables() const ...@@ -99,8 +105,9 @@ inline table_map Item_subselect::used_tables() const
Item_singleval_subselect::Item_singleval_subselect(THD *thd, Item_singleval_subselect::Item_singleval_subselect(THD *thd,
st_select_lex *select_lex): 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; max_columns= 1;
maybe_null= 1; maybe_null= 1;
} }
...@@ -119,28 +126,38 @@ Item::Type Item_subselect::type() const ...@@ -119,28 +126,38 @@ Item::Type Item_subselect::type() const
double Item_singleval_subselect::val () double Item_singleval_subselect::val ()
{ {
if (engine->exec()) if (engine->exec())
{
assign_null();
return 0; return 0;
}
return real_value; return real_value;
} }
longlong Item_singleval_subselect::val_int () longlong Item_singleval_subselect::val_int ()
{ {
if (engine->exec()) if (engine->exec())
{
assign_null();
return 0; return 0;
}
return int_value; return int_value;
} }
String *Item_singleval_subselect::val_str (String *str) String *Item_singleval_subselect::val_str (String *str)
{ {
if (engine->exec() || null_value) if (engine->exec() || null_value)
{
assign_null();
return 0; return 0;
}
return &str_value; return &str_value;
} }
Item_exists_subselect::Item_exists_subselect(THD *thd, Item_exists_subselect::Item_exists_subselect(THD *thd,
st_select_lex *select_lex): 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; max_columns= UINT_MAX;
null_value= 0; //can't be NULL null_value= 0; //can't be NULL
maybe_null= 0; //can't be NULL maybe_null= 0; //can't be NULL
...@@ -157,21 +174,30 @@ void Item_exists_subselect::fix_length_and_dec() ...@@ -157,21 +174,30 @@ void Item_exists_subselect::fix_length_and_dec()
double Item_exists_subselect::val () double Item_exists_subselect::val ()
{ {
if (engine->exec()) if (engine->exec())
{
assign_null();
return 0; return 0;
}
return (double) value; return (double) value;
} }
longlong Item_exists_subselect::val_int () longlong Item_exists_subselect::val_int ()
{ {
if (engine->exec()) if (engine->exec())
{
assign_null();
return 0; return 0;
}
return value; return value;
} }
String *Item_exists_subselect::val_str(String *str) String *Item_exists_subselect::val_str(String *str)
{ {
if (engine->exec()) if (engine->exec())
{
assign_null();
return 0; return 0;
}
str->set(value); str->set(value);
return str; return str;
} }
......
...@@ -39,8 +39,7 @@ class Item_subselect :public Item ...@@ -39,8 +39,7 @@ class Item_subselect :public Item
uint max_columns; uint max_columns;
public: public:
Item_subselect(THD *thd, st_select_lex *select_lex, Item_subselect();
select_subselect* result);
Item_subselect(Item_subselect *item) Item_subselect(Item_subselect *item)
{ {
null_value= item->null_value; null_value= item->null_value;
...@@ -50,6 +49,14 @@ class Item_subselect :public Item ...@@ -50,6 +49,14 @@ class Item_subselect :public Item
engine_owner= 0; engine_owner= 0;
name= item->name; 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(); ~Item_subselect();
virtual void assign_null() virtual void assign_null()
{ {
......
...@@ -457,6 +457,7 @@ bool wait_for_tables(THD *thd); ...@@ -457,6 +457,7 @@ bool wait_for_tables(THD *thd);
bool table_is_used(TABLE *table, bool wait_for_name_lock); bool table_is_used(TABLE *table, bool wait_for_name_lock);
bool drop_locked_tables(THD *thd,const char *db, const char *table_name); 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); 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, Field *find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables,
bool report_error); bool report_error);
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, 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); ...@@ -546,7 +547,11 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables, SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, int *error); 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, bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
List_iterator<Item> *it); List_iterator<Item> *it);
......
...@@ -1781,9 +1781,29 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, ...@@ -1781,9 +1781,29 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
return field; 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 * 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) bool report_error)
{ {
Field *found=0; Field *found=0;
...@@ -1829,13 +1849,18 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, ...@@ -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); strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
table_name=buff; table_name=buff;
} }
my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),table_name, if (report_error)
thd->where); my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
table_name, thd->where);
else
return (Field*) not_found_field;
} }
else else
if (report_error) if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
item->full_name(),thd->where); item->full_name(),thd->where);
else
return (Field*) not_found_field;
return (Field*) 0; return (Field*) 0;
} }
bool allow_rowid= tables && !tables->next; // Only one table bool allow_rowid= tables && !tables->next; // Only one table
...@@ -1850,11 +1875,10 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, ...@@ -1850,11 +1875,10 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
return (Field*) 0; return (Field*) 0;
if (found) if (found)
{ {
if (!report_error) // Returns first found if (!thd->where) // Returns first found
break; break;
if (report_error) my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0), name,thd->where);
name,thd->where);
return (Field*) 0; return (Field*) 0;
} }
found=field; found=field;
...@@ -1865,11 +1889,39 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, ...@@ -1865,11 +1889,39 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
if (report_error) if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR),
MYF(0), item->full_name(), thd->where); MYF(0), item->full_name(), thd->where);
else
return (Field*) not_found_field;
return (Field*) 0; 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 ** 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); List_iterator<Item> li(items);
Item **found=0,*item; Item **found=0,*item;
...@@ -1894,7 +1946,7 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error) ...@@ -1894,7 +1946,7 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error)
{ {
if ((*found)->eq(item,0)) if ((*found)->eq(item,0))
continue; // Same field twice (Access?) 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), my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
find->full_name(), current_thd->where); find->full_name(), current_thd->where);
return (Item**) 0; return (Item**) 0;
...@@ -1917,10 +1969,17 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error) ...@@ -1917,10 +1969,17 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error)
break; break;
} }
} }
if (!found && report_error) if (found)
my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0), return found;
find->full_name(), current_thd->where); else if (report_error != REPORT_EXCEPT_NOT_FOUND)
return 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 (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, ...@@ -6487,7 +6487,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
order->in_field_list=1; order->in_field_list=1;
return 0; 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) if (item)
{ {
order->item=item; // use it order->item=item; // use it
...@@ -6587,7 +6587,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields, ...@@ -6587,7 +6587,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
thd->set_query_id=1; // Not really needed, but... thd->set_query_id=1; // Not really needed, but...
for (; new_field ; new_field= new_field->next) 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 */ new_field->item=item; /* Change to shared Item */
else 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