@@ -212,7 +212,7 @@ int vectorInRowAlloc(sqlite3 *db, const UnpackedRecord *pRecord, VectorInRow *pV
212
212
213
213
if ( pVectorInRow -> nKeys <= 0 ){
214
214
rc = SQLITE_ERROR ;
215
- goto out ;
215
+ goto out ;
216
216
}
217
217
218
218
if ( sqlite3_value_type (pVectorValue )== SQLITE_NULL ){
@@ -233,7 +233,7 @@ int vectorInRowAlloc(sqlite3 *db, const UnpackedRecord *pRecord, VectorInRow *pV
233
233
234
234
if ( sqlite3_value_type (pVectorValue ) == SQLITE_BLOB ){
235
235
vectorInitFromBlob (pVectorInRow -> pVector , sqlite3_value_blob (pVectorValue ), sqlite3_value_bytes (pVectorValue ));
236
- } else if ( sqlite3_value_type (pVectorValue ) == SQLITE_TEXT ){
236
+ } else if ( sqlite3_value_type (pVectorValue ) == SQLITE_TEXT ){
237
237
// users can put strings (e.g. '[1,2,3]') in the table and we should process them correctly
238
238
if ( vectorParse (pVectorValue , pVectorInRow -> pVector , pzErrMsg ) != 0 ){
239
239
rc = SQLITE_ERROR ;
@@ -321,10 +321,10 @@ void vectorOutRowsGet(sqlite3_context *context, const VectorOutRows *pRows, int
321
321
322
322
void vectorOutRowsFree (sqlite3 * db , VectorOutRows * pRows ) {
323
323
int i ;
324
-
324
+
325
325
// both aIntValues and ppValues can be null if processing failing in the middle and we didn't created VectorOutRows
326
326
assert ( pRows -> aIntValues == NULL || pRows -> ppValues == NULL );
327
-
327
+
328
328
if ( pRows -> aIntValues != NULL ){
329
329
sqlite3DbFree (db , pRows -> aIntValues );
330
330
}else if ( pRows -> ppValues != NULL ){
@@ -337,8 +337,8 @@ void vectorOutRowsFree(sqlite3 *db, VectorOutRows *pRows) {
337
337
}
338
338
}
339
339
340
- /*
341
- * Internal type to represent VECTOR_COLUMN_TYPES array
340
+ /*
341
+ * Internal type to represent VECTOR_COLUMN_TYPES array
342
342
* We support both FLOATNN and FNN_BLOB type names for the following reasons:
343
343
* 1. FLOATNN is easy to type for humans and generally OK to use for column type names
344
344
* 2. FNN_BLOB is aligned with SQLite affinity rules and can be used in cases where compatibility with type affinity rules is important
@@ -349,15 +349,15 @@ struct VectorColumnType {
349
349
int nBits ;
350
350
};
351
351
352
- static struct VectorColumnType VECTOR_COLUMN_TYPES [] = {
353
- { "FLOAT32" , 32 },
354
- { "FLOAT64" , 64 },
355
- { "F32_BLOB" , 32 },
356
- { "F64_BLOB" , 64 }
352
+ static struct VectorColumnType VECTOR_COLUMN_TYPES [] = {
353
+ { "FLOAT32" , 32 },
354
+ { "FLOAT64" , 64 },
355
+ { "F32_BLOB" , 32 },
356
+ { "F64_BLOB" , 64 }
357
357
};
358
358
359
359
/*
360
- * Internal type to represent VECTOR_PARAM_NAMES array with recognized parameters for index creation
360
+ * Internal type to represent VECTOR_PARAM_NAMES array with recognized parameters for index creation
361
361
* For example, libsql_vector_idx(embedding, 'type=diskann', 'metric=cosine')
362
362
*/
363
363
struct VectorParamName {
@@ -368,7 +368,7 @@ struct VectorParamName {
368
368
u64 value ;
369
369
};
370
370
371
- static struct VectorParamName VECTOR_PARAM_NAMES [] = {
371
+ static struct VectorParamName VECTOR_PARAM_NAMES [] = {
372
372
{ "type" , VECTOR_INDEX_TYPE_PARAM_ID , 0 , "diskann" , VECTOR_INDEX_TYPE_DISKANN },
373
373
{ "metric" , VECTOR_METRIC_TYPE_PARAM_ID , 0 , "cosine" , VECTOR_METRIC_TYPE_COS },
374
374
{ "metric" , VECTOR_METRIC_TYPE_PARAM_ID , 0 , "l2" , VECTOR_METRIC_TYPE_L2 },
@@ -550,15 +550,34 @@ int vectorIdxParseColumnType(const char *zType, int *pType, int *pDims, const ch
550
550
return -1 ;
551
551
}
552
552
553
- int initVectorIndexMetaTable (sqlite3 * db ) {
554
- static const char * zSql = "CREATE TABLE IF NOT EXISTS " VECTOR_INDEX_GLOBAL_META_TABLE " ( name TEXT PRIMARY KEY, metadata BLOB ) WITHOUT ROWID;" ;
555
- return sqlite3_exec (db , zSql , 0 , 0 , 0 );
553
+ int initVectorIndexMetaTable (sqlite3 * db , const char * zDbSName ) {
554
+ int rc ;
555
+ static const char * zSqlTemplate = "CREATE TABLE IF NOT EXISTS \"%w\"." VECTOR_INDEX_GLOBAL_META_TABLE " ( name TEXT PRIMARY KEY, metadata BLOB ) WITHOUT ROWID;" ;
556
+ char * zSql ;
557
+
558
+ assert ( zDbSName != NULL );
559
+
560
+ zSql = sqlite3_mprintf (zSqlTemplate , zDbSName );
561
+ if ( zSql == NULL ){
562
+ return SQLITE_NOMEM_BKPT ;
563
+ }
564
+ rc = sqlite3_exec (db , zSql , 0 , 0 , 0 );
565
+ sqlite3_free (zSql );
566
+ return rc ;
556
567
}
557
568
558
- int insertIndexParameters (sqlite3 * db , const char * zName , const VectorIdxParams * pParameters ) {
559
- static const char * zSql = "INSERT INTO " VECTOR_INDEX_GLOBAL_META_TABLE " VALUES (?, ?)" ;
560
- sqlite3_stmt * pStatement = NULL ;
569
+ int insertIndexParameters (sqlite3 * db , const char * zDbSName , const char * zName , const VectorIdxParams * pParameters ) {
561
570
int rc = SQLITE_ERROR ;
571
+ static const char * zSqlTemplate = "INSERT INTO \"%w\"." VECTOR_INDEX_GLOBAL_META_TABLE " VALUES (?, ?)" ;
572
+ sqlite3_stmt * pStatement = NULL ;
573
+ char * zSql ;
574
+
575
+ assert ( zDbSName != NULL );
576
+
577
+ zSql = sqlite3_mprintf (zSqlTemplate , zDbSName );
578
+ if ( zSql == NULL ){
579
+ return SQLITE_NOMEM_BKPT ;
580
+ }
562
581
563
582
rc = sqlite3_prepare_v2 (db , zSql , -1 , & pStatement , 0 );
564
583
if ( rc != SQLITE_OK ){
@@ -579,6 +598,9 @@ int insertIndexParameters(sqlite3* db, const char *zName, const VectorIdxParams
579
598
rc = SQLITE_OK ;
580
599
}
581
600
clear_and_exit :
601
+ if ( zSql != NULL ){
602
+ sqlite3_free (zSql );
603
+ }
582
604
if ( pStatement != NULL ){
583
605
sqlite3_finalize (pStatement );
584
606
}
@@ -672,24 +694,31 @@ int vectorIndexGetParameters(
672
694
}
673
695
674
696
675
- int vectorIndexDrop (sqlite3 * db , const char * zIdxName ) {
697
+ int vectorIndexDrop (sqlite3 * db , const char * zDbSName , const char * zIdxName ) {
676
698
// we want to try delete all traces of index on every attempt
677
699
// this is done to prevent unrecoverable situations where index were dropped but index parameters deletion failed and second attempt will fail on first step
678
- int rcIdx = diskAnnDropIndex (db , zIdxName );
679
- int rcParams = removeIndexParameters (db , zIdxName );
700
+ int rcIdx , rcParams ;
701
+
702
+ assert ( zDbSName != NULL );
703
+
704
+ rcIdx = diskAnnDropIndex (db , zDbSName , zIdxName );
705
+ rcParams = removeIndexParameters (db , zIdxName );
680
706
return rcIdx != SQLITE_OK ? rcIdx : rcParams ;
681
707
}
682
708
683
- int vectorIndexClear (sqlite3 * db , const char * zIdxName ) {
684
- return diskAnnClearIndex (db , zIdxName );
709
+ int vectorIndexClear (sqlite3 * db , const char * zDbSName , const char * zIdxName ) {
710
+ assert ( zDbSName != NULL );
711
+ return diskAnnClearIndex (db , zDbSName , zIdxName );
685
712
}
686
713
687
- int vectorIndexCreate (Parse * pParse , Index * pIdx , const IdList * pUsing ) {
714
+ int vectorIndexCreate (Parse * pParse , Index * pIdx , const char * zDbSName , const IdList * pUsing ) {
688
715
int i , rc = SQLITE_OK ;
689
716
int dims , type ;
690
717
int hasLibsqlVectorIdxFn = 0 , hasCollation = 0 ;
691
718
const char * pzErrMsg ;
692
719
720
+ assert ( zDbSName != NULL );
721
+
693
722
sqlite3 * db = pParse -> db ;
694
723
Table * pTable = pIdx -> pTable ;
695
724
struct ExprList_item * pListItem ;
@@ -776,34 +805,33 @@ int vectorIndexCreate(Parse *pParse, Index *pIdx, const IdList *pUsing) {
776
805
return SQLITE_ERROR ;
777
806
}
778
807
779
- if ( vectorIdxKeyGet (pTable , & idxKey , & pzErrMsg ) != 0 ){
780
- sqlite3ErrorMsg (pParse , "failed to detect underlying table key: %s" , pzErrMsg );
781
- return SQLITE_ERROR ;
782
- }
783
- if ( idxKey .nKeyColumns != 1 ){
784
- sqlite3ErrorMsg (pParse , "vector index for tables without ROWID and composite primary key are not supported" );
785
- return SQLITE_ERROR ;
786
- }
787
-
788
808
// schema is locked while db is initializing and we need to just proceed here
789
809
if ( db -> init .busy == 1 ){
790
810
goto succeed ;
791
811
}
792
812
793
- rc = initVectorIndexMetaTable (db );
813
+ rc = initVectorIndexMetaTable (db , zDbSName );
794
814
if ( rc != SQLITE_OK ){
795
815
return rc ;
796
816
}
797
817
rc = parseVectorIdxParams (pParse , & idxParams , type , dims , pListItem + 1 , pArgsList -> nExpr - 1 );
798
818
if ( rc != SQLITE_OK ){
799
819
return rc ;
800
820
}
801
- rc = diskAnnCreateIndex (db , pIdx -> zName , & idxKey , & idxParams );
821
+ if ( vectorIdxKeyGet (pTable , & idxKey , & pzErrMsg ) != 0 ){
822
+ sqlite3ErrorMsg (pParse , "failed to detect underlying table key: %s" , pzErrMsg );
823
+ return SQLITE_ERROR ;
824
+ }
825
+ if ( idxKey .nKeyColumns != 1 ){
826
+ sqlite3ErrorMsg (pParse , "vector index for tables without ROWID and composite primary key are not supported" );
827
+ return SQLITE_ERROR ;
828
+ }
829
+ rc = diskAnnCreateIndex (db , zDbSName , pIdx -> zName , & idxKey , & idxParams );
802
830
if ( rc != SQLITE_OK ){
803
831
sqlite3ErrorMsg (pParse , "unable to initialize diskann vector index" );
804
832
return rc ;
805
833
}
806
- rc = insertIndexParameters (db , pIdx -> zName , & idxParams );
834
+ rc = insertIndexParameters (db , zDbSName , pIdx -> zName , & idxParams );
807
835
if ( rc != SQLITE_OK ){
808
836
sqlite3ErrorMsg (pParse , "unable to update global metadata table" );
809
837
return rc ;
@@ -815,7 +843,7 @@ int vectorIndexCreate(Parse *pParse, Index *pIdx, const IdList *pUsing) {
815
843
return SQLITE_OK ;
816
844
}
817
845
818
- int vectorIndexSearch (sqlite3 * db , int argc , sqlite3_value * * argv , VectorOutRows * pRows , char * * pzErrMsg ) {
846
+ int vectorIndexSearch (sqlite3 * db , const char * zDbSName , int argc , sqlite3_value * * argv , VectorOutRows * pRows , char * * pzErrMsg ) {
819
847
int type , dims , k , rc ;
820
848
const char * zIdxName ;
821
849
const char * zErrMsg ;
@@ -826,6 +854,8 @@ int vectorIndexSearch(sqlite3 *db, int argc, sqlite3_value **argv, VectorOutRows
826
854
VectorIdxParams idxParams ;
827
855
vectorIdxParamsInit (& idxParams , NULL , 0 );
828
856
857
+ assert ( zDbSName != NULL );
858
+
829
859
if ( argc != 3 ){
830
860
* pzErrMsg = sqlite3_mprintf ("vector search must have exactly 3 parameters" );
831
861
rc = SQLITE_ERROR ;
@@ -871,22 +901,22 @@ int vectorIndexSearch(sqlite3 *db, int argc, sqlite3_value **argv, VectorOutRows
871
901
rc = SQLITE_ERROR ;
872
902
goto out ;
873
903
}
874
- pIndex = sqlite3FindIndex (db , zIdxName , db -> aDb [ 0 ]. zDbSName );
904
+ pIndex = sqlite3FindIndex (db , zIdxName , zDbSName );
875
905
if ( pIndex == NULL ){
876
906
* pzErrMsg = sqlite3_mprintf ("vector index not found" );
877
907
rc = SQLITE_ERROR ;
878
908
goto out ;
879
909
}
910
+ rc = diskAnnOpenIndex (db , zDbSName , zIdxName , & idxParams , & pDiskAnn );
911
+ if ( rc != SQLITE_OK ){
912
+ * pzErrMsg = sqlite3_mprintf ("failed to open diskann index" );
913
+ goto out ;
914
+ }
880
915
if ( vectorIdxKeyGet (pIndex -> pTable , & pKey , & zErrMsg ) != 0 ){
881
916
* pzErrMsg = sqlite3_mprintf ("failed to extract table key: %s" , zErrMsg );
882
917
rc = SQLITE_ERROR ;
883
918
goto out ;
884
919
}
885
- rc = diskAnnOpenIndex (db , zIdxName , & idxParams , & pDiskAnn );
886
- if ( rc != SQLITE_OK ){
887
- * pzErrMsg = sqlite3_mprintf ("failed to open diskann index" );
888
- goto out ;
889
- }
890
920
rc = diskAnnSearch (pDiskAnn , pVector , k , & pKey , pRows , pzErrMsg );
891
921
out :
892
922
if ( pDiskAnn != NULL ){
@@ -932,22 +962,25 @@ int vectorIndexDelete(
932
962
933
963
int vectorIndexCursorInit (
934
964
sqlite3 * db ,
935
- VectorIdxCursor * * ppCursor ,
936
- const char * zIndexName
965
+ const char * zDbSName ,
966
+ const char * zIndexName ,
967
+ VectorIdxCursor * * ppCursor
937
968
){
938
969
int rc ;
939
970
VectorIdxCursor * pCursor ;
940
971
VectorIdxParams params ;
941
972
vectorIdxParamsInit (& params , NULL , 0 );
942
973
974
+ assert ( zDbSName != NULL );
975
+
943
976
if ( vectorIndexGetParameters (db , zIndexName , & params ) != 0 ){
944
977
return SQLITE_ERROR ;
945
978
}
946
979
pCursor = sqlite3DbMallocZero (db , sizeof (VectorIdxCursor ));
947
980
if ( pCursor == 0 ){
948
981
return SQLITE_NOMEM_BKPT ;
949
982
}
950
- rc = diskAnnOpenIndex (db , zIndexName , & params , & pCursor -> pIndex );
983
+ rc = diskAnnOpenIndex (db , zDbSName , zIndexName , & params , & pCursor -> pIndex );
951
984
if ( rc != SQLITE_OK ){
952
985
sqlite3DbFree (db , pCursor );
953
986
return rc ;
0 commit comments