@@ -10362,6 +10362,163 @@ static int vec0Rollback(sqlite3_vtab *pVTab) {
1036210362 return SQLITE_OK ;
1036310363}
1036410364
10365+ /**
10366+ * xRename implementation for vec0.
10367+ * Renames all shadow tables to match the new virtual table name,
10368+ * then updates cached table names and finalizes stale prepared statements.
10369+ */
10370+ static int vec0Rename (sqlite3_vtab * pVtab , const char * zNew ) {
10371+ vec0_vtab * p = (vec0_vtab * )pVtab ;
10372+ int rc = SQLITE_OK ;
10373+
10374+ // Build a single SQL string with ALTER TABLE RENAME for every shadow table.
10375+ sqlite3_str * s = sqlite3_str_new (p -> db );
10376+
10377+ // Core shadow tables (always present)
10378+ sqlite3_str_appendf (s ,
10379+ "ALTER TABLE \"%w\".\"%w_info\" RENAME TO \"%w_info\";" ,
10380+ p -> schemaName , p -> tableName , zNew );
10381+ sqlite3_str_appendf (s ,
10382+ "ALTER TABLE \"%w\".\"%w_rowids\" RENAME TO \"%w_rowids\";" ,
10383+ p -> schemaName , p -> tableName , zNew );
10384+ sqlite3_str_appendf (s ,
10385+ "ALTER TABLE \"%w\".\"%w_chunks\" RENAME TO \"%w_chunks\";" ,
10386+ p -> schemaName , p -> tableName , zNew );
10387+
10388+ // Auxiliary shadow table (only if auxiliary columns exist)
10389+ if (p -> numAuxiliaryColumns > 0 ) {
10390+ sqlite3_str_appendf (s ,
10391+ "ALTER TABLE \"%w\".\"%w_auxiliary\" RENAME TO \"%w_auxiliary\";" ,
10392+ p -> schemaName , p -> tableName , zNew );
10393+ }
10394+
10395+ // Per-vector-column shadow tables
10396+ for (int i = 0 ; i < p -> numVectorColumns ; i ++ ) {
10397+ sqlite3_str_appendf (s ,
10398+ "ALTER TABLE \"%w\".\"%w_vector_chunks%02d\" RENAME TO \"%w_vector_chunks%02d\";" ,
10399+ p -> schemaName , p -> tableName , i , zNew , i );
10400+
10401+ #if SQLITE_VEC_ENABLE_RESCORE
10402+ if (p -> shadowRescoreChunksNames [i ]) {
10403+ sqlite3_str_appendf (s ,
10404+ "ALTER TABLE \"%w\".\"%w_rescore_chunks%02d\" RENAME TO \"%w_rescore_chunks%02d\";" ,
10405+ p -> schemaName , p -> tableName , i , zNew , i );
10406+ sqlite3_str_appendf (s ,
10407+ "ALTER TABLE \"%w\".\"%w_rescore_vectors%02d\" RENAME TO \"%w_rescore_vectors%02d\";" ,
10408+ p -> schemaName , p -> tableName , i , zNew , i );
10409+ }
10410+ #endif
10411+
10412+ #if SQLITE_VEC_ENABLE_DISKANN
10413+ if (p -> shadowVectorsNames [i ]) {
10414+ sqlite3_str_appendf (s ,
10415+ "ALTER TABLE \"%w\".\"%w_vectors%02d\" RENAME TO \"%w_vectors%02d\";" ,
10416+ p -> schemaName , p -> tableName , i , zNew , i );
10417+ sqlite3_str_appendf (s ,
10418+ "ALTER TABLE \"%w\".\"%w_diskann_nodes%02d\" RENAME TO \"%w_diskann_nodes%02d\";" ,
10419+ p -> schemaName , p -> tableName , i , zNew , i );
10420+ sqlite3_str_appendf (s ,
10421+ "ALTER TABLE \"%w\".\"%w_diskann_buffer%02d\" RENAME TO \"%w_diskann_buffer%02d\";" ,
10422+ p -> schemaName , p -> tableName , i , zNew , i );
10423+ }
10424+ #endif
10425+ }
10426+
10427+ #if SQLITE_VEC_EXPERIMENTAL_IVF_ENABLE
10428+ for (int i = 0 ; i < p -> numVectorColumns ; i ++ ) {
10429+ if (p -> shadowIvfCellsNames [i ]) {
10430+ sqlite3_str_appendf (s ,
10431+ "ALTER TABLE \"%w\".\"%w_ivf_cells%02d\" RENAME TO \"%w_ivf_cells%02d\";" ,
10432+ p -> schemaName , p -> tableName , i , zNew , i );
10433+ }
10434+ }
10435+ #endif
10436+
10437+ // Per-metadata-column shadow tables
10438+ for (int i = 0 ; i < p -> numMetadataColumns ; i ++ ) {
10439+ sqlite3_str_appendf (s ,
10440+ "ALTER TABLE \"%w\".\"%w_metadatachunks%02d\" RENAME TO \"%w_metadatachunks%02d\";" ,
10441+ p -> schemaName , p -> tableName , i , zNew , i );
10442+ if (p -> metadata_columns [i ].kind == VEC0_METADATA_COLUMN_KIND_TEXT ) {
10443+ sqlite3_str_appendf (s ,
10444+ "ALTER TABLE \"%w\".\"%w_metadatatext%02d\" RENAME TO \"%w_metadatatext%02d\";" ,
10445+ p -> schemaName , p -> tableName , i , zNew , i );
10446+ }
10447+ }
10448+
10449+ char * zSql = sqlite3_str_finish (s );
10450+ if (!zSql ) {
10451+ return SQLITE_NOMEM ;
10452+ }
10453+
10454+ rc = sqlite3_exec (p -> db , zSql , 0 , 0 , 0 );
10455+ sqlite3_free (zSql );
10456+ if (rc != SQLITE_OK ) {
10457+ return rc ;
10458+ }
10459+
10460+ // Finalize all prepared statements — they reference old table names.
10461+ vec0_free_resources (p );
10462+
10463+ // Update cached table name
10464+ sqlite3_free (p -> tableName );
10465+ p -> tableName = sqlite3_mprintf ("%s" , zNew );
10466+ if (!p -> tableName ) return SQLITE_NOMEM ;
10467+
10468+ // Update cached shadow table names
10469+ sqlite3_free (p -> shadowRowidsName );
10470+ p -> shadowRowidsName = sqlite3_mprintf ("%s_rowids" , zNew );
10471+
10472+ sqlite3_free (p -> shadowChunksName );
10473+ p -> shadowChunksName = sqlite3_mprintf ("%s_chunks" , zNew );
10474+
10475+ for (int i = 0 ; i < p -> numVectorColumns ; i ++ ) {
10476+ sqlite3_free (p -> shadowVectorChunksNames [i ]);
10477+ p -> shadowVectorChunksNames [i ] =
10478+ sqlite3_mprintf ("%s_vector_chunks%02d" , zNew , i );
10479+
10480+ #if SQLITE_VEC_ENABLE_RESCORE
10481+ if (p -> shadowRescoreChunksNames [i ]) {
10482+ sqlite3_free (p -> shadowRescoreChunksNames [i ]);
10483+ p -> shadowRescoreChunksNames [i ] =
10484+ sqlite3_mprintf ("%s_rescore_chunks%02d" , zNew , i );
10485+ sqlite3_free (p -> shadowRescoreVectorsNames [i ]);
10486+ p -> shadowRescoreVectorsNames [i ] =
10487+ sqlite3_mprintf ("%s_rescore_vectors%02d" , zNew , i );
10488+ }
10489+ #endif
10490+
10491+ #if SQLITE_VEC_ENABLE_DISKANN
10492+ if (p -> shadowVectorsNames [i ]) {
10493+ sqlite3_free (p -> shadowVectorsNames [i ]);
10494+ p -> shadowVectorsNames [i ] =
10495+ sqlite3_mprintf ("%s_vectors%02d" , zNew , i );
10496+ sqlite3_free (p -> shadowDiskannNodesNames [i ]);
10497+ p -> shadowDiskannNodesNames [i ] =
10498+ sqlite3_mprintf ("%s_diskann_nodes%02d" , zNew , i );
10499+ }
10500+ #endif
10501+ }
10502+
10503+ #if SQLITE_VEC_EXPERIMENTAL_IVF_ENABLE
10504+ for (int i = 0 ; i < p -> numVectorColumns ; i ++ ) {
10505+ if (p -> shadowIvfCellsNames [i ]) {
10506+ sqlite3_free (p -> shadowIvfCellsNames [i ]);
10507+ p -> shadowIvfCellsNames [i ] =
10508+ sqlite3_mprintf ("%s_ivf_cells%02d" , zNew , i );
10509+ }
10510+ }
10511+ #endif
10512+
10513+ for (int i = 0 ; i < p -> numMetadataColumns ; i ++ ) {
10514+ sqlite3_free (p -> shadowMetadataChunksNames [i ]);
10515+ p -> shadowMetadataChunksNames [i ] =
10516+ sqlite3_mprintf ("%s_metadatachunks%02d" , zNew , i );
10517+ }
10518+
10519+ return SQLITE_OK ;
10520+ }
10521+
1036510522static sqlite3_module vec0Module = {
1036610523 /* iVersion */ 3 ,
1036710524 /* xCreate */ vec0Create ,
@@ -10382,7 +10539,7 @@ static sqlite3_module vec0Module = {
1038210539 /* xCommit */ vec0Commit ,
1038310540 /* xRollback */ vec0Rollback ,
1038410541 /* xFindFunction */ 0 ,
10385- /* xRename */ 0 , // https://github.com/asg017/sqlite-vec/issues/43
10542+ /* xRename */ vec0Rename ,
1038610543 /* xSavepoint */ 0 ,
1038710544 /* xRelease */ 0 ,
1038810545 /* xRollbackTo */ 0 ,
0 commit comments