Add support for up to VARCHAR (size up to 65535)

Renamed HA_VAR_LENGTH to HA_VAR_LENGTH_PART
Renamed in all files FIELD_TYPE_STRING and FIELD_TYPE_VAR_STRING to MYSQL_TYPE_STRING and MYSQL_TYPE_VAR_STRING to make it easy to catch all possible errors
Added support for VARCHAR KEYS to heap
Removed support for ISAM
Now only long VARCHAR columns are changed to TEXT on demand (not CHAR)
Internal temporary files can now use fixed length tables if the used VARCHAR columns are short


BitKeeper/deleted/.del-ha_isam.cc~4dce65904db2675e:
  Delete: sql/ha_isam.cc
BitKeeper/deleted/.del-_cache.c~b5d80b5c3ae233b1:
  Delete: isam/_cache.c
BitKeeper/deleted/.del-_dbug.c~88d7964ae5e3c9bd:
  Delete: isam/_dbug.c
BitKeeper/deleted/.del-_dynrec.c~48dd758f5a5450df:
  Delete: isam/_dynrec.c
BitKeeper/deleted/.del-_key.c~ce62d47a6c681084:
  Delete: isam/_key.c
BitKeeper/deleted/.del-_locking.c~dea4cdc6ea425c67:
  Delete: isam/_locking.c
BitKeeper/deleted/.del-_packrec.c~47ae1b16c007e9be:
  Delete: isam/_packrec.c
BitKeeper/deleted/.del-_page.c~148b1a613d052ee8:
  Delete: isam/_page.c
BitKeeper/deleted/.del-_search.c~f509292aa1ff18ff:
  Delete: isam/_search.c
BitKeeper/deleted/.del-_statrec.c~58d9263b3475d58b:
  Delete: isam/_statrec.c
BitKeeper/deleted/.del-changed.c~d075de80a314b02d:
  Delete: isam/changed.c
BitKeeper/deleted/.del-close.c~fd62629496ee5bcc:
  Delete: isam/close.c
BitKeeper/deleted/.del-create.c~96cecc433c0c2242:
  Delete: isam/create.c
BitKeeper/deleted/.del-delete.c~65ee8daaa75a14b6:
  Delete: isam/delete.c
BitKeeper/deleted/.del-extra.c~706f29d72beb2565:
  Delete: isam/extra.c
BitKeeper/deleted/.del-info.c~96cfb747af8da0d:
  Delete: isam/info.c
BitKeeper/deleted/.del-isamchk.c~c0f59c2687d2248f:
  Delete: isam/isamchk.c
BitKeeper/deleted/.del-isamlog.c~85b6b31c6e2b8519:
  Delete: isam/isamlog.c
BitKeeper/deleted/.del-log.c~55a973013d55cade:
  Delete: isam/log.c
BitKeeper/deleted/.del-open.c~95b3b75042fae00a:
  Delete: isam/open.c
BitKeeper/deleted/.del-pack_isam.c~43801f0df7504834:
  Delete: isam/pack_isam.c
BitKeeper/deleted/.del-panic.c~f7fd71605324f8f3:
  Delete: isam/panic.c
BitKeeper/deleted/.del-range.c~142f1f8ac4948082:
  Delete: isam/range.c
BitKeeper/deleted/.del-rfirst.c~66f494291dc005d3:
  Delete: isam/rfirst.c
BitKeeper/deleted/.del-rkey.c~cc54c6498352f999:
  Delete: isam/rkey.c
BitKeeper/deleted/.del-rlast.c~d1fe1866139e9866:
  Delete: isam/rlast.c
BitKeeper/deleted/.del-rnext.c~b308eaa1e11ea7de:
  Delete: isam/rnext.c
BitKeeper/deleted/.del-rprev.c~b359f71fdea4bbce:
  Delete: isam/rprev.c
BitKeeper/deleted/.del-rrnd.c~7fcfcce88d4a5200:
  Delete: isam/rrnd.c
BitKeeper/deleted/.del-rsame.c~75a62d5548103a15:
  Delete: isam/rsame.c
BitKeeper/deleted/.del-rsamepos.c~5b5652dd2cda6d5d:
  Delete: isam/rsamepos.c
BitKeeper/deleted/.del-sort.c~e2e56b5a37ce86f4:
  Delete: isam/sort.c
BitKeeper/deleted/.del-static.c~3a1354b84f4a9cc7:
  Delete: isam/static.c
BitKeeper/deleted/.del-test1.c~64d52e9412d457ed:
  Delete: isam/test1.c
BitKeeper/deleted/.del-test2.c~2f9a632cab572958:
  Delete: isam/test2.c
BitKeeper/deleted/.del-test3.c~e8a7a4afe8a087:
  Delete: isam/test3.c
BitKeeper/deleted/.del-isamdef.h~ac8d49e7e2201c66:
  Delete: isam/isamdef.h
BitKeeper/deleted/.del-update.c~670264f51dc44934:
  Delete: isam/update.c
BitKeeper/deleted/.del-write.c~8f1918b1f6770e54:
  Delete: isam/write.c
BitKeeper/deleted/.del-Makefile.am~6cfa0db5e7778d09:
  Delete: isam/Makefile.am
BitKeeper/deleted/.del-make-ccc~3ee55391eda0b0ab:
  Delete: isam/make-ccc
BitKeeper/deleted/.del-ChangeLog~208984fb7a51e568:
  Delete: isam/ChangeLog
BitKeeper/deleted/.del-test_all.res~c2aafb49a3a77db7:
  Delete: isam/test_all.res
BitKeeper/deleted/.del-test_all~93c701e44a9c5b65:
  Delete: isam/test_all
BitKeeper/deleted/.del-.cvsignore~54f6f0f2d5012561:
  Delete: isam/.cvsignore
BitKeeper/deleted/.del-ha_isammrg.cc~dc682e4755d77a2e:
  Delete: sql/ha_isammrg.cc
BitKeeper/deleted/.del-ha_isam.h~bf53d533be3d3927:
  Delete: sql/ha_isam.h
BitKeeper/deleted/.del-ha_isammrg.h~66fd2e5bfe7207dc:
  Delete: sql/ha_isammrg.h
acinclude.m4:
  Remove ISAM
client/mysqldump.c:
  FIELD_TYPE -> MYSQL_TYPE
client/mysqltest.c:
  Add missing DBUG_RETURN
configure.in:
  Remove ISAM
heap/heapdef.h:
  Add support for VARCHAR
heap/hp_create.c:
  Add support for VARCHAR
heap/hp_delete.c:
  Add support for VARCHAR
heap/hp_hash.c:
  Add support for VARCHAR
  (VARCHAR keys was not supported before)
heap/hp_rkey.c:
  Add support for VARCHAR
heap/hp_update.c:
  Add support for VARCHAR
heap/hp_write.c:
  Add support for VARCHAR
  (Added flag SEARCH_UPDATE to mark that this is an update)
include/decimal.h:
  Remove not needed my_global.h
include/m_ctype.h:
  Add support for VARCHAR
include/my_base.h:
  Add support for VARCHAR
include/my_handler.h:
  Moved general purpose macro from MyISAM code
include/mysql_com.h:
  Add support for VARCHAR
libmysql/libmysql.c:
  Add support for VARCHAR
libmysqld/Makefile.am:
  Removed ISAM
myisam/ft_static.c:
  Add support for VARCHAR
myisam/ft_test1.c:
  Add support for VARCHAR
myisam/ft_update.c:
  Add support for VARCHAR
myisam/mi_check.c:
  Add support for VARCHAR
myisam/mi_create.c:
  Add support for VARCHAR
  - VARCHAR key segments are marked with HA_VAR_LENGTH_PART
myisam/mi_key.c:
  Add support for VARCHAR
  Fixed bug in old VARCHAR code when reading index-only
myisam/mi_range.c:
  Fixed comment style
myisam/mi_rnext_same.c:
  Handle case where equal keys can be of different length
myisam/mi_search.c:
  Add support for VARCHAR
myisam/mi_test1.c:
  Add support for VARCHAR
myisam/mi_unique.c:
  Add support for VARCHAR
  (Some new code to handle keys that are equal but have different lengths)
myisam/mi_write.c:
  Fixed comment
myisam/myisamchk.c:
  Better infotext if wrong type
mysql-test/r/bdb.result:
  Updated old result and new results for VARCHAR
mysql-test/r/create.result:
  Updated old result and new results for VARCHAR
mysql-test/r/ctype_tis620.result:
  Updated old result and new results for VARCHAR
  (Old code sorted tis620 wrong)
mysql-test/r/ctype_ucs.result:
  Updated old result and new results for VARCHAR
mysql-test/r/endspace.result:
  Updated old result and new results for VARCHAR
mysql-test/r/func_like.result:
  Updated old result and new results for VARCHAR
mysql-test/r/heap.result:
  Updated old result and new results for VARCHAR
mysql-test/r/innodb.result:
  Updated old result. This will change a bit when also InnoDB supports VARCHAR
mysql-test/r/merge.result:
  Updated old result and new results for VARCHAR
mysql-test/r/myisam.result:
  Updated old result and new results for VARCHAR
mysql-test/r/mysqldump.result:
  Updated old result and new results for VARCHAR
mysql-test/r/order_by.result:
  Updated old result and new results for VARCHAR
  (Key length is different for VARCHAR)
mysql-test/r/ps.result:
  Updated old result and new results for VARCHAR
mysql-test/r/ps_1general.result:
  Updated results for new .frm version
  Don't print seconds in show full process list as this may change
mysql-test/r/ps_2myisam.result:
  Updated old result and new results for VARCHAR
mysql-test/r/ps_3innodb.result:
  Updated old result and new results for VARCHAR
mysql-test/r/ps_4heap.result:
  Updated old result and new results for VARCHAR
mysql-test/r/ps_5merge.result:
  Updated old result and new results for VARCHAR
mysql-test/r/ps_6bdb.result:
  Updated old result and new results for VARCHAR
mysql-test/r/select.result.es:
  Updated results by hand
mysql-test/r/select.result:
  Updated old result and new results for VARCHAR
mysql-test/r/select_found.result:
  Updated old result and new results for VARCHAR
mysql-test/r/show_check.result:
  Updated old result and new results for VARCHAR
mysql-test/r/strict.result:
  Updated old result and new results for VARCHAR
mysql-test/r/subselect.result:
  Updated old result and new results for VARCHAR
mysql-test/r/system_mysql_db.result:
  Updated old result and new results for VARCHAR
mysql-test/r/type_blob.result:
  Updated old result and new results for VARCHAR
mysql-test/r/type_ranges.result:
  Updated old result and new results for VARCHAR
mysql-test/r/type_ranges.result.es:
  Updated some results by hand
mysql-test/t/bdb.test:
  Test VARCHAR
mysql-test/t/ctype_ucs.test:
  Some fixes related to VARCHAR
mysql-test/t/endspace.test:
  Fixes to make it easier to compare columns with end space
mysql-test/t/heap.test:
  Test VARCHAR
mysql-test/t/innodb.test:
  Prepare for testing VARCHAR
mysql-test/t/myisam.test:
  Test VARCHAR
mysql-test/t/ps_1general.test:
  Don't show seconds for show processlist
mysql-test/t/ps_4heap.test:
  Update for VARCHAR
mysql-test/t/strict.test:
  Fix test for VARCHAR
mysql-test/t/type_blob.test:
  Update test for VARCHAR
  Note that now you can't store 'a' and 'a ' in an unique varchar/text index if the column is not binary
mysys/my_handler.c:
  Add support for VARCHAR
ndb/src/common/util/NdbSqlUtil.cpp:
  Fix for usage of strnncollsp
scripts/mysql_fix_privilege_tables.sh:
  Simple fix so that my_print_defaults works
sql/Makefile.am:
  Remove ISAM
sql/field.cc:
  Add support for VARCHAR
  Fixed the keys for blob's are compared with strnncollsp
  Ensure that old tables from MySQL 4.0 works as they did before.
  (Old VARCHAR will be converted to new VARCHAR on ALTER TABLE)
sql/field.h:
  Add support for VARCHAR
sql/field_conv.cc:
  Change FIELD_TYPE_VAR_STRING -> MYSQL_TYPE_VARCHAR
  Added usage of HA_KEY_BLOB_LENGTH
sql/ha_berkeley.cc:
  Add support for VARCHAR
  Added usage of table->insert_or_update if we would ever want to know in key_cmp if we are changing keys
sql/ha_heap.cc:
  Add support for VARCHAR
sql/ha_innodb.cc:
  Changed MYSQL_TYPE_VAR_STRING to MYSQL_TYPE_VARCHAR.
  Waiting for Heikki to add full VARCHAR support
sql/ha_innodb.h:
  InnoDB doesn't support full VARCHAR yet
sql/ha_myisam.cc:
  Add support for VARCHAR
sql/ha_ndbcluster.cc:
  Add support for VARCHAR
sql/handler.h:
  Added HA_NO_VARCHAR for table handler that doesn't support VARCHAR. In this case MySQL will create a normal CHAR instead
sql/item.cc:
  Fixed access of already freed memory
  Added support of VARCHAR
  - varchar length is now checked in mysql_prepare
sql/item_cmpfunc.cc:
  Added new parameter to strncollsp
sql/item_sum.cc:
  Added new parameter to strncollsp
  FIELD_TYPE -> MYSQL_TYPE
sql/key.cc:
  Add support for VARCHAR
sql/opt_range.cc:
  Remove character set parameter from set_key_image()
sql/opt_sum.cc:
  Remove character set parameter from set_key_image()
sql/protocol.cc:
  Return MYSQL_TYPE_VAR_STRING instead of MYSQL_TYPE_VARCHAR to clients (to not cause compatiblity problems)
sql/sql_acl.cc:
  Change key handling code so that we can use CHAR or VARCHAR for the user table columns
sql/sql_base.cc:
  Remove old, not used code
sql/sql_help.cc:
  Remove charset from get_key_image
sql/sql_parse.cc:
  Ensure that OPTION_TABLE_LOCK is cleared ASAP; This fixed a problem in BDB transaction code when one used LOCK TABLES on a BDB table
  Added support for VARCHAR
  Moved field length checking and VARCHAR -> TEXT convert to mysql_prepare (as we need the know the character set for the column)
sql/sql_select.cc:
  Added support of VARCHAR
  Added heuristic to use fixed size rows for tmp tables if we are using only a few short VARCHAR's
sql/sql_string.cc:
  Added extra argument to strnncollsp
sql/sql_table.cc:
  Add support for VARCHAR
  Automaticly convert (with warning) big VARCHAR (but not CHAR) to TEXT
  If handler doesn't support VARCHAR convert VARCHAR to CHAR
sql/sql_update.cc:
  Fixed compiler warning
sql/sql_yacc.yy:
  Add support for VARCHAR
sql/strfunc.cc:
  Fixed valgrind warning
sql/structs.h:
  Added 'table' to KEY structure to make life easier for some handler functions
sql/table.cc:
  Add support for VARCHAR
  - New .frm version
  - FIELD_TYPE -> MYSQL_TYPE
sql/table.h:
  Added insert_or_update; A bool flag a handler can set/reset if needed (for handler internal usage)
sql/unireg.h:
  Add support for VARCHAR
strings/ctype-big5.c:
  Added new argument to strnncollsp() to allow one to define if end space are significant or not
  Changed my_like_range... to correctly calculate min_length & max_length
strings/ctype-bin.c:
  Added new argument to strnncollsp() to allow one to define if end space are significant or not
strings/ctype-czech.c:
  Changed my_like_range... to correctly calculate min_length & max_length
strings/ctype-gbk.c:
  Added new argument to strnncollsp() to allow one to define if end space are significant or not
  Changed my_like_range... to correctly calculate min_length & max_length
strings/ctype-latin1.c:
  Added new argument to strnncollsp() to allow one to define if end space are significant or not
strings/ctype-mb.c:
  Added new argument to strnncollsp() to allow one to define if end space are significant or not
  Changed my_like_range... to correctly calculate min_length & max_length
strings/ctype-simple.c:
  Added new argument to strnncollsp() to allow one to define if end space are significant or not
  Changed my_like_range... to correctly calculate min_length & max_length
strings/ctype-sjis.c:
  Added new argument to strnncollsp() to allow one to define if end space are significant or not
  Changed my_like_range... to correctly calculate min_length & max_length
strings/ctype-tis620.c:
  Added new argument to strnncollsp() to allow one to define if end space are significant or not
  Changed my_like_range... to correctly calculate min_length & max_length
strings/ctype-uca.c:
  Added new argument to strnncollsp() to allow one to define if end space are significant or not
strings/ctype-ucs2.c:
  Changed my_like_range... to correctly calculate min_length & max_length
strings/ctype-utf8.c:
  Added new argument to strnncollsp() to allow one to define if end space are significant or not
strings/ctype-win1250ch.c:
  Changed my_like_range... to correctly calculate min_length & max_length
strings/decimal.c:
  Fixed include files usage
  Fixed some compiler warnings
tests/client_test.c:
  Ensure tests works with VARCHAR
This commit is contained in:
unknown 2004-12-06 02:00:37 +02:00
parent cd16e4c9c7
commit a8ea31fae6
169 changed files with 3295 additions and 19154 deletions

View File

@ -1107,23 +1107,6 @@ AC_SUBST(orbit_libs)
AC_SUBST(orbit_idl)
])
AC_DEFUN([MYSQL_CHECK_ISAM], [
AC_ARG_WITH([isam], [
--with-isam Enable the ISAM table type],
[with_isam="$withval"],
[with_isam=no])
isam_libs=
if test X"$with_isam" = X"yes"
then
AC_DEFINE([HAVE_ISAM], [1], [Using old ISAM tables])
isam_libs="\$(top_builddir)/isam/libnisam.a\
\$(top_builddir)/merge/libmerge.a"
fi
AC_SUBST(isam_libs)
])
dnl ---------------------------------------------------------------------------
dnl Macro: MYSQL_CHECK_BDB
dnl Sets HAVE_BERKELEY_DB if inst library is found

View File

@ -1546,12 +1546,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];

View File

@ -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));
}

View File

@ -2826,7 +2826,6 @@ AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_CHARSET_NAME], ["$default_charset"],
AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_COLLATION_NAME], ["$default_collation"],
[Define the default charset name])
MYSQL_CHECK_ISAM
MYSQL_CHECK_BDB
MYSQL_CHECK_INNODB
MYSQL_CHECK_EXAMPLEDB
@ -2889,12 +2888,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

View File

@ -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);

View File

@ -69,9 +69,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 +
@ -82,7 +94,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;

View File

@ -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))

View File

@ -246,14 +246,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
{
@ -298,6 +311,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++)
@ -350,6 +376,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++)
@ -384,6 +415,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++)
@ -399,9 +435,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;
@ -426,9 +481,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
{
@ -436,7 +491,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
@ -488,7 +566,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
@ -525,6 +627,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)
@ -577,6 +686,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)
{
@ -627,6 +754,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)
{
@ -666,6 +810,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:

View File

@ -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);

View File

@ -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))

View File

@ -106,7 +106,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
@ -293,7 +293,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);
}

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -1,10 +0,0 @@
.deps
.libs
Makefile
Makefile.in
isamchk
isamlog
pack_isam
test1
test2
test3

View File

@ -1,186 +0,0 @@
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

View File

@ -1,45 +0,0 @@
# 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.%

View File

@ -1,92 +0,0 @@
/* 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 */

View File

@ -1,132 +0,0 @@
/* 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 */

File diff suppressed because it is too large Load Diff

View File

@ -1,238 +0,0 @@
/* 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 */
}

View File

@ -1,345 +0,0 @@
/* 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 */

File diff suppressed because it is too large Load Diff

View File

@ -1,143 +0,0 @@
/* 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 */

View File

@ -1,889 +0,0 @@
/* 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 */
/* S|ker efter positionen f|r en nyckel samt d{rmedh|rande funktioner */
#include "isamdef.h"
#include "m_ctype.h"
#define CMP(a,b) (a<b ? -1 : a == b ? 0 : 1)
/* Check index */
int _nisam_check_index(N_INFO *info, int inx)
{
if (inx == -1) /* Use last index */
inx=info->lastinx;
if (inx >= (int) info->s->state.keys || inx < 0)
{
my_errno=HA_ERR_WRONG_INDEX;
return -1;
}
if (info->lastinx != inx) /* Index changed */
{
info->lastinx = inx;
info->lastpos = NI_POS_ERROR;
info->update= ((info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED)) |
HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
}
if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache))
return(-1);
return(inx);
} /* ni_check_index */
/* S|ker reda p} positionen f|r ett record p} basen av en nyckel */
/* Positionen l{ggs i info->lastpos */
/* Returns -1 if not found and 1 if search at upper levels */
int _nisam_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, uint key_len, uint nextflag, register ulong pos)
{
int error,flag;
uint nod_flag;
uchar *keypos,*maxpos;
uchar lastkey[N_MAX_KEY_BUFF],*buff;
DBUG_ENTER("_nisam_search");
DBUG_PRINT("enter",("pos: %ld nextflag: %d lastpos: %ld",
pos,nextflag,info->lastpos));
if (pos == NI_POS_ERROR)
{
my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
info->lastpos= NI_POS_ERROR;
if (!(nextflag & (SEARCH_SMALLER | SEARCH_BIGGER | SEARCH_LAST)))
DBUG_RETURN(-1); /* Not found ; return error */
DBUG_RETURN(1); /* Search at upper levels */
}
if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,
test(!(nextflag & SEARCH_SAVE_BUFF)))))
goto err;
DBUG_DUMP("page",(byte*) buff,getint(buff));
flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
&keypos,lastkey);
nod_flag=test_if_nod(buff);
maxpos=buff+getint(buff)-1;
if (flag)
{
if ((error=_nisam_search(info,keyinfo,key,key_len,nextflag,
_nisam_kpos(nod_flag,keypos))) <= 0)
DBUG_RETURN(error);
if (flag >0)
{
if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) &&
keypos == buff+2+nod_flag)
DBUG_RETURN(1); /* Bigger than key */
}
else if (nextflag & SEARCH_BIGGER && keypos >= maxpos)
DBUG_RETURN(1); /* Smaller than key */
}
else
{
if (nextflag & SEARCH_FIND && (!(keyinfo->base.flag & HA_NOSAME)
|| key_len) && nod_flag)
{
if ((error=_nisam_search(info,keyinfo,key,key_len,SEARCH_FIND,
_nisam_kpos(nod_flag,keypos))) >= 0 ||
my_errno != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(error);
info->int_pos= NI_POS_ERROR; /* Buffer not in memory */
}
}
if (pos != info->int_pos)
{
uchar *old_buff=buff;
if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,
test(!(nextflag & SEARCH_SAVE_BUFF)))))
goto err;
keypos=buff+(keypos-old_buff);
maxpos=buff+(maxpos-old_buff);
}
if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0)
{
keypos=_nisam_get_last_key(info,keyinfo,buff,lastkey,keypos);
if (!(nextflag & SEARCH_SMALLER) &&
_nisam_key_cmp(keyinfo->seg, lastkey, key, key_len, SEARCH_FIND))
{
my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
goto err;
}
}
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey));
VOID(_nisam_move_key(keyinfo,info->lastkey,lastkey));
info->lastpos=_nisam_dpos(info,nod_flag,keypos);
info->int_keypos=info->buff+ (keypos-buff);
info->int_maxpos=info->buff+ (maxpos-buff);
info->page_changed=0;
info->buff_used= (info->buff != buff);
info->last_search_keypage=info->int_pos;
DBUG_PRINT("exit",("found key at %ld",info->lastpos));
DBUG_RETURN(0);
err:
DBUG_PRINT("exit",("Error: %d",my_errno));
info->lastpos= NI_POS_ERROR;
DBUG_RETURN (-1);
} /* _nisam_search */
/* Search after key in page-block */
/* If packed key puts smaller or identical key in buff */
/* ret_pos point to where find or bigger key starts */
/* ARGSUSED */
int _nisam_bin_search(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page,
uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
uchar *buff __attribute__((unused)))
{
reg4 int start,mid,end;
int flag;
uint totlength,nod_flag;
DBUG_ENTER("_nisam_bin_search");
LINT_INIT(flag);
totlength=keyinfo->base.keylength+(nod_flag=test_if_nod(page));
start=0; mid=1;
end= (int) ((getint(page)-2-nod_flag)/totlength-1);
DBUG_PRINT("test",("getint: %d end: %d",getint(page),end));
page+=2+nod_flag;
while (start != end)
{
mid= (start+end)/2;
if ((flag=_nisam_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len,
comp_flag))
>= 0)
end=mid;
else
start=mid+1;
}
if (mid != start)
flag=_nisam_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len,
comp_flag);
if (flag < 0)
start++; /* point at next, bigger key */
*ret_pos=page+(uint) start*totlength;
DBUG_PRINT("exit",("flag: %d keypos: %d",flag,start));
DBUG_RETURN(flag);
} /* _nisam_bin_search */
/* Used instead of _nisam_bin_search() when key is packed */
/* Puts smaller or identical key in buff */
/* Key is searched sequentially */
int _nisam_seq_search(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, uchar *buff)
{
int flag;
uint nod_flag,length;
uchar t_buff[N_MAX_KEY_BUFF],*end;
DBUG_ENTER("_nisam_seq_search");
LINT_INIT(flag); LINT_INIT(length);
end= page+getint(page);
nod_flag=test_if_nod(page);
page+=2+nod_flag;
*ret_pos=page;
while (page < end)
{
length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
if ((flag=_nisam_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag)) >= 0)
break;
#ifdef EXTRA_DEBUG
DBUG_PRINT("loop",("page: %lx key: '%s' flag: %d",page,t_buff,flag));
#endif
memcpy(buff,t_buff,length);
*ret_pos=page;
}
if (flag == 0)
memcpy(buff,t_buff,length); /* Result is first key */
DBUG_PRINT("exit",("flag: %d ret_pos: %lx",flag,*ret_pos));
DBUG_RETURN(flag);
} /* _nisam_seq_search */
/* Get pos to a key_block */
ulong _nisam_kpos(uint nod_flag, uchar *after_key)
{
after_key-=nod_flag;
switch (nod_flag) {
case 3:
return uint3korr(after_key)*512L;
case 2:
return uint2korr(after_key)*512L;
case 1:
return (uint) (*after_key)*512L;
case 0: /* At leaf page */
default: /* Impossible */
return(NI_POS_ERROR);
}
} /* _kpos */
/* Save pos to a key_block */
void _nisam_kpointer(register N_INFO *info, register uchar *buff, ulong pos)
{
pos/=512L;
switch (info->s->base.key_reflength) {
case 3: int3store(buff,pos); break;
case 2: int2store(buff,(uint) pos); break;
case 1: buff[0]= (uchar) pos; break;
default: abort(); /* impossible */
}
} /* _nisam_kpointer */
/* Calc pos to a data-record */
ulong _nisam_dpos(N_INFO *info, uint nod_flag, uchar *after_key)
{
ulong pos;
after_key-=(nod_flag + info->s->rec_reflength);
switch (info->s->rec_reflength) {
case 4:
pos= (ulong) uint4korr(after_key);
break;
case 3:
pos= (ulong) uint3korr(after_key);
break;
case 2:
pos= (ulong) uint2korr(after_key);
break;
default:
pos=0L; /* Shut compiler up */
}
return (info->s->base.options &
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
pos*info->s->base.reclength;
}
/* save pos to record */
void _nisam_dpointer(N_INFO *info, uchar *buff, ulong pos)
{
if (!(info->s->base.options &
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
pos/=info->s->base.reclength;
switch (info->s->rec_reflength) {
case 4: int4store(buff,pos); break;
case 3: int3store(buff,pos); break;
case 2: int2store(buff,(uint) pos); break;
default: abort(); /* Impossible */
}
} /* _nisam_dpointer */
/*
** Compare two keys with is bigger
** Returns <0, 0, >0 acording to with is bigger
** Key_length specifies length of key to use. Number-keys can't
** be splitted
** If flag <> SEARCH_FIND compare also position
*/
int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar *b, uint key_length, uint nextflag)
{
reg4 int flag,length_diff;
int16 s_1,s_2;
int32 l_1,l_2;
uint32 u_1,u_2;
float f_1,f_2;
double d_1,d_2;
reg5 uchar *end;
if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))
|| key_length == 0)
key_length=N_MAX_KEY_BUFF*2;
for ( ; (int) key_length >0 ; key_length-= (keyseg++)->base.length)
{
end= a+ min(keyseg->base.length,key_length);
switch ((enum ha_base_keytype) keyseg->base.type) {
case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
case HA_KEYTYPE_BINARY:
if (keyseg->base.flag & HA_SPACE_PACK)
{
uchar *as, *bs;
int length,b_length;
as=a++; bs=b++;
length= (length_diff= ((int) *as - (b_length= (int) *bs))) < 0 ?
(int) *as : b_length;
end= a+ min(key_length,(uint) length);
if (use_strnxfrm(default_charset_info)) {
if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
{
while (a < end)
if ((flag= (int) *a++ - (int) *b++))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
}
else
{
if ((flag = my_strnncoll(default_charset_info,
a, (int) (end-a), b, b_length)))
return (keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag;
b+= (uint) (end-a);
a=end;
}
}
else
{
while (a < end)
if ((flag= (int) *a++ - (int) *b++))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
}
if (key_length < (uint) keyseg->base.length)
{ /* key_part */
if (length_diff)
{
if (length_diff < 0 || (uint) *as <= key_length)
return ((keyseg->base.flag & HA_REVERSE_SORT) ?
-length_diff : length_diff);
for (length= (int) key_length-b_length; length-- > 0 ;)
{
if (*a++ != ' ')
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -1 : 1);
}
}
if (nextflag & SEARCH_NO_FIND) /* Find record after key */
return (nextflag & SEARCH_BIGGER) ? -1 : 1;
return 0;
}
else
{
if (length_diff)
return ((keyseg->base.flag & HA_REVERSE_SORT) ?
-length_diff : length_diff);
}
a=as+ (uint) *as+1 ; b= bs+ b_length+1; /* to next key */
}
else
{
if (use_strnxfrm(default_charset_info)) {
if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
{
while (a < end)
if ((flag= (int) *a++ - (int) *b++))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
}
else
{
if ((flag = my_strnncoll(default_charset_info,
a, (int) (end-a), b, (int) (end-a))))
return (keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag;
b+= (uint) (end-a);
a=end;
}
}
else
{
while (a < end)
if ((flag= (int) *a++ - (int) *b++))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
}
}
break;
case HA_KEYTYPE_INT8:
{
int i_1= (int) *((signed char*) a);
int i_2= (int) *((signed char*) b);
if ((flag = CMP(i_1,i_2)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b++;
break;
}
case HA_KEYTYPE_SHORT_INT:
shortget(s_1,a);
shortget(s_2,b);
if ((flag = CMP(s_1,s_2)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 2; /* sizeof(short int); */
break;
case HA_KEYTYPE_USHORT_INT:
{
uint16 us_1,us_2;
ushortget(us_1,a);
ushortget(us_2,b);
if ((flag = CMP(us_1,us_2)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+=2; /* sizeof(short int); */
break;
}
case HA_KEYTYPE_LONG_INT:
longget(l_1,a);
longget(l_2,b);
if ((flag = CMP(l_1,l_2)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 4; /* sizeof(long int); */
break;
case HA_KEYTYPE_ULONG_INT:
ulongget(u_1,a);
ulongget(u_2,b);
if ((flag = CMP(u_1,u_2)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 4; /* sizeof(long int); */
break;
case HA_KEYTYPE_INT24:
l_1=sint3korr(a);
l_2=sint3korr(b);
if ((flag = CMP(l_1,l_2)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 3;
break;
case HA_KEYTYPE_UINT24:
l_1=(long) uint3korr(a);
l_2=(long) uint3korr(b);
if ((flag = CMP(l_1,l_2)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 3;
break;
case HA_KEYTYPE_FLOAT:
bmove((byte*) &f_1,(byte*) a,(int) sizeof(float));
bmove((byte*) &f_2,(byte*) b,(int) sizeof(float));
if ((flag = CMP(f_1,f_2)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= sizeof(float);
break;
case HA_KEYTYPE_DOUBLE:
doubleget(d_1,a);
doubleget(d_2,b);
if ((flag = CMP(d_1,d_2)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= sizeof(double);
break;
case HA_KEYTYPE_NUM: /* Numeric key */
{
int swap_flag=keyseg->base.flag & HA_REVERSE_SORT;
if (keyseg->base.flag & HA_SPACE_PACK)
{
int alength,blength;
if (swap_flag)
swap_variables(uchar*, a, b);
alength= *a++; blength= *b++;
if ((flag=(int) (keyseg->base.length-key_length)) < 0)
flag=0;
if (alength != blength+flag)
{
if ((alength > blength+flag && *a != '-') ||
(alength < blength+flag && *b == '-'))
return 1;
else
return -1;
}
if (*a == '-' && *b == '-')
{
swap_flag=1;
swap_variables(uchar*, a, b);
}
end=a+alength;
while (a < end)
if (*a++ != *b++)
{
a--; b--;
if (my_isdigit(default_charset_info, (char) *a) &&
my_isdigit(default_charset_info, (char) *b))
return ((int) *a - (int) *b);
if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
return (-1);
if (*b == '-' || *b++ == ' ' ||
my_isdigit(default_charset_info,(char) *a))
return (1);
if (*a++ == ' ')
return (-1);
}
}
else
{
for ( ; a < end && *a == ' ' && *b == ' ' ; a++, b++) ;
if (*a == '-' && *b == '-')
swap_flag=1;
if (swap_flag)
{
end=b+(int) (end-a);
swap_variables(uchar*, a, b);
}
while (a < end)
if (*a++ != *b++)
{
a--; b--;
if (my_isdigit(default_charset_info,(char) *a) &&
my_isdigit(default_charset_info,(char) *b))
return ((int) *a - (int) *b);
if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
return (-1);
if (*b == '-' || *b++ == ' ' ||
my_isdigit(default_charset_info,(char) *a))
return (1);
if (*a++ == ' ')
return -1;
}
}
if (swap_flag)
swap_variables(uchar*, a, b);
break;
}
#ifdef HAVE_LONG_LONG
case HA_KEYTYPE_LONGLONG:
{
longlong ll_a,ll_b;
longlongget(ll_a,a);
longlongget(ll_b,b);
if ((flag = CMP(ll_a,ll_b)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= sizeof(longlong);
break;
}
case HA_KEYTYPE_ULONGLONG:
{
ulonglong ll_a,ll_b;
longlongget(ll_a,a);
longlongget(ll_b,b);
if ((flag = CMP(ll_a,ll_b)))
return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= sizeof(ulonglong);
break;
}
#endif
case HA_KEYTYPE_END: /* Ready */
case HA_KEYTYPE_VARTEXT: /* Impossible */
case HA_KEYTYPE_VARBINARY: /* Impossible */
goto end;
}
}
end:
if (!(nextflag & SEARCH_FIND))
{
if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
LINT_INIT(l_1); LINT_INIT(l_2);
switch (keyseg->base.length) {
case 4:
u_1= (ulong) uint4korr(a);
u_2= (ulong) uint4korr(b);
break;
case 3:
u_1= (ulong) uint3korr(a);
u_2= (ulong) uint3korr(b);
break;
case 2:
u_1= (ulong) uint2korr(a);
u_2= (ulong) uint2korr(b);
break;
default: abort(); /* Impossible */
}
flag = CMP(u_1,u_2);
if (nextflag & SEARCH_SAME)
return (flag); /* read same */
if (nextflag & SEARCH_BIGGER)
return (flag <= 0 ? -1 : 1); /* read next */
return (flag < 0 ? -1 : 1); /* read previous */
}
return 0;
} /* _nisam_key_cmp */
/* Get key from key-block */
/* page points at previous key; its advanced to point at next key */
/* key should contain previous key */
/* Returns length of found key + pointers */
/* nod_flag is a flag if we are on nod */
uint _nisam_get_key(register N_KEYDEF *keyinfo, uint nod_flag,
register uchar **page, register uchar *key)
{
reg1 N_KEYSEG *keyseg;
uchar *start,*start_key;
uint length,c_length;
LINT_INIT(start);
start_key=key; c_length=0;
for (keyseg=keyinfo->seg ; keyseg->base.type ;keyseg++)
{
if (keyseg->base.flag & (HA_SPACE_PACK | HA_PACK_KEY))
{
start=key;
if (keyseg->base.flag & HA_SPACE_PACK)
key++;
if ((length= *(*page)++) & 128)
{
key+= (c_length=(length & 127));
if (c_length == 0) /* Same key */
{
key+= *start; /* Same diff_key as prev */
length=0;
}
else
{
if (keyseg->base.flag & HA_SPACE_PACK)
length= *(*page)++;
else
length=keyseg->base.length-length+128; /* Rest of key */
/* Prevent core dumps if wrong data formats */
if (length > keyseg->base.length)
length=0;
}
}
}
else
length=keyseg->base.length;
memcpy((byte*) key,(byte*) *page,(size_t) length); key+=length;
if (keyseg->base.flag & HA_SPACE_PACK)
*start= (uchar) ((key-start)-1);
*page+=length;
}
length=keyseg->base.length+nod_flag;
bmove((byte*) key,(byte*) *page,length);
*page+=length;
return((uint) (key-start_key)+keyseg->base.length);
} /* _nisam_get_key */
/* same as _nisam_get_key but used with fixed length keys */
uint _nisam_get_static_key(register N_KEYDEF *keyinfo, uint nod_flag, register uchar **page, register uchar *key)
{
memcpy((byte*) key,(byte*) *page,
(size_t) (keyinfo->base.keylength+nod_flag));
*page+=keyinfo->base.keylength+nod_flag;
return(keyinfo->base.keylength);
} /* _nisam_get_static_key */
/* Get last key from key-block, starting from keypos */
/* Return pointer to where keystarts */
uchar *_nisam_get_last_key(N_INFO *info, N_KEYDEF *keyinfo, uchar *keypos, uchar *lastkey, uchar *endpos)
{
uint nod_flag;
uchar *lastpos;
nod_flag=test_if_nod(keypos);
if (! (keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
{
lastpos=endpos-keyinfo->base.keylength-nod_flag;
if (lastpos > keypos)
bmove((byte*) lastkey,(byte*) lastpos,keyinfo->base.keylength+nod_flag);
}
else
{
lastpos=0 ; keypos+=2+nod_flag;
lastkey[0]=0;
while (keypos < endpos)
{
lastpos=keypos;
VOID(_nisam_get_key(keyinfo,nod_flag,&keypos,lastkey));
}
}
return lastpos;
} /* _nisam_get_last_key */
/* Calculate length of key */
uint _nisam_keylength(N_KEYDEF *keyinfo, register uchar *key)
{
reg1 N_KEYSEG *keyseg;
uchar *start;
if (! (keyinfo->base.flag & HA_SPACE_PACK_USED))
return (keyinfo->base.keylength);
start=key;
for (keyseg=keyinfo->seg ; keyseg->base.type ; keyseg++)
{
if (keyseg->base.flag & HA_SPACE_PACK)
key+= *key+1;
else
key+= keyseg->base.length;
}
return((uint) (key-start)+keyseg->base.length);
} /* _nisam_keylength */
/* Move a key */
uchar *_nisam_move_key(N_KEYDEF *keyinfo, uchar *to, uchar *from)
{
reg1 uint length;
memcpy((byte*) to, (byte*) from,
(size_t) (length=_nisam_keylength(keyinfo,from)));
return to+length;
}
/* Find next/previous record with same key */
/* This can't be used when database is touched after last read */
int _nisam_search_next(register N_INFO *info, register N_KEYDEF *keyinfo,
uchar *key, uint nextflag, ulong pos)
{
int error;
uint nod_flag;
uchar lastkey[N_MAX_KEY_BUFF];
DBUG_ENTER("_nisam_search_next");
DBUG_PRINT("enter",("nextflag: %d lastpos: %d int_keypos: %lx",
nextflag,info->lastpos,info->int_keypos));
DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,key););
if ((nextflag & SEARCH_BIGGER && info->int_keypos >= info->int_maxpos) ||
info->int_pos == NI_POS_ERROR || info->page_changed)
DBUG_RETURN(_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
pos));
if (info->buff_used)
{
if (!_nisam_fetch_keypage(info,keyinfo,info->last_search_keypage,
info->buff,0))
{
info->lastpos= NI_POS_ERROR;
DBUG_RETURN(-1);
}
info->buff_used=0;
}
/* Last used buffer is in info->buff */
nod_flag=test_if_nod(info->buff);
VOID(_nisam_move_key(keyinfo,lastkey,key));
if (nextflag & SEARCH_BIGGER) /* Next key */
{
ulong tmp_pos=_nisam_kpos(nod_flag,info->int_keypos);
if (tmp_pos != NI_POS_ERROR)
{
if ((error=_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
tmp_pos)) <=0)
DBUG_RETURN(error);
}
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&info->int_keypos,lastkey));
}
else /* Previous key */
{
info->int_keypos=_nisam_get_last_key(info,keyinfo,info->buff,lastkey,
info->int_keypos);
if (info->int_keypos == info->buff+2)
DBUG_RETURN(_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
pos));
if ((error=_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
_nisam_kpos(nod_flag,info->int_keypos))) <= 0)
DBUG_RETURN(error);
}
info->int_keypos=_nisam_get_last_key(info,keyinfo,info->buff,lastkey,
info->int_keypos);
VOID(_nisam_move_key(keyinfo,info->lastkey,lastkey));
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&info->int_keypos,info->lastkey));
info->lastpos=_nisam_dpos(info,nod_flag,info->int_keypos);
DBUG_PRINT("exit",("found key at %d",info->lastpos));
DBUG_RETURN(0);
} /* _nisam_search_next */
/* S|ker reda p} positionen f|r f|rsta recordet i ett index */
/* Positionen l{ggs i info->lastpos */
int _nisam_search_first(register N_INFO *info, register N_KEYDEF *keyinfo, register ulong pos)
{
uint nod_flag;
uchar *page;
DBUG_ENTER("_nisam_search_first");
if (pos == NI_POS_ERROR)
{
my_errno=HA_ERR_KEY_NOT_FOUND;
info->lastpos= NI_POS_ERROR;
DBUG_RETURN(-1);
}
do
{
if (!_nisam_fetch_keypage(info,keyinfo,pos,info->buff,0))
{
info->lastpos= NI_POS_ERROR;
DBUG_RETURN(-1);
}
nod_flag=test_if_nod(info->buff);
page=info->buff+2+nod_flag;
} while ((pos=_nisam_kpos(nod_flag,page)) != NI_POS_ERROR);
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,info->lastkey));
info->int_keypos=page; info->int_maxpos=info->buff+getint(info->buff)-1;
info->lastpos=_nisam_dpos(info,nod_flag,page);
info->page_changed=info->buff_used=0;
info->last_search_keypage=info->int_pos;
DBUG_PRINT("exit",("found key at %d",info->lastpos));
DBUG_RETURN(0);
} /* _nisam_search_first */
/* S|ker reda p} positionen f|r sista recordet i ett index */
/* Positionen l{ggs i info->lastpos */
int _nisam_search_last(register N_INFO *info, register N_KEYDEF *keyinfo, register ulong pos)
{
uint nod_flag;
uchar *buff,*page;
DBUG_ENTER("_nisam_search_last");
if (pos == NI_POS_ERROR)
{
my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
info->lastpos= NI_POS_ERROR;
DBUG_RETURN(-1);
}
buff=info->buff;
do
{
if (!_nisam_fetch_keypage(info,keyinfo,pos,buff,0))
{
info->lastpos= NI_POS_ERROR;
DBUG_RETURN(-1);
}
page= buff+getint(buff);
nod_flag=test_if_nod(buff);
} while ((pos=_nisam_kpos(nod_flag,page)) != NI_POS_ERROR);
VOID(_nisam_get_last_key(info,keyinfo,buff,info->lastkey,page));
info->lastpos=_nisam_dpos(info,nod_flag,page);
info->int_keypos=info->int_maxpos=page;
info->page_changed=info->buff_used=0;
info->last_search_keypage=info->int_pos;
DBUG_PRINT("exit",("found key at %d",info->lastpos));
DBUG_RETURN(0);
} /* _nisam_search_last */

View File

@ -1,265 +0,0 @@
/* 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 fixed-length-records */
#include "isamdef.h"
int _nisam_write_static_record(N_INFO *info, const byte *record)
{
uchar temp[4]; /* Not sizeof(long) */
if (info->s->state.dellink != NI_POS_ERROR)
{
ulong filepos=info->s->state.dellink;
info->rec_cache.seek_not_done=1; /* We have done a seek */
VOID(my_seek(info->dfile,info->s->state.dellink+1,MY_SEEK_SET,MYF(0)));
if (my_read(info->dfile,(char*) &temp[0],sizeof(temp), MYF(MY_NABP)))
goto err;
info->s->state.dellink=uint4korr(temp);
if (info->s->state.dellink == (uint32) ~0) /* Fix for 64 bit long */
info->s->state.dellink=NI_POS_ERROR;
info->s->state.del--;
info->s->state.empty-=info->s->base.reclength;
VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0)));
if (my_write(info->dfile, (char*) record, info->s->base.reclength,
MYF(MY_NABP)))
goto err;
}
else
{
if (info->s->state.data_file_length > info->s->base.max_data_file_length)
{
my_errno=HA_ERR_RECORD_FILE_FULL;
return(2);
}
if (info->opt_flag & WRITE_CACHE_USED)
{ /* Cash in use */
if (my_b_write(&info->rec_cache, (byte*) record, info->s->base.reclength))
goto err;
}
else
{
info->rec_cache.seek_not_done=1; /* We have done a seek */
VOID(my_seek(info->dfile,info->s->state.data_file_length,
MY_SEEK_SET,MYF(0)));
if (my_write(info->dfile,(char*) record,info->s->base.reclength,
MYF(MY_NABP | MY_WAIT_IF_FULL)))
goto err;
}
info->s->state.data_file_length+=info->s->base.reclength;
info->s->state.splitt++;
}
return 0;
err:
return 1;
}
int _nisam_update_static_record(N_INFO *info, ulong pos, const byte *record)
{
info->rec_cache.seek_not_done=1; /* We have done a seek */
VOID(my_seek(info->dfile,pos,MY_SEEK_SET,MYF(0)));
return (my_write(info->dfile,(char*) record,info->s->base.reclength,
MYF(MY_NABP)) != 0);
}
int _nisam_delete_static_record(N_INFO *info)
{
uchar temp[5]; /* 1+sizeof(uint32) */
info->s->state.del++;
info->s->state.empty+=info->s->base.reclength;
temp[0]= '\0'; /* Mark that record is deleted */
int4store(temp+1,info->s->state.dellink);
info->s->state.dellink = info->lastpos;
info->rec_cache.seek_not_done=1;
VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0)));
return (my_write(info->dfile,(byte*) temp,(uint) sizeof(temp),
MYF(MY_NABP)) != 0);
}
int _nisam_cmp_static_record(register N_INFO *info, register const byte *old)
{
DBUG_ENTER("_nisam_rectest");
/* We are going to do changes; dont let anybody disturb */
dont_break(); /* Dont allow SIGHUP or SIGINT */
if (info->opt_flag & WRITE_CACHE_USED)
{
if (flush_io_cache(&info->rec_cache))
{
DBUG_RETURN(-1);
}
info->rec_cache.seek_not_done=1; /* We have done a seek */
}
if ((info->opt_flag & READ_CHECK_USED))
{ /* If check isn't disabled */
info->rec_cache.seek_not_done=1; /* We have done a seek */
VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0)));
if (my_read(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
MYF(MY_NABP)))
DBUG_RETURN(-1);
if (memcmp((byte*) info->rec_buff, (byte*) old,
(uint) info->s->base.reclength))
{
DBUG_DUMP("read",old,info->s->base.reclength);
DBUG_DUMP("disk",info->rec_buff,info->s->base.reclength);
my_errno=HA_ERR_RECORD_CHANGED; /* Record have changed */
DBUG_RETURN(1);
}
}
DBUG_RETURN(0);
}
/* Read a fixed-length-record */
/* Returns 0 if Ok. */
/* 1 if record is deleted */
/* MY_FILE_ERROR on read-error or locking-error */
int _nisam_read_static_record(register N_INFO *info, register ulong pos,
register byte *record)
{
int error;
if (pos != NI_POS_ERROR)
{
if (info->opt_flag & WRITE_CACHE_USED &&
info->rec_cache.pos_in_file <= pos &&
flush_io_cache(&info->rec_cache))
return(-1);
info->rec_cache.seek_not_done=1; /* We have done a seek */
error=my_pread(info->dfile,(char*) record,info->s->base.reclength,
pos,MYF(MY_NABP)) != 0;
if (info->s->r_locks == 0 && info->s->w_locks == 0)
VOID(_nisam_writeinfo(info,0));
if (! error)
{
if (!*record) return(1); /* Record is deleted */
info->update|= HA_STATE_AKTIV; /* Record is read */
my_errno=HA_ERR_RECORD_DELETED;
return(0);
}
return(-1); /* Error on read */
}
VOID(_nisam_writeinfo(info,0)); /* No such record */
return(-1);
} /* _nisam_read_record */
int _nisam_read_rnd_static_record(N_INFO *info, byte *buf,
register ulong filepos,
int skipp_deleted_blocks)
{
int locked,error,cache_read;
uint cache_length;
ISAM_SHARE *share=info->s;
DBUG_ENTER("_nisam_read_rnd_static_record");
cache_read=0;
LINT_INIT(cache_length);
if (info->opt_flag & WRITE_CACHE_USED &&
(info->rec_cache.pos_in_file <= filepos || skipp_deleted_blocks) &&
flush_io_cache(&info->rec_cache))
DBUG_RETURN(-1);
if (info->opt_flag & READ_CACHE_USED)
{ /* Cash in use */
if (filepos == my_b_tell(&info->rec_cache) &&
(skipp_deleted_blocks || !filepos))
{
cache_read=1; /* Read record using cache */
cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
}
else
info->rec_cache.seek_not_done=1; /* Filepos is changed */
}
#ifndef NO_LOCKING
locked=0;
if (info->lock_type == F_UNLCK)
{
if (filepos >= share->state.data_file_length)
{ /* Test if new records */
if (_nisam_readinfo(info,F_RDLCK,0))
DBUG_RETURN(-1);
locked=1;
}
else
{ /* We don't nead new info */
#ifndef UNSAFE_LOCKING
if ((! cache_read || share->base.reclength > cache_length) &&
share->r_locks == 0 && share->w_locks == 0)
{ /* record not in cache */
if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
DBUG_RETURN(-1);
locked=1;
}
#else
info->tmp_lock_type=F_RDLCK;
#endif
}
}
#endif
if (filepos >= share->state.data_file_length)
{
#ifndef NO_LOCKING
DBUG_PRINT("test",("filepos: %ld (%ld) records: %ld del: %ld",
filepos/share->base.reclength,filepos,
share->state.records, share->state.del));
VOID(_nisam_writeinfo(info,0));
#endif
my_errno=HA_ERR_END_OF_FILE;
DBUG_RETURN(-1);
}
info->lastpos= filepos;
info->nextpos= filepos+share->base.reclength;
if (! cache_read) /* No cacheing */
{
error=_nisam_read_static_record(info,filepos,buf);
if (error > 0)
my_errno=HA_ERR_RECORD_DELETED;
DBUG_RETURN(error);
}
/* Read record with cacheing */
error=my_b_read(&info->rec_cache,(byte*) buf,share->base.reclength);
#ifndef NO_LOCKING
if (locked)
VOID(_nisam_writeinfo(info,0)); /* Unlock keyfile */
#endif
if (!error)
{
if (!buf[0])
{ /* Record is removed */
my_errno=HA_ERR_RECORD_DELETED;
DBUG_RETURN(1);
}
/* Found and may be updated */
info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
DBUG_RETURN(0);
}
if (info->rec_cache.error != -1 || my_errno == 0)
my_errno=HA_ERR_WRONG_IN_RECORD;
DBUG_RETURN(-1); /* Something wrong (EOF?) */
}

View File

@ -1,35 +0,0 @@
/* 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 */
/* Check if somebody has changed table since last check. */
#include "isamdef.h"
/* Return 0 if table isn't changed */
int nisam_is_changed(N_INFO *info)
{
int result;
DBUG_ENTER("nisam_is_changed");
#ifndef NO_LOCKING
if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1);
VOID(_nisam_writeinfo(info,0));
#endif
result=(int) info->data_changed;
info->data_changed=0;
DBUG_PRINT("exit",("result: %d",result));
DBUG_RETURN(result);
}

View File

@ -1,92 +0,0 @@
/* 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 */
/* close a isam-database */
#include "isamdef.h"
int nisam_close(register N_INFO *info)
{
int error=0,flag;
ISAM_SHARE *share=info->s;
DBUG_ENTER("nisam_close");
DBUG_PRINT("enter",("base: %lx reopen: %u locks: %u",
info,(uint) share->reopen,
(uint) (share->w_locks+share->r_locks)));
pthread_mutex_lock(&THR_LOCK_isam);
if (info->lock_type == F_EXTRA_LCK)
info->lock_type=F_UNLCK; /* HA_EXTRA_NO_USER_CHANGE */
#ifndef NO_LOCKING
if (info->lock_type != F_UNLCK)
VOID(nisam_lock_database(info,F_UNLCK));
#else
info->lock_type=F_UNLCK;
share->w_locks--;
if (_nisam_writeinfo(info,test(share->changed)))
error=my_errno;
#endif
pthread_mutex_lock(&share->intern_lock);
if (share->base.options & HA_OPTION_READ_ONLY_DATA)
share->r_locks--;
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{
if (end_io_cache(&info->rec_cache))
error=my_errno;
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
}
flag= !--share->reopen;
nisam_open_list=list_delete(nisam_open_list,&info->open_list);
pthread_mutex_unlock(&share->intern_lock);
if (flag)
{
if (share->kfile >= 0 &&
flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_RELEASE))
error=my_errno;
if (share->kfile >= 0 && my_close(share->kfile,MYF(0)))
error = my_errno;
#ifdef HAVE_MMAP
_nisam_unmap_file(info);
#endif
if (share->decode_trees)
{
my_free((gptr) share->decode_trees,MYF(0));
my_free((gptr) share->decode_tables,MYF(0));
}
#ifdef THREAD
thr_lock_delete(&share->lock);
VOID(pthread_mutex_destroy(&share->intern_lock));
#endif
my_free((gptr) info->s,MYF(0));
}
pthread_mutex_unlock(&THR_LOCK_isam);
if (info->dfile >= 0 && my_close(info->dfile,MYF(0)))
error = my_errno;
nisam_log_command(LOG_CLOSE,info,NULL,0,error);
my_free((gptr) info->rec_alloc,MYF(0));
my_free((gptr) info,MYF(0));
if (error)
{
my_errno=error;
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
} /* nisam_close */

View File

@ -1,328 +0,0 @@
/* 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 */
/* Skapar en isam-databas */
#include "isamdef.h"
#if defined(MSDOS) || defined(__WIN__)
#ifdef __WIN__
#include <fcntl.h>
#else
#include <process.h> /* Prototype for getpid */
#endif
#endif
/*
** Old options is used when recreating database, from isamchk
** Note that the minimun reclength that MySQL allows for static rows
** are 5. (Will be fixed in the next generation)
*/
int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo,
N_RECINFO *recinfo,
ulong records,ulong reloc, uint flags,uint old_options,
ulong data_file_length)
{
register uint i,j;
File dfile,file;
int errpos,save_errno;
uint fields,length,max_key_length,packed,pointer,reclength,min_pack_length,
key_length,info_length,key_segs,options,min_key_length_skipp,max_block,
base_pos;
char buff[max(FN_REFLEN,512)];
ulong tot_length,pack_reclength;
enum en_fieldtype type;
ISAM_SHARE share;
N_KEYDEF *keydef;
N_KEYSEG *keyseg;
N_RECINFO *rec;
DBUG_ENTER("nisam_create");
LINT_INIT(dfile);
pthread_mutex_lock(&THR_LOCK_isam);
errpos=0;
options=0;
base_pos=512; /* Enough for N_STATE_INFO */
bzero((byte*) &share,sizeof(share));
if ((file = my_create(fn_format(buff,name,"",N_NAME_IEXT,4),0,
O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
goto err;
errpos=1;
VOID(fn_format(buff,name,"",N_NAME_DEXT,2+4));
if (!(flags & HA_DONT_TOUCH_DATA))
{
if ((dfile = my_create(buff,0,O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
goto err;
errpos=2;
}
else if (!(old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
options=old_options & (HA_OPTION_COMPRESS_RECORD |
HA_OPTION_READ_ONLY_DATA | HA_OPTION_PACK_RECORD);
if (reloc > records)
reloc=records; /* Check if wrong parameter */
/* Start by checking fields and field-types used */
reclength=0;
for (rec=recinfo, fields=packed=min_pack_length=0, pack_reclength=0L;
rec->base.type != (int) FIELD_LAST;
rec++,fields++)
{
reclength+=rec->base.length;
if ((type=(enum en_fieldtype) rec->base.type))
{
packed++;
if (type == FIELD_BLOB)
{
share.base.blobs++;
rec->base.length-= sizeof(char*); /* Don't calc pointer */
if (pack_reclength != NI_POS_ERROR)
{
if (rec->base.length == 4)
pack_reclength= (ulong) NI_POS_ERROR;
else
pack_reclength+=sizeof(char*)+(1 << (rec->base.length*8));
}
}
else if (type == FIELD_SKIP_PRESPACE ||
type == FIELD_SKIP_ENDSPACE)
{
if (pack_reclength != NI_POS_ERROR)
pack_reclength+= rec->base.length > 255 ? 2 : 1;
min_pack_length++;
}
else if (type == FIELD_ZERO)
packed--;
else if (type != FIELD_SKIP_ZERO)
{
min_pack_length+=rec->base.length;
packed--; /* Not a pack record type */
}
}
else
min_pack_length+=rec->base.length;
}
if ((packed & 7) == 1)
{ /* Bad packing, try to remove a zero-field */
while (rec != recinfo)
{
rec--;
if (rec->base.type == (int) FIELD_SKIP_ZERO && rec->base.length == 1)
{
rec->base.type=(int) FIELD_NORMAL;
packed--;
min_pack_length++;
break;
}
}
}
if (packed && !(options & HA_OPTION_COMPRESS_RECORD))
options|=HA_OPTION_PACK_RECORD; /* Must use packed records */
packed=(packed+7)/8;
if (pack_reclength != NI_POS_ERROR)
pack_reclength+= reclength+packed;
min_pack_length+=packed;
if (options & HA_OPTION_COMPRESS_RECORD)
{
if (data_file_length >= (1L << 24))
pointer=4;
else if (data_file_length >= (1L << 16))
pointer=3;
else
pointer=2;
}
else if (((records == 0L && pack_reclength < 255) ||
options & HA_OPTION_PACK_RECORD) ||
records >= (ulong) 16000000L ||
pack_reclength == (ulong) NI_POS_ERROR ||
((options & HA_OPTION_PACK_RECORD) &&
pack_reclength+4 >= (ulong) 14000000L/records))
pointer=4;
else if (records == 0L || records >= (ulong) 65000L ||
((options & HA_OPTION_PACK_RECORD) &&
pack_reclength+4 >= (ulong) 60000L/records))
pointer=3;
else
pointer=2;
max_block=max_key_length=0; tot_length=key_segs=0;
for (i=0, keydef=keyinfo ; i < keys ; i++ , keydef++)
{
share.state.key_root[i]= share.state.key_del[i]= NI_POS_ERROR;
share.base.rec_per_key[i]= (keydef->base.flag & HA_NOSAME) ? 1L : 0L;
min_key_length_skipp=length=0;
key_length=pointer;
if (keydef->base.flag & HA_PACK_KEY &&
keydef->seg[0].base.length > 127)
keydef->base.flag&= ~HA_PACK_KEY; /* Can't pack long keys */
if (keydef->base.flag & HA_PACK_KEY)
{
if ((keydef->seg[0].base.flag & HA_SPACE_PACK) &&
keydef->seg[0].base.type == (int) HA_KEYTYPE_NUM)
keydef->seg[0].base.flag&= ~HA_SPACE_PACK;
if (!(keydef->seg[0].base.flag & HA_SPACE_PACK))
length++;
keydef->seg[0].base.flag|=HA_PACK_KEY; /* for easyer intern test */
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
if (!(keydef->seg[0].base.flag & HA_SPACE_PACK))
min_key_length_skipp+=keydef->seg[0].base.length;
}
keydef->base.keysegs=0;
for (keyseg=keydef->seg ; keyseg->base.type ; keyseg++)
{
keydef->base.keysegs++;
if (keyseg->base.length > 127)
keyseg->base.flag&= ~(HA_SPACE_PACK | HA_PACK_KEY);
if (keyseg->base.flag & HA_SPACE_PACK)
{
keydef->base.flag |= HA_SPACE_PACK_USED;
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
length++;
min_key_length_skipp+=keyseg->base.length;
}
key_length+= keyseg->base.length;
}
bzero((gptr) keyseg,sizeof(keyseg[0]));
keyseg->base.length=(uint16) pointer; /* Last key part is pointer */
key_segs+=keydef->base.keysegs;
length+=key_length;
keydef->base.block_length=nisam_block_size;
keydef->base.keylength= (uint16) key_length;
keydef->base.minlength= (uint16) (length-min_key_length_skipp);
keydef->base.maxlength= (uint16) length;
if ((uint) keydef->base.block_length > max_block)
max_block=(uint) keydef->base.block_length;
if (length > max_key_length)
max_key_length= length;
tot_length+= (records/(ulong) (((uint) keydef->base.block_length-5)/
(length*2)))*
(ulong) keydef->base.block_length;
}
info_length=(uint) (base_pos+sizeof(N_BASE_INFO)+keys*sizeof(N_SAVE_KEYDEF)+
(keys+key_segs)*sizeof(N_SAVE_KEYSEG)+
fields*sizeof(N_SAVE_RECINFO));
bmove(share.state.header.file_version,(byte*) nisam_file_magic,4);
old_options=options| (old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
HA_OPTION_COMPRESS_RECORD |
HA_OPTION_TEMP_COMPRESS_RECORD: 0);
int2store(share.state.header.options,old_options);
int2store(share.state.header.header_length,info_length);
int2store(share.state.header.state_info_length,sizeof(N_STATE_INFO));
int2store(share.state.header.base_info_length,sizeof(N_BASE_INFO));
int2store(share.state.header.base_pos,base_pos);
share.state.dellink = NI_POS_ERROR;
share.state.process= (ulong) getpid();
share.state.uniq= (ulong) file;
share.state.loop= 0;
share.state.version= (ulong) time((time_t*) 0);
share.base.options=options;
share.base.rec_reflength=pointer;
share.base.key_reflength=((!tot_length || tot_length > 30000000L) ? 3 :
tot_length > 120000L ? 2 : 1);
share.base.keys= share.state.keys = keys;
share.base.keystart = share.state.key_file_length=MY_ALIGN(info_length,
nisam_block_size);
share.base.max_block=max_block;
share.base.max_key_length=(uint) ALIGN_SIZE(max_key_length+4);
share.base.records=records;
share.base.reloc=reloc;
share.base.reclength=reclength;
share.base.pack_reclength=
(uint) (reclength+packed-share.base.blobs*sizeof(char*));
share.base.max_pack_length=pack_reclength;
share.base.min_pack_length=min_pack_length;
share.base.pack_bits=packed;
share.base.fields=fields;
share.base.pack_fields=packed;
share.base.sortkey= (ushort) ~0;
share.base.max_data_file_length= (pointer == 4) ? (ulong) ~0L :
(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
(ulong) (1L << (pointer*8)) :
(pointer == 3 && reclength >= 256L) ? (ulong) NI_POS_ERROR :
((ulong) reclength * (1L << (pointer*8)));
share.base.max_key_file_length= (share.base.key_reflength == 3 ?
NI_POS_ERROR :
(ulong)
(1L << (share.base.key_reflength*8))*512);
share.base.min_block_length=
(share.base.pack_reclength+3 < N_EXTEND_BLOCK_LENGTH &&
! share.base.blobs) ?
max(share.base.pack_reclength,N_MIN_BLOCK_LENGTH) :
N_EXTEND_BLOCK_LENGTH;
if (! (flags & HA_DONT_TOUCH_DATA))
share.base.create_time= (long) time((time_t*) 0);
bzero(buff,base_pos);
if (my_write(file,(char*) &share.state,sizeof(N_STATE_INFO),MYF(MY_NABP)) ||
my_write(file,buff,base_pos-sizeof(N_STATE_INFO),MYF(MY_NABP)) ||
my_write(file,(char*) &share.base,sizeof(N_BASE_INFO),MYF(MY_NABP)))
goto err;
for (i=0 ; i < share.base.keys ; i++)
{
if (my_write(file,(char*) &keyinfo[i].base,sizeof(N_SAVE_KEYDEF),
MYF(MY_NABP)))
goto err;
for (j=0 ; j <= keyinfo[i].base.keysegs ; j++)
{
if (my_write(file,(char*) &keyinfo[i].seg[j].base,sizeof(N_SAVE_KEYSEG),
MYF(MY_NABP)))
goto err;
}
}
for (i=0 ; i < share.base.fields ; i++)
if (my_write(file,(char*) &recinfo[i].base, (uint) sizeof(N_SAVE_RECINFO),
MYF(MY_NABP)))
goto err;
/* Enlarge files */
if (my_chsize(file, (ulong) share.base.keystart, 0, MYF(0)))
goto err;
if (! (flags & HA_DONT_TOUCH_DATA))
{
#ifdef USE_RELOC
if (my_chsize(dfile, share.base.min_pack_length*reloc, 0, MYF(0)))
goto err;
#endif
errpos=1;
if (my_close(dfile,MYF(0)))
goto err;
}
errpos=0;
pthread_mutex_unlock(&THR_LOCK_isam);
if (my_close(file,MYF(0)))
goto err;
DBUG_RETURN(0);
err:
pthread_mutex_unlock(&THR_LOCK_isam);
save_errno=my_errno;
switch (errpos) {
case 2:
VOID(my_close(dfile,MYF(0)));
/* fall through */
case 1:
VOID(my_close(file,MYF(0)));
}
my_errno=save_errno; /* R{tt felkod tillbaka */
DBUG_RETURN(-1);
} /* nisam_create */

View File

@ -1,615 +0,0 @@
/* 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 */
/* Tar bort ett record fr}n en isam-databas */
#include "isamdef.h"
#ifdef __WIN__
#include <errno.h>
#endif
#include <assert.h>
static int d_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,ulong page,
uchar *anc_buff);
static int del(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uchar *anc_buff,
ulong leaf_page,uchar *leaf_buff,uchar *keypos,
ulong next_block,uchar *ret_key);
static int underflow(N_INFO *info,N_KEYDEF *keyinfo,uchar *anc_buff,
ulong leaf_page, uchar *leaf_buff,uchar *keypos);
static uint remove_key(N_KEYDEF *keyinfo,uint nod_flag,uchar *keypos,
uchar *lastkey,uchar *page_end);
int nisam_delete(N_INFO *info,const byte *record)
{
uint i;
uchar *old_key;
int save_errno;
uint32 lastpos;
ISAM_SHARE *share=info->s;
DBUG_ENTER("nisam_delete");
/* Test if record is in datafile */
if (!(info->update & HA_STATE_AKTIV))
{
my_errno=HA_ERR_KEY_NOT_FOUND; /* No database read */
DBUG_RETURN(-1);
}
if (share->base.options & HA_OPTION_READ_ONLY_DATA)
{
my_errno=EACCES;
DBUG_RETURN(-1);
}
#ifndef NO_LOCKING
if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1);
#endif
if ((*share->compare_record)(info,record))
goto err; /* Fel vid kontroll-l{sning */
/* Remove all keys from the .ISAM file */
old_key=info->lastkey+share->base.max_key_length;
for (i=0 ; i < share->state.keys ; i++ )
{
VOID(_nisam_make_key(info,i,old_key,record,info->lastpos));
if (_nisam_ck_delete(info,i,old_key)) goto err;
}
if ((*share->delete_record)(info))
goto err; /* Remove record from database */
info->update= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_DELETED;
share->state.records--;
lastpos= (uint32) info->lastpos;
nisam_log_command(LOG_DELETE,info,(byte*) &lastpos,sizeof(lastpos),0);
VOID(_nisam_writeinfo(info,1));
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);
err:
save_errno=my_errno;
lastpos= (uint32) info->lastpos;
nisam_log_command(LOG_DELETE,info,(byte*) &lastpos, sizeof(lastpos),0);
VOID(_nisam_writeinfo(info,1));
info->update|=HA_STATE_WRITTEN; /* Buffer changed */
allow_break(); /* Allow SIGHUP & SIGINT */
my_errno=save_errno;
if (save_errno == HA_ERR_KEY_NOT_FOUND)
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
} /* nisam_delete */
/* Tar bort en nyckel till isam-nyckelfilen */
int _nisam_ck_delete(register N_INFO *info, uint keynr, uchar *key)
{
int error;
uint nod_flag;
ulong old_root;
uchar *root_buff;
N_KEYDEF *keyinfo;
DBUG_ENTER("_nisam_ck_delete");
if ((old_root=info->s->state.key_root[keynr]) == NI_POS_ERROR)
{
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
keyinfo=info->s->keyinfo+keynr;
if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
N_MAX_KEY_BUFF*2)))
DBUG_RETURN(-1);
if (!_nisam_fetch_keypage(info,keyinfo,old_root,root_buff,0))
{
error= -1;
goto err;
}
if ((error=d_search(info,keyinfo,key,old_root,root_buff)) >0)
{
if (error == 2)
{
DBUG_PRINT("test",("Enlarging of root when deleting"));
error=_nisam_enlarge_root(info,keynr,key);
}
else
{
error=0;
if (getint(root_buff) <= (nod_flag=test_if_nod(root_buff))+3)
{
if (nod_flag)
info->s->state.key_root[keynr]=_nisam_kpos(nod_flag,
root_buff+2+nod_flag);
else
info->s->state.key_root[keynr]= NI_POS_ERROR;
if (_nisam_dispose(info,keyinfo,old_root))
error= -1;
}
}
}
err:
my_afree((gptr) root_buff);
DBUG_RETURN(error);
} /* _nisam_ck_delete */
/* Tar bort en nyckel under root */
/* Returnerar 1 om nuvarande buffert minskade */
/* Returnerar 2 om nuvarande buffert |kar */
static int d_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, ulong page, uchar *anc_buff)
{
int flag,ret_value,save_flag;
uint length,nod_flag;
uchar *leaf_buff,*keypos,*next_keypos;
ulong leaf_page,next_block;
uchar lastkey[N_MAX_KEY_BUFF];
DBUG_ENTER("d_search");
DBUG_DUMP("page",(byte*) anc_buff,getint(anc_buff));
flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,0,SEARCH_SAME,&keypos,
lastkey);
nod_flag=test_if_nod(anc_buff);
leaf_buff=0;
LINT_INIT(leaf_page);
if (nod_flag)
{
leaf_page=_nisam_kpos(nod_flag,keypos);
if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
N_MAX_KEY_BUFF*2)))
{
my_errno=ENOMEM;
DBUG_RETURN(-1);
}
if (!_nisam_fetch_keypage(info,keyinfo,leaf_page,leaf_buff,0))
goto err;
}
if (flag != 0)
{
if (!nod_flag)
{
my_errno=HA_ERR_CRASHED; /* This should newer happend */
goto err;
}
save_flag=0;
ret_value=d_search(info,keyinfo,key,leaf_page,leaf_buff);
}
else
{ /* Found key */
next_keypos=keypos; /* Find where next block is */
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&next_keypos,lastkey));
next_block=_nisam_kpos(nod_flag,next_keypos);
length=getint(anc_buff);
length-= remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length);
putint(anc_buff,length,nod_flag);
if (!nod_flag)
{ /* On leaf page */
if (_nisam_write_keypage(info,keyinfo,page,anc_buff))
DBUG_RETURN(-1);
DBUG_RETURN(length <= (uint) keyinfo->base.block_length/2);
}
save_flag=1;
ret_value=del(info,keyinfo,key,anc_buff,leaf_page,leaf_buff,keypos,
next_block,lastkey);
}
if (ret_value >0)
{
save_flag=1;
if (ret_value == 1)
ret_value= underflow(info,keyinfo,anc_buff,leaf_page,leaf_buff,keypos);
else
{ /* This happens only with packed keys */
DBUG_PRINT("test",("Enlarging of key when deleting"));
VOID(_nisam_get_last_key(info,keyinfo,anc_buff,lastkey,keypos));
ret_value=_nisam_insert(info,keyinfo,key,anc_buff,keypos,lastkey,
(uchar*) 0,(uchar*) 0,0L);
}
}
if (ret_value == 0 && getint(anc_buff) > keyinfo->base.block_length)
{
save_flag=1;
ret_value=_nisam_splitt_page(info,keyinfo,key,anc_buff,lastkey) | 2;
}
if (save_flag)
ret_value|=_nisam_write_keypage(info,keyinfo,page,anc_buff);
else
{
DBUG_DUMP("page",(byte*) anc_buff,getint(anc_buff));
}
my_afree((byte*) leaf_buff);
DBUG_RETURN(ret_value);
err:
my_afree((byte*) leaf_buff);
DBUG_PRINT("exit",("Error: %d",my_errno));
DBUG_RETURN (-1);
} /* d_search */
/* Remove a key that has a page-reference */
static int del(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key,
uchar *anc_buff, ulong leaf_page, uchar *leaf_buff,
uchar *keypos, /* Pos to where deleted key was */
ulong next_block,
uchar *ret_key) /* key before keypos in anc_buff */
{
int ret_value,length;
uint a_length,nod_flag;
ulong next_page;
uchar keybuff[N_MAX_KEY_BUFF],*endpos,*next_buff,*key_start;
ISAM_SHARE *share=info->s;
S_PARAM s_temp;
DBUG_ENTER("del");
DBUG_PRINT("enter",("leaf_page: %ld keypos: %lx",leaf_page,keypos));
DBUG_DUMP("leaf_buff",(byte*) leaf_buff,getint(leaf_buff));
endpos=leaf_buff+getint(leaf_buff);
key_start=_nisam_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos);
if ((nod_flag=test_if_nod(leaf_buff)))
{
next_page= _nisam_kpos(nod_flag,endpos);
if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
N_MAX_KEY_BUFF)))
DBUG_RETURN(-1);
if (!_nisam_fetch_keypage(info,keyinfo,next_page,next_buff,0))
ret_value= -1;
else
{
DBUG_DUMP("next_page",(byte*) next_buff,getint(next_buff));
if ((ret_value=del(info,keyinfo,key,anc_buff,next_page,next_buff,
keypos,next_block,ret_key)) >0)
{
endpos=leaf_buff+getint(leaf_buff);
if (ret_value == 1)
{
ret_value=underflow(info,keyinfo,leaf_buff,next_page,
next_buff,endpos);
if (ret_value == 0 && getint(leaf_buff) > keyinfo->base.block_length)
{
ret_value=_nisam_splitt_page(info,keyinfo,key,leaf_buff,ret_key) | 2;
}
}
else
{
DBUG_PRINT("test",("Inserting of key when deleting"));
VOID(_nisam_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos));
ret_value=_nisam_insert(info,keyinfo,key,leaf_buff,endpos,keybuff,
(uchar*) 0,(uchar*) 0,0L);
}
}
if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
goto err;
}
my_afree((byte*) next_buff);
DBUG_RETURN(ret_value);
}
/* Remove last key from leaf page */
putint(leaf_buff,key_start-leaf_buff,nod_flag);
if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
goto err;
/* Place last key in ancestor page on deleted key position */
a_length=getint(anc_buff);
endpos=anc_buff+a_length;
VOID(_nisam_get_last_key(info,keyinfo,anc_buff,ret_key,keypos));
length=_nisam_get_pack_key_length(keyinfo,share->base.key_reflength,
keypos == endpos ? (uchar*) 0 : keypos,
ret_key,keybuff,&s_temp);
if (length > 0)
bmove_upp((byte*) endpos+length,(byte*) endpos,(uint) (endpos-keypos));
else
bmove(keypos,keypos-length, (int) (endpos-keypos)+length);
_nisam_store_key(keyinfo,keypos,&s_temp);
/* Save pointer to next leaf */
VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key));
_nisam_kpointer(info,keypos - share->base.key_reflength,next_block);
putint(anc_buff,a_length+length,share->base.key_reflength);
DBUG_RETURN( getint(leaf_buff) <= (uint) keyinfo->base.block_length/2 );
err:
DBUG_RETURN(-1);
} /* del */
/* Balances adjacent pages if underflow occours */
static int underflow(register N_INFO *info, register N_KEYDEF *keyinfo,
uchar *anc_buff,
ulong leaf_page, /* Ancestor page and underflow page */
uchar *leaf_buff,
uchar *keypos) /* Position to pos after key */
{
int t_length;
uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag;
ulong next_page;
uchar anc_key[N_MAX_KEY_BUFF],leaf_key[N_MAX_KEY_BUFF],
*buff,*endpos,*next_keypos,*half_pos,*temp_pos;
S_PARAM s_temp;
ISAM_SHARE *share=info->s;
DBUG_ENTER("underflow");
DBUG_PRINT("enter",("leaf_page: %ld keypos: %lx",leaf_page,keypos));
DBUG_DUMP("anc_buff",(byte*) anc_buff,getint(anc_buff));
DBUG_DUMP("leaf_buff",(byte*) leaf_buff,getint(leaf_buff));
buff=info->buff;
next_keypos=keypos;
nod_flag=test_if_nod(leaf_buff);
p_length=2+nod_flag;
anc_length=getint(anc_buff);
leaf_length=getint(leaf_buff);
info->page_changed=1;
if ((keypos < anc_buff+anc_length && (share->rnd++ & 1)) ||
keypos == anc_buff+2+share->base.key_reflength)
{ /* Use page right of anc-page */
DBUG_PRINT("test",("use right page"));
VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&next_keypos,
buff));
next_page= _nisam_kpos(share->base.key_reflength,next_keypos);
if (!_nisam_fetch_keypage(info,keyinfo,next_page,buff,0))
goto err;
buff_length=getint(buff);
DBUG_DUMP("next",(byte*) buff,buff_length);
/* find keys to make a big key-page */
bmove((byte*) next_keypos-share->base.key_reflength,(byte*) buff+2,
share->base.key_reflength);
VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos));
VOID(_nisam_get_last_key(info,keyinfo,leaf_buff,leaf_key,
leaf_buff+leaf_length));
/* merge pages and put parting key from anc_buff between */
t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,buff+p_length,
(leaf_length == nod_flag+2 ?
(uchar*) 0 : leaf_key),
anc_key,&s_temp);
length=buff_length-p_length;
endpos=buff+length+leaf_length+t_length;
bmove_upp((byte*) endpos, (byte*) buff+buff_length,length);
memcpy((byte*) buff, (byte*) leaf_buff,(size_t) leaf_length);
_nisam_store_key(keyinfo,buff+leaf_length,&s_temp);
buff_length=(uint) (endpos-buff);
putint(buff,buff_length,nod_flag);
/* remove key from anc_buff */
s_length=remove_key(keyinfo,share->base.key_reflength,keypos,anc_key,
anc_buff+anc_length);
putint(anc_buff,(anc_length-=s_length),share->base.key_reflength);
if (buff_length <= keyinfo->base.block_length)
{ /* Keys in one page */
memcpy((byte*) leaf_buff,(byte*) buff,(size_t) buff_length);
if (_nisam_dispose(info,keyinfo,next_page))
goto err;
}
else
{ /* Page is full */
VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos));
half_pos=_nisam_find_half_pos(info,keyinfo,buff,leaf_key);
length=(uint) (half_pos-buff);
memcpy((byte*) leaf_buff,(byte*) buff,(size_t) length);
putint(leaf_buff,length,nod_flag);
endpos=anc_buff+anc_length;
/* Correct new keypointer to leaf_page */
length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key);
_nisam_kpointer(info,leaf_key+length,next_page);
/* Save key in anc_buff */
t_length=(int) _nisam_get_pack_key_length(keyinfo,
share->base.key_reflength,
keypos == endpos ?
(uchar*) 0 : keypos,
anc_key,leaf_key,&s_temp);
if (t_length >= 0)
bmove_upp((byte*) endpos+t_length,(byte*) endpos,
(uint) (endpos-keypos));
else
bmove(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length);
_nisam_store_key(keyinfo,keypos,&s_temp);
putint(anc_buff,(anc_length+=t_length),share->base.key_reflength);
/* Store new page */
if (nod_flag)
bmove((byte*) buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag);
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key));
t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,(uchar*) 0,
(uchar*) 0, leaf_key,&s_temp);
s_temp.n_length= *half_pos; /* For _nisam_store_key */
length=(uint) ((buff+getint(buff))-half_pos);
bmove((byte*) buff+p_length+t_length,(byte*) half_pos,(size_t) length);
_nisam_store_key(keyinfo,buff+p_length,&s_temp);
putint(buff,length+t_length+p_length,nod_flag);
if (_nisam_write_keypage(info,keyinfo,next_page,buff))
goto err;
}
if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
goto err;
DBUG_RETURN(anc_length <= (uint) keyinfo->base.block_length/2);
}
DBUG_PRINT("test",("use left page"));
keypos=_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos);
next_page= _nisam_kpos(share->base.key_reflength,keypos);
if (!_nisam_fetch_keypage(info,keyinfo,next_page,buff,0))
goto err;
buff_length=getint(buff);
endpos=buff+buff_length;
DBUG_DUMP("prev",(byte*) buff,buff_length);
/* find keys to make a big key-page */
bmove((byte*) next_keypos - share->base.key_reflength,(byte*) leaf_buff+2,
share->base.key_reflength);
next_keypos=keypos;
VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&next_keypos,
anc_key));
VOID(_nisam_get_last_key(info,keyinfo,buff,leaf_key,endpos));
/* merge pages and put parting key from anc_buff between */
t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,
leaf_buff+p_length,
(leaf_length == nod_flag+2 ?
(uchar*) 0 : leaf_key),
anc_key,&s_temp);
if (t_length >= 0)
bmove((byte*) endpos+t_length,(byte*) leaf_buff+p_length,
(size_t) (leaf_length-p_length));
else /* We gained space */
bmove((byte*) endpos,(byte*) leaf_buff+((int) p_length-t_length),
(size_t) (leaf_length-p_length+t_length));
_nisam_store_key(keyinfo,endpos,&s_temp);
buff_length=buff_length+leaf_length-p_length+t_length;
putint(buff,buff_length,nod_flag);
/* remove key from anc_buff */
s_length=remove_key(keyinfo,share->base.key_reflength,keypos,anc_key,
anc_buff+anc_length);
putint(anc_buff,(anc_length-=s_length),share->base.key_reflength);
if (buff_length <= keyinfo->base.block_length)
{ /* Keys in one page */
if (_nisam_dispose(info,keyinfo,leaf_page))
goto err;
}
else
{ /* Page is full */
VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos));
endpos=half_pos=_nisam_find_half_pos(info,keyinfo,buff,leaf_key);
/* Correct new keypointer to leaf_page */
length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key);
_nisam_kpointer(info,leaf_key+length,leaf_page);
/* Save key in anc_buff */
DBUG_DUMP("anc_buff",(byte*) anc_buff,anc_length);
DBUG_DUMP("key",(byte*) leaf_key,16);
temp_pos=anc_buff+anc_length;
t_length=(int) _nisam_get_pack_key_length(keyinfo,
share->base.key_reflength,
keypos == temp_pos ? (uchar*) 0
: keypos,
anc_key,leaf_key,&s_temp);
if (t_length > 0)
bmove_upp((byte*) temp_pos+t_length,(byte*) temp_pos,
(uint) (temp_pos-keypos));
else
bmove(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length);
_nisam_store_key(keyinfo,keypos,&s_temp);
putint(anc_buff,(anc_length+=t_length),share->base.key_reflength);
/* Store new page */
if (nod_flag)
bmove((byte*) leaf_buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag);
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key));
t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag, (uchar*) 0,
(uchar*) 0, leaf_key, &s_temp);
s_temp.n_length= *half_pos; /* For _nisam_store_key */
length=(uint) ((buff+buff_length)-half_pos);
bmove((byte*) leaf_buff+p_length+t_length,(byte*) half_pos,
(size_t) length);
_nisam_store_key(keyinfo,leaf_buff+p_length,&s_temp);
putint(leaf_buff,length+t_length+p_length,nod_flag);
putint(buff,endpos-buff,nod_flag);
if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
goto err;
}
if (_nisam_write_keypage(info,keyinfo,next_page,buff))
goto err;
DBUG_RETURN(anc_length <= (uint) keyinfo->base.block_length/2);
err:
DBUG_RETURN(-1);
} /* underflow */
/* remove a key from packed buffert */
/* returns how many chars was removed */
static uint remove_key(N_KEYDEF *keyinfo, uint nod_flag,
uchar *keypos, /* Where key starts */
uchar *lastkey, /* key to be removed */
uchar *page_end) /* End of page */
{
int r_length,s_length,first,diff_flag;
uchar *start;
DBUG_ENTER("remove_key");
DBUG_PRINT("enter",("keypos: %lx page_end: %lx",keypos,page_end));
start=keypos;
if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
s_length=(int) (keyinfo->base.keylength+nod_flag);
else
{ /* Let keypos point at next key */
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey));
s_length=(uint) (keypos-start);
if (keyinfo->base.flag & HA_PACK_KEY)
{
diff_flag= (keyinfo->seg[0].base.flag & HA_SPACE_PACK);
first= *start;
if (keypos != page_end && *keypos & 128 && first != 128)
{ /* Referens length */
if ((r_length= *keypos++ & 127) == 0)
{ /* Same key after */
if (first & 128)
start++; /* Skip ref length */
if (diff_flag)
start+= *start+1; /* Skip key length */
else
start+=keyinfo->seg[0].base.length- (first & 127);
s_length=(uint)(keypos-start); /* Remove pntrs and next-key-flag */
}
else if (! (first & 128))
{ /* Deleted key was not compressed */
if (diff_flag)
{
*start= (uchar) (r_length+ *keypos);
start+=r_length+1; /* Let ref-part remain */
s_length=(uint) (keypos-start)+1; /* Skip everything between */
}
else
{
start+=r_length+1; /* Let ref-part remain */
s_length=(uint) (keypos-start); /* Skip everything between */
}
}
else if ((first & 127) < r_length)
{ /* mid-part of key is used */
r_length-=(first & 127);
start++; /* Ref remains the same */
if (diff_flag)
*start++= (uchar) (*keypos++ + r_length);
start+= r_length;
s_length=(uint) (keypos-start); /* Skip everything between */
}
}
}
}
bmove((byte*) start,(byte*) start+s_length,
(uint) (page_end-start-s_length));
DBUG_RETURN((uint) s_length);
} /* remove_key */

View File

@ -1,271 +0,0 @@
/* 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 */
/* Extra functions we want to do with a database */
/* - Set flags for quicker databasehandler */
/* - Set databasehandler to normal */
/* - Reset recordpointers as after open database */
#include "isamdef.h"
#ifdef HAVE_MMAP
#include <sys/mman.h>
#endif
#ifdef __WIN__
#include <errno.h>
#endif
/* set extra flags for database */
int nisam_extra(N_INFO *info, enum ha_extra_function function)
{
int error=0;
DBUG_ENTER("nisam_extra");
switch (function) {
case HA_EXTRA_RESET:
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
error=end_io_cache(&info->rec_cache);
}
info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
case HA_EXTRA_RESET_STATE:
info->lastinx= 0; /* Use first index as def */
info->int_pos=info->lastpos= NI_POS_ERROR;
info->page_changed=1;
/* Next/prev gives first/last */
if (info->opt_flag & READ_CACHE_USED)
{
VOID(flush_io_cache(&info->rec_cache));
reinit_io_cache(&info->rec_cache,READ_CACHE,0,
(pbool) (info->lock_type != F_UNLCK),
(pbool) test(info->update & HA_STATE_ROW_CHANGED));
}
info->update=((info->update & HA_STATE_CHANGED) |
HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
break;
case HA_EXTRA_CACHE:
#ifndef NO_LOCKING
if (info->lock_type == F_UNLCK && (info->options & HA_OPTION_PACK_RECORD))
{
error=1; /* Not possibly if not locked */
my_errno=EACCES;
break;
}
#endif
#if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
if ((info->options & HA_OPTION_COMPRESS_RECORD))
{
pthread_mutex_lock(&info->s->intern_lock);
if (_nisam_memmap_file(info))
{
/* We don't nead MADV_SEQUENTIAL if small file */
madvise(info->s->file_map,info->s->state.data_file_length,
info->s->state.data_file_length <= RECORD_CACHE_SIZE*16 ?
MADV_RANDOM : MADV_SEQUENTIAL);
pthread_mutex_unlock(&info->s->intern_lock);
break;
}
pthread_mutex_unlock(&info->s->intern_lock);
}
#endif
if (info->opt_flag & WRITE_CACHE_USED)
{
info->opt_flag&= ~WRITE_CACHE_USED;
if ((error=end_io_cache(&info->rec_cache)))
break;
}
if (!(info->opt_flag &
(READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED)))
{
if (!(init_io_cache(&info->rec_cache,info->dfile,
(uint) min(info->s->state.data_file_length+1,
my_default_record_cache_size),
READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK),
MYF(MY_WAIT_IF_FULL))))
{
info->opt_flag|=READ_CACHE_USED;
info->update&= ~HA_STATE_ROW_CHANGED;
}
/* info->rec_cache.end_of_file=info->s->state.data_file_length; */
}
break;
case HA_EXTRA_REINIT_CACHE:
if (info->opt_flag & READ_CACHE_USED)
{
reinit_io_cache(&info->rec_cache,READ_CACHE,info->nextpos,
(pbool) (info->lock_type != F_UNLCK),
(pbool) test(info->update & HA_STATE_ROW_CHANGED));
info->update&= ~HA_STATE_ROW_CHANGED;
/* info->rec_cache.end_of_file=info->s->state.data_file_length; */
}
break;
case HA_EXTRA_WRITE_CACHE:
#ifndef NO_LOCKING
if (info->lock_type == F_UNLCK)
{
error=1; /* Not possibly if not locked */
break;
}
#endif
if (!(info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)))
{
if (!(init_io_cache(&info->rec_cache,info->dfile,0,
WRITE_CACHE,info->s->state.data_file_length,
(pbool) (info->lock_type != F_UNLCK),
MYF(MY_WAIT_IF_FULL))))
{
info->opt_flag|=WRITE_CACHE_USED;
info->update&= ~HA_STATE_ROW_CHANGED;
}
}
break;
case HA_EXTRA_PREPARE_FOR_UPDATE:
if (info->s->data_file_type != DYNAMIC_RECORD)
break;
/* Remove read/write cache if dynamic rows */
case HA_EXTRA_NO_CACHE:
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
error=end_io_cache(&info->rec_cache);
}
#if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
if (info->opt_flag & MEMMAP_USED)
madvise(info->s->file_map,info->s->state.data_file_length,MADV_RANDOM);
#endif
break;
case HA_EXTRA_FLUSH_CACHE:
if (info->opt_flag & WRITE_CACHE_USED)
error=flush_io_cache(&info->rec_cache);
break;
case HA_EXTRA_NO_READCHECK:
info->opt_flag&= ~READ_CHECK_USED; /* No readcheck */
break;
case HA_EXTRA_READCHECK:
info->opt_flag|= READ_CHECK_USED;
break;
case HA_EXTRA_KEYREAD: /* Read only keys to record */
case HA_EXTRA_REMEMBER_POS:
info->opt_flag |= REMEMBER_OLD_POS;
bmove((byte*) info->lastkey+info->s->base.max_key_length*2,
(byte*) info->lastkey,info->s->base.max_key_length);
info->save_update= info->update;
info->save_lastinx= info->lastinx;
info->save_lastpos= info->lastpos;
if (function == HA_EXTRA_REMEMBER_POS)
break;
/* fall through */
case HA_EXTRA_KEYREAD_CHANGE_POS:
info->opt_flag |= KEY_READ_USED;
info->read_record=_nisam_read_key_record;
break;
case HA_EXTRA_NO_KEYREAD:
case HA_EXTRA_RESTORE_POS:
if (info->opt_flag & REMEMBER_OLD_POS)
{
bmove((byte*) info->lastkey,
(byte*) info->lastkey+info->s->base.max_key_length*2,
info->s->base.max_key_length);
info->update= info->save_update | HA_STATE_WRITTEN;
info->lastinx= info->save_lastinx;
info->lastpos= info->save_lastpos;
}
info->read_record= info->s->read_record;
info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
break;
case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */
info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
break;
case HA_EXTRA_WAIT_LOCK:
info->lock_wait=0;
break;
case HA_EXTRA_NO_WAIT_LOCK:
info->lock_wait=MY_DONT_WAIT;
break;
case HA_EXTRA_NO_KEYS:
#ifndef NO_LOCKING
if (info->lock_type == F_UNLCK)
{
error=1; /* Not possibly if not lock */
break;
}
#endif
info->s->state.keys=0;
info->s->state.key_file_length=info->s->base.keystart;
info->s->changed=1; /* Update on close */
break;
case HA_EXTRA_FORCE_REOPEN:
case HA_EXTRA_PREPARE_FOR_DELETE:
pthread_mutex_lock(&THR_LOCK_isam);
info->s->last_version= 0L; /* Impossible version */
#ifdef __WIN__
/* Close the isam and data files as Win32 can't drop an open table */
if (flush_key_blocks(dflt_key_cache, info->s->kfile, FLUSH_RELEASE))
error=my_errno;
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
error=end_io_cache(&info->rec_cache);
}
if (info->lock_type != F_UNLCK && ! info->was_locked)
{
info->was_locked=info->lock_type;
if (nisam_lock_database(info,F_UNLCK))
error=my_errno;
}
if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0)))
error=my_errno;
{
LIST *list_element ;
for (list_element=nisam_open_list ;
list_element ;
list_element=list_element->next)
{
N_INFO *tmpinfo=(N_INFO*) list_element->data;
if (tmpinfo->s == info->s)
{
if (tmpinfo->dfile >= 0 && my_close(tmpinfo->dfile,MYF(0)))
error = my_errno;
tmpinfo->dfile=-1;
}
}
}
info->s->kfile=-1; /* Files aren't open anymore */
#endif
pthread_mutex_unlock(&THR_LOCK_isam);
break;
case HA_EXTRA_FLUSH:
if (info->s->not_flushed)
{
info->s->not_flushed=0;
if (my_sync(info->s->kfile, MYF(0)))
error= my_errno;
if (my_sync(info->dfile, MYF(0)))
error= my_errno;
}
break;
case HA_EXTRA_NORMAL: /* Theese isn't in use */
case HA_EXTRA_QUICK:
case HA_EXTRA_KEY_CACHE:
case HA_EXTRA_NO_KEY_CACHE:
default:
break;
}
nisam_log_command(LOG_EXTRA,info,(byte*) &function,sizeof(function),error);
DBUG_RETURN(error);
} /* nisam_extra */

View File

@ -1,77 +0,0 @@
/* 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 */
/* Ger tillbaka en struct med information om isam-filen */
#include "isamdef.h"
#ifdef __WIN__
#include <sys/stat.h>
#endif
ulong nisam_position(N_INFO *info)
{
return info->lastpos;
}
/* If flag == 1 one only gets pos of last record */
/* if flag == 2 one get current info (no sync from database */
int nisam_info(N_INFO *info, register N_ISAMINFO *x, int flag)
{
struct stat state;
ISAM_SHARE *share=info->s;
DBUG_ENTER("nisam_info");
x->recpos = info->lastpos;
if (flag & (HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE |
HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK))
{
#ifndef NO_LOCKING
if (!(flag & HA_STATUS_NO_LOCK))
{
pthread_mutex_lock(&share->intern_lock);
VOID(_nisam_readinfo(info,F_RDLCK,0));
VOID(_nisam_writeinfo(info,0));
pthread_mutex_unlock(&share->intern_lock);
}
#endif
x->records = share->state.records;
x->deleted = share->state.del;
x->delete_length= share->state.empty;
x->keys = share->state.keys;
x->reclength = share->base.reclength;
x->mean_reclength= share->state.records ?
(share->state.data_file_length-share->state.empty)/share->state.records :
share->min_pack_length;
x->data_file_length=share->state.data_file_length;
x->max_data_file_length=share->base.max_data_file_length;
x->index_file_length=share->state.key_file_length;
x->max_index_file_length=share->base.max_key_file_length;
x->filenr = info->dfile;
x->errkey = info->errkey;
x->dupp_key_pos= info->dupp_key_pos;
x->options = share->base.options;
x->create_time=share->base.create_time;
x->isamchk_time=share->base.isamchk_time;
x->rec_per_key=share->base.rec_per_key;
if ((flag & HA_STATUS_TIME) && !fstat(info->dfile,&state))
x->update_time=state.st_mtime;
else
x->update_time=0;
x->sortkey= -1; /* No clustering */
}
DBUG_RETURN(0);
} /* nisam_info */

File diff suppressed because it is too large Load Diff

View File

@ -1,418 +0,0 @@
/* 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 */
/* Denna fil includeras i alla isam-filer */
#define ISAM_LIBRARY
#include <nisam.h> /* Structs & some defines */
#ifdef THREAD
#include <my_pthread.h>
#include <thr_lock.h>
#else
#include <my_no_pthread.h>
#endif
#include <keycache.h>
#ifdef my_write
#undef my_write /* We want test if disk full */
#endif
#undef HA_SORT_ALLOWS_SAME
#define HA_SORT_ALLOWS_SAME 128 /* Can't be > 128 in NISAM */
#ifdef __WATCOMC__
#pragma pack(2)
#define uint uint16 /* Same format as in MSDOS */
#endif
#ifdef __ZTC__
#pragma ZTC align 2
#define uint uint16 /* Same format as in MSDOS */
#endif
#if defined(__WIN__) && defined(_MSC_VER)
#pragma pack(push,isamdef,2)
#define uint uint16
#endif
typedef struct st_state_info
{
struct { /* Fileheader */
uchar file_version[4];
uchar options[2];
uchar header_length[2];
uchar state_info_length[2];
uchar base_info_length[2];
uchar base_pos[2];
uchar not_used[2];
} header;
ulong records; /* Antal record i databasen */
ulong del; /* Antalet borttagna poster */
ulong dellink; /* L{nk till n{sta borttagna */
ulong key_file_length;
ulong data_file_length;
ulong splitt; /* Antal splittrade delar */
ulong empty; /* Outnyttjat utrymme */
ulong process; /* Vem som senast uppdatera */
ulong loop; /* not used anymore */
ulong uniq; /* Unik nr i denna process */
ulong key_root[N_MAXKEY]; /* Pekare till rootblocken */
ulong key_del[N_MAXKEY]; /* Del-l{nkar f|r n-block */
ulong sec_index_changed; /* Updated when new sec_index */
ulong sec_index_used; /* 1 bit for each sec index in use */
ulong version; /* timestamp of create */
uint keys; /* Keys in use for database */
} N_STATE_INFO;
typedef struct st_base_info
{
ulong keystart; /* Var nycklarna b|rjar */
ulong records,reloc; /* Parameter vid skapandet */
ulong max_pack_length; /* Max possibly length of packed rec.*/
ulong max_data_file_length;
ulong max_key_file_length;
uint reclength; /* length of unpacked record */
uint options; /* Options used */
uint pack_reclength; /* Length of full packed rec. */
uint min_pack_length;
uint min_block_length;
uint rec_reflength; /* = 2 or 3 or 4 */
uint key_reflength; /* = 2 or 3 or 4 */
uint keys; /* Keys defined for database */
uint blobs; /* Number of blobs */
uint max_block; /* Max blockl{ngd anv{nd */
uint max_key_length; /* L{ngsta nyckel-l{ngden */
uint fields, /* Antal f{lt i databasen */
pack_fields, /* Packade f{lt i databasen */
pack_bits; /* Length of packed bits */
time_t create_time; /* Time when created database */
time_t isamchk_time; /* Time for last recover */
ulong rec_per_key[N_MAXKEY]; /* for sql optimizing */
uint sortkey; /* sorted by this key */
} N_BASE_INFO;
#ifdef __ZTC__
#pragma ZTC align
#undef uint
#endif
#ifdef __WATCOMC__
#pragma pack()
#undef uint
#endif
#if defined(__WIN__) && defined(_MSC_VER)
#pragma pack(pop,isamdef)
#undef uint
#endif
/* Structs used intern in database */
typedef struct st_n_blob /* Info of record */
{
uint offset; /* Offset to blob in record */
uint pack_length; /* Type of packed length */
uint length; /* Calc:ed for each record */
} N_BLOB;
typedef struct st_isam_pack {
ulong header_length;
uint ref_length;
} N_PACK;
typedef struct st_isam_share { /* Shared between opens */
N_STATE_INFO state;
N_BASE_INFO base;
N_KEYDEF *keyinfo; /* Nyckelinfo */
N_RECINFO *rec; /* Pointer till recdata */
N_PACK pack; /* Data about packed records */
N_BLOB *blobs; /* Pointer to blobs */
char *filename; /* Name of indexfile */
byte *file_map; /* mem-map of file if possible */
ulong this_process; /* processid */
ulong last_process; /* For table-change-check */
ulong last_version; /* Version on start */
uint rec_reflength; /* rec_reflength in use now */
int kfile; /* Shared keyfile */
int mode; /* mode of file on open */
int reopen; /* How many times reopened */
uint state_length;
uint w_locks,r_locks; /* Number of read/write locks */
uint min_pack_length; /* Theese is used by packed data */
uint max_pack_length;
uint blocksize; /* blocksize of keyfile */
my_bool changed,not_flushed; /* If changed since lock */
int rnd; /* rnd-counter */
DECODE_TREE *decode_trees;
uint16 *decode_tables;
enum data_file_type data_file_type;
int (*read_record)(struct st_isam_info*, ulong, byte*);
int (*write_record)(struct st_isam_info*, const byte*);
int (*update_record)(struct st_isam_info*, ulong, const byte*);
int (*delete_record)(struct st_isam_info*);
int (*read_rnd)(struct st_isam_info*, byte*, ulong, int);
int (*compare_record)(struct st_isam_info*, const byte *);
#ifdef THREAD
THR_LOCK lock;
pthread_mutex_t intern_lock; /* Locking for use with _locking */
#endif
} ISAM_SHARE;
typedef uint bit_type;
typedef struct st_bit_buff { /* Used for packing of record */
bit_type current_byte;
uint bits;
uchar *pos,*end;
uint error;
} BIT_BUFF;
typedef struct st_isam_info {
ISAM_SHARE *s; /* Shared between open:s */
N_BLOB *blobs; /* Pointer to blobs */
int dfile; /* The datafile */
BIT_BUFF bit_buff;
uint options;
uint opt_flag; /* Optim. for space/speed */
uint update; /* If file changed since open */
char *filename; /* parameter to open filename */
ulong this_uniq; /* uniq filenumber or thread */
ulong last_uniq; /* last uniq number */
ulong this_loop; /* counter for this open */
ulong last_loop; /* last used counter */
ulong lastpos, /* Last record position */
nextpos; /* Position to next record */
ulong int_pos; /* Intern variabel */
ulong dupp_key_pos; /* Position to record with dupp key */
ulong last_search_keypage;
ulong save_lastpos;
uint packed_length; /* Length of found, packed record */
uint alloced_rec_buff_length; /* Max recordlength malloced */
uchar *buff, /* Temp area for key */
*lastkey; /* Last used search key */
byte *rec_buff, /* Tempbuff for recordpack */
*rec_alloc; /* Malloced area for record */
uchar *int_keypos, /* Intern variabel */
*int_maxpos; /* Intern variabel */
int lastinx; /* Last used index */
int errkey; /* Got last error on this key */
uint data_changed; /* Somebody has changed data */
int lock_type; /* How database was locked */
int tmp_lock_type; /* When locked by readinfo */
int was_locked; /* Was locked in panic */
myf lock_wait; /* is 0 or MY_DONT_WAIT */
my_bool page_changed;
my_bool buff_used;
uint save_update; /* When using KEY_READ */
int save_lastinx;
int (*read_record)(struct st_isam_info*, ulong, byte*);
LIST open_list;
IO_CACHE rec_cache; /* When cacheing records */
#ifdef THREAD
THR_LOCK_DATA lock;
#endif
} N_INFO;
/* Some defines used by isam-funktions */
#define USE_HOLE_KEY 0 /* Use hole key in _nisam_search() */
#define F_EXTRA_LCK -1
/* bits in opt_flag */
#define MEMMAP_USED 32
#define REMEMBER_OLD_POS 64
#define getint(x) ((uint) (uint16) *((int16*) (x)) & 32767)
#define putint(x,y,nod) (*((uint16*) (x))= ((nod ? (uint16) 32768 : 0)+(uint16) (y)))
#ifdef WORDS_BIGENDIAN
#define test_if_nod(x) (x[0] & 128 ? info->s->base.key_reflength : 0)
#else
#define test_if_nod(x) (x[1] & 128 ? info->s->base.key_reflength : 0)
#endif
#define N_MIN_BLOCK_LENGTH 8 /* Because of delete-link */
#define N_EXTEND_BLOCK_LENGTH 20 /* Don't use to small record-blocks */
#define N_SPLITT_LENGTH ((N_EXTEND_BLOCK_LENGTH+3)*2)
#define MAX_DYN_BLOCK_HEADER 11 /* Max prefix of record-block */
#define DYN_DELETE_BLOCK_HEADER 8 /* length of delete-block-header */
#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */
#define INDEX_BLOCK_MARGIN 16 /* Safety margin for .ISM tables */
#define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */
#define PACK_TYPE_SPACE_FIELDS 2
#define PACK_TYPE_ZERO_FILL 4
#ifdef THREAD
extern pthread_mutex_t THR_LOCK_isam;
#endif
/* Some extern variables */
extern LIST *nisam_open_list;
extern uchar NEAR nisam_file_magic[],NEAR nisam_pack_file_magic[];
extern uint NEAR nisam_read_vec[],nisam_quick_table_bits;
extern File nisam_log_file;
/* This is used by _nisam_get_pack_key_length och _nisam_store_key */
typedef struct st_s_param
{
uint ref_length,key_length,
n_ref_length,
n_length,
totlength,
part_of_prev_key,prev_length;
uchar *key, *prev_key;
} S_PARAM;
/* Prototypes for intern functions */
extern int _nisam_read_dynamic_record(N_INFO *info,ulong filepos,byte *buf);
extern int _nisam_write_dynamic_record(N_INFO*, const byte*);
extern int _nisam_update_dynamic_record(N_INFO*, ulong, const byte*);
extern int _nisam_delete_dynamic_record(N_INFO *info);
extern int _nisam_cmp_dynamic_record(N_INFO *info,const byte *record);
extern int _nisam_read_rnd_dynamic_record(N_INFO *, byte *,ulong, int);
extern int _nisam_write_blob_record(N_INFO*, const byte*);
extern int _nisam_update_blob_record(N_INFO*, ulong, const byte*);
extern int _nisam_read_static_record(N_INFO *info,ulong filepos,byte *buf);
extern int _nisam_write_static_record(N_INFO*, const byte*);
extern int _nisam_update_static_record(N_INFO*, ulong, const byte*);
extern int _nisam_delete_static_record(N_INFO *info);
extern int _nisam_cmp_static_record(N_INFO *info,const byte *record);
extern int _nisam_read_rnd_static_record(N_INFO*, byte *,ulong, int);
extern int _nisam_ck_write(N_INFO *info,uint keynr,uchar *key);
extern int _nisam_enlarge_root(N_INFO *info,uint keynr,uchar *key);
extern int _nisam_insert(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
uchar *anc_buff,uchar *key_pos,uchar *key_buff,
uchar *father_buff, uchar *father_keypos,
ulong father_page);
extern int _nisam_splitt_page(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
uchar *buff,uchar *key_buff);
extern uchar *_nisam_find_half_pos(N_INFO *info,N_KEYDEF *keyinfo,uchar *page,
uchar *key);
extern uint _nisam_get_pack_key_length(N_KEYDEF *keyinfo,uint nod_flag,
uchar *key_pos,uchar *key_buff,
uchar *key, S_PARAM *s_temp);
extern void _nisam_store_key(N_KEYDEF *keyinfo,uchar *key_pos,
S_PARAM *s_temp);
extern int _nisam_ck_delete(N_INFO *info,uint keynr,uchar *key);
extern int _nisam_readinfo(N_INFO *info,int lock_flag,int check_keybuffer);
extern int _nisam_writeinfo(N_INFO *info, uint flag);
extern int _nisam_test_if_changed(N_INFO *info);
extern int _nisam_check_index(N_INFO *info,int inx);
extern int _nisam_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uint key_len,uint nextflag,ulong pos);
extern int _nisam_bin_search(struct st_isam_info *info,N_KEYDEF *keyinfo,uchar *page,uchar *key,uint key_len,uint comp_flag,uchar * *ret_pos,uchar *buff);
extern int _nisam_seq_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *page,uchar *key,uint key_len,uint comp_flag,uchar * *ret_pos,uchar *buff);
extern ulong _nisam_kpos(uint nod_flag,uchar *after_key);
extern void _nisam_kpointer(N_INFO *info,uchar *buff,ulong pos);
extern ulong _nisam_dpos(N_INFO *info, uint nod_flag,uchar *after_key);
extern void _nisam_dpointer(N_INFO *info, uchar *buff,ulong pos);
extern int _nisam_key_cmp(N_KEYSEG *keyseg,uchar *a,uchar *b,
uint key_length,uint nextflag);
extern uint _nisam_get_key(N_KEYDEF *keyinfo,uint nod_flag,uchar * *page,uchar *key);
extern uint _nisam_get_static_key(N_KEYDEF *keyinfo,uint nod_flag,uchar * *page,uchar *key);
extern uchar *_nisam_get_last_key(N_INFO *info,N_KEYDEF *keyinfo,uchar *keypos,uchar *lastkey,uchar *endpos);
extern uint _nisam_keylength(N_KEYDEF *keyinfo,uchar *key);
extern uchar *_nisam_move_key(N_KEYDEF *keyinfo,uchar *to,uchar *from);
extern int _nisam_search_next(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uint nextflag,ulong pos);
extern int _nisam_search_first(N_INFO *info,N_KEYDEF *keyinfo,ulong pos);
extern int _nisam_search_last(N_INFO *info,N_KEYDEF *keyinfo,ulong pos);
extern uchar *_nisam_fetch_keypage(N_INFO *info,N_KEYDEF *keyinfo,my_off_t page,
uchar *buff,int return_buffer);
extern int _nisam_write_keypage(N_INFO *info,N_KEYDEF *keyinfo,my_off_t page,
uchar *buff);
extern int _nisam_dispose(N_INFO *info,N_KEYDEF *keyinfo,my_off_t pos);
extern ulong _nisam_new(N_INFO *info,N_KEYDEF *keyinfo);
extern uint _nisam_make_key(N_INFO *info,uint keynr,uchar *key,
const char *record,ulong filepos);
extern uint _nisam_pack_key(N_INFO *info,uint keynr,uchar *key,uchar *old,uint key_length);
extern int _nisam_read_key_record(N_INFO *info,ulong filepos,byte *buf);
extern int _nisam_read_cache(IO_CACHE *info,byte *buff,ulong pos,
uint length,int re_read_if_possibly);
extern byte *fix_rec_buff_for_blob(N_INFO *info,uint blob_length);
extern uint _nisam_rec_unpack(N_INFO *info,byte *to,byte *from,
uint reclength);
my_bool _nisam_rec_check(N_INFO *info,const char *from);
extern int _nisam_write_part_record(N_INFO *info,ulong filepos,uint length,
ulong next_filepos,byte **record,
uint *reclength,int *flag);
extern void _nisam_print_key(FILE *stream,N_KEYSEG *keyseg,const uchar *key);
extern my_bool _nisam_read_pack_info(N_INFO *info,pbool fix_keys);
extern int _nisam_read_pack_record(N_INFO *info,ulong filepos,byte *buf);
extern int _nisam_read_rnd_pack_record(N_INFO*, byte *,ulong, int);
extern int _nisam_pack_rec_unpack(N_INFO *info,byte *to,byte *from,
uint reclength);
extern ulong _nisam_checksum(const byte *mem, uint count);
typedef struct st_sortinfo {
uint key_length;
ulong max_records;
int (*key_cmp)(const void *, const void *, const void *);
int (*key_read)(void *buff);
int (*key_write)(const void *buff);
void (*lock_in_memory)(void);
} SORT_PARAM;
int _create_index_by_sort(SORT_PARAM *info,pbool no_messages,
uint sortbuff_size);
#define BLOCK_INFO_HEADER_LENGTH 11
typedef struct st_block_info { /* Parameter to _nisam_get_block_info */
uchar header[BLOCK_INFO_HEADER_LENGTH];
uint rec_len;
uint data_len;
uint block_len;
ulong filepos; /* Must be ulong on Alpha! */
ulong next_filepos;
uint second_read;
} BLOCK_INFO;
/* bits in return from _nisam_get_block_info */
#define BLOCK_FIRST 1
#define BLOCK_LAST 2
#define BLOCK_DELETED 4
#define BLOCK_ERROR 8 /* Wrong data */
#define BLOCK_SYNC_ERROR 16 /* Right data at wrong place */
#define BLOCK_FATAL_ERROR 32 /* hardware-error */
enum nisam_log_commands {
LOG_OPEN,LOG_WRITE,LOG_UPDATE,LOG_DELETE,LOG_CLOSE,LOG_EXTRA,LOG_LOCK
};
#define nisam_log_simple(a,b,c,d) if (nisam_log_file >= 0) _nisam_log(a,b,c,d)
#define nisam_log_command(a,b,c,d,e) if (nisam_log_file >= 0) _nisam_log_command(a,b,c,d,e)
#define nisam_log_record(a,b,c,d,e) if (nisam_log_file >= 0) _nisam_log_record(a,b,c,d,e)
extern uint _nisam_get_block_info(BLOCK_INFO *,File, ulong);
extern uint _nisam_rec_pack(N_INFO *info,byte *to,const byte *from);
extern uint _nisam_pack_get_block_info(BLOCK_INFO *, uint, File, ulong);
extern uint _calc_total_blob_length(N_INFO *info,const byte *record);
extern void _nisam_log(enum nisam_log_commands command,N_INFO *info,
const byte *buffert,uint length);
extern void _nisam_log_command(enum nisam_log_commands command,
N_INFO *info, const byte *buffert,
uint length, int result);
extern void _nisam_log_record(enum nisam_log_commands command,N_INFO *info,
const byte *record,ulong filepos,
int result);
extern my_bool _nisam_memmap_file(N_INFO *info);
extern void _nisam_unmap_file(N_INFO *info);

View File

@ -1,853 +0,0 @@
/* 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 */
/* write whats in isam.log */
#ifndef USE_MY_FUNC
#define USE_MY_FUNC
#endif
#include "isamdef.h"
#include <my_tree.h>
#include <stdarg.h>
#ifdef HAVE_GETRUSAGE
#include <sys/resource.h>
#endif
#define FILENAME(A) (A ? A->show_name : "Unknown")
struct isamlog_file_info {
long process;
int filenr,id;
my_string name,show_name,record;
N_INFO *isam;
bool closed,used;
ulong accessed;
};
struct test_if_open_param {
my_string name;
int max_id;
};
struct st_access_param
{
ulong min_accessed;
struct isamlog_file_info *found;
};
#define NO_FILEPOS (ulong) ~0L
extern int main(int argc,char * *argv);
static void get_options(int *argc,char ***argv);
static int examine_log(my_string file_name,char **table_names);
static int read_string(IO_CACHE *file,gptr *to,uint length);
static int file_info_compare(void *a,void *b);
static int test_if_open(struct isamlog_file_info *key,element_count count,
struct test_if_open_param *param);
static void fix_blob_pointers(N_INFO *isam,byte *record);
static uint set_maximum_open_files(uint);
static int test_when_accessed(struct isamlog_file_info *key,element_count count,
struct st_access_param *access_param);
static void file_info_free(struct isamlog_file_info *info);
static int close_some_file(TREE *tree);
static int reopen_closed_file(TREE *tree,struct isamlog_file_info *file_info);
static int find_record_with_key(struct isamlog_file_info *file_info,
byte *record);
static void printf_log(const char *str,...);
static bool cmp_filename(struct isamlog_file_info *file_info,my_string name);
static uint verbose=0,update=0,test_info=0,max_files=0,re_open_count=0,
recover=0,prefix_remove=0,opt_processes=0;
static my_string log_filename=0,filepath=0,write_filename=0,record_pos_file=0;
static ulong com_count[10][3],number_of_commands=(ulong) ~0L,start_offset=0,
record_pos= NO_FILEPOS,isamlog_filepos,isamlog_process;
static const char *command_name[]=
{"open","write","update","delete","close","extra","lock","re-open",NullS};
int main(int argc, char **argv)
{
int error,i,first;
ulong total_count,total_error,total_recover;
MY_INIT(argv[0]);
log_filename=nisam_log_filename;
get_options(&argc,&argv);
/* Nr of isam-files */
max_files=(set_maximum_open_files(min(max_files,8))-6)/2;
if (update)
printf("Trying to %s ISAM files according to log '%s'\n",
(recover ? "recover" : "update"),log_filename);
error= examine_log(log_filename,argv);
if (update && ! error)
puts("Tables updated successfully");
total_count=total_error=total_recover=0;
for (i=first=0 ; command_name[i] ; i++)
{
if (com_count[i][0])
{
if (!first++)
{
if (verbose || update)
puts("");
puts("Commands Used count Errors Recover errors");
}
printf("%-12s%9ld%10ld%17ld\n",command_name[i],com_count[i][0],
com_count[i][1],com_count[i][2]);
total_count+=com_count[i][0];
total_error+=com_count[i][1];
total_recover+=com_count[i][2];
}
}
if (total_count)
printf("%-12s%9ld%10ld%17ld\n","Total",total_count,total_error,
total_recover);
if (re_open_count)
printf("Had to do %d re-open because of too few possibly open files\n",
re_open_count);
VOID(nisam_panic(HA_PANIC_CLOSE));
my_end(test_info ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
exit(error);
return 0; /* No compiler warning */
} /* main */
static void get_options(register int *argc, register char ***argv)
{
int help,version;
const char *pos,*usage;
char option;
help=0;
usage="Usage: %s [-?iruvIPV] [-c #] [-f #] [-F filepath/] [-o #] [-R file recordpos] [-w write_file] [log-filename [table ...]] \n";
pos= "";
while (--*argc > 0 && *(pos = *(++*argv)) == '-' ) {
while (*++pos)
{
version=0;
switch((option=*pos)) {
case '#':
DBUG_PUSH (++pos);
pos=" "; /* Skip rest of arg */
break;
case 'c':
if (! *++pos)
{
if (!--*argc)
goto err;
else
pos= *(++*argv);
}
number_of_commands=(ulong) atol(pos);
pos=" ";
break;
case 'u':
update=1;
break;
case 'f':
if (! *++pos)
{
if (!--*argc)
goto err;
else
pos= *(++*argv);
}
max_files=(uint) atoi(pos);
pos=" ";
break;
case 'i':
test_info=1;
break;
case 'o':
if (! *++pos)
{
if (!--*argc)
goto err;
else
pos= *(++*argv);
}
start_offset=(ulong) atol(pos);
pos=" ";
break;
case 'p':
if (! *++pos)
{
if (!--*argc)
goto err;
else
pos= *(++*argv);
}
prefix_remove=atoi(pos);
break;
case 'r':
update=1;
recover++;
break;
case 'P':
opt_processes=1;
break;
case 'R':
if (! *++pos)
{
if (!--*argc)
goto err;
else
pos= *(++*argv);
}
record_pos_file=(char*) pos;
if (!--*argc)
goto err;
record_pos=(ulong) atol(*(++*argv));
pos= " ";
break;
case 'v':
verbose++;
break;
case 'w':
if (! *++pos)
{
if (!--*argc)
goto err;
else
pos= *(++*argv);
}
write_filename=(char*) pos;
pos=" ";
break;
case 'F':
if (! *++pos)
{
if (!--*argc)
goto err;
else
pos= *(++*argv);
}
filepath= (char*) pos;
pos=" ";
break;
case 'V':
version=1;
/* Fall through */
case 'I':
case '?':
printf("%s Ver 3.3 for %s at %s\n",my_progname,SYSTEM_TYPE,
MACHINE_TYPE);
puts("By Monty, for your professional use\n");
if (version)
break;
puts("Write info about whats in a ISAM log file.");
printf("If no file name is given %s is used\n",log_filename);
puts("");
printf(usage,my_progname);
puts("");
puts("Options: -? or -I \"Info\" -V \"version\" -c \"do only # commands\"");
puts(" -f \"max open files\" -F \"filepath\" -i \"extra info\"");
puts(" -o \"offset\" -p # \"remove # components from path\"");
puts(" -r \"recover\" -R \"file recordposition\"");
puts(" -u \"update\" -v \"verbose\" -w \"write file\"");
puts(" -P \"processes\"");
puts("\nOne can give a second and a third '-v' for more verbose.");
puts("Normaly one does a update (-u).");
puts("If a recover is done all writes and all possibly updates and deletes is done\nand errors are only counted.");
puts("If one gives table names as arguments only these tables will be updated\n");
help=1;
break;
default:
printf("illegal option: \"-%c\"\n",*pos);
break;
}
}
}
if (! *argc)
{
if (help)
exit(0);
(*argv)++;
}
if (*argc >= 1)
{
log_filename=(char*) pos;
(*argc)--;
(*argv)++;
}
return;
err:
VOID(fprintf(stderr,"option \"%c\" used without or with wrong argument\n",
option));
exit(1);
}
static int examine_log(my_string file_name, char **table_names)
{
uint command,result,files_open;
ulong access_time,length;
uint32 filepos;
int lock_command,ni_result;
char isam_file_name[FN_REFLEN];
uchar head[20];
gptr buff;
struct test_if_open_param open_param;
IO_CACHE cache;
File file;
FILE *write_file;
enum ha_extra_function extra_command;
TREE tree;
struct isamlog_file_info file_info,*curr_file_info;
char llbuff[22],llbuff2[22];
DBUG_ENTER("examine_log");
if ((file=my_open(file_name,O_RDONLY,MYF(MY_WME))) < 0)
DBUG_RETURN(1);
write_file=0;
if (write_filename)
{
if (!(write_file=my_fopen(write_filename,O_WRONLY,MYF(MY_WME))))
{
my_close(file,MYF(0));
DBUG_RETURN(1);
}
}
init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0));
bzero((gptr) com_count,sizeof(com_count));
init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
(tree_element_free) file_info_free, NULL);
VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
0,0));
files_open=0; access_time=0;
while (access_time++ != number_of_commands &&
!my_b_read(&cache,(byte*) head,9))
{
isamlog_filepos=my_b_tell(&cache)-9L;
file_info.filenr=uint2korr(head+1);
isamlog_process=file_info.process=(long) uint4korr(head+3);
if (!opt_processes)
file_info.process=0;
result=uint2korr(head+7);
if ((curr_file_info=(struct isamlog_file_info*)
tree_search(&tree, &file_info, tree.custom_arg)))
{
curr_file_info->accessed=access_time;
if (update && curr_file_info->used && curr_file_info->closed)
{
if (reopen_closed_file(&tree,curr_file_info))
{
command=sizeof(com_count)/sizeof(com_count[0][0])/3;
result=0;
goto com_err;
}
}
}
command=(uint) head[0];
if (command < sizeof(com_count)/sizeof(com_count[0][0])/3 &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
{
com_count[command][0]++;
if (result)
com_count[command][1]++;
}
switch ((enum nisam_log_commands) command) {
case LOG_OPEN:
if (!table_names[0])
{
com_count[command][0]--; /* Must be counted explicite */
if (result)
com_count[command][1]--;
}
if (curr_file_info)
printf("\nWarning: %s is opened with same process and filenumber\nMaybe you should use the -P option ?\n",
curr_file_info->show_name);
if (my_b_read(&cache,(byte*) head,2))
goto err;
file_info.name=0;
file_info.show_name=0;
file_info.record=0;
if (read_string(&cache,(gptr*) &file_info.name,(uint) uint2korr(head)))
goto err;
{
uint i;
char *pos,*to;
/* Fix if old DOS files to new format */
for (pos=file_info.name; (pos=strchr(pos,'\\')) ; pos++)
*pos= '/';
pos=file_info.name;
for (i=0 ; i < prefix_remove ; i++)
{
char *next;
if (!(next=strchr(pos,'/')))
break;
pos=next+1;
}
to=isam_file_name;
if (filepath)
to=convert_dirname(isam_file_name, filepath, NullS);
strmov(to,pos);
fn_ext(isam_file_name)[0]=0; /* Remove extension */
}
open_param.name=file_info.name;
open_param.max_id=0;
VOID(tree_walk(&tree,(tree_walk_action) test_if_open,(void*) &open_param,
left_root_right));
file_info.id=open_param.max_id+1;
file_info.show_name=my_memdup(isam_file_name,
(uint) strlen(isam_file_name)+6,
MYF(MY_WME));
if (file_info.id > 1)
sprintf(strend(file_info.show_name),"<%d>",file_info.id);
file_info.closed=1;
file_info.accessed=access_time;
file_info.used=1;
if (table_names[0])
{
char **name;
file_info.used=0;
for (name=table_names ; *name ; name++)
{
if (!strcmp(*name,isam_file_name))
file_info.used=1; /* Update/log only this */
}
}
if (update && file_info.used)
{
if (files_open >= max_files)
{
if (close_some_file(&tree))
goto com_err;
files_open--;
}
if (!(file_info.isam= nisam_open(isam_file_name,O_RDWR,
HA_OPEN_WAIT_IF_LOCKED)))
goto com_err;
if (!(file_info.record=my_malloc(file_info.isam->s->base.reclength,
MYF(MY_WME))))
goto end;
files_open++;
file_info.closed=0;
}
VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg));
if (file_info.used)
{
if (verbose && !record_pos_file)
printf_log("%s: open -> %d",file_info.show_name, file_info.filenr);
com_count[command][0]++;
if (result)
com_count[command][1]++;
}
break;
case LOG_CLOSE:
if (verbose && !record_pos_file &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
printf_log("%s: %s -> %d",FILENAME(curr_file_info),
command_name[command],result);
if (curr_file_info)
{
if (!curr_file_info->closed)
files_open--;
VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
}
break;
case LOG_EXTRA:
if (my_b_read(&cache,(byte*) head,sizeof(extra_command)))
goto err;
memcpy_fixed(&extra_command,head,sizeof(extra_command));
if (verbose && !record_pos_file &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
printf_log("%s: %s(%d) -> %d",FILENAME(curr_file_info),
command_name[command], (int) extra_command,result);
if (update && curr_file_info && !curr_file_info->closed)
{
if (nisam_extra(curr_file_info->isam,extra_command) != (int) result)
{
fflush(stdout);
VOID(fprintf(stderr,
"Warning: error %d, expected %d on command %s at %s\n",
my_errno,result,command_name[command],
llstr(isamlog_filepos,llbuff)));
fflush(stderr);
}
}
break;
case LOG_DELETE:
if (my_b_read(&cache,(byte*) head,sizeof(filepos)))
goto err;
memcpy_fixed(&filepos,head,sizeof(filepos));
if (verbose && (!record_pos_file ||
((record_pos == filepos || record_pos == NO_FILEPOS) &&
!cmp_filename(curr_file_info,record_pos_file))) &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
printf_log("%s: %s at %ld -> %d",FILENAME(curr_file_info),
command_name[command],(long) filepos,result);
if (update && curr_file_info && !curr_file_info->closed)
{
if (nisam_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
{
if (!recover)
goto com_err;
com_count[command][2]++; /* Mark error */
}
ni_result=nisam_delete(curr_file_info->isam,curr_file_info->record);
if ((ni_result == 0 && result) ||
(ni_result && (uint) my_errno != result))
{
if (!recover)
goto com_err;
if (ni_result)
com_count[command][2]++; /* Mark error */
if (verbose)
printf_log("error: Got result %d from mi_delete instead of %d",
ni_result, result);
}
}
break;
case LOG_WRITE:
case LOG_UPDATE:
if (my_b_read(&cache,(byte*) head,8))
goto err;
filepos=uint4korr(head);
length=uint4korr(head+4);
buff=0;
if (read_string(&cache,&buff,(uint) length))
goto err;
if ((!record_pos_file ||
((record_pos == filepos || record_pos == NO_FILEPOS) &&
!cmp_filename(curr_file_info,record_pos_file))) &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
{
if (write_file &&
(my_fwrite(write_file,buff,length,MYF(MY_WAIT_IF_FULL | MY_NABP))))
goto end;
if (verbose)
printf_log("%s: %s at %ld, length=%ld -> %d",
FILENAME(curr_file_info),
command_name[command], filepos,length,result);
}
if (update && curr_file_info && !curr_file_info->closed)
{
if (curr_file_info->isam->s->base.blobs)
fix_blob_pointers(curr_file_info->isam,buff);
if ((enum nisam_log_commands) command == LOG_UPDATE)
{
if (nisam_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
{
if (!recover)
{
result=0;
goto com_err;
}
if (verbose)
printf_log("error: Didn't find row to update with mi_rrnd");
if (recover == 1 || result ||
find_record_with_key(curr_file_info,buff))
{
com_count[command][2]++; /* Mark error */
break;
}
}
ni_result=nisam_update(curr_file_info->isam,curr_file_info->record,
buff);
if ((ni_result == 0 && result) ||
(ni_result && (uint) my_errno != result))
{
if (!recover)
goto com_err;
if (verbose)
printf_log("error: Got result %d from mi_update instead of %d",
ni_result, result);
if (ni_result)
com_count[command][2]++; /* Mark error */
}
}
else
{
ni_result=nisam_write(curr_file_info->isam,buff);
if ((ni_result == 0 && result) ||
(ni_result && (uint) my_errno != result))
{
if (!recover)
goto com_err;
if (ni_result)
com_count[command][2]++; /* Mark error */
}
if (! recover && filepos != curr_file_info->isam->lastpos)
{
printf("error: Wrote at position: %s, should have been %s",
llstr(curr_file_info->isam->lastpos,llbuff),
llstr(filepos,llbuff2));
goto end;
}
}
}
my_free(buff,MYF(0));
break;
case LOG_LOCK:
if (my_b_read(&cache,(byte*) head,sizeof(lock_command)))
goto err;
memcpy_fixed(&lock_command,head,sizeof(lock_command));
if (verbose && !record_pos_file &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
printf_log("%s: %s(%d) -> %d\n",FILENAME(curr_file_info),
command_name[command],lock_command,result);
if (update && curr_file_info && !curr_file_info->closed)
{
if (nisam_lock_database(curr_file_info->isam,lock_command) !=
(int) result)
goto com_err;
}
break;
default:
VOID(fprintf(stderr,
"Error: found unknown command %d in logfile, aborted\n",
command));
fflush(stderr);
goto end;
}
}
end_key_cache(dflt_key_cache,1);
delete_tree(&tree);
VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0)));
if (write_file && my_fclose(write_file,MYF(MY_WME)))
DBUG_RETURN(1);
DBUG_RETURN(0);
err:
fflush(stdout);
VOID(fprintf(stderr,"Got error %d when reading from logfile\n",my_errno));
fflush(stderr);
goto end;
com_err:
fflush(stdout);
VOID(fprintf(stderr,"Got error %d, expected %d on command %s at %s\n",
my_errno,result,command_name[command],
llstr(isamlog_filepos,llbuff)));
fflush(stderr);
end:
end_key_cache(dflt_key_cache,1);
delete_tree(&tree);
VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0)));
if (write_file)
VOID(my_fclose(write_file,MYF(MY_WME)));
DBUG_RETURN(1);
}
static int read_string(IO_CACHE *file, reg1 gptr *to, reg2 uint length)
{
DBUG_ENTER("read_string");
if (*to)
my_free((gptr) *to,MYF(0));
if (!(*to= (gptr) my_malloc(length+1,MYF(MY_WME))) ||
my_b_read(file,(byte*) *to,length))
{
if (*to)
my_free(*to,MYF(0));
*to= 0;
DBUG_RETURN(1);
}
*((char*) *to+length)= '\0';
DBUG_RETURN (0);
} /* read_string */
static int file_info_compare(void *a, void *b)
{
long lint;
if ((lint=((struct isamlog_file_info*) a)->process -
((struct isamlog_file_info*) b)->process))
return lint < 0L ? -1 : 1;
return (((struct isamlog_file_info*) a)->filenr -
((struct isamlog_file_info*) b)->filenr);
}
/* ARGSUSED */
static int test_if_open (struct isamlog_file_info *key,
element_count count __attribute__((unused)),
struct test_if_open_param *param)
{
if (!strcmp(key->name,param->name) && key->id > param->max_id)
param->max_id=key->id;
return 0;
}
static void fix_blob_pointers( N_INFO *info, byte *record)
{
byte *pos;
N_BLOB *blob,*end;
pos=record+info->s->base.reclength;
for (end=info->blobs+info->s->base.blobs, blob= info->blobs;
blob != end ;
blob++)
{
bmove(record+blob->offset+blob->pack_length,&pos,sizeof(char*));
pos+=_calc_blob_length(blob->pack_length,record+blob->offset);
}
}
static uint set_maximum_open_files(uint maximum_files)
{
#if defined(HAVE_GETRUSAGE) && defined(RLIMIT_NOFILE)
struct rlimit rlimit;
int old_max;
if (maximum_files > MY_NFILE)
maximum_files=MY_NFILE; /* Don't crash my_open */
if (!getrlimit(RLIMIT_NOFILE,&rlimit))
{
old_max=rlimit.rlim_max;
if (maximum_files && (int) maximum_files > old_max)
rlimit.rlim_max=maximum_files;
rlimit.rlim_cur=rlimit.rlim_max;
if (setrlimit(RLIMIT_NOFILE,&rlimit))
{
if (old_max != (int) maximum_files)
{ /* Set as much as we can */
rlimit.rlim_max=rlimit.rlim_cur=old_max;
setrlimit(RLIMIT_NOFILE,&rlimit);
}
}
getrlimit(RLIMIT_NOFILE,&rlimit); /* Read if broken setrlimit */
if (maximum_files && maximum_files < rlimit.rlim_cur)
VOID(fprintf(stderr,"Warning: Error from setrlimit: Max open files is %d\n",old_max));
return rlimit.rlim_cur;
}
#endif
return min(maximum_files,MY_NFILE);
}
/* close the file with hasn't been accessed for the longest time */
/* ARGSUSED */
static int test_when_accessed (struct isamlog_file_info *key,
element_count count __attribute__((unused)),
struct st_access_param *access_param)
{
if (key->accessed < access_param->min_accessed && ! key->closed)
{
access_param->min_accessed=key->accessed;
access_param->found=key;
}
return 0;
}
static void file_info_free(struct isamlog_file_info *fileinfo)
{
DBUG_ENTER("file_info_free");
if (update)
{
if (!fileinfo->closed)
VOID(nisam_close(fileinfo->isam));
if (fileinfo->record)
my_free(fileinfo->record,MYF(0));
}
my_free(fileinfo->name,MYF(0));
my_free(fileinfo->show_name,MYF(0));
DBUG_VOID_RETURN;
}
static int close_some_file(TREE *tree)
{
struct st_access_param access_param;
access_param.min_accessed=LONG_MAX;
access_param.found=0;
VOID(tree_walk(tree,(tree_walk_action) test_when_accessed,
(void*) &access_param,left_root_right));
if (!access_param.found)
return 1; /* No open file that is possibly to close */
if (nisam_close(access_param.found->isam))
return 1;
access_param.found->closed=1;
return 0;
}
static int reopen_closed_file(TREE *tree, struct isamlog_file_info *fileinfo)
{
char name[FN_REFLEN];
if (close_some_file(tree))
return 1; /* No file to close */
strmov(name,fileinfo->show_name);
if (fileinfo->id > 1)
*strrchr(name,'<')='\0'; /* Remove "<id>" */
if (!(fileinfo->isam= nisam_open(name,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)))
return 1;
fileinfo->closed=0;
re_open_count++;
return 0;
}
/* Try to find record with uniq key */
static int find_record_with_key(struct isamlog_file_info *file_info,
byte *record)
{
uint key;
N_INFO *info=file_info->isam;
uchar tmp_key[N_MAX_KEY_BUFF];
for (key=0 ; key < info->s->state.keys ; key++)
{
if (info->s->keyinfo[key].base.flag & HA_NOSAME)
{
VOID(_nisam_make_key(info,key,tmp_key,record,0L));
return nisam_rkey(info,file_info->record,(int) key,(char*) tmp_key,0,
HA_READ_KEY_EXACT);
}
}
return 1;
}
static void printf_log(const char *format,...)
{
char llbuff[21];
va_list args;
va_start(args,format);
if (verbose > 2)
printf("%9s:",llstr(isamlog_filepos,llbuff));
if (verbose > 1)
printf("%5ld ",isamlog_process); /* Write process number */
(void) vprintf((char*) format,args);
putchar('\n');
va_end(args);
}
static bool cmp_filename(struct isamlog_file_info *file_info,my_string name)
{
if (!file_info)
return 1;
return strcmp(file_info->name,name) ? 1 : 0;
}

View File

@ -1,156 +0,0 @@
/* 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 */
/* Logging of isamcommands and records on logfile */
#include "isamdef.h"
#if defined(MSDOS) || defined(__WIN__)
#include <errno.h>
#include <fcntl.h>
#ifndef __WIN__
#include <process.h>
#endif
#endif
#ifdef VMS
#include <processes.h>
#endif
#ifdef THREAD
#undef GETPID
#define GETPID() (log_type == 1 ? getpid() : (long) my_thread_id());
#else
#define GETPID() getpid()
#endif
/* Activate logging if flag is 1 and reset logging if flag is 0 */
static int log_type=0;
int nisam_log(int activate_log)
{
int error=0;
char buff[FN_REFLEN];
DBUG_ENTER("nisam_log");
log_type=activate_log;
if (activate_log)
{
if (nisam_log_file < 0)
{
if ((nisam_log_file = my_create(fn_format(buff,nisam_log_filename,
"",".log",4),
0,(O_RDWR | O_BINARY | O_APPEND),MYF(0)))
< 0)
DBUG_RETURN(1);
}
}
else if (nisam_log_file >= 0)
{
error=my_close(nisam_log_file,MYF(0));
nisam_log_file= -1;
}
DBUG_RETURN(error);
}
/* Logging of records and commands on logfile */
/* All logs starts with command(1) dfile(2) process(4) result(2) */
void _nisam_log(enum nisam_log_commands command, N_INFO *info, const byte *buffert, uint length)
{
char buff[11];
int error,old_errno;
ulong pid=(ulong) GETPID();
old_errno=my_errno;
bzero(buff,sizeof(buff));
buff[0]=(char) command;
int2store(buff+1,info->dfile);
int4store(buff+3,pid);
int2store(buff+9,length);
pthread_mutex_lock(&THR_LOCK_isam);
error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
VOID(my_write(nisam_log_file,buffert,length,MYF(0)));
if (!error)
error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
pthread_mutex_unlock(&THR_LOCK_isam);
my_errno=old_errno;
}
void _nisam_log_command(enum nisam_log_commands command, N_INFO *info, const byte *buffert, uint length, int result)
{
char buff[9];
int error,old_errno;
ulong pid=(ulong) GETPID();
old_errno=my_errno;
buff[0]=(char) command;
int2store(buff+1,info->dfile);
int4store(buff+3,pid);
int2store(buff+7,result);
pthread_mutex_lock(&THR_LOCK_isam);
error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
if (buffert)
VOID(my_write(nisam_log_file,buffert,length,MYF(0)));
if (!error)
error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
pthread_mutex_unlock(&THR_LOCK_isam);
my_errno=old_errno;
}
void _nisam_log_record(enum nisam_log_commands command, N_INFO *info, const byte *record, ulong filepos, int result)
{
char buff[17],*pos;
int error,old_errno;
uint length;
ulong pid=(ulong) GETPID();
old_errno=my_errno;
if (!info->s->base.blobs)
length=info->s->base.reclength;
else
length=info->s->base.reclength+ _calc_total_blob_length(info,record);
buff[0]=(char) command;
int2store(buff+1,info->dfile);
int4store(buff+3,pid);
int2store(buff+7,result);
int4store(buff+9,filepos);
int4store(buff+13,length);
pthread_mutex_lock(&THR_LOCK_isam);
error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
VOID(my_write(nisam_log_file,(byte*) record,info->s->base.reclength,MYF(0)));
if (info->s->base.blobs)
{
N_BLOB *blob,*end;
for (end=info->blobs+info->s->base.blobs, blob= info->blobs;
blob != end ;
blob++)
{
bmove(&pos,record+blob->offset+blob->pack_length,sizeof(char*));
VOID(my_write(nisam_log_file,pos,blob->length,MYF(0)));
}
}
if (!error)
error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
pthread_mutex_unlock(&THR_LOCK_isam);
my_errno=old_errno;
}

View File

@ -1,3 +0,0 @@
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

View File

@ -1,477 +0,0 @@
/* 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 */
/* open a isam-database */
#include "isamdef.h"
#if defined(MSDOS) || defined(__WIN__)
#ifdef __WIN__
#include <fcntl.h>
#else
#include <process.h> /* Prototype for getpid */
#endif
#endif
#ifdef VMS
#include "static.c"
#endif
static void setup_functions(ISAM_SHARE *info);
static void setup_key_functions(N_KEYDEF *keyinfo);
#define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \
pos+=size;}
/******************************************************************************
** Return the shared struct if the table is already open.
** In MySQL the server will handle version issues.
******************************************************************************/
static N_INFO *test_if_reopen(char *filename)
{
LIST *pos;
for (pos=nisam_open_list ; pos ; pos=pos->next)
{
N_INFO *info=(N_INFO*) pos->data;
ISAM_SHARE *share=info->s;
if (!strcmp(share->filename,filename) && share->last_version)
return info;
}
return 0;
}
/******************************************************************************
open a isam database.
By default exit with error if database is locked
if handle_locking & HA_OPEN_WAIT_IF_LOCKED then wait if database is locked
if handle_locking & HA_OPEN_IGNORE_IF_LOCKED then continue, but count-vars
in st_i_info may be wrong. count-vars are automaticly fixed after next
isam request.
******************************************************************************/
N_INFO *nisam_open(const char *name, int mode, uint handle_locking)
{
int lock_error,kfile,open_mode,save_errno;
uint i,j,len,errpos,head_length,base_pos,offset,info_length,extra;
char name_buff[FN_REFLEN],*disk_cache,*disk_pos;
N_INFO info,*m_info,*old_info;
ISAM_SHARE share_buff,*share;
DBUG_ENTER("nisam_open");
LINT_INIT(m_info);
kfile= -1;
lock_error=1;
errpos=0;
head_length=sizeof(share_buff.state.header);
bzero((byte*) &info,sizeof(info));
VOID(fn_format(name_buff,name,"",N_NAME_IEXT,4+16+32));
pthread_mutex_lock(&THR_LOCK_isam);
if (!(old_info=test_if_reopen(name_buff)))
{
share= &share_buff;
bzero((gptr) &share_buff,sizeof(share_buff));
if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
{
if ((errno != EROFS && errno != EACCES) ||
mode != O_RDONLY ||
(kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
goto err;
}
errpos=1;
if (my_read(kfile,(char*) share->state.header.file_version,head_length,
MYF(MY_NABP)))
goto err;
if (memcmp((byte*) share->state.header.file_version,
(byte*) nisam_file_magic, 3) ||
share->state.header.file_version[3] == 0 ||
(uchar) share->state.header.file_version[3] > 3)
{
DBUG_PRINT("error",("Wrong header in %s",name_buff));
DBUG_DUMP("error_dump",(char*) share->state.header.file_version,
head_length);
my_errno=HA_ERR_CRASHED;
goto err;
}
if (uint2korr(share->state.header.options) &
~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
HA_OPTION_TEMP_COMPRESS_RECORD))
{
DBUG_PRINT("error",("wrong options: 0x%lx",
uint2korr(share->state.header.options)));
my_errno=HA_ERR_OLD_FILE;
goto err;
}
info_length=uint2korr(share->state.header.header_length);
base_pos=uint2korr(share->state.header.base_pos);
if (!(disk_cache=(char*) my_alloca(info_length)))
{
my_errno=ENOMEM;
goto err;
}
errpos=2;
VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
#ifndef NO_LOCKING
if (!(handle_locking & HA_OPEN_TMP_TABLE))
{
if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF,
MYF(handle_locking & HA_OPEN_WAIT_IF_LOCKED ?
0 : MY_DONT_WAIT))) &&
!(handle_locking & HA_OPEN_IGNORE_IF_LOCKED))
goto err;
}
#endif
errpos=3;
if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
goto err;
len=uint2korr(share->state.header.state_info_length);
if (len != sizeof(N_STATE_INFO))
{
DBUG_PRINT("warning",
("saved_state_info_length: %d base_info_length: %d",
len,sizeof(N_STATE_INFO)));
}
if (len > sizeof(N_STATE_INFO))
len=sizeof(N_STATE_INFO);
share->state_length=len;
memcpy(&share->state.header.file_version[0],disk_cache,(size_t) len);
len=uint2korr(share->state.header.base_info_length);
if (len != sizeof(N_BASE_INFO))
{
DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d",
len,sizeof(N_BASE_INFO)));
if (len <= offsetof(N_BASE_INFO,sortkey))
share->base.sortkey=(ushort) ~0;
}
memcpy((char*) (byte*) &share->base,disk_cache+base_pos,
(size_t) min(len,sizeof(N_BASE_INFO)));
disk_pos=disk_cache+base_pos+len;
share->base.options=uint2korr(share->state.header.options);
if (share->base.max_key_length > N_MAX_KEY_BUFF)
{
my_errno=HA_ERR_UNSUPPORTED;
goto err;
}
if (share->base.options & HA_OPTION_COMPRESS_RECORD)
share->base.max_key_length+=2; /* For safety */
if (!my_multi_malloc(MY_WME,
&share,sizeof(*share),
&share->keyinfo,share->base.keys*sizeof(N_KEYDEF),
&share->rec,(share->base.fields+1)*sizeof(N_RECINFO),
&share->blobs,sizeof(N_BLOB)*share->base.blobs,
&share->filename,strlen(name_buff)+1,
NullS))
goto err;
errpos=4;
*share=share_buff;
strmov(share->filename,name_buff);
/* Fix key in used if old nisam-database */
if (share->state_length <= offsetof(N_STATE_INFO,keys))
share->state.keys=share->base.keys;
share->blocksize=min(IO_SIZE,nisam_block_size);
for (i=0 ; i < share->base.keys ; i++)
{
get_next_element(&share->keyinfo[i].base,disk_pos,sizeof(N_SAVE_KEYDEF));
setup_key_functions(share->keyinfo+i);
set_if_smaller(share->blocksize,share->keyinfo[i].base.block_length);
for (j=0 ; j <= share->keyinfo[i].base.keysegs ; j++)
{
get_next_element(&share->keyinfo[i].seg[j],disk_pos,
sizeof(N_SAVE_KEYSEG));
}
}
if (!share->blocksize)
{
my_errno=HA_ERR_CRASHED;
goto err;
}
for (i=j=offset=0 ; i < share->base.fields ; i++)
{
get_next_element(&share->rec[i].base,disk_pos,sizeof(N_SAVE_RECINFO));
#ifndef NOT_PACKED_DATABASES
share->rec[i].pack_type=0;
share->rec[i].huff_tree=0;
#endif
if (share->rec[i].base.type == (int) FIELD_BLOB)
{
share->blobs[j].pack_length=share->rec[i].base.length;
share->blobs[j].offset=offset;
j++;
offset+=sizeof(char*);
}
offset+=share->rec[i].base.length;
}
share->rec[i].base.type=(int) FIELD_LAST;
#ifndef NO_LOCKING
if (! lock_error)
{
VOID(my_lock(kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
lock_error=1; /* Database unlocked */
}
#endif
if ((info.dfile=my_open(fn_format(name_buff,name,"",N_NAME_DEXT,2+4),
mode | O_SHARE,
MYF(MY_WME))) < 0)
goto err;
errpos=5;
share->kfile=kfile;
share->mode=open_mode;
share->this_process=(ulong) getpid();
share->rnd= (int) share->this_process; /* rnd-counter for splitts */
#ifndef DBUG_OFF
share->rnd=0; /* To make things repeatable */
#endif
share->last_process= share->state.process;
if (!(share->last_version=share->state.version))
share->last_version=1; /* Safety */
share->rec_reflength=share->base.rec_reflength; /* May be changed */
share->data_file_type=STATIC_RECORD;
if (share->base.options & HA_OPTION_COMPRESS_RECORD)
{
share->data_file_type = COMPRESSED_RECORD;
share->base.options|= HA_OPTION_READ_ONLY_DATA;
info.s=share;
if (_nisam_read_pack_info(&info,
(pbool) test(!(share->base.options &
(HA_OPTION_PACK_RECORD |
HA_OPTION_TEMP_COMPRESS_RECORD)))))
goto err;
}
else if (share->base.options & HA_OPTION_PACK_RECORD)
share->data_file_type = DYNAMIC_RECORD;
my_afree((gptr) disk_cache);
setup_functions(share);
#ifdef THREAD
thr_lock_init(&share->lock);
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
#endif
}
else
{
share= old_info->s;
if (mode == O_RDWR && share->mode == O_RDONLY)
{
my_errno=EACCES; /* Can't open in write mode*/
goto err;
}
if ((info.dfile=my_open(fn_format(name_buff,old_info->filename,"",
N_NAME_DEXT,2+4),
mode | O_SHARE,MYF(MY_WME))) < 0)
{
my_errno=errno;
goto err;
}
errpos=5;
}
/* alloc and set up private structure parts */
if (!my_multi_malloc(MY_WME,
&m_info,sizeof(N_INFO),
&info.blobs,sizeof(N_BLOB)*share->base.blobs,
&info.buff,(share->base.max_block*2+
share->base.max_key_length),
&info.lastkey,share->base.max_key_length*3+1,
&info.filename,strlen(name)+1,
NullS))
goto err;
errpos=6;
strmov(info.filename,name);
memcpy(info.blobs,share->blobs,sizeof(N_BLOB)*share->base.blobs);
info.s=share;
info.lastpos= NI_POS_ERROR;
info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
info.opt_flag=READ_CHECK_USED;
info.alloced_rec_buff_length=share->base.pack_reclength;
info.this_uniq= (ulong) info.dfile; /* Uniq number in process */
info.this_loop=0; /* Update counter */
info.last_uniq= share->state.uniq;
info.last_loop= share->state.loop;
info.options=share->base.options |
(mode == O_RDONLY ? HA_OPTION_READ_ONLY_DATA : 0);
info.lock_type=F_UNLCK;
info.errkey= -1;
pthread_mutex_lock(&share->intern_lock);
info.read_record=share->read_record;
share->reopen++;
if (share->base.options & HA_OPTION_READ_ONLY_DATA)
{
info.lock_type=F_RDLCK;
share->r_locks++;
info.this_uniq=share->state.uniq; /* Row checksum */
}
#ifndef NO_LOCKING
if (handle_locking & HA_OPEN_TMP_TABLE)
#endif
{
share->w_locks++; /* We don't have to update status */
info.lock_type=F_WRLCK;
}
pthread_mutex_unlock(&share->intern_lock);
/* Allocate buffer for one record */
extra=0;
if (share->base.options & HA_OPTION_PACK_RECORD)
extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
DYN_DELETE_BLOCK_HEADER;
if (!(info.rec_alloc=(byte*) my_malloc(share->base.pack_reclength+extra+
6,
MYF(MY_WME | MY_ZEROFILL))))
goto err;
if (extra)
info.rec_buff=info.rec_alloc+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER);
else
info.rec_buff=info.rec_alloc;
*m_info=info;
#ifdef THREAD
thr_lock_data_init(&share->lock,&m_info->lock,NULL);
#endif
m_info->open_list.data=(void*) m_info;
nisam_open_list=list_add(nisam_open_list,&m_info->open_list);
pthread_mutex_unlock(&THR_LOCK_isam);
nisam_log_simple(LOG_OPEN,m_info,share->filename,
(uint) strlen(share->filename));
DBUG_RETURN(m_info);
err:
save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
switch (errpos) {
case 6:
my_free((gptr) m_info,MYF(0));
/* fall through */
case 5:
VOID(my_close(info.dfile,MYF(0)));
if (old_info)
break; /* Don't remove open table */
/* fall through */
case 4:
my_free((gptr) share,MYF(0));
/* fall through */
case 3:
#ifndef NO_LOCKING
if (! lock_error)
VOID(my_lock(kfile, F_UNLCK, 0L, F_TO_EOF, MYF(MY_SEEK_NOT_DONE)));
#endif
/* fall through */
case 2:
my_afree((gptr) disk_cache);
/* fall through */
case 1:
VOID(my_close(kfile,MYF(0)));
/* fall through */
case 0:
default:
break;
}
pthread_mutex_unlock(&THR_LOCK_isam);
my_errno=save_errno;
DBUG_RETURN (NULL);
} /* nisam_open */
/* Set up functions in structs */
static void setup_functions(register ISAM_SHARE *share)
{
if (share->base.options & HA_OPTION_COMPRESS_RECORD)
{
share->read_record=_nisam_read_pack_record;
share->read_rnd=_nisam_read_rnd_pack_record;
}
else if (share->base.options & HA_OPTION_PACK_RECORD)
{
share->read_record=_nisam_read_dynamic_record;
share->read_rnd=_nisam_read_rnd_dynamic_record;
share->delete_record=_nisam_delete_dynamic_record;
share->compare_record=_nisam_cmp_dynamic_record;
/* add bits used to pack data to pack_reclength for faster allocation */
share->base.pack_reclength+= share->base.pack_bits;
if (share->base.blobs)
{
share->update_record=_nisam_update_blob_record;
share->write_record=_nisam_write_blob_record;
}
else
{
share->write_record=_nisam_write_dynamic_record;
share->update_record=_nisam_update_dynamic_record;
}
}
else
{
share->read_record=_nisam_read_static_record;
share->read_rnd=_nisam_read_rnd_static_record;
share->delete_record=_nisam_delete_static_record;
share->compare_record=_nisam_cmp_static_record;
share->update_record=_nisam_update_static_record;
share->write_record=_nisam_write_static_record;
}
return;
}
static void setup_key_functions(register N_KEYDEF *keyinfo)
{
if (keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED))
{
keyinfo->bin_search=_nisam_seq_search;
keyinfo->get_key=_nisam_get_key;
}
else
{
keyinfo->bin_search=_nisam_bin_search;
keyinfo->get_key=_nisam_get_static_key;
}
return;
}
/*
Calculate a long checksum for a memoryblock. Used to verify pack_isam
SYNOPSIS
checksum()
mem Pointer to memory block
count Count of bytes
*/
ulong _nisam_checksum(const byte *mem, uint count)
{
ulong crc;
for (crc= 0; count-- ; mem++)
crc= ((crc << 1) + *((uchar*) mem)) +
test(crc & ((ulong) 1L << (8*sizeof(ulong)-1)));
return crc;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,135 +0,0 @@
/* 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 */
#include "isamdef.h"
/* if flag == HA_PANIC_CLOSE then all misam files are closed */
/* if flag == HA_PANIC_WRITE then all misam files are unlocked and
all changed data in single user misam is written to file */
/* if flag == HA_PANIC_READ then all misam files that was locked when
nisam_panic(HA_PANIC_WRITE) was done is locked. A ni_readinfo() is
done for all single user files to get changes in database */
int nisam_panic(enum ha_panic_function flag)
{
int error=0;
LIST *list_element,*next_open;
N_INFO *info;
DBUG_ENTER("nisam_panic");
pthread_mutex_lock(&THR_LOCK_isam);
for (list_element=nisam_open_list ; list_element ; list_element=next_open)
{
next_open=list_element->next; /* Save if close */
info=(N_INFO*) list_element->data;
switch (flag) {
case HA_PANIC_CLOSE:
pthread_mutex_unlock(&THR_LOCK_isam); /* Not exactly right... */
if (nisam_close(info))
error=my_errno;
pthread_mutex_lock(&THR_LOCK_isam);
break;
case HA_PANIC_WRITE: /* Do this to free databases */
#ifdef CANT_OPEN_FILES_TWICE
if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
break;
#endif
if (flush_key_blocks(dflt_key_cache,info->s->kfile,FLUSH_RELEASE))
error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache))
error=my_errno;
if (info->opt_flag & READ_CACHE_USED)
{
if (flush_io_cache(&info->rec_cache))
error=my_errno;
reinit_io_cache(&info->rec_cache,READ_CACHE,0,
(pbool) (info->lock_type != F_UNLCK),1);
}
#ifndef NO_LOCKING
if (info->lock_type != F_UNLCK && ! info->was_locked)
{
info->was_locked=info->lock_type;
if (nisam_lock_database(info,F_UNLCK))
error=my_errno;
}
#else
{
int save_status=info->s->w_locks; /* Only w_locks! */
info->s->w_locks=0;
if (_nisam_writeinfo(info, test(info->update & HA_STATE_CHANGED)))
error=my_errno;
info->s->w_locks=save_status;
info->update&= ~HA_STATE_CHANGED; /* Not changed */
}
#endif /* NO_LOCKING */
#ifdef CANT_OPEN_FILES_TWICE
if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0)))
error = my_errno;
if (info->dfile >= 0 && my_close(info->dfile,MYF(0)))
error = my_errno;
info->s->kfile=info->dfile= -1; /* Files aren't open anymore */
break;
#endif
case HA_PANIC_READ: /* Restore to before WRITE */
#ifdef CANT_OPEN_FILES_TWICE
{ /* Open closed files */
char name_buff[FN_REFLEN];
if (info->s->kfile < 0)
if ((info->s->kfile= my_open(fn_format(name_buff,info->filename,"",
N_NAME_IEXT,4),info->mode,
MYF(MY_WME))) < 0)
error = my_errno;
if (info->dfile < 0)
{
if ((info->dfile= my_open(fn_format(name_buff,info->filename,"",
N_NAME_DEXT,4),info->mode,
MYF(MY_WME))) < 0)
error = my_errno;
info->rec_cache.file=info->dfile;
}
}
#endif
#ifndef NO_LOCKING
if (info->was_locked)
{
if (nisam_lock_database(info, info->was_locked))
error=my_errno;
info->was_locked=0;
}
#else
{
int lock_type,w_locks;
lock_type=info->lock_type ; w_locks=info->s->w_locks;
info->lock_type=0; info->s->w_locks=0;
if (_nisam_readinfo(info,0,1)) /* Read changed data */
error=my_errno;
info->lock_type=lock_type; info->s->w_locks=w_locks;
}
/* Don't use buffer when doing next */
info->update|=HA_STATE_WRITTEN;
#endif /* NO_LOCKING */
break;
}
}
if (flag == HA_PANIC_CLOSE)
VOID(nisam_log(0)); /* Close log if neaded */
pthread_mutex_unlock(&THR_LOCK_isam);
if (!error) DBUG_RETURN(0);
my_errno=error;
DBUG_RETURN(-1);
} /* nisam_panic */

View File

@ -1,191 +0,0 @@
/* 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 */
/*
Gives a approximated number of how many records there is between two keys.
Used when optimizing querries.
*/
#include "isamdef.h"
static ulong _nisam_record_pos(N_INFO *info,const byte *key,uint key_len,
enum ha_rkey_function search_flag);
static double _nisam_search_pos(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
uint key_len,uint nextflag,ulong pos);
static uint _nisam_keynr(N_INFO *info,N_KEYDEF *keyinfo,uchar *page,
uchar *keypos,uint *ret_max_key);
/* If start_key = 0 assume read from start */
/* If end_key = 0 assume read to end */
/* Returns NI_POS_ERROR on error */
ulong nisam_records_in_range(N_INFO *info, int inx, const byte *start_key,
uint start_key_len,
enum ha_rkey_function start_search_flag,
const byte *end_key, uint end_key_len,
enum ha_rkey_function end_search_flag)
{
ulong start_pos,end_pos;
DBUG_ENTER("nisam_records_in_range");
if ((inx = _nisam_check_index(info,inx)) < 0)
DBUG_RETURN(NI_POS_ERROR);
#ifndef NO_LOCKING
if (_nisam_readinfo(info,F_RDLCK,1))
DBUG_RETURN(NI_POS_ERROR);
#endif
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
start_pos= (start_key ?
_nisam_record_pos(info,start_key,start_key_len,start_search_flag) :
0L);
end_pos= (end_key ?
_nisam_record_pos(info,end_key,end_key_len,end_search_flag) :
info->s->state.records+1L);
VOID(_nisam_writeinfo(info,0));
if (start_pos == NI_POS_ERROR || end_pos == NI_POS_ERROR)
DBUG_RETURN(NI_POS_ERROR);
DBUG_PRINT("info",("records: %ld",end_pos-start_pos));
DBUG_RETURN(end_pos < start_pos ? 0L :
(end_pos == start_pos ? 1L : end_pos-start_pos));
}
/* Find relative position (in records) for key in index-tree */
static ulong _nisam_record_pos(N_INFO *info, const byte *key, uint key_len,
enum ha_rkey_function search_flag)
{
uint inx=(uint) info->lastinx;
N_KEYDEF *keyinfo=info->s->keyinfo+inx;
uchar *key_buff;
double pos;
DBUG_ENTER("_nisam_record_pos");
DBUG_PRINT("enter",("search_flag: %d",search_flag));
if (key_len >= (keyinfo->base.keylength-info->s->rec_reflength)
&& !(keyinfo->base.flag & HA_SPACE_PACK_USED))
key_len=USE_HOLE_KEY;
key_buff=info->lastkey+info->s->base.max_key_length;
key_len=_nisam_pack_key(info,inx,key_buff,(uchar*) key,key_len);
DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,
(uchar*) key_buff););
pos=_nisam_search_pos(info,keyinfo,key_buff,key_len,
nisam_read_vec[search_flag] | SEARCH_SAVE_BUFF,
info->s->state.key_root[inx]);
if (pos >= 0.0)
{
DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->s->state.records)));
DBUG_RETURN((ulong) (pos*info->s->state.records+0.5));
}
DBUG_RETURN(NI_POS_ERROR);
}
/* This is a modified version of _nisam_search */
/* Returns offset for key in indextable (decimal 0.0 <= x <= 1.0) */
static double _nisam_search_pos(register N_INFO *info, register N_KEYDEF *keyinfo,
uchar *key, uint key_len, uint nextflag,
register ulong pos)
{
int flag;
uint nod_flag,keynr,max_keynr;
uchar *keypos,*buff;
double offset;
DBUG_ENTER("_nisam_search_pos");
if (pos == NI_POS_ERROR)
DBUG_RETURN(0.5);
if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,1)))
goto err;
flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
&keypos,info->lastkey);
nod_flag=test_if_nod(buff);
keynr=_nisam_keynr(info,keyinfo,buff,keypos,&max_keynr);
if (flag)
{
/*
** Didn't found match. keypos points at next (bigger) key
* Try to find a smaller, better matching key.
** Matches keynr + [0-1]
*/
if ((offset=_nisam_search_pos(info,keyinfo,key,key_len,nextflag,
_nisam_kpos(nod_flag,keypos))) < 0)
DBUG_RETURN(offset);
}
else
{
/*
** Found match. Keypos points at the start of the found key
** Matches keynr+1
*/
offset=1.0; /* Matches keynr+1 */
if (nextflag & SEARCH_FIND && (!(keyinfo->base.flag & HA_NOSAME)
|| key_len) && nod_flag)
{
/*
** There may be identical keys in the tree. Try to match on of those.
** Matches keynr + [0-1]
*/
if ((offset=_nisam_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
_nisam_kpos(nod_flag,keypos))) < 0)
DBUG_RETURN(offset); /* Read error */
}
}
DBUG_PRINT("info",("keynr: %d offset: %g max_keynr: %d nod: %d flag: %d",
keynr,offset,max_keynr,nod_flag,flag));
DBUG_RETURN((keynr+offset)/(max_keynr+1));
err:
DBUG_PRINT("exit",("Error: %d",my_errno));
DBUG_RETURN (-1.0);
}
/* Get keynummer of current key and max number of keys in nod */
static uint _nisam_keynr(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page, uchar *keypos, uint *ret_max_key)
{
uint nod_flag,keynr,max_key;
uchar t_buff[N_MAX_KEY_BUFF],*end;
end= page+getint(page);
nod_flag=test_if_nod(page);
page+=2+nod_flag;
if (!(keyinfo->base.flag &
(HA_PACK_KEY | HA_SPACE_PACK | HA_SPACE_PACK_USED)))
{
*ret_max_key= (uint) (end-page)/(keyinfo->base.keylength+nod_flag);
return (uint) (keypos-page)/(keyinfo->base.keylength+nod_flag);
}
max_key=keynr=0;
while (page < end)
{
t_buff[0]=0; /* Don't move packed key */
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff));
max_key++;
if (page == keypos)
keynr=max_key;
}
*ret_max_key=max_key;
return(keynr);
}

View File

@ -1,34 +0,0 @@
/* 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 f|rsta posten som har samma isam-nyckel */
#include "isamdef.h"
/*
L{ser f|rsta posten med samma isamnyckel som f|reg}ende l{sning.
Man kan ha gjort write, update eller delete p} f|reg}ende post.
OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
*/
int nisam_rfirst(N_INFO *info, byte *buf, int inx)
{
DBUG_ENTER("nisam_rfirst");
info->lastpos= NI_POS_ERROR;
info->update|= HA_STATE_PREV_FOUND;
DBUG_RETURN(nisam_rnext(info,buf,inx));
} /* nisam_rfirst */

View File

@ -1,63 +0,0 @@
/* 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 p} basen av en isam_nyckel */
#include "isamdef.h"
/* Read a record using key */
/* Ordinary search_flag is 0 ; Give error if no record with key */
int nisam_rkey(N_INFO *info, byte *buf, int inx, const byte *key, uint key_len, enum ha_rkey_function search_flag)
{
uchar *key_buff;
ISAM_SHARE *share=info->s;
DBUG_ENTER("nisam_rkey");
DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d",
info,inx,search_flag));
if ((inx = _nisam_check_index(info,inx)) < 0)
DBUG_RETURN(-1);
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
if (key_len >= (share->keyinfo[inx].base.keylength - share->rec_reflength)
&& !(info->s->keyinfo[inx].base.flag & HA_SPACE_PACK_USED))
key_len=USE_HOLE_KEY;
key_buff=info->lastkey+info->s->base.max_key_length;
key_len=_nisam_pack_key(info,(uint) inx,key_buff,(uchar*) key,key_len);
DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,share->keyinfo[inx].seg,
(uchar*) key););
#ifndef NO_LOCKING
if (_nisam_readinfo(info,F_RDLCK,1))
goto err;
#endif
VOID(_nisam_search(info,info->s->keyinfo+inx,key_buff,key_len,
nisam_read_vec[search_flag],info->s->state.key_root[inx]));
if ((*info->read_record)(info,info->lastpos,buf) >= 0)
{
info->update|= HA_STATE_AKTIV; /* Record is read */
DBUG_RETURN(0);
}
info->lastpos = NI_POS_ERROR; /* Didn't find key */
VOID(_nisam_move_key(info->s->keyinfo+inx,info->lastkey,key_buff));
if (search_flag == HA_READ_AFTER_KEY)
info->update|=HA_STATE_NEXT_FOUND; /* Previous gives last row */
err:
DBUG_RETURN(-1);
} /* nisam_rkey */

View File

@ -1,34 +0,0 @@
/* 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 sista posten som har samma isam-nyckel */
#include "isamdef.h"
/*
L{ser sista posten med samma isamnyckel som f|reg}ende l{sning.
Man kan ha gjort write, update eller delete p} f|reg}ende post.
OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
*/
int nisam_rlast(N_INFO *info, byte *buf, int inx)
{
DBUG_ENTER("nisam_rlast");
info->lastpos= NI_POS_ERROR;
info->update|= HA_STATE_NEXT_FOUND;
DBUG_RETURN(nisam_rprev(info,buf,inx));
} /* nisam_rlast */

View File

@ -1,67 +0,0 @@
/* 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 n{sta post med samma isam-nyckel */
#include "isamdef.h"
/*
L{ser n{sta post med samma isamnyckel som f|reg}ende l{sning.
Man kan ha gjort write, update eller delete p} f|reg}ende post.
OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
*/
int nisam_rnext(N_INFO *info, byte *buf, int inx)
{
int error,changed;
uint flag;
DBUG_ENTER("nisam_rnext");
if ((inx = _nisam_check_index(info,inx)) < 0)
DBUG_RETURN(-1);
flag=SEARCH_BIGGER; /* Read next */
if (info->lastpos == NI_POS_ERROR && info->update & HA_STATE_PREV_FOUND)
flag=0; /* Read first */
#ifndef NO_LOCKING
if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1);
#endif
changed=_nisam_test_if_changed(info);
if (!flag)
error=_nisam_search_first(info,info->s->keyinfo+inx,
info->s->state.key_root[inx]);
else if (!changed)
error=_nisam_search_next(info,info->s->keyinfo+inx,info->lastkey,flag,
info->s->state.key_root[inx]);
else
error=_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,flag,
info->s->state.key_root[inx]);
/* Don't clear if database-changed */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |
HA_STATE_BUFF_SAVED);
info->update|= HA_STATE_NEXT_FOUND;
if (error && my_errno == HA_ERR_KEY_NOT_FOUND)
my_errno=HA_ERR_END_OF_FILE;
if ((*info->read_record)(info,info->lastpos,buf) >=0)
{
info->update|= HA_STATE_AKTIV; /* Record is read */
DBUG_RETURN(0);
}
DBUG_RETURN(-1);
} /* nisam_rnext */

View File

@ -1,64 +0,0 @@
/* 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 f|reg}ende post med samma isam-nyckel */
#include "isamdef.h"
/*
L{ser f|reg}ende post med samma isamnyckel som f|reg}ende l{sning.
Man kan ha gjort write, update eller delete p} f|reg}ende post.
OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
*/
int nisam_rprev(N_INFO *info, byte *buf, int inx)
{
int error,changed;
register uint flag;
DBUG_ENTER("nisam_rprev");
if ((inx = _nisam_check_index(info,inx)) < 0)
DBUG_RETURN(-1);
flag=SEARCH_SMALLER; /* Read previous */
if (info->lastpos == NI_POS_ERROR && info->update & HA_STATE_NEXT_FOUND)
flag=0; /* Read last */
#ifndef NO_LOCKING
if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1);
#endif
changed=_nisam_test_if_changed(info);
if (!flag)
error=_nisam_search_last(info,info->s->keyinfo+inx,info->s->state.key_root[inx]);
else if (!changed)
error=_nisam_search_next(info,info->s->keyinfo+inx,info->lastkey,flag,
info->s->state.key_root[inx]);
else
error=_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,flag,
info->s->state.key_root[inx]);
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |
HA_STATE_BUFF_SAVED);
info->update|= HA_STATE_PREV_FOUND;
if (error && my_errno == HA_ERR_KEY_NOT_FOUND)
my_errno=HA_ERR_END_OF_FILE;
if ((*info->read_record)(info,info->lastpos,buf) >=0)
{
info->update|= HA_STATE_AKTIV; /* Record is read */
DBUG_RETURN(0);
}
DBUG_RETURN(-1);
} /* nisam_rprev */

View File

@ -1,55 +0,0 @@
/* 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 */
/* Read a record with random-access. The position to the record must
get by N_INFO. The next record can be read with pos= -1 */
#include "isamdef.h"
/*
If filepos == NI_POS_ERROR, read next
Returns:
0 = Ok.
1 = Row was deleted
-1 = EOF (check errno to verify)
*/
int nisam_rrnd(N_INFO *info, byte *buf, register ulong filepos)
{
int skipp_deleted_blocks;
DBUG_ENTER("nisam_rrnd");
skipp_deleted_blocks=0;
if (filepos == NI_POS_ERROR)
{
skipp_deleted_blocks=1;
if (info->lastpos == NI_POS_ERROR) /* First read ? */
filepos= info->s->pack.header_length; /* Read first record */
else
filepos= info->nextpos;
}
info->lastinx= -1; /* Can't forward or backward */
/* Init all but update-flag */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache))
DBUG_RETURN(my_errno);
DBUG_RETURN ((*info->s->read_rnd)(info,buf,filepos,skipp_deleted_blocks));
}

View File

@ -1,70 +0,0 @@
/* 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 nuvarande record med direktl{sning */
/* Klarar b}de poster l{sta med nyckel och rrnd. */
#include "isamdef.h"
/* Funktionen ger som resultat:
0 = Ok.
1 = Posten borttagen
-1 = EOF (eller motsvarande: se errno) */
int nisam_rsame(N_INFO *info, byte *record, int inx)
/* If inx >= 0 find record using key */
{
DBUG_ENTER("nisam_rsame");
if (inx >= (int) info->s->state.keys || inx < -1)
{
my_errno=HA_ERR_WRONG_INDEX;
DBUG_RETURN(-1);
}
if (info->lastpos == NI_POS_ERROR || info->update & HA_STATE_DELETED)
{
my_errno=HA_ERR_KEY_NOT_FOUND; /* No current record */
DBUG_RETURN(-1);
}
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
/* L{s record fr}n datafilen */
#ifndef NO_LOCKING
if (_nisam_readinfo(info,F_RDLCK,1))
DBUG_RETURN(-1);
#endif
if (inx >= 0)
{
info->lastinx=inx;
VOID(_nisam_make_key(info,(uint) inx,info->lastkey,record,info->lastpos));
VOID(_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,SEARCH_SAME,
info->s->state.key_root[inx]));
}
if ((*info->read_record)(info,info->lastpos,record) == 0)
DBUG_RETURN(0);
if (my_errno == HA_ERR_RECORD_DELETED)
{
my_errno=HA_ERR_KEY_NOT_FOUND;
DBUG_RETURN(1);
}
DBUG_RETURN(-1);
} /* nisam_rsame */

View File

@ -1,59 +0,0 @@
/* 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 */
/* read record through position and fix key-position */
/* As nisam_rsame but supply a position */
#include "isamdef.h"
/*
** If inx >= 0 update index pointer
** Returns one of the following values:
** 0 = Ok.
** 1 = Record deleted
** -1 = EOF (or something similar. More information in my_errno)
*/
int nisam_rsame_with_pos(N_INFO *info, byte *record, int inx, ulong filepos)
{
DBUG_ENTER("nisam_rsame_with_pos");
if (inx >= (int) info->s->state.keys || inx < -1)
{
my_errno=HA_ERR_WRONG_INDEX;
DBUG_RETURN(-1);
}
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
if ((*info->s->read_rnd)(info,record,filepos,0))
{
if (my_errno == HA_ERR_RECORD_DELETED)
{
my_errno=HA_ERR_KEY_NOT_FOUND;
DBUG_RETURN(1);
}
DBUG_RETURN(-1);
}
info->lastpos=filepos;
info->lastinx=inx;
if (inx >= 0)
{
VOID(_nisam_make_key(info,(uint) inx,info->lastkey,record,info->lastpos));
info->update|=HA_STATE_KEY_CHANGED; /* Don't use indexposition */
}
DBUG_RETURN(0);
} /* nisam_rsame_pos */

View File

@ -1,558 +0,0 @@
/* 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 */
/*
Creates a index for a database by reading keys, sorting them and outputing
them in sorted order through SORT_INFO functions.
*/
#include "isamdef.h"
#if defined(MSDOS) || defined(__WIN__)
#include <fcntl.h>
#else
#include <stddef.h>
#endif
#include <queues.h>
/* static variabels */
#define MERGEBUFF 15
#define MERGEBUFF2 31
#define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD)
#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */
my_off_t file_pos; /* Position var bufferten finns */
ulong count; /* Antal nycklar i bufferten */
uchar *base,*key; /* Pekare inom sort_key - indexdel */
uint mem_count; /* Antal nycklar kvar i minnet */
uint max_keys; /* Max keys in buffert */
} BUFFPEK;
extern void print_error _VARARGS((const char *fmt,...));
/* functions defined in this file */
static ulong NEAR_F find_all_keys(SORT_PARAM *info,uint keys,
uchar * *sort_keys,
BUFFPEK *buffpek,int *maxbuffer,
FILE **tempfile, my_string tempname);
static int NEAR_F write_keys(SORT_PARAM *info,uchar * *sort_keys,
uint count, BUFFPEK *buffpek,FILE **tempfile,
my_string tempname);
static int NEAR_F write_index(SORT_PARAM *info,uchar * *sort_keys,
uint count);
static int NEAR_F merge_many_buff(SORT_PARAM *info,uint keys,
uchar * *sort_keys,
BUFFPEK *buffpek,int *maxbuffer,
FILE * *t_file, my_string tempname);
static uint NEAR_F read_to_buffer(FILE *fromfile,BUFFPEK *buffpek,
uint sort_length);
static int NEAR_F merge_buffers(SORT_PARAM *info,uint keys,FILE *from_file,
FILE *to_file, uchar * *sort_keys,
BUFFPEK *lastbuff,BUFFPEK *Fb,
BUFFPEK *Tb);
static int NEAR_F merge_index(SORT_PARAM *,uint,uchar **,BUFFPEK *, int,
FILE *);
static char **make_char_array(uint fields,uint length,myf my_flag);
static FILE *opentemp(my_string name);
static void closetemp(char *name,FILE *stream);
/* Creates a index of sorted keys */
/* Returns 0 if everything went ok */
int _create_index_by_sort(info,no_messages,sortbuff_size)
SORT_PARAM *info;
pbool no_messages;
uint sortbuff_size;
{
int error,maxbuffer,skr;
uint memavl,old_memavl,keys,sort_length;
BUFFPEK *buffpek;
char tempname[FN_REFLEN];
ulong records;
uchar **sort_keys;
FILE *tempfile;
DBUG_ENTER("_create_index_by_sort");
tempfile=0; buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1;
maxbuffer=1;
memavl=max(sortbuff_size,MIN_SORT_MEMORY);
records= info->max_records;
sort_length= info->key_length;
LINT_INIT(keys);
while (memavl >= MIN_SORT_MEMORY)
{
if ((records+1)*(sort_length+sizeof(char*)) < (ulong) memavl)
keys= records+1;
else
do
{
skr=maxbuffer;
if (memavl < sizeof(BUFFPEK)*(uint) maxbuffer ||
(keys=(memavl-sizeof(BUFFPEK)*(uint) maxbuffer)/
(sort_length+sizeof(char*))) <= 1)
{
print_error("Sortbuffer to small");
goto err;
}
}
while ((maxbuffer= (int) (records/(keys-1)+1)) != skr);
if ((sort_keys= (uchar **) make_char_array(keys,sort_length,MYF(0))))
{
if ((buffpek = (BUFFPEK*) my_malloc((uint) (sizeof(BUFFPEK)*
(uint) maxbuffer),
MYF(0))))
break;
else
my_free((gptr) sort_keys,MYF(0));
}
old_memavl=memavl;
if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY)
memavl=MIN_SORT_MEMORY;
}
if (memavl < MIN_SORT_MEMORY)
{
print_error("Sortbuffer to small");
goto err;
}
(*info->lock_in_memory)(); /* Everything is allocated */
if (!no_messages)
printf(" - Searching for keys, allocating buffer for %d keys\n",keys);
if ((records=find_all_keys(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile,
tempname))
== (ulong) -1)
goto err;
if (maxbuffer == 0)
{
if (!no_messages)
printf(" - Dumping %lu keys\n",records);
if (write_index(info,sort_keys,(uint) records))
goto err;
}
else
{
keys=(keys*(sort_length+sizeof(char*)))/sort_length;
if (maxbuffer >= MERGEBUFF2)
{
if (!no_messages)
printf(" - Merging %lu keys\n",records);
if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile,
tempname))
goto err;
}
if (!no_messages)
puts(" - Last merge and dumping keys");
if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,tempfile))
goto err;
}
error =0;
err:
if (sort_keys)
my_free((gptr) sort_keys,MYF(0));
if (buffpek)
my_free((gptr) buffpek,MYF(0));
if (tempfile)
closetemp(tempname,tempfile);
DBUG_RETURN(error ? -1 : 0);
} /* _create_index_by_sort */
/* Search after all keys and place them in a temp. file */
static ulong NEAR_F find_all_keys(info,keys,sort_keys,buffpek,maxbuffer,
tempfile,tempname)
SORT_PARAM *info;
uint keys;
uchar **sort_keys;
BUFFPEK *buffpek;
int *maxbuffer;
FILE **tempfile;
my_string tempname;
{
int error;
uint index,indexpos;
DBUG_ENTER("find_all_keys");
index=indexpos=error=0;
while (!(error=(*info->key_read)(sort_keys[index])))
{
if ((uint) ++index == keys)
{
if (indexpos >= (uint) *maxbuffer ||
write_keys(info,sort_keys,index-1,buffpek+indexpos,tempfile,
tempname))
DBUG_RETURN(NI_POS_ERROR);
memcpy(sort_keys[0],sort_keys[index-1],(size_t) info->key_length);
index=1; indexpos++;
}
}
if (error > 0)
DBUG_RETURN(NI_POS_ERROR); /* Aborted by get_key */
if (indexpos)
if (indexpos >= (uint) *maxbuffer ||
write_keys(info,sort_keys,index,buffpek+indexpos,tempfile,tempname))
DBUG_RETURN(NI_POS_ERROR);
*maxbuffer=(int) indexpos;
DBUG_RETURN(indexpos*(keys-1)+index);
} /* find_all_keys */
/* Write all keys in memory to file for later merge */
static int NEAR_F write_keys(info,sort_keys,count,buffpek,tempfile,tempname)
SORT_PARAM *info;
reg1 uchar **sort_keys;
uint count;
BUFFPEK *buffpek;
reg2 FILE **tempfile;
my_string tempname;
{
DBUG_ENTER("write_keys");
qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp,
NullS);
if (! *tempfile && ! (*tempfile=opentemp(tempname)))
DBUG_RETURN(1);
buffpek->file_pos=my_ftell(*tempfile,MYF(0));
buffpek->count=count;
while (count--)
if (my_fwrite(*tempfile,(byte*)*sort_keys++,info->key_length,MYF_RW))
DBUG_RETURN(1);
DBUG_RETURN(0);
} /* write_keys */
/* Write index */
static int NEAR_F write_index(info,sort_keys,count)
SORT_PARAM *info;
reg1 uchar **sort_keys;
reg2 uint count;
{
DBUG_ENTER("write_index");
qsort2((gptr) sort_keys,(size_t) count,sizeof(byte*),
(qsort2_cmp) info->key_cmp, NullS);
while (count--)
if ((*info->key_write)(*sort_keys++))
DBUG_RETURN(-1);
DBUG_RETURN(0);
} /* write_index */
/* Merge buffers to make < MERGEBUFF2 buffers */
static int NEAR_F merge_many_buff(info,keys,sort_keys,buffpek,maxbuffer,t_file,
t_name)
SORT_PARAM *info;
uint keys;
uchar **sort_keys;
int *maxbuffer;
BUFFPEK *buffpek;
FILE **t_file;
my_string t_name;
{
register int i;
FILE *from_file,*to_file,*temp;
FILE *t_file2;
char t_name2[FN_REFLEN];
BUFFPEK *lastbuff;
DBUG_ENTER("merge_many_buff");
if (!(t_file2=opentemp(t_name2)))
DBUG_RETURN(1);
from_file= *t_file ; to_file= t_file2;
while (*maxbuffer >= MERGEBUFF2)
{
lastbuff=buffpek;
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
{
if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
buffpek+i,buffpek+i+MERGEBUFF-1))
break;
}
if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
buffpek+i,buffpek+ *maxbuffer))
break;
*maxbuffer= (int) (lastbuff-buffpek)-1;
temp=from_file; from_file=to_file; to_file=temp;
VOID(my_fseek(to_file,0L,MY_SEEK_SET,MYF(0)));
}
if (to_file == *t_file)
{
closetemp(t_name,to_file);
*t_file=t_file2;
VOID(strmov(t_name,t_name2));
}
else closetemp(t_name2,to_file);
DBUG_RETURN(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
} /* merge_many_buff */
/* Read data to buffer */
/* This returns (uint) -1 if something goes wrong */
static uint NEAR_F read_to_buffer(fromfile,buffpek,sort_length)
FILE *fromfile;
BUFFPEK *buffpek;
uint sort_length;
{
register uint count;
uint length;
if ((count=(uint) min((ulong) buffpek->max_keys,buffpek->count)))
{
VOID(my_fseek(fromfile,buffpek->file_pos,MY_SEEK_SET,MYF(0)));
if (my_fread(fromfile,(byte*) buffpek->base,
(length= sort_length*count),MYF_RW))
return((uint) -1);
buffpek->key=buffpek->base;
buffpek->file_pos+= length; /* New filepos */
buffpek->count-= count;
buffpek->mem_count= count;
}
return (count*sort_length);
} /* read_to_buffer */
/* Merge buffers to one buffer */
/* If to_file == 0 then use info->key_write */
static int NEAR_F merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff,
Fb,Tb)
SORT_PARAM *info;
uint keys;
FILE *from_file,*to_file;
uchar **sort_keys;
BUFFPEK *lastbuff,*Fb,*Tb;
{
int error;
uint sort_length,maxcount;
ulong count;
my_off_t to_start_filepos;
uchar *strpos;
BUFFPEK *buffpek,**refpek;
QUEUE queue;
DBUG_ENTER("merge_buffers");
count=error=0;
maxcount=keys/((uint) (Tb-Fb) +1);
sort_length=info->key_length;
LINT_INIT(to_start_filepos);
if (to_file)
to_start_filepos=my_ftell(to_file,MYF(0));
strpos=(uchar*) sort_keys;
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
(int (*)(void *, byte *,byte *)) info->key_cmp,0))
DBUG_RETURN(1);
for (buffpek= Fb ; buffpek <= Tb && error != -1 ; buffpek++)
{
count+= buffpek->count;
buffpek->base= strpos;
buffpek->max_keys=maxcount;
strpos+= (uint) (error=(int) read_to_buffer(from_file,buffpek,
sort_length));
queue_insert(&queue,(void*) buffpek);
}
if (error == -1)
goto err;
while (queue.elements > 1)
{
for (;;)
{
buffpek=(BUFFPEK*) queue_top(&queue);
if (to_file)
{
if (my_fwrite(to_file,(byte*) buffpek->key,(uint) sort_length,
MYF_RW | MY_WAIT_IF_FULL))
{
error=1; goto err;
}
}
else
{
if ((*info->key_write)((void*) buffpek->key))
{
error=1; goto err;
}
}
buffpek->key+=sort_length;
if (! --buffpek->mem_count)
{
if (!(error=(int) read_to_buffer(from_file,buffpek,sort_length)))
{
uchar *base=buffpek->base;
uint max_keys=buffpek->max_keys;
VOID(queue_remove(&queue,0));
/* Put room used by buffer to use in other buffer */
for (refpek= (BUFFPEK**) &queue_top(&queue);
refpek <= (BUFFPEK**) &queue_end(&queue);
refpek++)
{
buffpek= *refpek;
if (buffpek->base+buffpek->max_keys*sort_length == base)
{
buffpek->max_keys+=max_keys;
break;
}
else if (base+max_keys*sort_length == buffpek->base)
{
buffpek->base=base;
buffpek->max_keys+=max_keys;
break;
}
}
break; /* One buffer have been removed */
}
}
queue_replaced(&queue); /* Top element has been replaced */
}
}
buffpek=(BUFFPEK*) queue_top(&queue);
buffpek->base=(uchar *) sort_keys;
buffpek->max_keys=keys;
do
{
if (to_file)
{
if (my_fwrite(to_file,(byte*) buffpek->key,
(uint) (sort_length*buffpek->mem_count),
MYF_RW | MY_WAIT_IF_FULL))
{
error=1; goto err;
}
}
else
{
register uchar *end;
strpos= buffpek->key;
for (end=strpos+buffpek->mem_count*sort_length;
strpos != end ;
strpos+=sort_length)
{
if ((*info->key_write)((void*) strpos))
{
error=1; goto err;
}
}
}
}
while ((error=(int) read_to_buffer(from_file,buffpek,sort_length)) != -1 &&
error != 0);
lastbuff->count=count;
if (to_file)
lastbuff->file_pos=to_start_filepos; /* New block starts here */
err:
delete_queue(&queue);
DBUG_RETURN(error);
} /* merge_buffers */
/* Do a merge to output-file (save only positions) */
static int NEAR_F merge_index(info,keys,sort_keys,buffpek,maxbuffer,tempfile)
SORT_PARAM *info;
uint keys;
uchar **sort_keys;
BUFFPEK *buffpek;
int maxbuffer;
FILE *tempfile;
{
DBUG_ENTER("merge_index");
if (merge_buffers(info,keys,tempfile,(FILE*) 0,sort_keys,buffpek,buffpek,
buffpek+maxbuffer))
DBUG_RETURN(1);
DBUG_RETURN(0);
} /* merge_index */
/* Make a pointer of arrays to keys */
static char **make_char_array(fields,length,my_flag)
register uint fields;
uint length;
myf my_flag;
{
register char **pos;
char **old_pos,*char_pos;
DBUG_ENTER("make_char_array");
if ((old_pos= (char**) my_malloc( fields*(length+sizeof(char*)), my_flag)))
{
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
while (fields--)
*(pos++) = (char_pos+= length);
}
DBUG_RETURN(old_pos);
} /* make_char_array */
/* |ppnar en tempor{rfil som kommer att raderas efter anv{nding */
static FILE *opentemp(name)
my_string name;
{
FILE *stream;
reg1 my_string str_pos;
DBUG_ENTER("opentemp");
if (!(str_pos=my_tempnam(NullS,"ST",MYF(MY_WME))))
DBUG_RETURN(0);
VOID(strmov(name,str_pos));
(*free)(str_pos); /* Inte via vanliga malloc */
stream=my_fopen(name,(int) (O_RDWR | FILE_BINARY | O_CREAT | O_TEMPORARY),
MYF(MY_WME));
#if O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES)
VOID(my_delete(name,MYF(MY_WME | ME_NOINPUT)));
#endif
DBUG_PRINT("exit",("stream: %lx",stream));
DBUG_RETURN (stream);
} /* opentemp */
static void closetemp(char *name __attribute__((unused)) ,FILE *stream)
{
DBUG_ENTER("closetemp");
if (stream)
VOID(my_fclose(stream,MYF(MY_WME)));
#ifdef CANT_DELETE_OPEN_FILES
if (name)
VOID(my_delete(name,MYF(MY_WME)));
#endif
DBUG_VOID_RETURN;
} /* closetemp */

View File

@ -1,45 +0,0 @@
/* 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 */
/*
Static variables for ISAM library. All definied here for easy making of
a shared library
*/
#ifndef _global_h
#include "isamdef.h"
#endif
LIST *nisam_open_list=0;
uchar NEAR nisam_file_magic[]=
{ (uchar) 254, (uchar) 254,'\005', '\002', };
uchar NEAR nisam_pack_file_magic[]=
{ (uchar) 254, (uchar) 254,'\006', '\001', };
my_string nisam_log_filename= (char*) "isam.log";
File nisam_log_file= -1;
uint nisam_quick_table_bits=9;
uint nisam_block_size=1024; /* Best by test */
my_bool nisam_flush=0;
/* read_vec[] is used for converting between P_READ_KEY.. and SEARCH_ */
/* Position is , == , >= , <= , > , < */
uint NEAR nisam_read_vec[]=
{
SEARCH_FIND, SEARCH_FIND | SEARCH_BIGGER, SEARCH_FIND | SEARCH_SMALLER,
SEARCH_NO_FIND | SEARCH_BIGGER, SEARCH_NO_FIND | SEARCH_SMALLER,
SEARCH_FIND, SEARCH_LAST,SEARCH_LAST | SEARCH_SMALLER
};

View File

@ -1,179 +0,0 @@
/* 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 */
#include "isamdef.h"
static void get_options(int argc, char *argv[]);
static int rec_pointer_size=0,verbose=0,remove_ant=0,pack_keys=1,flags[50],
packed_field=FIELD_SKIP_PRESPACE;
int main(int argc, char *argv[])
{
N_INFO *file;
int i,j,error,deleted,found;
char record[128],key[32],*filename,read_record[128];
N_KEYDEF keyinfo[10];
N_RECINFO recinfo[10];
MY_INIT(argv[0]);
filename= (char*) "test1";
my_init();
get_options(argc,argv);
keyinfo[0].seg[0].base.type=HA_KEYTYPE_NUM;
keyinfo[0].seg[0].base.flag=(uint8) (pack_keys ?
HA_PACK_KEY | HA_SPACE_PACK : 0);
keyinfo[0].seg[0].base.start=0;
keyinfo[0].seg[0].base.length=6;
keyinfo[0].seg[1].base.type=HA_KEYTYPE_END;
keyinfo[0].base.flag = (uint8) (pack_keys ?
HA_NOSAME | HA_PACK_KEY : HA_NOSAME);
recinfo[0].base.type=packed_field; recinfo[0].base.length=6;
recinfo[1].base.type=FIELD_NORMAL; recinfo[1].base.length=24;
recinfo[2].base.type=FIELD_LAST;
deleted=0;
bzero((byte*) flags,sizeof(flags));
printf("- Creating isam-file\n");
if (nisam_create(filename,1,keyinfo,recinfo,
(ulong) (rec_pointer_size ? (1L << (rec_pointer_size*8))/40 :
0),10l,0,0,0L))
goto err;
if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
goto err;
printf("- Writing key:s\n");
strmov(record," ..... key"); strappend(record,30,' ');
my_errno=0;
for (i=49 ; i>=1 ; i-=2 )
{
j=i%25 +1;
sprintf(key,"%6d",j);
bmove(record,key,6);
error=nisam_write(file,record);
flags[j]=1;
if (verbose || error)
printf("J= %2d nisam_write: %d errno: %d\n", j,error,my_errno);
}
if (nisam_close(file)) goto err;
printf("- Reopening file\n");
if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED))) goto err;
printf("- Removing keys\n");
for (i=1 ; i<=10 ; i++)
{
if (i == remove_ant) { VOID(nisam_close(file)) ; exit(0) ; }
sprintf(key,"%6d",(j=(int) ((rand() & 32767)/32767.*25)));
my_errno=0;
if ((error = nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)))
{
if (verbose || (flags[j] == 1 ||
(error && my_errno != HA_ERR_KEY_NOT_FOUND)))
printf("key: %s nisam_rkey: %3d errno: %3d\n",key,error,my_errno);
}
else
{
error=nisam_delete(file,read_record);
if (verbose || error)
printf("key: %s nisam_delete: %3d errno: %3d\n",key,error,my_errno);
flags[j]=0;
if (! error)
deleted++;
}
}
printf("- Reading records with key\n");
for (i=1 ; i<=25 ; i++)
{
sprintf(key,"%6d",i);
bmove(record,key,6);
my_errno=0;
error=nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT);
if (verbose ||
(error == 0 && flags[i] != 1) ||
(error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))
{
printf("key: %s nisam_rkey: %3d errno: %3d record: %s\n",
key,error,my_errno,record+1);
}
}
printf("- Reading records with position\n");
for (i=1,found=0 ; i <= 30 ; i++)
{
my_errno=0;
if ((error=nisam_rrnd(file,read_record,i == 1 ? 0L : NI_POS_ERROR)) == -1)
{
if (found != 25-deleted)
printf("Found only %d of %d records\n",found,25-deleted);
break;
}
if (!error)
found++;
if (verbose || (error != 0 && error != 1))
{
printf("pos: %2d nisam_rrnd: %3d errno: %3d record: %s\n",
i-1,error,my_errno,read_record+1);
}
}
if (nisam_close(file)) goto err;
my_end(MY_CHECK_ERROR);
exit(0);
err:
printf("got error: %3d when using nisam-database\n",my_errno);
exit(1);
return 0; /* skip warning */
} /* main */
/* l{ser optioner */
/* OBS! intierar endast DEBUG - ingen debuggning h{r ! */
static void get_options(int argc, char *argv[])
{
char *pos;
while (--argc >0 && *(pos = *(++argv)) == '-' ) {
switch(*++pos) {
case 'R': /* Length of record pointer */
rec_pointer_size=atoi(++pos);
if (rec_pointer_size > 3)
rec_pointer_size=0;
break;
case 'P':
pack_keys=0; /* Don't use packed key */
break;
case 'S':
packed_field=FIELD_NORMAL; /* static-size record*/
break;
case 'v': /* verbose */
verbose=1;
break;
case 'm':
remove_ant=atoi(++pos);
break;
case 'V':
printf("isamtest1 Ver 1.0 \n");
exit(0);
case '#':
DEBUGGER_ON;
DBUG_PUSH (++pos);
break;
}
}
return;
} /* get options */

View File

@ -1,841 +0,0 @@
/* 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 */
/* Test av isam-databas: stor test */
#ifndef USE_MY_FUNC /* We want to be able to dbug this !! */
#define USE_MY_FUNC
#endif
#ifdef DBUG_OFF
#undef DBUG_OFF
#endif
#ifndef SAFEMALLOC
#define SAFEMALLOC
#endif
#include "isamdef.h"
#define STANDAR_LENGTH 37
#define NISAM_KEYS 6
#if !defined(MSDOS) && !defined(labs)
#define labs(a) abs(a)
#endif
static void get_options(int argc, char *argv[]);
static uint rnd(uint max_value);
static void fix_length(byte *record,uint length);
static void put_blob_in_record(char *blob_pos,char **blob_buffer);
static void copy_key(struct st_isam_info *info,uint inx,
uchar *record,uchar *key);
static int verbose=0,testflag=0,pack_type=HA_SPACE_PACK,
first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,locking=0,
rec_pointer_size=0,pack_fields=1,use_log=0;
static uint keys=NISAM_KEYS,recant=1000;
static uint use_blob=0;
static uint16 key1[1000],key3[5000];
static char record[300],record2[300],key[100],key2[100],
read_record[300],read_record2[300],read_record3[300];
/* Test program */
int main(int argc, char *argv[])
{
uint i;
int j,n1,n2,n3,error,k;
uint write_count,update,dupp_keys,opt_delete,start,length,blob_pos,
reclength,ant;
ulong lastpos,range_records,records;
N_INFO *file;
N_KEYDEF keyinfo[10];
N_RECINFO recinfo[10];
N_ISAMINFO info;
char *filename,*blob_buffer;
MY_INIT(argv[0]);
filename= (char*) "test2.ISM";
get_options(argc,argv);
if (! async_io)
my_disable_async_io=1;
reclength=STANDAR_LENGTH+60+(use_blob ? 8 : 0);
blob_pos=STANDAR_LENGTH+60;
keyinfo[0].seg[0].base.start=0;
keyinfo[0].seg[0].base.length=6;
keyinfo[0].seg[0].base.type=HA_KEYTYPE_TEXT;
keyinfo[0].seg[0].base.flag=(uint8) pack_type;
keyinfo[0].seg[1].base.type=0;
keyinfo[0].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
keyinfo[1].seg[0].base.start=7;
keyinfo[1].seg[0].base.length=6;
keyinfo[1].seg[0].base.type=HA_KEYTYPE_BINARY;
keyinfo[1].seg[0].base.flag=0;
keyinfo[1].seg[1].base.start=0; /* Tv}delad nyckel */
keyinfo[1].seg[1].base.length=6;
keyinfo[1].seg[1].base.type=HA_KEYTYPE_NUM;
keyinfo[1].seg[1].base.flag=HA_REVERSE_SORT;
keyinfo[1].seg[2].base.type=0;
keyinfo[1].base.flag =0;
keyinfo[2].seg[0].base.start=12;
keyinfo[2].seg[0].base.length=8;
keyinfo[2].seg[0].base.type=HA_KEYTYPE_BINARY;
keyinfo[2].seg[0].base.flag=HA_REVERSE_SORT;
keyinfo[2].seg[1].base.type=0;
keyinfo[2].base.flag =HA_NOSAME;
keyinfo[3].seg[0].base.start=0;
keyinfo[3].seg[0].base.length=reclength-(use_blob ? 8 : 0);
keyinfo[3].seg[0].base.type=HA_KEYTYPE_TEXT;
keyinfo[3].seg[0].base.flag=(uint8) pack_type;
keyinfo[3].seg[1].base.type=0;
keyinfo[3].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
keyinfo[4].seg[0].base.start=0;
keyinfo[4].seg[0].base.length=5;
keyinfo[4].seg[0].base.type=HA_KEYTYPE_TEXT;
keyinfo[4].seg[0].base.flag=0;
keyinfo[4].seg[1].base.type=0;
keyinfo[4].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
keyinfo[5].seg[0].base.start=0;
keyinfo[5].seg[0].base.length=4;
keyinfo[5].seg[0].base.type=HA_KEYTYPE_TEXT;
keyinfo[5].seg[0].base.flag=(uint8) pack_type;
keyinfo[5].seg[1].base.type=0;
keyinfo[5].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
recinfo[0].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[0].base.length=7;
recinfo[1].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[1].base.length=5;
recinfo[2].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[2].base.length=9;
recinfo[3].base.type=FIELD_NORMAL;
recinfo[3].base.length=STANDAR_LENGTH-7-5-9-4;
recinfo[4].base.type=pack_fields ? FIELD_SKIP_ZERO : 0;
recinfo[4].base.length=4;
recinfo[5].base.type=pack_fields ? FIELD_SKIP_ENDSPACE : 0;
recinfo[5].base.length=60;
if (use_blob)
{
recinfo[6].base.type=FIELD_BLOB;
recinfo[6].base.length=4+sizeof(char*); /* 4 byte ptr, 4 byte length */
recinfo[7].base.type= FIELD_LAST;
}
else
recinfo[6].base.type= FIELD_LAST;
write_count=update=dupp_keys=opt_delete=0;
blob_buffer=0;
for (i=999 ; i>0 ; i--) key1[i]=0;
for (i=4999 ; i>0 ; i--) key3[i]=0;
printf("- Creating isam-file\n");
/* DBUG_PUSH(""); */
my_delete(filename,MYF(0)); /* Remove old locks under gdb */
file= 0;
if (nisam_create(filename,keys,&keyinfo[first_key],&recinfo[0],
(ulong) (rec_pointer_size ? (1L << (rec_pointer_size*8))/
reclength : 0),100l,0,0,0L))
goto err;
if (use_log)
nisam_log(1);
if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
goto err;
printf("- Writing key:s\n");
if (key_cacheing)
init_key_cache(dflt_key_cache,512,IO_SIZE*16,0,0); /* Use a small cache */
if (locking)
nisam_lock_database(file,F_WRLCK);
if (write_cacheing)
nisam_extra(file,HA_EXTRA_WRITE_CACHE);
for (i=0 ; i < recant ; i++)
{
n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
sprintf(record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count);
longstore(record+STANDAR_LENGTH-4,(long) i);
fix_length(record,(uint) STANDAR_LENGTH+rnd(60));
put_blob_in_record(record+blob_pos,&blob_buffer);
DBUG_PRINT("test",("record: %d",i));
if (nisam_write(file,record))
{
if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
{
printf("Error: %d in write at record: %d\n",my_errno,i);
goto err;
}
if (verbose) printf(" Double key: %d\n",n3);
}
else
{
if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3)
{
printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
goto err;
}
write_count++; key1[n1]++; key3[n3]=1;
}
/* Check if we can find key without flushing database */
if (i == recant/2)
{
for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
if (!j)
for (j=999 ; j>0 && key1[j] == 0 ; j--) ;
sprintf(key,"%6d",j);
if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
{
printf("Test in loop: Can't find key: \"%s\"\n",key);
goto err;
}
}
}
if (testflag==1) goto end;
if (write_cacheing)
if (nisam_extra(file,HA_EXTRA_NO_CACHE))
{
puts("got error from nisam_extra(HA_EXTRA_NO_CACHE)");
goto end;
}
printf("- Delete\n");
for (i=0 ; i<recant/10 ; i++)
{
for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
if (j != 0)
{
sprintf(key,"%6d",j);
if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
{
printf("can't find key1: \"%s\"\n",key);
goto err;
}
if (nisam_delete(file,read_record))
{
printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record);
goto err;
}
opt_delete++;
key1[atoi(read_record+keyinfo[0].seg[0].base.start)]--;
key3[atoi(read_record+keyinfo[2].seg[0].base.start)]=0;
}
}
if (testflag==2) goto end;
printf("- Update\n");
for (i=0 ; i<recant/10 ; i++)
{
n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
sprintf(record2,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update);
longstore(record2+STANDAR_LENGTH-4,(long) i);
fix_length(record2,(uint) STANDAR_LENGTH+rnd(60));
for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
if (j != 0)
{
sprintf(key,"%6d",j);
if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
{
printf("can't find key1: \"%s\"\n",key);
goto err;
}
if (use_blob)
{
if (i & 1)
put_blob_in_record(record+blob_pos,&blob_buffer);
else
bmove(record+blob_pos,read_record+blob_pos,8);
}
if (nisam_update(file,read_record,record2))
{
if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
{
printf("error: %d; can't update:\nFrom: \"%s\"\nTo: \"%s\"\n",
my_errno,read_record,record2);
goto err;
}
if (verbose)
printf("Double key when tried to update:\nFrom: \"%s\"\nTo: \"%s\"\n",record,record2);
}
else
{
key1[atoi(read_record+keyinfo[0].seg[0].base.start)]--;
key3[atoi(read_record+keyinfo[2].seg[0].base.start)]=0;
key1[n1]++; key3[n3]=1;
update++;
}
}
}
if (testflag==3) goto end;
printf("- Same key: first - next -> last - prev -> first\n");
DBUG_PRINT("progpos",("first - next -> last - prev -> first"));
for (i=999, dupp_keys=j=0 ; i>0 ; i--)
{
if (key1[i] >dupp_keys) { dupp_keys=key1[i]; j=i; }
}
sprintf(key,"%6d",j);
if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys);
if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err;
if (nisam_rsame(file,read_record2,-1)) goto err;
if (memcmp(read_record,read_record2,reclength) != 0)
{
printf("nisam_rsame didn't find same record\n");
goto end;
}
nisam_info(file,&info,0);
if (nisam_rfirst(file,read_record2,0) ||
nisam_rsame_with_pos(file,read_record2,0,info.recpos) ||
memcmp(read_record,read_record2,reclength) != 0)
{
printf("nisam_rsame_with_pos didn't find same record\n");
goto end;
}
{
int skr=nisam_rnext(file,read_record2,0);
if ((skr && my_errno != HA_ERR_END_OF_FILE) ||
nisam_rprev(file,read_record2,-1) ||
memcmp(read_record,read_record2,reclength) != 0)
{
printf("nisam_rsame_with_pos lost position\n");
goto end;
}
}
ant=1;
start=keyinfo[0].seg[0].base.start; length=keyinfo[0].seg[0].base.length;
while (nisam_rnext(file,read_record2,0) == 0 &&
memcmp(read_record2+start,key,length) == 0) ant++;
if (ant != dupp_keys)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys);
goto end;
}
ant=0;
while (nisam_rprev(file,read_record3,0) == 0 &&
bcmp(read_record3+start,key,length) == 0) ant++;
if (ant != dupp_keys)
{
printf("prev: I can only find: %d records of %d\n",ant,dupp_keys);
goto end;
}
printf("- All keys: first - next -> last - prev -> first\n");
DBUG_PRINT("progpos",("All keys: first - next -> last - prev -> first"));
ant=1;
if (nisam_rfirst(file,read_record,0))
{
printf("Can't find first record\n");
goto end;
}
while (nisam_rnext(file,read_record3,0) == 0 && ant < write_count+10)
ant++;
if (ant != write_count - opt_delete)
{
printf("next: I found: %d records of %d\n",ant,write_count - opt_delete);
goto end;
}
if (nisam_rlast(file,read_record2,0) ||
bcmp(read_record2,read_record3,reclength))
{
printf("Can't find last record\n");
DBUG_DUMP("record2",(byte*) read_record2,reclength);
DBUG_DUMP("record3",(byte*) read_record3,reclength);
goto end;
}
ant=1;
while (nisam_rprev(file,read_record3,0) == 0 && ant < write_count+10)
ant++;
if (ant != write_count - opt_delete)
{
printf("prev: I found: %d records of %d\n",ant,write_count);
goto end;
}
if (bcmp(read_record,read_record3,reclength))
{
printf("Can't find first record\n");
goto end;
}
printf("- Test if: Read first - next - prev - prev - next == first\n");
DBUG_PRINT("progpos",("- Read first - next - prev - prev - next == first"));
if (nisam_rfirst(file,read_record,0) ||
nisam_rnext(file,read_record3,0) ||
nisam_rprev(file,read_record3,0) ||
nisam_rprev(file,read_record3,0) == 0 ||
nisam_rnext(file,read_record3,0))
goto err;
if (bcmp(read_record,read_record3,reclength) != 0)
printf("Can't find first record\n");
printf("- Test if: Read last - prev - next - next - prev == last\n");
DBUG_PRINT("progpos",("Read last - prev - next - next - prev == last"));
if (nisam_rlast(file,read_record2,0) ||
nisam_rprev(file,read_record3,0) ||
nisam_rnext(file,read_record3,0) ||
nisam_rnext(file,read_record3,0) == 0 ||
nisam_rprev(file,read_record3,0))
goto err;
if (bcmp(read_record2,read_record3,reclength))
printf("Can't find last record\n");
puts("- Test read key-part");
strmov(key2,key);
for(i=strlen(key2) ; i-- > 1 ;)
{
key2[i]=0;
if (nisam_rkey(file,read_record,0,key2,(uint) i,HA_READ_KEY_EXACT)) goto err;
if (bcmp(read_record+start,key,(uint) i))
{
puts("Didn't find right record");
goto end;
}
}
if (dupp_keys > 2)
{
printf("- Read key (first) - next - delete - next -> last\n");
DBUG_PRINT("progpos",("first - next - delete - next -> last"));
if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err;
if (nisam_rnext(file,read_record3,0)) goto err;
if (nisam_delete(file,read_record3)) goto err;
opt_delete++;
ant=1;
while (nisam_rnext(file,read_record3,0) == 0 &&
bcmp(read_record3+start,key,length) == 0) ant++;
if (ant != dupp_keys-1)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1);
goto end;
}
}
if (dupp_keys>4)
{
printf("- Read last of key - prev - delete - prev -> first\n");
DBUG_PRINT("progpos",("last - prev - delete - prev -> first"));
if (nisam_rprev(file,read_record3,0)) goto err;
if (nisam_rprev(file,read_record3,0)) goto err;
if (nisam_delete(file,read_record3)) goto err;
opt_delete++;
ant=1;
while (nisam_rprev(file,read_record3,0) == 0 &&
bcmp(read_record3+start,key,length) == 0) ant++;
if (ant != dupp_keys-2)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2);
goto end;
}
}
if (dupp_keys > 6)
{
printf("- Read first - delete - next -> last\n");
DBUG_PRINT("progpos",("first - delete - next -> last"));
if (nisam_rkey(file,read_record3,0,key,0,HA_READ_KEY_EXACT)) goto err;
if (nisam_delete(file,read_record3)) goto err;
opt_delete++;
ant=1;
if (nisam_rnext(file,read_record,0))
goto err; /* Skall finnas poster */
while (nisam_rnext(file,read_record3,0) == 0 &&
bcmp(read_record3+start,key,length) == 0) ant++;
if (ant != dupp_keys-3)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3);
goto end;
}
printf("- Read last - delete - prev -> first\n");
DBUG_PRINT("progpos",("last - delete - prev -> first"));
if (nisam_rprev(file,read_record3,0)) goto err;
if (nisam_delete(file,read_record3)) goto err;
opt_delete++;
ant=0;
while (nisam_rprev(file,read_record3,0) == 0 &&
bcmp(read_record3+start,key,length) == 0) ant++;
if (ant != dupp_keys-4)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4);
goto end;
}
}
puts("- Test if: Read rrnd - same");
DBUG_PRINT("progpos",("Read rrnd - same"));
for (i=0 ; i < write_count ; i++)
{
if (nisam_rrnd(file,read_record,i == 0 ? 0L : NI_POS_ERROR) == 0)
break;
}
if (i == write_count)
goto err;
bmove(read_record2,read_record,reclength);
for (i=2 ; i-- > 0 ;)
{
if (nisam_rsame(file,read_record2,(int) i)) goto err;
if (bcmp(read_record,read_record2,reclength) != 0)
{
printf("is_rsame didn't find same record\n");
goto end;
}
}
puts("- Test nisam_records_in_range");
nisam_info(file,&info,HA_STATUS_VARIABLE);
for (i=0 ; i < info.keys ; i++)
{
if (nisam_rfirst(file,read_record,(int) i) ||
nisam_rlast(file,read_record2,(int) i))
goto err;
copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key);
copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2);
range_records=nisam_records_in_range(file,(int) i,key,0,HA_READ_KEY_EXACT,
key2,0,HA_READ_AFTER_KEY);
if (range_records < info.records*8/10 ||
range_records > info.records*12/10)
{
printf("ni_records_range returned %lu; Should be about %lu\n",
range_records,info.records);
goto end;
}
if (verbose)
{
printf("ni_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n",
range_records,info.records,
labs((long) range_records - (long) info.records)*100.0/
info.records);
}
}
for (i=0 ; i < 5 ; i++)
{
for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
for (k=rnd(1000) ; k>0 && key1[k] == 0 ; k--) ;
if (j != 0 && k != 0)
{
if (j > k)
swap_variables(int, j, k);
sprintf(key,"%6d",j);
sprintf(key2,"%6d",k);
range_records=nisam_records_in_range(file,0,key,0,HA_READ_AFTER_KEY,
key2,0,HA_READ_BEFORE_KEY);
records=0;
for (j++ ; j < k ; j++)
records+=key1[j];
if ((long) range_records < (long) records*7/10-2 ||
(long) range_records > (long) records*13/10+2)
{
printf("ni_records_range returned %ld; Should be about %ld\n",
range_records,records);
goto end;
}
if (verbose && records)
{
printf("ni_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n",
range_records,records,
labs((long) range_records-(long) records)*100.0/records);
}
}
}
printf("- nisam_info\n");
nisam_info(file,&info,0);
if (info.records != write_count-opt_delete || info.deleted > opt_delete + update
|| info.keys != keys)
{
puts("Wrong info from nisam_info");
printf("Got: records: %ld opt_delete: %ld i_keys: %d\n",
info.records,info.deleted,info.keys);
}
if (verbose)
{
char buff[80];
get_date(buff,3,info.create_time);
printf("info: Created %s\n",buff);
get_date(buff,3,info.isamchk_time);
printf("info: checked %s\n",buff);
get_date(buff,3,info.update_time);
printf("info: Modified %s\n",buff);
}
nisam_panic(HA_PANIC_WRITE);
nisam_panic(HA_PANIC_READ);
if (nisam_is_changed(file))
puts("Warning: nisam_is_changed reported that datafile was changed");
printf("- nisam_extra(CACHE) + nisam_rrnd.... + nisam_extra(NO_CACHE)\n");
if (nisam_extra(file,HA_EXTRA_RESET) || nisam_extra(file,HA_EXTRA_CACHE))
{
if (locking || (!use_blob && !pack_fields))
{
puts("got error from nisam_extra(HA_EXTRA_CACHE)");
goto end;
}
}
ant=0;
while ((error=nisam_rrnd(file,record,NI_POS_ERROR)) >= 0 &&
ant < write_count + 10)
ant+= error ? 0 : 1;
if (ant != write_count-opt_delete)
{
printf("rrnd with cache: I can only find: %d records of %d\n",
ant,write_count-opt_delete);
goto end;
}
if (nisam_extra(file,HA_EXTRA_NO_CACHE))
{
puts("got error from nisam_extra(HA_EXTRA_NO_CACHE)");
goto end;
}
if (testflag == 4) goto end;
printf("- Removing keys\n");
lastpos = NI_POS_ERROR;
/* DBUG_POP(); */
nisam_extra(file,HA_EXTRA_RESET);
while ((error=nisam_rrnd(file,read_record,NI_POS_ERROR)) >=0)
{
nisam_info(file,&info,1);
if (lastpos >= info.recpos && lastpos != NI_POS_ERROR)
{
printf("nisam_rrnd didn't advance filepointer; old: %ld, new: %ld\n",
lastpos,info.recpos);
goto err;
}
lastpos=info.recpos;
if (error == 0)
{
if (nisam_rsame(file,read_record,-1))
{
printf("can't find record %lx\n",info.recpos);
goto err;
}
if (use_blob)
{
ulong blob_length,pos;
uchar *ptr;
longget(blob_length,read_record+blob_pos+4);
ptr=(uchar*) blob_length;
longget(blob_length,read_record+blob_pos);
for (pos=0 ; pos < blob_length ; pos++)
{
if (ptr[pos] != (uchar) (blob_length+pos))
{
printf("found blob with wrong info at %ld\n",lastpos);
use_blob=0;
break;
}
}
}
if (nisam_delete(file,read_record))
{
printf("can't delete record: %s\n",read_record);
goto err;
}
opt_delete++;
}
}
if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED)
printf("error: %d from nisam_rrnd\n",my_errno);
if (write_count != opt_delete)
{
printf("Deleted only %d of %d records\n",write_count,opt_delete);
goto err;
}
end:
if (nisam_close(file))
goto err;
nisam_panic(HA_PANIC_CLOSE); /* Should close log */
printf("\nFollowing test have been made:\n");
printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
if (rec_pointer_size)
printf("Record pointer size: %d\n",rec_pointer_size);
if (key_cacheing)
puts("Key cacheing used");
if (write_cacheing)
puts("Write cacheing used");
if (async_io && locking)
puts("Asyncron io with locking used");
else if (locking)
puts("Locking used");
if (use_blob)
puts("blobs used");
end_key_cache(dflt_key_cache,1);
if (blob_buffer)
my_free(blob_buffer,MYF(0));
my_end(MY_CHECK_ERROR | MY_GIVE_INFO);
return(0);
err:
printf("got error: %d when using NISAM-database\n",my_errno);
if (file)
VOID(nisam_close(file));
return(1);
} /* main */
/* l{ser optioner */
/* OBS! intierar endast DEBUG - ingen debuggning h{r ! */
static void get_options( int argc, char *argv[])
{
char *pos,*progname;
DEBUGGER_OFF;
progname= argv[0];
while (--argc >0 && *(pos = *(++argv)) == '-' ) {
switch(*++pos) {
case 'b':
if (*++pos)
nisam_block_size= MY_ALIGN(atoi(pos),512);
set_if_bigger(nisam_block_size,8192); /* Max block size */
set_if_smaller(nisam_block_size,1024);
break;
case 'B':
use_blob=1;
break;
case 'K': /* Use key cacheing */
key_cacheing=1;
break;
case 'W': /* Use write cacheing */
write_cacheing=1;
if (*++pos)
my_default_record_cache_size=atoi(pos);
break;
case 'i':
if (*++pos)
srand(atoi(pos));
break;
case 'l':
use_log=1;
break;
case 'L':
locking=1;
break;
case 'A': /* use asyncron io */
async_io=1;
if (*++pos)
my_default_record_cache_size=atoi(pos);
break;
case 'v': /* verbose */
verbose=1;
break;
case 'm': /* records */
recant=atoi(++pos);
break;
case 'f':
if ((first_key=atoi(++pos)) <0 || first_key >= NISAM_KEYS)
first_key=0;
break;
case 'k':
if ((keys=(uint) atoi(++pos)) < 1 ||
keys > (uint) (NISAM_KEYS-first_key))
keys=NISAM_KEYS-first_key;
break;
case 'P':
pack_type=0; /* Don't use DIFF_LENGTH */
break;
case 'R': /* Length of record pointer */
rec_pointer_size=atoi(++pos);
if (rec_pointer_size > 3)
rec_pointer_size=0;
break;
case 'S':
pack_fields=0; /* Static-length-records */
break;
case 't':
testflag=atoi(++pos); /* testmod */
break;
case '?':
case 'I':
case 'V':
printf("%s Ver 1.4 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
puts("TCX Datakonsult AB, by Monty, for your professional use\n");
printf("Usage: %s [-?ABIKLPRSVWltv] [-b#] [-k#] [-f#] [-m#] [-t#]\n",progname);
exit(0);
case '#':
DEBUGGER_ON;
DBUG_PUSH (++pos);
break;
default:
printf("Illegal option: '%c'\n",*pos);
break;
}
}
return;
} /* get options */
/* Ge ett randomv{rde inom ett intervall 0 <=x <= n */
static uint rnd( uint max_value)
{
return (uint) ((rand() & 32767)/32767.0*max_value);
} /* rnd */
/* G|r en record av skiftande length */
static void fix_length( byte *rec, uint length)
{
bmove(rec+STANDAR_LENGTH,
"0123456789012345678901234567890123456789012345678901234567890",
length-STANDAR_LENGTH);
strfill(rec+length,STANDAR_LENGTH+60-length,' ');
} /* fix_length */
/* Put maybe a blob in record */
static void put_blob_in_record(char *blob_pos, char **blob_buffer)
{
ulong i,length;
if (use_blob)
{
if (rnd(10) == 0)
{
if (! *blob_buffer &&
!(*blob_buffer=my_malloc((uint) use_blob,MYF(MY_WME))))
{
use_blob=0;
return;
}
length=rnd(use_blob);
for (i=0 ; i < length ; i++)
(*blob_buffer)[i]=(char) (length+i);
longstore(blob_pos,length);
bmove(blob_pos+4,(char*) blob_buffer,sizeof(char*));
}
else
{
longstore(blob_pos,0);
}
}
return;
}
static void copy_key( N_INFO *info, uint inx, uchar *rec, uchar *key_buff)
{
N_KEYSEG *keyseg;
for (keyseg=info->s->keyinfo[inx].seg ; keyseg->base.type ; keyseg++)
{
memcpy(key_buff,rec+keyseg->base.start,(size_t) keyseg->base.length);
key_buff+=keyseg->base.length;
}
return;
}

View File

@ -1,494 +0,0 @@
/* 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 */
/* Test av locking */
#ifndef __NETWARE__
#include "nisam.h"
#include <sys/types.h>
#include <keycache.h>
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#ifndef WEXITSTATUS
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
#ifndef WIFEXITED
# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
#if defined(HAVE_LRAND48)
#define rnd(X) (lrand48() % X)
#define rnd_init(X) srand48(X)
#else
#define rnd(X) (random() % X)
#define rnd_init(X) srandom(X)
#endif
const char *filename= "test3.ISM";
uint tests=10,forks=10,key_cacheing=0,use_log=0;
static void get_options(int argc, char *argv[]);
void start_test(int id);
int test_read(N_INFO *,int),test_write(N_INFO *,int,int),
test_update(N_INFO *,int,int),test_rrnd(N_INFO *,int);
struct record {
char id[8];
uint32 nr;
char text[10];
} record;
int main(int argc,char **argv)
{
int status,wait_ret;
uint i;
N_KEYDEF keyinfo[10];
N_RECINFO recinfo[10];
MY_INIT(argv[0]);
get_options(argc,argv);
keyinfo[0].seg[0].base.start=0;
keyinfo[0].seg[0].base.length=8;
keyinfo[0].seg[0].base.type=HA_KEYTYPE_TEXT;
keyinfo[0].seg[0].base.flag=HA_SPACE_PACK;
keyinfo[0].seg[1].base.type=0;
keyinfo[0].base.flag = (uint8) HA_PACK_KEY;
keyinfo[1].seg[0].base.start=8;
keyinfo[1].seg[0].base.length=sizeof(uint32);
keyinfo[1].seg[0].base.type=HA_KEYTYPE_LONG_INT;
keyinfo[1].seg[0].base.flag=0;
keyinfo[1].seg[1].base.type=0;
keyinfo[1].base.flag =HA_NOSAME;
recinfo[0].base.type=0;
recinfo[0].base.length=sizeof(record.id);
recinfo[1].base.type=0;
recinfo[1].base.length=sizeof(record.nr);
recinfo[2].base.type=0;
recinfo[2].base.length=sizeof(record.text);
recinfo[3].base.type=FIELD_LAST;
puts("- Creating isam-file");
my_delete(filename,MYF(0)); /* Remove old locks under gdb */
if (nisam_create(filename,2,&keyinfo[0],&recinfo[0],10000,0,0,0,0L))
exit(1);
rnd_init(0);
printf("- Starting %d processes\n",forks); fflush(stdout);
for (i=0 ; i < forks; i++)
{
if (!fork())
{
start_test(i+1);
sleep(1);
return 0;
}
VOID(rnd(1));
}
for (i=0 ; i < forks ; i++)
while ((wait_ret=wait(&status)) && wait_ret == -1);
return 0;
}
static void get_options(argc,argv)
int argc;
char *argv[];
{
char *pos,*progname;
DEBUGGER_OFF;
progname= argv[0];
while (--argc >0 && *(pos = *(++argv)) == '-' ) {
switch(*++pos) {
case 'l':
use_log=1;
break;
case 'f':
forks=atoi(++pos);
break;
case 't':
tests=atoi(++pos);
break;
case 'K': /* Use key cacheing */
key_cacheing=1;
break;
case 'A': /* All flags */
use_log=key_cacheing=1;
break;
case '?':
case 'I':
case 'V':
printf("%s Ver 1.0 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
puts("TCX Datakonsult AB, by Monty, for your professional use\n");
puts("Test av locking with threads\n");
printf("Usage: %s [-?lKA] [-f#] [-t#]\n",progname);
exit(0);
case '#':
DEBUGGER_ON;
DBUG_PUSH (++pos);
break;
default:
printf("Illegal option: '%c'\n",*pos);
break;
}
}
return;
}
void start_test(int id)
{
uint i;
int error,lock_type;
N_ISAMINFO isam_info;
N_INFO *file,*file1,*file2,*lock;
if (use_log)
nisam_log(1);
if (!(file1=nisam_open(filename,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)) ||
!(file2=nisam_open(filename,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)))
{
fprintf(stderr,"Can't open isam-file: %s\n",filename);
exit(1);
}
if (key_cacheing && rnd(2) == 0)
init_key_cache(dflt_key_cache,512,65536L,0,0);
printf("Process %d, pid: %d\n",id,(int) getpid()); fflush(stdout);
for (error=i=0 ; i < tests && !error; i++)
{
file= (rnd(2) == 1) ? file1 : file2;
lock=0 ; lock_type=0;
if (rnd(10) == 0)
{
if (nisam_lock_database(lock=(rnd(2) ? file1 : file2),
lock_type=(rnd(2) == 0 ? F_RDLCK : F_WRLCK)))
{
fprintf(stderr,"%2d: start: Can't lock table %d\n",id,my_errno);
error=1;
break;
}
}
switch (rnd(4)) {
case 0: error=test_read(file,id); break;
case 1: error=test_rrnd(file,id); break;
case 2: error=test_write(file,id,lock_type); break;
case 3: error=test_update(file,id,lock_type); break;
}
if (lock)
nisam_lock_database(lock,F_UNLCK);
}
if (!error)
{
nisam_info(file1,&isam_info,0);
printf("%2d: End of test. Records: %ld Deleted: %ld\n",
id,isam_info.records,isam_info.deleted);
fflush(stdout);
}
nisam_close(file1);
nisam_close(file2);
if (use_log)
nisam_log(0);
if (error)
{
printf("%2d: Aborted\n",id); fflush(stdout);
exit(1);
}
}
int test_read(N_INFO *file,int id)
{
uint i,lock,found,next,prev;
ulong find;
lock=0;
if (rnd(2) == 0)
{
lock=1;
if (nisam_lock_database(file,F_RDLCK))
{
fprintf(stderr,"%2d: Can't lock table %d\n",id,my_errno);
return 1;
}
}
found=next=prev=0;
for (i=0 ; i < 100 ; i++)
{
find=rnd(100000);
if (!nisam_rkey(file,record.id,1,(byte*) &find,
sizeof(find),HA_READ_KEY_EXACT))
found++;
else
{
if (my_errno != HA_ERR_KEY_NOT_FOUND)
{
fprintf(stderr,"%2d: Got error %d from read in read\n",id,my_errno);
return 1;
}
else if (!nisam_rnext(file,record.id,1))
next++;
else
{
if (my_errno != HA_ERR_END_OF_FILE)
{
fprintf(stderr,"%2d: Got error %d from rnext in read\n",id,my_errno);
return 1;
}
else if (!nisam_rprev(file,record.id,1))
prev++;
else
{
if (my_errno != HA_ERR_END_OF_FILE)
{
fprintf(stderr,"%2d: Got error %d from rnext in read\n",
id,my_errno);
return 1;
}
}
}
}
}
if (lock)
{
if (nisam_lock_database(file,F_UNLCK))
{
fprintf(stderr,"%2d: Can't unlock table\n",id);
return 1;
}
}
printf("%2d: read: found: %5d next: %5d prev: %5d\n",
id,found,next,prev);
fflush(stdout);
return 0;
}
int test_rrnd(N_INFO *file,int id)
{
uint count,lock;
lock=0;
if (rnd(2) == 0)
{
lock=1;
if (nisam_lock_database(file,F_RDLCK))
{
fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
nisam_close(file);
return 1;
}
if (rnd(2) == 0)
nisam_extra(file,HA_EXTRA_CACHE);
}
count=0;
if (nisam_rrnd(file,record.id,0L))
{
if (my_errno == HA_ERR_END_OF_FILE)
goto end;
fprintf(stderr,"%2d: Can't read first record (%d)\n",id,my_errno);
return 1;
}
for (count=1 ; !nisam_rrnd(file,record.id,NI_POS_ERROR) ;count++) ;
if (my_errno != HA_ERR_END_OF_FILE)
{
fprintf(stderr,"%2d: Got error %d from rrnd\n",id,my_errno);
return 1;
}
end:
if (lock)
{
nisam_extra(file,HA_EXTRA_NO_CACHE);
if (nisam_lock_database(file,F_UNLCK))
{
fprintf(stderr,"%2d: Can't unlock table\n",id);
exit(0);
}
}
printf("%2d: rrnd: %5d\n",id,count); fflush(stdout);
return 0;
}
int test_write(N_INFO *file,int id,int lock_type)
{
uint i,tries,count,lock;
lock=0;
if (rnd(2) == 0 || lock_type == F_RDLCK)
{
lock=1;
if (nisam_lock_database(file,F_WRLCK))
{
if (lock_type == F_RDLCK && my_errno == EDEADLK)
{
printf("%2d: write: deadlock\n",id); fflush(stdout);
return 0;
}
fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
nisam_close(file);
return 1;
}
if (rnd(2) == 0)
nisam_extra(file,HA_EXTRA_WRITE_CACHE);
}
sprintf(record.id,"%7d",(int) getpid());
strmov(record.text,"Testing...");
tries=(uint) rnd(100)+10;
for (i=count=0 ; i < tries ; i++)
{
record.nr=rnd(80000)+20000;
if (!nisam_write(file,record.id))
count++;
else
{
if (my_errno != HA_ERR_FOUND_DUPP_KEY)
{
fprintf(stderr,"%2d: Got error %d (errno %d) from write\n",id,my_errno,
errno);
return 1;
}
}
}
if (lock)
{
nisam_extra(file,HA_EXTRA_NO_CACHE);
if (nisam_lock_database(file,F_UNLCK))
{
fprintf(stderr,"%2d: Can't unlock table\n",id);
exit(0);
}
}
printf("%2d: write: %5d\n",id,count); fflush(stdout);
return 0;
}
int test_update(N_INFO *file,int id,int lock_type)
{
uint i,lock,found,next,prev,update;
ulong find;
struct record new_record;
lock=0;
if (rnd(2) == 0 || lock_type == F_RDLCK)
{
lock=1;
if (nisam_lock_database(file,F_WRLCK))
{
if (lock_type == F_RDLCK && my_errno == EDEADLK)
{
printf("%2d: write: deadlock\n",id); fflush(stdout);
return 0;
}
fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
return 1;
}
}
bzero((char*) &new_record,sizeof(new_record));
strmov(new_record.text,"Updated");
found=next=prev=update=0;
for (i=0 ; i < 100 ; i++)
{
find=rnd(100000);
if (!nisam_rkey(file,record.id,1,(byte*) &find,
sizeof(find),HA_READ_KEY_EXACT))
found++;
else
{
if (my_errno != HA_ERR_KEY_NOT_FOUND)
{
fprintf(stderr,"%2d: Got error %d from read in update\n",id,my_errno);
return 1;
}
else if (!nisam_rnext(file,record.id,1))
next++;
else
{
if (my_errno != HA_ERR_END_OF_FILE)
{
fprintf(stderr,"%2d: Got error %d from rnext in update\n",
id,my_errno);
return 1;
}
else if (!nisam_rprev(file,record.id,1))
prev++;
else
{
if (my_errno != HA_ERR_END_OF_FILE)
{
fprintf(stderr,"%2d: Got error %d from rnext in update\n",
id,my_errno);
return 1;
}
continue;
}
}
}
memcpy_fixed(new_record.id,record.id,sizeof(record.id));
new_record.nr=rnd(20000)+40000;
if (!nisam_update(file,record.id,new_record.id))
update++;
else
{
if (my_errno != HA_ERR_RECORD_CHANGED &&
my_errno != HA_ERR_RECORD_DELETED &&
my_errno != HA_ERR_FOUND_DUPP_KEY)
{
fprintf(stderr,"%2d: Got error %d from update\n",id,my_errno);
return 1;
}
}
}
if (lock)
{
if (nisam_lock_database(file,F_UNLCK))
{
fprintf(stderr,"Can't unlock table,id, error%d\n",my_errno);
return 1;
}
}
printf("%2d: update: %5d\n",id,update); fflush(stdout);
return 0;
}
#else /* __NETWARE__ */
#include <stdio.h>
main()
{
fprintf(stderr,"this test has not been ported to NetWare\n");
return 0;
}
#endif /* __NETWARE__ */

View File

@ -1,30 +0,0 @@
echo "test2 -L -K -W -P"
test2 -L -K -W -P
echo "test2 -L -K -W -P -A"
test2 -L -K -W -P -A
echo "test2 -L -K -W -P -S -R1 -m500"
test2 -L -K -W -P -S -R1 -m500
echo "test2 -L -K -R1 -m2000 ; Should give error 135"
test2 -L -K -R1 -m2000
echo "test2 -L -K -P -S -R3 -m50 -b1000000"
test2 -L -K -P -S -R3 -m50 -b1000000
echo "test2 -L -B"
test2 -L -B
echo "test2 -L -K -W -P -m50 -l"
test2 -L -K -W -P -m50 -l
isamlog
echo "test2 -L -K -W -P -m50 -l -b100"
test2 -L -K -W -P -m50 -l -b100
isamlog
echo "time test2"
time test2
echo "time test2 -K"
time test2 -K
echo "time test2 -L"
time test2 -L
echo "time test2 -L -K"
time test2 -L -K
echo "time test2 -L -K -W"
time test2 -L -K -W
echo "time test2 -L -K -W -S"
time test2 -L -K -W -S

View File

@ -1,30 +0,0 @@
echo "test2 -L -K -W -P"
test2 -L -K -W -P
echo "test2 -L -K -W -P -A"
test2 -L -K -W -P -A
echo "test2 -L -K -W -P -S -R1 -m500"
test2 -L -K -W -P -S -R1 -m500
echo "test2 -L -K -R1 -m2000 ; Should give error 135"
test2 -L -K -R1 -m2000
echo "test2 -L -K -P -S -R3 -m50 -b1000000"
test2 -L -K -P -S -R3 -m50 -b1000000
echo "test2 -L -B"
test2 -L -B
echo "test2 -L -K -W -P -m50 -l"
test2 -L -K -W -P -m50 -l
isamlog
echo "test2 -L -K -W -P -m50 -l -b100"
test2 -L -K -W -P -m50 -l -b100
isamlog
echo "time test2"
time test2
echo "time test2 -K"
time test2 -K
echo "time test2 -L"
time test2 -L
echo "time test2 -L -K"
time test2 -L -K
echo "time test2 -L -K -W"
time test2 -L -K -W
echo "time test2 -L -K -W -S"
time test2 -L -K -W -S

View File

@ -1,117 +0,0 @@
/* 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 */
/* Uppdaterare nuvarande record i en pisam-databas */
#include "isamdef.h"
#ifdef __WIN__
#include <errno.h>
#endif
/* Updaterar senaste l{sta record i databasen */
int nisam_update(register N_INFO *info, const byte *oldrec, const byte *newrec)
{
int flag,key_changed,save_errno;
reg3 ulong pos;
uint i,length;
uchar old_key[N_MAX_KEY_BUFF],*new_key;
DBUG_ENTER("nisam_update");
LINT_INIT(save_errno);
if (!(info->update & HA_STATE_AKTIV))
{
my_errno=HA_ERR_KEY_NOT_FOUND;
DBUG_RETURN(-1);
}
if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
{
my_errno=EACCES;
DBUG_RETURN(-1);
}
pos=info->lastpos;
#ifndef NO_LOCKING
if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1);
#endif
if ((*info->s->compare_record)(info,oldrec))
{
save_errno=my_errno;
goto err_end; /* Record has changed */
}
if (info->s->state.key_file_length >=
info->s->base.max_key_file_length -
info->s->blocksize* INDEX_BLOCK_MARGIN *info->s->state.keys)
{
save_errno=HA_ERR_INDEX_FILE_FULL;
goto err_end;
}
/* Flyttar de element i isamfilen som m}ste flyttas */
new_key=info->lastkey+info->s->base.max_key_length;
key_changed=HA_STATE_KEY_CHANGED; /* We changed current database */
/* Remove key that didn't change */
for (i=0 ; i < info->s->state.keys ; i++)
{
length=_nisam_make_key(info,i,new_key,newrec,pos);
if (length != _nisam_make_key(info,i,old_key,oldrec,pos) ||
memcmp((byte*) old_key,(byte*) new_key,length))
{
if ((int) i == info->lastinx)
key_changed|=HA_STATE_WRITTEN; /* Mark that keyfile changed */
if (_nisam_ck_delete(info,i,old_key)) goto err;
if (_nisam_ck_write(info,i,new_key)) goto err;
}
}
if ((*info->s->update_record)(info,pos,newrec))
goto err;
info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV |
key_changed);
nisam_log_record(LOG_UPDATE,info,newrec,info->lastpos,0);
VOID(_nisam_writeinfo(info,test(key_changed)));
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);
err:
DBUG_PRINT("error",("key: %d errno: %d",i,my_errno));
save_errno=my_errno;
if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL)
{
info->errkey= (int) i;
flag=0;
do
{
length=_nisam_make_key(info,i,new_key,newrec,pos);
if (length != _nisam_make_key(info,i,old_key,oldrec,pos) ||
memcmp((byte*) old_key,(byte*) new_key,length))
{
if ((flag++ && _nisam_ck_delete(info,i,new_key)) ||
_nisam_ck_write(info,i,old_key))
break;
}
} while (i-- != 0);
}
info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV |
key_changed);
err_end:
nisam_log_record(LOG_UPDATE,info,newrec,info->lastpos,save_errno);
VOID(_nisam_writeinfo(info,1));
allow_break(); /* Allow SIGHUP & SIGINT */
my_errno=(save_errno == HA_ERR_KEY_NOT_FOUND) ? HA_ERR_CRASHED : save_errno;
DBUG_RETURN(-1);
} /* nisam_update */

View File

@ -1,840 +0,0 @@
/* 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 */
/* Skriver ett record till en isam-databas */
#include "isamdef.h"
#ifdef __WIN__
#include <errno.h>
#endif
/* Functions declared in this file */
static int w_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
ulong pos, uchar *father_buff, uchar *father_keypos,
ulong father_page);
static int _nisam_balance_page(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
uchar *curr_buff,uchar *father_buff,
uchar *father_keypos,ulong father_page);
/* Write new record to database */
int nisam_write(N_INFO *info, const byte *record)
{
uint i;
ulong filepos;
uchar *buff;
DBUG_ENTER("nisam_write");
DBUG_PRINT("enter",("isam: %d data: %d",info->s->kfile,info->dfile));
if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
{
my_errno=EACCES;
DBUG_RETURN(-1);
}
#ifndef NO_LOCKING
if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1);
#endif
dont_break(); /* Dont allow SIGHUP or SIGINT */
#if !defined(NO_LOCKING) && defined(USE_RECORD_LOCK)
if (!info->locked && my_lock(info->dfile,F_WRLCK,0L,F_TO_EOF,
MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
goto err;
#endif
filepos= ((info->s->state.dellink != NI_POS_ERROR) ?
info->s->state.dellink :
info->s->state.data_file_length);
if (info->s->base.reloc == 1L && info->s->base.records == 1L &&
info->s->state.records == 1L)
{ /* System file */
my_errno=HA_ERR_RECORD_FILE_FULL;
goto err2;
}
if (info->s->state.key_file_length >=
info->s->base.max_key_file_length -
info->s->blocksize* INDEX_BLOCK_MARGIN *info->s->state.keys)
{
my_errno=HA_ERR_INDEX_FILE_FULL;
goto err2;
}
/* Write all keys to indextree */
buff=info->lastkey+info->s->base.max_key_length;
for (i=0 ; i < info->s->state.keys ; i++)
{
VOID(_nisam_make_key(info,i,buff,record,filepos));
if (_nisam_ck_write(info,i,buff)) goto err;
}
if ((*info->s->write_record)(info,record))
goto err;
info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |HA_STATE_AKTIV |
HA_STATE_WRITTEN);
info->s->state.records++;
info->lastpos=filepos;
nisam_log_record(LOG_WRITE,info,record,filepos,0);
VOID(_nisam_writeinfo(info,1));
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);
err:
if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL)
{
info->errkey= (int) i;
while ( i-- > 0)
{
VOID(_nisam_make_key(info,i,buff,record,filepos));
if (_nisam_ck_delete(info,i,buff))
break;
}
}
info->update=(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_WRITTEN);
err2:
nisam_log_record(LOG_WRITE,info,record,filepos,my_errno);
VOID(_nisam_writeinfo(info,1));
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(-1);
} /* nisam_write */
/* Write one key to btree */
int _nisam_ck_write(register N_INFO *info, uint keynr, uchar *key)
{
int error;
DBUG_ENTER("_nisam_ck_write");
if ((error=w_search(info,info->s->keyinfo+keynr,key,
info->s->state.key_root[keynr], (uchar *) 0, (uchar*) 0,
0L)) > 0)
error=_nisam_enlarge_root(info,keynr,key);
DBUG_RETURN(error);
} /* _nisam_ck_write */
/* Make a new root with key as only pointer */
int _nisam_enlarge_root(register N_INFO *info, uint keynr, uchar *key)
{
uint t_length,nod_flag;
reg2 N_KEYDEF *keyinfo;
S_PARAM s_temp;
ISAM_SHARE *share=info->s;
DBUG_ENTER("_nisam_enlarge_root");
info->page_changed=1;
nod_flag= (share->state.key_root[keynr] != NI_POS_ERROR) ?
share->base.key_reflength : 0;
_nisam_kpointer(info,info->buff+2,share->state.key_root[keynr]); /* if nod */
keyinfo=share->keyinfo+keynr;
t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,(uchar*) 0,(uchar*) 0,
key,&s_temp);
putint(info->buff,t_length+2+nod_flag,nod_flag);
_nisam_store_key(keyinfo,info->buff+2+nod_flag,&s_temp);
if ((share->state.key_root[keynr]= _nisam_new(info,keyinfo)) ==
NI_POS_ERROR ||
_nisam_write_keypage(info,keyinfo,share->state.key_root[keynr],info->buff))
DBUG_RETURN(-1);
DBUG_RETURN(0);
} /* _nisam_enlarge_root */
/* S|ker reda p} vart nyckeln skall s{ttas och placerar den dit */
/* Returnerar -1 om fel ; 0 om ok. 1 om nyckel propagerar upp}t */
static int w_search(register N_INFO *info, register N_KEYDEF *keyinfo,
uchar *key, ulong page, uchar *father_buff,
uchar *father_keypos, ulong father_page)
{
int error,flag;
uint comp_flag,nod_flag;
uchar *temp_buff,*keypos;
uchar keybuff[N_MAX_KEY_BUFF];
DBUG_ENTER("w_search");
DBUG_PRINT("enter",("page: %ld",page));
if (page == NI_POS_ERROR)
DBUG_RETURN(1); /* No key, make new */
if (keyinfo->base.flag & HA_SORT_ALLOWS_SAME)
comp_flag=SEARCH_BIGGER; /* Put after same key */
else if (keyinfo->base.flag & HA_NOSAME)
comp_flag=SEARCH_FIND; /* No dupplicates */
else
comp_flag=SEARCH_SAME; /* Keys in rec-pos order */
if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
N_MAX_KEY_BUFF)))
DBUG_RETURN(-1);
if (!_nisam_fetch_keypage(info,keyinfo,page,temp_buff,0))
goto err;
flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,0,comp_flag,&keypos,
keybuff);
nod_flag=test_if_nod(temp_buff);
if (flag == 0)
{
my_errno=HA_ERR_FOUND_DUPP_KEY;
/* get position to record with dupplicated key */
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff));
info->dupp_key_pos=_nisam_dpos(info,test_if_nod(temp_buff),keypos);
my_afree((byte*) temp_buff);
DBUG_RETURN(-1);
}
if ((error=w_search(info,keyinfo,key,_nisam_kpos(nod_flag,keypos),
temp_buff,keypos,page)) >0)
{
error=_nisam_insert(info,keyinfo,key,temp_buff,keypos,keybuff,father_buff,
father_keypos,father_page);
if (_nisam_write_keypage(info,keyinfo,page,temp_buff))
goto err;
}
my_afree((byte*) temp_buff);
DBUG_RETURN(error);
err:
my_afree((byte*) temp_buff);
DBUG_PRINT("exit",("Error: %d",my_errno));
DBUG_RETURN (-1);
} /* w_search */
/* Insert new key at right of key_pos */
/* Returns 2 if key contains key to upper level */
int _nisam_insert(register N_INFO *info, register N_KEYDEF *keyinfo,
uchar *key, uchar *anc_buff, uchar *key_pos, uchar *key_buff,
uchar *father_buff, uchar *father_key_pos, ulong father_page)
{
uint a_length,t_length,nod_flag;
uchar *endpos;
int key_offset;
S_PARAM s_temp;
DBUG_ENTER("_nisam_insert");
DBUG_PRINT("enter",("key_pos: %lx",key_pos));
DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,key););
nod_flag=test_if_nod(anc_buff);
a_length=getint(anc_buff);
endpos= anc_buff+ a_length;
t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,
(key_pos == endpos ? (uchar*) 0 : key_pos),
(key_pos == anc_buff+2+nod_flag ?
(uchar*) 0 : key_buff),key,&s_temp);
#ifndef DBUG_OFF
if (key_pos != anc_buff+2+nod_flag)
DBUG_DUMP("prev_key",(byte*) key_buff,_nisam_keylength(keyinfo,key_buff));
if (keyinfo->base.flag & HA_PACK_KEY)
{
DBUG_PRINT("test",("t_length: %d ref_len: %d",
t_length,s_temp.ref_length));
DBUG_PRINT("test",("n_ref_len: %d n_length: %d key: %lx",
s_temp.n_ref_length,s_temp.n_length,s_temp.key));
}
#endif
key_offset = (uint)(endpos-key_pos);
if((int) t_length < 0)
key_offset += (int) t_length;
if (key_offset < 0)
{
DBUG_PRINT("error",("Found a bug: negative key_offset %d\n", key_offset));
DBUG_RETURN(-1);
}
if ((int) t_length >= 0) /* t_length is almost always > 0 */
bmove_upp((byte*) endpos+t_length,(byte*) endpos,(uint)key_offset );
else
{
/* This may happen if a key was deleted and the next key could be
compressed better than before */
DBUG_DUMP("anc_buff",(byte*) anc_buff,a_length);
bmove(key_pos,key_pos - (int) t_length,(uint)key_offset);
}
_nisam_store_key(keyinfo,key_pos,&s_temp);
a_length+=t_length;
putint(anc_buff,a_length,nod_flag);
if (a_length <= keyinfo->base.block_length)
DBUG_RETURN(0); /* There is room on page */
/* Page is full */
if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)) &&
father_buff)
DBUG_RETURN(_nisam_balance_page(info,keyinfo,key,anc_buff,father_buff,
father_key_pos,father_page));
DBUG_RETURN(_nisam_splitt_page(info,keyinfo,key,anc_buff,key_buff));
} /* _nisam_insert */
/* splitt a full page in two and assign emerging item to key */
int _nisam_splitt_page(register N_INFO *info, register N_KEYDEF *keyinfo,
uchar *key, uchar *buff, uchar *key_buff)
{
uint length,a_length,key_ref_length,t_length,nod_flag;
uchar *key_pos,*pos;
ulong new_pos;
S_PARAM s_temp;
DBUG_ENTER("ni_splitt_page");
DBUG_DUMP("buff",(byte*) buff,getint(buff));
nod_flag=test_if_nod(buff);
key_ref_length=2+nod_flag;
key_pos=_nisam_find_half_pos(info,keyinfo,buff,key_buff);
length=(uint) (key_pos-buff);
a_length=getint(buff);
putint(buff,length,nod_flag);
info->page_changed=1;
/* Correct new page pointer */
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff));
if (nod_flag)
{
DBUG_PRINT("test",("Splitting nod"));
pos=key_pos-nod_flag;
memcpy((byte*) info->buff+2,(byte*) pos,(size_t) nod_flag);
}
/* Move midle item to key and pointer to new page */
if ((new_pos=_nisam_new(info,keyinfo)) == NI_POS_ERROR)
DBUG_RETURN(-1);
_nisam_kpointer(info,_nisam_move_key(keyinfo,key,key_buff),new_pos);
/* Store new page */
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff));
t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,(uchar *) 0, (uchar*) 0,
key_buff, &s_temp);
s_temp.n_length= *key_pos; /* Needed by ni_store_key */
length=(uint) ((buff+a_length)-key_pos);
memcpy((byte*) info->buff+key_ref_length+t_length,(byte*) key_pos,
(size_t) length);
_nisam_store_key(keyinfo,info->buff+key_ref_length,&s_temp);
putint(info->buff,length+t_length+key_ref_length,nod_flag);
if (_nisam_write_keypage(info,keyinfo,new_pos,info->buff))
DBUG_RETURN(-1);
DBUG_DUMP("key",(byte*) key,_nisam_keylength(keyinfo,key));
DBUG_RETURN(2); /* Middle key up */
} /* _nisam_splitt_page */
/* find out how much more room a key will take */
#ifdef QQ
uint _nisam_get_pack_key_length(N_KEYDEF *keyinfo, uint nod_flag, uchar *key_pos, uchar *key_buff, uchar *key, S_PARAM *s_temp)
/* If nod: Length of nod-pointer */
/* Position to pos after key in buff */
/* Last key before current key */
/* Current key */
/* How next key will be packed */
{
reg1 N_KEYSEG *keyseg;
int length;
uint key_length,ref_length,n_length,diff_flag,same_length;
uchar *start,*end,*key_end;
s_temp->key=key;
if (!(keyinfo->base.flag & HA_PACK_KEY))
return (s_temp->totlength=_nisam_keylength(keyinfo,key)+nod_flag);
s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
s_temp->prev_length=0;
same_length=0; keyseg=keyinfo->seg;
key_length=_nisam_keylength(keyinfo,key)+nod_flag;
if (keyseg->base.flag & HA_SPACE_PACK)
{
diff_flag=1;
end=key_end= key+ *key+1;
if (key_buff)
{
if (*key == *key_buff && *key)
same_length=1; /* Don't use key-pack if length == 0 */
else if (*key > *key_buff)
end=key+ *key_buff+1;
key_buff++;
}
key++;
}
else
{
diff_flag=0;
key_end=end= key+keyseg->base.length;
}
start=key;
if (key_buff)
while (key < end && *key == *key_buff)
{
key++; key_buff++;
}
s_temp->key=key; s_temp->key_length= (uint) (key_end-key);
if (same_length && key == key_end)
{
s_temp->ref_length=128;
length=(int) key_length-(int)(key_end-start); /* Same as prev key */
if (key_pos)
{
s_temp->n_length= *key_pos;
key_pos=0; /* Can't combine with next */
}
}
else
{
if (start != key)
{ /* Starts as prev key */
s_temp->ref_length= (uint) (key-start)+128;
length=(int) (1+key_length-(uint) (key-start));
}
else
length=(int) (key_length+ (1-diff_flag)); /* Not packed key */
}
s_temp->totlength=(uint) length;
DBUG_PRINT("test",("tot_length: %d length: %d uniq_key_length: %d",
key_length,length,s_temp->key_length));
/* If something after that is not 0 length test if we can combine */
if (key_pos && (n_length= *key_pos))
{
key_pos++;
ref_length=0;
if (n_length & 128)
{
if ((ref_length=n_length & 127))
if (diff_flag)
n_length= *key_pos++; /* Length of key-part */
else
n_length=keyseg->base.length - ref_length;
}
else
if (*start == *key_pos && diff_flag && start != key_end)
length++; /* One new pos for ref.len */
DBUG_PRINT("test",("length: %d key_pos: %lx",length,key_pos));
if (n_length != 128)
{ /* Not same key after */
key=start+ref_length;
while (n_length > 0 && key < key_end && *key == *key_pos)
{
key++; key_pos++;
ref_length++;
n_length--;
length--; /* We gained one char */
}
if (n_length == 0 && diff_flag)
{
n_length=128; /* Same as prev key */
length--; /* We don't need key-length */
}
else if (ref_length)
s_temp->n_ref_length=ref_length | 128;
}
s_temp->n_length=n_length;
}
return (uint) length;
} /* _nisam_get_pack_key_length */
#else
uint
_nisam_get_pack_key_length(N_KEYDEF *keyinfo,
uint nod_flag, /* If nod: Length of nod-pointer */
uchar *key_pos, /* Position to pos after key in buff */
uchar *key_buff,/* Last key before current key */
uchar *key, /* Current key */
S_PARAM *s_temp/* How next key will be packed */
)
{
reg1 N_KEYSEG *keyseg;
int length;
uint key_length,ref_length,n_length,diff_flag,same_length,org_key_length=0;
uchar *start,*end,*key_end;
s_temp->key=key;
if (!(keyinfo->base.flag & HA_PACK_KEY))
return (s_temp->totlength=_nisam_keylength(keyinfo,key)+nod_flag);
s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
same_length=0; keyseg=keyinfo->seg;
key_length=_nisam_keylength(keyinfo,key)+nod_flag;
s_temp->prev_key=key_buff;
if (keyseg->base.flag & HA_SPACE_PACK)
{
diff_flag=1;
end=key_end= key+ *key+1;
if (key_buff)
{
org_key_length= (uint) *key_buff;
if (*key == *key_buff && *key)
same_length=1; /* Don't use key-pack if length == 0 */
else if (*key > *key_buff)
end=key+ org_key_length+1;
key_buff++;
}
key++;
}
else
{
diff_flag=0;
key_end=end= key+(org_key_length=keyseg->base.length);
}
start=key;
if (key_buff)
while (key < end && *key == *key_buff)
{
key++; key_buff++;
}
s_temp->key=key; s_temp->key_length= (uint) (key_end-key);
if (same_length && key == key_end)
{
s_temp->ref_length=128;
length=(int) key_length-(int)(key_end-start); /* Same as prev key */
if (key_pos)
{ /* Can't combine with next */
s_temp->n_length= *key_pos; /* Needed by _nisam_store_key */
key_pos=0;
}
}
else
{
if (start != key)
{ /* Starts as prev key */
s_temp->ref_length= (uint) (key-start)+128;
length=(int) (1+key_length-(uint) (key-start));
}
else
length=(int) (key_length+ (1-diff_flag)); /* Not packed key */
}
s_temp->totlength=(uint) length;
s_temp->prev_length=0;
DBUG_PRINT("test",("tot_length: %d length: %d uniq_key_length: %d",
key_length,length,s_temp->key_length));
/* If something after that is not 0 length test if we can combine */
if (key_pos && (n_length= *key_pos++))
{
if (n_length == 128)
{
/*
We put a different key between two identical keys
Extend next key to have same prefix as this key
*/
if (s_temp->ref_length)
{ /* make next key longer */
s_temp->part_of_prev_key= s_temp->ref_length;
s_temp->prev_length= org_key_length - (s_temp->ref_length-128);
s_temp->n_length= s_temp->prev_length;
s_temp->prev_key+= diff_flag + (s_temp->ref_length - 128);
length+= s_temp->prev_length+diff_flag;
}
else
{ /* Can't use prev key */
s_temp->part_of_prev_key=0;
s_temp->prev_length= org_key_length;
s_temp->n_length= org_key_length;
s_temp->prev_key+= diff_flag; /* To start of key */
length+= org_key_length;
}
return (uint) length;
}
if (n_length & 128)
{
ref_length=n_length & 127;
if (diff_flag) /* If SPACE_PACK */
n_length= *key_pos++; /* Length of key-part */
else
n_length=keyseg->base.length - ref_length;
/* Test if new keys has fewer characters that match the previous key */
if (!s_temp->ref_length)
{ /* Can't use prev key */
s_temp->part_of_prev_key= 0;
s_temp->prev_length= ref_length;
s_temp->n_length= n_length+ref_length;
s_temp->prev_key+= diff_flag; /* To start of key */
return (uint) length+ref_length-diff_flag;
}
if (ref_length+128 > s_temp->ref_length)
{
/* We must copy characters from the original key to the next key */
s_temp->part_of_prev_key= s_temp->ref_length;
s_temp->prev_length= ref_length+128 - s_temp->ref_length;
s_temp->n_length= n_length + s_temp->prev_length;
s_temp->prev_key+= diff_flag + s_temp->ref_length -128;
return (uint) length + s_temp->prev_length;
}
}
else
{
ref_length=0;
if (*start == *key_pos && diff_flag && start != key_end)
length++; /* One new pos for ref.len */
}
DBUG_PRINT("test",("length: %d key_pos: %lx",length,key_pos));
key=start+ref_length;
while (n_length > 0 && key < key_end && *key == *key_pos)
{
key++; key_pos++;
ref_length++;
n_length--;
length--; /* We gained one char */
}
if (n_length == 0 && diff_flag)
{
n_length=128; /* Same as prev key */
length--; /* We don't need key-length */
}
else if (ref_length)
s_temp->n_ref_length=ref_length | 128;
s_temp->n_length=n_length;
}
return (uint) length;
} /* _nisam_get_pack_key_length */
#endif
/* store a key in page-buffert */
void _nisam_store_key(N_KEYDEF *keyinfo, register uchar *key_pos,
register S_PARAM *s_temp)
{
uint length;
uchar *start;
if (! (keyinfo->base.flag & HA_PACK_KEY))
{
memcpy((byte*) key_pos,(byte*) s_temp->key,(size_t) s_temp->totlength);
return;
}
start=key_pos;
if ((*key_pos=(uchar) s_temp->ref_length))
key_pos++;
if (s_temp->ref_length == 0 ||
(s_temp->ref_length > 128 &&
(keyinfo->seg[0].base.flag & HA_SPACE_PACK)))
*key_pos++= (uchar) s_temp->key_length;
bmove((byte*) key_pos,(byte*) s_temp->key,
(length=s_temp->totlength-(uint) (key_pos-start)));
key_pos+=length;
if (s_temp->prev_length)
{
/* Extend next key because new key didn't have same prefix as prev key */
if (s_temp->part_of_prev_key)
*key_pos++ = s_temp->part_of_prev_key;
if (keyinfo->seg[0].base.flag & HA_SPACE_PACK)
*key_pos++= s_temp->n_length;
memcpy(key_pos, s_temp->prev_key, s_temp->prev_length);
return;
}
if ((*key_pos = (uchar) s_temp->n_ref_length))
{
if (! (keyinfo->seg[0].base.flag & HA_SPACE_PACK))
return; /* Don't save keylength */
key_pos++; /* Store ref for next key */
}
*key_pos = (uchar) s_temp->n_length;
return;
} /* _nisam_store_key */
/* Calculate how to much to move to split a page in two */
/* Returns pointer and key for get_key() to get mid key */
/* There is at last 2 keys after pointer in buff */
uchar *_nisam_find_half_pos(N_INFO *info, N_KEYDEF *keyinfo, uchar *page, uchar *key)
{
uint keys,length,key_ref_length,nod_flag;
uchar *end,*lastpos;
DBUG_ENTER("_nisam_find_half_pos");
nod_flag=test_if_nod(page);
key_ref_length=2+nod_flag;
length=getint(page)-key_ref_length;
page+=key_ref_length;
if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
{
keys=(length/(keyinfo->base.keylength+nod_flag))/2;
DBUG_RETURN(page+keys*(keyinfo->base.keylength+nod_flag));
}
end=page+length/2-key_ref_length; /* This is aprox. half */
*key='\0';
do
{
lastpos=page;
VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,key));
} while (page < end);
DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx",lastpos,page,end));
DBUG_RETURN(lastpos);
} /* _nisam_find_half_pos */
/* Balance page with not packed keys with page on right/left */
/* returns 0 if balance was done */
static int _nisam_balance_page(register N_INFO *info, N_KEYDEF *keyinfo,
uchar *key, uchar *curr_buff, uchar *father_buff,
uchar *father_key_pos, ulong father_page)
{
my_bool right;
uint k_length,father_length,father_keylength,nod_flag,curr_keylength,
right_length,left_length,new_right_length,new_left_length,extra_length,
length,keys;
uchar *pos,*buff,*extra_buff;
ulong next_page,new_pos;
byte tmp_part_key[N_MAX_KEY_BUFF];
DBUG_ENTER("_nisam_balance_page");
k_length=keyinfo->base.keylength;
father_length=getint(father_buff);
father_keylength=k_length+info->s->base.key_reflength;
nod_flag=test_if_nod(curr_buff);
curr_keylength=k_length+nod_flag;
info->page_changed=1;
if ((father_key_pos != father_buff+father_length && (info->s->rnd++ & 1)) ||
father_key_pos == father_buff+2+info->s->base.key_reflength)
{
right=1;
next_page= _nisam_kpos(info->s->base.key_reflength,
father_key_pos+father_keylength);
buff=info->buff;
DBUG_PRINT("test",("use right page: %lu",next_page));
}
else
{
right=0;
father_key_pos-=father_keylength;
next_page= _nisam_kpos(info->s->base.key_reflength,father_key_pos);
/* Fix that curr_buff is to left */
buff=curr_buff; curr_buff=info->buff;
DBUG_PRINT("test",("use left page: %lu",next_page));
} /* father_key_pos ptr to parting key */
if (!_nisam_fetch_keypage(info,keyinfo,next_page,info->buff,0))
goto err;
DBUG_DUMP("next",(byte*) info->buff,getint(info->buff));
/* Test if there is room to share keys */
left_length=getint(curr_buff);
right_length=getint(buff);
keys=(left_length+right_length-4-nod_flag*2)/curr_keylength;
if ((right ? right_length : left_length) + curr_keylength <=
keyinfo->base.block_length)
{ /* Merge buffs */
new_left_length=2+nod_flag+(keys/2)*curr_keylength;
new_right_length=2+nod_flag+((keys+1)/2)*curr_keylength;
putint(curr_buff,new_left_length,nod_flag);
putint(buff,new_right_length,nod_flag);
if (left_length < new_left_length)
{ /* Move keys buff -> leaf */
pos=curr_buff+left_length;
memcpy((byte*) pos,(byte*) father_key_pos, (size_t) k_length);
memcpy((byte*) pos+k_length, (byte*) buff+2,
(size_t) (length=new_left_length - left_length - k_length));
pos=buff+2+length;
memcpy((byte*) father_key_pos,(byte*) pos,(size_t) k_length);
bmove((byte*) buff+2,(byte*) pos+k_length,new_right_length);
}
else
{ /* Move keys -> buff */
bmove_upp((byte*) buff+new_right_length,(byte*) buff+right_length,
right_length-2);
length=new_right_length-right_length-k_length;
memcpy((byte*) buff+2+length,father_key_pos,(size_t) k_length);
pos=curr_buff+new_left_length;
memcpy((byte*) father_key_pos,(byte*) pos,(size_t) k_length);
memcpy((byte*) buff+2,(byte*) pos+k_length,(size_t) length);
}
if (_nisam_write_keypage(info,keyinfo,next_page,info->buff) ||
_nisam_write_keypage(info,keyinfo,father_page,father_buff))
goto err;
DBUG_RETURN(0);
}
/* curr_buff[] and buff[] are full, lets splitt and make new nod */
extra_buff=info->buff+info->s->base.max_block;
new_left_length=new_right_length=2+nod_flag+(keys+1)/3*curr_keylength;
if (keys == 5) /* Too few keys to balance */
new_left_length-=curr_keylength;
extra_length=nod_flag+left_length+right_length-new_left_length-new_right_length-curr_keylength;
DBUG_PRINT("info",("left_length: %d right_length: %d new_left_length: %d new_right_length: %d extra_length: %d",
left_length, right_length,
new_left_length, new_right_length,
extra_length));
putint(curr_buff,new_left_length,nod_flag);
putint(buff,new_right_length,nod_flag);
putint(extra_buff,extra_length+2,nod_flag);
/* move first largest keys to new page */
pos=buff+right_length-extra_length;
memcpy((byte*) extra_buff+2,pos,(size_t) extra_length);
/* Save new parting key */
memcpy(tmp_part_key, pos-k_length,k_length);
/* Make place for new keys */
bmove_upp((byte*) buff+new_right_length,(byte*) pos-k_length,
right_length-extra_length-k_length-2);
/* Copy keys from left page */
pos= curr_buff+new_left_length;
memcpy((byte*) buff+2,(byte*) pos+k_length,
(size_t) (length=left_length-new_left_length-k_length));
/* Copy old parting key */
memcpy((byte*) buff+2+length,father_key_pos,(size_t) k_length);
/* Move new parting keys up */
memcpy((byte*) (right ? key : father_key_pos),pos, (size_t) k_length);
memcpy((byte*) (right ? father_key_pos : key), tmp_part_key, k_length);
if ((new_pos=_nisam_new(info,keyinfo)) == NI_POS_ERROR)
goto err;
_nisam_kpointer(info,key+k_length,new_pos);
if (_nisam_write_keypage(info,keyinfo,(right ? new_pos : next_page),
info->buff) ||
_nisam_write_keypage(info,keyinfo,(right ? next_page : new_pos),extra_buff))
goto err;
DBUG_RETURN(1); /* Middle key up */
err:
DBUG_RETURN(-1);
} /* _nisam_balance_page */

View File

@ -3151,6 +3151,7 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
param->store_param_func= store_param_str;
@ -4034,6 +4035,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
DBUG_ASSERT(param->buffer_length != 0);
param->fetch_result= fetch_result_bin;
break;
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
DBUG_ASSERT(param->buffer_length != 0);
@ -4098,6 +4100,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
param->skip_result= skip_result_string;

View File

@ -39,7 +39,7 @@ libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
noinst_HEADERS = embedded_priv.h emb_qcache.h
sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \
ha_innodb.cc ha_berkeley.cc ha_heap.cc \
ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \
hostname.cc init.cc password.c \
item.cc item_buff.cc item_cmpfunc.cc item_create.cc \

View File

@ -28,7 +28,7 @@ const HA_KEYSEG ft_keysegs[FT_SEGS]={
HA_KEYTYPE_VARTEXT, /* type */
63, /* language (will be overwritten) */
0, 0, 0, /* null_bit, bit_start, bit_end */
HA_VAR_LENGTH | HA_PACK_KEY, /* flag */
HA_VAR_LENGTH_PART | HA_PACK_KEY, /* flag */
HA_FT_MAXBYTELEN, /* length */
HA_FT_WLEN, /* start */
0, /* null_pos */

View File

@ -91,7 +91,7 @@ static int run_test(const char *filename)
keyinfo[0].keysegs=1;
keyinfo[0].seg[0].type= key_type;
keyinfo[0].seg[0].flag= (key_field == FIELD_BLOB)?HA_BLOB_PART:
(key_field == FIELD_VARCHAR)?HA_VAR_LENGTH:0;
(key_field == FIELD_VARCHAR)?HA_VAR_LENGTH_PART:0;
keyinfo[0].seg[0].start=recinfo[0].length;
keyinfo[0].seg[0].length=key_length;
keyinfo[0].seg[0].null_bit= 0;

View File

@ -77,7 +77,7 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi)
DBUG_RETURN(1);
}
ftsi->pos= ftsi->rec+ftsi->seg->start;
if (ftsi->seg->flag & HA_VAR_LENGTH)
if (ftsi->seg->flag & HA_VAR_LENGTH_PART)
{
ftsi->len=uint2korr(ftsi->pos);
ftsi->pos+=2; /* Skip VARCHAR length */

View File

@ -2024,7 +2024,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
sort_param.key_length+=keyseg[i].length;
if (keyseg[i].flag & HA_SPACE_PACK)
sort_param.key_length+=get_pack_length(keyseg[i].length);
if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH))
if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
sort_param.key_length+=2 + test(keyseg[i].length >= 127);
if (keyseg[i].flag & HA_NULL_PART)
sort_param.key_length++;
@ -2433,7 +2433,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
sort_param[i].key_length+=keyseg->length;
if (keyseg->flag & HA_SPACE_PACK)
sort_param[i].key_length+=get_pack_length(keyseg->length);
if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH))
if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
sort_param[i].key_length+=2 + test(keyseg->length >= 127);
if (keyseg->flag & HA_NULL_PART)
sort_param[i].key_length++;

View File

@ -276,8 +276,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
goto err;
#endif /*HAVE_SPATIAL*/
}
else
if (keydef->flag & HA_FULLTEXT)
else if (keydef->flag & HA_FULLTEXT)
{
keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
@ -310,7 +309,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Only use HA_PACK_KEY when first segment is a variable length key */
if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
HA_VAR_LENGTH)))
HA_VAR_LENGTH_PART)))
{
/* pack relative to previous key */
keydef->flag&= ~HA_PACK_KEY;
@ -344,12 +343,18 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
case HA_KEYTYPE_UINT24:
case HA_KEYTYPE_INT8:
keyseg->flag|= HA_SWAP_KEY;
/* fall through */
break;
case HA_KEYTYPE_VARTEXT:
case HA_KEYTYPE_VARBINARY:
if (!(keyseg->flag & HA_BLOB_PART))
keyseg->flag|= HA_VAR_LENGTH_PART;
break;
default:
break;
}
if (keyseg->flag & HA_SPACE_PACK)
{
DBUG_ASSERT(!(keyseg->flag & HA_VAR_LENGTH_PART));
keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
length++; /* At least one length byte */
@ -360,7 +365,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
length+=2;
}
}
if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
{
keydef->flag|=HA_VAR_LENGTH_KEY;
length++; /* At least one length byte */

View File

@ -102,7 +102,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
key+=char_length;
continue;
}
if (keyseg->flag & HA_VAR_LENGTH)
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint tmp_length=uint2korr(pos);
pos+=2; /* Skip VARCHAR length */
@ -216,7 +216,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
if (!(*key++= (char) 1-*old++)) /* Copy null marker */
{
k_length-=length;
if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
k_length-=2; /* Skip length */
continue; /* Found NULL */
}
@ -244,7 +244,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
key+= char_length;
continue;
}
else if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
else if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
{
/* Length of key-part used with mi_rkey() always 2 */
uint tmp_length=uint2korr(pos);
@ -356,7 +356,7 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
continue;
}
if (keyseg->flag & HA_VAR_LENGTH)
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint length;
get_key_length(length,key);
@ -364,7 +364,10 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
if (length > keyseg->length || key+length > key_end)
goto err;
#endif
memcpy(record+keyseg->start,(byte*) key, length);
/* Store key length */
int2store(record+keyseg->start, length);
/* And key data */
memcpy(record+keyseg->start+2,(byte*) key, length);
key+= length;
}
else if (keyseg->flag & HA_BLOB_PART)

View File

@ -172,9 +172,9 @@ static double _mi_search_pos(register MI_INFO *info,
if (flag == MI_FOUND_WRONG_KEY)
DBUG_RETURN(-1); /* error */
/*
** Didn't found match. keypos points at next (bigger) key
* Try to find a smaller, better matching key.
** Matches keynr + [0-1]
Didn't found match. keypos points at next (bigger) key
Try to find a smaller, better matching key.
Matches keynr + [0-1]
*/
if (flag > 0 && ! nod_flag)
offset= 1.0;
@ -185,8 +185,8 @@ static double _mi_search_pos(register MI_INFO *info,
else
{
/*
** Found match. Keypos points at the start of the found key
** Matches keynr+1
Found match. Keypos points at the start of the found key
Matches keynr+1
*/
offset=1.0; /* Matches keynr+1 */
if ((nextflag & SEARCH_FIND) && nod_flag &&
@ -194,8 +194,8 @@ static double _mi_search_pos(register MI_INFO *info,
key_len != USE_WHOLE_KEY))
{
/*
** There may be identical keys in the tree. Try to match on of those.
** Matches keynr + [0-1]
There may be identical keys in the tree. Try to match on of those.
Matches keynr + [0-1]
*/
if ((offset=_mi_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
_mi_kpos(nod_flag,keypos))) < 0)

View File

@ -57,7 +57,11 @@ int mi_rnext_same(MI_INFO *info, byte *buf)
#endif
case HA_KEY_ALG_BTREE:
default:
memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
if (!(info->update & HA_STATE_RNEXT_SAME))
{
/* First rnext_same; Store old key */
memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
}
for (;;)
{
if ((error=_mi_search_next(info,keyinfo,info->lastkey,
@ -81,7 +85,7 @@ int mi_rnext_same(MI_INFO *info, byte *buf)
rw_unlock(&info->s->key_root_lock[inx]);
/* Don't clear if database-changed */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
info->update|= HA_STATE_NEXT_FOUND;
info->update|= HA_STATE_NEXT_FOUND | HA_STATE_RNEXT_SAME;
if (error)
{

View File

@ -364,7 +364,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
if (!(*from++))
continue;
}
if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
get_key_length(l,from);
}
@ -831,7 +831,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
continue;
}
if (keyseg->flag &
(HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
(HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
uchar *tmp=page;
get_key_length(length,tmp);
@ -896,7 +896,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
if (!(*key++ = *from++))
continue; /* Null part */
}
if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
/* Get length of dynamic length key part */
if (from == from_end) { from=page; from_end=page_end; }
@ -1071,7 +1071,7 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
if (keyseg->flag & HA_NULL_PART)
if (!*key++)
continue;
if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint length;
get_key_length(length,key);
@ -1103,7 +1103,7 @@ uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key,
if (keyseg->flag & HA_NULL_PART)
if (!*key++)
continue;
if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint length;
get_key_length(length,key);

View File

@ -134,7 +134,7 @@ static int run_test(const char *filename)
uniqueseg[1].flag|= HA_BLOB_PART;
}
else if (extra_field == FIELD_VARCHAR)
uniqueseg[1].flag|= HA_VAR_LENGTH;
uniqueseg[1].flag|= HA_VAR_LENGTH_PART;
}
else
uniques=0;
@ -372,7 +372,7 @@ static void create_key(char *key,uint rownr)
}
*key++=0;
}
if (keyinfo[0].seg[0].flag & (HA_BLOB_PART | HA_VAR_LENGTH))
if (keyinfo[0].seg[0].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint tmp;
create_key_part(key+2,rownr);
@ -524,7 +524,7 @@ static struct my_option my_long_options[] =
{"key_binary_pack", 'B', "Undocumented",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_blob", 'b', "Undocumented",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_cache", 'K', "Undocumented", (gptr*) &key_cacheing,
(gptr*) &key_cacheing, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_length", 'k', "Undocumented", (gptr*) &key_length, (gptr*) &key_length,
@ -617,7 +617,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
key_field=FIELD_VARCHAR; /* varchar keys */
extra_field= FIELD_VARCHAR;
key_type= HA_KEYTYPE_VARTEXT;
pack_seg|= HA_VAR_LENGTH;
pack_seg|= HA_VAR_LENGTH_PART;
create_flag|= HA_PACK_RECORD;
break;
case 'K': /* Use key cacheing */

View File

@ -93,7 +93,7 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
}
}
pos= record+keyseg->start;
if (keyseg->flag & HA_VAR_LENGTH)
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint tmp_length=uint2korr(pos);
pos+=2; /* Skip VARCHAR length */
@ -136,7 +136,8 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
{
enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
uint length=keyseg->length;
uint a_length, b_length;
a_length= b_length= keyseg->length;
/* If part is NULL it's regarded as different */
if (keyseg->null_bit)
@ -154,43 +155,49 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
}
pos_a= a+keyseg->start;
pos_b= b+keyseg->start;
if (keyseg->flag & HA_VAR_LENGTH)
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint tmp_length=uint2korr(pos_a);
if (tmp_length != uint2korr(pos_b))
return 1;
pos_a+=2; /* Skip VARCHAR length */
pos_b+=2;
set_if_smaller(length,tmp_length);
a_length= uint2korr(pos_a);
b_length= uint2korr(pos_b);
pos_a+= 2; /* Skip VARCHAR length */
pos_b+= 2;
set_if_smaller(a_length, keyseg->length);
set_if_smaller(b_length, keyseg->length);
}
else if (keyseg->flag & HA_BLOB_PART)
{
/* Only compare 'length' characters if length<> 0 */
uint a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
uint b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
/* Only compare 'length' characters if length != 0 */
a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
/* Check that a and b are of equal length */
if (length && a_length > length)
a_length=length;
if (!length || length > b_length)
length=b_length;
if (length != a_length)
return 1;
/* Both strings are at least 'length' long */
if (keyseg->length)
{
/*
This is used in some cases when we are not interested in comparing
the whole length of the blob.
*/
set_if_smaller(a_length, keyseg->length);
set_if_smaller(b_length, keyseg->length);
}
memcpy_fixed((byte*) &pos_a,pos_a+keyseg->bit_start,sizeof(char*));
memcpy_fixed((byte*) &pos_b,pos_b+keyseg->bit_start,sizeof(char*));
}
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{
if (mi_compare_text(keyseg->charset, (uchar *) pos_a, length,
(uchar *) pos_b, length, 0, 0))
return 1;
if (mi_compare_text(keyseg->charset, (uchar *) pos_a, a_length,
(uchar *) pos_b, b_length, 0, 1))
return 1;
}
else
{
end= pos_a+length;
if (a_length != b_length)
return 1;
end= pos_a+a_length;
while (pos_a != end)
{
if (*pos_a++ != *pos_b++)
return 1;
}
}
}
return 0;

View File

@ -253,7 +253,7 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
comp_flag=SEARCH_BIGGER; /* Put after same key */
else if (keyinfo->flag & (HA_NOSAME|HA_FULLTEXT))
{
comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */
comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No duplicates */
if (keyinfo->flag & HA_NULL_ARE_EQUAL)
comp_flag|= SEARCH_NULL_ARE_EQUAL;
}

View File

@ -50,7 +50,7 @@ static int stopwords_inited= 0;
static MY_TMPDIR myisamchk_tmpdir;
static const char *type_names[]=
{ "?","char","binary", "short", "long", "float",
{ "impossible","char","binary", "short", "long", "float",
"double","number","unsigned short",
"unsigned long","longlong","ulonglong","int24",
"uint24","int8","varchar", "varbin","?",

View File

@ -0,0 +1,162 @@
# Initialise
--disable_warnings
drop table if exists t1,t2,t3;
--enable_warnings
disable_query_log;
select "--- Testing varchar ---";
enable_query_log;
#
# Simple basic test that endspace is saved
#
create table t1 (v varchar(10), c char(10), t text);
insert into t1 values('+ ', '+ ', '+ ');
set @a=repeat(' ',20);
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
select concat('*',v,'*',c,'*',t,'*') from t1;
# Check how columns are copied
show create table t1;
create table t2 like t1;
show create table t2;
create table t3 select * from t1;
show create table t3;
alter table t1 modify c varchar(10);
show create table t1;
alter table t1 modify v char(10);
show create table t1;
alter table t1 modify t varchar(10);
show create table t1;
select concat('*',v,'*',c,'*',t,'*') from t1;
drop table t1,t2,t3;
#
# Testing of keys
#
create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
show create table t1;
disable_query_log;
let $1=10;
while ($1)
{
let $2=27;
eval set @space=repeat(' ',10-$1);
while ($2)
{
eval set @char=char(ascii('a')+$2-1);
insert into t1 values(concat(@char,@space),concat(@char,@space),concat(@char,@space));
dec $2;
}
dec $1;
}
enable_query_log;
select count(*) from t1;
insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
select count(*) from t1 where v='a';
select count(*) from t1 where c='a';
select count(*) from t1 where t='a';
select count(*) from t1 where v='a ';
select count(*) from t1 where c='a ';
select count(*) from t1 where t='a ';
select count(*) from t1 where v between 'a' and 'a ';
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
select count(*) from t1 where v like 'a%';
select count(*) from t1 where c like 'a%';
select count(*) from t1 where t like 'a%';
select count(*) from t1 where v like 'a %';
explain select count(*) from t1 where v='a ';
explain select count(*) from t1 where c='a ';
explain select count(*) from t1 where t='a ';
explain select count(*) from t1 where v like 'a%';
explain select count(*) from t1 where v between 'a' and 'a ';
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
--error 1062
alter table t1 add unique(v);
alter table t1 add key(v);
select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
explain select * from t1 where v='a';
# GROUP BY
select v,count(*) from t1 group by v limit 10;
select v,count(t) from t1 group by v limit 10;
select v,count(c) from t1 group by v limit 10;
select sql_big_result v,count(t) from t1 group by v limit 10;
select sql_big_result v,count(c) from t1 group by v limit 10;
select c,count(*) from t1 group by c limit 10;
select c,count(t) from t1 group by c limit 10;
select sql_big_result c,count(t) from t1 group by c limit 10;
select t,count(*) from t1 group by t limit 10;
select t,count(t) from t1 group by t limit 10;
select sql_big_result t,count(t) from t1 group by t limit 10;
drop table t1;
#
# Test unique keys
#
create table t1 (a char(10), unique (a));
insert into t1 values ('a ');
--error 1062
insert into t1 values ('a ');
alter table t1 modify a varchar(10);
--error 1062
insert into t1 values ('a '),('a '),('a '),('a ');
--error 1062
insert into t1 values ('a ');
--error 1062
insert into t1 values ('a ');
--error 1062
insert into t1 values ('a ');
update t1 set a='a ' where a like 'a%';
select concat(a,'.') from t1;
update t1 set a='abc ' where a like 'a ';
select concat(a,'.') from t1;
update t1 set a='a ' where a like 'a %';
select concat(a,'.') from t1;
update t1 set a='a ' where a like 'a ';
select concat(a,'.') from t1;
drop table t1;
#
# test show create table
#
create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
show create table t1;
drop table t1;
create table t1 (v char(10) character set utf8);
show create table t1;
drop table t1;
create table t1 (v varchar(10), c char(10)) row_format=fixed;
show create table t1;
insert into t1 values('a','a'),('a ','a ');
select concat('*',v,'*',c,'*') from t1;
drop table t1;
#
# Test long varchars
#
create table t1 (v varchar(65530), key(v(10)));
insert into t1 values(repeat('a',65530));
select length(v) from t1 where v=repeat('a',65530);
drop table t1;
#
# Some errors/warnings on create
#
create table t1 (v varchar(65530), key(v));
drop table if exists t1;
create table t1 (v varchar(65536));
show create table t1;
drop table t1;
create table t1 (v varchar(65530) character set utf8);
show create table t1;
drop table t1;

View File

@ -140,13 +140,13 @@ id parent_id level
1015 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref level level 1 const 1 Using index
1 SIMPLE t1 ref level level 1 const 6 Using index
explain select level,id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref level level 1 const 1 Using index
1 SIMPLE t1 ref level level 1 const 6 Using index
explain select level,id,parent_id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref level level 1 const 1
1 SIMPLE t1 ref level level 1 const 6
select level,id from t1 where level=1;
level id
1 1002
@ -625,7 +625,7 @@ id parent_id level
1016 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref level level 1 const 1 Using index
1 SIMPLE t1 ref level level 1 const 6 Using index
select level,id from t1 where level=1;
level id
1 1004
@ -1284,3 +1284,382 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
id
4
DROP TABLE t1;
set storage_engine=bdb;
drop table if exists t1,t2,t3;
--- Testing varchar ---
--- Testing varchar ---
create table t1 (v varchar(10), c char(10), t text);
insert into t1 values('+ ', '+ ', '+ ');
set @a=repeat(' ',20);
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
Warnings:
Warning 1265 Data truncated for column 'v' at row 1
select concat('*',v,'*',c,'*',t,'*') from t1;
concat('*',v,'*',c,'*',t,'*')
*+ *+*+ *
*+ *+*+ *
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` text
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
create table t2 like t1;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` text
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
create table t3 select * from t1;
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` text
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
alter table t1 modify c varchar(10);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` varchar(10) default NULL,
`t` text
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
alter table t1 modify v char(10);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` char(10) default NULL,
`c` varchar(10) default NULL,
`t` text
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
alter table t1 modify t varchar(10);
Warnings:
Warning 1265 Data truncated for column 't' at row 2
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` char(10) default NULL,
`c` varchar(10) default NULL,
`t` varchar(10) default NULL
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
select concat('*',v,'*',c,'*',t,'*') from t1;
concat('*',v,'*',c,'*',t,'*')
*+*+*+ *
*+*+*+ *
drop table t1,t2,t3;
create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` text,
KEY `v` (`v`),
KEY `c` (`c`),
KEY `t` (`t`(10))
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
270
insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
select count(*) from t1 where v='a';
count(*)
10
select count(*) from t1 where c='a';
count(*)
10
select count(*) from t1 where t='a';
count(*)
10
select count(*) from t1 where v='a ';
count(*)
10
select count(*) from t1 where c='a ';
count(*)
10
select count(*) from t1 where t='a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
count(*)
10
select count(*) from t1 where v like 'a%';
count(*)
11
select count(*) from t1 where c like 'a%';
count(*)
11
select count(*) from t1 where t like 'a%';
count(*)
11
select count(*) from t1 where v like 'a %';
count(*)
9
explain select count(*) from t1 where v='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 13 const 10 Using where
explain select count(*) from t1 where c='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c c 11 const 10 Using where
explain select count(*) from t1 where t='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range t t 13 NULL 10 Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL 11 Using where
explain select count(*) from t1 where v between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL 10 Using where
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL 10 Using where
alter table t1 add unique(v);
ERROR 23000: Duplicate entry '{ ' for key 1
alter table t1 add key(v);
select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
qq
*a*a*a*
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
explain select * from t1 where v='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v,v_2 v 13 const 10 Using where
select v,count(*) from t1 group by v limit 10;
v count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(c) from t1 group by v limit 10;
v count(c)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(c) from t1 group by v limit 10;
v count(c)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select c,count(*) from t1 group by c limit 10;
c count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select c,count(t) from t1 group by c limit 10;
c count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result c,count(t) from t1 group by c limit 10;
c count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select t,count(*) from t1 group by t limit 10;
t count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select t,count(t) from t1 group by t limit 10;
t count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result t,count(t) from t1 group by t limit 10;
t count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
drop table t1;
create table t1 (a char(10), unique (a));
insert into t1 values ('a ');
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a' for key 1
alter table t1 modify a varchar(10);
insert into t1 values ('a '),('a '),('a '),('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
update t1 set a='a ' where a like 'a%';
select concat(a,'.') from t1;
concat(a,'.')
a .
update t1 set a='abc ' where a like 'a ';
select concat(a,'.') from t1;
concat(a,'.')
a .
update t1 set a='a ' where a like 'a %';
select concat(a,'.') from t1;
concat(a,'.')
a .
update t1 set a='a ' where a like 'a ';
select concat(a,'.') from t1;
concat(a,'.')
a .
drop table t1;
create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` text,
KEY `v` (`v`(5)),
KEY `c` (`c`(5)),
KEY `t` (`t`(5))
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
drop table t1;
create table t1 (v char(10) character set utf8);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` char(10) character set utf8 default NULL
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
drop table t1;
create table t1 (v varchar(10), c char(10)) row_format=fixed;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
insert into t1 values('a','a'),('a ','a ');
select concat('*',v,'*',c,'*') from t1;
concat('*',v,'*',c,'*')
*a*a*
*a *a*
drop table t1;
create table t1 (v varchar(65530), key(v(10)));
insert into t1 values(repeat('a',65530));
select length(v) from t1 where v=repeat('a',65530);
length(v)
65530
drop table t1;
create table t1 (v varchar(65530), key(v));
Warnings:
Warning 1071 Specified key was too long; max key length is 255 bytes
drop table if exists t1;
create table t1 (v varchar(65536));
Warnings:
Note 1246 Converting column 'v' from VARCHAR to TEXT
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` mediumtext
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
drop table t1;
create table t1 (v varchar(65530) character set utf8);
Warnings:
Note 1246 Converting column 'v' from VARCHAR to TEXT
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` mediumtext character set utf8
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
drop table t1;
set storage_engine=MyISAM;

View File

@ -415,7 +415,7 @@ a int(11) YES NULL
b bigint(11) 0
c bigint(10) 0
d date YES NULL
e char(1)
e varchar(1)
f datetime YES NULL
g time YES NULL
h longblob

View File

@ -259,8 +259,8 @@ WU
<EFBFBD><EFBFBD>³°×<EFBFBD>
<EFBFBD><EFBFBD>³°<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>³·<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¹µל
<EFBFBD><EFBFBD>¹µ<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¹µל
<EFBFBD><EFBFBD>¹¸<EFBFBD>×<EFBFBD>
<EFBFBD><EFBFBD>¹¸<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¹<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ¹ל
@ -272,8 +272,8 @@ WU
<EFBFBD><EFBFBD>­¨¹<EFBFBD><EFBFBD><EFBFBD>³
<EFBFBD><EFBFBD>­¨¹<EFBFBD>
<EFBFBD><EFBFBD>¹´<EFBFBD>
<EFBFBD><EFBFBD>¹µל
<EFBFBD><EFBFBD>¹µל<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¹µל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·¸<EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>³<EFBFBD>
@ -350,8 +350,8 @@ WU
א<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
א<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
א<EFBFBD><EFBFBD>י<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ב<EFBFBD>י<EFBFBD>
ב<EFBFBD>י<EFBFBD>ד¨
ב<EFBFBD>י<EFBFBD>
ג<EFBFBD><EFBFBD><EFBFBD>¾<EFBFBD>¹¸ל
ג<EFBFBD>א<EFBFBD><EFBFBD>
ג<EFBFBD><EFBFBD>÷<EFBFBD><EFBFBD> ¤<>¹א¹ח¤×<C2A4>ט¹<D798>ל
@ -368,8 +368,8 @@ WU
¢¨<EFBFBD>א<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>
¢¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
¢¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
¢¹<EFBFBD><EFBFBD>°ל
¢¹<EFBFBD><EFBFBD>°<EFBFBD>
¢¹<EFBFBD><EFBFBD>°ל
¢<EFBFBD><EFBFBD>­ד¨
¢<EFBFBD><EFBFBD>­×<EFBFBD><EFBFBD>
¢<EFBFBD><EFBFBD>­א´<EFBFBD><EFBFBD>¹
@ -412,8 +412,8 @@ WU
א¤ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>א»ך<C2BB>«ל
א¤.«<><>. ב<>××<C397>¹א¹<D790><C2B9><EFBFBD>ט
א¤·<EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>«<EFBFBD>ט§
א¤¹ ב<><D791>«ל (»<><C2BB>א·<D790>ה·<D794>)
א¤¹ ב<>ח<EFBFBD>«ל (»<><C2BB>א·<D790>ה·<D794>)
א¤¹ ב<><D791>«ל (»<><C2BB>א·<D790>ה·<D794>)
א¤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ל
ב¤¹¹<EFBFBD> <20><>¹אµ<D790><C2B5>לא·<D790>´
ב¤<EFBFBD>¨י<EFBFBD><EFBFBD>
@ -494,12 +494,12 @@ WU
¨<EFBFBD>א<EFBFBD><EFBFBD>­
¨<EFBFBD><EFBFBD><EFBFBD>§
¨<EFBFBD>³³ל
¨<EFBFBD>µµל
¨<EFBFBD>µµל¹<EFBFBD><EFBFBD><EFBFBD>
¨<EFBFBD>µµ<EFBFBD><EFBFBD><EFBFBD>
¨<EFBFBD>µµ<EFBFBD>
¨<EFBFBD>µµ<EFBFBD>
¨<EFBFBD>µµ<EFBFBD>¹¹<EFBFBD>¹·ל
¨<EFBFBD>µµל
¨<EFBFBD>µ<EFBFBD><EFBFBD>´<EFBFBD>
¨<EFBFBD>µ<EFBFBD><EFBFBD>
¨<EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>³ל
@ -627,10 +627,10 @@ WU
×<EFBFBD>¹¾<EFBFBD><EFBFBD>
×<EFBFBD><EFBFBD><EFBFBD>µ
×<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
×ט<EFBFBD>
×ט<EFBFBD>©<EFBFBD>µ<EFBFBD>
×ט<EFBFBD>·<EFBFBD>¾<EFBFBD>ל
×ט<EFBFBD><EFBFBD><EFBFBD>­×<EFBFBD>­
×ט<EFBFBD>
×<EFBFBD>¹<EFBFBD><EFBFBD>
×<EFBFBD><EFBFBD>י<EFBFBD>¹
×<EFBFBD>××<EFBFBD><EFBFBD>
@ -758,12 +758,12 @@ WU
³¸<EFBFBD>µ<EFBFBD>
³<EFBFBD><EFBFBD>·<EFBFBD>
³<EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD>³ל
³<EFBFBD>§¤ל
³<EFBFBD>§¤ל×<EFBFBD><EFBFBD>
³<EFBFBD>§¤ל¾<EFBFBD>×<EFBFBD>ל
³<EFBFBD>§¤ל<EFBFBD>·¸<EFBFBD>ל
³<EFBFBD>§¤ל<EFBFBD><EFBFBD>·<EFBFBD>ל
³<EFBFBD>§¤ל<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
³<EFBFBD>§¤ל
³<EFBFBD>§<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ל
³<EFBFBD>§<EFBFBD>·¸<EFBFBD>ל
³<EFBFBD>§<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
@ -862,11 +862,11 @@ WU
µ<EFBFBD><EFBFBD><EFBFBD>¹
µ<EFBFBD>ט§¨<EFBFBD>ט§<EFBFBD><EFBFBD><EFBFBD>´ה<EFBFBD>
µ<EFBFBD>א<EFBFBD>ח´
µ<EFBFBD>ך
µ<EFBFBD>ך<EFBFBD>µ<EFBFBD>
µ<EFBFBD>י<EFBFBD>
µ<EFBFBD>כ<EFBFBD>
µ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>³ל
µ<EFBFBD>ך
אµח<EFBFBD>א´×
אµ<EFBFBD><EFBFBD>¹ד¨
אµ<EFBFBD><EFBFBD>¹µ<EFBFBD>
@ -917,8 +917,8 @@ WU
·<EFBFBD>÷·<EFBFBD><EFBFBD>
·<EFBFBD><EFBFBD>¹<EFBFBD><EFBFBD><EFBFBD>³
·<EFBFBD><EFBFBD>¹<EFBFBD>¾<EFBFBD>
·<EFBFBD><EFBFBD>¹<EFBFBD><EFBFBD>ל
·<EFBFBD><EFBFBD>¹<EFBFBD><EFBFBD><EFBFBD>
·<EFBFBD><EFBFBD>¹<EFBFBD><EFBFBD>ל
·<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>³
·ט<EFBFBD>·<EFBFBD><EFBFBD><EFBFBD>ב¨י§<EFBFBD><EFBFBD>²¹<EFBFBD>
·<EFBFBD>¦<EFBFBD><EFBFBD>¾<EFBFBD>
@ -1088,8 +1088,8 @@ WU
¹<EFBFBD>¾<EFBFBD>
¹<EFBFBD><EFBFBD><EFBFBD>·<EFBFBD>ל
¹<EFBFBD><EFBFBD>
¹<EFBFBD><EFBFBD>¹·<EFBFBD>ל
¹<EFBFBD><EFBFBD>¹·<EFBFBD>לא´×
¹<EFBFBD><EFBFBD>¹·<EFBFBD>ל
¹<EFBFBD><EFBFBD><EFBFBD>
¹<EFBFBD><EFBFBD><EFBFBD>°
¹<EFBFBD><EFBFBD>
@ -1115,8 +1115,8 @@ WU
¹<EFBFBD>·¸<EFBFBD>¹
¹<EFBFBD>¹×<EFBFBD><EFBFBD>
¹<EFBFBD>¹·×<EFBFBD><EFBFBD>
¹<EFBFBD>¹·¹ל
¹<EFBFBD>¹·¹<EFBFBD>
¹<EFBFBD>¹·¹ל
¹<EFBFBD>¹·¾<EFBFBD>
¹<EFBFBD>¹·¾<EFBFBD>
¹<EFBFBD>¹·<EFBFBD><EFBFBD><EFBFBD>
@ -1148,14 +1148,14 @@ WU
¹<EFBFBD>א«<EFBFBD>
¹<EFBFBD>´
¹<EFBFBD>´<EFBFBD>
¹<EFBFBD>µ<EFBFBD>ל
¹<EFBFBD>µ<EFBFBD><EFBFBD>
¹<EFBFBD>µ<EFBFBD>ל
¹<EFBFBD>µ<EFBFBD>
¹<EFBFBD>µ<EFBFBD>¾§<EFBFBD>ל
¹<EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD>
¹<EFBFBD>·<EFBFBD><EFBFBD>
¹<EFBFBD>·<EFBFBD><EFBFBD>¹ל
¹<EFBFBD>·<EFBFBD><EFBFBD>¹<EFBFBD><EFBFBD>ל
¹<EFBFBD>·<EFBFBD><EFBFBD>¹ל
¹<EFBFBD>¸<EFBFBD><EFBFBD>´<EFBFBD>
¹<EFBFBD>»»<EFBFBD>¹א¾¹µל(»<><C2BB>א·<D790>ה·<D794>)
¹<EFBFBD>¾¹¸ל
@ -1349,8 +1349,8 @@ WU
»<EFBFBD><EFBFBD>³<EFBFBD><EFBFBD>ל
»<EFBFBD><EFBFBD>ג<EFBFBD>·<EFBFBD>ל
»<EFBFBD><EFBFBD><EFBFBD>¶¹<EFBFBD>
»<EFBFBD><EFBFBD>­­ל
»<EFBFBD><EFBFBD>­­<EFBFBD>
»<EFBFBD><EFBFBD>­­ל
»<EFBFBD><EFBFBD>­´<EFBFBD>
»<EFBFBD><EFBFBD>³´<EFBFBD>
»<EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>
@ -1454,10 +1454,10 @@ WU
¾§<EFBFBD>ל<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
¾§<EFBFBD>ל<EFBFBD><EFBFBD>¹µל
¾§<EFBFBD>ל<EFBFBD>¹<EFBFBD>¹µל
¾¨¹ל
¾¨¹<EFBFBD>
¾¨¹<EFBFBD><EFBFBD>
¾¨¹<EFBFBD><EFBFBD>ל
¾¨¹ל
¾¨<EFBFBD><EFBFBD>¹
¾¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ל
¾¹<EFBFBD>
@ -1504,8 +1504,8 @@ WU
¾<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¤ל
¾<EFBFBD><EFBFBD><EFBFBD>¾<EFBFBD>²¹ל
¾<EFBFBD>י<EFBFBD><EFBFBD>×<EFBFBD><EFBFBD>
¾<EFBFBD><EFBFBD>»<EFBFBD><EFBFBD>ב´§ <20><>¹´י<C2B4>¤<EFBFBD><C2A4>ל<EFBFBD>ל
¾<EFBFBD><EFBFBD>»<EFBFBD><EFBFBD>ב´§ <20><>¹´י<C2B4>¤<EFBFBD><C2A4>ל<EFBFBD>ל ¨<><C2A8><EFBFBD>´
¾<EFBFBD><EFBFBD>»<EFBFBD><EFBFBD>ב´§ <20><>¹´י<C2B4>¤<EFBFBD><C2A4>ל<EFBFBD>ל
¾<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3 ¤<><C2A4>לא«ח¹אµ<D790><C2B5>ל
¾<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3 <20><>¹´י<C2B4>¤<EFBFBD><C2A4>ל<EFBFBD>ל
¾<EFBFBD><EFBFBD>י<EFBFBD>א¾<EFBFBD><EFBFBD>
@ -1604,10 +1604,10 @@ WU
¾<EFBFBD><EFBFBD>·<EFBFBD>§¾<EFBFBD>ח<EFBFBD>¾א¾<EFBFBD><EFBFBD>לµ<EFBFBD>י_
¾<EFBFBD><EFBFBD>¼<EFBFBD>
א¾ח§ <20><> <20><><EFBFBD>¹
א¾ח×<EFBFBD>ל
א¾×<EFBFBD><EFBFBD><EFBFBD>µ¹ל
א¾×<EFBFBD><EFBFBD>´<EFBFBD>
א¾×<EFBFBD><EFBFBD>¹·<EFBFBD>ל
א¾ח×<EFBFBD>ל
א¾ח­¨<EFBFBD>¹·<EFBFBD>ל
א¾ח­·<EFBFBD>¾<EFBFBD>ל
א¾ח­¹<EFBFBD><EFBFBD>
@ -1831,7 +1831,6 @@ WU
<EFBFBD><EFBFBD>א<EFBFBD><EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¹
<EFBFBD><EFBFBD>ט¹<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD>י§
<EFBFBD><EFBFBD>ט§·<EFBFBD>¾<EFBFBD>ל
<EFBFBD><EFBFBD>ט§·<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>ט§¹<EFBFBD><EFBFBD>
@ -1840,11 +1839,12 @@ WU
<EFBFBD><EFBFBD>ט§<EFBFBD><EFBFBD>µ¹ל
<EFBFBD><EFBFBD>ט§<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>ט§א<EFBFBD><EFBFBD><EFBFBD>§
<EFBFBD><EFBFBD>ט§ג<EFBFBD>¨¹ל
<EFBFBD><EFBFBD>ט§ג<EFBFBD>¨¹ל¢¹<EFBFBD>ט§
<EFBFBD><EFBFBD>ט§ג<EFBFBD>¨¹ל
<EFBFBD><EFBFBD>י§<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>³
<EFBFBD><EFBFBD>ט§<EFBFBD><EFBFBD>·<EFBFBD>ל
<EFBFBD><EFBFBD>ט§<EFBFBD><EFBFBD><EFBFBD>³
<EFBFBD><EFBFBD>י§
<EFBFBD><EFBFBD>¨<EFBFBD>
<EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¹<EFBFBD>
@ -1861,8 +1861,8 @@ WU
ב<EFBFBD>¾ב¾¤ ¤<>¹<EFBFBD>µ<EFBFBD><C2B5>¤×<C2A4>ט¹
ג<EFBFBD>§§<EFBFBD>¹א<EFBFBD><EFBFBD>ח<EFBFBD><EFBFBD><EFBFBD><EFBFBD>§א·¾<EFBFBD>
ג<EFBFBD>¨¹ל»<EFBFBD><EFBFBD>א<EFBFBD><EFBFBD><EFBFBD>°
<EFBFBD>·¸<EFBFBD>ל
<EFBFBD>·¸<EFBFBD>×<EFBFBD><EFBFBD>
<EFBFBD>·¸<EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>ט<EFBFBD><EFBFBD>
@ -2050,8 +2050,8 @@ WU
<EFBFBD><EFBFBD>ה<EFBFBD><EFBFBD><EFBFBD><EFBFBD>³
<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¸¹ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>²¹ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>²¹ל×<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>²¹ל
<EFBFBD><EFBFBD><EFBFBD>¹<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
@ -2146,11 +2146,11 @@ WU
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל×<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>לא×<EFBFBD>§
<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל´<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל<EFBFBD><EFBFBD>÷<EFBFBD><EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¹·<EFBFBD>ל
<EFBFBD><EFBFBD>¹<EFBFBD>¹<EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD>¹µ<EFBFBD>ב<EFBFBD>¹´ל
@ -2348,18 +2348,18 @@ WU
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>­
<EFBFBD><EFBFBD><EFBFBD>·¸<EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>§<EFBFBD>ל
<EFBFBD><EFBFBD>§<EFBFBD>ל¾<EFBFBD>
<EFBFBD><EFBFBD>§<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>§<EFBFBD>ל
<EFBFBD><EFBFBD>µ<EFBFBD>¹<EFBFBD>¹
<EFBFBD><EFBFBD>µ<EFBFBD>¾<EFBFBD>
<EFBFBD><EFBFBD>·¸<EFBFBD>
<EFBFBD><EFBFBD>·¸<EFBFBD>ל
<EFBFBD><EFBFBD>·¸<EFBFBD>×<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>·¸<EFBFBD>א´×
<EFBFBD><EFBFBD>·¸<EFBFBD>¾<EFBFBD>
<EFBFBD><EFBFBD>·¸<EFBFBD>¾<EFBFBD><EFBFBD>³
<EFBFBD><EFBFBD>·¸<EFBFBD>¾<EFBFBD>
<EFBFBD><EFBFBD>·¸<EFBFBD>ל
<EFBFBD><EFBFBD>¹·<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>×<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>א´×
@ -2393,15 +2393,15 @@ WU
<EFBFBD><EFBFBD>¢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¢<EFBFBD><EFBFBD>¹µל
<EFBFBD><EFBFBD>¢<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¤¹¸ל
<EFBFBD><EFBFBD>¤¹¸<EFBFBD>
<EFBFBD><EFBFBD>¤¹¸ל
<EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¨<EFBFBD>µ
<EFBFBD><EFBFBD>¨<EFBFBD>µµ<EFBFBD>
<EFBFBD><EFBFBD>¨<EFBFBD>µ<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¨<EFBFBD>¹´<EFBFBD>
<EFBFBD><EFBFBD>¨<EFBFBD>¹µל
<EFBFBD><EFBFBD>¨<EFBFBD>¹µ¹ל
<EFBFBD><EFBFBD>¨<EFBFBD>¹µל
<EFBFBD><EFBFBD>×<EFBFBD>
<EFBFBD><EFBFBD>×<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>×<EFBFBD>´<EFBFBD>
@ -2443,13 +2443,13 @@ WU
<EFBFBD><EFBFBD>¸<EFBFBD>´<EFBFBD>
<EFBFBD><EFBFBD>¸<EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
<EFBFBD><EFBFBD>¸<EFBFBD>
<EFBFBD><EFBFBD>¸<EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD>¸<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¸<EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD>¹·<EFBFBD>
<EFBFBD><EFBFBD>¹·<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¹<EFBFBD>··<EFBFBD>
<EFBFBD><EFBFBD>¹<EFBFBD>¹·ל
<EFBFBD><EFBFBD>¹<EFBFBD>¹·<EFBFBD>
<EFBFBD><EFBFBD>¹<EFBFBD>¹·ל
<EFBFBD><EFBFBD>¹<EFBFBD>µ<EFBFBD>
<EFBFBD><EFBFBD>¹<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>¹<EFBFBD><EFBFBD><EFBFBD>
@ -2511,10 +2511,10 @@ WU
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·¸<EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>×¹<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ¹ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ¹<EFBFBD>´<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ¹ל<EFBFBD>´<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ¹<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ¹ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>§¤¹<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>×<EFBFBD><EFBFBD>
@ -2529,8 +2529,8 @@ WU
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¸<EFBFBD>¾<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¾<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ל¾<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ¹ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>´´<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD>ל
@ -2540,9 +2540,9 @@ WU
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>³<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>³<EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ¹ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>²¹ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>²¹ל×<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>²¹<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>²¹ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ×<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>×<EFBFBD><EFBFBD>
@ -2623,8 +2623,8 @@ WU
<EFBFBD>¹¹·ל
<EFBFBD>¹<EFBFBD><EFBFBD>×
<EFBFBD>¹<EFBFBD>­­<EFBFBD>
<EFBFBD>¹<EFBFBD>¹µל
<EFBFBD>¹<EFBFBD>¹µ<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>ל
<EFBFBD>¹<EFBFBD>¹µל
<EFBFBD>¹<EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>
<EFBFBD>¹<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD>¹<EFBFBD>×<EFBFBD>
@ -2770,8 +2770,8 @@ WU
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¾<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ל א<><D790><EFBFBD>©<EFBFBD><C2A9> (ה·<D794>א÷¹<C3B7><C2B9>¹
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ¹ל
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>³
<EFBFBD><EFBFBD>¹<EFBFBD><EFBFBD>

View File

@ -1,15 +1,23 @@
DROP TABLE IF EXISTS t1;
SET CHARACTER SET koi8r;
CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2);
INSERT INTO t1 VALUES (_koi8r'ò'), (X'2004');
CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2, word2 CHAR(64) CHARACTER SET ucs2);
INSERT INTO t1 VALUES (_koi8r'ò',_koi8r'ò'), (X'2004',X'2004');
SELECT hex(word) FROM t1 ORDER BY word;
hex(word)
0420
2004
SELECT hex(word2) FROM t1 ORDER BY word2;
hex(word2)
0420
2004
DELETE FROM t1;
INSERT INTO t1 VALUES (X'042000200020'), (X'200400200020');
INSERT INTO t1 VALUES (X'042000200020',X'042000200020'), (X'200400200020', X'200400200020');
SELECT hex(word) FROM t1 ORDER BY word;
hex(word)
042000200020
200400200020
SELECT hex(word2) FROM t1 ORDER BY word2;
hex(word2)
0420
2004
DROP TABLE t1;

View File

@ -43,7 +43,7 @@ teststring
teststring
explain select * from t1 order by text1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL key1 32 NULL 3 Using index
1 SIMPLE t1 index NULL key1 34 NULL 3 Using index
alter table t1 modify text1 char(32) binary not null;
check table t1;
Table Op Msg_type Msg_text
@ -99,15 +99,15 @@ concat('|', text1, '|')
explain select concat('|', text1, '|') from t1 where text1='teststring ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range key1 key1 22 NULL 2 Using where
select * from t1 where text1 like 'teststring_%';
text1
teststring
teststring
select * from t1 where text1='teststring' or text1 like 'teststring_%';
text1
teststring
teststring
teststring
select concat('|', text1, '|') from t1 where text1 like 'teststring_%';
concat('|', text1, '|')
|teststring |
|teststring |
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
concat('|', text1, '|')
|teststring |
|teststring|
|teststring |
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
concat('|', text1, '|')
|teststring|
@ -121,14 +121,14 @@ concat('|', text1, '|')
drop table t1;
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1)) pack_keys=0;
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
select * from t1 where text1='teststring' or text1 like 'teststring_%';
text1
teststring
teststring
select * from t1 where text1='teststring' or text1 >= 'teststring\t';
text1
teststring
teststring
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
concat('|', text1, '|')
|teststring |
|teststring|
select concat('|', text1, '|') from t1 where text1='teststring' or text1 >= 'teststring\t';
concat('|', text1, '|')
|teststring |
|teststring|
drop table t1;
create table t1 (text1 varchar(32) not NULL, KEY key1 using BTREE (text1)) engine=heap;
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
@ -151,7 +151,7 @@ teststring
teststring
explain select * from t1 order by text1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL key1 32 NULL 3
1 SIMPLE t1 index NULL key1 34 NULL 3
alter table t1 modify text1 char(32) binary not null;
select * from t1 order by text1;
text1
@ -200,12 +200,10 @@ teststring
teststring
select text1, length(text1) from t1 where text1='teststring' or text1 like 'teststring_%';
text1 length(text1)
teststring 10
teststring 11
teststring 11
select text1, length(text1) from t1 where text1='teststring' or text1 >= 'teststring\t';
text1 length(text1)
teststring 10
teststring 11
teststring 11
select concat('|', text1, '|') from t1 order by text1;

View File

@ -3,10 +3,10 @@ create table t1 (a varchar(10), key(a));
insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
explain select * from t1 where a like 'abc%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index a a 11 NULL 5 Using where; Using index
1 SIMPLE t1 index a a 13 NULL 5 Using where; Using index
explain select * from t1 where a like concat('abc','%');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index a a 11 NULL 5 Using where; Using index
1 SIMPLE t1 index a a 13 NULL 5 Using where; Using index
select * from t1 where a like "abc%";
a
abc

View File

@ -1,4 +1,4 @@
drop table if exists t1;
drop table if exists t1,t2,t3;
create table t1 (a int not null,b int not null, primary key (a)) engine=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
insert into t1 values(1,1),(2,2),(3,3),(4,4);
delete from t1 where a=1 or a=0;
@ -233,3 +233,421 @@ SELECT * FROM t1 WHERE B is not null;
a B
1 1
DROP TABLE t1;
set storage_engine=HEAP;
create table t1 (v varchar(10), c char(10), t varchar(50));
insert into t1 values('+ ', '+ ', '+ ');
set @a=repeat(' ',20);
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
Warnings:
Warning 1265 Data truncated for column 'v' at row 1
select concat('*',v,'*',c,'*',t,'*') from t1;
concat('*',v,'*',c,'*',t,'*')
*+ *+*+ *
*+ *+*+ *
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` varchar(50) default NULL
) ENGINE=HEAP DEFAULT CHARSET=latin1
create table t2 like t1;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` varchar(50) default NULL
) ENGINE=HEAP DEFAULT CHARSET=latin1
create table t3 select * from t1;
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` varchar(50) default NULL
) ENGINE=HEAP DEFAULT CHARSET=latin1
alter table t1 modify c varchar(10);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` varchar(10) default NULL,
`t` varchar(50) default NULL
) ENGINE=HEAP DEFAULT CHARSET=latin1
alter table t1 modify v char(10);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` char(10) default NULL,
`c` varchar(10) default NULL,
`t` varchar(50) default NULL
) ENGINE=HEAP DEFAULT CHARSET=latin1
alter table t1 modify t varchar(10);
Warnings:
Warning 1265 Data truncated for column 't' at row 2
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` char(10) default NULL,
`c` varchar(10) default NULL,
`t` varchar(10) default NULL
) ENGINE=HEAP DEFAULT CHARSET=latin1
select concat('*',v,'*',c,'*',t,'*') from t1;
concat('*',v,'*',c,'*',t,'*')
*+*+*+ *
*+*+*+ *
drop table t1,t2,t3;
create table t1 (v varchar(10), c char(10), t varchar(50), key(v), key(c), key(t(10)));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` varchar(50) default NULL,
KEY `v` (`v`),
KEY `c` (`c`),
KEY `t` (`t`(10))
) ENGINE=HEAP DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
270
insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
select count(*) from t1 where v='a';
count(*)
10
select count(*) from t1 where c='a';
count(*)
10
select count(*) from t1 where t='a';
count(*)
10
select count(*) from t1 where v='a ';
count(*)
10
select count(*) from t1 where c='a ';
count(*)
10
select count(*) from t1 where t='a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
count(*)
10
select count(*) from t1 where v like 'a%';
count(*)
11
select count(*) from t1 where c like 'a%';
count(*)
11
select count(*) from t1 where t like 'a%';
count(*)
11
select count(*) from t1 where v like 'a %';
count(*)
9
explain select count(*) from t1 where v='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 13 const 10 Using where
explain select count(*) from t1 where c='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c c 11 const 10 Using where
explain select count(*) from t1 where t='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref t t 13 const 10 Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where
explain select count(*) from t1 where v between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where
alter table t1 add unique(v);
ERROR 23000: Duplicate entry '{ ' for key 1
alter table t1 add key(v);
select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
qq
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a*a*a*
explain select * from t1 where v='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v,v_2 v 13 const 10 Using where
select v,count(*) from t1 group by v limit 10;
v count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(c) from t1 group by v limit 10;
v count(c)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(c) from t1 group by v limit 10;
v count(c)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select c,count(*) from t1 group by c limit 10;
c count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select c,count(t) from t1 group by c limit 10;
c count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result c,count(t) from t1 group by c limit 10;
c count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select t,count(*) from t1 group by t limit 10;
t count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select t,count(t) from t1 group by t limit 10;
t count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result t,count(t) from t1 group by t limit 10;
t count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
drop table t1;
create table t1 (a char(10), unique (a));
insert into t1 values ('a');
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a' for key 1
alter table t1 modify a varchar(10);
insert into t1 values ('a '),('a '),('a '),('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
update t1 set a='a ' where a like 'a ';
update t1 set a='a ' where a like 'a ';
drop table t1;
create table t1 (v varchar(10), c char(10), t varchar(50), key using btree (v), key using btree (c), key using btree (t(10)));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` varchar(50) default NULL,
KEY `v` TYPE BTREE (`v`),
KEY `c` TYPE BTREE (`c`),
KEY `t` TYPE BTREE (`t`(10))
) ENGINE=HEAP DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
270
insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
select count(*) from t1 where v='a';
count(*)
10
select count(*) from t1 where c='a';
count(*)
10
select count(*) from t1 where t='a';
count(*)
10
select count(*) from t1 where v='a ';
count(*)
10
select count(*) from t1 where c='a ';
count(*)
10
select count(*) from t1 where t='a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
count(*)
10
explain select count(*) from t1 where v='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 13 const # Using where
explain select count(*) from t1 where c='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c c 11 const # Using where
explain select count(*) from t1 where t='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref t t 13 const # Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL # Using where
explain select count(*) from t1 where v between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL # Using where
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL # Using where
alter table t1 add unique(v);
ERROR 23000: Duplicate entry '{ ' for key 1
alter table t1 add key(v);
select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
qq
*a*a*a*
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
explain select * from t1 where v='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v,v_2 v 13 const 7 Using where
drop table t1;
create table t1 (a char(10), unique using btree (a)) engine=heap;
insert into t1 values ('a');
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a' for key 1
alter table t1 modify a varchar(10);
insert into t1 values ('a '),('a '),('a '),('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
update t1 set a='a ' where a like 'a ';
update t1 set a='a ' where a like 'a ';
drop table t1;
create table t1 (v varchar(10), c char(10), t varchar(50), key(v(5)), key(c(5)), key(t(5)));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` varchar(50) default NULL,
KEY `v` (`v`(5)),
KEY `c` (`c`(5)),
KEY `t` (`t`(5))
) ENGINE=HEAP DEFAULT CHARSET=latin1
drop table t1;
create table t1 (v varchar(65530), key(v(10)));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(65530) default NULL,
KEY `v` (`v`(10))
) ENGINE=HEAP DEFAULT CHARSET=latin1
insert into t1 values(repeat('a',65530));
select length(v) from t1 where v=repeat('a',65530);
length(v)
65530
drop table t1;
set storage_engine=MyISAM;

View File

@ -1421,19 +1421,19 @@ insert t2 select * from t1;
insert t3 select * from t1;
checksum table t1, t2, t3, t4 quick;
Table Checksum
test.t1 968604391
test.t1 272226711
test.t2 NULL
test.t3 NULL
test.t4 NULL
checksum table t1, t2, t3, t4;
Table Checksum
test.t1 968604391
test.t1 272226711
test.t2 968604391
test.t3 968604391
test.t4 NULL
checksum table t1, t2, t3, t4 extended;
Table Checksum
test.t1 968604391
test.t1 272226711
test.t2 968604391
test.t3 968604391
test.t4 NULL
@ -1664,3 +1664,5 @@ select count(*) from t1 where x = 18446744073709551601;
count(*)
1
drop table t1;
create table t1 (v varchar(16384)) engine=innodb;
ERROR 42000: Column length too big for column 'v' (max = 255); use BLOB instead

View File

@ -614,19 +614,19 @@ KEY files (fileset_id,fileset_root_id)
EXPLAIN SELECT * FROM t2 IGNORE INDEX (files) WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range PRIMARY PRIMARY 33 NULL 5 Using where
1 SIMPLE t2 range PRIMARY PRIMARY 35 NULL 5 Using where
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range PRIMARY,files PRIMARY 33 NULL 5 Using where
1 SIMPLE t2 range PRIMARY,files PRIMARY 35 NULL 5 Using where
EXPLAIN SELECT * FROM t1 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY,files PRIMARY 33 NULL 5 Using where
1 SIMPLE t1 range PRIMARY,files PRIMARY 35 NULL 5 Using where
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code = '0000000115' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 const PRIMARY,files PRIMARY 33 const,const 1
1 SIMPLE t2 ref PRIMARY,files PRIMARY 35 const,const 1 Using where
DROP TABLE t2, t1;
create table t1 (x int, y int, index xy(x, y));
create table t2 (x int, y int, index xy(x, y));

View File

@ -408,8 +408,8 @@ Table Op Msg_type Msg_text
test.t1 repair status OK
select concat(a,'.') from t1 where a='aaa';
concat(a,'.')
aaa.
aaa .
aaa.
select concat(a,'.') from t1 where binary a='aaa';
concat(a,'.')
aaa.
@ -461,20 +461,27 @@ concat(a,'.')
a .
drop table t1;
create table t1 (a int not null auto_increment primary key, b text not null, unique b (b(20)));
insert into t1 (b) values ('a'),('a '),('a ');
insert into t1 (b) values ('a'),('b'),('c');
select concat(b,'.') from t1;
concat(b,'.')
a.
a .
a .
b.
c.
update t1 set b='b ' where a=2;
update t1 set b='b ' where a > 1;
ERROR 23000: Duplicate entry 'b ' for key 2
insert into t1 (b) values ('b');
ERROR 23000: Duplicate entry 'b' for key 2
select * from t1;
a b
1 a
2 b
3 c
delete from t1 where b='b';
select a,concat(b,'.') from t1;
a concat(b,'.')
1 a.
3 a .
3 c.
drop table t1;
create table t1 (a int not null);
create table t2 (a int not null, primary key (a));
@ -506,18 +513,18 @@ insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, "");
insert t2 select * from t1;
checksum table t1, t2, t3 quick;
Table Checksum
test.t1 968604391
test.t1 272226711
test.t2 NULL
test.t3 NULL
checksum table t1, t2, t3;
Table Checksum
test.t1 968604391
test.t2 968604391
test.t1 272226711
test.t2 272226711
test.t3 NULL
checksum table t1, t2, t3 extended;
Table Checksum
test.t1 968604391
test.t2 968604391
test.t1 272226711
test.t2 272226711
test.t3 NULL
drop table t1,t2;
create table t1 (a int, key (a));
@ -554,3 +561,384 @@ select count(*) from t1 where a is null;
count(*)
2
drop table t1;
set storage_engine=MyISAM;
drop table if exists t1,t2,t3;
--- Testing varchar ---
--- Testing varchar ---
create table t1 (v varchar(10), c char(10), t text);
insert into t1 values('+ ', '+ ', '+ ');
set @a=repeat(' ',20);
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
Warnings:
Warning 1265 Data truncated for column 'v' at row 1
select concat('*',v,'*',c,'*',t,'*') from t1;
concat('*',v,'*',c,'*',t,'*')
*+ *+*+ *
*+ *+*+ *
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` text
) ENGINE=MyISAM DEFAULT CHARSET=latin1
create table t2 like t1;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` text
) ENGINE=MyISAM DEFAULT CHARSET=latin1
create table t3 select * from t1;
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` text
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t1 modify c varchar(10);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` varchar(10) default NULL,
`t` text
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t1 modify v char(10);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` char(10) default NULL,
`c` varchar(10) default NULL,
`t` text
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t1 modify t varchar(10);
Warnings:
Warning 1265 Data truncated for column 't' at row 2
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` char(10) default NULL,
`c` varchar(10) default NULL,
`t` varchar(10) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select concat('*',v,'*',c,'*',t,'*') from t1;
concat('*',v,'*',c,'*',t,'*')
*+*+*+ *
*+*+*+ *
drop table t1,t2,t3;
create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` text,
KEY `v` (`v`),
KEY `c` (`c`),
KEY `t` (`t`(10))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
270
insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
select count(*) from t1 where v='a';
count(*)
10
select count(*) from t1 where c='a';
count(*)
10
select count(*) from t1 where t='a';
count(*)
10
select count(*) from t1 where v='a ';
count(*)
10
select count(*) from t1 where c='a ';
count(*)
10
select count(*) from t1 where t='a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
count(*)
10
select count(*) from t1 where v like 'a%';
count(*)
11
select count(*) from t1 where c like 'a%';
count(*)
11
select count(*) from t1 where t like 'a%';
count(*)
11
select count(*) from t1 where v like 'a %';
count(*)
9
explain select count(*) from t1 where v='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 13 const 9 Using where; Using index
explain select count(*) from t1 where c='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c c 11 const 9 Using where; Using index
explain select count(*) from t1 where t='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range t t 13 NULL 9 Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL 10 Using where; Using index
explain select count(*) from t1 where v between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL 9 Using where; Using index
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL 9 Using where; Using index
alter table t1 add unique(v);
ERROR 23000: Duplicate entry '{ ' for key 1
alter table t1 add key(v);
select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
qq
*a*a*a*
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
*a *a*a *
explain select * from t1 where v='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v,v_2 v_2 13 const 7 Using where
select v,count(*) from t1 group by v limit 10;
v count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(c) from t1 group by v limit 10;
v count(c)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(c) from t1 group by v limit 10;
v count(c)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select c,count(*) from t1 group by c limit 10;
c count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select c,count(t) from t1 group by c limit 10;
c count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result c,count(t) from t1 group by c limit 10;
c count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select t,count(*) from t1 group by t limit 10;
t count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select t,count(t) from t1 group by t limit 10;
t count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result t,count(t) from t1 group by t limit 10;
t count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
drop table t1;
create table t1 (a char(10), unique (a));
insert into t1 values ('a ');
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a' for key 1
alter table t1 modify a varchar(10);
insert into t1 values ('a '),('a '),('a '),('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
insert into t1 values ('a ');
ERROR 23000: Duplicate entry 'a ' for key 1
update t1 set a='a ' where a like 'a%';
select concat(a,'.') from t1;
concat(a,'.')
a .
update t1 set a='abc ' where a like 'a ';
select concat(a,'.') from t1;
concat(a,'.')
a .
update t1 set a='a ' where a like 'a %';
select concat(a,'.') from t1;
concat(a,'.')
a .
update t1 set a='a ' where a like 'a ';
select concat(a,'.') from t1;
concat(a,'.')
a .
drop table t1;
create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL,
`t` text,
KEY `v` (`v`(5)),
KEY `c` (`c`(5)),
KEY `t` (`t`(5))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (v char(10) character set utf8);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` char(10) character set utf8 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (v varchar(10), c char(10)) row_format=fixed;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(10) default NULL,
`c` char(10) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
insert into t1 values('a','a'),('a ','a ');
select concat('*',v,'*',c,'*') from t1;
concat('*',v,'*',c,'*')
*a*a*
*a *a*
drop table t1;
create table t1 (v varchar(65530), key(v(10)));
insert into t1 values(repeat('a',65530));
select length(v) from t1 where v=repeat('a',65530);
length(v)
65530
drop table t1;
create table t1 (v varchar(65530), key(v));
Warnings:
Warning 1071 Specified key was too long; max key length is 1000 bytes
drop table if exists t1;
create table t1 (v varchar(65536));
Warnings:
Note 1246 Converting column 'v' from VARCHAR to TEXT
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` mediumtext
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (v varchar(65530) character set utf8);
Warnings:
Note 1246 Converting column 'v' from VARCHAR to TEXT
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` mediumtext character set utf8
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
set storage_engine=MyISAM;
create table t1 (v varchar(65535));
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs

View File

@ -106,7 +106,7 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES");
<table_structure name="t1">
<field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
<field Field="b" Type="text" Null="YES" Key="" Extra="" />
<field Field="c" Type="char(3)" Null="YES" Key="" Extra="" />
<field Field="c" Type="varchar(3)" Null="YES" Key="" Extra="" />
</table_structure>
<table_data name="t1">
<row>

View File

@ -272,7 +272,7 @@ create table t1 (a int not null, b int, c varchar(10), key (a, b, c));
insert into t1 values (1, NULL, NULL), (1, NULL, 'b'), (1, 1, NULL), (1, 1, 'b'), (1, 1, 'b'), (2, 1, 'a'), (2, 1, 'b'), (2, 2, 'a'), (2, 2, 'b'), (2, 3, 'c'),(1,3,'b');
explain select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index a a 20 NULL 11 Using where; Using index
1 SIMPLE t1 index a a 22 NULL 11 Using where; Using index
select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
a b c
1 NULL b
@ -348,7 +348,7 @@ Warning 1265 Data truncated for column 'b' at row 2
Warning 1265 Data truncated for column 'c' at row 3
explain select * from t1 order by a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 18 NULL 11 Using index
1 SIMPLE t1 index NULL a 20 NULL 11 Using index
select * from t1 order by a, b, c;
a b c
1 0
@ -364,7 +364,7 @@ a b c
2 3 c
explain select * from t1 order by a desc, b desc, c desc;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 18 NULL 11 Using index
1 SIMPLE t1 index NULL a 20 NULL 11 Using index
select * from t1 order by a desc, b desc, c desc;
a b c
2 3 c
@ -380,7 +380,7 @@ a b c
1 0
explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 18 NULL 3 Using where; Using index
1 SIMPLE t1 range a a 20 NULL 3 Using where; Using index
select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
a b c
1 1 b
@ -574,7 +574,7 @@ KEY StringField (FieldKey,StringVal(32))
INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3');
EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 36 const 3 Using where
1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 38 const 3 Using where
SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
FieldKey LongVal StringVal
1 0 2
@ -582,7 +582,7 @@ FieldKey LongVal StringVal
1 2 1
EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range FieldKey,LongField,StringField FieldKey 36 NULL 4 Using where; Using filesort
1 SIMPLE t1 range FieldKey,LongField,StringField FieldKey 38 NULL 4 Using where; Using filesort
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
FieldKey LongVal StringVal
3 1 2
@ -590,7 +590,7 @@ FieldKey LongVal StringVal
3 3 3
EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range FieldKey,LongField,StringField LongField 36 NULL 4 Using where
1 SIMPLE t1 range FieldKey,LongField,StringField LongField 38 NULL 4 Using where
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
FieldKey LongVal StringVal
3 1 2

View File

@ -207,10 +207,10 @@ create table t1 ( a int primary key, b varchar(30)) engine = MYISAM ;
prepare stmt1 from ' show table status from test like ''t1%'' ';
execute stmt1;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 MyISAM 9 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
t1 MyISAM 10 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
show table status from test like 't1%' ;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 MyISAM 9 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
t1 MyISAM 10 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
deallocate prepare stmt1 ;
drop table t1;
create table t1(a varchar(2), b varchar(3));

View File

@ -276,7 +276,7 @@ t2 MyISAM 9 Fixed 0 0 0 64424509439 1024 0 NULL # # # latin1_swedish_ci NULL
prepare stmt4 from ' show table status from test like ''t9%'' ';
execute stmt4;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t9 MyISAM 9 Dynamic 2 220 440 4294967295 2048 0 NULL # # # latin1_swedish_ci NULL
t9 MyISAM 10 Dynamic 2 222 444 4294967295 2048 0 NULL # # # latin1_swedish_ci NULL
prepare stmt4 from ' show status like ''Threads_running'' ';
execute stmt4;
Variable_name Value
@ -290,7 +290,7 @@ execute stmt4;
prepare stmt4 from ' show full processlist ';
execute stmt4;
Id User Host db Command Time State Info
number root localhost test Query 0 NULL show full processlist
number root localhost test Query seconds NULL show full processlist
prepare stmt4 from ' show grants for user ';
prepare stmt4 from ' show create table t2 ';
ERROR HY000: This command is not supported in the prepared statement protocol yet

View File

@ -69,7 +69,7 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
def test t9 t9 c21 c21 253 10 10 Y 0 0 8
def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@ -1705,8 +1705,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
3 duplicate
4 duplicate
3 duplicate
4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@ -1777,11 +1777,11 @@ t5 CREATE TABLE `t5` (
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`const06` char(10) NOT NULL default '',
`param06` longtext,
`const07` date default NULL,
`param07` longblob,
`const08` varchar(19) NOT NULL default '',
`const08` char(19) NOT NULL default '',
`param08` longtext,
`const09` datetime default NULL,
`param09` longblob,
@ -1807,11 +1807,11 @@ def test t5 t5 const04 const04 254 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 254 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 const06 const06 254 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
def test t5 t5 const07 const07 10 10 10 Y 128 0 63
def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
def test t5 t5 const08 const08 253 19 19 N 1 0 8
def test t5 t5 const08 const08 254 19 19 N 1 0 8
def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
def test t5 t5 const09 const09 12 19 19 Y 128 0 63
def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63

View File

@ -69,8 +69,8 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
def test t9 t9 c21 c21 253 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 254 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
def test t9 t9 c25 c25 252 65535 4 Y 144 0 63
@ -1760,11 +1760,11 @@ t5 CREATE TABLE `t5` (
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`const06` char(10) NOT NULL default '',
`param06` longtext,
`const07` date default NULL,
`param07` longblob,
`const08` varchar(19) NOT NULL default '',
`const08` char(19) NOT NULL default '',
`param08` longtext,
`const09` datetime default NULL,
`param09` longblob,
@ -1790,11 +1790,11 @@ def test t5 t5 const04 const04 254 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 254 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 const06 const06 254 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
def test t5 t5 const07 const07 10 10 10 Y 128 0 63
def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
def test t5 t5 const08 const08 253 19 19 N 1 0 8
def test t5 t5 const08 const08 254 19 19 N 1 0 8
def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
def test t5 t5 const09 const09 12 19 19 Y 128 0 63
def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63

View File

@ -13,9 +13,9 @@ c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
c13 date, c14 datetime, c15 timestamp(14), c16 time,
c17 year, c18 bit, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 char(100), c24 char(100),
c25 char(100), c26 char(100), c27 char(100), c28 char(100),
c29 char(100), c30 char(100), c31 enum('one', 'two', 'three'),
c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100),
c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100),
c29 varchar(100), c30 varchar(100), c31 enum('one', 'two', 'three'),
c32 set('monday', 'tuesday', 'wednesday'),
primary key(c1)
) engine = 'HEAP' ;
@ -70,7 +70,7 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
def test t9 t9 c21 c21 253 10 10 Y 0 0 8
def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 253 100 8 Y 0 0 8
def test t9 t9 c24 c24 253 100 8 Y 0 0 8
@ -1689,8 +1689,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
3 duplicate
4 duplicate
3 duplicate
4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@ -1761,11 +1761,11 @@ t5 CREATE TABLE `t5` (
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`const06` char(10) NOT NULL default '',
`param06` longtext,
`const07` date default NULL,
`param07` longblob,
`const08` varchar(19) NOT NULL default '',
`const08` char(19) NOT NULL default '',
`param08` longtext,
`const09` datetime default NULL,
`param09` longblob,
@ -1791,11 +1791,11 @@ def test t5 t5 const04 const04 254 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 254 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 const06 const06 254 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
def test t5 t5 const07 const07 10 10 10 Y 128 0 63
def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
def test t5 t5 const08 const08 253 19 19 N 1 0 8
def test t5 t5 const08 const08 254 19 19 N 1 0 8
def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
def test t5 t5 const09 const09 12 19 19 Y 128 0 63
def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63

View File

@ -112,7 +112,7 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
def test t9 t9 c21 c21 253 10 10 Y 0 0 8
def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@ -1700,11 +1700,11 @@ t5 CREATE TABLE `t5` (
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`const06` char(10) NOT NULL default '',
`param06` longtext,
`const07` date default NULL,
`param07` longblob,
`const08` varchar(19) NOT NULL default '',
`const08` char(19) NOT NULL default '',
`param08` longtext,
`const09` datetime default NULL,
`param09` longblob,
@ -1730,11 +1730,11 @@ def test t5 t5 const04 const04 254 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 254 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 const06 const06 254 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
def test t5 t5 const07 const07 10 10 10 Y 128 0 63
def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
def test t5 t5 const08 const08 253 19 19 N 1 0 8
def test t5 t5 const08 const08 254 19 19 N 1 0 8
def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
def test t5 t5 const09 const09 12 19 19 Y 128 0 63
def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63
@ -3121,7 +3121,7 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
def test t9 t9 c21 c21 253 10 10 Y 0 0 8
def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@ -4709,11 +4709,11 @@ t5 CREATE TABLE `t5` (
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`const06` char(10) NOT NULL default '',
`param06` longtext,
`const07` date default NULL,
`param07` longblob,
`const08` varchar(19) NOT NULL default '',
`const08` char(19) NOT NULL default '',
`param08` longtext,
`const09` datetime default NULL,
`param09` longblob,
@ -4739,11 +4739,11 @@ def test t5 t5 const04 const04 254 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 254 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 const06 const06 254 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
def test t5 t5 const07 const07 10 10 10 Y 128 0 63
def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
def test t5 t5 const08 const08 253 19 19 N 1 0 8
def test t5 t5 const08 const08 254 19 19 N 1 0 8
def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
def test t5 t5 const09 const09 12 19 19 Y 128 0 63
def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63

View File

@ -69,7 +69,7 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
def test t9 t9 c21 c21 253 10 10 Y 0 0 8
def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@ -1688,8 +1688,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
3 duplicate
4 duplicate
3 duplicate
4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@ -1760,11 +1760,11 @@ t5 CREATE TABLE `t5` (
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`const06` char(10) NOT NULL default '',
`param06` longtext,
`const07` date default NULL,
`param07` longblob,
`const08` varchar(19) NOT NULL default '',
`const08` char(19) NOT NULL default '',
`param08` longtext,
`const09` datetime default NULL,
`param09` longblob,
@ -1790,11 +1790,11 @@ def test t5 t5 const04 const04 254 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 254 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 const06 const06 254 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
def test t5 t5 const07 const07 10 10 10 Y 128 0 63
def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
def test t5 t5 const08 const08 253 19 19 N 1 0 8
def test t5 t5 const08 const08 254 19 19 N 1 0 8
def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
def test t5 t5 const09 const09 12 19 19 Y 128 0 63
def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63

View File

@ -2309,7 +2309,7 @@ select * from t2 where s = 'one';
s
select * from t3 where s = 'one';
s
one
one
select * from t1,t2 where t1.s = t2.s;
s s
two two

View File

@ -1,4 +1,6 @@
drop table if exists t1,t2,t3,t4;
drop table if exists t1_1,t1_2,t9_1,t9_2;
drop view if exists v1;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
@ -2074,10 +2076,8 @@ INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12
SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
gvid the_success the_fail the_size the_time
Warnings:
Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
Warning 1292 Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row 1
Warning 1292 Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row 1
SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
gvid the_success the_fail the_size the_time
DROP TABLE t1,t2;
@ -2340,7 +2340,7 @@ select * from t2 where s = 'one';
s
select * from t3 where s = 'one';
s
one
one
select * from t1,t2 where t1.s = t2.s;
s s
two two

View File

@ -84,7 +84,7 @@ UNIQUE KEY e_n (email,name)
EXPLAIN SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system PRIMARY,kid NULL NULL NULL 0 const row not found
1 SIMPLE t2 index NULL e_n 100 NULL 200
1 SIMPLE t2 index NULL e_n 104 NULL 200
SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
email
email1

View File

@ -154,7 +154,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` char(10) default NULL,
`b` varchar(10) default NULL,
KEY `b` (`b`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
alter table t1 MAX_ROWS=200 ROW_FORMAT=dynamic PACK_KEYS=0;

View File

@ -810,12 +810,14 @@ col1 col2
NULL NULL
1.79769313486232e+308 0
DROP TABLE t1;
CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(5));
INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello ');
CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6));
INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello ');
INSERT INTO t1 (col1) VALUES ('hellobob');
ERROR 01000: Data truncated for column 'col1' at row 1
INSERT INTO t1 (col2) VALUES ('hellobob');
ERROR 01000: Data truncated for column 'col2' at row 1
INSERT INTO t1 (col2) VALUES ('hello ');
ERROR 01000: Data truncated for column 'col2' at row 1
UPDATE t1 SET col1 ='hellobob' WHERE col1 ='he';
ERROR 01000: Data truncated for column 'col1' at row 2
UPDATE t1 SET col2 ='hellobob' WHERE col2 ='he';
@ -830,9 +832,9 @@ Warning 1265 Data truncated for column 'col2' at row 2
SELECT * FROM t1;
col1 col2
hello hello
he hello
hello hello
hello hello
he hellot
hello hello
hello hellob
DROP TABLE t1;
CREATE TABLE t1 (col1 enum('red','blue','green'));
INSERT INTO t1 VALUES ('red'),('blue'),('green');

Some files were not shown because too many files have changed in this diff Show More