From a8d0a28784782444fa00630035dce69fc574a223 Mon Sep 17 00:00:00 2001 From: Alex Garcia Date: Wed, 20 Nov 2024 00:56:56 -0800 Subject: [PATCH] fix aux tests --- sqlite-vec.c | 61 --- tests/__snapshots__/test-auxiliary.ambr | 579 ++++++++++++++++++++++++ 2 files changed, 579 insertions(+), 61 deletions(-) diff --git a/sqlite-vec.c b/sqlite-vec.c index c4f375c..d8490cd 100644 --- a/sqlite-vec.c +++ b/sqlite-vec.c @@ -8162,67 +8162,6 @@ int vec0Update_Insert(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, } } - if(p->numAuxiliaryColumns > 0) { - sqlite3_stmt *stmt; - sqlite3_str * s = sqlite3_str_new(NULL); - sqlite3_str_appendf(s, "INSERT INTO " VEC0_SHADOW_AUXILIARY_NAME "(", p->schemaName, p->tableName); - for(int i = 0; i < p->numAuxiliaryColumns; i++) { - if(i!=0) { - sqlite3_str_appendchar(s, 1, ','); - } - sqlite3_str_appendf(s, "value%02d", i); - } - sqlite3_str_appendall(s, ") VALUES ("); - for(int i = 0; i < p->numAuxiliaryColumns; i++) { - if(i!=0) { - sqlite3_str_appendchar(s, 1, ','); - } - sqlite3_str_appendchar(s, 1, '?'); - } - sqlite3_str_appendall(s, ")"); - char * zSql = sqlite3_str_finish(s); - // TODO double check error handling ehre - if(!zSql) { - rc = SQLITE_NOMEM; - goto cleanup; - } - rc = sqlite3_prepare_v2(p->db, zSql, -1, &stmt, NULL); - if(rc != SQLITE_OK) { - goto cleanup; - } - - for (int i = 0; i < vec0_num_defined_user_columns(p); i++) { - if(p->user_column_kinds[i] != SQLITE_VEC0_USER_COLUMN_KIND_AUXILIARY) { - continue; - } - int auxiliary_key_idx = p->user_column_idxs[i]; - sqlite3_value * v = argv[2+VEC0_COLUMN_USERN_START + i]; - int v_type = sqlite3_value_type(v); - if(v_type != SQLITE_NULL && (v_type != p->auxiliary_columns[auxiliary_key_idx].type)) { - sqlite3_finalize(stmt); - rc = SQLITE_ERROR; - vtab_set_error( - pVTab, - "Auxiliary column type mismatch: The auxiliary column %.*s has type %s, but %s was provided.", - p->auxiliary_columns[auxiliary_key_idx].name_length, - p->auxiliary_columns[auxiliary_key_idx].name, - type_name(p->auxiliary_columns[auxiliary_key_idx].type), - type_name(v_type) - ); - goto cleanup; - } - sqlite3_bind_value(stmt, 1 + auxiliary_key_idx, v); - } - - rc = sqlite3_step(stmt); - if(rc != SQLITE_DONE) { - sqlite3_finalize(stmt); - rc = SQLITE_ERROR; - goto cleanup; - } - sqlite3_finalize(stmt); - } - // read all the inserted vectors into vectorDatas, validate their lengths. for (int i = 0; i < vec0_num_defined_user_columns(p); i++) { if(p->user_column_kinds[i] != SQLITE_VEC0_USER_COLUMN_KIND_VECTOR) { diff --git a/tests/__snapshots__/test-auxiliary.ambr b/tests/__snapshots__/test-auxiliary.ambr index 3b97d2a..bfe3d2c 100644 --- a/tests/__snapshots__/test-auxiliary.ambr +++ b/tests/__snapshots__/test-auxiliary.ambr @@ -5,6 +5,323 @@ 'message': 'vec0 constructor error: More than 16 auxiliary columns were provided', }) # --- +# name: test_deletes + OrderedDict({ + 'sql': 'select rowid, * from v', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'vector': b'\x00\x00\x80?', + 'name': 'alex', + }), + OrderedDict({ + 'rowid': 2, + 'vector': b'\x00\x00\x00@', + 'name': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'vector': b'\x00\x00@@', + 'name': 'craig', + }), + ]), + }) +# --- +# name: test_deletes.1 + dict({ + 'v_auxiliary': OrderedDict({ + 'sql': 'select * from v_auxiliary', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'value00': 'alex', + }), + OrderedDict({ + 'rowid': 2, + 'value00': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'value00': 'craig', + }), + ]), + }), + 'v_chunks': OrderedDict({ + 'sql': 'select * from v_chunks', + 'rows': list([ + OrderedDict({ + 'chunk_id': 1, + 'size': 8, + 'validity': b'\x07', + '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', + }), + ]), + }), + 'v_rowids': OrderedDict({ + 'sql': 'select * from v_rowids', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 0, + }), + OrderedDict({ + 'rowid': 2, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 1, + }), + OrderedDict({ + 'rowid': 3, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 2, + }), + ]), + }), + 'v_vector_chunks00': OrderedDict({ + 'sql': 'select * from v_vector_chunks00', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + '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', + }), + ]), + }), + }) +# --- +# name: test_deletes.2 + OrderedDict({ + 'sql': 'delete from v where rowid = 1', + 'rows': list([ + ]), + }) +# --- +# name: test_deletes.3 + OrderedDict({ + 'sql': 'select rowid, * from v', + 'rows': list([ + OrderedDict({ + 'rowid': 2, + 'vector': b'\x00\x00\x00@', + 'name': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'vector': b'\x00\x00@@', + 'name': 'craig', + }), + ]), + }) +# --- +# name: test_deletes.4 + dict({ + 'v_auxiliary': OrderedDict({ + 'sql': 'select * from v_auxiliary', + 'rows': list([ + OrderedDict({ + 'rowid': 2, + 'value00': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'value00': 'craig', + }), + ]), + }), + 'v_chunks': OrderedDict({ + 'sql': 'select * from v_chunks', + 'rows': list([ + OrderedDict({ + 'chunk_id': 1, + 'size': 8, + 'validity': b'\x06', + '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', + }), + ]), + }), + 'v_rowids': OrderedDict({ + 'sql': 'select * from v_rowids', + 'rows': list([ + OrderedDict({ + 'rowid': 2, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 1, + }), + OrderedDict({ + 'rowid': 3, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 2, + }), + ]), + }), + 'v_vector_chunks00': OrderedDict({ + 'sql': 'select * from v_vector_chunks00', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + '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', + }), + ]), + }), + }) +# --- +# name: test_knn + OrderedDict({ + 'sql': 'select * from v', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'vector': b'\x00\x00\x80?', + 'name': 'alex', + }), + OrderedDict({ + 'rowid': 2, + 'vector': b'\x00\x00\x00@', + 'name': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'vector': b'\x00\x00@@', + 'name': 'craig', + }), + ]), + }) +# --- +# name: test_knn[illegal KNN w/ aux] + dict({ + 'error': 'OperationalError', + 'message': 'An illegal WHERE constraint was provided on a vec0 auxiliary column in a KNN query.', + }) +# --- +# name: test_knn[legal KNN w/ aux] + OrderedDict({ + 'sql': "select *, distance from v where vector match '[5]' and k = 10", + 'rows': list([ + OrderedDict({ + 'rowid': 3, + 'vector': b'\x00\x00@@', + 'name': 'craig', + 'distance': 2.0, + }), + OrderedDict({ + 'rowid': 2, + 'vector': b'\x00\x00\x00@', + 'name': 'brian', + 'distance': 3.0, + }), + OrderedDict({ + 'rowid': 1, + 'vector': b'\x00\x00\x80?', + 'name': 'alex', + 'distance': 4.0, + }), + ]), + }) +# --- +# name: test_normal.1 + OrderedDict({ + 'sql': 'select * from v', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'a': b'\x11\x11\x11\x11', + 'name': 'alex', + }), + OrderedDict({ + 'rowid': 2, + 'a': b'""""', + 'name': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'a': b'3333', + 'name': 'craig', + }), + ]), + }) +# --- +# name: test_normal.2 + dict({ + 'v_auxiliary': OrderedDict({ + 'sql': 'select * from v_auxiliary', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'value00': 'alex', + }), + OrderedDict({ + 'rowid': 2, + 'value00': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'value00': 'craig', + }), + ]), + }), + 'v_chunks': OrderedDict({ + 'sql': 'select * from v_chunks', + 'rows': list([ + OrderedDict({ + 'chunk_id': 1, + 'size': 8, + 'validity': b'\x07', + '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', + }), + ]), + }), + 'v_rowids': OrderedDict({ + 'sql': 'select * from v_rowids', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 0, + }), + OrderedDict({ + 'rowid': 2, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 1, + }), + OrderedDict({ + 'rowid': 3, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 2, + }), + ]), + }), + 'v_vector_chunks00': OrderedDict({ + 'sql': 'select * from v_vector_chunks00', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'vectors': b'\x11\x11\x11\x11""""3333\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + }), + ]), + }), + }) +# --- +# name: test_normal[sqlite_master post drop] + OrderedDict({ + 'sql': 'select * from sqlite_master order by name', + 'rows': list([ + OrderedDict({ + 'type': 'table', + 'name': 'sqlite_sequence', + 'tbl_name': 'sqlite_sequence', + 'rootpage': 5, + 'sql': 'CREATE TABLE sqlite_sequence(name,seq)', + }), + ]), + }) +# --- # name: test_normal[sqlite_master] OrderedDict({ 'sql': 'select * from sqlite_master order by name', @@ -75,3 +392,265 @@ ]), }) # --- +# name: test_types + OrderedDict({ + 'sql': 'select * from v', + 'rows': list([ + ]), + }) +# --- +# name: test_types.1 + OrderedDict({ + 'sql': 'insert into v(vector, aux_int, aux_float, aux_text, aux_blob) values (?, ?, ?, ?, ?)', + 'rows': list([ + ]), + }) +# --- +# name: test_types.2 + OrderedDict({ + 'sql': 'select * from v', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'vector': b'\x11\x11\x11\x11', + 'aux_int': 1, + 'aux_float': 1.22, + 'aux_text': 'text', + 'aux_blob': b'blob', + }), + ]), + }) +# --- +# name: test_types.3 + dict({ + 'error': 'IntegrityError', + 'message': 'Auxiliary column type mismatch: The auxiliary column aux_int has type INTEGER, but TEXT was provided.', + }) +# --- +# name: test_types.4 + dict({ + 'error': 'IntegrityError', + 'message': 'Auxiliary column type mismatch: The auxiliary column aux_float has type FLOAT, but TEXT was provided.', + }) +# --- +# name: test_types.5 + dict({ + 'error': 'IntegrityError', + 'message': 'Auxiliary column type mismatch: The auxiliary column aux_text has type TEXT, but INTEGER was provided.', + }) +# --- +# name: test_types.6 + dict({ + 'error': 'IntegrityError', + 'message': 'Auxiliary column type mismatch: The auxiliary column aux_blob has type BLOB, but INTEGER was provided.', + }) +# --- +# name: test_types.7 + OrderedDict({ + 'sql': 'insert into v(vector, aux_int, aux_float, aux_text, aux_blob) values (?, ?, ?, ?, ?)', + 'rows': list([ + ]), + }) +# --- +# name: test_types.8 + OrderedDict({ + 'sql': 'select * from v', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'vector': b'\x11\x11\x11\x11', + 'aux_int': 1, + 'aux_float': 1.22, + 'aux_text': 'text', + 'aux_blob': b'blob', + }), + OrderedDict({ + 'rowid': 2, + 'vector': b'\x11\x11\x11\x11', + 'aux_int': None, + 'aux_float': None, + 'aux_text': None, + 'aux_blob': None, + }), + ]), + }) +# --- +# name: test_updates + OrderedDict({ + 'sql': 'select rowid, * from v', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'vector': b'\x00\x00\x80?', + 'name': 'alex', + }), + OrderedDict({ + 'rowid': 2, + 'vector': b'\x00\x00\x00@', + 'name': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'vector': b'\x00\x00@@', + 'name': 'craig', + }), + ]), + }) +# --- +# name: test_updates.1 + dict({ + 'v_auxiliary': OrderedDict({ + 'sql': 'select * from v_auxiliary', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'value00': 'alex', + }), + OrderedDict({ + 'rowid': 2, + 'value00': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'value00': 'craig', + }), + ]), + }), + 'v_chunks': OrderedDict({ + 'sql': 'select * from v_chunks', + 'rows': list([ + OrderedDict({ + 'chunk_id': 1, + 'size': 8, + 'validity': b'\x07', + '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', + }), + ]), + }), + 'v_rowids': OrderedDict({ + 'sql': 'select * from v_rowids', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 0, + }), + OrderedDict({ + 'rowid': 2, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 1, + }), + OrderedDict({ + 'rowid': 3, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 2, + }), + ]), + }), + 'v_vector_chunks00': OrderedDict({ + 'sql': 'select * from v_vector_chunks00', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + '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', + }), + ]), + }), + }) +# --- +# name: test_updates.2 + OrderedDict({ + 'sql': "update v set name = 'ALEX' where rowid = 1", + 'rows': list([ + ]), + }) +# --- +# name: test_updates.3 + OrderedDict({ + 'sql': 'select rowid, * from v', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'vector': b'\x00\x00\x80?', + 'name': 'ALEX', + }), + OrderedDict({ + 'rowid': 2, + 'vector': b'\x00\x00\x00@', + 'name': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'vector': b'\x00\x00@@', + 'name': 'craig', + }), + ]), + }) +# --- +# name: test_updates.4 + dict({ + 'v_auxiliary': OrderedDict({ + 'sql': 'select * from v_auxiliary', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'value00': 'ALEX', + }), + OrderedDict({ + 'rowid': 2, + 'value00': 'brian', + }), + OrderedDict({ + 'rowid': 3, + 'value00': 'craig', + }), + ]), + }), + 'v_chunks': OrderedDict({ + 'sql': 'select * from v_chunks', + 'rows': list([ + OrderedDict({ + 'chunk_id': 1, + 'size': 8, + 'validity': b'\x07', + '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', + }), + ]), + }), + 'v_rowids': OrderedDict({ + 'sql': 'select * from v_rowids', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 0, + }), + OrderedDict({ + 'rowid': 2, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 1, + }), + OrderedDict({ + 'rowid': 3, + 'id': None, + 'chunk_id': 1, + 'chunk_offset': 2, + }), + ]), + }), + 'v_vector_chunks00': OrderedDict({ + 'sql': 'select * from v_vector_chunks00', + 'rows': list([ + OrderedDict({ + 'rowid': 1, + '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', + }), + ]), + }), + }) +# ---