Change table update strategy to full recreation every time
This commit is contained in:
parent
b46ff44dc7
commit
685d47d91f
135
dist/lib/sqlite/db-schema-manager.js
vendored
135
dist/lib/sqlite/db-schema-manager.js
vendored
@ -102,7 +102,9 @@ class SQLiteSchemaManager {
|
||||
* Create a new table
|
||||
*/
|
||||
async createTable(table) {
|
||||
console.log(`Creating table: ${table.tableName}`);
|
||||
if (!table.tableName.match(/_temp_\d+$/)) {
|
||||
console.log(`Creating table: ${table.tableName}`);
|
||||
}
|
||||
let new_table = _.cloneDeep(table);
|
||||
if (new_table.parentTableName) {
|
||||
const parent_table = this.db_schema.tables.find((t) => t.tableName === new_table.parentTableName);
|
||||
@ -148,26 +150,42 @@ class SQLiteSchemaManager {
|
||||
*/
|
||||
async updateTable(table) {
|
||||
console.log(`Updating table: ${table.tableName}`);
|
||||
const existingColumns = this.getTableColumns(table.tableName);
|
||||
const schemaColumns = table.fields.map((f) => f.fieldName || "");
|
||||
// SQLite has limited ALTER TABLE support
|
||||
// We need to use the recreation strategy for complex changes
|
||||
const columnsToAdd = table.fields.filter((f) => f.fieldName &&
|
||||
!existingColumns.find((c) => c.name == f.fieldName && c.type == this.mapDataType(f)));
|
||||
const columnsToRemove = existingColumns.filter((c) => !schemaColumns.includes(c.name));
|
||||
const columnsToUpdate = table.fields.filter((f) => f.fieldName &&
|
||||
f.updatedField &&
|
||||
existingColumns.find((c) => c.name == f.fieldName && c.type == this.mapDataType(f)));
|
||||
// Simple case: only adding columns
|
||||
if (columnsToRemove.length === 0 && columnsToUpdate.length === 0) {
|
||||
for (const field of columnsToAdd) {
|
||||
await this.addColumn(table.tableName, field);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Complex case: need to recreate table
|
||||
await this.recreateTable(table);
|
||||
}
|
||||
// const existingColumns = this.getTableColumns(table.tableName);
|
||||
// const schemaColumns = table.fields.map((f) => f.fieldName || "");
|
||||
// // SQLite has limited ALTER TABLE support
|
||||
// // We need to use the recreation strategy for complex changes
|
||||
// const columnsToAdd = table.fields.filter(
|
||||
// (f) =>
|
||||
// f.fieldName &&
|
||||
// !existingColumns.find(
|
||||
// (c) =>
|
||||
// c.name == f.fieldName && c.type == this.mapDataType(f),
|
||||
// ),
|
||||
// );
|
||||
// // const columnsToRemove = existingColumns.filter(
|
||||
// // (c) => !schemaColumns.includes(c.name),
|
||||
// // );
|
||||
// // const columnsToUpdate = table.fields.filter(
|
||||
// // (f) =>
|
||||
// // f.fieldName &&
|
||||
// // f.updatedField &&
|
||||
// // existingColumns.find(
|
||||
// // (c) =>
|
||||
// // c.name == f.fieldName && c.type == this.mapDataType(f),
|
||||
// // ),
|
||||
// // );
|
||||
// for (const field of columnsToAdd) {
|
||||
// await this.addColumn(table.tableName, field);
|
||||
// }
|
||||
// // // Simple case: only adding columns
|
||||
// // if (columnsToRemove.length === 0 && columnsToUpdate.length === 0) {
|
||||
// // for (const field of columnsToAdd) {
|
||||
// // await this.addColumn(table.tableName, field);
|
||||
// // }
|
||||
// // } else {
|
||||
// // // Complex case: need to recreate table
|
||||
// // }
|
||||
await this.recreateTable(table);
|
||||
}
|
||||
/**
|
||||
* Get existing columns for a table
|
||||
@ -382,79 +400,4 @@ class SQLiteSchemaManager {
|
||||
this.db.close();
|
||||
}
|
||||
}
|
||||
// Example usage
|
||||
async function main() {
|
||||
const schema = {
|
||||
dbName: "example_db",
|
||||
tables: [
|
||||
{
|
||||
tableName: "users",
|
||||
tableDescription: "User accounts",
|
||||
fields: [
|
||||
{
|
||||
fieldName: "id",
|
||||
dataType: "INTEGER",
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
{
|
||||
fieldName: "username",
|
||||
dataType: "TEXT",
|
||||
notNullValue: true,
|
||||
unique: true,
|
||||
},
|
||||
{
|
||||
fieldName: "email",
|
||||
dataType: "TEXT",
|
||||
notNullValue: true,
|
||||
},
|
||||
{
|
||||
fieldName: "created_at",
|
||||
dataType: "TEXT",
|
||||
defaultValueLiteral: "CURRENT_TIMESTAMP",
|
||||
},
|
||||
],
|
||||
indexes: [
|
||||
{
|
||||
indexName: "idx_users_email",
|
||||
indexType: "regular",
|
||||
indexTableFields: [
|
||||
{ value: "email", dataType: "TEXT" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
tableName: "posts",
|
||||
fields: [
|
||||
{
|
||||
fieldName: "id",
|
||||
dataType: "INTEGER",
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
{
|
||||
fieldName: "user_id",
|
||||
dataType: "INTEGER",
|
||||
notNullValue: true,
|
||||
foreignKey: {
|
||||
destinationTableName: "users",
|
||||
destinationTableColumnName: "id",
|
||||
cascadeDelete: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: "title",
|
||||
dataType: "TEXT",
|
||||
notNullValue: true,
|
||||
},
|
||||
{
|
||||
fieldName: "content",
|
||||
dataType: "TEXT",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
export { SQLiteSchemaManager };
|
||||
|
||||
1
dist/types/index.d.ts
vendored
1
dist/types/index.d.ts
vendored
@ -110,7 +110,6 @@ export type BUN_SQLITE_FieldSchemaType = {
|
||||
fieldName?: string;
|
||||
fieldDescription?: string;
|
||||
originName?: string;
|
||||
updatedField?: boolean;
|
||||
dataType: (typeof BUN_SQLITE_DATATYPES)[number]["value"];
|
||||
nullValue?: boolean;
|
||||
notNullValue?: boolean;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@moduletrace/bun-sqlite",
|
||||
"version": "1.0.19",
|
||||
"version": "1.0.20",
|
||||
"description": "SQLite manager for Bun",
|
||||
"author": "Benjamin Toby",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@ -155,7 +155,9 @@ class SQLiteSchemaManager {
|
||||
private async createTable(
|
||||
table: BUN_SQLITE_TableSchemaType,
|
||||
): Promise<void> {
|
||||
console.log(`Creating table: ${table.tableName}`);
|
||||
if (!table.tableName.match(/_temp_\d+$/)) {
|
||||
console.log(`Creating table: ${table.tableName}`);
|
||||
}
|
||||
|
||||
let new_table = _.cloneDeep(table);
|
||||
|
||||
@ -225,42 +227,49 @@ class SQLiteSchemaManager {
|
||||
): Promise<void> {
|
||||
console.log(`Updating table: ${table.tableName}`);
|
||||
|
||||
const existingColumns = this.getTableColumns(table.tableName);
|
||||
const schemaColumns = table.fields.map((f) => f.fieldName || "");
|
||||
// const existingColumns = this.getTableColumns(table.tableName);
|
||||
// const schemaColumns = table.fields.map((f) => f.fieldName || "");
|
||||
|
||||
// SQLite has limited ALTER TABLE support
|
||||
// We need to use the recreation strategy for complex changes
|
||||
// // SQLite has limited ALTER TABLE support
|
||||
// // We need to use the recreation strategy for complex changes
|
||||
|
||||
const columnsToAdd = table.fields.filter(
|
||||
(f) =>
|
||||
f.fieldName &&
|
||||
!existingColumns.find(
|
||||
(c) =>
|
||||
c.name == f.fieldName && c.type == this.mapDataType(f),
|
||||
),
|
||||
);
|
||||
const columnsToRemove = existingColumns.filter(
|
||||
(c) => !schemaColumns.includes(c.name),
|
||||
);
|
||||
const columnsToUpdate = table.fields.filter(
|
||||
(f) =>
|
||||
f.fieldName &&
|
||||
f.updatedField &&
|
||||
existingColumns.find(
|
||||
(c) =>
|
||||
c.name == f.fieldName && c.type == this.mapDataType(f),
|
||||
),
|
||||
);
|
||||
// const columnsToAdd = table.fields.filter(
|
||||
// (f) =>
|
||||
// f.fieldName &&
|
||||
// !existingColumns.find(
|
||||
// (c) =>
|
||||
// c.name == f.fieldName && c.type == this.mapDataType(f),
|
||||
// ),
|
||||
// );
|
||||
|
||||
// Simple case: only adding columns
|
||||
if (columnsToRemove.length === 0 && columnsToUpdate.length === 0) {
|
||||
for (const field of columnsToAdd) {
|
||||
await this.addColumn(table.tableName, field);
|
||||
}
|
||||
} else {
|
||||
// Complex case: need to recreate table
|
||||
await this.recreateTable(table);
|
||||
}
|
||||
// // const columnsToRemove = existingColumns.filter(
|
||||
// // (c) => !schemaColumns.includes(c.name),
|
||||
// // );
|
||||
|
||||
// // const columnsToUpdate = table.fields.filter(
|
||||
// // (f) =>
|
||||
// // f.fieldName &&
|
||||
// // f.updatedField &&
|
||||
// // existingColumns.find(
|
||||
// // (c) =>
|
||||
// // c.name == f.fieldName && c.type == this.mapDataType(f),
|
||||
// // ),
|
||||
// // );
|
||||
|
||||
// for (const field of columnsToAdd) {
|
||||
// await this.addColumn(table.tableName, field);
|
||||
// }
|
||||
|
||||
// // // Simple case: only adding columns
|
||||
// // if (columnsToRemove.length === 0 && columnsToUpdate.length === 0) {
|
||||
// // for (const field of columnsToAdd) {
|
||||
// // await this.addColumn(table.tableName, field);
|
||||
// // }
|
||||
// // } else {
|
||||
// // // Complex case: need to recreate table
|
||||
// // }
|
||||
|
||||
await this.recreateTable(table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -558,80 +567,4 @@ class SQLiteSchemaManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Example usage
|
||||
async function main() {
|
||||
const schema: BUN_SQLITE_DatabaseSchemaType = {
|
||||
dbName: "example_db",
|
||||
tables: [
|
||||
{
|
||||
tableName: "users",
|
||||
tableDescription: "User accounts",
|
||||
fields: [
|
||||
{
|
||||
fieldName: "id",
|
||||
dataType: "INTEGER",
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
{
|
||||
fieldName: "username",
|
||||
dataType: "TEXT",
|
||||
notNullValue: true,
|
||||
unique: true,
|
||||
},
|
||||
{
|
||||
fieldName: "email",
|
||||
dataType: "TEXT",
|
||||
notNullValue: true,
|
||||
},
|
||||
{
|
||||
fieldName: "created_at",
|
||||
dataType: "TEXT",
|
||||
defaultValueLiteral: "CURRENT_TIMESTAMP",
|
||||
},
|
||||
],
|
||||
indexes: [
|
||||
{
|
||||
indexName: "idx_users_email",
|
||||
indexType: "regular",
|
||||
indexTableFields: [
|
||||
{ value: "email", dataType: "TEXT" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
tableName: "posts",
|
||||
fields: [
|
||||
{
|
||||
fieldName: "id",
|
||||
dataType: "INTEGER",
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
{
|
||||
fieldName: "user_id",
|
||||
dataType: "INTEGER",
|
||||
notNullValue: true,
|
||||
foreignKey: {
|
||||
destinationTableName: "users",
|
||||
destinationTableColumnName: "id",
|
||||
cascadeDelete: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: "title",
|
||||
dataType: "TEXT",
|
||||
notNullValue: true,
|
||||
},
|
||||
{
|
||||
fieldName: "content",
|
||||
dataType: "TEXT",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export { SQLiteSchemaManager };
|
||||
|
||||
@ -111,7 +111,7 @@ export type BUN_SQLITE_FieldSchemaType = {
|
||||
fieldName?: string;
|
||||
fieldDescription?: string;
|
||||
originName?: string;
|
||||
updatedField?: boolean;
|
||||
// updatedField?: boolean;
|
||||
dataType: (typeof BUN_SQLITE_DATATYPES)[number]["value"];
|
||||
nullValue?: boolean;
|
||||
notNullValue?: boolean;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user