gpt4 book ai didi

javascript - 持久性JS : Updating an existing database using migrate()

转载 作者:太空宇宙 更新时间:2023-11-04 14:16:44 24 4
gpt4 key购买 nike

我目前正在尝试使用 PersistenceJS 的迁移插件对现有数据库进行更改。我可以很好地在数据库中添加/编辑/删除项目——但是……

  • 如何向现有(!)表中添加一列?
  • 如何更改现有 (!) 列的类型,例如从“文本”到“整数”?

  • 这些更改应保留当前存在的数据。

遗憾的是,文档有点稀缺,也许你能帮忙?

这是当前有效设置:

persistence.store.websql.config(persistence, 'tododatabase', 'todos are fun', 5*1024*1024);

var Todo = persistence.define('Todo', {
task: 'TEXT',
priority: 'INT',
done: 'BOOL'
});

persistence.schemaSync();

function addTodo( item ){
var todo = new Todo();
todo.task = item.task;
todo.priority = item.priority;
todo.done = item.done;

persistence.add(todo);
persistence.flush();
};

function deleteTodo( item, callback ){
// item.id was created automatically by calling "new Todo()"
Todo.all().filter('id','=', item.id ).destroyAll( function(){
persistence.flush( callback );
});
};

有点的迁移代码:

persistence.defineMigration(1, {
up: function() {
this.createTable('Todo', function(t){
t.text('task');
t.integer('priority');
t.boolean('done');
});
},
down: function() {
this.dropTable('Todo');
}
});

persistence.defineMigration(2, {
up: function() {
this.addColumn('Todo', 'due', 'DATE');
},
down: function() {
this.removeColumn('Todo', 'due');
}
});


function migrate( callback ){
console.log('migrating...');
persistence.migrations.init( function(){
console.log('migration init');
// this should migrate up to the latest version, in our case: 2
persistence.migrate( function(){
console.log('migration complete!');
} );
});
}

结果……

  1. 调用 migrate() 只会记录“迁移初始化”,不会调用完整的处理程序,不会创建“到期”列
  2. 在调用 migrate() 之前不调用 schemaSync() 正如 Zef Hemel 自己在 this post 中提出的那样产生与 1 相同的结果。
  3. 将第一行更改为 persistence.store.websql.config(persistence, 'newdatabase', 'testing migration', 5*1024*1024);,不调用 schemaSync(),只调用migrate() 将成功记录“迁移完成!” — 但它是在一个新的、完全空的数据库“newdatabase”中这样做的,该数据库当然不会保留任何现有数据。

总结

有一个数据库是使用 persistence.store.websql.config(...), persistence.define('Todo',...) 创建的和 persistence.schemaSync()

我现在想保留该数据库中已经存在的所有数据,但又想

  • 将列 priority 的类型从“整数”更改为“文本”
  • 向所有现有待办事项添加类型为“日期”的到期

如果你能把我推向正确的方向,我将不胜感激!

谢谢!

最佳答案

我终于让它工作了。我想指出一些与我的初始要求有关的问题,以供将来引用。看一下第一个迁移定义:

persistence.defineMigration(1, {
up: function() {
this.createTable('Todo', function(t){
...


毫不奇怪,createTable 将执行此操作:它将执行 SQL 语句 'CREATE TABLE Todo ...',如果有已经具有名称 Todo 的表。这就是为什么它适用于新数据库,但不适用于现有数据库。请记住:我已经有一个实时数据库,其中包含需要更新的表“Todo”。如果您是新手(即您没有使用过 schemaSync),createTable 工作得很好。由于 Migrations 插件不提供 createTableIfNotExists 方法,我需要使用 executeSql 如下:

persistence.defineMigration(1, {
up: function() {
this.executeSql('CREATE TABLE IF NOT EXISTS Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority INT, done BOOL)');
...


现在从架构版本 0 到 1 的迁移成功了,到版本 2 的迁移也成功了。

随着迁移到版本 3,priority 列的类型需要从 int 更改为 text。这通常使用 ALTER COLUMN SQL 命令来完成,Web SQL/SQLite 不支持该命令。参见 Omitted Features for SQLite .

使用 SQLite 更改列需要 4 个步骤的解决方法:

persistence.defineMigration(3, {
up: function() {
// rename current table
this.executeSql('ALTER TABLE Todo RENAME TO OldTodo');
// create new table with required columns and column types
this.executeSql('CREATE TABLE Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority TEXT, done BOOL)');
// copy contents from old table to new table
this.executeSql('INSERT INTO Todo(id, task, priority, done) SELECT id, task, priority, done FROM OldTodo');
// delete old table
this.executeSql('DROP TABLE OldTodo');
},
...


当然,改变列类型后,'Todo'的实体定义也要改变:

var Todo = persistence.define('Todo', {
task: 'TEXT',
priority: 'TEXT', // was 'INT'
due: 'DATE',
done: 'BOOL'
});


最后,完整的源代码:

persistence.store.websql.config(persistence, 'tododatabase', 'todos are fun', 5*1024*1024);

// persistence.debug = true;

//v0 + v1
// var Todo = persistence.define('Todo', {
// task: 'TEXT',
// priority: 'INT',
// done: 'BOOL'
// });

//v2
// var Todo = persistence.define('Todo', {
// task: 'TEXT',
// priority: 'INT',
// due: 'DATE',
// done: 'BOOL'
// });

//v3
var Todo = persistence.define('Todo', {
task: 'TEXT',
priority: 'TEXT',
due: 'DATE',
done: 'BOOL'
});


persistence.defineMigration(1, {
up: function() {
this.executeSql('CREATE TABLE IF NOT EXISTS Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority INT, done BOOL)');
},
down: function() {
this.dropTable('Todo');
}
});

persistence.defineMigration(2, {
up: function() {
this.addColumn('Todo', 'due', 'DATE');
},
down: function() {
this.removeColumn('Todo', 'due');
}
});

persistence.defineMigration(3, {
up: function() {
// rename current table
this.executeSql('ALTER TABLE Todo RENAME TO OldTodo');
// create new table with required columns
this.executeSql('CREATE TABLE Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority TEXT, due DATE, done BOOL)');
// copy contents from old table to new table
this.executeSql('INSERT INTO Todo(id, task, priority, due, done) SELECT id, task, priority, due, done FROM OldTodo');
// delete current table
this.executeSql('DROP TABLE OldTodo');
},
down: function() {
this.executeSql('ALTER TABLE Todo RENAME TO OldTodo');
this.executeSql('CREATE TABLE Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority INT, due DATE, done BOOL)');
this.executeSql('INSERT INTO Todo(id, task, priority, due, done) SELECT id, task, priority, due, done FROM OldTodo');
this.executeSql('DROP TABLE OldTodo');
}
});


function migrate( callback ){
console.log('migrating...');
persistence.migrations.init( function(){
console.log('migration init');
persistence.migrate( function(){
console.debug('migration complete!');
callback();
} );
});
};

migrate( onMigrationComplete );

function onMigrationComplete(){
// database is ready. do amazing things...
};

关于javascript - 持久性JS : Updating an existing database using migrate(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24204554/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com