~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
15
16
/* Read record based on a key */
17
1130.3.28 by Monty Taylor
Moved heapdef.h and myisamdef.h to *_priv.h for easier filtering for include guard check.
18
#include "myisam_priv.h"
1 by brian
clean slate
19
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
20
using namespace drizzled;
21
1 by brian
clean slate
22
	/* Read a record using key */
23
	/* Ordinary search_flag is 0 ; Give error if no record with key */
24
481 by Brian Aker
Remove all of uchar.
25
int mi_rkey(MI_INFO *info, unsigned char *buf, int inx, const unsigned char *key,
1 by brian
clean slate
26
            key_part_map keypart_map, enum ha_rkey_function search_flag)
27
{
481 by Brian Aker
Remove all of uchar.
28
  unsigned char *key_buff;
1 by brian
clean slate
29
  MYISAM_SHARE *share=info->s;
30
  MI_KEYDEF *keyinfo;
31
  HA_KEYSEG *last_used_keyseg;
482 by Brian Aker
Remove uint.
32
  uint32_t pack_key_length, use_key_length, nextflag;
33
  uint32_t myisam_search_flag;
1 by brian
clean slate
34
  int res= 0;
35
36
  if ((inx = _mi_check_index(info,inx)) < 0)
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
37
    return(errno);
1 by brian
clean slate
38
39
  info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
40
  info->last_key_func= search_flag;
41
  keyinfo= share->keyinfo + inx;
42
43
  if (info->once_flags & USE_PACKED_KEYS)
44
  {
45
    info->once_flags&= ~USE_PACKED_KEYS;	/* Reset flag */
46
    /*
47
      key is already packed!;  This happens when we are using a MERGE TABLE
48
      In this key 'key_part_map' is the length of the key !
49
    */
50
    key_buff=info->lastkey+info->s->base.max_key_length;
51
    pack_key_length= keypart_map;
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
52
    memmove(key_buff, key, pack_key_length);
1 by brian
clean slate
53
    last_used_keyseg= info->s->keyinfo[inx].seg + info->last_used_keyseg;
54
  }
55
  else
56
  {
51.1.109 by Jay Pipes
Removed/replaced DBUG
57
    assert(keypart_map);
1 by brian
clean slate
58
    /* Save the packed key for later use in the second buffer of lastkey. */
59
    key_buff=info->lastkey+info->s->base.max_key_length;
481 by Brian Aker
Remove all of uchar.
60
    pack_key_length=_mi_pack_key(info,(uint) inx, key_buff, (unsigned char*) key,
1 by brian
clean slate
61
				 keypart_map, &last_used_keyseg);
62
    /* Save packed_key_length for use by the MERGE engine. */
63
    info->pack_key_length= pack_key_length;
206 by Brian Aker
Removed final uint dead types.
64
    info->last_used_keyseg= (uint16_t) (last_used_keyseg -
1 by brian
clean slate
65
                                      info->s->keyinfo[inx].seg);
66
  }
67
68
  if (fast_mi_readinfo(info))
69
    goto err;
70
71
  nextflag=myisam_read_vec[search_flag];
72
  use_key_length=pack_key_length;
73
  if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
74
    use_key_length=USE_WHOLE_KEY;
75
76
  switch (info->s->keyinfo[inx].key_alg) {
77
  case HA_KEY_ALG_BTREE:
78
  default:
79
    myisam_search_flag= myisam_read_vec[search_flag];
80
    if (!_mi_search(info, keyinfo, key_buff, use_key_length,
81
                    myisam_search_flag, info->s->state.key_root[inx]))
82
    {
83
      /*
84
        Found a key, but it might not be usable. We cannot use rows that
85
        are inserted by other threads after we got our table lock
86
        ("concurrent inserts"). The record may not even be present yet.
87
        Keys are inserted into the index(es) before the record is
88
        inserted into the data file. When we got our table lock, we
89
        saved the current data_file_length. Concurrent inserts always go
90
        to the end of the file. So we can test if the found key
91
        references a new record.
92
93
        If we are searching for a partial key (or using >, >=, < or <=) and
94
        the data is outside of the data file, we need to continue searching
95
        for the first key inside the data file.
96
97
        We do also continue searching if an index condition check function
98
        is available.
99
      */
100
      while ((info->lastpos >= info->state->data_file_length &&
101
              (search_flag != HA_READ_KEY_EXACT ||
102
              last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) ||
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
103
             (info->index_cond_func &&
1 by brian
clean slate
104
              !(res= mi_check_index_cond(info, inx, buf))))
105
      {
482 by Brian Aker
Remove uint.
106
        uint32_t not_used[2];
1 by brian
clean slate
107
        /*
108
          Skip rows that are inserted by other threads since we got a lock
109
          Note that this can only happen if we are not searching after an
110
          full length exact key, because the keys are sorted
111
          according to position
112
        */
113
        if  (_mi_search_next(info, keyinfo, info->lastkey,
114
                             info->lastkey_length,
115
                             myisam_readnext_vec[search_flag],
116
                             info->s->state.key_root[inx]))
117
          break;
118
        /*
119
          Check that the found key does still match the search.
120
          _mi_search_next() delivers the next key regardless of its
121
          value.
122
        */
123
        if (search_flag == HA_READ_KEY_EXACT &&
124
            ha_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length,
125
                       SEARCH_FIND, not_used))
126
        {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
127
          errno= HA_ERR_KEY_NOT_FOUND;
1 by brian
clean slate
128
          info->lastpos= HA_OFFSET_ERROR;
129
          break;
130
        }
131
      }
132
      if (res == 2)
133
      {
134
        info->lastpos= HA_OFFSET_ERROR;
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
135
        return((errno= HA_ERR_KEY_NOT_FOUND));
1 by brian
clean slate
136
      }
137
      /*
138
        Error if no row found within the data file. (Bug #29838)
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
139
        Do not overwrite errno if already at HA_OFFSET_ERROR.
1 by brian
clean slate
140
      */
141
      if (info->lastpos != HA_OFFSET_ERROR &&
142
          info->lastpos >= info->state->data_file_length)
143
      {
144
        info->lastpos= HA_OFFSET_ERROR;
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
145
        errno= HA_ERR_KEY_NOT_FOUND;
1 by brian
clean slate
146
      }
147
    }
148
  }
149
150
  /* Calculate length of the found key;  Used by mi_rnext_same */
151
  if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg &&
152
      info->lastpos != HA_OFFSET_ERROR)
153
    info->last_rkey_length= _mi_keylength_part(keyinfo, info->lastkey,
154
					       last_used_keyseg);
155
  else
156
    info->last_rkey_length= pack_key_length;
157
158
  /* Check if we don't want to have record back, only error message */
159
  if (!buf)
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
160
    return(info->lastpos == HA_OFFSET_ERROR ? errno : 0);
1 by brian
clean slate
161
162
  if (!(*info->read_record)(info,info->lastpos,buf))
163
  {
164
    info->update|= HA_STATE_AKTIV;		/* Record is read */
51.1.109 by Jay Pipes
Removed/replaced DBUG
165
    return(0);
1 by brian
clean slate
166
  }
167
168
  info->lastpos = HA_OFFSET_ERROR;		/* Didn't find key */
169
170
  /* Store last used key as a base for read next */
171
  memcpy(info->lastkey,key_buff,pack_key_length);
172
  info->last_rkey_length= pack_key_length;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
173
  memset(info->lastkey+pack_key_length, 0, info->s->base.rec_reflength);
1 by brian
clean slate
174
  info->lastkey_length=pack_key_length+info->s->base.rec_reflength;
175
176
  if (search_flag == HA_READ_AFTER_KEY)
177
    info->update|=HA_STATE_NEXT_FOUND;		/* Previous gives last row */
178
err:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
179
  return(errno);
1 by brian
clean slate
180
} /* _mi_rkey */