Sqlite таблицы и базы данных миграции в опубликованном приложении? - PullRequest
0 голосов
/ 19 декабря 2018

Я разработал приложение для Android на реакции-родной и экспо.Я также опубликовал приложение в Google Play.

Теперь я сделал некоторые изменения в своих таблицах БД SQLite локально.

Предположим, до того, как схема таблицы была такой:

CREATE TABLE expenditures (id integer primary key, max_amount REAL not null);

И теперь я хотел бы изменить это на следующее:

CREATE TABLE expenditures (id integer primary key, max_amount TEXT not null);

Есть ли способ запустить метод после нового обновления / обновления в производственном приложении (магазин Google Play)?Таким образом, я могу изменить таблицы только один раз после обновления, и другие вновь установленные пользователи не будут затронуты этой функцией.На родном андроиде я нашел два метода:

  1. onCreate: Вызывается впервые, когда необходимо создание таблиц.
  2. onUpgrade: этот метод вызывается при обновлении версии базы данных.

Но так как я разработал свое приложение с реактивным и экспо, я не могу использовать описанные выше методы.Хотя я обнаружил onUpgrade в коде expo , я не уверен, как использовать эту функцию в expo.

Или есть ли лучший способ обработки миграции базы данных в опубликованном приложениив реакции-родной и экспо?

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

вы можете поместить файлы изменений sql в папку активов android / app / src / main / assets / like

<version>.sql -> 1.sql or 2.sql

, и этот файл может содержать запрос на миграцию, например

alter table NOTE add NAME TEXT;

и запускать эти запросы в соответствии с версией приложения в методе onUpgrade ()

0 голосов
/ 27 декабря 2018

Я не думаю, что вы действительно можете использовать материал управления версиями, с которым вы связались, так как это приведет к удалению вашей базы данных и ее воссозданию с нуля, так что вы потеряете свои данные.вручную отслеживать миграции, которые вы уже выполнили в таблице.Затем вы можете создать эту таблицу, если она еще не существует (что можно сделать очень глупо, сначала попытавшись запросить ее, а если это не удастся, создайте ее).Если у вас есть список всех известных миграций по порядку, вы можете просто удалить элементы, у которых уже есть запись в таблице, и запустить оставшиеся.

Из старого приложения Cordova я написал этот код (да, это действительностарый, он все еще использует Require JS для определения модуля):

/**
 * Provide access to an SQL database, using the SQLite plugin for
 * Cordova devices so we aren't limited in how much data we can store,
 * and falling back to browser native support on desktop.
 *
 * Unfortunately webSQL is deprecated and slowly being phased out.
 */
define(['require', 'module', 'deviceReady!'], function(require, module, isCordova) {
    'use strict';

    var dbRootObject = isCordova ? window.sqlitePlugin : window,
    config = module.config();

    if (typeof dbRootObject.openDatabase == 'undefined') {
        window.alert('Your browser has no SQL support!  Please try a Webkit-based browser');
        return null;
    } else {
        var db = dbRootObject.openDatabase(config.dbName, '', 'Direct Result database', null),
        transaction = function(callback) {
            // We go through this trouble to automatically provide
            // error reporting and auto-rollback.
            var makeFacade = function(t) {
                return {
                    sql: function(sql, args, okCallback, errorCallback) {
                        var okFn, errFn;
                        if (okCallback) {
                            okFn = function(t, r) { return okCallback(makeFacade(t), r); };
                        } else {
                            okFn = null;
                        }
                        if (errorCallback) {
                            errFn = function(t, e) { console.log('SQL error: '+sql, e); return errorCallback(makeFacade(t), e); };
                        } else {
                            errFn = function(t, e) {
                                // It's important we throw an exn,
                                // else the txn won't be aborted!
                                window.alert(e.message + ' sql: '+sql);
                                throw(e.message + ' sql: '+sql);
                            };
                        }
                        return t.executeSql(sql, args, okFn, errFn);
                    }
                };
            };
            return db.transaction(function(t) {
                return callback(makeFacade(t));
            }, function(e) { console.log('error'); console.log(e); });
        },

        // We're going to have to create or own migrations, because
        // both the Cordova SQLite plugin and the Firefox WebSQL
        // extension don't implement versioning in their WebSQL API.
        migrate = function(version, upFn, done, txn) { // "Down" migrations are currently not supported
            var doIt = function(t) {
                t.sql('SELECT NOT EXISTS (SELECT version FROM sqldb_migrations WHERE version = ?) AS missing',
                      [version], function(t, r) {
                          if (r.rows.item(0).missing == '1') {
                              upFn(t, function() {
                                  t.sql('INSERT INTO sqldb_migrations (version)'+
                                        'VALUES (?)', [version], done);
                              });
                          } else {
                              done(t);
                          }
                      });
            };
            if (txn) doIt(txn);
            else transaction(doIt);
        },

        maybeRunMigrations = function(callback) {
            var migrations = [],
            addMigration = function(name, migration) {
                migrations.push([name, migration]);
            },
            runMigrations = function(t) {
                if (migrations.length === 0) {
                    callback(t);
                } else {
                    var m = migrations.shift(),
                    name = m[0],
                    migration = m[1];
                    migrate(name, migration, runMigrations, t);
                }
            };

            // ADD MIGRATIONS HERE. The idea is you can just add migrations
            // in a queue and they'll be run in sequence.

            // Here are two example migrations
            addMigration('1', function (t, done) {
                t.sql('CREATE TABLE people ('+
                      '  id integer PRIMARY KEY NOT NULL, '+
                      '  initials text NOT NULL, '+
                      '  first_name text NOT NULL, '+
                      '  family_name text NOT NULL, '+
                      '  email text NOT NULL, ', [], done);
            });
            addMigration('2', function(t, done) {
                t.sql('ALTER TABLE people ADD COLUMN phone_number text', [], done);
            });

            transaction(function(t) {
                t.sql('CREATE TABLE IF NOT EXISTS sqldb_migrations ('+
                      '  version int UNIQUE, '+
                      '  timestamp_applied text NOT NULL DEFAULT CURRENT_TIMESTAMP '+
                      ')', [], function (t, r) { runMigrations(t, migrations); });
            });
        };

        // Expose "migrate" just in case
        return {transaction: transaction, migrate: migrate, maybeRunMigrations: maybeRunMigrations};
    }
});

Вам также нужно будет проявить большую осторожность, так как я обнаружил, как трудно на самом деле изменить или даже отбросить столбцы с помощьюSQLite (или, по крайней мере, не с плагином Cordova в то время, когда я писал этот код)!Так что будьте очень осторожны с ограничениями, иначе вы в конечном итоге будете рисовать себя в углу.

Я не пробовал, но возможно, если вы переименуете старую таблицу, создайте новую заново с помощьюизмененные столбцы, а затем скопировать данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...