Skip to content

Commit

Permalink
Merge pull request #215 from markuspfeiffer/dev-migration
Browse files Browse the repository at this point in the history
Added a new SQL parser for migrations.
  • Loading branch information
pardom committed Apr 18, 2014
2 parents bd98740 + 7c7c73c commit 7b2ed13
Show file tree
Hide file tree
Showing 25 changed files with 851 additions and 21 deletions.
44 changes: 36 additions & 8 deletions src/com/activeandroid/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,18 @@
import com.activeandroid.util.ReflectionUtils;

public class Configuration {

public final static String SQL_PARSER_LEGACY = "legacy";
public final static String SQL_PARSER_DELIMITED = "delimited";

//////////////////////////////////////////////////////////////////////////////////////
// PRIVATE MEMBERS
//////////////////////////////////////////////////////////////////////////////////////

private Context mContext;
private String mDatabaseName;
private int mDatabaseVersion;
private String mSqlParser;
private List<Class<? extends Model>> mModelClasses;
private List<Class<? extends TypeSerializer>> mTypeSerializers;
private int mCacheSize;
Expand Down Expand Up @@ -61,6 +66,10 @@ public String getDatabaseName() {
public int getDatabaseVersion() {
return mDatabaseVersion;
}

public String getSqlParser() {
return mSqlParser;
}

public List<Class<? extends Model>> getModelClasses() {
return mModelClasses;
Expand Down Expand Up @@ -91,9 +100,11 @@ public static class Builder {
private static final String AA_DB_VERSION = "AA_DB_VERSION";
private final static String AA_MODELS = "AA_MODELS";
private final static String AA_SERIALIZERS = "AA_SERIALIZERS";
private final static String AA_SQL_PARSER = "AA_SQL_PARSER";

private static final int DEFAULT_CACHE_SIZE = 1024;
private static final String DEFAULT_DB_NAME = "Application.db";
private static final String DEFAULT_SQL_PARSER = SQL_PARSER_LEGACY;

//////////////////////////////////////////////////////////////////////////////////////
// PRIVATE MEMBERS
Expand All @@ -104,6 +115,7 @@ public static class Builder {
private Integer mCacheSize;
private String mDatabaseName;
private Integer mDatabaseVersion;
private String mSqlParser;
private List<Class<? extends Model>> mModelClasses;
private List<Class<? extends TypeSerializer>> mTypeSerializers;

Expand Down Expand Up @@ -134,6 +146,11 @@ public Builder setDatabaseVersion(int databaseVersion) {
mDatabaseVersion = databaseVersion;
return this;
}

public Builder setSqlParser(String sqlParser) {
mSqlParser = sqlParser;
return this;
}

public Builder addModelClass(Class<? extends Model> modelClass) {
if (mModelClasses == null) {
Expand Down Expand Up @@ -188,24 +205,28 @@ public Configuration create() {
// Get database name from meta-data
if (mDatabaseName != null) {
configuration.mDatabaseName = mDatabaseName;
}
else {
} else {
configuration.mDatabaseName = getMetaDataDatabaseNameOrDefault();
}

// Get database version from meta-data
if (mDatabaseVersion != null) {
configuration.mDatabaseVersion = mDatabaseVersion;
}
else {
} else {
configuration.mDatabaseVersion = getMetaDataDatabaseVersionOrDefault();
}

// Get SQL parser from meta-data
if (mSqlParser != null) {
configuration.mSqlParser = mSqlParser;
} else {
configuration.mSqlParser = getMetaDataSqlParserOrDefault();
}

// Get model classes from meta-data
if (mModelClasses != null) {
configuration.mModelClasses = mModelClasses;
}
else {
} else {
final String modelList = ReflectionUtils.getMetaData(mContext, AA_MODELS);
if (modelList != null) {
configuration.mModelClasses = loadModelList(modelList.split(","));
Expand All @@ -215,8 +236,7 @@ public Configuration create() {
// Get type serializer classes from meta-data
if (mTypeSerializers != null) {
configuration.mTypeSerializers = mTypeSerializers;
}
else {
} else {
final String serializerList = ReflectionUtils.getMetaData(mContext, AA_SERIALIZERS);
if (serializerList != null) {
configuration.mTypeSerializers = loadSerializerList(serializerList.split(","));
Expand Down Expand Up @@ -250,6 +270,14 @@ private int getMetaDataDatabaseVersionOrDefault() {
return aaVersion;
}

private String getMetaDataSqlParserOrDefault() {
final String mode = ReflectionUtils.getMetaData(mContext, AA_SQL_PARSER);
if (mode == null) {
return DEFAULT_SQL_PARSER;
}
return mode;
}

private List<Class<? extends Model>> loadModelList(String[] models) {
final List<Class<? extends Model>> modelClasses = new ArrayList<Class<? extends Model>>();
final ClassLoader classLoader = mContext.getClass().getClassLoader();
Expand Down
74 changes: 61 additions & 13 deletions src/com/activeandroid/DatabaseHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.activeandroid.util.IOUtils;
import com.activeandroid.util.Log;
import com.activeandroid.util.NaturalOrderComparator;
import com.activeandroid.util.SQLiteUtils;
import com.activeandroid.util.SqlParser;

public final class DatabaseHelper extends SQLiteOpenHelper {
//////////////////////////////////////////////////////////////////////////////////////
Expand All @@ -42,13 +44,20 @@ public final class DatabaseHelper extends SQLiteOpenHelper {

public final static String MIGRATION_PATH = "migrations";

//////////////////////////////////////////////////////////////////////////////////////
// PRIVATE FIELDS
//////////////////////////////////////////////////////////////////////////////////////

private final String mSqlParser;

//////////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////////

public DatabaseHelper(Configuration configuration) {
super(configuration.getContext(), configuration.getDatabaseName(), null, configuration.getDatabaseVersion());
copyAttachedDatabase(configuration.getContext(), configuration.getDatabaseName());
mSqlParser = configuration.getSqlParser();
}

//////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -187,22 +196,61 @@ private boolean executeMigrations(SQLiteDatabase db, int oldVersion, int newVers

return migrationExecuted;
}

private void executeSqlScript(SQLiteDatabase db, String file) {

InputStream stream = null;

try {
final InputStream input = Cache.getContext().getAssets().open(MIGRATION_PATH + "/" + file);
final BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String line = null;

while ((line = reader.readLine()) != null) {
line = line.replace(";", "").trim();
if (!line.isEmpty()) {
db.execSQL(line);
}
}
}
catch (IOException e) {
stream = Cache.getContext().getAssets().open(MIGRATION_PATH + "/" + file);

if (Configuration.SQL_PARSER_DELIMITED.equalsIgnoreCase(mSqlParser)) {
executeDelimitedSqlScript(db, stream);

} else {
executeLegacySqlScript(db, stream);

}

} catch (IOException e) {
Log.e("Failed to execute " + file, e);

} finally {
IOUtils.closeQuietly(stream);

}
}

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

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

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

private void executeLegacySqlScript(SQLiteDatabase 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 (!line.isEmpty()) {
db.execSQL(line);
}
}

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

}
}
}
69 changes: 69 additions & 0 deletions src/com/activeandroid/util/IOUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

package com.activeandroid.util;

/*
* Copyright (C) 2014 Markus Pfeiffer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import android.database.Cursor;

import java.io.Closeable;
import java.io.IOException;

import com.activeandroid.util.Log;


public class IOUtils {

/**
* Unconditionally close a {@link Closeable}.
* <p/>
* Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is
* typically used in finally blocks.
* @param closeable A {@link Closeable} to close.
*/
public static void closeQuietly(final Closeable closeable) {

if (closeable == null) {
return;
}

try {
closeable.close();
} catch (final IOException e) {
Log.e("Couldn't close closeable.", e);
}
}

/**
* Unconditionally close a {@link Cursor}.
* <p/>
* Equivalent to {@link Cursor#close()}, except any exceptions will be ignored. This is
* typically used in finally blocks.
* @param cursor A {@link Cursor} to close.
*/
public static void closeQuietly(final Cursor cursor) {

if (cursor == null) {
return;
}

try {
cursor.close();
} catch (final Exception e) {
Log.e("Couldn't close cursor.", e);
}
}
}
Loading

0 comments on commit 7b2ed13

Please sign in to comment.