Example #1
0
static int send_change_user_packet(MCPVIO_EXT *mpvio,
                                   const uchar *data, int data_len)
{
    MYSQL *mysql= mpvio->mysql;
    char *buff, *end;
    int res= 1;
    size_t conn_attr_len= (mysql->options.extension) ?
                          mysql->options.extension->connect_attrs_len : 0;

    buff= my_alloca(USERNAME_LENGTH+1 + data_len+1 + NAME_LEN+1 + 2 + NAME_LEN+1 + 9 + conn_attr_len);

    end= strmake(buff, mysql->user, USERNAME_LENGTH) + 1;

    if (!data_len)
        *end++= 0;
    else
    {
        if (mysql->client_flag & CLIENT_SECURE_CONNECTION)
        {
            DBUG_ASSERT(data_len <= 255);
            if (data_len > 255)
            {
                my_set_error(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0);
                goto error;
            }
            *end++= data_len;
        }
        else
        {
            DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1);
            DBUG_ASSERT(data[SCRAMBLE_LENGTH_323] == 0);
        }
        memcpy(end, data, data_len);
        end+= data_len;
    }
    end= strmake(end, mpvio->db ? mpvio->db : "", NAME_LEN) + 1;

    if (mysql->server_capabilities & CLIENT_PROTOCOL_41)
    {
        int2store(end, (ushort) mysql->charset->nr);
        end+= 2;
    }

    if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
        end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;

    end= ma_send_connect_attr(mysql, end);

    res= simple_command(mysql, MYSQL_COM_CHANGE_USER,
                        buff, (ulong)(end-buff), 1, NULL);

error:
    my_afree(buff);
    return res;
}
Example #2
0
File: write.c Project: OPSF/uClinux
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 */
int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length)
{
  uint page_size;
  stPageList ReinsertList;
  my_off_t old_root;
  MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
  DBUG_ENTER("rtree_delete");

  if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
  {
    my_errno= HA_ERR_END_OF_FILE;
    DBUG_RETURN(-1); /* purecov: inspected */
  }
  DBUG_PRINT("rtree", ("starting deletion at root page: %lu",
                       (ulong) old_root));

  ReinsertList.pages = NULL;
  ReinsertList.n_pages = 0;
  ReinsertList.m_pages = 0;
  
  switch (rtree_delete_req(info, keyinfo, key, key_length, old_root, 
                                 &page_size, &ReinsertList, 0))
  {
    case 2: /* empty */
    {
      info->s->state.key_root[keynr] = HA_OFFSET_ERROR;
      DBUG_RETURN(0);
    }
    case 0: /* deleted */
    {
      uint nod_flag;
      ulong i;
      for (i = 0; i < ReinsertList.n_pages; ++i)
      {
        uchar *page_buf;
        uchar *k;
        uchar *last;

        if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
        {
          my_errno = HA_ERR_OUT_OF_MEM;
          goto err1;
        }
        if (!_mi_fetch_keypage(info, keyinfo, ReinsertList.pages[i].offs, 
                               DFLT_INIT_HITS, page_buf, 0))
          goto err1;
        nod_flag = mi_test_if_nod(page_buf);
        DBUG_PRINT("rtree", ("reinserting keys from "
                             "page: %lu  level: %d  nod_flag: %u",
                             (ulong) ReinsertList.pages[i].offs,
                             ReinsertList.pages[i].level, nod_flag));

        k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
        last = rt_PAGE_END(page_buf);
        for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
        {
          int res;
          if ((res= rtree_insert_level(info, keynr, k, key_length,
                                       ReinsertList.pages[i].level)) == -1)
          {
            my_afree((uchar*)page_buf);
            goto err1;
          }
          if (res)
          {
            ulong j;
            DBUG_PRINT("rtree", ("root has been split, adjust levels"));
            for (j= i; j < ReinsertList.n_pages; j++)
            {
              ReinsertList.pages[j].level++;
              DBUG_PRINT("rtree", ("keys from page: %lu  now level: %d",
                                   (ulong) ReinsertList.pages[i].offs,
                                   ReinsertList.pages[i].level));
            }
          }
        }
        my_afree((uchar*)page_buf);
        if (_mi_dispose(info, keyinfo, ReinsertList.pages[i].offs,
            DFLT_INIT_HITS))
          goto err1;
      }
      if (ReinsertList.pages)
        my_free((uchar*) ReinsertList.pages, MYF(0));

      /* check for redundant root (not leaf, 1 child) and eliminate */
      if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
        goto err1;
      if (!_mi_fetch_keypage(info, keyinfo, old_root, DFLT_INIT_HITS,
                             info->buff, 0))
        goto err1;
      nod_flag = mi_test_if_nod(info->buff);
      page_size = mi_getint(info->buff);
      if (nod_flag && (page_size == 2 + key_length + nod_flag))
      {
        my_off_t new_root = _mi_kpos(nod_flag,
                                     rt_PAGE_FIRST_KEY(info->buff, nod_flag));
        if (_mi_dispose(info, keyinfo, old_root, DFLT_INIT_HITS))
          goto err1;
        info->s->state.key_root[keynr] = new_root;
      }
      info->update= HA_STATE_DELETED;
      DBUG_RETURN(0);

err1:
      DBUG_RETURN(-1); /* purecov: inspected */
    }
    case 1: /* not found */
    {
      my_errno = HA_ERR_KEY_NOT_FOUND;
      DBUG_RETURN(-1); /* purecov: inspected */
    }
    default:
    case -1: /* error */
    {
      DBUG_RETURN(-1); /* purecov: inspected */
    }
  }
}
static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, 
                           uint key_length, my_off_t page, uint *page_size, 
                           stPageList *ReinsertList, int level)
{
  uchar *k;
  uchar *last;
  ulong i;
  uint nod_flag;
  uchar *page_buf;
  int res;
  DBUG_ENTER("rtree_delete_req");

  if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
  {
    my_errno = HA_ERR_OUT_OF_MEM;
    DBUG_RETURN(-1); /* purecov: inspected */
  }
  if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
    goto err1;
  nod_flag = mi_test_if_nod(page_buf);
  DBUG_PRINT("rtree", ("page: %lu  level: %d  nod_flag: %u",
                       (ulong) page, level, nod_flag));

  k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
  last = rt_PAGE_END(page_buf);

  for (i = 0; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag), ++i)
  {
    if (nod_flag)
    { 
      /* not leaf */
      if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN))
      {
        switch ((res = rtree_delete_req(info, keyinfo, key, key_length, 
                  _mi_kpos(nod_flag, k), page_size, ReinsertList, level + 1)))
        {
          case 0: /* deleted */
          { 
            /* test page filling */
            if (*page_size + key_length >= rt_PAGE_MIN_SIZE(keyinfo->block_length)) 
            { 
              /* OK */
              /* Calculate a new key value (MBR) for the shrinked block. */
              if (rtree_set_key_mbr(info, keyinfo, k, key_length, 
                                  _mi_kpos(nod_flag, k)))
                goto err1;
              if (_mi_write_keypage(info, keyinfo, page,
                                    DFLT_INIT_HITS, page_buf))
                goto err1;
            }
            else
            { 
              /*
                Too small: delete key & add it descendant to reinsert list.
                Store position and level of the block so that it can be
                accessed later for inserting the remaining keys.
              */
              DBUG_PRINT("rtree", ("too small. move block to reinsert list"));
              if (rtree_fill_reinsert_list(ReinsertList, _mi_kpos(nod_flag, k),
                                           level + 1))
                goto err1;
              /*
                Delete the key that references the block. This makes the
                block disappear from the index. Hence we need to insert
                its remaining keys later. Note: if the block is a branch
                block, we do not only remove this block, but the whole
                subtree. So we need to re-insert its keys on the same
                level later to reintegrate the subtrees.
              */
              rtree_delete_key(info, page_buf, k, key_length, nod_flag);
              if (_mi_write_keypage(info, keyinfo, page,
                                    DFLT_INIT_HITS, page_buf))
                goto err1;
              *page_size = mi_getint(page_buf);
            }
            
            goto ok;
          }
          case 1: /* not found - continue searching */
          {
            break;
          }
          case 2: /* vacuous case: last key in the leaf */
          {
            rtree_delete_key(info, page_buf, k, key_length, nod_flag);
            if (_mi_write_keypage(info, keyinfo, page,
                                  DFLT_INIT_HITS, page_buf))
              goto err1;
            *page_size = mi_getint(page_buf);
            res = 0;
            goto ok;
          }
          default: /* error */
          case -1:
          {
            goto err1;
          }
        }
      }
    }
    else  
    {
      /* leaf */
      if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_EQUAL | MBR_DATA))
      {
        rtree_delete_key(info, page_buf, k, key_length, nod_flag);
        *page_size = mi_getint(page_buf);
        if (*page_size == 2) 
        {
          /* last key in the leaf */
          res = 2;
          if (_mi_dispose(info, keyinfo, page, DFLT_INIT_HITS))
            goto err1;
        }
        else
        {
          res = 0;
          if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
            goto err1;
        }
        goto ok;
      }
    }
  }
  res = 1;

ok:
  my_afree((uchar*)page_buf);
  DBUG_RETURN(res);

err1:
  my_afree((uchar*)page_buf);
  DBUG_RETURN(-1); /* purecov: inspected */
}
static int rtree_find_req(MI_INFO *info, MI_KEYDEF *keyinfo, uint search_flag,
			  uint nod_cmp_flag, my_off_t page, int level)
{
  uchar *k;
  uchar *last;
  uint nod_flag;
  int res;
  uchar *page_buf;
  int k_len;
  uint *saved_key = (uint*) (info->rtree_recursion_state) + level;
  
  if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
  {
    my_errno = HA_ERR_OUT_OF_MEM;
    return -1;
  }
  if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
    goto err1;
  nod_flag = mi_test_if_nod(page_buf);

  k_len = keyinfo->keylength - info->s->base.rec_reflength;
  
  if(info->rtree_recursion_depth >= level)
  {
    k = page_buf + *saved_key;
  }
  else
  {
    k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
  }
  last = rt_PAGE_END(page_buf);

  for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag))
  {
    if (nod_flag) 
    { 
      /* this is an internal node in the tree */
      if (!(res = rtree_key_cmp(keyinfo->seg, info->first_mbr_key, k, 
                            info->last_rkey_length, nod_cmp_flag)))
      {
        switch ((res = rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag,
                                      _mi_kpos(nod_flag, k), level + 1)))
        {
          case 0: /* found - exit from recursion */
            *saved_key = (uint) (k - page_buf);
            goto ok;
          case 1: /* not found - continue searching */
            info->rtree_recursion_depth = level;
            break;
          default: /* error */
          case -1:
            goto err1;
        }
      }
    }
    else 
    { 
      /* this is a leaf */
      if (!rtree_key_cmp(keyinfo->seg, info->first_mbr_key, k, 
                         info->last_rkey_length, search_flag))
      {
        uchar *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
        info->lastpos = _mi_dpos(info, 0, after_key);
        info->lastkey_length = k_len + info->s->base.rec_reflength;
        memcpy(info->lastkey, k, info->lastkey_length);
        info->rtree_recursion_depth = level;
        *saved_key = (uint) (last - page_buf);

        if (after_key < last)
        {
          info->int_keypos = info->buff;
          info->int_maxpos = info->buff + (last - after_key);
          memcpy(info->buff, after_key, last - after_key);
          info->buff_used = 0;
        }
        else
        {
	  info->buff_used = 1;
        }

        res = 0;
        goto ok;
      }
    }
  }
  info->lastpos = HA_OFFSET_ERROR;
  my_errno = HA_ERR_KEY_NOT_FOUND;
  res = 1;

ok:
  my_afree((uchar*)page_buf);
  return res;

err1:
  my_afree((uchar*)page_buf);
  info->lastpos = HA_OFFSET_ERROR;
  return -1;
}
static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, 
                            uint key_length, my_off_t page, my_off_t *new_page, 
                            int ins_level, int level)
{
  uchar *k;
  uint nod_flag;
  uchar *page_buf;
  int res;
  DBUG_ENTER("rtree_insert_req");

  if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length + 
                                     MI_MAX_KEY_BUFF)))
  {
    my_errno = HA_ERR_OUT_OF_MEM;
    DBUG_RETURN(-1); /* purecov: inspected */
  }
  if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
    goto err1;
  nod_flag = mi_test_if_nod(page_buf);
  DBUG_PRINT("rtree", ("page: %lu  level: %d  ins_level: %d  nod_flag: %u",
                       (ulong) page, level, ins_level, nod_flag));

  if ((ins_level == -1 && nod_flag) ||       /* key: go down to leaf */
      (ins_level > -1 && ins_level > level)) /* branch: go down to ins_level */
  { 
    if ((k = rtree_pick_key(info, keyinfo, key, key_length, page_buf, 
                             nod_flag)) == NULL)
      goto err1;
    switch ((res = rtree_insert_req(info, keyinfo, key, key_length, 
                     _mi_kpos(nod_flag, k), new_page, ins_level, level + 1)))
    {
      case 0: /* child was not split */
      {
        rtree_combine_rect(keyinfo->seg, k, key, k, key_length);
        if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
          goto err1;
        goto ok;
      }
      case 1: /* child was split */
      {
        uchar *new_key = page_buf + keyinfo->block_length + nod_flag;
        /* set proper MBR for key */
        if (rtree_set_key_mbr(info, keyinfo, k, key_length, 
                            _mi_kpos(nod_flag, k)))
          goto err1;
        /* add new key for new page */
        _mi_kpointer(info, new_key - nod_flag, *new_page);
        if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, *new_page))
          goto err1;
        res = rtree_add_key(info, keyinfo, new_key, key_length, 
                           page_buf, new_page);
        if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
          goto err1;
        goto ok;
      }
      default:
      case -1: /* error */
      {
        goto err1;
      }
    }
  }
  else
  { 
    res = rtree_add_key(info, keyinfo, key, key_length, page_buf, new_page);
    if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
      goto err1;
    goto ok;
  }

ok:
  my_afree((uchar*)page_buf);
  DBUG_RETURN(res);

err1:
  my_afree((uchar*)page_buf);
  DBUG_RETURN(-1); /* purecov: inspected */
}
ha_rows rtree_estimate(MI_INFO *info, uint keynr, uchar *key, 
                       uint key_length, uint flag)
{
  MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
  my_off_t root;
  uint i = 0;
  uchar *k;
  uchar *last;
  uint nod_flag;
  uchar *page_buf;
  uint k_len;
  double area = 0;
  ha_rows res = 0;

  if (flag & MBR_DISJOINT)
    return info->state->records;

  if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
    return HA_POS_ERROR;
  if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
    return HA_POS_ERROR;
  if (!_mi_fetch_keypage(info, keyinfo, root, DFLT_INIT_HITS, page_buf, 0))
    goto err1;
  nod_flag = mi_test_if_nod(page_buf);

  k_len = keyinfo->keylength - info->s->base.rec_reflength;

  k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
  last = rt_PAGE_END(page_buf);

  for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag), ++i)
  {
    if (nod_flag)
    {
      double k_area = rtree_rect_volume(keyinfo->seg, k, key_length);

      /* The following should be safe, even if we compare doubles */
      if (k_area == 0)
      {
        if (flag & (MBR_CONTAIN | MBR_INTERSECT))
        {
          area += 1;
        }
        else if (flag & (MBR_WITHIN | MBR_EQUAL))
        {
          if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN))
            area += 1;
        }
        else
          goto err1;
      }
      else
      {
        if (flag & (MBR_CONTAIN | MBR_INTERSECT))
        {
          area += rtree_overlapping_area(keyinfo->seg, key, k, key_length) / 
                  k_area;
        }
        else if (flag & (MBR_WITHIN | MBR_EQUAL))
        {
          if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN))
            area += rtree_rect_volume(keyinfo->seg, key, key_length) /
                    k_area;
        }
        else
          goto err1;
      }
    }
    else
    {
      if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, flag))
        ++res;
    }
  }
  if (nod_flag)
  {
    if (i)
      res = (ha_rows) (area / i * info->state->records);
    else 
      res = HA_POS_ERROR;
  }

  my_afree((uchar*)page_buf);
  return res;

err1:
  my_afree((uchar*)page_buf);
  return HA_POS_ERROR;
}
Example #8
0
static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key, 
                             uint key_length, int ins_level)
{
  my_off_t old_root;
  MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
  int res;
  my_off_t new_page;
  DBUG_ENTER("rtree_insert_level");

  if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
  {
    if ((old_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
      DBUG_RETURN(-1);
    info->buff_used = 1;
    mi_putint(info->buff, 2, 0);
    res = rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL);
    if (_mi_write_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, info->buff))
      DBUG_RETURN(1);
    info->s->state.key_root[keynr] = old_root;
    DBUG_RETURN(res);
  }

  switch ((res = rtree_insert_req(info, keyinfo, key, key_length, 
                                  old_root, &new_page, ins_level, 0)))
  {
    case 0: /* root was not split */
    {
      break;
    }
    case 1: /* root was split, grow a new root */
    { 
      uchar *new_root_buf;
      my_off_t new_root;
      uchar *new_key;
      uint nod_flag = info->s->base.key_reflength;

      DBUG_PRINT("rtree", ("root was split, grow a new root"));
      if (!(new_root_buf = (uchar*)my_alloca((uint)keyinfo->block_length + 
                                             MI_MAX_KEY_BUFF)))
      {
        my_errno = HA_ERR_OUT_OF_MEM;
        DBUG_RETURN(-1); /* purecov: inspected */
      }

      mi_putint(new_root_buf, 2, nod_flag);
      if ((new_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) ==
	  HA_OFFSET_ERROR)
        goto err1;

      new_key = new_root_buf + keyinfo->block_length + nod_flag;

      _mi_kpointer(info, new_key - nod_flag, old_root);
      if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, old_root))
        goto err1;
      if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL) 
          == -1)
        goto err1;
      _mi_kpointer(info, new_key - nod_flag, new_page);
      if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, new_page))
        goto err1;
      if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL) 
          == -1)
        goto err1;
      if (_mi_write_keypage(info, keyinfo, new_root,
                            DFLT_INIT_HITS, new_root_buf))
        goto err1;
      info->s->state.key_root[keynr] = new_root;
      DBUG_PRINT("rtree", ("new root page: %lu  level: %d  nod_flag: %u",
                           (ulong) new_root, 0, mi_test_if_nod(new_root_buf)));

      my_afree((uchar*)new_root_buf);
      break;
err1:
      my_afree((uchar*)new_root_buf);
      DBUG_RETURN(-1); /* purecov: inspected */
    }
    default:
    case -1: /* error */
    {
      break;
    }
  }
  DBUG_RETURN(res);
}
Example #9
0
static int rtree_get_req(MI_INFO *info, MI_KEYDEF *keyinfo, uint key_length, 
                         my_off_t page, int level)
{
  uchar *k;
  uchar *last;
  uint nod_flag;
  int res;
  uchar *page_buf;
  uint k_len;
  uint *saved_key = (uint*) (info->rtree_recursion_state) + level;
  
  if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
    return -1;
  if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
    goto err1;
  nod_flag = mi_test_if_nod(page_buf);

  k_len = keyinfo->keylength - info->s->base.rec_reflength;

  if(info->rtree_recursion_depth >= level)
  {
    k = page_buf + *saved_key;
    if (!nod_flag)
    {
      /* Only leaf pages contain data references. */
      /* Need to check next key with data reference. */
      k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
    }
  }
  else
  {
    k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
  }
  last = rt_PAGE_END(page_buf);

  for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag))
  {
    if (nod_flag) 
    { 
      /* this is an internal node in the tree */
      switch ((res = rtree_get_req(info, keyinfo, key_length, 
                                  _mi_kpos(nod_flag, k), level + 1)))
      {
        case 0: /* found - exit from recursion */
          *saved_key = k - page_buf;
          goto ok;
        case 1: /* not found - continue searching */
          info->rtree_recursion_depth = level;
          break;
        default:
        case -1: /* error */
          goto err1;
      }
    }
    else 
    { 
      /* this is a leaf */
      uchar *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
      info->lastpos = _mi_dpos(info, 0, after_key);
      info->lastkey_length = k_len + info->s->base.rec_reflength;
      memcpy(info->lastkey, k, info->lastkey_length);

      info->rtree_recursion_depth = level;
      *saved_key = k - page_buf;

      if (after_key < last)
      {
        info->int_keypos = (uchar*)saved_key;
        memcpy(info->buff, page_buf, keyinfo->block_length);
        info->int_maxpos = rt_PAGE_END(info->buff);
        info->buff_used = 0;
      }
      else
      {
	info->buff_used = 1;
      }

      res = 0;
      goto ok;
    }
  }
  info->lastpos = HA_OFFSET_ERROR;
  my_errno = HA_ERR_KEY_NOT_FOUND;
  res = 1;

ok:
  my_afree((uchar*)page_buf);
  return res;

err1:
  my_afree((uchar*)page_buf);
  info->lastpos = HA_OFFSET_ERROR;
  return -1;
}
Example #10
0
int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key, 
                     uint key_length, my_off_t *new_page_offs)
{
  int n1, n2; /* Number of items in groups */

  SplitStruct *task;
  SplitStruct *cur;
  SplitStruct *stop;
  double *coord_buf;
  double *next_coord;
  int n_dim;
  uchar *source_cur, *cur1, *cur2;
  uchar *new_page= info->buff;
  int err_code= 0;
  uint nod_flag= mi_test_if_nod(page);
  uint full_length= key_length + (nod_flag ? nod_flag : 
                                  info->s->base.rec_reflength);
  int max_keys= (mi_getint(page)-2) / (full_length);
  DBUG_ENTER("rtree_split_page");
  DBUG_PRINT("rtree", ("splitting block"));

  n_dim = keyinfo->keysegs / 2;
  
  if (!(coord_buf= (double*) my_alloca(n_dim * 2 * sizeof(double) *
                                       (max_keys + 1 + 4) +
                                       sizeof(SplitStruct) * (max_keys + 1))))
    DBUG_RETURN(-1); /* purecov: inspected */

  task= (SplitStruct *)(coord_buf + n_dim * 2 * (max_keys + 1 + 4));

  next_coord = coord_buf;
 
  stop = task + max_keys;
  source_cur = rt_PAGE_FIRST_KEY(page, nod_flag);

  for (cur = task; cur < stop; ++cur, source_cur = rt_PAGE_NEXT_KEY(source_cur, 
       key_length, nod_flag))
  {
    cur->coords = reserve_coords(&next_coord, n_dim);
    cur->key = source_cur;
    rtree_d_mbr(keyinfo->seg, source_cur, key_length, cur->coords);
  }

  cur->coords = reserve_coords(&next_coord, n_dim);
  rtree_d_mbr(keyinfo->seg, key, key_length, cur->coords);
  cur->key = key;

  if (split_rtree_node(task, max_keys + 1,
       mi_getint(page) + full_length + 2, full_length, 
       rt_PAGE_MIN_SIZE(keyinfo->block_length),
       2, 2, &next_coord, n_dim))
  {
    err_code = 1;
    goto split_err;
  }

  info->buff_used= 1;
  stop = task + (max_keys + 1);
  cur1 = rt_PAGE_FIRST_KEY(page, nod_flag);
  cur2 = rt_PAGE_FIRST_KEY(new_page, nod_flag);

  n1= n2 = 0;
  for (cur = task; cur < stop; ++cur)
  {
    uchar *to;
    if (cur->n_node == 1)
    {
      to = cur1;
      cur1 = rt_PAGE_NEXT_KEY(cur1, key_length, nod_flag);
      ++n1;
    }
    else
    {
      to = cur2;
      cur2 = rt_PAGE_NEXT_KEY(cur2, key_length, nod_flag);
      ++n2;
    }
    if (to != cur->key)
      memcpy(to - nod_flag, cur->key - nod_flag, full_length);
  }
 
  mi_putint(page, 2 + n1 * full_length, nod_flag);
  mi_putint(new_page, 2 + n2 * full_length, nod_flag);

  if ((*new_page_offs= _mi_new(info, keyinfo, DFLT_INIT_HITS)) == 
                                                               HA_OFFSET_ERROR)
    err_code= -1;
  else
    err_code= _mi_write_keypage(info, keyinfo, *new_page_offs,
                                DFLT_INIT_HITS, new_page);
  DBUG_PRINT("rtree", ("split new block: %lu", (ulong) *new_page_offs));

split_err:
  my_afree((uchar*) coord_buf);
  DBUG_RETURN(err_code);
}
Example #11
0
int bin2dec(const char *from, decimal_t *to, int precision, int scale)
{
    int error=E_DEC_OK, intg=precision-scale,
            intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
            intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
            intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
    dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
    const char *stop;
    char *d_copy;
    int bin_size= decimal_bin_size(precision, scale);

    //sanity(to);
    d_copy= (char*) my_alloca(bin_size);
    memcpy(d_copy, from, bin_size);
    d_copy[0]^= 0x80;
    from= d_copy;

    FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
    if (unlikely(error))
    {
        if (intg1 < intg0+(intg0x>0))
        {
            from+=dig2bytes[intg0x]+sizeof(dec1)*(intg0-intg1);
            frac0=frac0x=intg0x=0;
            intg0=intg1;
        }
        else
        {
            frac0x=0;
            frac0=frac1;
        }
    }

    to->sign=(mask != 0);
    to->intg=intg0*DIG_PER_DEC1+intg0x;
    to->frac=frac0*DIG_PER_DEC1+frac0x;

    if (intg0x)
    {
        int i=dig2bytes[intg0x];
        dec1 UNINIT_VAR(x);
        switch (i)
        {
            case 1: x=mi_sint1korr(from); break;
            case 2: x=mi_sint2korr(from); break;
            case 3: x=mi_sint3korr(from); break;
            case 4: x=mi_sint4korr(from); break;
            default: DBUG_ASSERT(0);
        }
        from+=i;
        *buf=x ^ mask;
        if (((ulonglong)*buf) >= (ulonglong) powers10[intg0x+1])
            goto err;
        if (buf > to->buf || *buf != 0)
            buf++;
        else
            to->intg-=intg0x;
    }
    for (stop=from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1))
    {
        DBUG_ASSERT(sizeof(dec1) == 4);
        *buf=mi_sint4korr(from) ^ mask;
        if (((uint32)*buf) > DIG_MAX)
            goto err;
        if (buf > to->buf || *buf != 0)
            buf++;
        else
            to->intg-=DIG_PER_DEC1;
    }
    DBUG_ASSERT(to->intg >=0);
    for (stop=from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1))
    {
        DBUG_ASSERT(sizeof(dec1) == 4);
        *buf=mi_sint4korr(from) ^ mask;
        if (((uint32)*buf) > DIG_MAX)
            goto err;
        buf++;
    }
    if (frac0x)
    {
        int i=dig2bytes[frac0x];
        dec1 UNINIT_VAR(x);
        switch (i)
        {
            case 1: x=mi_sint1korr(from); break;
            case 2: x=mi_sint2korr(from); break;
            case 3: x=mi_sint3korr(from); break;
            case 4: x=mi_sint4korr(from); break;
            default: DBUG_ASSERT(0);
        }
        *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
        if (((uint32)*buf) > DIG_MAX)
            goto err;
        buf++;
    }
    my_afree(d_copy);

    if (to->intg == 0 && to->frac == 0)
        decimal_make_zero(to);
    return error;

err:
    my_afree(d_copy);
    decimal_make_zero(to);
    return(E_DEC_BAD_NUM);
}
Example #12
0
static int send_client_reply_packet(MCPVIO_EXT *mpvio,
                                    const uchar *data, int data_len)
{
    MYSQL *mysql= mpvio->mysql;
    NET *net= &mysql->net;
    char *buff, *end;
    size_t conn_attr_len= (mysql->options.extension) ?
                          mysql->options.extension->connect_attrs_len : 0;

    /* see end= buff+32 below, fixed size of the packet is 32 bytes */
    buff= my_alloca(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN + conn_attr_len + 9);

    mysql->client_flag|= mysql->options.client_flag;
    mysql->client_flag|= CLIENT_CAPABILITIES;

    if (mysql->client_flag & CLIENT_MULTI_STATEMENTS)
        mysql->client_flag|= CLIENT_MULTI_RESULTS;

#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
    if (mysql->options.ssl_key || mysql->options.ssl_cert ||
            mysql->options.ssl_ca || mysql->options.ssl_capath ||
            mysql->options.ssl_cipher)
        mysql->options.use_ssl= 1;
    if (mysql->options.use_ssl)
        mysql->client_flag|= CLIENT_SSL;

    /* if server doesn't support SSL and verification of server certificate
       was set to mandatory, we need to return an error */
    if (mysql->options.use_ssl && !(mysql->server_capabilities & CLIENT_SSL))
    {
        if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) ||
                (mysql->options.extension && (mysql->options.extension->ssl_fp ||
                                              mysql->options.extension->ssl_fp_list)))
        {
            my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
                         ER(CR_SSL_CONNECTION_ERROR),
                         "Server doesn't support SSL");
            goto error;
        }
    }

#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/
    if (mpvio->db)
        mysql->client_flag|= CLIENT_CONNECT_WITH_DB;

    /* Remove options that server doesn't support */
    mysql->client_flag= mysql->client_flag &
                        (~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)
                         | mysql->server_capabilities);

#ifndef HAVE_COMPRESS
    mysql->client_flag&= ~CLIENT_COMPRESS;
#endif

    if (mysql->client_flag & CLIENT_PROTOCOL_41)
    {
        /* 4.1 server and 4.1 client has a 32 byte option flag */
        int4store(buff,mysql->client_flag);
        int4store(buff+4, net->max_packet_size);
        buff[8]= (char) mysql->charset->nr;
        bzero(buff+9, 32-9);
        end= buff+32;
    }
    else
    {
        int2store(buff, mysql->client_flag);
        int3store(buff+2, net->max_packet_size);
        end= buff+5;
    }
#ifdef HAVE_OPENSSL
    if (mysql->options.ssl_key ||
            mysql->options.ssl_cert ||
            mysql->options.ssl_ca ||
            mysql->options.ssl_capath ||
            mysql->options.ssl_cipher
#ifdef CRL_IMPLEMENTED
            || (mysql->options.extension &&
                (mysql->options.extension->ssl_crl ||
                 mysql->options.extension->ssl_crlpath))
#endif
       )
        mysql->options.use_ssl= 1;

    if (mysql->options.use_ssl &&
            (mysql->client_flag & CLIENT_SSL))
    {
        SSL *ssl;
        /*
          Send mysql->client_flag, max_packet_size - unencrypted otherwise
          the server does not know we want to do SSL
        */
        if (my_net_write(net, (char*)buff, (size_t) (end-buff)) || net_flush(net))
        {
            my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
                         ER(CR_SERVER_LOST_EXTENDED),
                         "sending connection information to server",
                         errno);
            goto error;
        }

        /* Create SSL */
        if (!(ssl= my_ssl_init(mysql)))
            goto error;

        /* Connect to the server */
        if (my_ssl_connect(ssl))
        {
            SSL_free(ssl);
            goto error;
        }

        if (mysql->options.extension &&
                (mysql->options.extension->ssl_fp || mysql->options.extension->ssl_fp_list))
        {
            if (ma_ssl_verify_fingerprint(ssl))
                goto error;
        }

        if ((mysql->options.ssl_ca || mysql->options.ssl_capath) &&
                (mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
                my_ssl_verify_server_cert(ssl))
            goto error;
    }
#endif /* HAVE_OPENSSL */

    DBUG_PRINT("info",("Server version = '%s'  capabilites: %lu  status: %u  client_flag: %lu",
                       mysql->server_version, mysql->server_capabilities,
                       mysql->server_status, mysql->client_flag));

    compile_time_assert(MYSQL_USERNAME_LENGTH == USERNAME_LENGTH);

    /* This needs to be changed as it's not useful with big packets */
    if (mysql->user[0])
        strmake(end, mysql->user, USERNAME_LENGTH);
    else
        read_user_name(end);

    /* We have to handle different version of handshake here */
    DBUG_PRINT("info",("user: %s",end));
    end= strend(end) + 1;
    if (data_len)
    {
        if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
        {
            *end++= data_len;
            memcpy(end, data, data_len);
            end+= data_len;
        }
        else
        {
            DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1); /* incl. \0 at the end */
            memcpy(end, data, data_len);
            end+= data_len;
        }
    }
    else
        *end++= 0;

    /* Add database if needed */
    if (mpvio->db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
    {
        end= strmake(end, mpvio->db, NAME_LEN) + 1;
        mysql->db= my_strdup(mpvio->db, MYF(MY_WME));
    }

    if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
        end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;

    end= ma_send_connect_attr(mysql, end);

    /* Write authentication package */
    if (my_net_write(net, buff, (size_t) (end-buff)) || net_flush(net))
    {
        my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
                     ER(CR_SERVER_LOST_EXTENDED),
                     "sending authentication information",
                     errno);
        goto error;
    }
    my_afree(buff);
    return 0;

error:
    my_afree(buff);
    return 1;
}
Example #13
0
static int 
w_search(register MI_INFO * info, register MI_KEYDEF * keyinfo,
	 uchar * key, uint key_length, my_off_t page,
	 uchar * father_buff,
	 uchar * father_keypos, my_off_t father_page,
	 my_bool insert_last)
{
	int		error     , flag;
	uint		comp_flag, nod_flag;
	uchar          *temp_buff, *keypos;
	uchar		keybuff  [MI_MAX_KEY_BUFF];
	my_bool		was_last_key;
	my_off_t	next_page;
	DBUG_ENTER("w_search");
	DBUG_PRINT("enter", ("page: %ld", page));

	if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
		comp_flag = SEARCH_BIGGER;	/* Put after same key */
	else if (keyinfo->flag & HA_NOSAME)
		comp_flag = SEARCH_FIND | SEARCH_UPDATE;	/* No dupplicates */
	else
		comp_flag = SEARCH_SAME;	/* Keys in rec-pos order */

	if (!(temp_buff = (uchar *) my_alloca((uint) keyinfo->block_length +
					      MI_MAX_KEY_BUFF * 2)))
		DBUG_RETURN(-1);
	if (!_mi_fetch_keypage(info, keyinfo, page, temp_buff, 0))
		goto err;

	flag = (*keyinfo->bin_search) (info, keyinfo, temp_buff, key, key_length, comp_flag,
				       &keypos, keybuff, &was_last_key);
	nod_flag = mi_test_if_nod(temp_buff);
	if (flag == 0) {
		uint		tmp_key_length;
		my_errno = HA_ERR_FOUND_DUPP_KEY;
		/* get position to record with duplicated key */
		tmp_key_length = (*keyinfo->get_key) (keyinfo, nod_flag, &keypos, keybuff);
		if (tmp_key_length)
			info->dupp_key_pos = _mi_dpos(info, 0, keybuff + tmp_key_length);
		else
			info->dupp_key_pos = HA_OFFSET_ERROR;
		my_afree((byte *) temp_buff);
		DBUG_RETURN(-1);
	}
	if (flag == MI_FOUND_WRONG_KEY)
		DBUG_RETURN(-1);
	if (!was_last_key)
		insert_last = 0;
	next_page = _mi_kpos(nod_flag, keypos);
	if (next_page == HA_OFFSET_ERROR ||
	    (error = w_search(info, keyinfo, key, key_length, next_page,
			      temp_buff, keypos, page, insert_last)) > 0) {
		error = _mi_insert(info, keyinfo, key, temp_buff, keypos, keybuff, father_buff,
				   father_keypos, father_page, insert_last);
		if (_mi_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 */