Commit 916dab97 authored by unknown's avatar unknown

Merge with new VARCHAR code


configure.in:
  Auto merged
BitKeeper/deleted/.del-acinclude.m4~f4ab416bac5003:
  Auto merged
BitKeeper/deleted/.del-ha_isam.cc~4dce65904db2675e:
  Auto merged
BitKeeper/deleted/.del-ha_isammrg.cc~dc682e4755d77a2e:
  Auto merged
client/mysqldump.c:
  Auto merged
client/mysqltest.c:
  Auto merged
heap/hp_create.c:
  Auto merged
heap/hp_delete.c:
  Auto merged
heap/hp_hash.c:
  Auto merged
heap/hp_write.c:
  Auto merged
include/decimal.h:
  Auto merged
include/m_ctype.h:
  Auto merged
libmysql/libmysql.c:
  Auto merged
libmysqld/Makefile.am:
  Auto merged
myisam/mi_check.c:
  Auto merged
myisam/mi_create.c:
  Auto merged
myisam/mi_write.c:
  Auto merged
mysql-test/r/ctype_tis620.result:
  Auto merged
mysql-test/r/ctype_ucs.result:
  Auto merged
mysql-test/r/myisam.result:
  Auto merged
mysql-test/r/mysqldump.result:
  Auto merged
mysql-test/r/order_by.result:
  Auto merged
mysql-test/r/ps.result:
  Auto merged
mysql-test/r/ps_1general.result:
  Auto merged
mysql-test/r/ps_2myisam.result:
  Auto merged
mysql-test/r/ps_3innodb.result:
  Auto merged
mysql-test/r/ps_4heap.result:
  Auto merged
mysql-test/r/ps_5merge.result:
  Auto merged
mysql-test/r/ps_6bdb.result:
  Auto merged
mysql-test/r/select.result:
  Auto merged
mysql-test/r/strict.result:
  Auto merged
mysql-test/r/subselect.result:
  Auto merged
mysql-test/r/type_blob.result:
  Auto merged
mysql-test/t/ctype_ucs.test:
  Auto merged
mysql-test/t/endspace.test:
  Auto merged
mysql-test/t/myisam.test:
  Auto merged
mysql-test/t/ps_1general.test:
  Auto merged
mysql-test/t/strict.test:
  Auto merged
mysql-test/t/type_blob.test:
  Auto merged
ndb/src/common/util/NdbSqlUtil.cpp:
  Auto merged
scripts/mysql_fix_privilege_tables.sh:
  Auto merged
sql/field.h:
  Auto merged
sql/field_conv.cc:
  Auto merged
sql/ha_heap.cc:
  Auto merged
sql/ha_innodb.cc:
  Auto merged
sql/ha_innodb.h:
  Auto merged
sql/ha_myisam.cc:
  Auto merged
sql/ha_ndbcluster.cc:
  Auto merged
sql/handler.h:
  Auto merged
sql/item_cmpfunc.cc:
  Auto merged
sql/item_sum.cc:
  Auto merged
sql/opt_range.cc:
  Auto merged
sql/opt_sum.cc:
  Auto merged
sql/protocol.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_help.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
sql/structs.h:
  Auto merged
sql/table.cc:
  Auto merged
strings/ctype-czech.c:
  Auto merged
strings/ctype-uca.c:
  Auto merged
strings/ctype-utf8.c:
  Auto merged
strings/ctype-win1250ch.c:
  Auto merged
strings/decimal.c:
  Auto merged
tests/client_test.c:
  Auto merged
mysql-test/r/bdb.result:
  Merge with VARCHAR code
mysql-test/r/heap.result:
  Merge with VARCHAR code
mysql-test/r/innodb.result:
  Merge with VARCHAR code
mysql-test/r/select.result.es:
  Merge with VARCHAR code
mysql-test/t/bdb.test:
  Merge with VARCHAR code
mysql-test/t/heap.test:
  Merge with VARCHAR code
mysql-test/t/innodb.test:
  Merge with VARCHAR code
sql/field.cc:
  Merge with VARCHAR code
sql/item.cc:
  Merge with VARCHAR code
sql/sql_acl.cc:
  Merge with VARCHAR code
sql/sql_parse.cc:
  Merge with VARCHAR code
sql/sql_table.cc:
  Merge with VARCHAR code
sql/sql_update.cc:
  Merge with VARCHAR code
sql/table.h:
  Merge with VARCHAR code
strings/ctype-mb.c:
  Don't pad my_like_range with max_str for simple LIKE expression
strings/ctype-tis620.c:
  Merge with VARCHAR code
strings/ctype-ucs2.c:
  Added new argument to my_strnncollsp_ucs2()
  Simply code
parents 8a2514ba e04e1dd2
......@@ -1623,12 +1623,13 @@ static void dumpTable(uint numFields, char *table)
we'll dump in hex only BLOB columns.
*/
is_blob= (opt_hex_blob && field->charsetnr == 63 &&
(field->type == FIELD_TYPE_STRING ||
field->type == FIELD_TYPE_VAR_STRING ||
field->type == FIELD_TYPE_BLOB ||
field->type == FIELD_TYPE_LONG_BLOB ||
field->type == FIELD_TYPE_MEDIUM_BLOB ||
field->type == FIELD_TYPE_TINY_BLOB)) ? 1 : 0;
(field->type == MYSQL_TYPE_STRING ||
field->type == MYSQL_TYPE_VAR_STRING ||
field->type == MYSQL_TYPE_VARCHAR ||
field->type == MYSQL_TYPE_BLOB ||
field->type == MYSQL_TYPE_LONG_BLOB ||
field->type == MYSQL_TYPE_MEDIUM_BLOB ||
field->type == MYSQL_TYPE_TINY_BLOB)) ? 1 : 0;
if (extended_insert)
{
ulong length = lengths[i];
......
......@@ -778,7 +778,7 @@ int var_set(const char *var_name, const char *var_name_end,
}
else
v = var_reg + digit;
return eval_expr(v, var_val, (const char**)&var_val_end);
DBUG_RETURN(eval_expr(v, var_val, (const char**)&var_val_end));
}
......
......@@ -2420,7 +2420,6 @@ AC_SUBST(readline_basedir)
AC_SUBST(readline_link)
AC_SUBST(readline_h_ln_cmd)
MYSQL_CHECK_ISAM
MYSQL_CHECK_BDB
MYSQL_CHECK_INNODB
MYSQL_CHECK_EXAMPLEDB
......@@ -2481,12 +2480,6 @@ then
# Configuration for optional table handlers
#
if test X"$have_isam" != Xno
then
sql_server_dirs="$sql_server_dirs isam merge"
AC_CONFIG_FILES(isam/Makefile merge/Makefile)
fi
if test X"$have_berkeley_db" != Xno; then
if test X"$have_berkeley_db" != Xyes; then
# we must build berkeley db from source
......
......@@ -86,7 +86,8 @@ extern ulong hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
extern void hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
HASH_INFO *newlink);
extern int hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
const byte *rec2);
const byte *rec2,
my_bool diff_if_only_endspace_difference);
extern int hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
const byte *key);
extern void hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
......@@ -94,6 +95,7 @@ extern uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos);
extern uint hp_rb_key_length(HP_KEYDEF *keydef, const byte *key);
extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key);
extern uint hp_rb_var_key_length(HP_KEYDEF *keydef, const byte *key);
extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
extern int hp_close(register HP_INFO *info);
extern void hp_clear(HP_SHARE *info);
......
......@@ -76,9 +76,21 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
case HA_KEYTYPE_UINT24:
case HA_KEYTYPE_INT8:
keyinfo->seg[j].flag|= HA_SWAP_KEY;
break;
case HA_KEYTYPE_VARBINARY:
/* Case-insensitiveness is handled in coll->hash_sort */
keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT;
/* fall_through */
case HA_KEYTYPE_VARTEXT:
if (!my_binary_compare(keyinfo->seg[j].charset))
keyinfo->flag|= HA_END_SPACE_KEY;
keyinfo->flag|= HA_VAR_LENGTH_KEY;
break;
default:
break;
}
if (keyinfo->seg[j].flag & HA_END_SPACE_ARE_EQUAL)
keyinfo->flag|= HA_END_SPACE_KEY;
}
keyinfo->length= length;
length+= keyinfo->rb_tree.size_of_element +
......@@ -89,7 +101,9 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
key_segs++; /* additional HA_KEYTYPE_END segment */
if (keyinfo->flag & HA_NULL_PART_KEY)
if (keyinfo->flag & HA_VAR_LENGTH_KEY)
keyinfo->get_key_length= hp_rb_var_key_length;
else if (keyinfo->flag & HA_NULL_PART_KEY)
keyinfo->get_key_length= hp_rb_null_key_length;
else
keyinfo->get_key_length= hp_rb_key_length;
......
......@@ -123,7 +123,7 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
while (pos->ptr_to_rec != recpos)
{
if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
last_ptr=pos; /* Previous same key */
gpos=pos;
if (!(pos=pos->next_key))
......
......@@ -262,14 +262,27 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
if (seg->type == HA_KEYTYPE_TEXT)
{
CHARSET_INFO *cs= seg->charset;
uint char_length= (uint) ((uchar*) key - pos);
uint length= seg->length;
if (cs->mbmaxlen > 1)
{
uint length= char_length;
uint char_length;
char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
set_if_smaller(char_length, length); /* QQ: ok to remove? */
set_if_smaller(length, char_length);
}
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
cs->coll->hash_sort(cs, pos, length, &nr, &nr2);
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
{
CHARSET_INFO *cs= seg->charset;
uint length= uint2korr(pos);
if (cs->mbmaxlen > 1)
{
uint char_length;
char_length= my_charpos(cs, pos +2, pos +2 + length,
seg->length/cs->mbmaxlen);
set_if_smaller(length, char_length);
}
cs->coll->hash_sort(cs, pos+2, length, &nr, &nr2);
}
else
{
......@@ -314,6 +327,19 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
{
CHARSET_INFO *cs= seg->charset;
uint length= uint2korr(pos);
if (cs->mbmaxlen > 1)
{
uint char_length;
char_length= my_charpos(cs, pos + 2 , pos + 2 + length,
seg->length/cs->mbmaxlen);
set_if_smaller(length, char_length);
}
cs->coll->hash_sort(cs, pos+2, length, &nr, &nr2);
}
else
{
for (; pos < end ; pos++)
......@@ -366,6 +392,11 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
{
uint length= uint2korr(pos);
seg->charset->hash_sort(seg->charset, pos+2, length, &nr, NULL);
}
else
{
for ( ; pos < (uchar*) key ; pos++)
......@@ -400,6 +431,11 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
{
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
{
uint length= uint2korr(pos);
seg->charset->hash_sort(seg->charset, pos+2, length, &nr, NULL);
}
else
{
for ( ; pos < end ; pos++)
......@@ -415,9 +451,28 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
#endif
/* Compare keys for two records. Returns 0 if they are identical */
/*
Compare keys for two records. Returns 0 if they are identical
int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
SYNOPSIS
hp_rec_key_cmp()
keydef Key definition
rec1 Record to compare
rec2 Other record to compare
diff_if_only_endspace_difference
Different number of end space is significant
NOTES
diff_if_only_endspace_difference is used to allow us to insert
'a' and 'a ' when there is an an unique key.
RETURN
0 Key is identical
<> 0 Key differes
*/
int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2,
my_bool diff_if_only_endspace_difference)
{
HA_KEYSEG *seg,*endseg;
......@@ -442,9 +497,9 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
{
uint char_length= seg->length / cs->mbmaxlen;
char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
set_if_smaller(char_length1, seg->length); /* QQ: ok to remove? */
set_if_smaller(char_length1, seg->length);
char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
set_if_smaller(char_length2, seg->length); /* QQ: ok to remove? */
set_if_smaller(char_length2, seg->length);
}
else
{
......@@ -452,7 +507,30 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
}
if (seg->charset->coll->strnncollsp(seg->charset,
pos1,char_length1,
pos2,char_length2))
pos2,char_length2, 0))
return 1;
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
{
uchar *pos1= (uchar*)rec1 + seg->start;
uchar *pos2= (uchar*)rec2 + seg->start;
uint char_length1= uint2korr(pos1);
uint char_length2= uint2korr(pos2);
CHARSET_INFO *cs= seg->charset;
if (cs->mbmaxlen > 1)
{
uint char_length= seg->length / cs->mbmaxlen;
char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length);
set_if_smaller(char_length1, seg->length);
char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length);
set_if_smaller(char_length2, seg->length);
}
if (cs->coll->strnncollsp(seg->charset,
pos1+2, char_length1,
pos2+2, char_length2,
seg->flag & HA_END_SPACE_ARE_EQUAL ?
0 : diff_if_only_endspace_difference))
return 1;
}
else
......@@ -504,7 +582,31 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
if (seg->charset->coll->strnncollsp(seg->charset,
(uchar*) pos, char_length_rec,
(uchar*) key, char_length_key))
(uchar*) key, char_length_key, 0))
return 1;
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
{
uchar *pos= (uchar*) rec + seg->start;
CHARSET_INFO *cs= seg->charset;
uint char_length_rec= uint2korr(pos);
uint char_length_key= uint2korr(key);
if (cs->mbmaxlen > 1)
{
uint char_length= seg->length / cs->mbmaxlen;
char_length_key= my_charpos(cs, key+2, key +2 + char_length_key,
char_length);
set_if_smaller(char_length_key, seg->length);
char_length_rec= my_charpos(cs, pos +2 , pos + 2 + char_length_rec,
char_length);
set_if_smaller(char_length_rec, seg->length);
}
if (cs->coll->strnncollsp(seg->charset,
(uchar*) pos+2, char_length_rec,
(uchar*) key+2, char_length_key, 0))
return 1;
}
else
......@@ -541,6 +643,13 @@ void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
}
}
#define FIX_LENGTH(cs, pos, length, char_length) \
do { \
if (length > char_length) \
char_length= my_charpos(cs, pos, pos+length, char_length); \
set_if_smaller(char_length,length); \
} while(0)
uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos)
......@@ -593,6 +702,24 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
}
continue;
}
if (seg->flag & HA_VAR_LENGTH_PART)
{
uchar *pos= (uchar*) rec + seg->start;
uint length= seg->length;
uint tmp_length= uint2korr(pos);
CHARSET_INFO *cs= seg->charset;
char_length= length/cs->mbmaxlen;
pos+=2; /* Skip VARCHAR length */
set_if_smaller(length,tmp_length);
FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
memcpy((byte*) key,(byte*) pos,(size_t) char_length);
key+= char_length;
continue;
}
char_length= seg->length;
if (seg->charset->mbmaxlen > 1)
{
......@@ -643,6 +770,23 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
}
continue;
}
if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
{
/* Length of key-part used with heap_rkey() always 2 */
uint tmp_length=uint2korr(old);
uint length= seg->length;
CHARSET_INFO *cs= seg->charset;
char_length= length/cs->mbmaxlen;
k_len-= 2+length;
old+= 2;
set_if_smaller(length,tmp_length); /* Safety */
FIX_LENGTH(cs, old, length, char_length);
store_key_length_inc(key,char_length);
memcpy((byte*) key, old,(size_t) char_length);
key+= char_length;
continue;
}
char_length= seg->length;
if (seg->charset->mbmaxlen > 1)
{
......@@ -682,6 +826,27 @@ uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key)
return key - start_key;
}
uint hp_rb_var_key_length(HP_KEYDEF *keydef, const byte *key)
{
const byte *start_key= key;
HA_KEYSEG *seg, *endseg;
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
{
uint length= seg->length;
if (seg->null_bit && !*key++)
continue;
if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
{
get_key_length(length, key);
}
key+= length;
}
return key - start_key;
}
/*
Test if any of the key parts are NULL.
Return:
......
......@@ -64,7 +64,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
info->update= 0;
DBUG_RETURN(my_errno);
}
if (!(keyinfo->flag & HA_NOSAME))
if (!(keyinfo->flag & HA_NOSAME) || (keyinfo->flag & HA_END_SPACE_KEY))
memcpy(info->lastkey, key, (size_t) keyinfo->length);
}
memcpy(record, pos, (size_t) share->reclength);
......
......@@ -37,7 +37,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
p_lastinx= share->keydef + info->lastinx;
for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++)
{
if (hp_rec_key_cmp(keydef, old, heap_new))
if (hp_rec_key_cmp(keydef, old, heap_new, 0))
{
if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) ||
(*keydef->write_key)(info, keydef, heap_new, pos))
......@@ -74,7 +74,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
}
while (keydef >= share->keydef)
{
if (hp_rec_key_cmp(keydef, old, heap_new))
if (hp_rec_key_cmp(keydef, old, heap_new, 0))
{
if ((*keydef->delete_key)(info, keydef, heap_new, pos, 0) ||
(*keydef->write_key)(info, keydef, old, pos))
......
......@@ -105,7 +105,7 @@ int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record,
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
if (keyinfo->flag & HA_NOSAME)
{
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME | SEARCH_UPDATE;
keyinfo->rb_tree.flag= TREE_NO_DUPS;
}
else
......@@ -369,7 +369,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
pos=empty;
do
{
if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1))
{
DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
}
......
......@@ -17,8 +17,6 @@
#ifndef _decimal_h
#define _decimal_h
#include <my_global.h>
typedef enum {TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} decimal_round_mode;
typedef int32 decimal_digit;
......
......@@ -106,7 +106,8 @@ typedef struct my_collation_handler_st
int (*strnncoll)(struct charset_info_st *,
const uchar *, uint, const uchar *, uint, my_bool);
int (*strnncollsp)(struct charset_info_st *,
const uchar *, uint, const uchar *, uint);
const uchar *, uint, const uchar *, uint,
my_bool diff_if_only_endspace_difference);
int (*strnxfrm)(struct charset_info_st *,
uchar *, uint, const uchar *, uint);
my_bool (*like_range)(struct charset_info_st *,
......@@ -259,7 +260,8 @@ extern int my_strnncoll_simple(CHARSET_INFO *, const uchar *, uint,
const uchar *, uint, my_bool);
extern int my_strnncollsp_simple(CHARSET_INFO *, const uchar *, uint,
const uchar *, uint);
const uchar *, uint,
my_bool diff_if_only_endspace_difference);
extern void my_hash_sort_simple(CHARSET_INFO *cs,
const uchar *key, uint len,
......
......@@ -213,7 +213,7 @@ enum ha_base_keytype {
/*
Key has a part that can have end space. If this is an unique key
we have to handle it differently from other unique keys as we can find
many matching rows for one key (becaue end space are not compared)
many matching rows for one key (because end space are not compared)
*/
#define HA_END_SPACE_KEY 4096
......@@ -221,12 +221,17 @@ enum ha_base_keytype {
#define HA_SPACE_PACK 1 /* Pack space in key-seg */
#define HA_PART_KEY_SEG 4 /* Used by MySQL for part-key-cols */
#define HA_VAR_LENGTH 8
#define HA_VAR_LENGTH_PART 8
#define HA_NULL_PART 16
#define HA_BLOB_PART 32
#define HA_SWAP_KEY 64
#define HA_REVERSE_SORT 128 /* Sort key in reverse order */
#define HA_NO_SORT 256 /* do not bother sorting on this keyseg */
/*
End space in unique/varchar are considered equal. (Like 'a' and 'a ')
Only needed for internal temporary tables.
*/
#define HA_END_SPACE_ARE_EQUAL 512
/* optionbits for database */
#define HA_OPTION_PACK_RECORD 1
......@@ -345,6 +350,7 @@ enum ha_base_keytype {
#define HA_STATE_BUFF_SAVED 512 /* If current keybuff is info->buff */
#define HA_STATE_ROW_CHANGED 1024 /* To invalide ROW cache */
#define HA_STATE_EXTEND_BLOCK 2048
#define HA_STATE_RNEXT_SAME 4096 /* rnext_same was called */
enum en_fieldtype {
FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE,
......
......@@ -57,6 +57,13 @@ typedef struct st_HA_KEYSEG /* Key-portion */
{ length=mi_uint2korr((key)+1); (key)+=3; length_pack=3; } \
}
#define store_key_length_inc(key,length) \
{ if ((length) < 255) \
{ *(key)++=(length); } \
else \
{ *(key)=255; mi_int2store((key)+1,(length)); (key)+=3; } \
}
extern int mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
my_bool, my_bool);
extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
......
......@@ -209,7 +209,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDATE,
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
MYSQL_TYPE_TINY_BLOB=249,
......
.deps
.libs
Makefile
Makefile.in
isamchk
isamlog
pack_isam
test1
test2
test3
2000-04-26 Michael Widenius <monty@mysql.com>
* Fixed bug when doing read_next after a delete/insert which balanced key
pages (In this case one internal buffer was wrongly reused)
1999-11-23 Michael Widenius <monty@monty.pp.sci.fi>
* Changed prefix from ni_ to nisam_ to avoid problems on MacOS X.
1999-08-17 Michael Widenius <monty@tik.pp.sci.fi>
* Changed last parameter to mi_open() to be a bit flag instead of an int.
1998-10-01 Michael Widenius <monty@monty.pp.sci.fi>
* Fixed bug in key packing when using some USE_STRCOLL character sets.
Thu Aug 20 23:17:41 1998 Michael Widenius <monty@bitch.pp.sci.fi>
* isamchk.c: Sometimes isamchk --sort-table caused isamchk to die.
1998-06-28 Michael Widenius <monty@monty.pp.sci.fi>
* Fixed some possible race conditions when using with MySQL and
many reopen/close of the same tables under heavy load!
* Changed isamchk to re-pack records when doing a repair to make it more safer.
Thu Mar 12 21:44:08 1998 Michael Widenius <monty@monty.pp.sci.fi>
* Added a safty test to _ni_rec_unpack.
Wed Nov 26 01:52:55 1997 <monty@monty.pp.sci.fi>
* Fixed small problem when reading delete-marked records with rkey, rnext and
rprev. In normal applications this should never happen.
Thu Nov 20 14:01:21 1997 <monty@monty.pp.sci.fi>
* Fixed range key bug when using compressed key where the first part wasn't
compressed.
* Converted everything to use prototypes.
Mon Sep 29 13:16:27 1997 <monty@monty.pp.sci.fi>
* Fixed problem with isamchk and compressed records files with record_reflength
< 4 (Gave wrong key when using isamchk -rq).
Fri Sep 26 16:06:37 1997 <monty@monty.pp.sci.fi>
* Fixed bug in range calculation.
Thu Aug 14 14:44:33 1997 <monty@monty.pp.sci.fi>
* Removed a couple of unnecessary seeks from 'delete static record'
Tue Jul 1 22:04:16 1997 <monty@monty.pp.sci.fi>
* Added checking of 'wrong packed records' when using 'isamchk -e' or
isamchk -ro.
Fri Feb 7 22:22:28 1997 Michael Widenius <monty@bitch.sci.fi>
* Fixed use of packed tables with threads (One static variable left)
Thu Jan 23 09:05:22 1997 Michael Widenius <monty@bitch.sci.fi>
* Changed create to detect keys > 127 and not pack them. Now one can
define keys with a length of up to (nisam_block_size-18)/2
by changeing N_MAX_KEY_LENGTH.
Fri Jan 10 21:01:44 1997 Michael Widenius <monty@bitch.sci.fi>
* added signed chars as key type.
Fri Apr 26 14:31:05 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
* create.c: All keyfile blocks are now IO_SIZE big (for better keycashing).
Tue Mar 12 22:42:52 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
* isamchk.c: Changed to print info if system table
* write.c: Don't allow more than 1 record in system table.
Fri Feb 2 16:40:32 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
* isamchk.c; Check that delete-link-chain is ok before trying to delete with 'q'.
Thu Jan 11 13:21:23 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
* All same isam files now shares a structure to allow many opens off the same
file
Sat Nov 25 12:33:53 1995 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
* All functions now used my_errno instead of errno
Mon Oct 23 12:32:02 1995 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
* isamchk.c: Don't print that database should be fixed on automatic rep.
Sun Aug 27 20:13:56 1995 Michael Widenius <monty@bitch.analytikerna.se (Michael Widenius)>
* _dynrec.c added flush_io_cash() if someone did a read when using
WRITE CASHING.
Thu Apr 20 01:41:24 1995 Michael Widenius (monty@bitch)
* fixed errno when got error of 'key-not-found' when updateing or
deleting record.
Tue Jan 17 19:37:48 1995 Michael Widenius (monty@bitch)
* isamchk can now unpack databases.
* prolinted all files.
Fri May 27 15:01:06 1994 Michael Widenius (monty@bitch)
* Don't lock packed databases.
Sat Apr 16 22:41:23 1994 Michael Widenius (monty@bitch)
* Added new function read_rsame_with_pos.
Wed Mar 30 15:52:19 1994 Michael Widenius (monty@bitch)
* Added creation and recover date to indexfile and isamchk.
Sat Mar 26 15:03:37 1994 Michael Widenius (monty@bitch)
* change is_panic() to close all files on ha_panic(write) on systems
(VMS) with can't open one file twice.
Fri Feb 4 21:09:56 1994 Michael Widenius (monty@bitch)
* READ_CASH on packed files now makes them mem-mapped if possibly
Sat Sep 18 14:56:32 1993 Michael Widenius (monty at bitch)
* changed _search to use pointer to buffer when reading keys.
Mon Aug 16 19:45:29 1993 Michael Widenius (monty at bitch)
* isamchk and packisam resolves symbolic links before file is used.
This forces temp-files on same disk as orginal file and rename
of temp-files dosen't destroy symbolic links.
Mon May 31 18:26:08 1993 Michael Widenius (monty at bitch)
* Added crc-check of records when packing for safe test if pack ok.
Tue Mar 2 19:16:00 1993 Michael Widenius (monty@bitch)
* Added logging of records with ni_log().
Fri Jan 29 00:56:58 1993 Michael Widenius (monty@bitch)
* Fixed bug in _read_rnd_static_record ; A lock was made for
each record even if it was in cash.
Sun Nov 15 12:51:36 1992 Michael Widenius (monty@bitch)
* last change breaked _dynrec, when not compileing with dbug.
Fri Nov 6 03:46:38 1992 Michael Widenius (monty@bitch)
* Fixed bugg when using packed records and reclength < 8 byte.
Wed Oct 28 22:23:32 1992 Michael Widenius (monty@bitch)
* Changed _cash.c to use io_cash to allow use of aioread.
Fri Oct 23 00:45:53 1992 Michael Widenius (monty@bitch)
* Added MY_WAIT_IF_FULL to pack_isam.
Sat Oct 17 14:51:15 1992 Michael Widenius (monty@bitch)
* Added use of subset of keys (isamchk -k#)
Mon Oct 5 21:53:18 1992 Michael Widenius (monty@bitch)
* Remove reloc of database ; Gives only problems with isamchk.
Mon Aug 17 03:17:09 1992 Michael Widenius (monty@bitch)
* Changed isam to use io_cash instead of rec_cash
# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
#
# 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
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
LDADD = @CLIENT_EXTRA_LDFLAGS@ libnisam.a ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
pkglib_LIBRARIES = libnisam.a
bin_PROGRAMS = isamchk isamlog pack_isam
isamchk_DEPENDENCIES= $(LIBRARIES)
isamlog_DEPENDENCIES= $(LIBRARIES)
pack_isam_DEPENDENCIES= $(LIBRARIES)
noinst_PROGRAMS = test1 test2 test3
noinst_HEADERS = isamdef.h
test1_DEPENDENCIES= $(LIBRARIES)
test2_DEPENDENCIES= $(LIBRARIES)
test3_DEPENDENCIES= $(LIBRARIES)
libnisam_a_SOURCES = open.c extra.c info.c rkey.c rnext.c \
_search.c _page.c _key.c _locking.c \
rrnd.c _cache.c _statrec.c _packrec.c \
_dynrec.c update.c write.c delete.c \
rprev.c rfirst.c rlast.c rsame.c rsamepos.c \
panic.c close.c create.c range.c _dbug.c \
log.c changed.c static.c
isamchk_SOURCES = isamchk.c sort.c
CLEANFILES = test?.IS? isam.log
# Move to automake rules ?
prolint:; plparse -b -u -hF1 "-width(0,0)" "-format=%f:%l:\s%t:%n\s%m" \
"-elib(????)" "+elib(?3??)" my.lnt $(nisam_SOURCES)
# Don't update the files from bitkeeper
%::SCCS/s.%
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Functions for read record cacheing with nisam */
/* Used instead of my_b_read() to allow for no-cacheed seeks */
#include "isamdef.h"
#define READING_NEXT 1
#define READING_HEADER 2
/* Copy block from cache if it`s in it. If re_read_if_possibly is */
/* set read to cache (if after current file-position) else read to */
/* buff */
int _nisam_read_cache(IO_CACHE *info, byte *buff, ulong pos, uint length,
int flag)
{
uint read_length,in_buff_length;
ulong offset;
char *in_buff_pos;
if (pos < info->pos_in_file)
{
read_length= (uint) min((ulong) length,(ulong) (info->pos_in_file-pos));
info->seek_not_done=1;
VOID(my_seek(info->file,pos,MY_SEEK_SET,MYF(0)));
if (my_read(info->file,buff,read_length,MYF(MY_NABP)))
return 1;
if (!(length-=read_length))
return 0;
pos+=read_length;
buff+=read_length;
}
if ((offset=pos - (ulong) info->pos_in_file) <
(ulong) (info->read_end - info->request_pos))
{
in_buff_pos=info->request_pos+(uint) offset;
in_buff_length= min(length,(uint) (info->read_end-in_buff_pos));
memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length);
if (!(length-=in_buff_length))
return 0;
pos+=in_buff_length;
buff+=in_buff_length;
}
else
in_buff_length=0;
if (flag & READING_NEXT)
{
if (pos != ((info)->pos_in_file +
(uint) ((info)->read_end - (info)->request_pos)))
{
info->pos_in_file=pos; /* Force start here */
info->read_pos=info->read_end=info->request_pos; /* Everything used */
info->seek_not_done=1;
}
else
info->read_pos=info->read_end; /* All block used */
if (!(*info->read_function)(info,buff,length))
return 0;
if (!(flag & READING_HEADER) || info->error == -1 ||
(uint) info->error+in_buff_length < 3)
return 1;
if (BLOCK_INFO_HEADER_LENGTH < in_buff_length + (uint) info->error)
bzero(buff+info->error,BLOCK_INFO_HEADER_LENGTH - in_buff_length -
(uint) info->error);
return 0;
}
info->seek_not_done=1;
VOID(my_seek(info->file,pos,MY_SEEK_SET,MYF(0)));
if ((read_length=my_read(info->file,buff,length,MYF(0))) == length)
return 0;
if (!(flag & READING_HEADER) || (int) read_length == -1 ||
read_length+in_buff_length < 3)
return 1;
bzero(buff+read_length,BLOCK_INFO_HEADER_LENGTH - in_buff_length -
read_length);
return 0;
} /* _nisam_read_cache */
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Support rutiner with are using with dbug */
#include "isamdef.h"
/* Print a key in user understandable format */
void _nisam_print_key(FILE *stream, register N_KEYSEG *keyseg, const uchar *key)
{
int flag;
short int s_1;
long int l_1;
float f_1;
double d_1;
uchar *end;
VOID(fputs("Key: \"",stream));
flag=0;
for (; keyseg->base.type ;keyseg++)
{
if (flag++)
VOID(putc('-',stream));
end= (uchar*) key+ keyseg->base.length;
switch (keyseg->base.type) {
case HA_KEYTYPE_BINARY:
if (!(keyseg->base.flag & HA_SPACE_PACK) && keyseg->base.length == 1)
{ /* packed binary digit */
VOID(fprintf(stream,"%d",(uint) *key++));
break;
}
/* fall through */
case HA_KEYTYPE_TEXT:
case HA_KEYTYPE_NUM:
if (keyseg->base.flag & HA_SPACE_PACK)
{
VOID(fprintf(stream,"%.*s",(int) *key,key+1));
key+= (int) *key+1;
}
else
{
VOID(fprintf(stream,"%.*s",(int) keyseg->base.length,key));
key=end;
}
break;
case HA_KEYTYPE_INT8:
VOID(fprintf(stream,"%d",(int) *((signed char*) key)));
key=end;
break;
case HA_KEYTYPE_SHORT_INT:
shortget(s_1,key);
VOID(fprintf(stream,"%d",(int) s_1));
key=end;
break;
case HA_KEYTYPE_USHORT_INT:
{
ushort u_1;
ushortget(u_1,key);
VOID(fprintf(stream,"%u",(uint) u_1));
key=end;
break;
}
case HA_KEYTYPE_LONG_INT:
longget(l_1,key);
VOID(fprintf(stream,"%ld",l_1));
key=end;
break;
case HA_KEYTYPE_ULONG_INT:
longget(l_1,key);
VOID(fprintf(stream,"%lu",(ulong) l_1));
key=end;
break;
case HA_KEYTYPE_INT24:
VOID(fprintf(stream,"%ld",(long) sint3korr(key)));
key=end;
break;
case HA_KEYTYPE_UINT24:
VOID(fprintf(stream,"%ld",(long) uint3korr(key)));
key=end;
break;
case HA_KEYTYPE_FLOAT:
bmove((byte*) &f_1,(byte*) key,(int) sizeof(float));
VOID(fprintf(stream,"%g",(double) f_1));
key=end;
break;
case HA_KEYTYPE_DOUBLE:
doubleget(d_1,key);
VOID(fprintf(stream,"%g",d_1));
key=end;
break;
#ifdef HAVE_LONG_LONG
case HA_KEYTYPE_LONGLONG:
{
char buff[21];
longlong tmp;
longlongget(tmp,key);
longlong2str(tmp,buff,-10);
VOID(fprintf(stream,"%s",buff));
key=end;
break;
}
case HA_KEYTYPE_ULONGLONG:
{
char buff[21];
longlong tmp;
longlongget(tmp,key);
longlong2str(tmp,buff,10);
VOID(fprintf(stream,"%s",buff));
key=end;
break;
}
#endif
default: break; /* This never happens */
}
}
VOID(fputs("\n",stream));
return;
} /* print_key */
This diff is collapsed.
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Functions to handle keys */
#include "isamdef.h"
#include "m_ctype.h"
static void _nisam_put_key_in_record(N_INFO *info,uint keynr,byte *record);
/* Make a intern key from a record */
/* If ascii key convert according to sortorder */
/* Ret: Length of key */
uint _nisam_make_key(register N_INFO *info, uint keynr, uchar *key, const char *record, ulong filepos)
{
uint length;
byte *pos,*end;
uchar *start;
reg1 N_KEYSEG *keyseg;
enum ha_base_keytype type;
DBUG_ENTER("_nisam_make_key");
start=key;
for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->base.type ;keyseg++)
{
type=(enum ha_base_keytype) keyseg->base.type;
if (keyseg->base.flag & HA_SPACE_PACK)
{
pos= (byte*) record+keyseg->base.start; end=pos+keyseg->base.length;
if (type != HA_KEYTYPE_NUM)
{
while (end > pos && end[-1] == ' ')
end--;
}
else
{
while (pos < end && pos[0] == ' ')
pos++;
}
*key++= (uchar) (length=(uint) (end-pos));
memcpy((byte*) key,(byte*) pos,(size_t) length);
if (!use_strnxfrm(default_charset_info))
{
if (type == HA_KEYTYPE_TEXT)
my_strnxfrm(default_charset_info,(uchar*) key, length,
(uchar*) key, length);
}
key+=length;
}
else
{
memcpy((byte*) key,(byte*) record+keyseg->base.start,
(size_t) keyseg->base.length);
if (!use_strnxfrm(default_charset_info))
{
if (type == HA_KEYTYPE_TEXT)
my_strnxfrm(default_charset_info,(uchar*) key,
(uint) keyseg->base.length,
(uchar*) key,
(uint) keyseg->base.length);
}
#ifdef NAN_TEST
else if (type == HA_KEYTYPE_FLOAT)
{
float nr;
bmove((byte*) &nr,(byte*) key,sizeof(float));
if (nr == (float) FLT_MAX)
{
nr= (float) FLT_MAX;
bmove((byte*) key,(byte*) &nr,sizeof(float));
}
}
else if (type == HA_KEYTYPE_DOUBLE)
{
double nr;
bmove((byte*) &nr,(byte*) key,sizeof(double));
if (nr == DBL_MAX)
{
nr=DBL_MAX;
bmove((byte*) key,(byte*) &nr,sizeof(double));
}
}
#endif
key+= keyseg->base.length;
}
}
_nisam_dpointer(info,key,filepos);
DBUG_PRINT("exit",("keynr: %d",keynr));
DBUG_DUMP("key",(byte*) start,(uint) (key-start)+keyseg->base.length);
DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,info->s->keyinfo[keynr].seg,start););
DBUG_RETURN((uint) (key-start)); /* Return keylength */
} /* _nisam_make_key */
/* Pack a key to intern format from given format (c_rkey) */
/* if key_length is set returns new length of key */
uint _nisam_pack_key(register N_INFO *info, uint keynr, uchar *key, uchar *old, uint key_length)
/* Length of used key */
{
int k_length;
uint length;
uchar *pos,*end;
reg1 N_KEYSEG *keyseg;
enum ha_base_keytype type;
DBUG_ENTER("_nisam_pack_key");
if ((k_length=(int) key_length) <= 0)
k_length=N_MAX_KEY_BUFF;
for (keyseg=info->s->keyinfo[keynr].seg ;
keyseg->base.type && k_length >0;
k_length-=keyseg->base.length, old+=keyseg->base.length, keyseg++)
{
length=min((uint) keyseg->base.length,(uint) k_length);
type=(enum ha_base_keytype) keyseg->base.type;
if (keyseg->base.flag & HA_SPACE_PACK)
{
pos=old; end=pos+length;
if (type != HA_KEYTYPE_NUM)
{
while (end > pos && end[-1] == ' ')
end--;
}
else
{
while (pos < end && pos[0] == ' ')
pos++;
}
*key++ = (uchar) (length=(uint) (end-pos));
memcpy((byte*) key,pos,(size_t) length);
}
else
memcpy((byte*) key,old,(size_t) length);
if (!use_strnxfrm(default_charset_info))
{
if (type == HA_KEYTYPE_TEXT)
my_strnxfrm(default_charset_info,(uchar*) key,length,
(uchar*) key,length);
}
key+= length;
}
if (!keyseg->base.type)
{
if (k_length >= 0) /* Hole key */
key_length=0;
}
else
{ /* Part-key ; fill with null */
length= (uint) -k_length; /* unused part of last key */
do
{
length+= (keyseg->base.flag & HA_SPACE_PACK) ? 1 :
keyseg->base.length;
keyseg++;
} while (keyseg->base.type);
bzero((byte*) key,length);
}
DBUG_RETURN(key_length); /* Return part-keylength */
} /* _nisam_pack_key */
/* Put a key in record */
/* Used when only-keyread is wanted */
static void _nisam_put_key_in_record(register N_INFO *info, uint keynr, byte *record)
{
uint length;
reg2 byte *key;
byte *pos;
reg1 N_KEYSEG *keyseg;
DBUG_ENTER("_nisam_put_key_in_record");
key=(byte*) info->lastkey;
for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->base.type ;keyseg++)
{
if (keyseg->base.flag & HA_SPACE_PACK)
{
length= (uint) (uchar) *key++;
pos= record+keyseg->base.start;
if (keyseg->base.type != (int) HA_KEYTYPE_NUM)
{
memcpy(pos,key,(size_t) length);
bfill(pos+length,keyseg->base.length-length,' ');
}
else
{
bfill(pos,keyseg->base.length-length,' ');
memcpy(pos+keyseg->base.length-length,key,(size_t) length);
}
key+=length;
}
else
{
memcpy(record+keyseg->base.start,(byte*) key,
(size_t) keyseg->base.length);
key+= keyseg->base.length;
}
}
DBUG_VOID_RETURN;
} /* _nisam_put_key_in_record */
/* Here when key reads are used */
int _nisam_read_key_record(N_INFO *info, ulong filepos, byte *buf)
{
VOID(_nisam_writeinfo(info,0));
if (filepos != NI_POS_ERROR)
{
if (info->lastinx >= 0)
{ /* Read only key */
_nisam_put_key_in_record(info,(uint) info->lastinx,buf);
info->update|= HA_STATE_AKTIV; /* We should find a record */
return 0;
}
my_errno=HA_ERR_WRONG_INDEX;
return(-1);
}
return(-1); /* Wrong data to read */
}
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
locking of isam-tables.
reads info from a isam-table. Must be first request before doing any furter
calls to any isamfunktion. Is used to allow many process use the same
isamdatabase.
*/
#include "isamdef.h"
#ifdef __WIN__
#include <errno.h>
#endif
/* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
int nisam_lock_database(N_INFO *info, int lock_type)
{
int error;
uint count;
ISAM_SHARE *share;
uint flag;
DBUG_ENTER("nisam_lock_database");
flag=error=0;
#ifndef NO_LOCKING
share=info->s;
if (share->base.options & HA_OPTION_READ_ONLY_DATA ||
info->lock_type == lock_type)
DBUG_RETURN(0);
pthread_mutex_lock(&share->intern_lock);
switch (lock_type) {
case F_UNLCK:
if (info->lock_type == F_RDLCK)
count= --share->r_locks;
else
count= --share->w_locks;
if (info->lock_type == F_WRLCK && !share->w_locks &&
flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_KEEP))
error=my_errno;
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
if (end_io_cache(&info->rec_cache))
error=my_errno;
if (!count)
{
if (share->changed && !share->w_locks)
{
share->state.process= share->last_process=share->this_process;
share->state.loop= info->last_loop= ++info->this_loop;
share->state.uniq= info->last_uniq= info->this_uniq;
if (my_pwrite(share->kfile,(char*) &share->state.header,
share->state_length,0L,MYF(MY_NABP)))
error=my_errno;
share->changed=0;
#ifdef __WIN__
if (nisam_flush)
{
_commit(share->kfile);
_commit(info->dfile);
}
else
share->not_flushed=1;
#endif
}
if (share->r_locks)
{ /* Only read locks left */
flag=1;
if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
error=my_errno;
}
else if (!share->w_locks)
{ /* No more locks */
flag=1;
if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
error=my_errno;
}
}
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
info->lock_type= F_UNLCK;
break;
case F_RDLCK:
if (info->lock_type == F_WRLCK)
{ /* Change RW to READONLY */
if (share->w_locks == 1)
{
flag=1;
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
MYF(MY_SEEK_NOT_DONE)))
{
error=my_errno;
break;
}
}
share->w_locks--;
share->r_locks++;
info->lock_type=lock_type;
break;
}
if (!share->r_locks && !share->w_locks)
{
flag=1;
#ifdef HAVE_FCNTL
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
{
error=my_errno;
break;
}
if (my_pread(share->kfile,
(char*) &share->state.header,share->state_length,0L,
MYF(MY_NABP)))
{
error=my_errno;
VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
my_errno=error;
break;
}
#else
VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
{
error=my_errno;
break;
}
if (my_read(share->kfile,
(char*) &share->state.header,share->state_length,
MYF(MY_NABP)))
{
error=my_errno;
VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait));
my_errno=error;
break;
}
#endif
}
VOID(_nisam_test_if_changed(info));
share->r_locks++;
info->lock_type=lock_type;
break;
case F_WRLCK:
if (info->lock_type == F_RDLCK)
{ /* Change RW to READONLY */
if (share->r_locks == 1)
{
flag=1;
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
MYF(info->lock_wait | MY_SEEK_NOT_DONE)))
{
error=my_errno;
break;
}
share->r_locks--;
share->w_locks++;
info->lock_type=lock_type;
break;
}
}
if (!(share->base.options & HA_OPTION_READ_ONLY_DATA) && !share->w_locks)
{
flag=1;
VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
{
error=my_errno;
break;
}
if (!share->r_locks)
{
if (my_read(share->kfile,
(char*) &share->state.header,share->state_length,
MYF(MY_NABP)))
{
error=my_errno;
VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait));
my_errno=error;
break;
}
}
}
VOID(_nisam_test_if_changed(info));
info->lock_type=lock_type;
share->w_locks++;
break;
default:
break; /* Impossible */
}
pthread_mutex_unlock(&share->intern_lock);
#if defined(FULL_LOG) || defined(_lint)
lock_type|=(int) (flag << 8); /* Set bit to set if real lock */
nisam_log_command(LOG_LOCK,info,(byte*) &lock_type,sizeof(lock_type),
error);
#endif
#endif
DBUG_RETURN(error);
} /* nisam_lock_database */
/* Is used before access to database is granted */
int _nisam_readinfo(register N_INFO *info, int lock_type, int check_keybuffer)
{
ISAM_SHARE *share;
DBUG_ENTER("_nisam_readinfo");
share=info->s;
if (info->lock_type == F_UNLCK)
{
if (!share->r_locks && !share->w_locks)
{
#ifndef HAVE_FCNTL
VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
#endif
#ifndef NO_LOCKING
#ifdef UNSAFE_LOCKING
if ((info->tmp_lock_type=lock_type) != F_RDLCK)
#endif
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
DBUG_RETURN(1);
#endif
#ifdef HAVE_FCNTL
if (my_pread(share->kfile,
(char*) &share->state.header,share->state_length,0L,
MYF(MY_NABP)))
#else
if (my_read(share->kfile,
(char*) &share->state.header,share->state_length,
MYF(MY_NABP)))
#endif
{
#ifndef NO_LOCKING
int error=my_errno;
VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
MYF(MY_SEEK_NOT_DONE)));
my_errno=error;
#endif
DBUG_RETURN(1);
}
}
if (check_keybuffer)
VOID(_nisam_test_if_changed(info));
}
else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
{
my_errno=EACCES; /* Not allowed to change */
DBUG_RETURN(-1); /* when have read_lock() */
}
DBUG_RETURN(0);
} /* _nisam_readinfo */
/* Every isam-function that uppdates the isam-database must! end */
/* with this request */
/* ARGSUSED */
int _nisam_writeinfo(register N_INFO *info, uint flags)
{
int error,olderror;
ISAM_SHARE *share;
DBUG_ENTER("_nisam_writeinfo");
error=0;
share=info->s;
if (share->r_locks == 0 && share->w_locks == 0)
{
olderror=my_errno; /* Remember last error */
if (flags)
{ /* Two threads can't be here */
share->state.process= share->last_process= share->this_process;
share->state.loop= info->last_loop= ++info->this_loop;
share->state.uniq= info->last_uniq= info->this_uniq;
if ((error=my_pwrite(share->kfile,(char*) &share->state.header,
share->state_length,0L,MYF(MY_NABP)) != 0))
olderror=my_errno;
#ifdef __WIN__
if (nisam_flush)
{
_commit(share->kfile);
_commit(info->dfile);
}
#endif
}
if (flags != 2)
{
#ifndef NO_LOCKING
#ifdef UNSAFE_LOCKING
if (info->tmp_lock_type != F_RDLCK)
#endif
{
if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
DBUG_RETURN(1);
}
#endif
}
my_errno=olderror;
}
else if (flags)
share->changed= 1; /* Mark keyfile changed */
DBUG_RETURN(error);
} /* _nisam_writeinfo */
/* Test if someone has changed the database */
/* (Should be called after readinfo) */
int _nisam_test_if_changed(register N_INFO *info)
{
#ifndef NO_LOCKING
{
ISAM_SHARE *share=info->s;
if (share->state.process != share->last_process ||
share->state.loop != info->last_loop ||
share->state.uniq != info->last_uniq)
{ /* Keyfile has changed */
if (share->state.process != share->this_process)
VOID(flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_RELEASE));
share->last_process=share->state.process;
info->last_loop= share->state.loop;
info->last_uniq= share->state.uniq;
info->update|= HA_STATE_WRITTEN; /* Must use file on next */
info->data_changed= 1; /* For nisam_is_changed */
return 1;
}
}
#endif
return (!(info->update & HA_STATE_AKTIV) ||
(info->update & (HA_STATE_WRITTEN | HA_STATE_DELETED |
HA_STATE_KEY_CHANGED)));
} /* _nisam_test_if_changed */
This diff is collapsed.
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* L{ser och skriver nyckelblock */
#include "isamdef.h"
#ifdef __WIN__
#include <errno.h>
#endif
/* Fetch a key-page in memory */
uchar *_nisam_fetch_keypage(register N_INFO *info, N_KEYDEF *keyinfo,
my_off_t page, uchar *buff, int return_buffer)
{
uchar *tmp;
tmp=(uchar*) key_cache_read(dflt_key_cache,
info->s->kfile,page,DFLT_INIT_HITS,(byte*) buff,
(uint) keyinfo->base.block_length,
(uint) keyinfo->base.block_length,
return_buffer);
if (tmp == info->buff)
{
info->update|=HA_STATE_BUFF_SAVED;
info->int_pos=(ulong) page;
info->buff_used=1;
}
else
{
info->update&= ~HA_STATE_BUFF_SAVED;
if (tmp)
info->int_pos=(ulong) page;
else
{
info->int_pos=NI_POS_ERROR;
DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno));
my_errno=HA_ERR_CRASHED;
}
}
return tmp;
} /* _nisam_fetch_keypage */
/* Write a key-page on disk */
int _nisam_write_keypage(register N_INFO *info, register N_KEYDEF *keyinfo,
my_off_t page, uchar *buff)
{
reg3 uint length;
#ifndef QQ /* Safety check */
if (page < info->s->base.keystart ||
page+keyinfo->base.block_length > info->s->state.key_file_length ||
page & (nisam_block_size-1))
{
DBUG_PRINT("error",("Trying to write outside key region: %lu",
(long) page));
my_errno=EINVAL;
return(-1);
}
DBUG_PRINT("page",("write page at: %lu",(long) page,buff));
DBUG_DUMP("buff",(byte*) buff,getint(buff));
#endif
if ((length=keyinfo->base.block_length) > IO_SIZE*2 &&
info->s->state.key_file_length != page+length)
length= ((getint(buff)+IO_SIZE-1) & (uint) ~(IO_SIZE-1));
#ifdef HAVE_purify
{
length=getint(buff);
bzero((byte*) buff+length,keyinfo->base.block_length-length);
length=keyinfo->base.block_length;
}
#endif
return (key_cache_write(dflt_key_cache,
info->s->kfile,page,DFLT_INIT_HITS,
(byte*) buff,length,
(uint) keyinfo->base.block_length,
(int) (info->lock_type != F_UNLCK)));
} /* nisam_write_keypage */
/* Remove page from disk */
int _nisam_dispose(register N_INFO *info, N_KEYDEF *keyinfo, my_off_t pos)
{
uint keynr= (uint) (keyinfo - info->s->keyinfo);
ulong old_link; /* ulong is ok here */
DBUG_ENTER("_nisam_dispose");
old_link=info->s->state.key_del[keynr];
info->s->state.key_del[keynr]=(ulong) pos;
DBUG_RETURN(key_cache_write(dflt_key_cache,
info->s->kfile,pos,DFLT_INIT_HITS,
(byte*) &old_link,
sizeof(long),
(uint) keyinfo->base.block_length,
(int) (info->lock_type != F_UNLCK)));
} /* _nisam_dispose */
/* Make new page on disk */
ulong _nisam_new(register N_INFO *info, N_KEYDEF *keyinfo)
{
uint keynr= (uint) (keyinfo - info->s->keyinfo);
ulong pos;
DBUG_ENTER("_nisam_new");
if ((pos=info->s->state.key_del[keynr]) == NI_POS_ERROR)
{
if (info->s->state.key_file_length >= info->s->base.max_key_file_length)
{
my_errno=HA_ERR_INDEX_FILE_FULL;
DBUG_RETURN(NI_POS_ERROR);
}
pos=info->s->state.key_file_length;
info->s->state.key_file_length+= keyinfo->base.block_length;
}
else
{
if (!key_cache_read(dflt_key_cache,
info->s->kfile,pos,DFLT_INIT_HITS,
(byte*) &info->s->state.key_del[keynr],
(uint) sizeof(long),
(uint) keyinfo->base.block_length,0))
pos= NI_POS_ERROR;
}
DBUG_PRINT("exit",("Pos: %d",pos));
DBUG_RETURN(pos);
} /* _nisam_new */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
ccc -DHAVE_CONFIG_H -I. -I. -I.. -I./../include -I../include -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c _cache.c _dbug.c _dynrec.c _key.c _locking.c _packrec.c _page.c _search.c _statrec.c changed.c close.c create.c delete.c extra.c info.c log.c open.c panic.c range.c rfirst.c rkey.c rlast.c rnext.c rprev.c rrnd.c rsame.c rsamepos.c static.c update.c write.c
rm libnisam.a
ar -cr libnisam.a _cache.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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