mirror of
https://github.com/tursodatabase/libsql.git
synced 2024-11-23 12:06:16 +00:00
534 lines
25 KiB
Plaintext
534 lines
25 KiB
Plaintext
# 2024-06-12
|
|
#
|
|
# Copyright 2024 the libSQL authors
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
# this software and associated documentation files (the "Software"), to deal in
|
|
# the Software without restriction, including without limitation the rights to
|
|
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
# the Software, and to permit persons to whom the Software is furnished to do so,
|
|
# subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in all
|
|
# copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
#
|
|
#***********************************************************************
|
|
# This file implements regression tests for libSQL library. The
|
|
# focus of this file is vector search.
|
|
|
|
|
|
set testdir [file dirname $argv0]
|
|
source $testdir/tester.tcl
|
|
set testprefix vector
|
|
|
|
sqlite3_db_config_lookaside db 0 0 0
|
|
|
|
do_execsql_test vector-pragmas {
|
|
CREATE TABLE t_pragmas( v FLOAT32(3) );
|
|
CREATE INDEX t_pragmas_idx ON t_pragmas( libsql_vector_idx(v) );
|
|
INSERT INTO t_pragmas VALUES (vector('[1,2,3]'));
|
|
PRAGMA integrity_check;
|
|
PRAGMA index_list='t_pragmas';
|
|
} {
|
|
{ok}
|
|
0 t_pragmas_idx 0 c 0
|
|
}
|
|
|
|
do_execsql_test vector-typename {
|
|
CREATE TABLE t_type_spaces( v FLOAT32 ( 3 ) );
|
|
CREATE INDEX t_type_spaces_idx ON t_type_spaces( libsql_vector_idx(v) );
|
|
INSERT INTO t_type_spaces VALUES (vector('[1,2,3]'));
|
|
} {}
|
|
|
|
do_execsql_test vector-backfill {
|
|
CREATE TABLE t_backfill( v FLOAT32(3) );
|
|
INSERT INTO t_backfill VALUES (vector('[1,2,3]'));
|
|
INSERT INTO t_backfill VALUES (vector('[2,3,4]'));
|
|
INSERT INTO t_backfill VALUES (vector('[3,4,5]'));
|
|
INSERT INTO t_backfill VALUES (vector('[4,5,6]'));
|
|
CREATE INDEX t_backfill_idx ON t_backfill( libsql_vector_idx(v) );
|
|
SELECT rowid FROM vector_top_k('t_backfill_idx', vector('[3,4,5]'), 4);
|
|
} {3 4 2 1}
|
|
|
|
do_execsql_test vector-reindex {
|
|
CREATE TABLE t_reindex( v FLOAT32(3) );
|
|
CREATE INDEX t_reindex_idx ON t_reindex( libsql_vector_idx(v) );
|
|
INSERT INTO t_reindex VALUES (vector('[1,2,3]'));
|
|
INSERT INTO t_reindex VALUES (vector('[2,3,4]'));
|
|
INSERT INTO t_reindex VALUES (vector('[3,4,5]'));
|
|
INSERT INTO t_reindex VALUES (vector('[4,5,6]'));
|
|
REINDEX t_reindex_idx;
|
|
SELECT rowid FROM vector_top_k('t_reindex_idx', vector('[3,4,5]'), 4);
|
|
} {3 4 2 1}
|
|
|
|
do_execsql_test vector-text-pk {
|
|
CREATE TABLE t_text_pk( email TEXT PRIMARY KEY, v FLOAT32(3) );
|
|
CREATE INDEX t_text_pk_idx ON t_text_pk( libsql_vector_idx(v) );
|
|
INSERT INTO t_text_pk VALUES ('e-1', vector('[1,2,3]'));
|
|
INSERT INTO t_text_pk VALUES ('e-2', vector('[2,3,4]'));
|
|
INSERT INTO t_text_pk VALUES ('e-3', vector('[3,4,5]'));
|
|
INSERT INTO t_text_pk VALUES ('e-4', vector('[4,5,6]'));
|
|
SELECT id FROM vector_top_k('t_text_pk_idx', vector('[3,4,5]'), 4);
|
|
} {3 4 2 1}
|
|
|
|
do_execsql_test vector-text-pk-norow {
|
|
CREATE TABLE t_text_pk_norow( v1, v2, v3, email TEXT PRIMARY KEY, v FLOAT32(3) ) WITHOUT ROWID;
|
|
CREATE INDEX t_text_pk_norow_idx ON t_text_pk_norow( libsql_vector_idx(v) );
|
|
INSERT INTO t_text_pk_norow VALUES (1, 1, 1, 'e-1', vector('[1,2,3]'));
|
|
INSERT INTO t_text_pk_norow VALUES (1, 1, 1, 'e-2', vector('[2,3,4]'));
|
|
INSERT INTO t_text_pk_norow VALUES (1, 1, 1, 'e-3', vector('[3,4,5]'));
|
|
INSERT INTO t_text_pk_norow VALUES (1, 1, 1, 'e-4', vector('[4,5,6]'));
|
|
SELECT id FROM vector_top_k('t_text_pk_norow_idx', vector('[3,4,5]'), 4);
|
|
} {e-3 e-4 e-2 e-1}
|
|
|
|
do_execsql_test vector-delete {
|
|
CREATE TABLE t_delete( id INTEGER PRIMARY KEY, v FLOAT32(3) );
|
|
CREATE INDEX t_delete_idx ON t_delete( libsql_vector_idx(v) );
|
|
INSERT INTO t_delete VALUES (10, vector('[1,1,1]'));
|
|
INSERT INTO t_delete VALUES (20, vector('[-1,-1,-1]'));
|
|
SELECT rowid FROM vector_top_k('t_delete_idx', vector('[1,1,1]'), 1);
|
|
DELETE FROM t_delete WHERE id = 10;
|
|
SELECT rowid FROM vector_top_k('t_delete_idx', vector('[1,1,1]'), 1);
|
|
} {10 20}
|
|
|
|
do_execsql_test vector-update {
|
|
CREATE TABLE t_update( id INTEGER PRIMARY KEY, v FLOAT32(3) );
|
|
CREATE INDEX t_update_idx ON t_update( libsql_vector_idx(v) );
|
|
INSERT INTO t_update VALUES (10, vector('[1,1,1]'));
|
|
INSERT INTO t_update VALUES (20, vector('[-1,-1,-1]'));
|
|
UPDATE t_update SET v = vector('[-1,-1,-1]') WHERE id = 10;
|
|
UPDATE t_update SET v = vector('[1,1,1]') WHERE id = 20;
|
|
SELECT rowid FROM vector_top_k('t_update_idx', vector('[1,1,1]'), 2);
|
|
} {20 10}
|
|
|
|
do_execsql_test vector-simple {
|
|
CREATE TABLE t_simple( v FLOAT32(3));
|
|
CREATE INDEX t_simple_idx ON t_simple( libsql_vector_idx(v) );
|
|
INSERT INTO t_simple VALUES(vector('[1,2,3]'));
|
|
INSERT INTO t_simple VALUES(vector('[2,3,4]'));
|
|
INSERT INTO t_simple VALUES(vector('[5,6,7]'));
|
|
SELECT * FROM vector_top_k('t_simple_idx', '[1,2,3]', 1);
|
|
SELECT * FROM vector_top_k('t_simple_idx', '[5,6,7]', 1);
|
|
SELECT * FROM vector_top_k('t_simple_idx', vector('[1,2,3]'), 1);
|
|
SELECT * FROM vector_top_k('t_simple_idx', vector('[1,2,3]'), CAST(1 as REAL));
|
|
} {{1} {3} {1} {1}}
|
|
|
|
do_execsql_test vector-empty {
|
|
CREATE TABLE t_empty( v FLOAT32(3));
|
|
CREATE INDEX t_empty_idx ON t_empty( libsql_vector_idx(v) );
|
|
SELECT * FROM vector_top_k('t_empty_idx', '[1,2,3]', 1);
|
|
INSERT INTO t_empty VALUES(vector('[1,2,3]'));
|
|
DELETE FROM t_empty WHERE rowid = 1;
|
|
SELECT * FROM vector_top_k('t_empty_idx', '[5,6,7]', 1);
|
|
} {}
|
|
|
|
|
|
do_execsql_test vector-null {
|
|
CREATE TABLE t_null( v FLOAT32(2));
|
|
CREATE INDEX t_null_idx ON t_null( libsql_vector_idx(v) );
|
|
INSERT INTO t_null VALUES(vector('[1,-1]'));
|
|
INSERT INTO t_null VALUES(NULL);
|
|
INSERT INTO t_null VALUES(vector('[-2,1]'));
|
|
SELECT * FROM vector_top_k('t_null_idx', '[1,1]', 2);
|
|
UPDATE t_null SET v = vector('[1,1]') WHERE rowid = 2;
|
|
SELECT rowid FROM vector_top_k('t_null_idx', vector('[1,1]'), 3);
|
|
UPDATE t_null SET v = NULL WHERE rowid = 3;
|
|
SELECT rowid FROM vector_top_k('t_null_idx', vector('[1,1]'), 3);
|
|
UPDATE t_null SET v = NULL;
|
|
SELECT rowid FROM vector_top_k('t_null_idx', vector('[1,1]'), 3);
|
|
} {
|
|
1 3
|
|
2 1 3
|
|
2 1
|
|
}
|
|
|
|
do_execsql_test vector-sql {
|
|
CREATE TABLE t_sql( v FLOAT32(3));
|
|
CREATE INDEX t_sql_idx ON t_sql( libsql_vector_idx(v) );
|
|
INSERT INTO t_sql VALUES(vector('[1,2,3]')), (vector('[2,3,4]'));
|
|
SELECT sql FROM sqlite_master WHERE name LIKE '%t_sql%';
|
|
SELECT name FROM libsql_vector_meta_shadow WHERE name = 't_sql_idx';
|
|
} {{CREATE TABLE t_sql( v FLOAT32(3))} {CREATE TABLE t_sql_idx_shadow (index_key INTEGER , data BLOB, PRIMARY KEY (index_key))} {CREATE INDEX t_sql_idx_shadow_idx ON t_sql_idx_shadow (index_key)} {CREATE INDEX t_sql_idx ON t_sql( libsql_vector_idx(v) )} {t_sql_idx}}
|
|
|
|
do_execsql_test vector-drop-index {
|
|
CREATE TABLE t_index_drop( v FLOAT32(3));
|
|
CREATE INDEX t_index_drop_idx ON t_index_drop( libsql_vector_idx(v) );
|
|
INSERT INTO t_index_drop VALUES(vector('[1,2,3]')), (vector('[2,3,4]'));
|
|
DROP INDEX t_index_drop_idx;
|
|
SELECT sql FROM sqlite_master WHERE name LIKE '%t_index_drop%';
|
|
SELECT name FROM libsql_vector_meta_shadow WHERE name = 't_index_drop_idx';
|
|
} {{CREATE TABLE t_index_drop( v FLOAT32(3))}}
|
|
|
|
do_execsql_test vector-drop-table {
|
|
CREATE TABLE t_table_drop( v FLOAT32(3));
|
|
CREATE INDEX t_table_drop_idx ON t_table_drop( libsql_vector_idx(v) );
|
|
INSERT INTO t_table_drop VALUES(vector('[1,2,3]')), (vector('[2,3,4]'));
|
|
DROP table t_table_drop;
|
|
SELECT sql FROM sqlite_master WHERE name LIKE '%t_table_drop%';
|
|
SELECT name FROM libsql_vector_meta_shadow WHERE name = 't_table_drop_idx';
|
|
} {}
|
|
|
|
do_execsql_test vector-mixed-format {
|
|
CREATE TABLE t_mixed( v FLOAT32(3));
|
|
INSERT INTO t_mixed VALUES('[1,2,3]');
|
|
INSERT INTO t_mixed VALUES(vector('[2,3,4]'));
|
|
INSERT INTO t_mixed VALUES('[5,6,7]');
|
|
CREATE INDEX t_mixed_idx ON t_mixed( libsql_vector_idx(v) );
|
|
SELECT * FROM vector_top_k('t_mixed_idx', '[1,2,3]', 1);
|
|
SELECT * FROM vector_top_k('t_mixed_idx', '[5,6,7]', 1);
|
|
SELECT * FROM vector_top_k('t_mixed_idx', vector('[1,2,3]'), 1);
|
|
} {1 3 1}
|
|
|
|
do_execsql_test vector-alter-column {
|
|
CREATE TABLE t_vec_alter( v BLOB );
|
|
INSERT INTO t_vec_alter VALUES('[1,2,3]');
|
|
INSERT INTO t_vec_alter VALUES(vector('[2,3,4]'));
|
|
INSERT INTO t_vec_alter VALUES('[5,6,7]');
|
|
ALTER TABLE t_vec_alter ALTER COLUMN v TO v FLOAT32(3);
|
|
CREATE INDEX t_vec_alter_idx ON t_vec_alter( libsql_vector_idx(v) );
|
|
SELECT * FROM vector_top_k('t_vec_alter_idx', '[1,2,3]', 1);
|
|
SELECT * FROM vector_top_k('t_vec_alter_idx', '[5,6,7]', 1);
|
|
SELECT * FROM vector_top_k('t_vec_alter_idx', vector('[1,2,3]'), 1);
|
|
} {1 3 1}
|
|
|
|
do_execsql_test vector-create-as {
|
|
CREATE TABLE t_text_origin( v TEXT );
|
|
INSERT INTO t_text_origin VALUES('[1,2,3]');
|
|
INSERT INTO t_text_origin VALUES('[2,3,4]');
|
|
INSERT INTO t_text_origin VALUES('[5,6,7]');
|
|
CREATE TABLE t_blob_dup AS SELECT vector(v) as v FROM t_text_origin;
|
|
ALTER TABLE t_blob_dup ALTER COLUMN v TO v FLOAT32(3);
|
|
CREATE INDEX t_blob_dup_idx ON t_blob_dup( libsql_vector_idx(v) );
|
|
|
|
SELECT * FROM vector_top_k('t_blob_dup_idx', vector('[1,2,3]'), 1);
|
|
SELECT * FROM vector_top_k('t_blob_dup_idx', vector('[5,6,7]'), 1);
|
|
SELECT * FROM vector_top_k('t_blob_dup_idx', vector('[1,2,3]'), 1);
|
|
} {1 3 1}
|
|
|
|
do_execsql_test vector-index-dont-affect-sql {
|
|
CREATE TABLE t_vector_other_sql ( emb FLOAT32(2) );
|
|
INSERT INTO t_vector_other_sql VALUES (vector('[1,2]')), (vector('[3,4]'));
|
|
CREATE INDEX t_vector_other_sql_idx ON t_vector_other_sql(libsql_vector_idx(emb));
|
|
INSERT INTO t_vector_other_sql VALUES (vector('[5,6]')), (vector('[7,8]'));
|
|
SELECT COUNT(*) FROM t_vector_other_sql;
|
|
SELECT COUNT(*) FROM t_vector_other_sql WHERE emb = vector('[1,2]');
|
|
SELECT rowid FROM t_vector_other_sql WHERE emb = vector('[1,2]');
|
|
SELECT rowid FROM t_vector_other_sql WHERE emb = vector('[3,4]');
|
|
SELECT rowid FROM t_vector_other_sql WHERE emb = vector('[5,6]');
|
|
SELECT rowid FROM t_vector_other_sql WHERE emb = vector('[7,8]');
|
|
} {4 1 1 2 3 4}
|
|
|
|
do_execsql_test vector-partial-index-dont-affect-sql {
|
|
CREATE TABLE t_vector_other_sql_part ( emb FLOAT32(2), t TEXT );
|
|
INSERT INTO t_vector_other_sql_part VALUES (vector('[1,2]'), 'paper'), (vector('[3,4]'), 'journal');
|
|
CREATE INDEX t_vector_other_sql_part_idx ON t_vector_other_sql_part(libsql_vector_idx(emb));
|
|
INSERT INTO t_vector_other_sql_part VALUES (vector('[5,6]'), 'journal'), (vector('[7,8]'), 'paper');
|
|
SELECT COUNT(*) FROM t_vector_other_sql_part;
|
|
SELECT COUNT(*) FROM t_vector_other_sql_part WHERE emb = vector('[1,2]');
|
|
SELECT COUNT(*) FROM t_vector_other_sql_part WHERE t = 'paper';
|
|
SELECT rowid FROM t_vector_other_sql_part WHERE emb = vector('[1,2]');
|
|
SELECT rowid FROM t_vector_other_sql_part WHERE emb = vector('[3,4]');
|
|
SELECT rowid FROM t_vector_other_sql_part WHERE emb = vector('[5,6]');
|
|
SELECT rowid FROM t_vector_other_sql_part WHERE emb = vector('[7,8]');
|
|
} {4 1 2 1 2 3 4}
|
|
|
|
do_execsql_test vector-index-dont-affect-sql-pk {
|
|
CREATE TABLE t_vector_other_sql_pk ( name TEXT PRIMARY KEY, emb FLOAT32(2) );
|
|
INSERT INTO t_vector_other_sql_pk VALUES ('a', vector('[1,2]')), ('b', vector('[3,4]'));
|
|
CREATE INDEX t_vector_other_sql_pk_idx ON t_vector_other_sql_pk(libsql_vector_idx(emb));
|
|
INSERT INTO t_vector_other_sql_pk VALUES ('c', vector('[5,6]')), ('d', vector('[7,8]'));
|
|
SELECT COUNT(*) FROM t_vector_other_sql_pk;
|
|
SELECT COUNT(*) FROM t_vector_other_sql_pk WHERE emb = vector('[1,2]');
|
|
SELECT rowid FROM t_vector_other_sql_pk WHERE emb = vector('[1,2]');
|
|
SELECT rowid FROM t_vector_other_sql_pk WHERE emb = vector('[3,4]');
|
|
SELECT rowid FROM t_vector_other_sql_pk WHERE emb = vector('[5,6]');
|
|
SELECT rowid FROM t_vector_other_sql_pk WHERE emb = vector('[7,8]');
|
|
} {4 1 1 2 3 4}
|
|
|
|
do_execsql_test vector-attach {
|
|
CREATE TABLE t_attach ( emb FLOAT32(2) );
|
|
INSERT INTO t_attach VALUES (vector('[1,2]')), (vector('[3,4]'));
|
|
CREATE INDEX t_attach_idx ON t_attach(libsql_vector_idx(emb));
|
|
ATTACH ':memory:' as "q u o t e "" h e r e ";
|
|
CREATE TABLE "q u o t e "" h e r e ".t_attach ( emb FLOAT32(2) );
|
|
INSERT INTO "q u o t e "" h e r e ".t_attach VALUES (vector('[5,6]')), (vector('[7,8]'));
|
|
CREATE INDEX "q u o t e "" h e r e ".t_attach_idx ON t_attach(libsql_vector_idx(emb));
|
|
SELECT rowid FROM vector_top_k('t_attach_idx', vector('[5,6]'), 4);
|
|
} {2 1}
|
|
|
|
do_execsql_test vector-vacuum {
|
|
CREATE TABLE t_vacuum ( emb FLOAT32(2) );
|
|
INSERT INTO t_vacuum VALUES (vector('[1,2]')), (vector('[3,4]')), (vector('[5,6]'));
|
|
CREATE INDEX t_vacuum_idx ON t_vacuum(libsql_vector_idx(emb));
|
|
VACUUM;
|
|
SELECT COUNT(*) FROM t_vacuum;
|
|
SELECT COUNT(*) FROM t_vacuum_idx_shadow;
|
|
DELETE FROM t_vacuum WHERE rowid = 2;
|
|
VACUUM;
|
|
SELECT * FROM vector_top_k('t_vacuum_idx', vector('[1,2]'), 3);
|
|
SELECT * FROM vector_top_k('t_vacuum_idx', vector('[5,6]'), 3);
|
|
SELECT * FROM vector_top_k('t_vacuum_idx', vector('[3,4]'), 3);
|
|
} {3 3 1 2 2 1 2 1}
|
|
|
|
do_execsql_test vector-many-columns {
|
|
CREATE TABLE t_many ( i INTEGER PRIMARY KEY, e1 FLOAT32(2), e2 FLOAT32(2) );
|
|
CREATE INDEX t_many_1_idx ON t_many(libsql_vector_idx(e1));
|
|
CREATE INDEX t_many_2_idx ON t_many(libsql_vector_idx(e2));
|
|
INSERT INTO t_many VALUES (1, vector('[1,1]'), vector('[-1,-1]')), (2, vector('[-1,-1]'), vector('[1,1]'));
|
|
SELECT * FROM vector_top_k('t_many_1_idx', vector('[1,1]'), 2);
|
|
SELECT * FROM vector_top_k('t_many_2_idx', vector('[1,1]'), 2);
|
|
} {1 2 2 1}
|
|
|
|
do_execsql_test vector-transaction {
|
|
CREATE TABLE t_transaction ( i INTEGER PRIMARY KEY, e FLOAT32(2) );
|
|
CREATE INDEX t_transaction_idx ON t_transaction(libsql_vector_idx(e));
|
|
INSERT INTO t_transaction VALUES (1, vector('[1,2]')), (2, vector('[3,4]'));
|
|
BEGIN;
|
|
INSERT INTO t_transaction VALUES (3, vector('[4,5]')), (4, vector('[5,6]'));
|
|
SELECT * FROM vector_top_k('t_transaction_idx', vector('[4,5]'), 2);
|
|
ROLLBACK;
|
|
SELECT * FROM vector_top_k('t_transaction_idx', vector('[1,2]'), 2);
|
|
} {3 4 1 2}
|
|
|
|
do_execsql_test vector-1bit {
|
|
CREATE TABLE t_1bit( v FLOAT32(3) );
|
|
CREATE INDEX t_1bit_idx ON t_1bit( libsql_vector_idx(v, 'compress_neighbors=float1bit') );
|
|
INSERT INTO t_1bit VALUES (vector('[-1,-1,1]'));
|
|
INSERT INTO t_1bit VALUES (vector('[-1,1,-1.5]'));
|
|
INSERT INTO t_1bit VALUES (vector('[1,-1,-1]'));
|
|
INSERT INTO t_1bit VALUES (vector('[-1,-1,-1]'));
|
|
SELECT rowid FROM vector_top_k('t_1bit_idx', vector('[1,-1,-1]'), 4);
|
|
} {3 4 2 1}
|
|
|
|
do_execsql_test vector-all-params {
|
|
CREATE TABLE t_all_params ( emb FLOAT32(2) );
|
|
CREATE INDEX t_all_params_idx ON t_all_params(libsql_vector_idx(emb, 'type=diskann', 'metric=cos', 'alpha=1.2', 'search_l=200', 'insert_l=70', 'max_neighbors=6', 'compress_neighbors=float1bit'));
|
|
INSERT INTO t_all_params VALUES (vector('[1,2]')), (vector('[3,4]'));
|
|
SELECT * FROM vector_top_k('t_all_params_idx', vector('[1,2]'), 2);
|
|
} {1 2}
|
|
|
|
do_execsql_test vector-f64-index {
|
|
CREATE TABLE t_f64 ( emb FLOAT64(2) );
|
|
CREATE INDEX t_f64_idx ON t_f64(libsql_vector_idx(emb));
|
|
INSERT INTO t_f64 VALUES (vector64('[1,2]')), (vector64('[3,4]'));
|
|
SELECT * FROM vector_top_k('t_f64_idx', vector64('[1,2]'), 2);
|
|
} {1 2}
|
|
|
|
reset_db
|
|
|
|
do_execsql_test vector-partial {
|
|
CREATE TABLE t_partial( name TEXT, type INT, v FLOAT32(3));
|
|
INSERT INTO t_partial VALUES ( 'a', 0, vector('[1,2,3]') );
|
|
INSERT INTO t_partial VALUES ( 'b', 1, vector('[3,4,5]') );
|
|
INSERT INTO t_partial VALUES ( 'c', 2, vector('[4,5,6]') );
|
|
INSERT INTO t_partial VALUES ( 'd', 0, vector('[5,6,7]') );
|
|
INSERT INTO t_partial VALUES ( 'e', 1, vector('[6,7,8]') );
|
|
INSERT INTO t_partial VALUES ( 'f', 2, vector('[7,8,9]') );
|
|
CREATE INDEX t_partial_idx_0 ON t_partial( libsql_vector_idx(v) ) WHERE type = 0;
|
|
CREATE INDEX t_partial_idx_1 ON t_partial( libsql_vector_idx(v) ) WHERE type = 1;
|
|
CREATE INDEX t_partial_idx_not_0 ON t_partial( libsql_vector_idx(v) ) WHERE type != 0;
|
|
SELECT id FROM vector_top_k('t_partial_idx_0', vector('[1,2,3]'), 10);
|
|
SELECT id FROM vector_top_k('t_partial_idx_1', vector('[1,2,3]'), 10);
|
|
SELECT id FROM vector_top_k('t_partial_idx_not_0', vector('[1,2,3]'), 10);
|
|
INSERT INTO t_partial VALUES ( 'g', 0, vector('[8,9,10]') );
|
|
INSERT INTO t_partial VALUES ( 'h', 1, vector('[9,10,11]') );
|
|
INSERT INTO t_partial VALUES ( 'i', 2, vector('[10,11,12]') );
|
|
SELECT id FROM vector_top_k('t_partial_idx_0', vector('[1,2,3]'), 10);
|
|
SELECT id FROM vector_top_k('t_partial_idx_1', vector('[1,2,3]'), 10);
|
|
SELECT id FROM vector_top_k('t_partial_idx_not_0', vector('[1,2,3]'), 10);
|
|
} {
|
|
1 4
|
|
2 5
|
|
2 3 5 6
|
|
|
|
1 4 7
|
|
2 5 8
|
|
2 3 5 6 8 9
|
|
}
|
|
|
|
reset_db
|
|
|
|
do_execsql_test vector-1bit-index {
|
|
CREATE TABLE t_1bit_table( v FLOAT1BIT(4) );
|
|
INSERT INTO t_1bit_table VALUES ( vector1bit('[1,-1,1,-1]') );
|
|
CREATE INDEX t_1bit_table_idx ON t_1bit_table( libsql_vector_idx(v) );
|
|
INSERT INTO t_1bit_table VALUES ( vector1bit('[-1,1,1,-1]') );
|
|
INSERT INTO t_1bit_table VALUES ( vector1bit('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_1bit_table_idx', vector1bit('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
do_execsql_test vector-f64-compress-f32 {
|
|
CREATE TABLE t_f64_f32( v FLOAT64(4) );
|
|
CREATE INDEX t_f64_f32_idx ON t_f64_f32( libsql_vector_idx(v, 'compress_neighbors=float32') );
|
|
INSERT INTO t_f64_f32 VALUES ( vector64('[1,-1,1,-1]') );
|
|
INSERT INTO t_f64_f32 VALUES ( vector64('[-1,1,1,-1]') );
|
|
INSERT INTO t_f64_f32 VALUES ( vector64('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_f64_f32_idx', vector64('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
do_execsql_test vector-f32-compress-f8 {
|
|
CREATE TABLE t_f32_f8( v FLOAT32(4) );
|
|
CREATE INDEX t_f32_f8_idx ON t_f32_f8( libsql_vector_idx(v, 'compress_neighbors=float8') );
|
|
INSERT INTO t_f32_f8 VALUES ( vector('[1,-1,1,-1]') );
|
|
INSERT INTO t_f32_f8 VALUES ( vector('[-1,1,1,-1]') );
|
|
INSERT INTO t_f32_f8 VALUES ( vector('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_f32_f8_idx', vector('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
do_execsql_test vector-f32-compress-f16 {
|
|
CREATE TABLE t_f32_f16( v FLOAT32(4) );
|
|
CREATE INDEX t_f32_f16_idx ON t_f32_f16( libsql_vector_idx(v, 'compress_neighbors=float16') );
|
|
INSERT INTO t_f32_f16 VALUES ( vector('[1,-1,1,-1]') );
|
|
INSERT INTO t_f32_f16 VALUES ( vector('[-1,1,1,-1]') );
|
|
INSERT INTO t_f32_f16 VALUES ( vector('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_f32_f16_idx', vector('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
do_execsql_test vector-f32-compress-bf16 {
|
|
CREATE TABLE t_f32_bf16( v FLOAT32(4) );
|
|
CREATE INDEX t_f32_bf16_idx ON t_f32_bf16( libsql_vector_idx(v, 'compress_neighbors=floatb16') );
|
|
INSERT INTO t_f32_bf16 VALUES ( vector('[1,-1,1,-1]') );
|
|
INSERT INTO t_f32_bf16 VALUES ( vector('[-1,1,1,-1]') );
|
|
INSERT INTO t_f32_bf16 VALUES ( vector('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_f32_bf16_idx', vector('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
do_execsql_test vector-f8 {
|
|
CREATE TABLE t_f8( v FLOAT8(4) );
|
|
CREATE INDEX t_f8_idx ON t_f8( libsql_vector_idx(v) );
|
|
INSERT INTO t_f8 VALUES ( vector8('[1,-1,1,-1]') );
|
|
INSERT INTO t_f8 VALUES ( vector8('[-1,1,1,-1]') );
|
|
INSERT INTO t_f8 VALUES ( vector8('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_f8_idx', vector8('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
do_execsql_test vector-f16 {
|
|
CREATE TABLE t_f16( v FLOAT16(4) );
|
|
CREATE INDEX t_f16_idx ON t_f16( libsql_vector_idx(v) );
|
|
INSERT INTO t_f16 VALUES ( vector16('[1,-1,1,-1]') );
|
|
INSERT INTO t_f16 VALUES ( vector16('[-1,1,1,-1]') );
|
|
INSERT INTO t_f16 VALUES ( vector16('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_f16_idx', vector16('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
do_execsql_test vector-bf16 {
|
|
CREATE TABLE t_bf16( v FLOATB16(4) );
|
|
CREATE INDEX t_bf16_idx ON t_bf16( libsql_vector_idx(v) );
|
|
INSERT INTO t_bf16 VALUES ( vectorb16('[1,-1,1,-1]') );
|
|
INSERT INTO t_bf16 VALUES ( vectorb16('[-1,1,1,-1]') );
|
|
INSERT INTO t_bf16 VALUES ( vectorb16('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_bf16_idx', vectorb16('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
do_execsql_test vector-f8-compress-1bit {
|
|
CREATE TABLE t_f8_1bit( v FLOAT8(4) );
|
|
CREATE INDEX t_f8_1bit_idx ON t_f8_1bit( libsql_vector_idx(v, 'compress_neighbors=float1bit') );
|
|
INSERT INTO t_f8_1bit VALUES ( vector8('[1,-1,1,-1]') );
|
|
INSERT INTO t_f8_1bit VALUES ( vector8('[-1,1,1,-1]') );
|
|
INSERT INTO t_f8_1bit VALUES ( vector8('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_f8_1bit_idx', vector8('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
do_execsql_test vector-f16-compress-1bit {
|
|
CREATE TABLE t_f16_1bit( v FLOAT16(4) );
|
|
CREATE INDEX t_f16_1bit_idx ON t_f16_1bit( libsql_vector_idx(v, 'compress_neighbors=float1bit') );
|
|
INSERT INTO t_f16_1bit VALUES ( vector16('[1,-1,1,-1]') );
|
|
INSERT INTO t_f16_1bit VALUES ( vector16('[-1,1,1,-1]') );
|
|
INSERT INTO t_f16_1bit VALUES ( vector16('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_f16_1bit_idx', vector16('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
do_execsql_test vector-bf16-compress-1bit {
|
|
CREATE TABLE t_bf16_1bit( v FLOATB16(4) );
|
|
CREATE INDEX t_bf16_1bit_idx ON t_bf16_1bit( libsql_vector_idx(v, 'compress_neighbors=float1bit') );
|
|
INSERT INTO t_bf16_1bit VALUES ( vectorb16('[1,-1,1,-1]') );
|
|
INSERT INTO t_bf16_1bit VALUES ( vectorb16('[-1,1,1,-1]') );
|
|
INSERT INTO t_bf16_1bit VALUES ( vectorb16('[1,-1,-1,1]') );
|
|
SELECT * FROM vector_top_k('t_bf16_1bit_idx', vectorb16('[10,-10,-20,20]'), 4);
|
|
} {3 1 2}
|
|
|
|
proc error_messages {sql} {
|
|
set ret ""
|
|
catch {
|
|
set stmt [sqlite3_prepare db $sql -1 dummy]
|
|
sqlite3_step $stmt
|
|
sqlite3_finalize $stmt
|
|
} ret
|
|
set ret [sqlite3_errmsg db]
|
|
}
|
|
|
|
do_test vector-errors {
|
|
set ret [list]
|
|
lappend ret [error_messages {CREATE INDEX t_no_idx ON t_no( libsql_vector_idx(v) )}]
|
|
sqlite3_exec db { CREATE TABLE t_err ( a INTEGER, b BLOB, c FLOAT32(-1), d FLOAT32(0), e FLOAT32(1) ) }
|
|
sqlite3_exec db { CREATE TABLE t_err2 ( a, b, v FLOAT32(4), PRIMARY KEY (a, b) ) WITHOUT ROWID }
|
|
lappend ret [error_messages {CREATE INDEX t_err_idx ON t_err( libsql_vector_idx(v) )}]
|
|
lappend ret [error_messages {CREATE INDEX t_err_idx ON t_err( libsql_vector(e) )}]
|
|
lappend ret [error_messages {CREATE INDEX t_err_idx ON t_err( libsql_vector_idx(a) )}]
|
|
lappend ret [error_messages {CREATE INDEX t_err_idx ON t_err( libsql_vector_idx(b) )}]
|
|
lappend ret [error_messages {CREATE INDEX t_err_idx ON t_err( libsql_vector_idx(c) )}]
|
|
lappend ret [error_messages {CREATE INDEX t_err_idx ON t_err( libsql_vector_idx(d) )}]
|
|
lappend ret [error_messages {CREATE INDEX t_err_idx ON t_err( libsql_vector_idx(e, 'a=1') )}]
|
|
lappend ret [error_messages {CREATE INDEX t_err_idx ON t_err( libsql_vector_idx(e, 'metric=unknown') )}]
|
|
lappend ret [error_messages {CREATE INDEX t_err_idx ON t_err( libsql_vector_idx(e, 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine', 'metric=cosine') )}]
|
|
lappend ret [error_messages {CREATE INDEX t_err_idx ON t_err2( libsql_vector_idx(v) )}]
|
|
sqlite3_exec db { CREATE TABLE t_err3 ( e FLOAT32(4) ) }
|
|
sqlite3_exec db { CREATE INDEX t_err3_idx ON t_err3 (libsql_vector_idx(e)) }
|
|
lappend ret [error_messages {INSERT INTO t_err3 VALUES (vector('[1]'))}]
|
|
lappend ret [error_messages {INSERT INTO t_err3 VALUES (vector('[1, 2, 3, 4, 5]'))}]
|
|
lappend ret [error_messages {INSERT INTO t_err3 VALUES (vector64('[1,2,3,4]'))}]
|
|
lappend ret [error_messages {SELECT * FROM vector_top_k('t_err3_idx', vector('[1,2]'), 2)}]
|
|
lappend ret [error_messages {SELECT * FROM vector_top_k('t_err3_idx', vector('[1,2,3,4]'), 2.5)}]
|
|
sqlite3_exec db { CREATE TABLE t_mixed_t( v FLOAT32(3)); }
|
|
sqlite3_exec db { INSERT INTO t_mixed_t VALUES('[1]'); }
|
|
lappend ret [error_messages {CREATE INDEX t_mixed_t_idx ON t_mixed_t( libsql_vector_idx(v) )}]
|
|
lappend ret [error_messages {SELECT * FROM vector_top_k('t.t_attach_idx', vector('[3,4,5]'), 4)}]
|
|
} [list {*}{
|
|
{no such table: main.t_no}
|
|
{no such column: v}
|
|
{no such function: libsql_vector}
|
|
{vector index: unexpected vector column type: INTEGER}
|
|
{vector index: unexpected vector column type: BLOB}
|
|
{vector index: non digit symbol in vector column parameter: FLOAT32(-1)}
|
|
{vector index: vector column must have non-zero dimension for index: FLOAT32(0)}
|
|
{vector index: invalid vector index parameter 'a=1': invalid parameter}
|
|
{vector index: invalid vector index parameter 'metric=unknown': invalid parameter}
|
|
{vector index: invalid vector index parameter 'metric=cosine': unable to serialize vector index parameter}
|
|
{vector index: unsupported for tables without ROWID and composite primary key}
|
|
{vector index(insert): dimensions are different: 1 != 4}
|
|
{vector index(insert): dimensions are different: 5 != 4}
|
|
{vector index(insert): vector type differs from column type: 2 != 1}
|
|
{vector index(search): dimensions are different: 2 != 4}
|
|
{vector index(search): third parameter (k) must be an integer, but float value were provided}
|
|
{vector index(insert): dimensions are different: 1 != 3}
|
|
{vector index(search): unknown schema 't'}
|
|
}]
|
|
|
|
|
|
do_test vector-index-attach-setup {
|
|
forcedelete test2.db
|
|
forcedelete test2.db-journal
|
|
sqlite3 db2 test2.db
|
|
|
|
execsql {
|
|
CREATE TABLE t_attach(e FLOAT32(3));
|
|
CREATE INDEX t_attach_idx ON t_attach(libsql_vector_idx(e));
|
|
INSERT INTO t_attach VALUES (vector('[1,2,3]'));
|
|
INSERT INTO t_attach VALUES (vector('[2,3,4]'));
|
|
INSERT INTO t_attach VALUES (vector('[3,4,5]'));
|
|
INSERT INTO t_attach VALUES (vector('[4,5,6]'));
|
|
} db2
|
|
} {}
|
|
|
|
do_execsql_test vector-index-attach-query {
|
|
ATTACH DATABASE 'test2.db' AS t;
|
|
SELECT * FROM vector_top_k('t.t_attach_idx', vector('[3,4,5]'), 4);
|
|
} {3 4 2 1}
|