Commit 3ede0ff2 authored by Sergei Golubchik's avatar Sergei Golubchik

UPDATE/DELETE post-fixes

parent 4ef48fbf
......@@ -75,12 +75,12 @@ id hex(v)
9 7B713F3E5258323F80D1113D673B2B3F66E3583F
10 6CA1D43E9DF91B3FE580DA3E1C247D3F147CF33E
flush tables;
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
select id,vec_distance(v, x'B047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
id d
9 0.4719976290006591
10 0.5069011044450041
3 0.5865673124650332
select id,vec_distance(x'b047263c9f87233fcfd27e3eae493e3f0329f43e', v) d from t1 order by d limit 3;
select id,vec_distance(x'b047263C9f87233fcfd27e3eae493e3f0329f43e', v) d from t1 order by d limit 3;
id d
9 0.4719976290006591
10 0.5069011044450041
......@@ -198,32 +198,32 @@ id1 id2 vec_distance(t1.v, t2.v)
7 8 1.288239696195716
8 7 1.288239696195716
delete from t1 where v = x'7b713f3e5258323f80d1113d673b2b3f66e3583f';
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
select id,vec_distance(v, x'B047263C9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
id d
10 0.256948729687565
3 0.344061212052452
7 0.5394116168863548
10 0.5069011044450041
3 0.5865673124650332
7 0.7344464697214867
insert t1 (v) values (x'7b713f3e5258323f80d1113d673b2b3f66e3583f');
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
select id,vec_distance(v, x'b047263c9F87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
id d
11 0.22278176178224385
10 0.256948729687565
3 0.344061212052452
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
11 0.4719976290006591
10 0.5069011044450041
3 0.5865673124650332
select id,vec_distance(v, x'B047263c9F87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
id d
11 0.22278176178224385
10 0.256948729687565
3 0.344061212052452
7 0.5394116168863548
5 0.5884475540369749
11 0.4719976290006591
10 0.5069011044450041
3 0.5865673124650332
7 0.7344464697214867
5 0.7671033529042712
update t1 set v=x'76EDFC3E4B57243F10F8423FB158713F020BAA3E' where v=x'6CA1D43E9DF91B3FE580DA3E1C247D3F147CF33E';
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
select id,vec_distance(v, x'B047263C9F87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
id d
11 0.22278176178224385
3 0.344061212052452
7 0.5394116168863548
10 0.5577650851591898
5 0.5884475540369749
11 0.4719976290006591
3 0.5865673124650332
7 0.7344464697214867
10 0.746836719209219
5 0.7671033529042712
delete from t1;
insert t1 (v) values (x'e360d63ebe554f3fcdbc523f4522193f5236083d'),
(x'f511303f72224a3fdd05fe3eb22a133ffae86a3f'),
......@@ -235,13 +235,13 @@ insert t1 (v) values (x'e360d63ebe554f3fcdbc523f4522193f5236083d'),
(x'56926c3fdf098d3e2c8c5e3d1ad4953daa9d0b3e'),
(x'7b713f3e5258323f80d1113d673b2b3f66e3583f'),
(x'6ca1d43e9df91b3fe580da3e1c247d3f147cf33e');
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
select id,vec_distance(v, x'b047263c9f87233Fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
id d
20 0.22278176178224385
21 0.256948729687565
14 0.344061212052452
18 0.5394116168863548
16 0.5884475540369749
20 0.4719976290006591
21 0.5069011044450041
14 0.5865673124650332
18 0.7344464697214867
16 0.7671033529042712
insert t1 (v) values ('');
ERROR 22007: Incorrect vector value: '...' for column `test`.`t1`.`v` at row 1
insert t1 (v) values (x'1234');
......
......@@ -27,9 +27,9 @@ insert t1 (v) values (x'e360d63ebe554f3fcdbc523f4522193f5236083d'),
select id, hex(v) from t1;
flush tables;
# test with a valid query vector
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
select id,vec_distance(v, x'B047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
# swapped arguments
select id,vec_distance(x'b047263c9f87233fcfd27e3eae493e3f0329f43e', v) d from t1 order by d limit 3;
select id,vec_distance(x'b047263C9f87233fcfd27e3eae493e3f0329f43e', v) d from t1 order by d limit 3;
# test with NULL (id is unpredictable)
select id>0,vec_distance(v, NULL) d from t1 order by d limit 3;
# test with invalid query vector (id is unpredictable)
......@@ -38,16 +38,16 @@ select t1.id as id1, t2.id as id2, vec_distance(t1.v, t2.v) from t1, t1 as t2 or
# test delete
delete from t1 where v = x'7b713f3e5258323f80d1113d673b2b3f66e3583f';
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
select id,vec_distance(v, x'B047263C9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
# test insert deleted vec
insert t1 (v) values (x'7b713f3e5258323f80d1113d673b2b3f66e3583f');
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
select id,vec_distance(v, x'b047263c9F87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 3;
# test update
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
select id,vec_distance(v, x'B047263c9F87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
update t1 set v=x'76EDFC3E4B57243F10F8423FB158713F020BAA3E' where v=x'6CA1D43E9DF91B3FE580DA3E1C247D3F147CF33E';
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
select id,vec_distance(v, x'B047263C9F87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
# test delete all and reinsert
delete from t1;
......@@ -61,7 +61,7 @@ insert t1 (v) values (x'e360d63ebe554f3fcdbc523f4522193f5236083d'),
(x'56926c3fdf098d3e2c8c5e3d1ad4953daa9d0b3e'),
(x'7b713f3e5258323f80d1113d673b2b3f66e3583f'),
(x'6ca1d43e9df91b3fe580da3e1c247d3f147cf33e');
select id,vec_distance(v, x'b047263c9f87233fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
select id,vec_distance(v, x'b047263c9f87233Fcfd27e3eae493e3f0329f43e') d from t1 order by d limit 5;
--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
insert t1 (v) values ('');
......
......@@ -21,10 +21,13 @@ insert t1 (v) values
start transaction;
insert t1 values
(30, x'f8e2413ed4ff773fef8b893eba487b3febee3f3f9e6f693f5961fd3ee479303d');
delete from t1 where id=1;
update t1 set v=x'a17e353e91676a3f8005c53e319b2d3f1410133fc018153e8dca3e3f3144ac3e' where id=2;
savepoint foo;
insert t1 values
(31, x'6129683f90fe1f3e1437bc3ed8c8f63dd141033f21e3a93e54346c3f8c4e043f'),
(32, x'1ec8b83d398c4d3f2efb463f23947a3fa1a5093fdde6303e5580413f51569b3e');
delete from t1 where id=5;
rollback to savepoint foo;
insert t1 values
(33, x'86d1003d4262033f8086713ffc4a633e317e933c4dce013d9c4d573fca83b93e');
......@@ -33,19 +36,20 @@ start transaction;
insert t1 values
(40, x'71046a3e85329b3e05240e3f45c9283f1847363f98d47d3f4224b73d487b613f'),
(41, x'71046a3e85329b3e05240e3f45c9283f1847363f98d47d3f4224b73d487b613f');
delete from t1 where id=7;
rollback;
select id,vec_distance(v, x'c923e33dc0da313fe7c7983e526b3d3fde63963e6eaf3a3f27fa133fe27a583f') d from t1 order by d limit 5;
id d
2 0.8781474260354732
10 0.8856208347761952
1 0.9381363209273885
30 1.0162643974895857
7 1.026397313888122
5 1.0308161006949719
select id,vec_distance(v, x'754b5f3ea2312b3fc169f43e4604883e1d20173e8dd7443f421b703fb11e0d3e') d from t1 order by d limit 5;
id d
2 0.9426904171992334
33 0.9477554826856
30 1.111405427702547
1 1.1154613877616022
10 1.118630286292343
8 1.1405733350751739
create table t2 (id int auto_increment primary key, v blob not null, vector index (v)) engine=innodb;
......@@ -73,7 +77,7 @@ id d
5 0.9706304662574956
30 0.98144492002831
50 1.079862635421575
51 1.2403734530917931
2 1.0907138991979892
select id,vec_distance(v, x'f618663f256be73e62cd453f8bcdbf3e16ae503c3858313f') d from t2 order by d limit 5;
id d
21 0.43559180321379337
......
......@@ -19,10 +19,13 @@ insert t1 (v) values
start transaction;
insert t1 values
(30, x'f8e2413ed4ff773fef8b893eba487b3febee3f3f9e6f693f5961fd3ee479303d');
delete from t1 where id=1;
update t1 set v=x'a17e353e91676a3f8005c53e319b2d3f1410133fc018153e8dca3e3f3144ac3e' where id=2;
savepoint foo;
insert t1 values
(31, x'6129683f90fe1f3e1437bc3ed8c8f63dd141033f21e3a93e54346c3f8c4e043f'),
(32, x'1ec8b83d398c4d3f2efb463f23947a3fa1a5093fdde6303e5580413f51569b3e');
delete from t1 where id=5;
rollback to savepoint foo;
insert t1 values
(33, x'86d1003d4262033f8086713ffc4a633e317e933c4dce013d9c4d573fca83b93e');
......@@ -31,6 +34,7 @@ start transaction;
insert t1 values
(40, x'71046a3e85329b3e05240e3f45c9283f1847363f98d47d3f4224b73d487b613f'),
(41, x'71046a3e85329b3e05240e3f45c9283f1847363f98d47d3f4224b73d487b613f');
delete from t1 where id=7;
rollback;
select id,vec_distance(v, x'c923e33dc0da313fe7c7983e526b3d3fde63963e6eaf3a3f27fa133fe27a583f') d from t1 order by d limit 5;
......
......@@ -5475,12 +5475,11 @@ handler::ha_delete_all_rows()
m_lock_type == F_WRLCK);
mark_trx_read_write();
int err= 0;
if ((err= table->open_hlindexes_for_write()) ||
(err= table->hlindexes_on_delete_all()))
return err;
int err= delete_all_rows();
if (!err)
err= table->hlindexes_on_delete_all();
return delete_all_rows();
return err;
}
......@@ -8186,9 +8185,6 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
DBUG_ASSERT(new_data == table->record[0]);
DBUG_ASSERT(old_data == table->record[1]);
if (table->open_hlindexes_for_write())
return 1;
uint saved_status= table->status;
error= ha_check_overlaps(old_data, new_data);
......@@ -8280,13 +8276,10 @@ int handler::ha_delete_row(const uchar *buf)
mark_trx_read_write();
increment_statistics(&SSV::ha_delete_count);
if (table->open_hlindexes_for_write())
return 1;
TABLE_IO_WAIT(tracker, PSI_TABLE_DELETE_ROW, active_index, error,
{ error= delete_row(buf);})
MYSQL_DELETE_ROW_DONE(error);
if (likely(!error) && !(error= table->hlindexes_on_delete()))
if (likely(!error) && !(error= table->hlindexes_on_delete(buf)))
{
rows_stats.deleted++;
Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
......
......@@ -9880,12 +9880,13 @@ int TABLE::hlindex_open(uint nr)
else
mysql_mutex_unlock(&s->LOCK_share);
TABLE *table= (TABLE*)alloc_root(&mem_root, sizeof(*table));
if (!table ||
open_table_from_share(in_use, s->hlindex, &empty_clex_str, db_stat, EXTRA_RECORD,
in_use->open_options, table, 0))
if (!table || open_table_from_share(in_use, s->hlindex, &empty_clex_str,
db_stat, EXTRA_RECORD, in_use->open_options, table, 0))
return 1;
hlindex= table;
}
else if (hlindex->in_use == in_use)
return 0;
hlindex->in_use= in_use; // mark in use for this query
hlindex->use_all_columns();
return hlindex->file->ha_external_lock(in_use, F_WRLCK);
......@@ -9895,17 +9896,8 @@ int TABLE::open_hlindexes_for_write()
{
DBUG_ASSERT(s->total_keys - s->keys <= 1);
for (uint i= s->keys; i < s->total_keys; i++)
{
KEY *key= s->key_info + i;
for (uint j=0; j < key->usable_key_parts; j++)
// TODO WHY?
// if (bitmap_is_set(write_set, key->key_part[j].fieldnr - 1))
{
if (hlindex_open(i))
return 1;
break;
}
}
if (hlindex_open(i))
return 1;
return 0;
}
......@@ -9931,37 +9923,34 @@ int TABLE::hlindexes_on_insert()
int TABLE::hlindexes_on_update()
{
DBUG_ASSERT(s->total_keys - s->keys == (hlindex != NULL));
if (!hlindex || !hlindex->in_use)
return 0;
int err;
// mark deleted node invalid and insert node for new row
if ((err= mhnsw_invalidate(this, this->record[1], key_info + s->keys)) ||
(err= mhnsw_insert(this, key_info + s->keys)))
return err;
if (hlindex && hlindex->in_use)
{
int err;
// mark deleted node invalid and insert node for new row
if ((err= mhnsw_invalidate(this, record[1], key_info + s->keys)) ||
(err= mhnsw_insert(this, key_info + s->keys)))
return err;
}
return 0;
}
int TABLE::hlindexes_on_delete()
int TABLE::hlindexes_on_delete(const uchar *buf)
{
DBUG_ASSERT(s->total_keys - s->keys == (hlindex != NULL));
if (!hlindex || !hlindex->in_use)
return 0;
if (int err= mhnsw_invalidate(this, this->record[0], key_info + s->keys))
return err;
DBUG_ASSERT(buf == record[0] || buf == record[1]); // note: REPLACE
if (hlindex && hlindex->in_use)
if (int err= mhnsw_invalidate(this, buf, key_info + s->keys))
return err;
return 0;
}
int TABLE::hlindexes_on_delete_all()
{
DBUG_ASSERT(s->total_keys - s->keys == (hlindex != NULL));
if (!hlindex || !hlindex->in_use)
return 0;
this->hlindex->file->ha_delete_all_rows();
if (hlindex && hlindex->in_use)
if (int err= mhnsw_delete_all(this, key_info + s->keys))
return err;
return 0;
}
......
......@@ -1797,7 +1797,7 @@ struct TABLE
int open_hlindexes_for_write();
int hlindexes_on_insert();
int hlindexes_on_update();
int hlindexes_on_delete();
int hlindexes_on_delete(const uchar *buf);
int hlindexes_on_delete_all();
int reset_hlindexes();
......
......@@ -37,7 +37,7 @@ enum Graph_table_fields {
FIELD_LAYER, FIELD_TREF, FIELD_VEC, FIELD_NEIGHBORS
};
enum Graph_table_indices {
IDX_LAYER
IDX_TREF, IDX_LAYER
};
class MHNSW_Context;
......@@ -258,7 +258,7 @@ class MHNSW_Context : public Sql_alloc
static int acquire(MHNSW_Context **ctx, TABLE *table, bool for_update);
static MHNSW_Context *get_from_share(TABLE_SHARE *share, TABLE *table);
void reset_ctx(TABLE_SHARE *share)
virtual void reset(TABLE_SHARE *share)
{
mysql_mutex_lock(&share->LOCK_share);
if (static_cast<MHNSW_Context*>(share->hlindex->hlindex_data) == this)
......@@ -279,7 +279,7 @@ class MHNSW_Context : public Sql_alloc
if (can_commit)
mysql_rwlock_unlock(&commit_lock);
if (root_size(&root) > mhnsw_cache_size)
reset_ctx(share);
reset(share);
if (--refcnt == 0)
this->~MHNSW_Context(); // XXX reuse
}
......@@ -351,7 +351,7 @@ class MHNSW_Trx : public MHNSW_Context
MHNSW_Trx *next= nullptr;
MHNSW_Trx(TABLE *table) : MHNSW_Context(table), table_share(table->s) {}
void reset_trx()
void reset(TABLE_SHARE *) override
{
node_cache.clear();
free_root(&root, MYF(0));
......@@ -361,7 +361,7 @@ class MHNSW_Trx : public MHNSW_Context
void release(bool, TABLE_SHARE *) override
{
if (root_size(&root) > mhnsw_cache_size)
reset_trx();
reset(nullptr);
}
static MHNSW_Trx *get_from_thd(THD *thd, TABLE *table);
......@@ -395,7 +395,7 @@ int MHNSW_Trx::MHNSW_hton::do_savepoint_rollback(handlerton *, THD *thd, void *)
{
for (auto trx= static_cast<MHNSW_Trx*>(thd_get_ha_data(thd, &hton));
trx; trx= trx->next)
trx->reset_trx();
trx->reset(nullptr);
return 0;
}
......@@ -424,7 +424,7 @@ int MHNSW_Trx::MHNSW_hton::do_commit(handlerton *, THD *thd, bool)
{
mysql_rwlock_wrlock(&ctx->commit_lock);
if (trx->list_of_nodes_is_lost)
ctx->reset_ctx(trx->table_share);
ctx->reset(trx->table_share);
else
{
// consider copying nodes from trx to shared cache when it makes sense
......@@ -1127,56 +1127,66 @@ void mhnsw_free(TABLE_SHARE *share)
graph_share->hlindex_data= 0;
}
int mhnsw_invalidate(TABLE *table, uchar *rec, KEY *keyinfo)
int mhnsw_invalidate(TABLE *table, const uchar *rec, KEY *keyinfo)
{
TABLE *graph= table->hlindex;
Field *vec_field= keyinfo->key_part->field;
String buf, *res= vec_field->val_str(&buf);
handler *h= table->file;
int err= 0;
MHNSW_Context *ctx;
bool use_ctx= !MHNSW_Context::acquire(&ctx, table, true);
/* metadata are checked on open */
DBUG_ASSERT(graph);
DBUG_ASSERT(keyinfo->algorithm == HA_KEY_ALG_VECTOR);
DBUG_ASSERT(keyinfo->usable_key_parts == 1);
DBUG_ASSERT(vec_field->binary());
DBUG_ASSERT(vec_field->cmp_type() == STRING_RESULT);
DBUG_ASSERT(res); // ER_INDEX_CANNOT_HAVE_NULL
DBUG_ASSERT(h->ref_length <= graph->field[1]->field_length);
DBUG_ASSERT(h->ref_length <= graph->field[2]->field_length);
if (res->length() == 0 || res->length() % 4)
return 1;
// use index on tref
if ((err= graph->file->ha_index_init(1, 0)))
return err;
DBUG_ASSERT(h->ref_length <= graph->field[FIELD_TREF]->field_length);
// target record:
h->position(rec);
graph->field[FIELD_TREF]->set_notnull();
graph->field[FIELD_TREF]->store_binary(
reinterpret_cast<const char *>(h->ref), h->ref_length);
graph->field[FIELD_TREF]->store_binary(h->ref, h->ref_length);
uchar *key= (uchar*)alloca(graph->key_info[1].key_length);
key_copy(key, graph->record[0], graph->key_info + 1,
graph->key_info[1].key_length);
uchar *key= (uchar*)alloca(graph->key_info[IDX_TREF].key_length);
key_copy(key, graph->record[0], &graph->key_info[IDX_TREF],
graph->key_info[IDX_TREF].key_length);
err= graph->file->ha_index_read_map(graph->record[1], key,
HA_WHOLE_KEY,
HA_READ_KEY_EXACT);
if (int err= graph->file->ha_index_read_idx_map(graph->record[1], IDX_TREF,
key, HA_WHOLE_KEY, HA_READ_KEY_EXACT))
return err;
restore_record(graph, record[1]);
graph->field[FIELD_TREF]->set_null();
if (int err= graph->file->ha_update_row(graph->record[1], graph->record[0]))
return err;
// Deleted tref not found in index, should not happen
if (err == HA_ERR_KEY_NOT_FOUND)
if (use_ctx)
{
DBUG_ASSERT(0);
return err;
graph->file->position(graph->record[0]);
FVectorNode *node= ctx->get_node(graph->file->ref);
node->deleted= true;
ctx->release(table);
}
restore_record(graph, record[1]);
graph->field[FIELD_TREF]->set_null();
return 0;
}
int mhnsw_delete_all(TABLE *table, KEY *keyinfo)
{
TABLE *graph= table->hlindex;
/* metadata are checked on open */
DBUG_ASSERT(graph);
DBUG_ASSERT(keyinfo->algorithm == HA_KEY_ALG_VECTOR);
DBUG_ASSERT(keyinfo->usable_key_parts == 1);
graph->file->ha_update_row(graph->record[1], graph->record[0]);
if (int err= graph->file->ha_delete_all_rows())
return err;
MHNSW_Context *ctx;
if (!MHNSW_Context::acquire(&ctx, table, true))
{
ctx->reset(table->s);
ctx->release(table);
}
return 0;
}
......@@ -1188,8 +1198,8 @@ const LEX_CSTRING mhnsw_hlindex_table_def(THD *thd, uint ref_length)
" tref varbinary(%u), "
" vec blob not null, "
" neighbors blob not null, "
" key (layer), "
" key (ref)) ";
" unique (tref), "
" key (layer)) ";
size_t len= sizeof(templ) + 32;
char *s= thd->alloc(len);
len= my_snprintf(s, len, templ, ref_length);
......
......@@ -24,7 +24,8 @@
const LEX_CSTRING mhnsw_hlindex_table_def(THD *thd, uint ref_length);
int mhnsw_insert(TABLE *table, KEY *keyinfo);
int mhnsw_first(TABLE *table, KEY *keyinfo, Item *dist, ulonglong limit);
int mhnsw_invalidate(TABLE *table, uchar *rec, KEY *keyinfo);
int mhnsw_invalidate(TABLE *table, const uchar *rec, KEY *keyinfo);
int mhnsw_delete_all(TABLE *table, KEY *keyinfo);
int mhnsw_next(TABLE *table);
void mhnsw_free(TABLE_SHARE *share);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment