@@ -747,17 +747,25 @@ int vectorIndexTryGetParametersFromBinFormat(sqlite3 *db, const char *zSql, cons
747747
748748int vectorIndexGetParameters (
749749 sqlite3 * db ,
750+ const char * zDbSName ,
750751 const char * zIdxName ,
751752 VectorIdxParams * pParams
752753) {
753754 int rc = SQLITE_OK ;
755+ assert ( zDbSName != NULL );
754756
755- static const char * zSelectSql = "SELECT metadata FROM " VECTOR_INDEX_GLOBAL_META_TABLE " WHERE name = ?" ;
757+ static const char * zSelectSqlTemplate = "SELECT metadata FROM \"%w\"." VECTOR_INDEX_GLOBAL_META_TABLE " WHERE name = ?" ;
758+ char * zSelectSql ;
759+ zSelectSql = sqlite3_mprintf (zSelectSqlTemplate , zDbSName );
760+ if ( zSelectSql == NULL ){
761+ return SQLITE_NOMEM_BKPT ;
762+ }
756763 // zSelectSqlPekkaLegacy handles the case when user created DB before 04 July 2024 (https://discord.com/channels/933071162680958986/1225560924526477322/1258367912402489397)
757764 // when instead of table with binary parameters rigid schema was used for index settings
758765 // we should drop this eventually - but for now we postponed this decision
759766 static const char * zSelectSqlPekkaLegacy = "SELECT vector_type, block_size, dims, distance_ops FROM libsql_vector_index WHERE name = ?" ;
760767 rc = vectorIndexTryGetParametersFromBinFormat (db , zSelectSql , zIdxName , pParams );
768+ sqlite3_free (zSelectSql );
761769 if ( rc == SQLITE_OK ){
762770 return SQLITE_OK ;
763771 }
@@ -940,9 +948,32 @@ int vectorIndexCreate(Parse *pParse, const Index *pIdx, const char *zDbSName, co
940948 return CREATE_OK ;
941949}
942950
951+ // extracts schema and index name part if full index name is composite (e.g. schema_name.index_name)
952+ // if full index name has no schema part - function returns SQLITE_OK but leaves pzIdxDbSName and pzIdxName untouched
953+ int getIndexNameParts (sqlite3 * db , const char * zIdxFullName , char * * pzIdxDbSName , char * * pzIdxName ) {
954+ int nFullName , nDbSName ;
955+ const char * pDot = zIdxFullName ;
956+ while ( * pDot != '.' && * pDot != '\0' ){
957+ pDot ++ ;
958+ }
959+ if ( * pDot == '\0' ){
960+ return SQLITE_OK ;
961+ }
962+ assert ( * pDot == '.' );
963+ nFullName = sqlite3Strlen30 (zIdxFullName );
964+ nDbSName = pDot - zIdxFullName ;
965+ * pzIdxDbSName = sqlite3DbStrNDup (db , zIdxFullName , nDbSName );
966+ * pzIdxName = sqlite3DbStrNDup (db , pDot + 1 , nFullName - nDbSName - 1 );
967+ if ( pzIdxName == NULL || pzIdxDbSName == NULL ){
968+ sqlite3DbFree (db , * pzIdxName );
969+ sqlite3DbFree (db , * pzIdxDbSName );
970+ return SQLITE_NOMEM_BKPT ;
971+ }
972+ return SQLITE_OK ;
973+ }
974+
943975int vectorIndexSearch (
944976 sqlite3 * db ,
945- const char * zDbSName ,
946977 int argc ,
947978 sqlite3_value * * argv ,
948979 VectorOutRows * pRows ,
@@ -952,7 +983,11 @@ int vectorIndexSearch(
952983) {
953984 int type , dims , k , rc ;
954985 double kDouble ;
955- const char * zIdxName ;
986+ const char * zIdxFullName ;
987+ char * zIdxDbSNameAlloc = NULL ; // allocated managed schema name string - must be freed if not null
988+ char * zIdxNameAlloc = NULL ; // allocated managed index name string - must be freed if not null
989+ const char * zIdxDbSName = NULL ; // schema name of the index (can be static in cases where explicit schema is omitted - so must not be freed)
990+ const char * zIdxName = NULL ; // index name (can be extracted with sqlite3_value_text and managed by SQLite - so must not be freed)
956991 const char * zErrMsg ;
957992 Vector * pVector = NULL ;
958993 DiskAnnIndex * pDiskAnn = NULL ;
@@ -961,8 +996,6 @@ int vectorIndexSearch(
961996 VectorIdxParams idxParams ;
962997 vectorIdxParamsInit (& idxParams , NULL , 0 );
963998
964- assert ( zDbSName != NULL );
965-
966999 if ( argc != 3 ){
9671000 * pzErrMsg = sqlite3_mprintf ("vector index(search): got %d parameters, expected 3" , argc );
9681001 rc = SQLITE_ERROR ;
@@ -1013,19 +1046,33 @@ int vectorIndexSearch(
10131046 rc = SQLITE_ERROR ;
10141047 goto out ;
10151048 }
1016- zIdxName = (const char * )sqlite3_value_text (argv [0 ]);
1017- if ( vectorIndexGetParameters (db , zIdxName , & idxParams ) != 0 ){
1049+ zIdxFullName = (const char * )sqlite3_value_text (argv [0 ]);
1050+ rc = getIndexNameParts (db , zIdxFullName , & zIdxDbSNameAlloc , & zIdxNameAlloc );
1051+ if ( rc != SQLITE_OK ){
1052+ * pzErrMsg = sqlite3_mprintf ("vector index(search): failed to parse index name" );
1053+ goto out ;
1054+ }
1055+ assert ( (zIdxDbSNameAlloc == NULL && zIdxNameAlloc == NULL ) || (zIdxDbSNameAlloc != NULL && zIdxNameAlloc != NULL ) );
1056+ if ( zIdxDbSNameAlloc == NULL && zIdxNameAlloc == NULL ){
1057+ zIdxDbSName = "main" ;
1058+ zIdxName = zIdxFullName ;
1059+ } else {
1060+ zIdxDbSName = zIdxDbSNameAlloc ;
1061+ zIdxName = zIdxNameAlloc ;
1062+ }
1063+
1064+ if ( vectorIndexGetParameters (db , zIdxDbSName , zIdxName , & idxParams ) != 0 ){
10181065 * pzErrMsg = sqlite3_mprintf ("vector index(search): failed to parse vector index parameters" );
10191066 rc = SQLITE_ERROR ;
10201067 goto out ;
10211068 }
1022- pIndex = sqlite3FindIndex (db , zIdxName , zDbSName );
1069+ pIndex = sqlite3FindIndex (db , zIdxName , zIdxDbSName );
10231070 if ( pIndex == NULL ){
10241071 * pzErrMsg = sqlite3_mprintf ("vector index(search): index not found" );
10251072 rc = SQLITE_ERROR ;
10261073 goto out ;
10271074 }
1028- rc = diskAnnOpenIndex (db , zDbSName , zIdxName , & idxParams , & pDiskAnn );
1075+ rc = diskAnnOpenIndex (db , zIdxDbSName , zIdxName , & idxParams , & pDiskAnn );
10291076 if ( rc != SQLITE_OK ){
10301077 * pzErrMsg = sqlite3_mprintf ("vector index(search): failed to open diskann index" );
10311078 goto out ;
@@ -1045,6 +1092,8 @@ int vectorIndexSearch(
10451092 if ( pVector != NULL ){
10461093 vectorFree (pVector );
10471094 }
1095+ sqlite3DbFree (db , zIdxNameAlloc );
1096+ sqlite3DbFree (db , zIdxDbSNameAlloc );
10481097 return rc ;
10491098}
10501099
@@ -1094,7 +1143,7 @@ int vectorIndexCursorInit(
10941143
10951144 assert ( zDbSName != NULL );
10961145
1097- if ( vectorIndexGetParameters (db , zIndexName , & params ) != 0 ){
1146+ if ( vectorIndexGetParameters (db , zDbSName , zIndexName , & params ) != 0 ){
10981147 return SQLITE_ERROR ;
10991148 }
11001149 pCursor = sqlite3DbMallocZero (db , sizeof (VectorIdxCursor ));
0 commit comments