DBUpdateHelper.java 4.2 KB
package com.shunzhi.parent.dbhelper;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.StringDef;
import android.text.TextUtils;
import android.util.Log;

import com.shunzhi.parent.dbhelper.utils.IOUtils;
import com.shunzhi.parent.dbhelper.utils.NaturalOrderComparator;
import com.shunzhi.parent.dbhelper.utils.SqlParser;

import org.greenrobot.greendao.database.Database;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import timber.log.Timber;

public class DBUpdateHelper {

    private Context context;
    public final static String SQL_PARSER_LEGACY = "legacy";
    public final static String SQL_PARSER_DELIMITED = "delimited";

    private final String mSqlParser;

    @StringDef({SQL_PARSER_DELIMITED, SQL_PARSER_LEGACY})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SQLParser {

    }

    public DBUpdateHelper(Context context, @SQLParser String sqlParser) {
        this.context = context.getApplicationContext();
        mSqlParser = sqlParser;
    }

    public boolean onUpdate(Database db, int oldVersion, int newVersion) {
        return executeMigrations(db, oldVersion, newVersion);
    }

    private boolean executeMigrations(Database db, int oldVersion, int newVersion) {
        boolean migrationExecuted = false;
        try {
            final List<String> files = Arrays.asList(context.getAssets().list("migrations"));
            Collections.sort(files, new NaturalOrderComparator());

            db.beginTransaction();
            try {
                for (String file : files) {
                    try {
                        final int version = Integer.valueOf(file.replace(".sql", ""));

                        if (version > oldVersion && version <= newVersion) {
                            executeSqlScript(db, file);
                            migrationExecuted = true;
                            Timber.i("---==="+file + " executed succesfully.");
                        }
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                }
                db.setTransactionSuccessful();
            } finally {
                db.endTransaction();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return migrationExecuted;
    }

    private final static String MIGRATION_PATH = "migrations";

    private void executeSqlScript(Database db, String file) {

        InputStream stream = null;

        try {
            stream = context.getAssets().open(MIGRATION_PATH + "/" + file);
            //因为我懒,不允许自定义解析方式
            //算了,还是加上吧  突然忘了类型限定怎么写了 就当练练手
            if (SQL_PARSER_DELIMITED.equalsIgnoreCase(mSqlParser)) {
                executeDelimitedSqlScript(db, stream);
            } else {
                executeLegacySqlScript(db, stream);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(stream);

        }
    }

    private void executeDelimitedSqlScript(Database db, InputStream stream) throws IOException {

        List<String> commands = SqlParser.parse(stream);

        for (String command : commands) {
            db.execSQL(command);
        }
    }

    private void executeLegacySqlScript(Database db, InputStream stream) throws IOException {

        InputStreamReader reader = null;
        BufferedReader buffer = null;

        try {
            reader = new InputStreamReader(stream);
            buffer = new BufferedReader(reader);
            String line = null;

            while ((line = buffer.readLine()) != null) {
                line = line.replace(";", "").trim();
                if (!TextUtils.isEmpty(line)) {
                    db.execSQL(line);
                }
            }

        } finally {
            IOUtils.closeQuietly(buffer);
            IOUtils.closeQuietly(reader);

        }
    }
}