MARIA_KEY *_ma_make_key(MARIA_HA *info, MARIA_KEY *int_key, uint keynr, uchar *key, const uchar *record, MARIA_RECORD_POS filepos, ulonglong trid) { const uchar *pos; reg1 HA_KEYSEG *keyseg; my_bool is_ft; DBUG_ENTER("_ma_make_key"); int_key->data= key; int_key->flag= 0; /* Always return full key */ int_key->keyinfo= info->s->keyinfo + keynr; is_ft= int_key->keyinfo->flag & HA_FULLTEXT; for (keyseg= int_key->keyinfo->seg ; keyseg->type ;keyseg++) { enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type; uint length=keyseg->length; uint char_length; CHARSET_INFO *cs=keyseg->charset; if (keyseg->null_bit) { if (record[keyseg->null_pos] & keyseg->null_bit) { *key++= 0; /* NULL in key */ continue; } *key++=1; /* Not NULL */ } char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length); pos= record+keyseg->start; if (type == HA_KEYTYPE_BIT) { if (keyseg->bit_length) { uchar bits= get_rec_bits(record + keyseg->bit_pos, keyseg->bit_start, keyseg->bit_length); *key++= (char) bits; length--; } memcpy(key, pos, length); key+= length; continue; } if (keyseg->flag & HA_SPACE_PACK) { if (type != HA_KEYTYPE_NUM) { length= (uint) cs->cset->lengthsp(cs, (const char*)pos, length); } else { const uchar *end= pos + length; while (pos < end && pos[0] == ' ') pos++; length= (uint) (end-pos); } FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); memcpy(key, pos, (size_t) char_length); key+=char_length; continue; } if (keyseg->flag & HA_VAR_LENGTH_PART) { uint pack_length= (keyseg->bit_start == 1 ? 1 : 2); uint tmp_length= (pack_length == 1 ? (uint) *pos : uint2korr(pos)); pos+= pack_length; /* Skip VARCHAR length */ set_if_smaller(length,tmp_length); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); memcpy(key,pos,(size_t) char_length); key+= char_length; continue; } else if (keyseg->flag & HA_BLOB_PART) { uint tmp_length= _ma_calc_blob_length(keyseg->bit_start,pos); uchar *blob_pos; memcpy(&blob_pos, pos+keyseg->bit_start,sizeof(char*)); set_if_smaller(length,tmp_length); FIX_LENGTH(cs, blob_pos, length, char_length); store_key_length_inc(key,char_length); memcpy(key, blob_pos, (size_t) char_length); key+= char_length; continue; } else if (keyseg->flag & HA_SWAP_KEY) { /* Numerical column */ #ifdef HAVE_ISNAN if (type == HA_KEYTYPE_FLOAT) { float nr; float4get(nr,pos); if (isnan(nr)) { /* Replace NAN with zero */ bzero(key,length); key+=length; continue; } } else if (type == HA_KEYTYPE_DOUBLE) { double nr; float8get(nr,pos); if (isnan(nr)) { bzero(key,length); key+=length; continue; } } #endif pos+=length; while (length--) { *key++ = *--pos; } continue; } FIX_LENGTH(cs, pos, length, char_length); memcpy(key, pos, char_length); if (length > char_length) cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' '); key+= length; } _ma_dpointer(info->s, key, filepos); int_key->data_length= (key - int_key->data); int_key->ref_length= info->s->rec_reflength; int_key->flag= 0; if (_ma_have_versioning(info) && trid) { int_key->ref_length+= transid_store_packed(info, key + int_key->ref_length, (TrID) trid); int_key->flag|= SEARCH_USER_KEY_HAS_TRANSID; } DBUG_PRINT("exit",("keynr: %d",keynr)); DBUG_DUMP_KEY("key", int_key); DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, int_key););
uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, key_part_map keypart_map) { HA_KEYSEG *seg, *endseg; uchar *start_key= key; for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg && keypart_map; old+= seg->length, seg++) { uint char_length; keypart_map>>= 1; if (seg->null_bit) { /* Convert NULL from MySQL representation into HEAP's. */ if (!(*key++= (char) 1 - *old++)) { /* Add key pack length (2) to key for VARCHAR segments */ if (seg->type == HA_KEYTYPE_VARTEXT1) old+= 2; continue; } } if (seg->flag & HA_SWAP_KEY) { uint length= seg->length; uchar *pos= (uchar*) old + length; while (length--) { *key++= *--pos; } 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; old+= 2; set_if_smaller(length,tmp_length); /* Safety */ FIX_LENGTH(cs, old, length, char_length); store_key_length_inc(key,char_length); memcpy((uchar*) key, old,(size_t) char_length); key+= char_length; continue; } char_length= seg->length; if (seg->charset->mbmaxlen > 1) { char_length= my_charpos(seg->charset, old, old+char_length, char_length / seg->charset->mbmaxlen); set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */ if (char_length < seg->length) seg->charset->cset->fill(seg->charset, (char*) key + char_length, seg->length - char_length, ' '); } memcpy(key, old, (size_t) char_length); key+= seg->length; } return (uint) (key - start_key); }
uint _mi_make_key(MI_INFO *info, uint keynr, uchar *key, const uchar *record, my_off_t filepos) { uchar *pos; uchar *start; HA_KEYSEG *keyseg; my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT; DBUG_ENTER("_mi_make_key"); if (info->s->keyinfo[keynr].flag & HA_SPATIAL) { /* TODO: nulls processing */ DBUG_RETURN(sp_make_key(info,keynr,key,record,filepos)); } start=key; for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++) { enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type; uint length=keyseg->length; uint char_length; const CHARSET_INFO *cs= keyseg->charset; if (keyseg->null_bit) { if (record[keyseg->null_pos] & keyseg->null_bit) { *key++= 0; /* NULL in key */ continue; } *key++=1; /* Not NULL */ } char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length); pos= (uchar*) record+keyseg->start; if (type == HA_KEYTYPE_BIT) { if (keyseg->bit_length) { uchar bits= get_rec_bits((uchar*) record + keyseg->bit_pos, keyseg->bit_start, keyseg->bit_length); *key++= bits; length--; } memcpy((uchar*) key, pos, length); key+= length; continue; } if (keyseg->flag & HA_SPACE_PACK) { if (type != HA_KEYTYPE_NUM) { length= cs->cset->lengthsp(cs, (char*) pos, length); } else { uchar *end= pos + length; while (pos < end && pos[0] == ' ') pos++; length=(uint) (end-pos); } FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); memcpy((uchar*) key,(uchar*) pos,(size_t) char_length); key+=char_length; continue; } if (keyseg->flag & HA_VAR_LENGTH_PART) { uint pack_length= (keyseg->bit_start == 1 ? 1 : 2); uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos)); pos+= pack_length; /* Skip VARCHAR length */ set_if_smaller(length,tmp_length); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); memcpy((uchar*) key,(uchar*) pos,(size_t) char_length); key+= char_length; continue; } else if (keyseg->flag & HA_BLOB_PART) { uint tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos); memcpy(&pos,pos+keyseg->bit_start,sizeof(char*)); set_if_smaller(length,tmp_length); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); memcpy((uchar*) key,(uchar*) pos,(size_t) char_length); key+= char_length; continue; } else if (keyseg->flag & HA_SWAP_KEY) { /* Numerical column */ if (type == HA_KEYTYPE_FLOAT) { float nr; float4get(&nr,pos); if (my_isnan(nr)) { /* Replace NAN with zero */ memset(key, 0, length); key+=length; continue; } } else if (type == HA_KEYTYPE_DOUBLE) { double nr; float8get(&nr,pos); if (my_isnan(nr)) { memset(key, 0, length); key+=length; continue; } } pos+=length; while (length--) { *key++ = *--pos; } continue; } FIX_LENGTH(cs, pos, length, char_length); memcpy((uchar*) key, pos, char_length); if (length > char_length) cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' '); key+= length; } _mi_dpointer(info,key,filepos); DBUG_PRINT("exit",("keynr: %d",keynr)); DBUG_DUMP("key",(uchar*) start,(uint) (key-start)+keyseg->length); DBUG_EXECUTE("key", _mi_print_key(DBUG_FILE,info->s->keyinfo[keynr].seg,start, (uint) (key-start)););
uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key, const uchar *rec, uchar *recpos) { uchar *start_key= key; HA_KEYSEG *seg, *endseg; for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++) { uint char_length; if (seg->null_bit) { if (!(*key++= 1 - MY_TEST(rec[seg->null_pos] & seg->null_bit))) continue; } if (seg->flag & HA_SWAP_KEY) { uint length= seg->length; uchar *pos= (uchar*) rec + seg->start; DBUG_ASSERT(seg->type != HA_KEYTYPE_BIT); #ifdef HAVE_ISNAN if (seg->type == HA_KEYTYPE_FLOAT) { float nr; float4get(nr, pos); if (isnan(nr)) { /* Replace NAN with zero */ bzero(key, length); key+= length; continue; } } else if (seg->type == HA_KEYTYPE_DOUBLE) { double nr; float8get(nr, pos); if (isnan(nr)) { bzero(key, length); key+= length; continue; } } #endif pos+= length; while (length--) { *key++= *--pos; } continue; } if (seg->flag & HA_VAR_LENGTH_PART) { uchar *pos= (uchar*) rec + seg->start; uint length= seg->length; uint pack_length= seg->bit_start; uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos)); CHARSET_INFO *cs= seg->charset; char_length= length/cs->mbmaxlen; pos+= pack_length; /* Skip VARCHAR length */ set_if_smaller(length,tmp_length); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); memcpy((uchar*) key,(uchar*) pos,(size_t) char_length); key+= char_length; continue; } char_length= seg->length; if (seg->charset->mbmaxlen > 1) { char_length= my_charpos(seg->charset, rec + seg->start, rec + seg->start + char_length, char_length / seg->charset->mbmaxlen); set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */ if (char_length < seg->length) seg->charset->cset->fill(seg->charset, (char*) key + char_length, seg->length - char_length, ' '); } if (seg->type == HA_KEYTYPE_BIT && seg->bit_length) { *key++= get_rec_bits(rec + seg->bit_pos, seg->bit_start, seg->bit_length); char_length--; } memcpy(key, rec + seg->start, (size_t) char_length); key+= seg->length; } memcpy(key, &recpos, sizeof(uchar*)); return (uint) (key - start_key); }