Commit 40c146f6 authored by unknown's avatar unknown

merge


sql/mysqld.cc:
  Auto merged
sql/sql_delete.cc:
  Auto merged
sql/sql_parse.cc:
  Auto merged
parents 62f9d3c2 f015cbdc
...@@ -451,3 +451,4 @@ vio/test-ssl ...@@ -451,3 +451,4 @@ vio/test-ssl
vio/test-sslclient vio/test-sslclient
vio/test-sslserver vio/test-sslserver
vio/viotest-ssl vio/viotest-ssl
libmysqld/ha_innodb.cc
This diff is collapsed.
...@@ -79,9 +79,11 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, ...@@ -79,9 +79,11 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
} }
DBUG_PRINT("info", DBUG_PRINT("info",
("records: %ld seeks: %d max links: %d hitrate: %.2f", ("records: %ld seeks: %d max links: %d hitrate: %.2f",
records,seek,max_links,(float) seek / (float) (records ? records : 1))); records,seek,max_links,
(float) seek / (float) (records ? records : 1)));
if (print_status) if (print_status)
printf("Key: %d records: %ld seeks: %d max links: %d hitrate: %.2f\n", printf("Key: %d records: %ld seeks: %d max links: %d hitrate: %.2f\n",
keynr, records, seek, max_links, (float) seek / (float) records); keynr, records, seek, max_links,
(float) seek / (float) (records ? records : 1));
return error; return error;
} }
...@@ -70,6 +70,7 @@ extern int _hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1, ...@@ -70,6 +70,7 @@ extern int _hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
extern int _hp_key_cmp(HP_KEYDEF *keydef,const byte *rec, extern int _hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
const byte *key); const byte *key);
extern void _hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec); extern void _hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
extern int _hp_close(register HP_INFO *info); extern int _hp_close(register HP_INFO *info);
extern void _hp_clear(HP_SHARE *info); extern void _hp_clear(HP_SHARE *info);
......
...@@ -158,11 +158,22 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key) ...@@ -158,11 +158,22 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{ {
uchar *pos=(uchar*) key; uchar *pos=(uchar*) key;
key+=seg->length; key+=seg->length;
if (seg->null_bit)
{
key++; /* Skipp null byte */
if (*pos) /* Found null */
{
nr^= (nr << 1) | 1;
continue;
}
pos++;
}
if (seg->type == HA_KEYTYPE_TEXT) if (seg->type == HA_KEYTYPE_TEXT)
{ {
for (; pos < (uchar*) key ; pos++) for (; pos < (uchar*) key ; pos++)
{ {
nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) my_sort_order[(uint) *pos]))+ (nr << 8); nr^=(ulong) ((((uint) nr & 63)+nr2) *
((uint) my_sort_order[(uint) *pos])) + (nr << 8);
nr2+=3; nr2+=3;
} }
} }
...@@ -170,7 +181,7 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key) ...@@ -170,7 +181,7 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{ {
for (; pos < (uchar*) key ; pos++) for (; pos < (uchar*) key ; pos++)
{ {
nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos))+ (nr << 8); nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos)) + (nr << 8);
nr2+=3; nr2+=3;
} }
} }
...@@ -188,11 +199,20 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec) ...@@ -188,11 +199,20 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++) for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{ {
uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length; uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
if (seg->null_bit)
{
if (rec[seg->null_pos] & seg->null_bit)
{
nr^= (nr << 1) | 1;
continue;
}
}
if (seg->type == HA_KEYTYPE_TEXT) if (seg->type == HA_KEYTYPE_TEXT)
{ {
for (; pos < end ; pos++) for (; pos < end ; pos++)
{ {
nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) my_sort_order[(uint) *pos]))+ (nr << 8); nr^=(ulong) ((((uint) nr & 63)+nr2)*
((uint) my_sort_order[(uint) *pos]))+ (nr << 8);
nr2+=3; nr2+=3;
} }
} }
...@@ -234,6 +254,16 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key) ...@@ -234,6 +254,16 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{ {
uchar *pos=(uchar*) key; uchar *pos=(uchar*) key;
key+=seg->length; key+=seg->length;
if (seg->null_bit)
{
key++;
if (*pos)
{
nr^= (nr << 1) | 1;
continue;
}
pos++;
}
if (seg->type == HA_KEYTYPE_TEXT) if (seg->type == HA_KEYTYPE_TEXT)
{ {
for (; pos < (uchar*) key ; pos++) for (; pos < (uchar*) key ; pos++)
...@@ -264,6 +294,14 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec) ...@@ -264,6 +294,14 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++) for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{ {
uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length; uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
if (seg->null_bit)
{
if (rec[seg->null_pos] & seg->null_bit)
{
nr^= (nr << 1) | 1;
continue;
}
}
if (seg->type == HA_KEYTYPE_TEXT) if (seg->type == HA_KEYTYPE_TEXT)
{ {
for ( ; pos < end ; pos++) for ( ; pos < end ; pos++)
...@@ -295,6 +333,14 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2) ...@@ -295,6 +333,14 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++) for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{ {
if (seg->null_bit)
{
if ((rec1[seg->null_pos] & seg->null_bit) !=
(rec2[seg->null_pos] & seg->null_bit))
return 1;
if (rec1[seg->null_pos] & seg->null_bit)
continue;
}
if (seg->type == HA_KEYTYPE_TEXT) if (seg->type == HA_KEYTYPE_TEXT)
{ {
if (my_sortcmp(rec1+seg->start,rec2+seg->start,seg->length)) if (my_sortcmp(rec1+seg->start,rec2+seg->start,seg->length))
...@@ -309,14 +355,24 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2) ...@@ -309,14 +355,24 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
return 0; return 0;
} }
/* Compare a key in a record to a hole key */ /* Compare a key in a record to a whole key */
int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key) int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
{ {
HP_KEYSEG *seg,*endseg; HP_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++) for (seg=keydef->seg,endseg=seg+keydef->keysegs ;
seg < endseg ;
key+= (seg++)->length)
{
if (seg->null_bit)
{ {
int found_null=test(rec[seg->null_pos] & seg->null_bit);
if (found_null != (int) *key++)
return 1;
if (found_null)
continue;
}
if (seg->type == HA_KEYTYPE_TEXT) if (seg->type == HA_KEYTYPE_TEXT)
{ {
if (my_sortcmp(rec+seg->start,key,seg->length)) if (my_sortcmp(rec+seg->start,key,seg->length))
...@@ -327,7 +383,6 @@ int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key) ...@@ -327,7 +383,6 @@ int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
if (bcmp(rec+seg->start,key,seg->length)) if (bcmp(rec+seg->start,key,seg->length))
return 1; return 1;
} }
key+=seg->length;
} }
return 0; return 0;
} }
...@@ -341,7 +396,28 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec) ...@@ -341,7 +396,28 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++) for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{ {
if (seg->null_bit)
*key++= test(rec[seg->null_pos] & seg->null_bit);
memcpy(key,rec+seg->start,(size_t) seg->length); memcpy(key,rec+seg->start,(size_t) seg->length);
key+=seg->length; key+=seg->length;
} }
} }
/*
Test if any of the key parts are NULL.
Return:
1 if any of the key parts was NULL
0 otherwise
*/
my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record)
{
HP_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
if (seg->null_bit && (record[seg->null_pos] & seg->null_bit))
return 1;
}
return 0;
}
...@@ -44,7 +44,12 @@ HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef, ...@@ -44,7 +44,12 @@ HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
key_segs+= keydef[i].keysegs; key_segs+= keydef[i].keysegs;
bzero((char*) &keydef[i].block,sizeof(keydef[i].block)); bzero((char*) &keydef[i].block,sizeof(keydef[i].block));
for (j=length=0 ; j < keydef[i].keysegs; j++) for (j=length=0 ; j < keydef[i].keysegs; j++)
{
length+=keydef[i].seg[j].length; length+=keydef[i].seg[j].length;
if (keydef[i].seg[j].null_bit &&
!(keydef[i].flag & HA_NULL_ARE_EQUAL))
keydef[i].flag |= HA_NULL_PART_KEY;
}
keydef[i].length=length; keydef[i].length=length;
if (length > max_length) if (length > max_length)
max_length=length; max_length=length;
......
...@@ -20,7 +20,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key) ...@@ -20,7 +20,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
{ {
byte *pos; byte *pos;
HP_SHARE *share=info->s; HP_SHARE *share=info->s;
DBUG_ENTER("hp_rkey"); DBUG_ENTER("heap_rkey");
DBUG_PRINT("enter",("base: %lx inx: %d",info,inx)); DBUG_PRINT("enter",("base: %lx inx: %d",info,inx));
if ((uint) inx >= share->keys) if ((uint) inx >= share->keys)
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <signal.h> #include <signal.h>
#define MAX_RECORDS 100000 #define MAX_RECORDS 100000
#define MAX_KEYS 3 #define MAX_KEYS 4
static int get_options(int argc, char *argv[]); static int get_options(int argc, char *argv[]);
static int rnd(int max_value); static int rnd(int max_value);
...@@ -40,16 +40,20 @@ static uint flag=0,verbose=0,testflag=0,recant=10000,silent=0; ...@@ -40,16 +40,20 @@ static uint flag=0,verbose=0,testflag=0,recant=10000,silent=0;
static uint keys=MAX_KEYS; static uint keys=MAX_KEYS;
static uint16 key1[1001]; static uint16 key1[1001];
static my_bool key3[MAX_RECORDS]; static my_bool key3[MAX_RECORDS];
static int reclength=39;
static int calc_check(byte *buf,uint length); static int calc_check(byte *buf,uint length);
static void make_record(char *record, uint n1, uint n2, uint n3,
const char *mark, uint count);
/* Huvudprogrammet */ /* Main program */
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
register uint i,j; register uint i,j;
uint ant,n1,n2,n3; uint ant,n1,n2,n3;
uint reclength,write_count,update,opt_delete,check2,dupp_keys,found_key; uint write_count,update,opt_delete,check2,dupp_keys,found_key;
int error; int error;
ulong pos; ulong pos;
unsigned long key_check; unsigned long key_check;
...@@ -66,7 +70,6 @@ int main(int argc, char *argv[]) ...@@ -66,7 +70,6 @@ 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);
reclength=37;
write_count=update=opt_delete=0; write_count=update=opt_delete=0;
key_check=0; key_check=0;
...@@ -77,21 +80,33 @@ int main(int argc, char *argv[]) ...@@ -77,21 +80,33 @@ int main(int argc, char *argv[])
keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY; keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[0].seg[0].start=0; keyinfo[0].seg[0].start=0;
keyinfo[0].seg[0].length=6; keyinfo[0].seg[0].length=6;
keyinfo[0].seg[0].null_bit=0;
keyinfo[1].seg=keyseg+1; keyinfo[1].seg=keyseg+1;
keyinfo[1].keysegs=2; keyinfo[1].keysegs=2;
keyinfo[1].flag=0; keyinfo[1].flag=0;
keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY; keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[1].seg[0].start=7; keyinfo[1].seg[0].start=7;
keyinfo[1].seg[0].length=6; keyinfo[1].seg[0].length=6;
keyinfo[1].seg[0].null_bit=0;
keyinfo[1].seg[1].type=HA_KEYTYPE_TEXT; keyinfo[1].seg[1].type=HA_KEYTYPE_TEXT;
keyinfo[1].seg[1].start=0; /* Tv}delad nyckel */ keyinfo[1].seg[1].start=0; /* key in two parts */
keyinfo[1].seg[1].length=6; keyinfo[1].seg[1].length=6;
keyinfo[1].seg[1].null_bit=0;
keyinfo[2].seg=keyseg+3; keyinfo[2].seg=keyseg+3;
keyinfo[2].keysegs=1; keyinfo[2].keysegs=1;
keyinfo[2].flag=HA_NOSAME; keyinfo[2].flag=HA_NOSAME;
keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY; keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[2].seg[0].start=12; keyinfo[2].seg[0].start=12;
keyinfo[2].seg[0].length=8; keyinfo[2].seg[0].length=8;
keyinfo[2].seg[0].null_bit=0;
keyinfo[3].keysegs=1;
keyinfo[3].flag=HA_NOSAME;
keyinfo[3].seg=keyseg+4;
keyinfo[3].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[3].seg[0].start=37;
keyinfo[3].seg[0].length=1;
keyinfo[3].seg[0].null_bit=1;
keyinfo[3].seg[0].null_pos=38;
bzero((char*) key1,sizeof(key1)); bzero((char*) key1,sizeof(key1));
bzero((char*) key3,sizeof(key3)); bzero((char*) key3,sizeof(key3));
...@@ -110,7 +125,7 @@ int main(int argc, char *argv[]) ...@@ -110,7 +125,7 @@ int main(int argc, char *argv[])
for (i=0 ; i < recant ; i++) for (i=0 ; i < recant ; i++)
{ {
n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*5,MAX_RECORDS)); n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*5,MAX_RECORDS));
sprintf(record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count); make_record(record,n1,n2,n3,"Pos",write_count);
if (heap_write(file,record)) if (heap_write(file,record))
{ {
...@@ -191,7 +206,7 @@ int main(int argc, char *argv[]) ...@@ -191,7 +206,7 @@ int main(int argc, char *argv[])
for (i=0 ; i < write_count/10 ; i++) for (i=0 ; i < write_count/10 ; i++)
{ {
n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*2,MAX_RECORDS)); n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*2,MAX_RECORDS));
sprintf(record2,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update); make_record(record2, n1, n2, n3, "XXX", update);
if (rnd(2) == 1) if (rnd(2) == 1)
{ {
if (heap_scan_init(file)) if (heap_scan_init(file))
...@@ -654,3 +669,13 @@ static int calc_check(byte *buf, uint length) ...@@ -654,3 +669,13 @@ static int calc_check(byte *buf, uint length)
check+= (int) (uchar) *(buf++); check+= (int) (uchar) *(buf++);
return check; return check;
} }
static void make_record(char *record, uint n1, uint n2, uint n3,
const char *mark, uint count)
{
bfill(record,reclength,' ');
sprintf(record,"%6d:%4d:%8d:%3.3s: %4d",
n1,n2,n3,mark,count);
record[37]='A'; /* Store A in null key */
record[38]=1; /* set as null */
}
...@@ -238,8 +238,10 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo, ...@@ -238,8 +238,10 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
_hp_movelink(pos,gpos,empty); _hp_movelink(pos,gpos,empty);
} }
/* Check if dupplicated keys */ /* Check if duplicated keys */
if ((keyinfo->flag & HA_NOSAME) && pos == gpos) if ((keyinfo->flag & HA_NOSAME) && pos == gpos &&
(!(keyinfo->flag & HA_NULL_PART_KEY) ||
!hp_if_null_in_key(keyinfo, record)))
{ {
pos=empty; pos=empty;
do do
......
...@@ -255,6 +255,8 @@ inline double ulonglong2double(ulonglong value) ...@@ -255,6 +255,8 @@ inline double ulonglong2double(ulonglong value)
#define HAVE_COMPRESS #define HAVE_COMPRESS
#define HAVE_CREATESEMAPHORE #define HAVE_CREATESEMAPHORE
#define HAVE_ISAM /* We want to have support for ISAM in 4.0 */
#ifdef NOT_USED #ifdef NOT_USED
#define HAVE_SNPRINTF /* Gave link error */ #define HAVE_SNPRINTF /* Gave link error */
#define _snprintf snprintf #define _snprintf snprintf
......
...@@ -78,11 +78,13 @@ typedef struct st_hp_keyseg /* Key-portion */ ...@@ -78,11 +78,13 @@ typedef struct st_hp_keyseg /* Key-portion */
uint start; /* Start of key in record (from 0) */ uint start; /* Start of key in record (from 0) */
uint length; /* Keylength */ uint length; /* Keylength */
uint type; uint type;
uint null_bit; /* bit set in row+null_pos */
uint null_pos;
} HP_KEYSEG; } HP_KEYSEG;
typedef struct st_hp_keydef /* Key definition with open */ typedef struct st_hp_keydef /* Key definition with open */
{ {
uint flag; /* NOSAME */ uint flag; /* HA_NOSAME |HA_NULL_PART_KEY */
uint keysegs; /* Number of key-segment */ uint keysegs; /* Number of key-segment */
uint length; /* Length of key (automatic) */ uint length; /* Length of key (automatic) */
HP_KEYSEG *seg; HP_KEYSEG *seg;
......
...@@ -68,7 +68,8 @@ enum ha_rkey_function { ...@@ -68,7 +68,8 @@ enum ha_rkey_function {
enum ha_key_alg { enum ha_key_alg {
HA_KEY_ALG_BTREE=0, /* B-tree, default one */ HA_KEY_ALG_BTREE=0, /* B-tree, default one */
HA_KEY_ALG_RTREE=1 /* R-tree, for spatial searches */ HA_KEY_ALG_RTREE=1, /* R-tree, for spatial searches */
HA_KEY_ALG_HASH=2 /* HASH keys (HEAP tables) */
}; };
/* The following is parameter to ha_extra() */ /* The following is parameter to ha_extra() */
...@@ -149,6 +150,7 @@ enum ha_base_keytype { ...@@ -149,6 +150,7 @@ enum ha_base_keytype {
#define HA_FULLTEXT 128 /* SerG: for full-text search */ #define HA_FULLTEXT 128 /* SerG: for full-text search */
#define HA_UNIQUE_CHECK 256 /* Check the key for uniqueness */ #define HA_UNIQUE_CHECK 256 /* Check the key for uniqueness */
#define HA_SPATIAL 1024 /* Alex Barkov: for spatial search */ #define HA_SPATIAL 1024 /* Alex Barkov: for spatial search */
#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
/* Automatic bits in key-flag */ /* Automatic bits in key-flag */
...@@ -259,6 +261,7 @@ enum ha_base_keytype { ...@@ -259,6 +261,7 @@ enum ha_base_keytype {
#define MBR_DISJOINT 4096 #define MBR_DISJOINT 4096
#define MBR_EQUAL 8192 #define MBR_EQUAL 8192
#define MBR_DATA 16384 #define MBR_DATA 16384
#define SEARCH_NULL_ARE_EQUAL 32768 /* NULL in keys are equal */
/* bits in opt_flag */ /* bits in opt_flag */
#define QUICK_USED 1 #define QUICK_USED 1
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* /*
Static variables for pisam library. All definied here for easy making of Static variables for ISAM library. All definied here for easy making of
a shared library a shared library
*/ */
......
...@@ -38,7 +38,7 @@ libmysqlsources = errmsg.c get_password.c password.c ...@@ -38,7 +38,7 @@ libmysqlsources = errmsg.c get_password.c password.c
noinst_HEADERS = embedded_priv.h noinst_HEADERS = embedded_priv.h
sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \
ha_innobase.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \ ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \
ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \ ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \
hostname.cc init.cc \ hostname.cc init.cc \
item.cc item_buff.cc item_cmpfunc.cc item_create.cc \ item.cc item_buff.cc item_cmpfunc.cc item_create.cc \
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* /*
Static variables for pisam library. All definied here for easy making of Static variables for MyISAM library. All definied here for easy making of
a shared library a shared library
*/ */
......
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
/* Functions declared in this file */ /* Functions declared in this file */
static int w_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, static int w_search(MI_INFO *info,MI_KEYDEF *keyinfo,
uint comp_flag, uchar *key,
uint key_length, my_off_t pos, uchar *father_buff, uint key_length, my_off_t pos, uchar *father_buff,
uchar *father_keypos, my_off_t father_page, uchar *father_keypos, my_off_t father_page,
my_bool insert_last); my_bool insert_last);
...@@ -245,10 +246,23 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key, ...@@ -245,10 +246,23 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
uint key_length) uint key_length)
{ {
int error; int error;
uint comp_flag;
MI_KEYDEF *keyinfo=info->s->keyinfo+keynr;
DBUG_ENTER("_mi_ck_write_btree"); DBUG_ENTER("_mi_ck_write_btree");
if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
comp_flag=SEARCH_BIGGER; /* Put after same key */
else if (keyinfo->flag & HA_NOSAME)
{
comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */
if (keyinfo->flag & HA_NULL_ARE_EQUAL)
comp_flag|= SEARCH_NULL_ARE_EQUAL;
}
else
comp_flag=SEARCH_SAME; /* Keys in rec-pos order */
if (info->s->state.key_root[keynr] == HA_OFFSET_ERROR || if (info->s->state.key_root[keynr] == HA_OFFSET_ERROR ||
(error=w_search(info,info->s->keyinfo+keynr,key, key_length, (error=w_search(info, keyinfo, comp_flag, key, key_length,
info->s->state.key_root[keynr], (uchar *) 0, (uchar*) 0, info->s->state.key_root[keynr], (uchar *) 0, (uchar*) 0,
(my_off_t) 0, 1)) > 0) (my_off_t) 0, 1)) > 0)
error=_mi_enlarge_root(info,keynr,key); error=_mi_enlarge_root(info,keynr,key);
...@@ -291,13 +305,12 @@ int _mi_enlarge_root(register MI_INFO *info, uint keynr, uchar *key) ...@@ -291,13 +305,12 @@ int _mi_enlarge_root(register MI_INFO *info, uint keynr, uchar *key)
*/ */
static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
uchar *key, uint key_length, my_off_t page, uint comp_flag, uchar *key, uint key_length, my_off_t page,
uchar *father_buff, uchar *father_buff, uchar *father_keypos,
uchar *father_keypos, my_off_t father_page, my_off_t father_page, my_bool insert_last)
my_bool insert_last)
{ {
int error,flag; int error,flag;
uint comp_flag,nod_flag, search_key_length; uint nod_flag, search_key_length;
uchar *temp_buff,*keypos; uchar *temp_buff,*keypos;
uchar keybuff[MI_MAX_KEY_BUFF]; uchar keybuff[MI_MAX_KEY_BUFF];
my_bool was_last_key; my_bool was_last_key;
...@@ -305,17 +318,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -305,17 +318,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_ENTER("w_search"); DBUG_ENTER("w_search");
DBUG_PRINT("enter",("page: %ld",page)); DBUG_PRINT("enter",("page: %ld",page));
search_key_length=USE_WHOLE_KEY; search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
comp_flag=SEARCH_BIGGER; /* Put after same key */
else if (keyinfo->flag & HA_NOSAME)
{
comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */
search_key_length= key_length;
}
else
comp_flag=SEARCH_SAME; /* Keys in rec-pos order */
if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
MI_MAX_KEY_BUFF*2))) MI_MAX_KEY_BUFF*2)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -344,7 +347,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -344,7 +347,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
insert_last=0; insert_last=0;
next_page=_mi_kpos(nod_flag,keypos); next_page=_mi_kpos(nod_flag,keypos);
if (next_page == HA_OFFSET_ERROR || if (next_page == HA_OFFSET_ERROR ||
(error=w_search(info,keyinfo,key,key_length,next_page, (error=w_search(info, keyinfo, comp_flag, key, key_length, next_page,
temp_buff, keypos, page, insert_last)) >0) temp_buff, keypos, page, insert_last)) >0)
{ {
error=_mi_insert(info,keyinfo,key,temp_buff,keypos,keybuff,father_buff, error=_mi_insert(info,keyinfo,key,temp_buff,keypos,keybuff,father_buff,
...@@ -759,15 +762,17 @@ static int keys_compare(bulk_insert_param *param, uchar *key1, uchar *key2) ...@@ -759,15 +762,17 @@ static int keys_compare(bulk_insert_param *param, uchar *key1, uchar *key2)
{ {
uint not_used; uint not_used;
return _mi_key_cmp(param->info->s->keyinfo[param->keynr].seg, return _mi_key_cmp(param->info->s->keyinfo[param->keynr].seg,
key1, key2, USE_WHOLE_KEY, SEARCH_SAME, &not_used); key1, key2, USE_WHOLE_KEY, SEARCH_SAME,
&not_used);
} }
static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param) static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param)
{ {
/* probably I can use info->lastkey here, but I'm not sure, /*
Probably I can use info->lastkey here, but I'm not sure,
and to be safe I'd better use local lastkey. and to be safe I'd better use local lastkey.
Monty, feel free to comment on this */ */
uchar lastkey[MI_MAX_KEY_BUFF]; uchar lastkey[MI_MAX_KEY_BUFF];
uint keylen; uint keylen;
MI_KEYDEF *keyinfo; MI_KEYDEF *keyinfo;
...@@ -794,6 +799,7 @@ static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param) ...@@ -794,6 +799,7 @@ static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param)
return -1; return -1;
} }
int _mi_init_bulk_insert(MI_INFO *info) int _mi_init_bulk_insert(MI_INFO *info)
{ {
MYISAM_SHARE *share=info->s; MYISAM_SHARE *share=info->s;
......
...@@ -263,3 +263,84 @@ score count(*) ...@@ -263,3 +263,84 @@ score count(*)
2 1 2 1
1 2 1 2
drop table t1; drop table t1;
CREATE TABLE t1 (a char(1));
INSERT INTO t1 VALUES ('A'),('B'),('A'),('B'),('A'),('B'),(NULL),('a'),('b'),(NULL),('A'),('B'),(NULL);
SELECT a FROM t1 GROUP BY a;
a
NULL
A
B
SELECT a,count(*) FROM t1 GROUP BY a;
a count(*)
NULL 3
A 5
B 5
SELECT a FROM t1 GROUP BY binary a;
a
NULL
A
B
a
b
SELECT a,count(*) FROM t1 GROUP BY binary a;
a count(*)
NULL 3
A 4
B 4
a 1
b 1
SELECT binary a FROM t1 GROUP BY 1;
binary a
NULL
A
B
a
b
SELECT binary a,count(*) FROM t1 GROUP BY 1;
binary a count(*)
NULL 3
A 4
B 4
a 1
b 1
SET SQL_BIG_TABLES=1;
SELECT a FROM t1 GROUP BY a;
a
NULL
A
B
SELECT a,count(*) FROM t1 GROUP BY a;
a count(*)
NULL 3
A 5
B 5
SELECT a FROM t1 GROUP BY binary a;
a
NULL
A
B
a
b
SELECT a,count(*) FROM t1 GROUP BY binary a;
a count(*)
NULL 3
A 4
B 4
a 1
b 1
SELECT binary a FROM t1 GROUP BY 1;
binary a
NULL
A
B
a
b
SELECT binary a,count(*) FROM t1 GROUP BY 1;
binary a count(*)
NULL 3
A 4
B 4
a 1
b 1
SET SQL_BIG_TABLES=0;
drop table t1;
...@@ -165,3 +165,29 @@ explain select * from t1 where btn="a" and new_col="a"; ...@@ -165,3 +165,29 @@ explain select * from t1 where btn="a" and new_col="a";
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 ref btn btn 11 const,const 10 where used t1 ref btn btn 11 const,const 10 where used
drop table t1; drop table t1;
CREATE TABLE t1 (
a int default NULL,
b int default NULL,
KEY a (a),
UNIQUE b (b)
) type=heap;
INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
SELECT * FROM t1 WHERE a=NULL;
a b
explain SELECT * FROM t1 WHERE a IS NULL;
table type possible_keys key key_len ref rows Extra
t1 ref a a 5 const 10 where used
SELECT * FROM t1 WHERE a<=>NULL;
a b
NULL 99
SELECT * FROM t1 WHERE b=NULL;
a b
explain SELECT * FROM t1 WHERE b IS NULL;
table type possible_keys key key_len ref rows Extra
t1 ref b b 5 const 1 where used
SELECT * FROM t1 WHERE b<=>NULL;
a b
99 NULL
INSERT INTO t1 VALUES (1,3);
Duplicate entry '3' for key 1
DROP TABLE t1;
...@@ -40,7 +40,6 @@ insert into t1 values (null); ...@@ -40,7 +40,6 @@ insert into t1 values (null);
select * from t1 where x != 0; select * from t1 where x != 0;
x x
drop table t1; drop table t1;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 ( CREATE TABLE t1 (
indexed_field int default NULL, indexed_field int default NULL,
KEY indexed_field (indexed_field) KEY indexed_field (indexed_field)
......
...@@ -286,15 +286,15 @@ a b c ...@@ -286,15 +286,15 @@ a b c
1 NULL NULL 1 NULL NULL
explain select * from t1 where a = 1 order by a desc, b desc; explain select * from t1 where a = 1 order by a desc, b desc;
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 ref a a 4 const 5 where used; Using index; Using filesort t1 ref a a 4 const 5 where used; Using index
select * from t1 where a = 1 order by a desc, b desc; select * from t1 where a = 1 order by a desc, b desc;
a b c a b c
1 3 b 1 3 b
1 1 NULL
1 1 b 1 1 b
1 1 b 1 1 b
1 NULL NULL 1 1 NULL
1 NULL b 1 NULL b
1 NULL NULL
explain select * from t1 where a = 1 and b is null order by a desc, b desc; explain select * from t1 where a = 1 and b is null order by a desc, b desc;
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 ref a a 9 const,const 2 where used; Using index; Using filesort t1 ref a a 9 const,const 2 where used; Using index; Using filesort
......
...@@ -243,3 +243,26 @@ select sql_big_result spid,sum(userid) from t1 group by spid desc; ...@@ -243,3 +243,26 @@ select sql_big_result spid,sum(userid) from t1 group by spid desc;
explain select sql_big_result score,count(*) from t1 group by score desc; explain select sql_big_result score,count(*) from t1 group by score desc;
select sql_big_result score,count(*) from t1 group by score desc; select sql_big_result score,count(*) from t1 group by score desc;
drop table t1; drop table t1;
#
# Compare with hash keys
#
CREATE TABLE t1 (a char(1));
INSERT INTO t1 VALUES ('A'),('B'),('A'),('B'),('A'),('B'),(NULL),('a'),('b'),(NULL),('A'),('B'),(NULL);
SELECT a FROM t1 GROUP BY a;
SELECT a,count(*) FROM t1 GROUP BY a;
SELECT a FROM t1 GROUP BY binary a;
SELECT a,count(*) FROM t1 GROUP BY binary a;
SELECT binary a FROM t1 GROUP BY 1;
SELECT binary a,count(*) FROM t1 GROUP BY 1;
# Do the same tests with MyISAM temporary tables
SET SQL_BIG_TABLES=1;
SELECT a FROM t1 GROUP BY a;
SELECT a,count(*) FROM t1 GROUP BY a;
SELECT a FROM t1 GROUP BY binary a;
SELECT a,count(*) FROM t1 GROUP BY binary a;
SELECT binary a FROM t1 GROUP BY 1;
SELECT binary a,count(*) FROM t1 GROUP BY 1;
SET SQL_BIG_TABLES=0;
drop table t1;
...@@ -100,3 +100,25 @@ update t1 set new_col=btn; ...@@ -100,3 +100,25 @@ update t1 set new_col=btn;
explain select * from t1 where btn="a"; explain select * from t1 where btn="a";
explain select * from t1 where btn="a" and new_col="a"; explain select * from t1 where btn="a" and new_col="a";
drop table t1; drop table t1;
#
# Test of NULL keys
#
CREATE TABLE t1 (
a int default NULL,
b int default NULL,
KEY a (a),
UNIQUE b (b)
) type=heap;
INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
SELECT * FROM t1 WHERE a=NULL;
explain SELECT * FROM t1 WHERE a IS NULL;
SELECT * FROM t1 WHERE a<=>NULL;
SELECT * FROM t1 WHERE b=NULL;
explain SELECT * FROM t1 WHERE b IS NULL;
SELECT * FROM t1 WHERE b<=>NULL;
--error 1062
INSERT INTO t1 VALUES (1,3);
DROP TABLE t1;
...@@ -25,7 +25,6 @@ drop table t1; ...@@ -25,7 +25,6 @@ drop table t1;
# Test problem med index on NULL columns and testing with =NULL; # Test problem med index on NULL columns and testing with =NULL;
# #
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 ( CREATE TABLE t1 (
indexed_field int default NULL, indexed_field int default NULL,
KEY indexed_field (indexed_field) KEY indexed_field (indexed_field)
......
...@@ -51,7 +51,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ ...@@ -51,7 +51,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_manager.h sql_map.h sql_string.h unireg.h \ sql_manager.h sql_map.h sql_string.h unireg.h \
field.h handler.h \ field.h handler.h \
ha_isammrg.h ha_isam.h ha_myisammrg.h\ ha_isammrg.h ha_isam.h ha_myisammrg.h\
ha_heap.h ha_myisam.h ha_berkeley.h ha_innobase.h \ ha_heap.h ha_myisam.h ha_berkeley.h ha_innodb.h \
opt_range.h opt_ft.h \ opt_range.h opt_ft.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h\ sql_select.h structs.h table.h sql_udf.h hash_filo.h\
lex.h lex_symbol.h sql_acl.h sql_crypt.h \ lex.h lex_symbol.h sql_acl.h sql_crypt.h \
...@@ -74,7 +74,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ ...@@ -74,7 +74,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
time.cc opt_range.cc opt_sum.cc opt_ft.cc \ time.cc opt_range.cc opt_sum.cc opt_ft.cc \
records.cc filesort.cc handler.cc \ records.cc filesort.cc handler.cc \
ha_heap.cc ha_myisam.cc ha_myisammrg.cc \ ha_heap.cc ha_myisam.cc ha_myisammrg.cc \
ha_berkeley.cc ha_innobase.cc \ ha_berkeley.cc ha_innodb.cc \
ha_isam.cc ha_isammrg.cc \ ha_isam.cc ha_isammrg.cc \
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \ sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \ sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
......
...@@ -1454,6 +1454,37 @@ int ha_berkeley::index_read(byte * buf, const byte * key, ...@@ -1454,6 +1454,37 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
DBUG_RETURN(error); DBUG_RETURN(error);
} }
/*
Read last key is solved by reading the next key and then reading
the previous key
*/
int ha_berkeley::index_read_last(byte * buf, const byte * key, uint key_len)
{
DBT row;
int error;
KEY *key_info= &table->key_info[active_index];
DBUG_ENTER("ha_berkeley::index_read");
statistic_increment(ha_read_key_count,&LOCK_status);
bzero((char*) &row,sizeof(row));
/* read of partial key */
pack_key(&last_key, active_index, key_buff, key, key_len);
/* Store for compare */
memcpy(key_buff2, key_buff, (key_len=last_key.size));
key_info->handler.bdb_return_if_eq= 1;
error=read_row(cursor->c_get(cursor, &last_key, &row, DB_SET_RANGE),
(char*) buf, active_index, &row, (DBT*) 0, 0);
key_info->handler.bdb_return_if_eq= 0;
bzero((char*) &row,sizeof(row));
if (read_row(cursor->c_get(cursor, &last_key, &row, DB_PREV),
(char*) buf, active_index, &row, &last_key, 1) ||
berkeley_key_cmp(table, key_info, key_buff2, key_len))
error=HA_ERR_KEY_NOT_FOUND;
DBUG_RETURN(error);
}
int ha_berkeley::index_next(byte * buf) int ha_berkeley::index_next(byte * buf)
{ {
......
...@@ -89,7 +89,7 @@ class ha_berkeley: public handler ...@@ -89,7 +89,7 @@ class ha_berkeley: public handler
int_option_flag(HA_READ_NEXT | HA_READ_PREV | int_option_flag(HA_READ_NEXT | HA_READ_PREV |
HA_REC_NOT_IN_SEQ | HA_REC_NOT_IN_SEQ |
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER | HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
HA_LONGLONG_KEYS | HA_NULL_KEY | HA_HAVE_KEY_READ_ONLY | HA_NULL_KEY | HA_HAVE_KEY_READ_ONLY |
HA_BLOB_KEY | HA_NOT_EXACT_COUNT | HA_BLOB_KEY | HA_NOT_EXACT_COUNT |
HA_PRIMARY_KEY_IN_READ_INDEX | HA_DROP_BEFORE_CREATE | HA_PRIMARY_KEY_IN_READ_INDEX | HA_DROP_BEFORE_CREATE |
HA_AUTO_PART_KEY), HA_AUTO_PART_KEY),
...@@ -123,6 +123,7 @@ class ha_berkeley: public handler ...@@ -123,6 +123,7 @@ class ha_berkeley: public handler
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 index, const byte * key, int index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag); uint key_len, enum ha_rkey_function find_flag);
int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf); int index_next(byte * buf);
int index_next_same(byte * buf, const byte *key, uint keylen); int index_next_same(byte * buf, const byte *key, uint keylen);
int index_prev(byte * buf); int index_prev(byte * buf);
......
...@@ -33,7 +33,7 @@ const char **ha_heap::bas_ext() const ...@@ -33,7 +33,7 @@ const char **ha_heap::bas_ext() const
int ha_heap::open(const char *name, int mode, uint test_if_locked) int ha_heap::open(const char *name, int mode, uint test_if_locked)
{ {
uint key,part,parts,mem_per_row=0; uint key,parts,mem_per_row=0;
ulong max_rows; ulong max_rows;
HP_KEYDEF *keydef; HP_KEYDEF *keydef;
HP_KEYSEG *seg; HP_KEYSEG *seg;
...@@ -48,24 +48,38 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) ...@@ -48,24 +48,38 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
for (key=0 ; key < table->keys ; key++) for (key=0 ; key < table->keys ; key++)
{ {
KEY *pos=table->key_info+key; KEY *pos=table->key_info+key;
KEY_PART_INFO *key_part= pos->key_part;
KEY_PART_INFO *key_part_end= key_part+pos->key_parts;
mem_per_row += (pos->key_length + (sizeof(char*) * 2)); mem_per_row += (pos->key_length + (sizeof(char*) * 2));
keydef[key].keysegs=(uint) pos->key_parts; keydef[key].keysegs=(uint) pos->key_parts;
keydef[key].flag = (pos->flags & HA_NOSAME); keydef[key].flag = (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
keydef[key].seg=seg; keydef[key].seg=seg;
for (part=0 ; part < pos->key_parts ; part++) for (; key_part != key_part_end ; key_part++, seg++)
{ {
uint flag=pos->key_part[part].key_type; uint flag=key_part->key_type;
Field *field=key_part->field;
if (!f_is_packed(flag) && if (!f_is_packed(flag) &&
f_packtype(flag) == (int) FIELD_TYPE_DECIMAL && f_packtype(flag) == (int) FIELD_TYPE_DECIMAL &&
!(flag & FIELDFLAG_BINARY)) !(flag & FIELDFLAG_BINARY))
seg->type= (int) HA_KEYTYPE_TEXT; seg->type= (int) HA_KEYTYPE_TEXT;
else else
seg->type= (int) HA_KEYTYPE_BINARY; seg->type= (int) HA_KEYTYPE_BINARY;
seg->start=(uint) pos->key_part[part].offset; seg->start=(uint) key_part->offset;
seg->length=(uint) pos->key_part[part].length; seg->length=(uint) key_part->length;
seg++; if (field->null_ptr)
{
seg->null_bit=field->null_bit;
seg->null_pos= (uint) (field->null_ptr-
(uchar*) table->record[0]);
}
else
{
seg->null_bit=0;
seg->null_pos=0;
}
} }
} }
mem_per_row += MY_ALIGN(table->reclength+1, sizeof(char*)); mem_per_row += MY_ALIGN(table->reclength+1, sizeof(char*));
...@@ -77,6 +91,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) ...@@ -77,6 +91,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
table->max_rows : max_rows), table->max_rows : max_rows),
table->min_rows); table->min_rows);
my_free((gptr) keydef,MYF(0)); my_free((gptr) keydef,MYF(0));
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 (!file ? errno : 0); return (!file ? errno : 0);
......
...@@ -36,7 +36,7 @@ class ha_heap: public handler ...@@ -36,7 +36,7 @@ class ha_heap: public handler
ulong option_flag() const ulong option_flag() const
{ return (HA_READ_RND_SAME | HA_NO_INDEX | HA_ONLY_WHOLE_INDEX | { return (HA_READ_RND_SAME | HA_NO_INDEX | HA_ONLY_WHOLE_INDEX |
HA_WRONG_ASCII_ORDER | HA_KEYPOS_TO_RNDPOS | HA_NO_BLOBS | HA_WRONG_ASCII_ORDER | HA_KEYPOS_TO_RNDPOS | HA_NO_BLOBS |
HA_REC_NOT_IN_SEQ); } HA_NULL_KEY | HA_REC_NOT_IN_SEQ | HA_NOT_READ_PREFIX_LAST); }
uint max_record_length() const { return HA_MAX_REC_LENGTH; } uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MAX_KEY; } uint max_keys() const { return MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_parts() const { return MAX_REF_PARTS; }
......
...@@ -35,7 +35,7 @@ InnoDB */ ...@@ -35,7 +35,7 @@ InnoDB */
#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1)) #define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
#include "ha_innobase.h" #include "ha_innodb.h"
/* We must declare this here because we undef SAFE_MUTEX below */ /* We must declare this here because we undef SAFE_MUTEX below */
pthread_mutex_t innobase_mutex; pthread_mutex_t innobase_mutex;
...@@ -2008,6 +2008,24 @@ ha_innobase::index_read( ...@@ -2008,6 +2008,24 @@ ha_innobase::index_read(
DBUG_RETURN(error); DBUG_RETURN(error);
} }
/*
The following functions works like index_read, but it find the last
row with the current index prefix.
This code is disabled until Heikki has verified that InnoDB support the
HA_READ_PREFIX_LAST flag and removed the HA_NOT_READ_PREFIX_LAST
flag from ha_innodb.h
*/
int
ha_innobase::index_read_last(mysql_byte *buf,
const mysql_byte *key_ptr,
uint key_len)
{
return index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST);
}
/************************************************************************ /************************************************************************
Changes the active index of a handle. */ Changes the active index of a handle. */
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB /* Copyright (C) 2000 MySQL AB && Innobase Oy
&& Innobase Oy
-This file is modified from ha_berkeley.h of MySQL distribution-
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -17,13 +14,17 @@ ...@@ -17,13 +14,17 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
This file is based on ha_berkeley.h of MySQL distribution
This file defines the Innodb handler: the interface between MySQL and
Innodb
*/
#ifdef __GNUC__ #ifdef __GNUC__
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
/* This file defines the Innobase handler: the interface between MySQL and
Innobase */
typedef struct st_innobase_share { typedef struct st_innobase_share {
THR_LOCK lock; THR_LOCK lock;
pthread_mutex_t mutex; pthread_mutex_t mutex;
...@@ -32,11 +33,11 @@ typedef struct st_innobase_share { ...@@ -32,11 +33,11 @@ typedef struct st_innobase_share {
} INNOBASE_SHARE; } INNOBASE_SHARE;
/* The class defining a handle to an Innobase table */ /* The class defining a handle to an Innodb table */
class ha_innobase: public handler class ha_innobase: public handler
{ {
void* innobase_prebuilt; /* (row_prebuilt_t*) prebuilt void* innobase_prebuilt; /* (row_prebuilt_t*) prebuilt
struct in Innobase, used to save struct in Innodb, used to save
CPU */ CPU */
THD* user_thd; /* the thread handle of the user THD* user_thd; /* the thread handle of the user
currently using the handle; this is currently using the handle; this is
...@@ -50,7 +51,7 @@ class ha_innobase: public handler ...@@ -50,7 +51,7 @@ class ha_innobase: public handler
byte* upd_buff; /* buffer used in updates */ byte* upd_buff; /* buffer used in updates */
byte* key_val_buff; /* buffer used in converting byte* key_val_buff; /* buffer used in converting
search key values from MySQL format search key values from MySQL format
to Innobase format */ to Innodb format */
uint ref_stored_len; /* length of the key value stored to uint ref_stored_len; /* length of the key value stored to
'ref' buffer of the handle, if any */ 'ref' buffer of the handle, if any */
ulong int_option_flag; ulong int_option_flag;
...@@ -78,11 +79,11 @@ class ha_innobase: public handler ...@@ -78,11 +79,11 @@ class ha_innobase: public handler
HA_REC_NOT_IN_SEQ | HA_REC_NOT_IN_SEQ |
HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER | HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY | HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY |
HA_LONGLONG_KEYS | HA_NULL_KEY | HA_NULL_KEY |
HA_NOT_EXACT_COUNT | HA_NOT_EXACT_COUNT |
HA_NO_WRITE_DELAYED | HA_NO_WRITE_DELAYED |
HA_PRIMARY_KEY_IN_READ_INDEX | HA_PRIMARY_KEY_IN_READ_INDEX |
HA_DROP_BEFORE_CREATE | HA_DROP_BEFORE_CREATE | HA_NOT_READ_PREFIX_LAST |
HA_NO_PREFIX_CHAR_KEYS), HA_NO_PREFIX_CHAR_KEYS),
last_dup_key((uint) -1), last_dup_key((uint) -1),
start_of_scan(0) start_of_scan(0)
...@@ -125,6 +126,7 @@ class ha_innobase: public handler ...@@ -125,6 +126,7 @@ class ha_innobase: public handler
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 index, const byte * key, int index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag); uint key_len, enum ha_rkey_function find_flag);
int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf); int index_next(byte * buf);
int index_next_same(byte * buf, const byte *key, uint keylen); int index_next_same(byte * buf, const byte *key, uint keylen);
int index_prev(byte * buf); int index_prev(byte * buf);
......
...@@ -109,6 +109,15 @@ int ha_isam::index_read_idx(byte * buf, uint index, const byte * key, ...@@ -109,6 +109,15 @@ int ha_isam::index_read_idx(byte * buf, uint index, const byte * key,
return !error ? 0 : my_errno ? my_errno : -1; return !error ? 0 : my_errno ? my_errno : -1;
} }
int ha_isam::index_read_last(byte * buf, const byte * key, uint key_len)
{
statistic_increment(ha_read_key_count,&LOCK_status);
int error=nisam_rkey(file, buf, active_index, key, key_len,
HA_READ_PREFIX_LAST);
table->status=error ? STATUS_NOT_FOUND: 0;
return !error ? 0 : my_errno ? my_errno : -1;
}
int ha_isam::index_next(byte * buf) int ha_isam::index_next(byte * buf)
{ {
statistic_increment(ha_read_next_count,&LOCK_status); statistic_increment(ha_read_next_count,&LOCK_status);
......
...@@ -33,7 +33,7 @@ class ha_isam: public handler ...@@ -33,7 +33,7 @@ class ha_isam: public handler
int_option_flag(HA_READ_NEXT | HA_READ_PREV | HA_READ_RND_SAME | int_option_flag(HA_READ_NEXT | HA_READ_PREV | HA_READ_RND_SAME |
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER | HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY | HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY |
HA_LONGLONG_KEYS | HA_KEY_READ_WRONG_STR | HA_DUPP_POS | HA_KEY_READ_WRONG_STR | HA_DUPP_POS |
HA_NOT_DELETE_WITH_CACHE) HA_NOT_DELETE_WITH_CACHE)
{} {}
~ha_isam() {} ~ha_isam() {}
...@@ -57,6 +57,7 @@ class ha_isam: public handler ...@@ -57,6 +57,7 @@ class ha_isam: public handler
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,
uint key_len, enum ha_rkey_function find_flag); uint key_len, enum ha_rkey_function find_flag);
int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf); int index_next(byte * buf);
int index_prev(byte * buf); int index_prev(byte * buf);
int index_first(byte * buf); int index_first(byte * buf);
......
...@@ -32,8 +32,9 @@ class ha_isammrg: public handler ...@@ -32,8 +32,9 @@ class ha_isammrg: public handler
~ha_isammrg() {} ~ha_isammrg() {}
const char *table_type() const { return "MRG_ISAM"; } const char *table_type() const { return "MRG_ISAM"; }
const char **bas_ext() const; const char **bas_ext() const;
ulong option_flag() const { return HA_READ_RND_SAME | HA_KEYPOS_TO_RNDPOS ulong option_flag() const { return (HA_READ_RND_SAME | HA_KEYPOS_TO_RNDPOS |
| HA_REC_NOT_IN_SEQ;} HA_NOT_READ_PREFIX_LAST |
HA_REC_NOT_IN_SEQ); }
uint max_record_length() const { return HA_MAX_REC_LENGTH; } uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return 0; } uint max_keys() const { return 0; }
uint max_key_parts() const { return 0; } uint max_key_parts() const { return 0; }
......
...@@ -777,6 +777,14 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key, ...@@ -777,6 +777,14 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
return error; return error;
} }
int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len)
{
statistic_increment(ha_read_key_count,&LOCK_status);
int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
int ha_myisam::index_next(byte * buf) int ha_myisam::index_next(byte * buf)
{ {
statistic_increment(ha_read_next_count,&LOCK_status); statistic_increment(ha_read_next_count,&LOCK_status);
...@@ -973,7 +981,7 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info) ...@@ -973,7 +981,7 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
} }
int ha_myisam::create(const char *name, register TABLE *form, int ha_myisam::create(const char *name, register TABLE *table,
HA_CREATE_INFO *info) HA_CREATE_INFO *info)
{ {
int error; int error;
...@@ -985,20 +993,20 @@ int ha_myisam::create(const char *name, register TABLE *form, ...@@ -985,20 +993,20 @@ int ha_myisam::create(const char *name, register TABLE *form,
MI_KEYDEF *keydef; MI_KEYDEF *keydef;
MI_COLUMNDEF *recinfo,*recinfo_pos; MI_COLUMNDEF *recinfo,*recinfo_pos;
MI_KEYSEG *keyseg; MI_KEYSEG *keyseg;
uint options=form->db_options_in_use; uint options=table->db_options_in_use;
DBUG_ENTER("ha_myisam::create"); DBUG_ENTER("ha_myisam::create");
type=HA_KEYTYPE_BINARY; // Keep compiler happy type=HA_KEYTYPE_BINARY; // Keep compiler happy
if (!(my_multi_malloc(MYF(MY_WME), if (!(my_multi_malloc(MYF(MY_WME),
&recinfo,(form->fields*2+2)*sizeof(MI_COLUMNDEF), &recinfo,(table->fields*2+2)*sizeof(MI_COLUMNDEF),
&keydef, form->keys*sizeof(MI_KEYDEF), &keydef, table->keys*sizeof(MI_KEYDEF),
&keyseg, &keyseg,
((form->key_parts + form->keys) * sizeof(MI_KEYSEG)), ((table->key_parts + table->keys) * sizeof(MI_KEYSEG)),
0))) 0)))
DBUG_RETURN(1); DBUG_RETURN(1);
pos=form->key_info; pos=table->key_info;
for (i=0; i < form->keys ; i++, pos++) for (i=0; i < table->keys ; i++, pos++)
{ {
keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT)); keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT));
keydef[i].seg=keyseg; keydef[i].seg=keyseg;
...@@ -1041,7 +1049,7 @@ int ha_myisam::create(const char *name, register TABLE *form, ...@@ -1041,7 +1049,7 @@ int ha_myisam::create(const char *name, register TABLE *form,
{ {
keydef[i].seg[j].null_bit=field->null_bit; keydef[i].seg[j].null_bit=field->null_bit;
keydef[i].seg[j].null_pos= (uint) (field->null_ptr- keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
(uchar*) form->record[0]); (uchar*) table->record[0]);
} }
else else
{ {
...@@ -1059,19 +1067,19 @@ int ha_myisam::create(const char *name, register TABLE *form, ...@@ -1059,19 +1067,19 @@ int ha_myisam::create(const char *name, register TABLE *form,
keydef[i].seg[j].flag|=HA_BLOB_PART; keydef[i].seg[j].flag|=HA_BLOB_PART;
/* save number of bytes used to pack length */ /* save number of bytes used to pack length */
keydef[i].seg[j].bit_start= (uint) (field->pack_length() - keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
form->blob_ptr_size); table->blob_ptr_size);
} }
} }
keyseg+=pos->key_parts; keyseg+=pos->key_parts;
} }
recpos=0; recinfo_pos=recinfo; recpos=0; recinfo_pos=recinfo;
while (recpos < (uint) form->reclength) while (recpos < (uint) table->reclength)
{ {
Field **field,*found=0; Field **field,*found=0;
minpos=form->reclength; length=0; minpos=table->reclength; length=0;
for (field=form->field ; *field ; field++) for (field=table->field ; *field ; field++)
{ {
if ((fieldpos=(*field)->offset()) >= recpos && if ((fieldpos=(*field)->offset()) >= recpos &&
fieldpos <= minpos) fieldpos <= minpos)
...@@ -1117,7 +1125,7 @@ int ha_myisam::create(const char *name, register TABLE *form, ...@@ -1117,7 +1125,7 @@ int ha_myisam::create(const char *name, register TABLE *form,
{ {
recinfo_pos->null_bit=found->null_bit; recinfo_pos->null_bit=found->null_bit;
recinfo_pos->null_pos= (uint) (found->null_ptr- recinfo_pos->null_pos= (uint) (found->null_ptr-
(uchar*) form->record[0]); (uchar*) table->record[0]);
} }
else else
{ {
...@@ -1132,20 +1140,23 @@ int ha_myisam::create(const char *name, register TABLE *form, ...@@ -1132,20 +1140,23 @@ int ha_myisam::create(const char *name, register TABLE *form,
} }
MI_CREATE_INFO create_info; MI_CREATE_INFO create_info;
bzero((char*) &create_info,sizeof(create_info)); bzero((char*) &create_info,sizeof(create_info));
create_info.max_rows=form->max_rows; create_info.max_rows=table->max_rows;
create_info.reloc_rows=form->min_rows; create_info.reloc_rows=table->min_rows;
create_info.auto_increment=(info->auto_increment_value ? create_info.auto_increment=(info->auto_increment_value ?
info->auto_increment_value -1 : info->auto_increment_value -1 :
(ulonglong) 0); (ulonglong) 0);
create_info.data_file_length=(ulonglong) form->max_rows*form->avg_row_length; create_info.data_file_length= ((ulonglong) table->max_rows *
table->avg_row_length);
create_info.raid_type=info->raid_type; create_info.raid_type=info->raid_type;
create_info.raid_chunks=info->raid_chunks ? info->raid_chunks : RAID_DEFAULT_CHUNKS; create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks :
create_info.raid_chunksize=info->raid_chunksize ? info->raid_chunksize : RAID_DEFAULT_CHUNKSIZE; RAID_DEFAULT_CHUNKS);
create_info.raid_chunksize=(info->raid_chunksize ? info->raid_chunksize :
RAID_DEFAULT_CHUNKSIZE);
create_info.data_file_name= info->data_file_name; create_info.data_file_name= info->data_file_name;
create_info.index_file_name=info->index_file_name; create_info.index_file_name=info->index_file_name;
error=mi_create(fn_format(buff,name,"","",2+4), error=mi_create(fn_format(buff,name,"","",2+4),
form->keys,keydef, table->keys,keydef,
(uint) (recinfo_pos-recinfo), recinfo, (uint) (recinfo_pos-recinfo), recinfo,
0, (MI_UNIQUEDEF*) 0, 0, (MI_UNIQUEDEF*) 0,
&create_info, &create_info,
......
...@@ -47,7 +47,7 @@ class ha_myisam: public handler ...@@ -47,7 +47,7 @@ class ha_myisam: public handler
int_option_flag(HA_READ_NEXT | HA_READ_PREV | HA_READ_RND_SAME | int_option_flag(HA_READ_NEXT | HA_READ_PREV | HA_READ_RND_SAME |
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER | HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY | HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY |
HA_LONGLONG_KEYS | HA_NULL_KEY | HA_NULL_KEY |
HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY), HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY),
enable_activate_all_index(1) enable_activate_all_index(1)
...@@ -71,6 +71,7 @@ class ha_myisam: public handler ...@@ -71,6 +71,7 @@ class ha_myisam: public handler
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,
uint key_len, enum ha_rkey_function find_flag); uint key_len, enum ha_rkey_function find_flag);
int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf); int index_next(byte * buf);
int index_prev(byte * buf); int index_prev(byte * buf);
int index_first(byte * buf); int index_first(byte * buf);
...@@ -78,8 +79,14 @@ class ha_myisam: public handler ...@@ -78,8 +79,14 @@ class ha_myisam: public handler
int index_next_same(byte *buf, const byte *key, uint keylen); int index_next_same(byte *buf, const byte *key, uint keylen);
int index_end() { ft_handler=NULL; return 0; } int index_end() { ft_handler=NULL; return 0; }
int ft_init() int ft_init()
{ if(!ft_handler) return 1; ft_handler->please->reinit_search(ft_handler); return 0; } {
FT_INFO *ft_init_ext(uint mode, uint inx,const byte *key, uint keylen, bool presort) if (!ft_handler)
return 1;
ft_handler->please->reinit_search(ft_handler);
return 0;
}
FT_INFO *ft_init_ext(uint mode, uint inx,const byte *key, uint keylen,
bool presort)
{ return ft_init_search(mode, file,inx,(byte*) key,keylen,presort); } { return ft_init_search(mode, file,inx,(byte*) key,keylen,presort); }
int ft_read(byte *buf); int ft_read(byte *buf);
int rnd_init(bool scan=1); int rnd_init(bool scan=1);
......
...@@ -112,6 +112,15 @@ int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key, ...@@ -112,6 +112,15 @@ int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
return error; return error;
} }
int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len)
{
statistic_increment(ha_read_key_count,&LOCK_status);
int error=myrg_rkey(file,buf,active_index, key, key_len,
HA_READ_PREFIX_LAST);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
int ha_myisammrg::index_next(byte * buf) int ha_myisammrg::index_next(byte * buf)
{ {
statistic_increment(ha_read_next_count,&LOCK_status); statistic_increment(ha_read_next_count,&LOCK_status);
......
...@@ -38,7 +38,7 @@ class ha_myisammrg: public handler ...@@ -38,7 +38,7 @@ class ha_myisammrg: public handler
HA_HAVE_KEY_READ_ONLY | HA_HAVE_KEY_READ_ONLY |
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER |
HA_LASTKEY_ORDER | HA_READ_NOT_EXACT_KEY | HA_LASTKEY_ORDER | HA_READ_NOT_EXACT_KEY |
HA_LONGLONG_KEYS | HA_NULL_KEY | HA_BLOB_KEY); } HA_NULL_KEY | HA_BLOB_KEY); }
uint max_record_length() const { return HA_MAX_REC_LENGTH; } uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MI_MAX_KEY; } uint max_keys() const { return MI_MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_parts() const { return MAX_REF_PARTS; }
...@@ -55,6 +55,7 @@ class ha_myisammrg: public handler ...@@ -55,6 +55,7 @@ class ha_myisammrg: public handler
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,
uint key_len, enum ha_rkey_function find_flag); uint key_len, enum ha_rkey_function find_flag);
int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf); int index_next(byte * buf);
int index_prev(byte * buf); int index_prev(byte * buf);
int index_first(byte * buf); int index_first(byte * buf);
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include "ha_berkeley.h" #include "ha_berkeley.h"
#endif #endif
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
#include "ha_innobase.h" #include "ha_innodb.h"
#endif #endif
#include <myisampack.h> #include <myisampack.h>
#include <errno.h> #include <errno.h>
......
...@@ -55,12 +55,11 @@ ...@@ -55,12 +55,11 @@
#define HA_REC_NOT_IN_SEQ 64 /* ha_info don't return recnumber; #define HA_REC_NOT_IN_SEQ 64 /* ha_info don't return recnumber;
It returns a position to ha_r_rnd */ It returns a position to ha_r_rnd */
#define HA_ONLY_WHOLE_INDEX 128 /* Can't use part key searches */ #define HA_ONLY_WHOLE_INDEX 128 /* Can't use part key searches */
#define HA_RSAME_NO_INDEX 256 /* RSAME can't restore index */ #define HA_NOT_READ_PREFIX_LAST 256 /* RSAME can't restore index */
#define HA_WRONG_ASCII_ORDER 512 /* Can't use sorting through key */ #define HA_WRONG_ASCII_ORDER 512 /* Can't use sorting through key */
#define HA_HAVE_KEY_READ_ONLY 1024 /* Can read only keys (no record) */ #define HA_HAVE_KEY_READ_ONLY 1024 /* Can read only keys (no record) */
#define HA_READ_NOT_EXACT_KEY 2048 /* Can read record after/before key */ #define HA_READ_NOT_EXACT_KEY 2048 /* Can read record after/before key */
#define HA_NO_INDEX 4096 /* No index needed for next/prev */ #define HA_NO_INDEX 4096 /* No index needed for next/prev */
#define HA_LONGLONG_KEYS 8192 /* Can have longlong as key */
#define HA_KEY_READ_WRONG_STR 16384 /* keyread returns converted strings */ #define HA_KEY_READ_WRONG_STR 16384 /* keyread returns converted strings */
#define HA_NULL_KEY 32768 /* One can have keys with NULL */ #define HA_NULL_KEY 32768 /* One can have keys with NULL */
#define HA_DUPP_POS 65536 /* ha_position() gives dupp row */ #define HA_DUPP_POS 65536 /* ha_position() gives dupp row */
...@@ -256,6 +255,10 @@ class handler :public Sql_alloc ...@@ -256,6 +255,10 @@ class handler :public Sql_alloc
virtual int index_first(byte * buf)=0; virtual int index_first(byte * buf)=0;
virtual int index_last(byte * buf)=0; virtual int index_last(byte * buf)=0;
virtual int index_next_same(byte *buf, const byte *key, uint keylen); virtual int index_next_same(byte *buf, const byte *key, uint keylen);
virtual int index_read_last(byte * buf, const byte * key, uint key_len)
{
return (my_errno=HA_ERR_WRONG_COMMAND);
}
virtual int ft_init() virtual int ft_init()
{ return -1; } { return -1; }
virtual FT_INFO *ft_init_ext(uint mode,uint inx,const byte *key, uint keylen, virtual FT_INFO *ft_init_ext(uint mode,uint inx,const byte *key, uint keylen,
......
...@@ -435,7 +435,8 @@ class Item_func_binary :public Item_str_func ...@@ -435,7 +435,8 @@ class Item_func_binary :public Item_str_func
public: public:
Item_func_binary(Item *a) :Item_str_func(a) {} Item_func_binary(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "binary"; } const char *func_name() const { return "binary"; }
String *val_str(String *a) { return (args[0]->val_str(a)); } String *val_str(String *a)
{ a=args[0]->val_str(a); null_value=args[0]->null_value; return a; }
void fix_length_and_dec() { binary=1; max_length=args[0]->max_length; } void fix_length_and_dec() { binary=1; max_length=args[0]->max_length; }
void print(String *str) { print_op(str); } void print(String *str) { print_op(str); }
}; };
......
...@@ -418,7 +418,8 @@ class Item_typecast :public Item_str_func ...@@ -418,7 +418,8 @@ class Item_typecast :public Item_str_func
{ {
public: public:
Item_typecast(Item *a) :Item_str_func(a) {} Item_typecast(Item *a) :Item_str_func(a) {}
String *val_str(String *a) { return (args[0]->val_str(a)); } String *val_str(String *a)
{ a=args[0]->val_str(a); null_value=args[0]->null_value; return a; }
void fix_length_and_dec() { max_length=args[0]->max_length; } void fix_length_and_dec() { max_length=args[0]->max_length; }
void print(String *str); void print(String *str);
}; };
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "ha_berkeley.h" #include "ha_berkeley.h"
#endif #endif
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
#include "ha_innobase.h" #include "ha_innodb.h"
#endif #endif
#include "ha_myisam.h" #include "ha_myisam.h"
#include <nisam.h> #include <nisam.h>
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "mysql_priv.h" #include "mysql_priv.h"
#include "ha_innobase.h" #include "ha_innodb.h"
#include "sql_select.h" #include "sql_select.h"
int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
......
...@@ -557,9 +557,9 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -557,9 +557,9 @@ pthread_handler_decl(handle_one_connection,arg)
pthread_detach_this_thread(); pthread_detach_this_thread();
#if !defined( __WIN__) && !defined(OS2) /* Win32 calls this in pthread_create */ #if !defined( __WIN__) && !defined(OS2) // Win32 calls this in pthread_create
if (my_thread_init()) // needed to be called first before we call // The following calls needs to be done before we call DBUG_ macros
// DBUG_ macros if (my_thread_init())
{ {
close_connection(&thd->net,ER_OUT_OF_RESOURCES); close_connection(&thd->net,ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_thread_count); statistic_increment(aborted_connects,&LOCK_thread_count);
...@@ -568,13 +568,13 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -568,13 +568,13 @@ pthread_handler_decl(handle_one_connection,arg)
} }
#endif #endif
// handle_one_connection() is the only way a thread would start /*
// and would always be on top of the stack handle_one_connection() is the only way a thread would start
// therefore, the thread stack always starts at the address of the first and would always be on top of the stack, therefore, the thread
// local variable of handle_one_connection, which is thd stack always starts at the address of the first local variable
// we need to know the start of the stack so that we could check for of handle_one_connection, which is thd. We need to know the
// stack overruns start of the stack so that we could check for stack overruns.
*/
DBUG_PRINT("info", ("handle_one_connection called by thread %d\n", DBUG_PRINT("info", ("handle_one_connection called by thread %d\n",
thd->thread_id)); thd->thread_id));
// now that we've called my_thread_init(), it is safe to call DBUG_* // now that we've called my_thread_init(), it is safe to call DBUG_*
......
This diff is collapsed.
...@@ -127,12 +127,13 @@ class TMP_TABLE_PARAM { ...@@ -127,12 +127,13 @@ class TMP_TABLE_PARAM {
ha_rows end_write_records; ha_rows end_write_records;
uint field_count,sum_func_count,func_count; uint field_count,sum_func_count,func_count;
uint hidden_field_count; uint hidden_field_count;
uint group_parts,group_length; uint group_parts,group_length,group_null_parts;
uint quick_group; uint quick_group;
bool using_indirect_summary_function; bool using_indirect_summary_function;
TMP_TABLE_PARAM() TMP_TABLE_PARAM()
:copy_funcs_it(copy_funcs), copy_field(0), group_parts(0), group_length(0) :copy_funcs_it(copy_funcs), copy_field(0), group_parts(0),
group_length(0), group_null_parts(0)
{} {}
~TMP_TABLE_PARAM() ~TMP_TABLE_PARAM()
{ {
......
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