Remove table.isVector feature altogether. All vector features are handled per column

This commit is contained in:
2026-08-05 11:01:58 +01:00
parent 000d40b4cb
commit 4f203ce4e7
18 changed files with 17 additions and 136 deletions
+2
View File
@@ -34,3 +34,5 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
/test /test
.vscode .vscode
.dump .dump
/.bun-mariadb
-2
View File
@@ -241,7 +241,6 @@ interface BUN_MARIADB_TableSchemaType {
parentTableName?: string; // inherit / merge fields from another table parentTableName?: string; // inherit / merge fields from another table
tableNameOld?: string; // rename: old name triggers ALTER TABLE RENAME tableNameOld?: string; // rename: old name triggers ALTER TABLE RENAME
collation?: "utf8mb4_bin" | "utf8mb4_unicode_520_ci"; collation?: "utf8mb4_bin" | "utf8mb4_unicode_520_ci";
isVector?: boolean; // mark as vector-oriented table
} }
``` ```
@@ -743,7 +742,6 @@ MariaDB native `VECTOR(n)` columns and `VECTOR INDEX` are supported (MariaDB 11.
```ts ```ts
{ {
tableName: "documents", tableName: "documents",
isVector: true,
fields: [ fields: [
{ {
fieldName: "embedding", fieldName: "embedding",
+3 -1
View File
@@ -26,7 +26,9 @@ export default async function DbSQL({ sql, values }) {
const singleRaw = res.single_res; const singleRaw = res.single_res;
return { return {
...res, ...res,
success: true, success: isSelect
? Boolean(single_res) || Boolean(payload?.[0])
: true,
payload, payload,
single_res, single_res,
debug: { debug: {
+1 -1
View File
@@ -15,7 +15,7 @@ export default async function createTable({ table, config, }) {
if (field.primaryKey && field.fieldName) { if (field.primaryKey && field.fieldName) {
primaryKeys.push(field.fieldName); primaryKeys.push(field.fieldName);
} }
if (field.foreignKey && !table.isVector) { if (field.foreignKey) {
foreignKeys.push(buildForeignKeyConstraint(field, table.tableName)); foreignKeys.push(buildForeignKeyConstraint(field, table.tableName));
} }
} }
+1 -2
View File
@@ -1,7 +1,6 @@
import type { BUN_MARIADB_TableSchemaType, BunMariaDBConfig } from "../../types"; import type { BUN_MARIADB_TableSchemaType, BunMariaDBConfig } from "../../types";
/** /**
* Full table rebuild. For `isVector` tables this drops and recreates in place * Full table rebuild using a temp-table swap (preserving rows when possible).
* (preserving rows when possible). For regular tables it uses a temp-table swap.
*/ */
export default function recreateTable({ table, config, }: { export default function recreateTable({ table, config, }: {
table: BUN_MARIADB_TableSchemaType; table: BUN_MARIADB_TableSchemaType;
+1 -44
View File
@@ -13,8 +13,7 @@ async function checkIfTableExists({ tableName, config, }) {
return Boolean(rows[0]?.table_exists); return Boolean(rows[0]?.table_exists);
} }
/** /**
* Full table rebuild. For `isVector` tables this drops and recreates in place * Full table rebuild using a temp-table swap (preserving rows when possible).
* (preserving rows when possible). For regular tables it uses a temp-table swap.
*/ */
export default async function recreateTable({ table, config, }) { export default async function recreateTable({ table, config, }) {
const doesTableExist = await checkIfTableExists({ const doesTableExist = await checkIfTableExists({
@@ -25,48 +24,6 @@ export default async function recreateTable({ table, config, }) {
await createTable({ table, config }); await createTable({ table, config });
return; return;
} }
/**
* Vector tables: drop + recreate + reinsert (MariaDB VECTOR INDEX / dim
* changes are not reliably alterable in place).
*/
if (table.isVector) {
console.log(`Recreating vector table: ${table.tableName}`);
const existingRows = await querySchemaRows({
query: `SELECT * FROM ${MariaDBQuoteGen(table.tableName)}`,
config,
});
await runSchemaQuery({ query: `SET FOREIGN_KEY_CHECKS = 0`, config });
try {
await runSchemaQuery({
query: `DROP TABLE IF EXISTS ${MariaDBQuoteGen(table.tableName)}`,
config,
});
await createTable({ table, config });
}
finally {
await runSchemaQuery({ query: `SET FOREIGN_KEY_CHECKS = 1`, config });
}
if (existingRows.length > 0) {
const schemaFieldNames = new Set((table.fields || [])
.map((f) => f.fieldName)
.filter((n) => Boolean(n)));
for (const row of existingRows) {
const columns = Object.keys(row).filter((c) => schemaFieldNames.has(c));
if (columns.length === 0)
continue;
const placeholders = columns.map(() => "?").join(", ");
const columnList = columns
.map((c) => MariaDBQuoteGen(c))
.join(", ");
await runSchemaQuery({
query: `INSERT INTO ${MariaDBQuoteGen(table.tableName)} (${columnList}) VALUES (${placeholders})`,
values: columns.map((c) => row[c] ?? null),
config,
});
}
}
return;
}
const tempTableName = `${table.tableName}_temp_${Date.now()}`; const tempTableName = `${table.tableName}_temp_${Date.now()}`;
const backupOldTableName = `${table.tableName}_old_${Date.now()}`; const backupOldTableName = `${table.tableName}_old_${Date.now()}`;
const existingColumns = await getTableColumns({ const existingColumns = await getTableColumns({
-1
View File
@@ -23,7 +23,6 @@ export default function resolveTable(table, db_schema) {
tableName: table.tableName, tableName: table.tableName,
tableDescription: table.tableDescription || parentTable.tableDescription, tableDescription: table.tableDescription || parentTable.tableDescription,
collation: table.collation || parentTable.collation, collation: table.collation || parentTable.collation,
isVector: table.isVector !== undefined ? table.isVector : parentTable.isVector,
fields: Array.from(mergedFieldsMap.values()), fields: Array.from(mergedFieldsMap.values()),
indexes: _.uniqBy([...(parentTable.indexes || []), ...(table.indexes || [])], "indexName"), indexes: _.uniqBy([...(parentTable.indexes || []), ...(table.indexes || [])], "indexName"),
uniqueConstraints: [ uniqueConstraints: [
-3
View File
@@ -15,9 +15,6 @@ function rulesMatch(live, desired) {
ruleIsCascade(live.updateRule) === desired.cascadeUpdate); ruleIsCascade(live.updateRule) === desired.cascadeUpdate);
} }
export function grabDesiredForeignKeys(table) { export function grabDesiredForeignKeys(table) {
if (table.isVector) {
return [];
}
const desired = []; const desired = [];
for (const field of table.fields || []) { for (const field of table.fields || []) {
const fk = field.foreignKey; const fk = field.foreignKey;
-2
View File
@@ -6,8 +6,6 @@ import { grabDesiredUniqueConstraints } from "./sync-unique-constraints";
function isVectorIndexDef(index, table) { function isVectorIndexDef(index, table) {
if (index.indexType === "VECTOR") if (index.indexType === "VECTOR")
return true; return true;
if (table.isVector)
return true;
const firstFieldName = index.indexTableFields?.[0]; const firstFieldName = index.indexTableFields?.[0];
if (!firstFieldName) if (!firstFieldName)
return false; return false;
-4
View File
@@ -74,10 +74,6 @@ export interface BUN_MARIADB_TableSchemaType {
*/ */
childTableDbId?: string | number; childTableDbId?: string | number;
collation?: (typeof MariaDBCollations)[number]; collation?: (typeof MariaDBCollations)[number];
/**
* If this is a vector-oriented table (native MariaDB VECTOR columns/indexes)
*/
isVector?: boolean;
} }
/** /**
* Reference object used to link a table to one of its child tables. * Reference object used to link a table to one of its child tables.
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@moduletrace/bun-mariadb", "name": "@moduletrace/bun-mariadb",
"version": "1.0.10", "version": "1.0.11",
"description": "Schema-driven MariaDB manager for Bun", "description": "Schema-driven MariaDB manager for Bun",
"author": "Benjamin Toby", "author": "Benjamin Toby",
"license": "MIT", "license": "MIT",
+3 -1
View File
@@ -39,7 +39,9 @@ export default async function DbSQL<
return { return {
...res, ...res,
success: true, success: isSelect
? Boolean(single_res) || Boolean(payload?.[0])
: true,
payload, payload,
single_res, single_res,
debug: { debug: {
+1 -1
View File
@@ -30,7 +30,7 @@ export default async function createTable({
primaryKeys.push(field.fieldName); primaryKeys.push(field.fieldName);
} }
if (field.foreignKey && !table.isVector) { if (field.foreignKey) {
foreignKeys.push( foreignKeys.push(
buildForeignKeyConstraint(field, table.tableName), buildForeignKeyConstraint(field, table.tableName),
); );
+1 -54
View File
@@ -26,8 +26,7 @@ async function checkIfTableExists({
} }
/** /**
* Full table rebuild. For `isVector` tables this drops and recreates in place * Full table rebuild using a temp-table swap (preserving rows when possible).
* (preserving rows when possible). For regular tables it uses a temp-table swap.
*/ */
export default async function recreateTable({ export default async function recreateTable({
table, table,
@@ -46,58 +45,6 @@ export default async function recreateTable({
return; return;
} }
/**
* Vector tables: drop + recreate + reinsert (MariaDB VECTOR INDEX / dim
* changes are not reliably alterable in place).
*/
if (table.isVector) {
console.log(`Recreating vector table: ${table.tableName}`);
const existingRows = await querySchemaRows<Record<string, any>>({
query: `SELECT * FROM ${MariaDBQuoteGen(table.tableName)}`,
config,
});
await runSchemaQuery({ query: `SET FOREIGN_KEY_CHECKS = 0`, config });
try {
await runSchemaQuery({
query: `DROP TABLE IF EXISTS ${MariaDBQuoteGen(table.tableName)}`,
config,
});
await createTable({ table, config });
} finally {
await runSchemaQuery({ query: `SET FOREIGN_KEY_CHECKS = 1`, config });
}
if (existingRows.length > 0) {
const schemaFieldNames = new Set(
(table.fields || [])
.map((f) => f.fieldName)
.filter((n): n is string => Boolean(n)),
);
for (const row of existingRows) {
const columns = Object.keys(row).filter((c) =>
schemaFieldNames.has(c),
);
if (columns.length === 0) continue;
const placeholders = columns.map(() => "?").join(", ");
const columnList = columns
.map((c) => MariaDBQuoteGen(c))
.join(", ");
await runSchemaQuery({
query: `INSERT INTO ${MariaDBQuoteGen(table.tableName)} (${columnList}) VALUES (${placeholders})`,
values: columns.map((c) => row[c] ?? null),
config,
});
}
}
return;
}
const tempTableName = `${table.tableName}_temp_${Date.now()}`; const tempTableName = `${table.tableName}_temp_${Date.now()}`;
const backupOldTableName = `${table.tableName}_old_${Date.now()}`; const backupOldTableName = `${table.tableName}_old_${Date.now()}`;
const existingColumns = await getTableColumns({ const existingColumns = await getTableColumns({
-2
View File
@@ -41,8 +41,6 @@ export default function resolveTable(
tableName: table.tableName, tableName: table.tableName,
tableDescription: table.tableDescription || parentTable.tableDescription, tableDescription: table.tableDescription || parentTable.tableDescription,
collation: table.collation || parentTable.collation, collation: table.collation || parentTable.collation,
isVector:
table.isVector !== undefined ? table.isVector : parentTable.isVector,
fields: Array.from(mergedFieldsMap.values()), fields: Array.from(mergedFieldsMap.values()),
indexes: _.uniqBy( indexes: _.uniqBy(
[...(parentTable.indexes || []), ...(table.indexes || [])], [...(parentTable.indexes || []), ...(table.indexes || [])],
-4
View File
@@ -57,10 +57,6 @@ function rulesMatch(
export function grabDesiredForeignKeys( export function grabDesiredForeignKeys(
table: BUN_MARIADB_TableSchemaType, table: BUN_MARIADB_TableSchemaType,
): DesiredForeignKey[] { ): DesiredForeignKey[] {
if (table.isVector) {
return [];
}
const desired: DesiredForeignKey[] = []; const desired: DesiredForeignKey[] = [];
for (const field of table.fields || []) { for (const field of table.fields || []) {
+2 -8
View File
@@ -14,7 +14,6 @@ function isVectorIndexDef(
table: BUN_MARIADB_TableSchemaType, table: BUN_MARIADB_TableSchemaType,
): boolean { ): boolean {
if (index.indexType === "VECTOR") return true; if (index.indexType === "VECTOR") return true;
if (table.isVector) return true;
const firstFieldName = index.indexTableFields?.[0]; const firstFieldName = index.indexTableFields?.[0];
if (!firstFieldName) return false; if (!firstFieldName) return false;
@@ -97,8 +96,7 @@ async function createIndex({
.map((field) => MariaDBQuoteGen(field)) .map((field) => MariaDBQuoteGen(field))
.join(", "); .join(", ");
const typeUpper = index.indexType?.toUpperCase(); const typeUpper = index.indexType?.toUpperCase();
const isSpecialType = const isSpecialType = typeUpper === "FULLTEXT" || typeUpper === "SPATIAL";
typeUpper === "FULLTEXT" || typeUpper === "SPATIAL";
const indexPrefix = isSpecialType ? `${typeUpper} ` : ""; const indexPrefix = isSpecialType ? `${typeUpper} ` : "";
const indexSuffix = const indexSuffix =
!isSpecialType && (typeUpper === "BTREE" || typeUpper === "HASH") !isSpecialType && (typeUpper === "BTREE" || typeUpper === "HASH")
@@ -199,11 +197,7 @@ export default async function syncIndexes({
const columnsMatch = const columnsMatch =
details.columns.length === schemaColumns.length && details.columns.length === schemaColumns.length &&
details.columns.every((col, idx) => col === schemaColumns[idx]); details.columns.every((col, idx) => col === schemaColumns[idx]);
const typeMatch = indexTypesMatch( const typeMatch = indexTypesMatch(details.type, schemaIndex, table);
details.type,
schemaIndex,
table,
);
if (!columnsMatch || !typeMatch) { if (!columnsMatch || !typeMatch) {
console.log(`Recreating changed index: ${indexName}`); console.log(`Recreating changed index: ${indexName}`);
-4
View File
@@ -96,10 +96,6 @@ export interface BUN_MARIADB_TableSchemaType {
*/ */
childTableDbId?: string | number; childTableDbId?: string | number;
collation?: (typeof MariaDBCollations)[number]; collation?: (typeof MariaDBCollations)[number];
/**
* If this is a vector-oriented table (native MariaDB VECTOR columns/indexes)
*/
isVector?: boolean;
} }
/** /**