mi_rnext.c 4.02 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000-2004 MySQL AB
2

unknown's avatar
unknown committed
3 4
   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
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
6

unknown's avatar
unknown committed
7 8 9 10
   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.
11

unknown's avatar
unknown committed
12 13 14 15 16 17
   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 "myisamdef.h"

18 19
#include "rt_index.h"

unknown's avatar
unknown committed
20 21 22 23 24 25 26
	/*
	   Read next row with the same key as previous read
	   One may have done a write, update or delete of the previous row.
	   NOTE! Even if one changes the previous row, the next read is done
	   based on the position of the last used key!
	*/

27
int mi_rnext(MI_INFO *info, uchar *buf, int inx)
unknown's avatar
unknown committed
28
{
29
  int error,changed;
unknown's avatar
unknown committed
30
  uint flag;
31
  int res= 0;
unknown's avatar
unknown committed
32 33 34 35 36 37 38 39
  DBUG_ENTER("mi_rnext");

  if ((inx = _mi_check_index(info,inx)) < 0)
    DBUG_RETURN(my_errno);
  flag=SEARCH_BIGGER;				/* Read next */
  if (info->lastpos == HA_OFFSET_ERROR && info->update & HA_STATE_PREV_FOUND)
    flag=0;					/* Read first */

unknown's avatar
unknown committed
40
  if (fast_mi_readinfo(info))
unknown's avatar
unknown committed
41 42 43
    DBUG_RETURN(my_errno);
  if (info->s->concurrent_insert)
    rw_rdlock(&info->s->key_root_lock[inx]);
44
  changed=_mi_test_if_changed(info);
unknown's avatar
unknown committed
45
  if (!flag)
46
  {
47
    switch(info->s->keyinfo[inx].key_alg){
48
#ifdef HAVE_RTREE_KEYS
49 50 51
    case HA_KEY_ALG_RTREE:
      error=rtree_get_first(info,inx,info->lastkey_length);
      break;
52
#endif
53 54 55
    case HA_KEY_ALG_BTREE:
    default:
      error=_mi_search_first(info,info->s->keyinfo+inx,
56
			   info->s->state.key_root[inx]);
57 58
      break;
    }
59
  }
unknown's avatar
unknown committed
60 61
  else
  {
unknown's avatar
unknown committed
62
    switch (info->s->keyinfo[inx].key_alg) {
63
#ifdef HAVE_RTREE_KEYS
unknown's avatar
unknown committed
64
    case HA_KEY_ALG_RTREE:
65
      /*
unknown's avatar
unknown committed
66 67 68
	Note that rtree doesn't support that the table
	may be changed since last call, so we do need
	to skip rows inserted by other threads like in btree
69
      */
unknown's avatar
unknown committed
70 71
      error= rtree_get_next(info,inx,info->lastkey_length);
      break;
72
#endif
unknown's avatar
unknown committed
73 74 75 76 77 78 79 80 81
    case HA_KEY_ALG_BTREE:
    default:
      if (!changed)
	error= _mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
			       info->lastkey_length,flag,
			       info->s->state.key_root[inx]);
      else
	error= _mi_search(info,info->s->keyinfo+inx,info->lastkey,
			  USE_WHOLE_KEY,flag, info->s->state.key_root[inx]);
unknown's avatar
unknown committed
82 83 84
    }
  }

85
  if (!error)
unknown's avatar
unknown committed
86
  {
87 88 89 90
    while ((info->s->concurrent_insert &&
            info->lastpos >= info->state->data_file_length) ||
           (info->index_cond_func &&
           !(res= mi_check_index_cond(info, inx, buf))))
unknown's avatar
unknown committed
91
    {
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
      /* 
         Skip rows that are either inserted by other threads since
         we got a lock or do not match pushed index conditions
      */
      if  ((error=_mi_search_next(info,info->s->keyinfo+inx,
                                  info->lastkey,
                                  info->lastkey_length,
                                  SEARCH_BIGGER,
                                  info->s->state.key_root[inx])))
        break;
    }
    if (!error && res == 2)
    {
      if (info->s->concurrent_insert)
        rw_unlock(&info->s->key_root_lock[inx]);
      info->lastpos= HA_OFFSET_ERROR;
      DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
unknown's avatar
unknown committed
109 110
    }
  }
111 112 113 114
  
  if (info->s->concurrent_insert)
    rw_unlock(&info->s->key_root_lock[inx]);

unknown's avatar
unknown committed
115 116 117 118 119 120 121 122 123
	/* Don't clear if database-changed */
  info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
  info->update|= HA_STATE_NEXT_FOUND;

  if (error)
  {
    if (my_errno == HA_ERR_KEY_NOT_FOUND)
      my_errno=HA_ERR_END_OF_FILE;
  }
124 125 126 127
  else if (!buf)
  {
    DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0);
  }
unknown's avatar
unknown committed
128 129 130 131 132 133 134 135
  else if (!(*info->read_record)(info,info->lastpos,buf))
  {
    info->update|= HA_STATE_AKTIV;		/* Record is read */
    DBUG_RETURN(0);
  }
  DBUG_PRINT("error",("Got error: %d,  errno: %d",error, my_errno));
  DBUG_RETURN(my_errno);
} /* mi_rnext */