Skip to content

Commit

Permalink
fix aux column error when using non-default rowid values, needs test
Browse files Browse the repository at this point in the history
  • Loading branch information
asg017 committed Nov 17, 2024
1 parent da29ace commit 1a216a6
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 62 deletions.
1 change: 1 addition & 0 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- skip invalid validity entries in knn filter?
- null!
- date/datetime
- [ ] test accessing aux values when rowid is different than 1,2,3 etc.
- later
- `v in (...)` handling
- remaining TODO items
Expand Down
117 changes: 56 additions & 61 deletions sqlite-vec.c
Original file line number Diff line number Diff line change
Expand Up @@ -7680,67 +7680,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) {
Expand Down Expand Up @@ -7832,6 +7771,62 @@ int vec0Update_Insert(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv,
goto cleanup;
}

if(p->numAuxiliaryColumns > 0) {
sqlite3_stmt *stmt;
sqlite3_str * s = sqlite3_str_new(NULL);
sqlite3_str_appendf(s, "INSERT INTO " VEC0_SHADOW_AUXILIARY_NAME "(rowid ", p->schemaName, p->tableName);
for(int i = 0; i < p->numAuxiliaryColumns; i++) {
sqlite3_str_appendf(s, ", value%02d", i);
}
sqlite3_str_appendall(s, ") VALUES (? ");
for(int i = 0; i < p->numAuxiliaryColumns; i++) {
sqlite3_str_appendall(s, ", ?");
}
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;
}
sqlite3_bind_int64(stmt, 1, rowid);

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 + 1 + auxiliary_key_idx, v);
}

rc = sqlite3_step(stmt);
if(rc != SQLITE_DONE) {
sqlite3_finalize(stmt);
rc = SQLITE_ERROR;
goto cleanup;
}
sqlite3_finalize(stmt);
}


for(int i = 0; i < vec0_num_defined_user_columns(p); i++) {
if(p->user_column_kinds[i] != SQLITE_VEC0_USER_COLUMN_KIND_METADATA) {
Expand Down
28 changes: 27 additions & 1 deletion test.sql
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@

.load dist/vec0
.echo on
.bail on

.mode qbox

create virtual table v using vec0(
vector float[1],
+description text
);
insert into v(rowid, vector, description) values (1, '[1]', 'aaa');
select * from v;

.exit

create virtual table vec_articles using vec0(
article_id integer primary key,
year integer partition key,
headline_embedding float[1],
+headline text,
+url text,
word_count integer,
print_section text,
print_page integer,
pub_date text,
);

insert into vec_articles values (1111, 2020, '[1]', 'headline', 'https://...', 200, 'A', 1, '2020-01-01');

select * from vec_articles;

.exit


create table movies(movie_id integer primary key, synopsis text);
INSERT INTO movies(movie_id, synopsis)
Expand Down

0 comments on commit 1a216a6

Please sign in to comment.