@@ -436,8 +436,8 @@ int diskAnnCreateIndex(
436436 int type , dims ;
437437 u64 maxNeighborsParam , blockSizeBytes ;
438438 char * zSql ;
439- char columnSqlDefs [DISKANN_SQL_RENDER_LIMIT ]; // definition of columns (e.g. index_key INTEGER BINARY, index_key1 TEXT, ...)
440- char columnSqlNames [DISKANN_SQL_RENDER_LIMIT ]; // just column names (e.g. index_key, index_key1, index_key2, ...)
439+ char columnSqlDefs [VECTOR_INDEX_SQL_RENDER_LIMIT ]; // definition of columns (e.g. index_key INTEGER BINARY, index_key1 TEXT, ...)
440+ char columnSqlNames [VECTOR_INDEX_SQL_RENDER_LIMIT ]; // just column names (e.g. index_key, index_key1, index_key2, ...)
441441 if ( vectorIdxKeyDefsRender (pKey , "index_key" , columnSqlDefs , sizeof (columnSqlDefs )) != 0 ){
442442 return SQLITE_ERROR ;
443443 }
@@ -490,14 +490,29 @@ int diskAnnCreateIndex(
490490 return SQLITE_ERROR ;
491491 }
492492 }
493- zSql = sqlite3MPrintf (
494- db ,
495- "CREATE TABLE IF NOT EXISTS \"%w\".%s_shadow (%s, data BLOB, PRIMARY KEY (%s))" ,
496- zDbSName ,
497- zIdxName ,
498- columnSqlDefs ,
499- columnSqlNames
500- );
493+ // we want to preserve rowid - so it must be explicit in the schema
494+ // also, we don't want to store redundant set of fields - so the strategy is like that:
495+ // 1. If we have single PK with INTEGER affinity and BINARY collation we only need single PK of same type
496+ // 2. In other case we need rowid PK and unique index over other fields
497+ if ( vectorIdxKeyRowidLike (pKey ) ){
498+ zSql = sqlite3MPrintf (
499+ db ,
500+ "CREATE TABLE IF NOT EXISTS \"%w\".%s_shadow (%s, data BLOB, PRIMARY KEY (%s))" ,
501+ zDbSName ,
502+ zIdxName ,
503+ columnSqlDefs ,
504+ columnSqlNames
505+ );
506+ }else {
507+ zSql = sqlite3MPrintf (
508+ db ,
509+ "CREATE TABLE IF NOT EXISTS \"%w\".%s_shadow (rowid INTEGER PRIMARY KEY, %s, data BLOB, UNIQUE (%s))" ,
510+ zDbSName ,
511+ zIdxName ,
512+ columnSqlDefs ,
513+ columnSqlNames
514+ );
515+ }
501516 rc = sqlite3_exec (db , zSql , 0 , 0 , 0 );
502517 sqlite3DbFree (db , zSql );
503518 return rc ;
@@ -570,8 +585,8 @@ static int diskAnnGetShadowRowid(const DiskAnnIndex *pIndex, const VectorInRow *
570585 sqlite3_stmt * pStmt = NULL ;
571586 char * zSql = NULL ;
572587
573- char columnSqlNames [DISKANN_SQL_RENDER_LIMIT ]; // just column names (e.g. index_key, index_key1, index_key2, ...)
574- char columnSqlPlaceholders [DISKANN_SQL_RENDER_LIMIT ]; // just placeholders (e.g. ?,?,?, ...)
588+ char columnSqlNames [VECTOR_INDEX_SQL_RENDER_LIMIT ]; // just column names (e.g. index_key, index_key1, index_key2, ...)
589+ char columnSqlPlaceholders [VECTOR_INDEX_SQL_RENDER_LIMIT ]; // just placeholders (e.g. ?,?,?, ...)
575590 if ( vectorIdxKeyNamesRender (pInRow -> nKeys , "index_key" , columnSqlNames , sizeof (columnSqlNames )) != 0 ){
576591 rc = SQLITE_ERROR ;
577592 goto out ;
@@ -628,7 +643,7 @@ static int diskAnnGetShadowRowKeys(const DiskAnnIndex *pIndex, u64 nRowid, const
628643 sqlite3_stmt * pStmt = NULL ;
629644 char * zSql = NULL ;
630645
631- char columnSqlNames [DISKANN_SQL_RENDER_LIMIT ]; // just column names (e.g. index_key, index_key1, index_key2, ...)
646+ char columnSqlNames [VECTOR_INDEX_SQL_RENDER_LIMIT ]; // just column names (e.g. index_key, index_key1, index_key2, ...)
632647 if ( vectorIdxKeyNamesRender (pKey -> nKeyColumns , "index_key" , columnSqlNames , sizeof (columnSqlNames )) != 0 ){
633648 rc = SQLITE_ERROR ;
634649 goto out ;
@@ -682,15 +697,19 @@ static int diskAnnInsertShadowRow(const DiskAnnIndex *pIndex, const VectorInRow
682697 sqlite3_stmt * pStmt = NULL ;
683698 char * zSql = NULL ;
684699
685- char columnSqlPlaceholders [DISKANN_SQL_RENDER_LIMIT ]; // just placeholders (e.g. ?,?,?, ...)
700+ char columnSqlPlaceholders [VECTOR_INDEX_SQL_RENDER_LIMIT ]; // just placeholders (e.g. ?,?,?, ...)
701+ char columnSqlNames [VECTOR_INDEX_SQL_RENDER_LIMIT ]; // just column names (e.g. index_key, index_key1, index_key2, ...)
686702 if ( vectorInRowPlaceholderRender (pVectorInRow , columnSqlPlaceholders , sizeof (columnSqlPlaceholders )) != 0 ){
687703 rc = SQLITE_ERROR ;
688704 goto out ;
689705 }
706+ if ( vectorIdxKeyNamesRender (pVectorInRow -> nKeys , "index_key" , columnSqlNames , sizeof (columnSqlNames )) != 0 ){
707+ return SQLITE_ERROR ;
708+ }
690709 zSql = sqlite3MPrintf (
691710 pIndex -> db ,
692- "INSERT INTO \"%w\".%s VALUES (%s, ?) RETURNING rowid" ,
693- pIndex -> zDbSName , pIndex -> zShadow , columnSqlPlaceholders
711+ "INSERT INTO \"%w\".%s(%s, data) VALUES (%s, ?) RETURNING rowid" ,
712+ pIndex -> zDbSName , pIndex -> zShadow , columnSqlNames , columnSqlPlaceholders
694713 );
695714 if ( zSql == NULL ){
696715 rc = SQLITE_NOMEM_BKPT ;
@@ -1247,7 +1266,7 @@ int diskAnnSearch(
12471266 goto out ;
12481267 }
12491268 nOutRows = MIN (k , ctx .nCandidates );
1250- rc = vectorOutRowsAlloc (pIndex -> db , pRows , nOutRows , pKey -> nKeyColumns , pKey -> aKeyAffinity [ 0 ] );
1269+ rc = vectorOutRowsAlloc (pIndex -> db , pRows , nOutRows , pKey -> nKeyColumns , vectorIdxKeyRowidLike ( pKey ) );
12511270 if ( rc != SQLITE_OK ){
12521271 * pzErrMsg = sqlite3_mprintf ("vector index(search): failed to allocate output rows" );
12531272 goto out ;
0 commit comments