wheatandcatの開発ブログ

React Nativeで開発しているペペロミア & memoirの技術系記事を投稿してます

expoのsqliteでmigrationさせる

今回の更新でsqliteのtableにカラム追加したので、その辺の話

対象のpull request

github.com

pull request見れば分かりますが、特に良い実装とかは無く愚直に実行しました。

対応内容

今回はのMigrationでは以下の通りに動作するように対応

  • 既にアプリをインストール済みのユーザー→カラム追加のクエリを実行
  • 新規でアプリをインストールしたユーザー→カラム追加済みのテーブルを作る

まず、Migration用のメソッド作成

import { SQLite } from "expo-sqlite";
import { success, error } from "./";

 export const migrationV1040 = async (
  tx: SQLite.Transaction,
  callback?: (error: any) => void
) => {
  const query = `alter table item_details add column place string;`;

   return tx.executeSql(
    query,
    [],
    (_: any, props: any) => success(props, callback),
    (_: any, err: any) => {
      error(err, callback);
    }
  );
};

 export const migrationV1041 = async (
  tx: SQLite.Transaction,
  callback?: (error: any) => void
) => {
  const query = `alter table item_details add column url string;`;

   return tx.executeSql(
    query,
    [],
    (_: any, props: any) => success(props, callback),
    (_: any, err: any) => {
      error(err, callback);
    }
  );
};

sqliteは、add columnを1クエリで複数投げられないので追加分実行

あとは起動時にアプリのバージョンと現在のDBのバージョンを比較して↑のメソッドを実行すればOK

まずは、新新規でアプリをインストールしたユーザーのバージョンを設定する。

■src/app.tsx

import app from "../app.json";
略)

   if (!data) {
      const uuid = Constants.installationId + uuidv1();
      const user: User = {
        uuid
      };
      db.transaction((tx: SQLite.Transaction) => {
        insertUser(tx, user, this.setUser);
      }
);
      AsyncStorage.setItem("userID", user.uuid);

      // 現在のバージョンを設定
      AsyncStorage.setItem("APP_VERSION", app.expo.version);
  }

初期ユーザー作成の際に現在のexpoに設定いしているアプリバージョンを保存する

既にアプリをインストール済みのユーザーへの対応とした以下を実装

src/containers/Version.tsx

  async componentDidMount() {
    let appVerion = await AsyncStorage.getItem("APP_VERSION");
    if (!appVerion) {
      appVerion = "1.0.0";
    }

    if (compareVersions.compare("1.0.4", appVerion, ">")) {
      // カラム追加のマイグレーション実行
      const ok = await migrationV104();
      if (ok) {
        // 現在のバージョンを設定
        AsyncStorage.setItem("APP_VERSION", "1.0.4");
      }
    }

    this.setState({
      loading: false
    });
  }

ちなみにバージョンの比較は↓のパッケージを使用しています github.com

ってことで自前で実装しました。 意外と実装が辛かったので、あとでパッケージ作ってもよいかもと思った。