mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Merge willster.(none):/home/stewart/Documents/MySQL/4.1/bug19914-mk2
into willster.(none):/home/stewart/Documents/MySQL/4.1/bug19914-mk2-merge2
This commit is contained in:
@@ -26,9 +26,6 @@
|
|||||||
#define USERNAME_LENGTH 16
|
#define USERNAME_LENGTH 16
|
||||||
#define SERVER_VERSION_LENGTH 60
|
#define SERVER_VERSION_LENGTH 60
|
||||||
#define SQLSTATE_LENGTH 5
|
#define SQLSTATE_LENGTH 5
|
||||||
#define SYSTEM_CHARSET_MBMAXLEN 3
|
|
||||||
#define NAME_BYTE_LEN NAME_LEN*SYSTEM_CHARSET_MBMAXLEN
|
|
||||||
#define USERNAME_BYTE_LENGTH USERNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN
|
|
||||||
|
|
||||||
#define LOCAL_HOST "localhost"
|
#define LOCAL_HOST "localhost"
|
||||||
#define LOCAL_HOST_NAMEDPIPE "."
|
#define LOCAL_HOST_NAMEDPIPE "."
|
||||||
|
@@ -1153,9 +1153,12 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
|
|||||||
/* We don't need to lock the key tree here as we don't allow
|
/* We don't need to lock the key tree here as we don't allow
|
||||||
concurrent threads when running myisamchk
|
concurrent threads when running myisamchk
|
||||||
*/
|
*/
|
||||||
int search_result= (keyinfo->flag & HA_SPATIAL) ?
|
int search_result=
|
||||||
|
#ifdef HAVE_RTREE_KEYS
|
||||||
|
(keyinfo->flag & HA_SPATIAL) ?
|
||||||
rtree_find_first(info, key, info->lastkey, key_length,
|
rtree_find_first(info, key, info->lastkey, key_length,
|
||||||
MBR_EQUAL | MBR_DATA) :
|
MBR_EQUAL | MBR_DATA) :
|
||||||
|
#endif
|
||||||
_mi_search(info,keyinfo,info->lastkey,key_length,
|
_mi_search(info,keyinfo,info->lastkey,key_length,
|
||||||
SEARCH_SAME, info->s->state.key_root[key]);
|
SEARCH_SAME, info->s->state.key_root[key]);
|
||||||
if (search_result)
|
if (search_result)
|
||||||
@@ -1366,7 +1369,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
|
|||||||
param->temp_filename);
|
param->temp_filename);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (filecopy(param,new_file,info->dfile,0L,new_header_length,
|
if (new_header_length &&
|
||||||
|
filecopy(param,new_file,info->dfile,0L,new_header_length,
|
||||||
"datafile-header"))
|
"datafile-header"))
|
||||||
goto err;
|
goto err;
|
||||||
info->s->state.dellink= HA_OFFSET_ERROR;
|
info->s->state.dellink= HA_OFFSET_ERROR;
|
||||||
@@ -2063,7 +2067,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
|
|||||||
param->temp_filename);
|
param->temp_filename);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (filecopy(param, new_file,info->dfile,0L,new_header_length,
|
if (new_header_length &&
|
||||||
|
filecopy(param, new_file,info->dfile,0L,new_header_length,
|
||||||
"datafile-header"))
|
"datafile-header"))
|
||||||
goto err;
|
goto err;
|
||||||
if (param->testflag & T_UNPACK)
|
if (param->testflag & T_UNPACK)
|
||||||
@@ -2431,7 +2436,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
|
|||||||
param->temp_filename);
|
param->temp_filename);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (filecopy(param, new_file,info->dfile,0L,new_header_length,
|
if (new_header_length &&
|
||||||
|
filecopy(param, new_file,info->dfile,0L,new_header_length,
|
||||||
"datafile-header"))
|
"datafile-header"))
|
||||||
goto err;
|
goto err;
|
||||||
if (param->testflag & T_UNPACK)
|
if (param->testflag & T_UNPACK)
|
||||||
|
@@ -428,7 +428,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBUG_PRINT("test",("Inserting of key when deleting"));
|
DBUG_PRINT("test",("Inserting of key when deleting"));
|
||||||
if (_mi_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos,
|
if (!_mi_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos,
|
||||||
&tmp))
|
&tmp))
|
||||||
goto err;
|
goto err;
|
||||||
ret_value=_mi_insert(info,keyinfo,key,leaf_buff,endpos,keybuff,
|
ret_value=_mi_insert(info,keyinfo,key,leaf_buff,endpos,keybuff,
|
||||||
|
@@ -1091,12 +1091,41 @@ void _my_store_blob_length(byte *pos,uint pack_length,uint length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Read record from datafile */
|
/*
|
||||||
/* Returns 0 if ok, -1 if error */
|
Read record from datafile.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
_mi_read_dynamic_record()
|
||||||
|
info MI_INFO pointer to table.
|
||||||
|
filepos From where to read the record.
|
||||||
|
buf Destination for record.
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
|
||||||
|
If a write buffer is active, it needs to be flushed if its contents
|
||||||
|
intersects with the record to read. We always check if the position
|
||||||
|
of the first byte of the write buffer is lower than the position
|
||||||
|
past the last byte to read. In theory this is also true if the write
|
||||||
|
buffer is completely below the read segment. That is, if there is no
|
||||||
|
intersection. But this case is unusual. We flush anyway. Only if the
|
||||||
|
first byte in the write buffer is above the last byte to read, we do
|
||||||
|
not flush.
|
||||||
|
|
||||||
|
A dynamic record may need several reads. So this check must be done
|
||||||
|
before every read. Reading a dynamic record starts with reading the
|
||||||
|
block header. If the record does not fit into the free space of the
|
||||||
|
header, the block may be longer than the header. In this case a
|
||||||
|
second read is necessary. These one or two reads repeat for every
|
||||||
|
part of the record.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 OK
|
||||||
|
-1 Error
|
||||||
|
*/
|
||||||
|
|
||||||
int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
|
int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
|
||||||
{
|
{
|
||||||
int flag;
|
int block_of_record;
|
||||||
uint b_type,left_length;
|
uint b_type,left_length;
|
||||||
byte *to;
|
byte *to;
|
||||||
MI_BLOCK_INFO block_info;
|
MI_BLOCK_INFO block_info;
|
||||||
@@ -1108,20 +1137,19 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
|
|||||||
LINT_INIT(to);
|
LINT_INIT(to);
|
||||||
LINT_INIT(left_length);
|
LINT_INIT(left_length);
|
||||||
file=info->dfile;
|
file=info->dfile;
|
||||||
block_info.next_filepos=filepos; /* for easyer loop */
|
block_of_record= 0; /* First block of record is numbered as zero. */
|
||||||
flag=block_info.second_read=0;
|
block_info.second_read= 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
/* A corrupted table can have wrong pointers. (Bug# 19835) */
|
||||||
|
if (filepos == HA_OFFSET_ERROR)
|
||||||
|
goto panic;
|
||||||
if (info->opt_flag & WRITE_CACHE_USED &&
|
if (info->opt_flag & WRITE_CACHE_USED &&
|
||||||
info->rec_cache.pos_in_file <= block_info.next_filepos &&
|
info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH &&
|
||||||
flush_io_cache(&info->rec_cache))
|
flush_io_cache(&info->rec_cache))
|
||||||
goto err;
|
goto err;
|
||||||
/* A corrupted table can have wrong pointers. (Bug# 19835) */
|
|
||||||
if (block_info.next_filepos == HA_OFFSET_ERROR)
|
|
||||||
goto panic;
|
|
||||||
info->rec_cache.seek_not_done=1;
|
info->rec_cache.seek_not_done=1;
|
||||||
if ((b_type=_mi_get_block_info(&block_info,file,
|
if ((b_type= _mi_get_block_info(&block_info, file, filepos))
|
||||||
block_info.next_filepos))
|
|
||||||
& (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
|
& (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
|
||||||
BLOCK_FATAL_ERROR))
|
BLOCK_FATAL_ERROR))
|
||||||
{
|
{
|
||||||
@@ -1129,9 +1157,8 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
|
|||||||
my_errno=HA_ERR_RECORD_DELETED;
|
my_errno=HA_ERR_RECORD_DELETED;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (flag == 0) /* First block */
|
if (block_of_record++ == 0) /* First block */
|
||||||
{
|
{
|
||||||
flag=1;
|
|
||||||
if (block_info.rec_len > (uint) info->s->base.max_pack_length)
|
if (block_info.rec_len > (uint) info->s->base.max_pack_length)
|
||||||
goto panic;
|
goto panic;
|
||||||
if (info->s->base.blobs)
|
if (info->s->base.blobs)
|
||||||
@@ -1146,11 +1173,35 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
|
|||||||
}
|
}
|
||||||
if (left_length < block_info.data_len || ! block_info.data_len)
|
if (left_length < block_info.data_len || ! block_info.data_len)
|
||||||
goto panic; /* Wrong linked record */
|
goto panic; /* Wrong linked record */
|
||||||
if (my_pread(file,(byte*) to,block_info.data_len,block_info.filepos,
|
/* copy information that is already read */
|
||||||
MYF(MY_NABP)))
|
{
|
||||||
|
uint offset= (uint) (block_info.filepos - filepos);
|
||||||
|
uint prefetch_len= (sizeof(block_info.header) - offset);
|
||||||
|
filepos+= sizeof(block_info.header);
|
||||||
|
|
||||||
|
if (prefetch_len > block_info.data_len)
|
||||||
|
prefetch_len= block_info.data_len;
|
||||||
|
if (prefetch_len)
|
||||||
|
{
|
||||||
|
memcpy((byte*) to, block_info.header + offset, prefetch_len);
|
||||||
|
block_info.data_len-= prefetch_len;
|
||||||
|
left_length-= prefetch_len;
|
||||||
|
to+= prefetch_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* read rest of record from file */
|
||||||
|
if (block_info.data_len)
|
||||||
|
{
|
||||||
|
if (info->opt_flag & WRITE_CACHE_USED &&
|
||||||
|
info->rec_cache.pos_in_file < filepos + block_info.data_len &&
|
||||||
|
flush_io_cache(&info->rec_cache))
|
||||||
|
goto err;
|
||||||
|
if (my_read(file, (byte*) to, block_info.data_len, MYF(MY_NABP)))
|
||||||
goto panic;
|
goto panic;
|
||||||
left_length-=block_info.data_len;
|
left_length-=block_info.data_len;
|
||||||
to+=block_info.data_len;
|
to+=block_info.data_len;
|
||||||
|
}
|
||||||
|
filepos= block_info.next_filepos;
|
||||||
} while (left_length);
|
} while (left_length);
|
||||||
|
|
||||||
info->update|= HA_STATE_AKTIV; /* We have a aktive record */
|
info->update|= HA_STATE_AKTIV; /* We have a aktive record */
|
||||||
@@ -1307,11 +1358,45 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read record from datafile.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
_mi_read_rnd_dynamic_record()
|
||||||
|
info MI_INFO pointer to table.
|
||||||
|
buf Destination for record.
|
||||||
|
filepos From where to read the record.
|
||||||
|
skip_deleted_blocks If to repeat reading until a non-deleted
|
||||||
|
record is found.
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
|
||||||
|
If a write buffer is active, it needs to be flushed if its contents
|
||||||
|
intersects with the record to read. We always check if the position
|
||||||
|
of the first byte of the write buffer is lower than the position
|
||||||
|
past the last byte to read. In theory this is also true if the write
|
||||||
|
buffer is completely below the read segment. That is, if there is no
|
||||||
|
intersection. But this case is unusual. We flush anyway. Only if the
|
||||||
|
first byte in the write buffer is above the last byte to read, we do
|
||||||
|
not flush.
|
||||||
|
|
||||||
|
A dynamic record may need several reads. So this check must be done
|
||||||
|
before every read. Reading a dynamic record starts with reading the
|
||||||
|
block header. If the record does not fit into the free space of the
|
||||||
|
header, the block may be longer than the header. In this case a
|
||||||
|
second read is necessary. These one or two reads repeat for every
|
||||||
|
part of the record.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 OK
|
||||||
|
!= 0 Error
|
||||||
|
*/
|
||||||
|
|
||||||
int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
|
int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
|
||||||
register my_off_t filepos,
|
register my_off_t filepos,
|
||||||
my_bool skip_deleted_blocks)
|
my_bool skip_deleted_blocks)
|
||||||
{
|
{
|
||||||
int flag,info_read,save_errno;
|
int block_of_record, info_read, save_errno;
|
||||||
uint left_len,b_type;
|
uint left_len,b_type;
|
||||||
byte *to;
|
byte *to;
|
||||||
MI_BLOCK_INFO block_info;
|
MI_BLOCK_INFO block_info;
|
||||||
@@ -1337,7 +1422,8 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
|
|||||||
else
|
else
|
||||||
info_read=1; /* memory-keyinfoblock is ok */
|
info_read=1; /* memory-keyinfoblock is ok */
|
||||||
|
|
||||||
flag=block_info.second_read=0;
|
block_of_record= 0; /* First block of record is numbered as zero. */
|
||||||
|
block_info.second_read= 0;
|
||||||
left_len=1;
|
left_len=1;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -1360,15 +1446,15 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
|
|||||||
{
|
{
|
||||||
if (_mi_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
|
if (_mi_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
|
||||||
sizeof(block_info.header),
|
sizeof(block_info.header),
|
||||||
(!flag && skip_deleted_blocks ? READING_NEXT : 0) |
|
(!block_of_record && skip_deleted_blocks ?
|
||||||
READING_HEADER))
|
READING_NEXT : 0) | READING_HEADER))
|
||||||
goto panic;
|
goto panic;
|
||||||
b_type=_mi_get_block_info(&block_info,-1,filepos);
|
b_type=_mi_get_block_info(&block_info,-1,filepos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (info->opt_flag & WRITE_CACHE_USED &&
|
if (info->opt_flag & WRITE_CACHE_USED &&
|
||||||
info->rec_cache.pos_in_file <= filepos &&
|
info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH &&
|
||||||
flush_io_cache(&info->rec_cache))
|
flush_io_cache(&info->rec_cache))
|
||||||
DBUG_RETURN(my_errno);
|
DBUG_RETURN(my_errno);
|
||||||
info->rec_cache.seek_not_done=1;
|
info->rec_cache.seek_not_done=1;
|
||||||
@@ -1393,7 +1479,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
|
|||||||
}
|
}
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (flag == 0) /* First block */
|
if (block_of_record == 0) /* First block */
|
||||||
{
|
{
|
||||||
if (block_info.rec_len > (uint) share->base.max_pack_length)
|
if (block_info.rec_len > (uint) share->base.max_pack_length)
|
||||||
goto panic;
|
goto panic;
|
||||||
@@ -1435,11 +1521,17 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
|
|||||||
{
|
{
|
||||||
if (_mi_read_cache(&info->rec_cache,(byte*) to,filepos,
|
if (_mi_read_cache(&info->rec_cache,(byte*) to,filepos,
|
||||||
block_info.data_len,
|
block_info.data_len,
|
||||||
(!flag && skip_deleted_blocks) ? READING_NEXT :0))
|
(!block_of_record && skip_deleted_blocks) ?
|
||||||
|
READING_NEXT : 0))
|
||||||
goto panic;
|
goto panic;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (info->opt_flag & WRITE_CACHE_USED &&
|
||||||
|
info->rec_cache.pos_in_file <
|
||||||
|
block_info.filepos + block_info.data_len &&
|
||||||
|
flush_io_cache(&info->rec_cache))
|
||||||
|
goto err;
|
||||||
/* VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0))); */
|
/* VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0))); */
|
||||||
if (my_read(info->dfile,(byte*) to,block_info.data_len,MYF(MY_NABP)))
|
if (my_read(info->dfile,(byte*) to,block_info.data_len,MYF(MY_NABP)))
|
||||||
{
|
{
|
||||||
@@ -1449,10 +1541,14 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flag++ == 0)
|
/*
|
||||||
|
Increment block-of-record counter. If it was the first block,
|
||||||
|
remember the position behind the block for the next call.
|
||||||
|
*/
|
||||||
|
if (block_of_record++ == 0)
|
||||||
{
|
{
|
||||||
info->nextpos=block_info.filepos+block_info.block_len;
|
info->nextpos= block_info.filepos + block_info.block_len;
|
||||||
skip_deleted_blocks=0;
|
skip_deleted_blocks= 0;
|
||||||
}
|
}
|
||||||
left_len-=block_info.data_len;
|
left_len-=block_info.data_len;
|
||||||
to+=block_info.data_len;
|
to+=block_info.data_len;
|
||||||
@@ -1484,6 +1580,11 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos)
|
|||||||
|
|
||||||
if (file >= 0)
|
if (file >= 0)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
We do not use my_pread() here because we want to have the file
|
||||||
|
pointer set to the end of the header after this function.
|
||||||
|
my_pread() may leave the file pointer untouched.
|
||||||
|
*/
|
||||||
VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
|
VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
|
||||||
if (my_read(file,(char*) header,sizeof(info->header),MYF(0)) !=
|
if (my_read(file,(char*) header,sizeof(info->header),MYF(0)) !=
|
||||||
sizeof(info->header))
|
sizeof(info->header))
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
||||||
{
|
{
|
||||||
int save_errno,errpos=0;
|
int save_errno,errpos=0;
|
||||||
uint files=0,i,dir_length,length,key_parts;
|
uint files= 0, i, dir_length, length, key_parts, min_keys= 0;
|
||||||
ulonglong file_offset=0;
|
ulonglong file_offset=0;
|
||||||
char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
|
char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
|
||||||
MYRG_INFO *m_info=0;
|
MYRG_INFO *m_info=0;
|
||||||
@@ -89,7 +89,10 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
|||||||
else
|
else
|
||||||
fn_format(buff, buff, "", "", 0);
|
fn_format(buff, buff, "", "", 0);
|
||||||
if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0))))
|
if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0))))
|
||||||
|
{
|
||||||
|
my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
if (!m_info) /* First file */
|
if (!m_info) /* First file */
|
||||||
{
|
{
|
||||||
key_parts=isam->s->base.key_parts;
|
key_parts=isam->s->base.key_parts;
|
||||||
@@ -106,6 +109,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
|||||||
files= 0;
|
files= 0;
|
||||||
}
|
}
|
||||||
m_info->reclength=isam->s->base.reclength;
|
m_info->reclength=isam->s->base.reclength;
|
||||||
|
min_keys= isam->s->base.keys;
|
||||||
errpos=3;
|
errpos=3;
|
||||||
}
|
}
|
||||||
m_info->open_tables[files].table= isam;
|
m_info->open_tables[files].table= isam;
|
||||||
@@ -121,6 +125,8 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
|||||||
m_info->records+= isam->state->records;
|
m_info->records+= isam->state->records;
|
||||||
m_info->del+= isam->state->del;
|
m_info->del+= isam->state->del;
|
||||||
m_info->data_file_length+= isam->state->data_file_length;
|
m_info->data_file_length+= isam->state->data_file_length;
|
||||||
|
if (min_keys > isam->s->base.keys)
|
||||||
|
min_keys= isam->s->base.keys;
|
||||||
for (i=0; i < key_parts; i++)
|
for (i=0; i < key_parts; i++)
|
||||||
m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] /
|
m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] /
|
||||||
m_info->tables);
|
m_info->tables);
|
||||||
@@ -138,7 +144,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
|||||||
my_errno=HA_ERR_RECORD_FILE_FULL;
|
my_errno=HA_ERR_RECORD_FILE_FULL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
m_info->keys= files ? isam->s->base.keys : 0;
|
m_info->keys= min_keys;
|
||||||
bzero((char*) &m_info->by_key,sizeof(m_info->by_key));
|
bzero((char*) &m_info->by_key,sizeof(m_info->by_key));
|
||||||
|
|
||||||
/* this works ok if the table list is empty */
|
/* this works ok if the table list is empty */
|
||||||
|
@@ -51,6 +51,8 @@ int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag)
|
|||||||
error=my_errno;
|
error=my_errno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
my_errno= error= HA_ERR_WRONG_INDEX;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -747,6 +747,27 @@ select export_set(5, name, upper(name), ",", 5) from bug20536;
|
|||||||
export_set(5, name, upper(name), ",", 5)
|
export_set(5, name, upper(name), ",", 5)
|
||||||
test1,TEST1,test1,TEST1,TEST1
|
test1,TEST1,test1,TEST1,TEST1
|
||||||
'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2'
|
'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2'
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
status enum('active','passive') collate latin1_general_ci
|
||||||
|
NOT NULL default 'passive'
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`status` enum('active','passive') character set latin1 collate latin1_general_ci NOT NULL default 'passive'
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
ALTER TABLE t1 ADD a int NOT NULL AFTER status;
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
status enum('active','passive') collate ucs2_turkish_ci
|
||||||
|
NOT NULL default 'passive'
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE `t2` (
|
||||||
|
`status` enum('active','passive') character set ucs2 collate ucs2_turkish_ci NOT NULL default 'passive'
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
ALTER TABLE t2 ADD a int NOT NULL AFTER status;
|
||||||
|
DROP TABLE t1,t2;
|
||||||
select password(name) from bug20536;
|
select password(name) from bug20536;
|
||||||
password(name)
|
password(name)
|
||||||
????????????????????
|
????????????????????
|
||||||
|
@@ -1340,15 +1340,3 @@ select a from t1 group by a;
|
|||||||
a
|
a
|
||||||
e
|
e
|
||||||
drop table t1;
|
drop table t1;
|
||||||
set names utf8;
|
|
||||||
grant select on test.* to юзер_юзер@localhost;
|
|
||||||
user()
|
|
||||||
юзер_юзер@localhost
|
|
||||||
revoke all on test.* from юзер_юзер@localhost;
|
|
||||||
drop user юзер_юзер@localhost;
|
|
||||||
create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45;
|
|
||||||
use имя_базы_в_кодировке_утф8_длиной_больше_чем_45;
|
|
||||||
select database();
|
|
||||||
database()
|
|
||||||
имя_базы_в_кодировке_утф8_длиной_больше_чем_45
|
|
||||||
drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45;
|
|
||||||
|
@@ -6,5 +6,5 @@ drop table t1;
|
|||||||
flush tables;
|
flush tables;
|
||||||
CREATE TABLE t1 (a int) ENGINE=INNODB;
|
CREATE TABLE t1 (a int) ENGINE=INNODB;
|
||||||
SELECT * from T1;
|
SELECT * from T1;
|
||||||
ERROR HY000: Can't open file: 'T1.ibd' (errno: 1)
|
ERROR HY000: Got error 1 from storage engine
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@@ -178,9 +178,9 @@ t3 CREATE TABLE `t3` (
|
|||||||
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
|
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
|
||||||
create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2);
|
create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2);
|
||||||
select * from t4;
|
select * from t4;
|
||||||
ERROR HY000: Can't open file: 't4.MRG' (errno: 143)
|
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists
|
||||||
alter table t4 add column c int;
|
alter table t4 add column c int;
|
||||||
ERROR HY000: Can't open file: 't4.MRG' (errno: 143)
|
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists
|
||||||
create database mysqltest;
|
create database mysqltest;
|
||||||
create table mysqltest.t6 (a int not null primary key auto_increment, message char(20));
|
create table mysqltest.t6 (a int not null primary key auto_increment, message char(20));
|
||||||
create table t5 (a int not null, b char(20), key(a)) engine=MERGE UNION=(test.t1,mysqltest.t6);
|
create table t5 (a int not null, b char(20), key(a)) engine=MERGE UNION=(test.t1,mysqltest.t6);
|
||||||
@@ -766,3 +766,18 @@ Table Op Msg_type Msg_text
|
|||||||
test.t1 check status OK
|
test.t1 check status OK
|
||||||
test.t2 check status OK
|
test.t2 check status OK
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
CREATE TABLE t1(a INT);
|
||||||
|
INSERT INTO t1 VALUES(2),(1);
|
||||||
|
CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1);
|
||||||
|
SELECT * FROM t2 WHERE a=2;
|
||||||
|
ERROR HY000: Got error 124 from storage engine
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
CREATE TABLE t1(a INT) ENGINE=MEMORY;
|
||||||
|
CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1);
|
||||||
|
SELECT * FROM t2;
|
||||||
|
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3);
|
||||||
|
SELECT * FROM t2;
|
||||||
|
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists
|
||||||
|
DROP TABLE t2;
|
||||||
|
@@ -889,3 +889,50 @@ create temporary table if not exists t1 (a1 int);
|
|||||||
execute stmt;
|
execute stmt;
|
||||||
drop temporary table t1;
|
drop temporary table t1;
|
||||||
deallocate prepare stmt;
|
deallocate prepare stmt;
|
||||||
|
CREATE TABLE t1(
|
||||||
|
ID int(10) unsigned NOT NULL auto_increment,
|
||||||
|
Member_ID varchar(15) NOT NULL default '',
|
||||||
|
Action varchar(12) NOT NULL,
|
||||||
|
Action_Date datetime NOT NULL,
|
||||||
|
Track varchar(15) default NULL,
|
||||||
|
User varchar(12) default NULL,
|
||||||
|
Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
|
||||||
|
CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (ID),
|
||||||
|
KEY Action (Action),
|
||||||
|
KEY Action_Date (Action_Date)
|
||||||
|
);
|
||||||
|
INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES
|
||||||
|
('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('111111', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
|
||||||
|
('222222', 'Enrolled', '2006-03-07', 'CAD' ),
|
||||||
|
('222222', 'Enrolled', '2006-03-07', 'CHF' ),
|
||||||
|
('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
|
||||||
|
('333333', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('444444', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('555555', 'Enrolled', '2006-07-21', 'CAD' ),
|
||||||
|
('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
|
||||||
|
('666666', 'Enrolled', '2006-02-09', 'CAD' ),
|
||||||
|
('666666', 'Enrolled', '2006-05-12', 'CHF' ),
|
||||||
|
('666666', 'Disenrolled', '2006-06-01', 'CAD' );
|
||||||
|
PREPARE STMT FROM
|
||||||
|
"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1
|
||||||
|
WHERE Member_ID=? AND Action='Enrolled' AND
|
||||||
|
(Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1
|
||||||
|
WHERE Member_ID=?
|
||||||
|
GROUP BY Track
|
||||||
|
HAVING Track>='CAD' AND
|
||||||
|
MAX(Action_Date)>'2006-03-01')";
|
||||||
|
SET @id='111111';
|
||||||
|
EXECUTE STMT USING @id,@id;
|
||||||
|
GROUP_CONCAT(Track SEPARATOR ', ')
|
||||||
|
NULL
|
||||||
|
SET @id='222222';
|
||||||
|
EXECUTE STMT USING @id,@id;
|
||||||
|
GROUP_CONCAT(Track SEPARATOR ', ')
|
||||||
|
CAD
|
||||||
|
DEALLOCATE PREPARE STMT;
|
||||||
|
DROP TABLE t1;
|
||||||
|
@@ -31,7 +31,7 @@ create table t1 engine=myisam SELECT 1,"table 1";
|
|||||||
flush tables;
|
flush tables;
|
||||||
repair table t1;
|
repair table t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 repair error Can't open file: 't1.MYI' (errno: 130)
|
test.t1 repair error Got error 130 from storage engine
|
||||||
repair table t1 use_frm;
|
repair table t1 use_frm;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 repair warning Number of rows changed from 0 to 1
|
test.t1 repair warning Number of rows changed from 0 to 1
|
||||||
|
@@ -2946,3 +2946,39 @@ ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10;
|
|||||||
a a b
|
a a b
|
||||||
10 1 359
|
10 1 359
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
field1 int NOT NULL,
|
||||||
|
field2 int NOT NULL,
|
||||||
|
field3 int NOT NULL,
|
||||||
|
PRIMARY KEY (field1,field2,field3)
|
||||||
|
);
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
fieldA int NOT NULL,
|
||||||
|
fieldB int NOT NULL,
|
||||||
|
PRIMARY KEY (fieldA,fieldB)
|
||||||
|
);
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1);
|
||||||
|
INSERT INTO t2 VALUES (1,1), (1,2), (1,3);
|
||||||
|
SELECT field1, field2, COUNT(*)
|
||||||
|
FROM t1 GROUP BY field1, field2;
|
||||||
|
field1 field2 COUNT(*)
|
||||||
|
1 1 2
|
||||||
|
1 2 3
|
||||||
|
1 3 1
|
||||||
|
SELECT field1, field2
|
||||||
|
FROM t1
|
||||||
|
GROUP BY field1, field2
|
||||||
|
HAVING COUNT(*) >= ALL (SELECT fieldB
|
||||||
|
FROM t2 WHERE fieldA = field1);
|
||||||
|
field1 field2
|
||||||
|
1 2
|
||||||
|
SELECT field1, field2
|
||||||
|
FROM t1
|
||||||
|
GROUP BY field1, field2
|
||||||
|
HAVING COUNT(*) < ANY (SELECT fieldB
|
||||||
|
FROM t2 WHERE fieldA = field1);
|
||||||
|
field1 field2
|
||||||
|
1 1
|
||||||
|
1 3
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
@@ -482,6 +482,27 @@ select make_set(3, name, upper(name)) from bug20536;
|
|||||||
select export_set(5, name, upper(name)) from bug20536;
|
select export_set(5, name, upper(name)) from bug20536;
|
||||||
select export_set(5, name, upper(name), ",", 5) from bug20536;
|
select export_set(5, name, upper(name), ",", 5) from bug20536;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #20108: corrupted default enum value for a ucs2 field
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
status enum('active','passive') collate latin1_general_ci
|
||||||
|
NOT NULL default 'passive'
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
ALTER TABLE t1 ADD a int NOT NULL AFTER status;
|
||||||
|
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
status enum('active','passive') collate ucs2_turkish_ci
|
||||||
|
NOT NULL default 'passive'
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
ALTER TABLE t2 ADD a int NOT NULL AFTER status;
|
||||||
|
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
|
||||||
# Some broken functions: add these tests just to document current behavior.
|
# Some broken functions: add these tests just to document current behavior.
|
||||||
|
|
||||||
# PASSWORD and OLD_PASSWORD don't work with UCS2 strings, but to fix it would
|
# PASSWORD and OLD_PASSWORD don't work with UCS2 strings, but to fix it would
|
||||||
|
@@ -1072,20 +1072,4 @@ explain select a from t1 group by a;
|
|||||||
select a from t1 group by a;
|
select a from t1 group by a;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
#
|
|
||||||
# Bug#20393: User name truncation in mysql client
|
|
||||||
# Bug#21432: Database/Table name limited to 64 bytes, not chars, problems with multi-byte
|
|
||||||
#
|
|
||||||
set names utf8;
|
|
||||||
#create user юзер_юзер@localhost;
|
|
||||||
grant select on test.* to юзер_юзер@localhost;
|
|
||||||
--exec $MYSQL --default-character-set=utf8 --user=юзер_юзер -e "select user()"
|
|
||||||
revoke all on test.* from юзер_юзер@localhost;
|
|
||||||
drop user юзер_юзер@localhost;
|
|
||||||
|
|
||||||
create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45;
|
|
||||||
use имя_базы_в_кодировке_утф8_длиной_больше_чем_45;
|
|
||||||
select database();
|
|
||||||
drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45;
|
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
@@ -32,7 +32,7 @@ flush tables;
|
|||||||
#
|
#
|
||||||
|
|
||||||
CREATE TABLE t1 (a int) ENGINE=INNODB;
|
CREATE TABLE t1 (a int) ENGINE=INNODB;
|
||||||
--error 1016
|
--error 1030
|
||||||
SELECT * from T1;
|
SELECT * from T1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
@@ -47,9 +47,9 @@ show create table t3;
|
|||||||
|
|
||||||
# The following should give errors
|
# The following should give errors
|
||||||
create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2);
|
create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2);
|
||||||
--error 1016
|
--error 1168
|
||||||
select * from t4;
|
select * from t4;
|
||||||
--error 1016
|
--error 1168
|
||||||
alter table t4 add column c int;
|
alter table t4 add column c int;
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -376,4 +376,29 @@ select * from t3;
|
|||||||
check table t1, t2;
|
check table t1, t2;
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#21617 - crash when selecting from merge table with inconsistent
|
||||||
|
# indexes
|
||||||
|
#
|
||||||
|
CREATE TABLE t1(a INT);
|
||||||
|
INSERT INTO t1 VALUES(2),(1);
|
||||||
|
CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1);
|
||||||
|
--error 1030
|
||||||
|
SELECT * FROM t2 WHERE a=2;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#10974 - No error message if merge table based on union of innodb,
|
||||||
|
# memory
|
||||||
|
#
|
||||||
|
CREATE TABLE t1(a INT) ENGINE=MEMORY;
|
||||||
|
CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1);
|
||||||
|
--error 1168
|
||||||
|
SELECT * FROM t2;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3);
|
||||||
|
--error 1168
|
||||||
|
SELECT * FROM t2;
|
||||||
|
DROP TABLE t2;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
@@ -951,4 +951,56 @@ execute stmt;
|
|||||||
drop temporary table t1;
|
drop temporary table t1;
|
||||||
deallocate prepare stmt;
|
deallocate prepare stmt;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#22085: Crash on the execution of a prepared statement that
|
||||||
|
# uses an IN subquery with aggregate functions in HAVING
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1(
|
||||||
|
ID int(10) unsigned NOT NULL auto_increment,
|
||||||
|
Member_ID varchar(15) NOT NULL default '',
|
||||||
|
Action varchar(12) NOT NULL,
|
||||||
|
Action_Date datetime NOT NULL,
|
||||||
|
Track varchar(15) default NULL,
|
||||||
|
User varchar(12) default NULL,
|
||||||
|
Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
|
||||||
|
CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (ID),
|
||||||
|
KEY Action (Action),
|
||||||
|
KEY Action_Date (Action_Date)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES
|
||||||
|
('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('111111', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
|
||||||
|
('222222', 'Enrolled', '2006-03-07', 'CAD' ),
|
||||||
|
('222222', 'Enrolled', '2006-03-07', 'CHF' ),
|
||||||
|
('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
|
||||||
|
('333333', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('444444', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||||
|
('555555', 'Enrolled', '2006-07-21', 'CAD' ),
|
||||||
|
('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
|
||||||
|
('666666', 'Enrolled', '2006-02-09', 'CAD' ),
|
||||||
|
('666666', 'Enrolled', '2006-05-12', 'CHF' ),
|
||||||
|
('666666', 'Disenrolled', '2006-06-01', 'CAD' );
|
||||||
|
|
||||||
|
PREPARE STMT FROM
|
||||||
|
"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1
|
||||||
|
WHERE Member_ID=? AND Action='Enrolled' AND
|
||||||
|
(Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1
|
||||||
|
WHERE Member_ID=?
|
||||||
|
GROUP BY Track
|
||||||
|
HAVING Track>='CAD' AND
|
||||||
|
MAX(Action_Date)>'2006-03-01')";
|
||||||
|
SET @id='111111';
|
||||||
|
EXECUTE STMT USING @id,@id;
|
||||||
|
SET @id='222222';
|
||||||
|
EXECUTE STMT USING @id,@id;
|
||||||
|
|
||||||
|
DEALLOCATE PREPARE STMT;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
@@ -1911,4 +1911,41 @@ SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r
|
|||||||
|
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #21853: assert failure for a grouping query with
|
||||||
|
# an ALL/ANY quantified subquery in HAVING
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
field1 int NOT NULL,
|
||||||
|
field2 int NOT NULL,
|
||||||
|
field3 int NOT NULL,
|
||||||
|
PRIMARY KEY (field1,field2,field3)
|
||||||
|
);
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
fieldA int NOT NULL,
|
||||||
|
fieldB int NOT NULL,
|
||||||
|
PRIMARY KEY (fieldA,fieldB)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1);
|
||||||
|
INSERT INTO t2 VALUES (1,1), (1,2), (1,3);
|
||||||
|
|
||||||
|
SELECT field1, field2, COUNT(*)
|
||||||
|
FROM t1 GROUP BY field1, field2;
|
||||||
|
|
||||||
|
SELECT field1, field2
|
||||||
|
FROM t1
|
||||||
|
GROUP BY field1, field2
|
||||||
|
HAVING COUNT(*) >= ALL (SELECT fieldB
|
||||||
|
FROM t2 WHERE fieldA = field1);
|
||||||
|
SELECT field1, field2
|
||||||
|
FROM t1
|
||||||
|
GROUP BY field1, field2
|
||||||
|
HAVING COUNT(*) < ANY (SELECT fieldB
|
||||||
|
FROM t2 WHERE fieldA = field1);
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
@@ -44,7 +44,9 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
|
|||||||
DBUG_PRINT("my",("fd: %d length: %lu MyFlags: %d",fd,(ulong) newlength,
|
DBUG_PRINT("my",("fd: %d length: %lu MyFlags: %d",fd,(ulong) newlength,
|
||||||
MyFlags));
|
MyFlags));
|
||||||
|
|
||||||
oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
|
if ((oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE))) == newlength)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize));
|
DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize));
|
||||||
|
|
||||||
if (oldsize > newlength)
|
if (oldsize > newlength)
|
||||||
|
@@ -164,28 +164,22 @@ void delete_queue(QUEUE *queue)
|
|||||||
|
|
||||||
void queue_insert(register QUEUE *queue, byte *element)
|
void queue_insert(register QUEUE *queue, byte *element)
|
||||||
{
|
{
|
||||||
reg2 uint idx,next;
|
reg2 uint idx, next;
|
||||||
int cmp;
|
int cmp;
|
||||||
|
DBUG_ASSERT(queue->elements < queue->max_elements);
|
||||||
#ifndef DBUG_OFF
|
queue->root[0]= element;
|
||||||
if (queue->elements < queue->max_elements)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
queue->root[0]=element;
|
|
||||||
idx= ++queue->elements;
|
idx= ++queue->elements;
|
||||||
|
|
||||||
/* max_at_top swaps the comparison if we want to order by desc */
|
/* max_at_top swaps the comparison if we want to order by desc */
|
||||||
while ((cmp=queue->compare(queue->first_cmp_arg,
|
while ((cmp= queue->compare(queue->first_cmp_arg,
|
||||||
element+queue->offset_to_key,
|
element + queue->offset_to_key,
|
||||||
queue->root[(next=idx >> 1)] +
|
queue->root[(next= idx >> 1)] +
|
||||||
queue->offset_to_key)) &&
|
queue->offset_to_key)) &&
|
||||||
(cmp ^ queue->max_at_top) < 0)
|
(cmp ^ queue->max_at_top) < 0)
|
||||||
{
|
{
|
||||||
queue->root[idx]=queue->root[next];
|
queue->root[idx]= queue->root[next];
|
||||||
idx=next;
|
idx= next;
|
||||||
}
|
|
||||||
queue->root[idx]=element;
|
|
||||||
}
|
}
|
||||||
|
queue->root[idx]= element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove item from queue */
|
/* Remove item from queue */
|
||||||
@@ -193,16 +187,12 @@ void queue_insert(register QUEUE *queue, byte *element)
|
|||||||
|
|
||||||
byte *queue_remove(register QUEUE *queue, uint idx)
|
byte *queue_remove(register QUEUE *queue, uint idx)
|
||||||
{
|
{
|
||||||
#ifndef DBUG_OFF
|
byte *element;
|
||||||
if (idx >= queue->max_elements)
|
DBUG_ASSERT(idx < queue->max_elements);
|
||||||
return 0;
|
element= queue->root[++idx]; /* Intern index starts from 1 */
|
||||||
#endif
|
queue->root[idx]= queue->root[queue->elements--];
|
||||||
{
|
_downheap(queue, idx);
|
||||||
byte *element=queue->root[++idx]; /* Intern index starts from 1 */
|
|
||||||
queue->root[idx]=queue->root[queue->elements--];
|
|
||||||
_downheap(queue,idx);
|
|
||||||
return element;
|
return element;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix when element on top has been replaced */
|
/* Fix when element on top has been replaced */
|
||||||
|
@@ -1618,7 +1618,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
|||||||
const char *passwd, const char *db,
|
const char *passwd, const char *db,
|
||||||
uint port, const char *unix_socket,ulong client_flag)
|
uint port, const char *unix_socket,ulong client_flag)
|
||||||
{
|
{
|
||||||
char buff[NAME_BYTE_LEN+USERNAME_BYTE_LENGTH+100];
|
char buff[NAME_LEN+USERNAME_LENGTH+100];
|
||||||
char *end,*host_info;
|
char *end,*host_info;
|
||||||
my_socket sock;
|
my_socket sock;
|
||||||
in_addr_t ip_addr;
|
in_addr_t ip_addr;
|
||||||
@@ -2063,7 +2063,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
|||||||
mysql->server_status, client_flag));
|
mysql->server_status, client_flag));
|
||||||
/* This needs to be changed as it's not useful with big packets */
|
/* This needs to be changed as it's not useful with big packets */
|
||||||
if (user && user[0])
|
if (user && user[0])
|
||||||
strmake(end,user,USERNAME_BYTE_LENGTH); /* Max user name */
|
strmake(end,user,USERNAME_LENGTH); /* Max user name */
|
||||||
else
|
else
|
||||||
read_user_name((char*) end);
|
read_user_name((char*) end);
|
||||||
|
|
||||||
@@ -2093,7 +2093,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
|||||||
/* Add database if needed */
|
/* Add database if needed */
|
||||||
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
|
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
|
||||||
{
|
{
|
||||||
end= strmake(end, db, NAME_BYTE_LEN) + 1;
|
end= strmake(end, db, NAME_LEN) + 1;
|
||||||
mysql->db= my_strdup(db,MYF(MY_WME));
|
mysql->db= my_strdup(db,MYF(MY_WME));
|
||||||
db= 0;
|
db= 0;
|
||||||
}
|
}
|
||||||
|
@@ -1192,6 +1192,8 @@ public:
|
|||||||
uint decimals,flags,pack_length;
|
uint decimals,flags,pack_length;
|
||||||
Field::utype unireg_check;
|
Field::utype unireg_check;
|
||||||
TYPELIB *interval; // Which interval to use
|
TYPELIB *interval; // Which interval to use
|
||||||
|
TYPELIB *save_interval; // Temporary copy for the above
|
||||||
|
// Used only for UCS2 intervals
|
||||||
List<String> interval_list;
|
List<String> interval_list;
|
||||||
CHARSET_INFO *charset;
|
CHARSET_INFO *charset;
|
||||||
Field::geometry_type geom_type;
|
Field::geometry_type geom_type;
|
||||||
|
@@ -387,6 +387,7 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
|
|||||||
}
|
}
|
||||||
else if ((type() == SUM_FUNC_ITEM ||
|
else if ((type() == SUM_FUNC_ITEM ||
|
||||||
(used_tables() & ~PARAM_TABLE_BIT)) &&
|
(used_tables() & ~PARAM_TABLE_BIT)) &&
|
||||||
|
type() != SUBSELECT_ITEM &&
|
||||||
type() != REF_ITEM)
|
type() != REF_ITEM)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@@ -184,7 +184,7 @@ character-set=latin1
|
|||||||
"INSERT DELAYED can't be used with table '%-.64s' because it is locked with LOCK TABLES",
|
"INSERT DELAYED can't be used with table '%-.64s' because it is locked with LOCK TABLES",
|
||||||
"Incorrect column name '%-.100s'",
|
"Incorrect column name '%-.100s'",
|
||||||
"The used storage engine can't index column '%-.64s'",
|
"The used storage engine can't index column '%-.64s'",
|
||||||
"All tables in the MERGE table are not identically defined",
|
"Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists",
|
||||||
"Can't write, because of unique constraint, to table '%-.64s'",
|
"Can't write, because of unique constraint, to table '%-.64s'",
|
||||||
"BLOB/TEXT column '%-.64s' used in key specification without a key length",
|
"BLOB/TEXT column '%-.64s' used in key specification without a key length",
|
||||||
"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",
|
||||||
|
@@ -2640,11 +2640,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
|
|||||||
while ((Str = str_list++))
|
while ((Str = str_list++))
|
||||||
{
|
{
|
||||||
if (Str->host.length > HOSTNAME_LENGTH ||
|
if (Str->host.length > HOSTNAME_LENGTH ||
|
||||||
system_charset_info->cset->charpos(system_charset_info,
|
Str->user.length > USERNAME_LENGTH)
|
||||||
Str->user.str,
|
|
||||||
Str->user.str +
|
|
||||||
Str->user.length,
|
|
||||||
USERNAME_LENGTH) < Str->user.length)
|
|
||||||
{
|
{
|
||||||
my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0));
|
my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0));
|
||||||
result= -1;
|
result= -1;
|
||||||
|
@@ -902,8 +902,8 @@ static int check_connection(THD *thd)
|
|||||||
char *user= end;
|
char *user= end;
|
||||||
char *passwd= strend(user)+1;
|
char *passwd= strend(user)+1;
|
||||||
char *db= passwd;
|
char *db= passwd;
|
||||||
char db_buff[NAME_BYTE_LEN + 1]; // buffer to store db in utf8
|
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
|
||||||
char user_buff[USERNAME_BYTE_LENGTH + 1]; // buffer to store user in utf8
|
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
|
||||||
uint dummy_errors;
|
uint dummy_errors;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -290,8 +290,6 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
if (having_fix_rc || thd->net.report_error)
|
if (having_fix_rc || thd->net.report_error)
|
||||||
DBUG_RETURN(-1); /* purecov: inspected */
|
DBUG_RETURN(-1); /* purecov: inspected */
|
||||||
if (having->with_sum_func)
|
|
||||||
having->split_sum_func2(thd, ref_pointer_array, all_fields, &having);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it subselect
|
// Is it subselect
|
||||||
@@ -306,6 +304,9 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (having && having->with_sum_func)
|
||||||
|
having->split_sum_func2(thd, ref_pointer_array, all_fields, &having);
|
||||||
|
|
||||||
if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
|
if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
|
13
sql/table.cc
13
sql/table.cc
@@ -77,6 +77,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
|
|||||||
my_string record;
|
my_string record;
|
||||||
const char **int_array;
|
const char **int_array;
|
||||||
bool use_hash, null_field_first;
|
bool use_hash, null_field_first;
|
||||||
|
bool error_reported= FALSE;
|
||||||
File file;
|
File file;
|
||||||
Field **field_ptr,*reg_field;
|
Field **field_ptr,*reg_field;
|
||||||
KEY *keyinfo;
|
KEY *keyinfo;
|
||||||
@@ -791,6 +792,11 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
|
|||||||
error= 1;
|
error= 1;
|
||||||
my_errno= ENOENT;
|
my_errno= ENOENT;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outparam->file->print_error(err, MYF(0));
|
||||||
|
error_reported= TRUE;
|
||||||
|
}
|
||||||
goto err_not_open; /* purecov: inspected */
|
goto err_not_open; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -812,6 +818,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
|
|||||||
err_end: /* Here when no file */
|
err_end: /* Here when no file */
|
||||||
delete crypted;
|
delete crypted;
|
||||||
*root_ptr= old_root;
|
*root_ptr= old_root;
|
||||||
|
if (!error_reported)
|
||||||
frm_error(error, outparam, name, ME_ERROR + ME_WAITTANG, errarg);
|
frm_error(error, outparam, name, ME_ERROR + ME_WAITTANG, errarg);
|
||||||
delete outparam->file;
|
delete outparam->file;
|
||||||
outparam->file=0; // For easyer errorchecking
|
outparam->file=0; // For easyer errorchecking
|
||||||
@@ -1413,7 +1420,7 @@ char *get_field(MEM_ROOT *mem, Field *field)
|
|||||||
|
|
||||||
bool check_db_name(char *name)
|
bool check_db_name(char *name)
|
||||||
{
|
{
|
||||||
uint name_length= 0; // name length in symbols
|
char *start= name;
|
||||||
/* Used to catch empty names and names with end space */
|
/* Used to catch empty names and names with end space */
|
||||||
bool last_char_is_space= TRUE;
|
bool last_char_is_space= TRUE;
|
||||||
|
|
||||||
@@ -1430,7 +1437,6 @@ bool check_db_name(char *name)
|
|||||||
name+system_charset_info->mbmaxlen);
|
name+system_charset_info->mbmaxlen);
|
||||||
if (len)
|
if (len)
|
||||||
{
|
{
|
||||||
name_length++;
|
|
||||||
name += len;
|
name += len;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1438,13 +1444,12 @@ bool check_db_name(char *name)
|
|||||||
#else
|
#else
|
||||||
last_char_is_space= *name==' ';
|
last_char_is_space= *name==' ';
|
||||||
#endif
|
#endif
|
||||||
name_length++;
|
|
||||||
if (*name == '/' || *name == '\\' || *name == FN_LIBCHAR ||
|
if (*name == '/' || *name == '\\' || *name == FN_LIBCHAR ||
|
||||||
*name == FN_EXTCHAR)
|
*name == FN_EXTCHAR)
|
||||||
return 1;
|
return 1;
|
||||||
name++;
|
name++;
|
||||||
}
|
}
|
||||||
return (last_char_is_space || name_length > NAME_LEN);
|
return last_char_is_space || (uint) (name - start) > NAME_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -190,13 +190,19 @@ bool mysql_create_frm(THD *thd, my_string file_name,
|
|||||||
goto err3;
|
goto err3;
|
||||||
|
|
||||||
{
|
{
|
||||||
/* Unescape all UCS2 intervals: were escaped in pack_headers */
|
/*
|
||||||
|
Restore all UCS2 intervals.
|
||||||
|
HEX representation of them is not needed anymore.
|
||||||
|
*/
|
||||||
List_iterator<create_field> it(create_fields);
|
List_iterator<create_field> it(create_fields);
|
||||||
create_field *field;
|
create_field *field;
|
||||||
while ((field=it++))
|
while ((field=it++))
|
||||||
{
|
{
|
||||||
if (field->interval && field->charset->mbminlen > 1)
|
if (field->save_interval)
|
||||||
unhex_type2(field->interval);
|
{
|
||||||
|
field->interval= field->save_interval;
|
||||||
|
field->save_interval= 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@@ -452,18 +458,36 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
|
|||||||
reclength=(uint) (field->offset+ data_offset + length);
|
reclength=(uint) (field->offset+ data_offset + length);
|
||||||
n_length+= (ulong) strlen(field->field_name)+1;
|
n_length+= (ulong) strlen(field->field_name)+1;
|
||||||
field->interval_id=0;
|
field->interval_id=0;
|
||||||
|
field->save_interval= 0;
|
||||||
if (field->interval)
|
if (field->interval)
|
||||||
{
|
{
|
||||||
uint old_int_count=int_count;
|
uint old_int_count=int_count;
|
||||||
|
|
||||||
if (field->charset->mbminlen > 1)
|
if (field->charset->mbminlen > 1)
|
||||||
{
|
{
|
||||||
/* Escape UCS2 intervals using HEX notation */
|
/*
|
||||||
|
Escape UCS2 intervals using HEX notation to avoid
|
||||||
|
problems with delimiters between enum elements.
|
||||||
|
As the original representation is still needed in
|
||||||
|
the function make_empty_rec to create a record of
|
||||||
|
filled with default values it is saved in save_interval
|
||||||
|
The HEX representation is created from this copy.
|
||||||
|
*/
|
||||||
|
field->save_interval= field->interval;
|
||||||
|
field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB));
|
||||||
|
*field->interval= *field->save_interval;
|
||||||
|
field->interval->type_names=
|
||||||
|
(const char **) sql_alloc(sizeof(char*) *
|
||||||
|
(field->interval->count+1));
|
||||||
|
field->interval->type_names[field->interval->count]= 0;
|
||||||
|
field->interval->type_lengths=
|
||||||
|
(uint *) sql_alloc(sizeof(uint) * field->interval->count);
|
||||||
|
|
||||||
for (uint pos= 0; pos < field->interval->count; pos++)
|
for (uint pos= 0; pos < field->interval->count; pos++)
|
||||||
{
|
{
|
||||||
char *dst;
|
char *dst;
|
||||||
uint length= field->interval->type_lengths[pos], hex_length;
|
uint length= field->save_interval->type_lengths[pos], hex_length;
|
||||||
const char *src= field->interval->type_names[pos];
|
const char *src= field->save_interval->type_names[pos];
|
||||||
const char *srcend= src + length;
|
const char *srcend= src + length;
|
||||||
hex_length= length * 2;
|
hex_length= length * 2;
|
||||||
field->interval->type_lengths[pos]= hex_length;
|
field->interval->type_lengths[pos]= hex_length;
|
||||||
@@ -715,6 +739,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
|
|||||||
field->charset,
|
field->charset,
|
||||||
field->geom_type,
|
field->geom_type,
|
||||||
field->unireg_check,
|
field->unireg_check,
|
||||||
|
field->save_interval ? field->save_interval :
|
||||||
field->interval,
|
field->interval,
|
||||||
field->field_name,
|
field->field_name,
|
||||||
&table);
|
&table);
|
||||||
|
Reference in New Issue
Block a user