Fix vector table errors

This commit is contained in:
Benjamin Toby 2026-04-05 09:34:18 +01:00
parent 259a684136
commit f500c52ee5
8 changed files with 74 additions and 28 deletions

View File

@ -6,6 +6,7 @@ import { select } from "@inquirer/prompts";
import { Database } from "bun:sqlite"; import { Database } from "bun:sqlite";
import listTables from "./list-tables"; import listTables from "./list-tables";
import runSQL from "./run-sql"; import runSQL from "./run-sql";
import * as sqliteVec from "sqlite-vec";
export default function () { export default function () {
return new Command("admin") return new Command("admin")
.description("View Tables and Data, Run SQL Queries, Etc.") .description("View Tables and Data, Run SQL Queries, Etc.")
@ -13,6 +14,7 @@ export default function () {
const { config } = await init(); const { config } = await init();
const { db_file_path } = grabDBDir({ config }); const { db_file_path } = grabDBDir({ config });
const db = new Database(db_file_path); const db = new Database(db_file_path);
sqliteVec.load(db);
console.log(chalk.bold(chalk.blue("\nBun SQLite Admin\n"))); console.log(chalk.bold(chalk.blue("\nBun SQLite Admin\n")));
try { try {
while (true) { while (true) {

View File

@ -44,6 +44,7 @@ declare class SQLiteSchemaManager {
* Add a new column to existing table * Add a new column to existing table
*/ */
private addColumn; private addColumn;
private checkIfTableExists;
/** /**
* Recreate table (for complex schema changes) * Recreate table (for complex schema changes)
*/ */

View File

@ -102,13 +102,10 @@ class SQLiteSchemaManager {
await this.createTable(table); await this.createTable(table);
this.insertDbManagerTable(table.tableName); this.insertDbManagerTable(table.tableName);
} }
else if (!table.isVector) { else {
// Update existing table // Update existing table
await this.updateTable(table); await this.updateTable(table);
} }
else {
return;
}
// Sync indexes // Sync indexes
await this.syncIndexes(table); await this.syncIndexes(table);
} }
@ -133,9 +130,9 @@ class SQLiteSchemaManager {
const columns = []; const columns = [];
const foreignKeys = []; const foreignKeys = [];
for (const field of new_table.fields) { for (const field of new_table.fields) {
const columnDef = this.buildColumnDefinition(field); const columnDef = this.buildColumnDefinition(field, table.isVector);
columns.push(columnDef); columns.push(columnDef);
if (field.foreignKey) { if (field.foreignKey && !table.isVector) {
foreignKeys.push(this.buildForeignKeyConstraint(field)); foreignKeys.push(this.buildForeignKeyConstraint(field));
} }
} }
@ -224,6 +221,12 @@ class SQLiteSchemaManager {
const sql = `ALTER TABLE "${tableName}" ADD COLUMN ${cleanDef}`; const sql = `ALTER TABLE "${tableName}" ADD COLUMN ${cleanDef}`;
this.db.run(sql); this.db.run(sql);
} }
checkIfTableExists(table) {
const tableExists = this.db
.query(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)
.get(table);
return Boolean(tableExists?.name);
}
/** /**
* Recreate table (for complex schema changes) * Recreate table (for complex schema changes)
*/ */
@ -232,11 +235,14 @@ class SQLiteSchemaManager {
if (!this.recreate_vector_table) { if (!this.recreate_vector_table) {
return; return;
} }
console.log(`Recreating vector table: ${table.tableName}`); const does_table_exist = this.checkIfTableExists(table.tableName);
const existingRows = this.db let existingRows = [];
.query(`SELECT * FROM "${table.tableName}"`) if (does_table_exist) {
.all(); existingRows = this.db
this.db.run(`DROP TABLE "${table.tableName}"`); .query(`SELECT * FROM "${table.tableName}"`)
.all();
this.db.run(`DROP TABLE "${table.tableName}"`);
}
await this.createTable(table); await this.createTable(table);
if (existingRows.length > 0) { if (existingRows.length > 0) {
for (let i = 0; i < existingRows.length; i++) { for (let i = 0; i < existingRows.length; i++) {
@ -274,7 +280,7 @@ class SQLiteSchemaManager {
/** /**
* Build column definition SQL * Build column definition SQL
*/ */
buildColumnDefinition(field) { buildColumnDefinition(field, is_vector) {
if (!field.fieldName) { if (!field.fieldName) {
throw new Error("Field name is required"); throw new Error("Field name is required");
} }
@ -284,7 +290,12 @@ class SQLiteSchemaManager {
const parts = [fieldName]; const parts = [fieldName];
// Data type mapping // Data type mapping
const dataType = this.mapDataType(field); const dataType = this.mapDataType(field);
parts.push(dataType); if (dataType == "BLOB") {
parts.push("FLOAT[128]");
}
else {
parts.push(dataType);
}
// Primary key // Primary key
if (field.primaryKey) { if (field.primaryKey) {
parts.push("PRIMARY KEY"); parts.push("PRIMARY KEY");

View File

@ -85,6 +85,9 @@ export interface BUN_SQLITE_TableSchemaType {
* If this is a vector table * If this is a vector table
*/ */
isVector?: boolean; isVector?: boolean;
/**
* Type of vector. Defaults to `vec0`
*/
vectorType?: string; vectorType?: string;
} }
/** /**

View File

@ -1,6 +1,6 @@
{ {
"name": "@moduletrace/bun-sqlite", "name": "@moduletrace/bun-sqlite",
"version": "1.0.24", "version": "1.0.25",
"description": "SQLite manager for Bun", "description": "SQLite manager for Bun",
"author": "Benjamin Toby", "author": "Benjamin Toby",
"main": "dist/index.js", "main": "dist/index.js",

View File

@ -6,6 +6,7 @@ import { select } from "@inquirer/prompts";
import { Database } from "bun:sqlite"; import { Database } from "bun:sqlite";
import listTables from "./list-tables"; import listTables from "./list-tables";
import runSQL from "./run-sql"; import runSQL from "./run-sql";
import * as sqliteVec from "sqlite-vec";
export default function () { export default function () {
return new Command("admin") return new Command("admin")
@ -15,6 +16,8 @@ export default function () {
const { db_file_path } = grabDBDir({ config }); const { db_file_path } = grabDBDir({ config });
const db = new Database(db_file_path); const db = new Database(db_file_path);
sqliteVec.load(db);
console.log(chalk.bold(chalk.blue("\nBun SQLite Admin\n"))); console.log(chalk.bold(chalk.blue("\nBun SQLite Admin\n")));
try { try {

View File

@ -5,6 +5,7 @@ import _ from "lodash";
import DbClient from "."; import DbClient from ".";
import type { import type {
BUN_SQLITE_DatabaseSchemaType, BUN_SQLITE_DatabaseSchemaType,
BUN_SQLITE_DATATYPES,
BUN_SQLITE_FieldSchemaType, BUN_SQLITE_FieldSchemaType,
BUN_SQLITE_TableSchemaType, BUN_SQLITE_TableSchemaType,
} from "../../types"; } from "../../types";
@ -159,11 +160,9 @@ class SQLiteSchemaManager {
// Create new table // Create new table
await this.createTable(table); await this.createTable(table);
this.insertDbManagerTable(table.tableName); this.insertDbManagerTable(table.tableName);
} else if (!table.isVector) { } else {
// Update existing table // Update existing table
await this.updateTable(table); await this.updateTable(table);
} else {
return;
} }
// Sync indexes // Sync indexes
@ -203,10 +202,10 @@ class SQLiteSchemaManager {
const foreignKeys: string[] = []; const foreignKeys: string[] = [];
for (const field of new_table.fields) { for (const field of new_table.fields) {
const columnDef = this.buildColumnDefinition(field); const columnDef = this.buildColumnDefinition(field, table.isVector);
columns.push(columnDef); columns.push(columnDef);
if (field.foreignKey) { if (field.foreignKey && !table.isVector) {
foreignKeys.push(this.buildForeignKeyConstraint(field)); foreignKeys.push(this.buildForeignKeyConstraint(field));
} }
} }
@ -326,6 +325,16 @@ class SQLiteSchemaManager {
this.db.run(sql); this.db.run(sql);
} }
private checkIfTableExists(table: string) {
const tableExists = this.db
.query(
`SELECT name FROM sqlite_master WHERE type='table' AND name=?`,
)
.get(table) as any;
return Boolean(tableExists?.name);
}
/** /**
* Recreate table (for complex schema changes) * Recreate table (for complex schema changes)
*/ */
@ -337,13 +346,18 @@ class SQLiteSchemaManager {
return; return;
} }
console.log(`Recreating vector table: ${table.tableName}`); const does_table_exist = this.checkIfTableExists(table.tableName);
const existingRows = this.db let existingRows: { [k: string]: any }[] = [];
.query(`SELECT * FROM "${table.tableName}"`)
.all() as { [k: string]: any }[]; if (does_table_exist) {
existingRows = this.db
.query(`SELECT * FROM "${table.tableName}"`)
.all() as { [k: string]: any }[];
this.db.run(`DROP TABLE "${table.tableName}"`);
}
this.db.run(`DROP TABLE "${table.tableName}"`);
await this.createTable(table); await this.createTable(table);
if (existingRows.length > 0) { if (existingRows.length > 0) {
@ -404,7 +418,10 @@ class SQLiteSchemaManager {
/** /**
* Build column definition SQL * Build column definition SQL
*/ */
private buildColumnDefinition(field: BUN_SQLITE_FieldSchemaType): string { private buildColumnDefinition(
field: BUN_SQLITE_FieldSchemaType,
is_vector?: boolean,
): string {
if (!field.fieldName) { if (!field.fieldName) {
throw new Error("Field name is required"); throw new Error("Field name is required");
} }
@ -417,7 +434,11 @@ class SQLiteSchemaManager {
// Data type mapping // Data type mapping
const dataType = this.mapDataType(field); const dataType = this.mapDataType(field);
parts.push(dataType); if (dataType == "BLOB") {
parts.push("FLOAT[128]");
} else {
parts.push(dataType);
}
// Primary key // Primary key
if (field.primaryKey) { if (field.primaryKey) {
@ -459,13 +480,15 @@ class SQLiteSchemaManager {
/** /**
* Map DSQL data types to SQLite types * Map DSQL data types to SQLite types
*/ */
private mapDataType(field: BUN_SQLITE_FieldSchemaType): string { private mapDataType(
field: BUN_SQLITE_FieldSchemaType,
): (typeof BUN_SQLITE_DATATYPES)[number]["value"] {
const dataType = field.dataType?.toLowerCase() || "text"; const dataType = field.dataType?.toLowerCase() || "text";
const vectorSize = field.vectorSize || 1536; const vectorSize = field.vectorSize || 1536;
// Vector Embeddings // Vector Embeddings
if (field.isVector) { if (field.isVector) {
return `FLOAT[${vectorSize}]`; return `FLOAT[${vectorSize}]` as any;
} }
// Integer types // Integer types

View File

@ -104,6 +104,9 @@ export interface BUN_SQLITE_TableSchemaType {
* If this is a vector table * If this is a vector table
*/ */
isVector?: boolean; isVector?: boolean;
/**
* Type of vector. Defaults to `vec0`
*/
vectorType?: string; vectorType?: string;
} }