Skip to content

Commit 7b2ed13

Browse files
committed
Merge pull request #215 from markuspfeiffer/dev-migration
Added a new SQL parser for migrations.
2 parents bd98740 + 7c7c73c commit 7b2ed13

25 files changed

+851
-21
lines changed

src/com/activeandroid/Configuration.java

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,18 @@
2727
import com.activeandroid.util.ReflectionUtils;
2828

2929
public class Configuration {
30+
31+
public final static String SQL_PARSER_LEGACY = "legacy";
32+
public final static String SQL_PARSER_DELIMITED = "delimited";
33+
3034
//////////////////////////////////////////////////////////////////////////////////////
3135
// PRIVATE MEMBERS
3236
//////////////////////////////////////////////////////////////////////////////////////
3337

3438
private Context mContext;
3539
private String mDatabaseName;
3640
private int mDatabaseVersion;
41+
private String mSqlParser;
3742
private List<Class<? extends Model>> mModelClasses;
3843
private List<Class<? extends TypeSerializer>> mTypeSerializers;
3944
private int mCacheSize;
@@ -61,6 +66,10 @@ public String getDatabaseName() {
6166
public int getDatabaseVersion() {
6267
return mDatabaseVersion;
6368
}
69+
70+
public String getSqlParser() {
71+
return mSqlParser;
72+
}
6473

6574
public List<Class<? extends Model>> getModelClasses() {
6675
return mModelClasses;
@@ -91,9 +100,11 @@ public static class Builder {
91100
private static final String AA_DB_VERSION = "AA_DB_VERSION";
92101
private final static String AA_MODELS = "AA_MODELS";
93102
private final static String AA_SERIALIZERS = "AA_SERIALIZERS";
103+
private final static String AA_SQL_PARSER = "AA_SQL_PARSER";
94104

95105
private static final int DEFAULT_CACHE_SIZE = 1024;
96106
private static final String DEFAULT_DB_NAME = "Application.db";
107+
private static final String DEFAULT_SQL_PARSER = SQL_PARSER_LEGACY;
97108

98109
//////////////////////////////////////////////////////////////////////////////////////
99110
// PRIVATE MEMBERS
@@ -104,6 +115,7 @@ public static class Builder {
104115
private Integer mCacheSize;
105116
private String mDatabaseName;
106117
private Integer mDatabaseVersion;
118+
private String mSqlParser;
107119
private List<Class<? extends Model>> mModelClasses;
108120
private List<Class<? extends TypeSerializer>> mTypeSerializers;
109121

@@ -134,6 +146,11 @@ public Builder setDatabaseVersion(int databaseVersion) {
134146
mDatabaseVersion = databaseVersion;
135147
return this;
136148
}
149+
150+
public Builder setSqlParser(String sqlParser) {
151+
mSqlParser = sqlParser;
152+
return this;
153+
}
137154

138155
public Builder addModelClass(Class<? extends Model> modelClass) {
139156
if (mModelClasses == null) {
@@ -188,24 +205,28 @@ public Configuration create() {
188205
// Get database name from meta-data
189206
if (mDatabaseName != null) {
190207
configuration.mDatabaseName = mDatabaseName;
191-
}
192-
else {
208+
} else {
193209
configuration.mDatabaseName = getMetaDataDatabaseNameOrDefault();
194210
}
195211

196212
// Get database version from meta-data
197213
if (mDatabaseVersion != null) {
198214
configuration.mDatabaseVersion = mDatabaseVersion;
199-
}
200-
else {
215+
} else {
201216
configuration.mDatabaseVersion = getMetaDataDatabaseVersionOrDefault();
202217
}
203218

219+
// Get SQL parser from meta-data
220+
if (mSqlParser != null) {
221+
configuration.mSqlParser = mSqlParser;
222+
} else {
223+
configuration.mSqlParser = getMetaDataSqlParserOrDefault();
224+
}
225+
204226
// Get model classes from meta-data
205227
if (mModelClasses != null) {
206228
configuration.mModelClasses = mModelClasses;
207-
}
208-
else {
229+
} else {
209230
final String modelList = ReflectionUtils.getMetaData(mContext, AA_MODELS);
210231
if (modelList != null) {
211232
configuration.mModelClasses = loadModelList(modelList.split(","));
@@ -215,8 +236,7 @@ public Configuration create() {
215236
// Get type serializer classes from meta-data
216237
if (mTypeSerializers != null) {
217238
configuration.mTypeSerializers = mTypeSerializers;
218-
}
219-
else {
239+
} else {
220240
final String serializerList = ReflectionUtils.getMetaData(mContext, AA_SERIALIZERS);
221241
if (serializerList != null) {
222242
configuration.mTypeSerializers = loadSerializerList(serializerList.split(","));
@@ -250,6 +270,14 @@ private int getMetaDataDatabaseVersionOrDefault() {
250270
return aaVersion;
251271
}
252272

273+
private String getMetaDataSqlParserOrDefault() {
274+
final String mode = ReflectionUtils.getMetaData(mContext, AA_SQL_PARSER);
275+
if (mode == null) {
276+
return DEFAULT_SQL_PARSER;
277+
}
278+
return mode;
279+
}
280+
253281
private List<Class<? extends Model>> loadModelList(String[] models) {
254282
final List<Class<? extends Model>> modelClasses = new ArrayList<Class<? extends Model>>();
255283
final ClassLoader classLoader = mContext.getClass().getClassLoader();

src/com/activeandroid/DatabaseHelper.java

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@
3131
import android.database.sqlite.SQLiteDatabase;
3232
import android.database.sqlite.SQLiteOpenHelper;
3333

34+
import com.activeandroid.util.IOUtils;
3435
import com.activeandroid.util.Log;
3536
import com.activeandroid.util.NaturalOrderComparator;
3637
import com.activeandroid.util.SQLiteUtils;
38+
import com.activeandroid.util.SqlParser;
3739

3840
public final class DatabaseHelper extends SQLiteOpenHelper {
3941
//////////////////////////////////////////////////////////////////////////////////////
@@ -42,13 +44,20 @@ public final class DatabaseHelper extends SQLiteOpenHelper {
4244

4345
public final static String MIGRATION_PATH = "migrations";
4446

47+
//////////////////////////////////////////////////////////////////////////////////////
48+
// PRIVATE FIELDS
49+
//////////////////////////////////////////////////////////////////////////////////////
50+
51+
private final String mSqlParser;
52+
4553
//////////////////////////////////////////////////////////////////////////////////////
4654
// CONSTRUCTORS
4755
//////////////////////////////////////////////////////////////////////////////////////
4856

4957
public DatabaseHelper(Configuration configuration) {
5058
super(configuration.getContext(), configuration.getDatabaseName(), null, configuration.getDatabaseVersion());
5159
copyAttachedDatabase(configuration.getContext(), configuration.getDatabaseName());
60+
mSqlParser = configuration.getSqlParser();
5261
}
5362

5463
//////////////////////////////////////////////////////////////////////////////////////
@@ -187,22 +196,61 @@ private boolean executeMigrations(SQLiteDatabase db, int oldVersion, int newVers
187196

188197
return migrationExecuted;
189198
}
190-
199+
191200
private void executeSqlScript(SQLiteDatabase db, String file) {
201+
202+
InputStream stream = null;
203+
192204
try {
193-
final InputStream input = Cache.getContext().getAssets().open(MIGRATION_PATH + "/" + file);
194-
final BufferedReader reader = new BufferedReader(new InputStreamReader(input));
195-
String line = null;
196-
197-
while ((line = reader.readLine()) != null) {
198-
line = line.replace(";", "").trim();
199-
if (!line.isEmpty()) {
200-
db.execSQL(line);
201-
}
202-
}
203-
}
204-
catch (IOException e) {
205+
stream = Cache.getContext().getAssets().open(MIGRATION_PATH + "/" + file);
206+
207+
if (Configuration.SQL_PARSER_DELIMITED.equalsIgnoreCase(mSqlParser)) {
208+
executeDelimitedSqlScript(db, stream);
209+
210+
} else {
211+
executeLegacySqlScript(db, stream);
212+
213+
}
214+
215+
} catch (IOException e) {
205216
Log.e("Failed to execute " + file, e);
217+
218+
} finally {
219+
IOUtils.closeQuietly(stream);
220+
206221
}
207222
}
223+
224+
private void executeDelimitedSqlScript(SQLiteDatabase db, InputStream stream) throws IOException {
225+
226+
List<String> commands = SqlParser.parse(stream);
227+
228+
for(String command : commands) {
229+
db.execSQL(command);
230+
}
231+
}
232+
233+
private void executeLegacySqlScript(SQLiteDatabase db, InputStream stream) throws IOException {
234+
235+
InputStreamReader reader = null;
236+
BufferedReader buffer = null;
237+
238+
try {
239+
reader = new InputStreamReader(stream);
240+
buffer = new BufferedReader(reader);
241+
String line = null;
242+
243+
while ((line = buffer.readLine()) != null) {
244+
line = line.replace(";", "").trim();
245+
if (!line.isEmpty()) {
246+
db.execSQL(line);
247+
}
248+
}
249+
250+
} finally {
251+
IOUtils.closeQuietly(buffer);
252+
IOUtils.closeQuietly(reader);
253+
254+
}
255+
}
208256
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
2+
package com.activeandroid.util;
3+
4+
/*
5+
* Copyright (C) 2014 Markus Pfeiffer
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
import android.database.Cursor;
21+
22+
import java.io.Closeable;
23+
import java.io.IOException;
24+
25+
import com.activeandroid.util.Log;
26+
27+
28+
public class IOUtils {
29+
30+
/**
31+
* Unconditionally close a {@link Closeable}.
32+
* <p/>
33+
* Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is
34+
* typically used in finally blocks.
35+
* @param closeable A {@link Closeable} to close.
36+
*/
37+
public static void closeQuietly(final Closeable closeable) {
38+
39+
if (closeable == null) {
40+
return;
41+
}
42+
43+
try {
44+
closeable.close();
45+
} catch (final IOException e) {
46+
Log.e("Couldn't close closeable.", e);
47+
}
48+
}
49+
50+
/**
51+
* Unconditionally close a {@link Cursor}.
52+
* <p/>
53+
* Equivalent to {@link Cursor#close()}, except any exceptions will be ignored. This is
54+
* typically used in finally blocks.
55+
* @param cursor A {@link Cursor} to close.
56+
*/
57+
public static void closeQuietly(final Cursor cursor) {
58+
59+
if (cursor == null) {
60+
return;
61+
}
62+
63+
try {
64+
cursor.close();
65+
} catch (final Exception e) {
66+
Log.e("Couldn't close cursor.", e);
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)