summaryrefslogtreecommitdiff
path: root/isam/_key.c
diff options
context:
space:
mode:
Diffstat (limited to 'isam/_key.c')
-rw-r--r--isam/_key.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/isam/_key.c b/isam/_key.c
new file mode 100644
index 00000000000..62f080af172
--- /dev/null
+++ b/isam/_key.c
@@ -0,0 +1,239 @@
+/* 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);
+#ifdef USE_STRCOLL
+ if (!use_strcoll(default_charset_info))
+#endif
+ {
+ if (type == HA_KEYTYPE_TEXT)
+ case_sort((byte*) key,length);
+ }
+ key+=length;
+ }
+ else
+ {
+ memcpy((byte*) key,(byte*) record+keyseg->base.start,
+ (size_t) keyseg->base.length);
+#ifdef USE_STRCOLL
+ if (!use_strcoll(default_charset_info))
+#endif
+ {
+ if (type == HA_KEYTYPE_TEXT)
+ case_sort((byte*) 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);
+#ifdef USE_STRCOLL
+ if (!use_strcoll(default_charset_info))
+#endif
+ {
+ if (type == HA_KEYTYPE_TEXT)
+ case_sort((byte*) 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 */
+}