fix: ALTER TABLE DROP COLUMN only modifies schema, demo page deep-copies query results to prevent reference sharing
This commit is contained in:
Vendored
+1
-8
@@ -5667,15 +5667,8 @@ class QueryExecutor {
|
|||||||
if (!schema.columns[stmt.column.name]) {
|
if (!schema.columns[stmt.column.name]) {
|
||||||
throw new DatabaseError(`Column "${stmt.column.name}" does not exist in table "${stmt.name}"`, 'COLUMN_NOT_FOUND');
|
throw new DatabaseError(`Column "${stmt.column.name}" does not exist in table "${stmt.name}"`, 'COLUMN_NOT_FOUND');
|
||||||
}
|
}
|
||||||
// 从 schema 引用上删除列定义(保留所有行数据)
|
// 只从 schema 引用上删除列定义,不碰行数据(避免引用共享导致查询结果被篡改)
|
||||||
delete schema.columns[stmt.column.name];
|
delete schema.columns[stmt.column.name];
|
||||||
// 清除已有行中该列的值(MemoryEngine 的 find 返回引用,delete 直接生效)
|
|
||||||
const rows = await this.engine.find(stmt.name, { table: stmt.name });
|
|
||||||
const colName = stmt.column.name;
|
|
||||||
for (const row of rows) {
|
|
||||||
if (colName in row)
|
|
||||||
delete row[colName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async executeTruncateTable(stmt) {
|
async executeTruncateTable(stmt) {
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-8
@@ -5663,15 +5663,8 @@ class QueryExecutor {
|
|||||||
if (!schema.columns[stmt.column.name]) {
|
if (!schema.columns[stmt.column.name]) {
|
||||||
throw new DatabaseError(`Column "${stmt.column.name}" does not exist in table "${stmt.name}"`, 'COLUMN_NOT_FOUND');
|
throw new DatabaseError(`Column "${stmt.column.name}" does not exist in table "${stmt.name}"`, 'COLUMN_NOT_FOUND');
|
||||||
}
|
}
|
||||||
// 从 schema 引用上删除列定义(保留所有行数据)
|
// 只从 schema 引用上删除列定义,不碰行数据(避免引用共享导致查询结果被篡改)
|
||||||
delete schema.columns[stmt.column.name];
|
delete schema.columns[stmt.column.name];
|
||||||
// 清除已有行中该列的值(MemoryEngine 的 find 返回引用,delete 直接生效)
|
|
||||||
const rows = await this.engine.find(stmt.name, { table: stmt.name });
|
|
||||||
const colName = stmt.column.name;
|
|
||||||
for (const row of rows) {
|
|
||||||
if (colName in row)
|
|
||||||
delete row[colName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async executeTruncateTable(stmt) {
|
async executeTruncateTable(stmt) {
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-8
@@ -5669,15 +5669,8 @@
|
|||||||
if (!schema.columns[stmt.column.name]) {
|
if (!schema.columns[stmt.column.name]) {
|
||||||
throw new DatabaseError(`Column "${stmt.column.name}" does not exist in table "${stmt.name}"`, 'COLUMN_NOT_FOUND');
|
throw new DatabaseError(`Column "${stmt.column.name}" does not exist in table "${stmt.name}"`, 'COLUMN_NOT_FOUND');
|
||||||
}
|
}
|
||||||
// 从 schema 引用上删除列定义(保留所有行数据)
|
// 只从 schema 引用上删除列定义,不碰行数据(避免引用共享导致查询结果被篡改)
|
||||||
delete schema.columns[stmt.column.name];
|
delete schema.columns[stmt.column.name];
|
||||||
// 清除已有行中该列的值(MemoryEngine 的 find 返回引用,delete 直接生效)
|
|
||||||
const rows = await this.engine.find(stmt.name, { table: stmt.name });
|
|
||||||
const colName = stmt.column.name;
|
|
||||||
for (const row of rows) {
|
|
||||||
if (colName in row)
|
|
||||||
delete row[colName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async executeTruncateTable(stmt) {
|
async executeTruncateTable(stmt) {
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+3
-1
@@ -221,7 +221,9 @@ async function runQuery() {
|
|||||||
const allResults = [];
|
const allResults = [];
|
||||||
for (const stmt of statements) {
|
for (const stmt of statements) {
|
||||||
const result = await db.query(stmt);
|
const result = await db.query(stmt);
|
||||||
allResults.push({ sql: stmt, result });
|
// 深拷贝结果,避免引用共享导致后续操作(如 ALTER TABLE DROP COLUMN)修改已渲染的结果
|
||||||
|
const resultCopy = Array.isArray(result) ? result.map(r => ({ ...r })) : result;
|
||||||
|
allResults.push({ sql: stmt, result: resultCopy });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allResults.length === 1) {
|
if (allResults.length === 1) {
|
||||||
|
|||||||
@@ -306,14 +306,8 @@ export class QueryExecutor {
|
|||||||
if (!schema.columns[stmt.column.name]) {
|
if (!schema.columns[stmt.column.name]) {
|
||||||
throw new DatabaseError(`Column "${stmt.column.name}" does not exist in table "${stmt.name}"`, 'COLUMN_NOT_FOUND');
|
throw new DatabaseError(`Column "${stmt.column.name}" does not exist in table "${stmt.name}"`, 'COLUMN_NOT_FOUND');
|
||||||
}
|
}
|
||||||
// 从 schema 引用上删除列定义(保留所有行数据)
|
// 只从 schema 引用上删除列定义,不碰行数据(避免引用共享导致查询结果被篡改)
|
||||||
delete schema.columns[stmt.column.name];
|
delete schema.columns[stmt.column.name];
|
||||||
// 清除已有行中该列的值(MemoryEngine 的 find 返回引用,delete 直接生效)
|
|
||||||
const rows = await this.engine.find(stmt.name, { table: stmt.name });
|
|
||||||
const colName = stmt.column.name;
|
|
||||||
for (const row of rows) {
|
|
||||||
if (colName in row) delete row[colName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
const { MetonaSqlark } = require('./dist/metona-sqlark.cjs.js');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const db = new MetonaSqlark({ name: 'test', mode: 'memory' });
|
||||||
|
await db.init();
|
||||||
|
|
||||||
|
await db.defineTable('users', {
|
||||||
|
id: { type: 'string', primaryKey: true },
|
||||||
|
name: { type: 'string', required: true },
|
||||||
|
email: { type: 'string' },
|
||||||
|
age: { type: 'number', default: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
// Step 1: ALTER TABLE ADD COLUMN
|
||||||
|
await db.query('ALTER TABLE users ADD COLUMN phone STRING');
|
||||||
|
|
||||||
|
const schema = await db.getEngine().getTableSchema('users');
|
||||||
|
console.log('Schema columns:', Object.keys(schema.columns));
|
||||||
|
|
||||||
|
// Step 2: INSERT
|
||||||
|
await db.query("INSERT INTO users (id, name, age, phone) VALUES ('6', 'Frank', 33, '123-4567')");
|
||||||
|
|
||||||
|
// Step 3: SELECT (first)
|
||||||
|
const result1 = await db.query("SELECT * FROM users WHERE id = '6'");
|
||||||
|
console.log('First query result:', JSON.stringify(result1));
|
||||||
|
console.log('First query fields:', Object.keys(result1[0]));
|
||||||
|
|
||||||
|
// Step 4: ALTER TABLE DROP COLUMN
|
||||||
|
await db.query('ALTER TABLE users DROP COLUMN phone');
|
||||||
|
|
||||||
|
// Step 5: SELECT (second)
|
||||||
|
const result2 = await db.query("SELECT * FROM users WHERE id = '6'");
|
||||||
|
console.log('Second query result:', JSON.stringify(result2));
|
||||||
|
console.log('Second query fields:', Object.keys(result2[0]));
|
||||||
|
|
||||||
|
await db.close();
|
||||||
|
})();
|
||||||
Reference in New Issue
Block a user