Skip to content

Commit 5d9b923

Browse files
committed
support UPDATE on auxiliary columns
1 parent a394c5f commit 5d9b923

File tree

4 files changed

+230
-4
lines changed

4 files changed

+230
-4
lines changed

TODO

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
# auxiliary columns
99

10-
- UPDATE support
1110
- later:
1211
- NOT NULL?
1312
- perf: INSERT stmt should be cached on vec0_vtab

sqlite-vec.c

+38-2
Original file line numberDiff line numberDiff line change
@@ -7059,6 +7059,28 @@ int vec0Update_Delete(sqlite3_vtab *pVTab, sqlite3_value *idValue) {
70597059
return SQLITE_OK;
70607060
}
70617061

7062+
int vec0Update_UpdateAuxColumn(vec0_vtab *p, int auxiliary_column_idx, sqlite3_value * value, i64 rowid) {
7063+
int rc;
7064+
sqlite3_stmt *stmt;
7065+
const char * zSql = sqlite3_mprintf("UPDATE " VEC0_SHADOW_AUXILIARY_NAME " SET value%02d = ? WHERE rowid = ?", p->schemaName, p->tableName, auxiliary_column_idx);
7066+
if(!zSql) {
7067+
return SQLITE_NOMEM;
7068+
}
7069+
rc = sqlite3_prepare_v2(p->db, zSql, -1, &stmt, NULL);
7070+
if(rc != SQLITE_OK) {
7071+
return rc;
7072+
}
7073+
sqlite3_bind_value(stmt, 1, value);
7074+
sqlite3_bind_int64(stmt, 2, rowid);
7075+
rc = sqlite3_step(stmt);
7076+
if(rc != SQLITE_DONE) {
7077+
sqlite3_finalize(stmt);
7078+
return SQLITE_ERROR;
7079+
}
7080+
sqlite3_finalize(stmt);
7081+
return SQLITE_OK;
7082+
}
7083+
70627084
int vec0Update_UpdateVectorColumn(vec0_vtab *p, i64 chunk_id, i64 chunk_offset,
70637085
int i, sqlite3_value *valueVector) {
70647086
int rc;
@@ -7183,9 +7205,23 @@ int vec0Update_Update(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv) {
71837205
return SQLITE_ERROR;
71847206
}
71857207

7186-
// TODO handle auxiliary column updates
7208+
// 3) handle auxiliary column updates
7209+
for (int i = 0; i < vec0_num_defined_user_columns(p); i++) {
7210+
if(p->user_column_kinds[i] != SQLITE_VEC0_USER_COLUMN_KIND_AUXILIARY) {
7211+
continue;
7212+
}
7213+
int auxiliary_column_idx = p->user_column_idxs[i];
7214+
sqlite3_value * value = argv[2+VEC0_COLUMN_USERN_START + i];
7215+
if(sqlite3_value_nochange(value)) {
7216+
continue;
7217+
}
7218+
rc = vec0Update_UpdateAuxColumn(p, auxiliary_column_idx, value, rowid);
7219+
if(rc != SQLITE_OK) {
7220+
return SQLITE_ERROR;
7221+
}
7222+
}
71877223

7188-
// 3) iterate over all new vectors, update the vectors
7224+
// 4) iterate over all new vectors, update the vectors
71897225
for (int i = 0; i < vec0_num_defined_user_columns(p); i++) {
71907226
if(p->user_column_kinds[i] != SQLITE_VEC0_USER_COLUMN_KIND_VECTOR) {
71917227
continue;

tests/__snapshots__/test-auxiliary.ambr

+179
Original file line numberDiff line numberDiff line change
@@ -461,3 +461,182 @@
461461
]),
462462
})
463463
# ---
464+
# name: test_updates
465+
OrderedDict({
466+
'sql': 'select rowid, * from v',
467+
'rows': list([
468+
OrderedDict({
469+
'rowid': 1,
470+
'vector': b'\x00\x00\x80?',
471+
'name': 'alex',
472+
}),
473+
OrderedDict({
474+
'rowid': 2,
475+
'vector': b'\x00\x00\x00@',
476+
'name': 'brian',
477+
}),
478+
OrderedDict({
479+
'rowid': 3,
480+
'vector': b'\x00\x00@@',
481+
'name': 'craig',
482+
}),
483+
]),
484+
})
485+
# ---
486+
# name: test_updates.1
487+
dict({
488+
'v_auxiliary': OrderedDict({
489+
'sql': 'select * from v_auxiliary',
490+
'rows': list([
491+
OrderedDict({
492+
'rowid': 1,
493+
'value00': 'alex',
494+
}),
495+
OrderedDict({
496+
'rowid': 2,
497+
'value00': 'brian',
498+
}),
499+
OrderedDict({
500+
'rowid': 3,
501+
'value00': 'craig',
502+
}),
503+
]),
504+
}),
505+
'v_chunks': OrderedDict({
506+
'sql': 'select * from v_chunks',
507+
'rows': list([
508+
OrderedDict({
509+
'chunk_id': 1,
510+
'size': 8,
511+
'validity': b'\x07',
512+
'rowids': b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
513+
}),
514+
]),
515+
}),
516+
'v_rowids': OrderedDict({
517+
'sql': 'select * from v_rowids',
518+
'rows': list([
519+
OrderedDict({
520+
'rowid': 1,
521+
'id': None,
522+
'chunk_id': 1,
523+
'chunk_offset': 0,
524+
}),
525+
OrderedDict({
526+
'rowid': 2,
527+
'id': None,
528+
'chunk_id': 1,
529+
'chunk_offset': 1,
530+
}),
531+
OrderedDict({
532+
'rowid': 3,
533+
'id': None,
534+
'chunk_id': 1,
535+
'chunk_offset': 2,
536+
}),
537+
]),
538+
}),
539+
'v_vector_chunks00': OrderedDict({
540+
'sql': 'select * from v_vector_chunks00',
541+
'rows': list([
542+
OrderedDict({
543+
'rowid': 1,
544+
'vectors': b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
545+
}),
546+
]),
547+
}),
548+
})
549+
# ---
550+
# name: test_updates.2
551+
OrderedDict({
552+
'sql': "update v set name = 'ALEX' where rowid = 1",
553+
'rows': list([
554+
]),
555+
})
556+
# ---
557+
# name: test_updates.3
558+
OrderedDict({
559+
'sql': 'select rowid, * from v',
560+
'rows': list([
561+
OrderedDict({
562+
'rowid': 1,
563+
'vector': b'\x00\x00\x80?',
564+
'name': 'ALEX',
565+
}),
566+
OrderedDict({
567+
'rowid': 2,
568+
'vector': b'\x00\x00\x00@',
569+
'name': 'brian',
570+
}),
571+
OrderedDict({
572+
'rowid': 3,
573+
'vector': b'\x00\x00@@',
574+
'name': 'craig',
575+
}),
576+
]),
577+
})
578+
# ---
579+
# name: test_updates.4
580+
dict({
581+
'v_auxiliary': OrderedDict({
582+
'sql': 'select * from v_auxiliary',
583+
'rows': list([
584+
OrderedDict({
585+
'rowid': 1,
586+
'value00': 'ALEX',
587+
}),
588+
OrderedDict({
589+
'rowid': 2,
590+
'value00': 'brian',
591+
}),
592+
OrderedDict({
593+
'rowid': 3,
594+
'value00': 'craig',
595+
}),
596+
]),
597+
}),
598+
'v_chunks': OrderedDict({
599+
'sql': 'select * from v_chunks',
600+
'rows': list([
601+
OrderedDict({
602+
'chunk_id': 1,
603+
'size': 8,
604+
'validity': b'\x07',
605+
'rowids': b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
606+
}),
607+
]),
608+
}),
609+
'v_rowids': OrderedDict({
610+
'sql': 'select * from v_rowids',
611+
'rows': list([
612+
OrderedDict({
613+
'rowid': 1,
614+
'id': None,
615+
'chunk_id': 1,
616+
'chunk_offset': 0,
617+
}),
618+
OrderedDict({
619+
'rowid': 2,
620+
'id': None,
621+
'chunk_id': 1,
622+
'chunk_offset': 1,
623+
}),
624+
OrderedDict({
625+
'rowid': 3,
626+
'id': None,
627+
'chunk_id': 1,
628+
'chunk_offset': 2,
629+
}),
630+
]),
631+
}),
632+
'v_vector_chunks00': OrderedDict({
633+
'sql': 'select * from v_vector_chunks00',
634+
'rows': list([
635+
OrderedDict({
636+
'rowid': 1,
637+
'vectors': b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
638+
}),
639+
]),
640+
}),
641+
})
642+
# ---

tests/test-auxiliary.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,19 @@ def test_types(db, snapshot):
7373

7474

7575
def test_updates(db, snapshot):
76-
pass
76+
db.execute(
77+
"create virtual table v using vec0(vector float[1], +name text, chunk_size=8)"
78+
)
79+
db.executemany(
80+
"insert into v(vector, name) values (?, ?)",
81+
[("[1]", "alex"), ("[2]", "brian"), ("[3]", "craig")],
82+
)
83+
assert exec(db, "select rowid, * from v") == snapshot()
84+
assert vec0_shadow_table_contents(db, "v") == snapshot()
85+
86+
assert exec(db, "update v set name = 'ALEX' where rowid = 1") == snapshot()
87+
assert exec(db, "select rowid, * from v") == snapshot()
88+
assert vec0_shadow_table_contents(db, "v") == snapshot()
7789

7890

7991
def test_deletes(db, snapshot):

0 commit comments

Comments
 (0)