1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

5.3 merge

This commit is contained in:
Sergei Golubchik
2013-01-28 13:36:05 +01:00
15 changed files with 208 additions and 82 deletions

View File

@@ -847,6 +847,38 @@ time(f1)
00:00:00.000200 00:00:00.000200
00:00:00.000300 00:00:00.000300
drop table t1; drop table t1;
create table t1(i int, g int);
insert into t1 values (null, 1), (0, 2);
select distinct i from t1 group by g;
i
NULL
0
drop table t1;
create table t1(i int, g blob);
insert into t1 values (null, 1), (0, 2);
select distinct i from t1 group by g;
i
NULL
0
drop table t1;
create table t1 (a int) engine=myisam;
insert into t1 values (0),(7);
create table t2 (b int) engine=myisam;
insert into t2 values (7),(0),(3);
create algorithm=temptable view v as
select distinct (select max(a) from t1 where alias.b = a) as field1 from t2 as alias group by field1;
select * from v;
field1
NULL
0
7
select distinct (select max(a) from t1 where alias.b = a) as field1 from t2 as alias group by field1;
field1
NULL
0
7
drop view v;
drop table t1, t2;
# #
# Bug #11744875: 4082: integer lengths cause truncation with distinct concat and innodb # Bug #11744875: 4082: integer lengths cause truncation with distinct concat and innodb
# #

View File

@@ -2933,6 +2933,13 @@ ORDER BY min_a;
min_a min_a
NULL NULL
DROP TABLE t1; DROP TABLE t1;
create table t1 (a int, b varchar(1), key(b,a)) engine=myisam;
insert t1 values (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(null,'i');
select min(a), b from t1 where a=7 or b='z' group by b;
min(a) b
7 g
flush tables;
drop table t1;
# #
# LP BUG#888456 Wrong result with DISTINCT , ANY , subquery_cache=off , NOT NULL # LP BUG#888456 Wrong result with DISTINCT , ANY , subquery_cache=off , NOT NULL
# #

View File

@@ -2768,6 +2768,21 @@ HAVING t1sum <> 1;
t1sum b t1sum b
DROP TABLE t1, t2; DROP TABLE t1, t2;
# #
# MDEV-3911: Assertion `fixed == 0' failed in Item_field::fix_fields
# on 2nd execution of PS with semijoin=on and IN subquery
#
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0,4),(8,6);
CREATE TABLE t2 (c INT, d INT) ENGINE=MyISAM;
INSERT INTO t2 VALUES (7,1),(0,7);
PREPARE stmt FROM ' SELECT * FROM t1 WHERE ( a, b ) IN ( SELECT c, d FROM t2 ) ';
execute stmt;
a b
execute stmt;
a b
deallocate prepare stmt;
drop table t1,t2;
#
# MySQL Bug#13340270: assertion table->sort.record_pointers == __null # MySQL Bug#13340270: assertion table->sort.record_pointers == __null
# #
CREATE TABLE t1 ( CREATE TABLE t1 (

View File

@@ -2782,6 +2782,21 @@ HAVING t1sum <> 1;
t1sum b t1sum b
DROP TABLE t1, t2; DROP TABLE t1, t2;
# #
# MDEV-3911: Assertion `fixed == 0' failed in Item_field::fix_fields
# on 2nd execution of PS with semijoin=on and IN subquery
#
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0,4),(8,6);
CREATE TABLE t2 (c INT, d INT) ENGINE=MyISAM;
INSERT INTO t2 VALUES (7,1),(0,7);
PREPARE stmt FROM ' SELECT * FROM t1 WHERE ( a, b ) IN ( SELECT c, d FROM t2 ) ';
execute stmt;
a b
execute stmt;
a b
deallocate prepare stmt;
drop table t1,t2;
#
# MySQL Bug#13340270: assertion table->sort.record_pointers == __null # MySQL Bug#13340270: assertion table->sort.record_pointers == __null
# #
CREATE TABLE t1 ( CREATE TABLE t1 (

View File

@@ -658,6 +658,31 @@ select time(f1) from t1 ;
select distinct time(f1) from t1 ; select distinct time(f1) from t1 ;
drop table t1; drop table t1;
#
# MDEV-3875 Wrong result (missing row) on a DISTINCT query with the same subquery in the SELECT list and GROUP BY
# MySQL Bug#66896 Distinct not distinguishing 0 from NULL when GROUP BY is used
#
create table t1(i int, g int); # remove_dup_with_hash_index
insert into t1 values (null, 1), (0, 2);
select distinct i from t1 group by g;
drop table t1;
create table t1(i int, g blob); # remove_dup_with_compare
insert into t1 values (null, 1), (0, 2);
select distinct i from t1 group by g;
drop table t1;
create table t1 (a int) engine=myisam;
insert into t1 values (0),(7);
create table t2 (b int) engine=myisam;
insert into t2 values (7),(0),(3);
create algorithm=temptable view v as
select distinct (select max(a) from t1 where alias.b = a) as field1 from t2 as alias group by field1;
select * from v;
select distinct (select max(a) from t1 where alias.b = a) as field1 from t2 as alias group by field1;
drop view v;
drop table t1, t2;
--echo # --echo #
--echo # Bug #11744875: 4082: integer lengths cause truncation with distinct concat and innodb --echo # Bug #11744875: 4082: integer lengths cause truncation with distinct concat and innodb
--echo # --echo #

View File

@@ -1155,6 +1155,15 @@ ORDER BY min_a;
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-729 lp:998028 - Server crashes on normal shutdown in closefrm after executing a query from MyISAM table
#
create table t1 (a int, b varchar(1), key(b,a)) engine=myisam;
insert t1 values (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(null,'i');
select min(a), b from t1 where a=7 or b='z' group by b;
flush tables;
drop table t1;
--echo # --echo #
--echo # LP BUG#888456 Wrong result with DISTINCT , ANY , subquery_cache=off , NOT NULL --echo # LP BUG#888456 Wrong result with DISTINCT , ANY , subquery_cache=off , NOT NULL
--echo # --echo #

View File

@@ -2462,6 +2462,25 @@ HAVING t1sum <> 1;
DROP TABLE t1, t2; DROP TABLE t1, t2;
--echo #
--echo # MDEV-3911: Assertion `fixed == 0' failed in Item_field::fix_fields
--echo # on 2nd execution of PS with semijoin=on and IN subquery
--echo #
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0,4),(8,6);
CREATE TABLE t2 (c INT, d INT) ENGINE=MyISAM;
INSERT INTO t2 VALUES (7,1),(0,7);
eval PREPARE stmt FROM ' SELECT * FROM t1 WHERE ( a, b ) IN ( SELECT c, d FROM t2 ) ';
execute stmt;
execute stmt;
deallocate prepare stmt;
drop table t1,t2;
--echo # --echo #
--echo # MySQL Bug#13340270: assertion table->sort.record_pointers == __null --echo # MySQL Bug#13340270: assertion table->sort.record_pointers == __null
--echo # --echo #

View File

@@ -1119,6 +1119,21 @@ bool Field::type_can_have_key_part(enum enum_field_types type)
} }
void Field::make_sort_key(uchar *buff,uint length)
{
if (maybe_null())
{
if (is_null())
{
bzero(buff, length + 1);
return;
}
*buff++= 1;
}
sort_string(buff, length);
}
/** /**
Numeric fields base class constructor. Numeric fields base class constructor.
*/ */

View File

@@ -410,6 +410,7 @@ public:
return bytes; return bytes;
} }
void make_sort_key(uchar *buff, uint length);
virtual void make_field(Send_field *); virtual void make_field(Send_field *);
virtual void sort_string(uchar *buff,uint length)=0; virtual void sort_string(uchar *buff,uint length)=0;
virtual bool optimize_range(uint idx, uint part); virtual bool optimize_range(uint idx, uint part);

View File

@@ -789,21 +789,9 @@ static void make_sortkey(register SORTPARAM *param,
bool maybe_null=0; bool maybe_null=0;
if ((field=sort_field->field)) if ((field=sort_field->field))
{ // Field { // Field
if (field->maybe_null()) field->make_sort_key(to, sort_field->length);
{ if ((maybe_null = field->maybe_null()))
if (field->is_null()) to++;
{
if (sort_field->reverse)
bfill(to,sort_field->length+1,(char) 255);
else
bzero((char*) to,sort_field->length+1);
to+= sort_field->length+1;
continue;
}
else
*to++=1;
}
field->sort_string(to, sort_field->length);
} }
else else
{ // Item { // Item
@@ -955,8 +943,11 @@ static void make_sortkey(register SORTPARAM *param,
} }
if (sort_field->reverse) if (sort_field->reverse)
{ /* Revers key */ { /* Revers key */
if (maybe_null) if (maybe_null && (to[-1]= !to[-1]))
to[-1]= ~to[-1]; {
to+= sort_field->length; // don't waste the time reversing all 0's
continue;
}
length=sort_field->length; length=sort_field->length;
while (length--) while (length--)
{ {

View File

@@ -74,7 +74,8 @@ bool Item_row::fix_fields(THD *thd, Item **ref)
Item **arg, **arg_end; Item **arg, **arg_end;
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++) for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
{ {
if ((*arg)->fix_fields(thd, arg)) if (!(*arg)->fixed &&
(*arg)->fix_fields(thd, arg))
return TRUE; return TRUE;
// we can't assign 'item' before, because fix_fields() can change arg // we can't assign 'item' before, because fix_fields() can change arg
Item *item= *arg; Item *item= *arg;

View File

@@ -1337,7 +1337,7 @@ void Item_str_func::left_right_max_length()
if (args[1]->const_item()) if (args[1]->const_item())
{ {
int length= (int) args[1]->val_int(); int length= (int) args[1]->val_int();
if (length <= 0) if (args[1]->null_value || length <= 0)
char_length=0; char_length=0;
else else
set_if_smaller(char_length, (uint) length); set_if_smaller(char_length, (uint) length);
@@ -1444,7 +1444,9 @@ void Item_func_substr::fix_length_and_dec()
if (args[1]->const_item()) if (args[1]->const_item())
{ {
int32 start= (int32) args[1]->val_int(); int32 start= (int32) args[1]->val_int();
if (start < 0) if (args[1]->null_value)
max_length= 0;
else if (start < 0)
max_length= ((uint)(-start) > max_length) ? 0 : (uint)(-start); max_length= ((uint)(-start) > max_length) ? 0 : (uint)(-start);
else else
max_length-= min((uint)(start - 1), max_length); max_length-= min((uint)(start - 1), max_length);
@@ -1452,7 +1454,7 @@ void Item_func_substr::fix_length_and_dec()
if (arg_count == 3 && args[2]->const_item()) if (arg_count == 3 && args[2]->const_item())
{ {
int32 length= (int32) args[2]->val_int(); int32 length= (int32) args[2]->val_int();
if (length <= 0) if (args[2]->null_value || length <= 0)
max_length=0; /* purecov: inspected */ max_length=0; /* purecov: inspected */
else else
set_if_smaller(max_length,(uint) length); set_if_smaller(max_length,(uint) length);
@@ -2650,7 +2652,9 @@ void Item_func_repeat::fix_length_and_dec()
/* Assumes that the maximum length of a String is < INT_MAX32. */ /* Assumes that the maximum length of a String is < INT_MAX32. */
/* Set here so that rest of code sees out-of-bound value as such. */ /* Set here so that rest of code sees out-of-bound value as such. */
if (count > INT_MAX32) if (args[1]->null_value)
count= 0;
else if (count > INT_MAX32)
count= INT_MAX32; count= INT_MAX32;
ulonglong char_length= (ulonglong) args[0]->max_char_length() * count; ulonglong char_length= (ulonglong) args[0]->max_char_length() * count;
@@ -2729,7 +2733,9 @@ void Item_func_rpad::fix_length_and_dec()
DBUG_ASSERT(collation.collation->mbmaxlen > 0); DBUG_ASSERT(collation.collation->mbmaxlen > 0);
/* Assumes that the maximum length of a String is < INT_MAX32. */ /* Assumes that the maximum length of a String is < INT_MAX32. */
/* Set here so that rest of code sees out-of-bound value as such. */ /* Set here so that rest of code sees out-of-bound value as such. */
if (char_length > INT_MAX32) if (args[1]->null_value)
char_length= 0;
else if (char_length > INT_MAX32)
char_length= INT_MAX32; char_length= INT_MAX32;
fix_char_length_ulonglong(char_length); fix_char_length_ulonglong(char_length);
} }
@@ -2833,7 +2839,9 @@ void Item_func_lpad::fix_length_and_dec()
DBUG_ASSERT(collation.collation->mbmaxlen > 0); DBUG_ASSERT(collation.collation->mbmaxlen > 0);
/* Assumes that the maximum length of a String is < INT_MAX32. */ /* Assumes that the maximum length of a String is < INT_MAX32. */
/* Set here so that rest of code sees out-of-bound value as such. */ /* Set here so that rest of code sees out-of-bound value as such. */
if (char_length > INT_MAX32) if (args[1]->null_value)
char_length= 0;
else if (char_length > INT_MAX32)
char_length= INT_MAX32; char_length= INT_MAX32;
fix_char_length_ulonglong(char_length); fix_char_length_ulonglong(char_length);
} }

View File

@@ -13382,9 +13382,10 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
*/ */
if (min_max_arg_part && min_max_arg_part->field->is_null()) if (min_max_arg_part && min_max_arg_part->field->is_null())
{ {
uchar *tmp_key_buff= (uchar*)my_alloca(max_used_key_length);
/* Find the first subsequent record without NULL in the MIN/MAX field. */ /* Find the first subsequent record without NULL in the MIN/MAX field. */
key_copy(tmp_record, record, index_info, max_used_key_length); key_copy(tmp_key_buff, record, index_info, max_used_key_length);
result= file->ha_index_read_map(record, tmp_record, result= file->ha_index_read_map(record, tmp_key_buff,
make_keypart_map(real_key_parts), make_keypart_map(real_key_parts),
HA_READ_AFTER_KEY); HA_READ_AFTER_KEY);
/* /*
@@ -13400,10 +13401,11 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
if (!result) if (!result)
{ {
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len)) if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
key_restore(record, tmp_record, index_info, 0); key_restore(record, tmp_key_buff, index_info, 0);
} }
else if (result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) else if (result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE)
result= 0; /* There is a result in any case. */ result= 0; /* There is a result in any case. */
my_afree(tmp_key_buff);
} }
} }

View File

@@ -2320,7 +2320,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
{ {
my_ptrdiff_t adjust_ptrs; my_ptrdiff_t adjust_ptrs;
Field **field,**org_field, *found_next_number_field; Field **field,**org_field, *found_next_number_field;
Field **vfield; Field **UNINIT_VAR(vfield);
TABLE *copy; TABLE *copy;
TABLE_SHARE *share; TABLE_SHARE *share;
uchar *bitmap; uchar *bitmap;

View File

@@ -227,7 +227,7 @@ static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields, static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
Item *having); Item *having);
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field, static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
ulong offset,Item *having); Item *having);
static int remove_dup_with_hash_index(THD *thd,TABLE *table, static int remove_dup_with_hash_index(THD *thd,TABLE *table,
uint field_count, Field **first_field, uint field_count, Field **first_field,
ulong key_length,Item *having); ulong key_length,Item *having);
@@ -19172,19 +19172,24 @@ void JOIN::clean_pre_sort_join_tab()
} }
/***************************************************************************** /**
Remove duplicates from tmp table Compare fields from table->record[0] and table->record[1],
This should be recoded to add a unique index to the table and remove possibly skipping few first fields.
duplicates
Table is a locked single thread table
fields is the number of fields to check (from the end)
*****************************************************************************/
@param table
@param ptr field to start the comparison from,
somewhere in the table->field[] array
@retval 1 different
@retval 0 identical
*/
static bool compare_record(TABLE *table, Field **ptr) static bool compare_record(TABLE *table, Field **ptr)
{ {
for (; *ptr ; ptr++) for (; *ptr ; ptr++)
{ {
if ((*ptr)->cmp_offset(table->s->rec_buff_length)) Field *f= *ptr;
if (f->is_null() != f->is_null(table->s->rec_buff_length) ||
(!f->is_null() && f->cmp_offset(table->s->rec_buff_length)))
return 1; return 1;
} }
return 0; return 0;
@@ -19212,16 +19217,16 @@ static void free_blobs(Field **ptr)
static int static int
remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having) remove_duplicates(JOIN *join, TABLE *table, List<Item> &fields, Item *having)
{ {
int error; int error;
ulong reclength,offset; ulong keylength= 0;
uint field_count; uint field_count;
THD *thd= join->thd; THD *thd= join->thd;
DBUG_ENTER("remove_duplicates"); DBUG_ENTER("remove_duplicates");
entry->reginfo.lock_type=TL_WRITE; table->reginfo.lock_type=TL_WRITE;
/* Calculate how many saved fields there is in list */ /* Calculate how many saved fields there is in list */
field_count=0; field_count=0;
@@ -19238,11 +19243,10 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
join->unit->select_limit_cnt= 1; // Only send first row join->unit->select_limit_cnt= 1; // Only send first row
DBUG_RETURN(0); DBUG_RETURN(0);
} }
Field **first_field=entry->field+entry->s->fields - field_count;
offset= (field_count ? Field **first_field=table->field+table->s->fields - field_count;
entry->field[entry->s->fields - field_count]-> for (Field **ptr=first_field; *ptr; ptr++)
offset(entry->record[0]) : 0); keylength+= (*ptr)->sort_length() + (*ptr)->maybe_null();
reclength=entry->s->reclength-offset;
/* /*
Disable LIMIT ROWS EXAMINED in order to avoid interrupting prematurely Disable LIMIT ROWS EXAMINED in order to avoid interrupting prematurely
@@ -19251,18 +19255,17 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
thd->lex->limit_rows_examined_cnt= ULONGLONG_MAX; thd->lex->limit_rows_examined_cnt= ULONGLONG_MAX;
if (thd->killed == ABORT_QUERY) if (thd->killed == ABORT_QUERY)
thd->reset_killed(); thd->reset_killed();
free_io_cache(entry); // Safety
entry->file->info(HA_STATUS_VARIABLE); free_io_cache(table); // Safety
if (entry->s->db_type() == heap_hton || table->file->info(HA_STATUS_VARIABLE);
(!entry->s->blob_fields && if (table->s->db_type() == heap_hton ||
((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->stats.records < (!table->s->blob_fields &&
((ALIGN_SIZE(keylength) + HASH_OVERHEAD) * table->file->stats.records <
thd->variables.sortbuff_size))) thd->variables.sortbuff_size)))
error=remove_dup_with_hash_index(join->thd, entry, error=remove_dup_with_hash_index(join->thd, table, field_count, first_field,
field_count, first_field, keylength, having);
reclength, having);
else else
error=remove_dup_with_compare(join->thd, entry, first_field, offset, error=remove_dup_with_compare(join->thd, table, first_field, having);
having);
if (join->select_lex != join->select_lex->master_unit()->fake_select_lex) if (join->select_lex != join->select_lex->master_unit()->fake_select_lex)
thd->lex->set_limit_rows_examined(); thd->lex->set_limit_rows_examined();
@@ -19272,18 +19275,13 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field, static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
ulong offset, Item *having) Item *having)
{ {
handler *file=table->file; handler *file=table->file;
char *org_record,*new_record; uchar *record=table->record[0];
uchar *record;
int error; int error;
ulong reclength= table->s->reclength-offset;
DBUG_ENTER("remove_dup_with_compare"); DBUG_ENTER("remove_dup_with_compare");
org_record=(char*) (record=table->record[0])+offset;
new_record=(char*) table->record[1]+offset;
if (file->ha_rnd_init_with_error(1)) if (file->ha_rnd_init_with_error(1))
DBUG_RETURN(1); DBUG_RETURN(1);
@@ -19320,7 +19318,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
error=0; error=0;
goto err; goto err;
} }
memcpy(new_record,org_record,reclength); store_record(table,record[1]);
/* Read through rest of file and mark duplicated rows deleted */ /* Read through rest of file and mark duplicated rows deleted */
bool found=0; bool found=0;
@@ -19379,8 +19377,9 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
int error; int error;
handler *file= table->file; handler *file= table->file;
ulong extra_length= ALIGN_SIZE(key_length)-key_length; ulong extra_length= ALIGN_SIZE(key_length)-key_length;
uint *field_lengths,*field_length; uint *field_lengths, *field_length;
HASH hash; HASH hash;
Field **ptr;
DBUG_ENTER("remove_dup_with_hash_index"); DBUG_ENTER("remove_dup_with_hash_index");
if (!my_multi_malloc(MYF(MY_WME), if (!my_multi_malloc(MYF(MY_WME),
@@ -19392,21 +19391,8 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
NullS)) NullS))
DBUG_RETURN(1); DBUG_RETURN(1);
{ for (ptr= first_field, field_length=field_lengths ; *ptr ; ptr++)
Field **ptr; (*field_length++)= (*ptr)->sort_length();
ulong total_length= 0;
for (ptr= first_field, field_length=field_lengths ; *ptr ; ptr++)
{
uint length= (*ptr)->sort_length();
(*field_length++)= length;
total_length+= length;
}
DBUG_PRINT("info",("field_count: %u key_length: %lu total_length: %lu",
field_count, key_length, total_length));
DBUG_ASSERT(total_length <= key_length);
key_length= total_length;
extra_length= ALIGN_SIZE(key_length)-key_length;
}
if (my_hash_init(&hash, &my_charset_bin, (uint) file->stats.records, 0, if (my_hash_init(&hash, &my_charset_bin, (uint) file->stats.records, 0,
key_length, (my_hash_get_key) 0, 0, 0)) key_length, (my_hash_get_key) 0, 0, 0))
@@ -19446,10 +19432,10 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
/* copy fields to key buffer */ /* copy fields to key buffer */
org_key_pos= key_pos; org_key_pos= key_pos;
field_length=field_lengths; field_length=field_lengths;
for (Field **ptr= first_field ; *ptr ; ptr++) for (ptr= first_field ; *ptr ; ptr++)
{ {
(*ptr)->sort_string(key_pos,*field_length); (*ptr)->make_sort_key(key_pos, *field_length);
key_pos+= *field_length++; key_pos+= (*ptr)->maybe_null() + *field_length++;
} }
/* Check if it exists before */ /* Check if it exists before */
if (my_hash_search(&hash, org_key_pos, key_length)) if (my_hash_search(&hash, org_key_pos, key_length))