Skip to content

Commit

Permalink
Implement methods to add columns and create new tables onUpgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
mick88 committed Oct 14, 2013
1 parent dc4c4bc commit 66c0d2d
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 53 deletions.
1 change: 1 addition & 0 deletions src/com/michaldabski/msqlite/DataTypes.java
Expand Up @@ -5,6 +5,7 @@ public class DataTypes
{
// Class field types
public final static int
TYPE_NA = -1,
TYPE_OTHER = 100,
TYPE_STRING = 101,
TYPE_COLLECTION = 102,
Expand Down
57 changes: 20 additions & 37 deletions src/com/michaldabski/msqlite/MSQLiteOpenHelper.java
Expand Up @@ -2,10 +2,8 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import android.annotation.TargetApi;
import android.content.ContentValues;
Expand All @@ -16,7 +14,6 @@
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import com.michaldabski.msqlite.models.Table;
Expand Down Expand Up @@ -46,30 +43,32 @@ public MSQLiteOpenHelper(Context context, String name, CursorFactory factory,
// Static methods
public static void createTable(SQLiteDatabase database, Class<?> type, boolean ifNotExist)
{
database
.execSQL(new CreateTable(type).setIF_NOT_EXIST(ifNotExist).build());
createTable(database, new Table(type), ifNotExist);
}

private static Map<String, String> getCreateTableStatements(SQLiteDatabase database)
public static void createTable(SQLiteDatabase database, Table table, boolean ifNotExist)
{
final int COLUMN_NAME = 0,
COLUMN_SQL = 1;
Cursor c = database.rawQuery("SELECT name, sql FROM SQLITE_MASTER WHERE type=?", new String [] {"table"});
Map<String,String> result = new HashMap<String, String>(c.getCount());
while (c.moveToNext())
{
result.put(c.getString(COLUMN_NAME), c.getString(COLUMN_SQL));
}
c.close();
return result;
database
.execSQL(new CreateTable(table).setIF_NOT_EXIST(ifNotExist).build());
}

private static void upgradeTable(SQLiteDatabase database, Table table)
{
Cursor cur = database.rawQuery("PRAGMA table_info("+table.getName()+");", null);
// TODO: Compare columns
// [cid, name, type, notnull, dflt_value, pk]
Log.i(table.getName(), "table upgraded");
Cursor cursor = database.rawQuery("PRAGMA table_info("+table.getName()+");", null);
if (cursor.getCount() == 0)
{
createTable(database, table, false);
Log.i("DatabaseUpgrade", "table created: "+table.getName());
}
else
{
Table currentDatabaseTable = Table.fromCursor(table.getName(), cursor);
for (String sql : Table.upgradeTable(currentDatabaseTable, table))
{
database.execSQL(sql);
Log.i("DatabaseUpgrade", "table altered. Query: "+sql);
}
}
}

public void upgradeDatabase()
Expand Down Expand Up @@ -125,23 +124,7 @@ public void onCreate(SQLiteDatabase db)
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
for (Class<?> c : classes)
{
dropTable(db, c, true);
createTable(db, c, false);
}
// TODO detect differences between tables and modify table instead of re-creating
}

@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
for (Class<?> c : classes)
{
dropTable(db, c, true);
createTable(db, c, false);
}
// TODO detect differences between tables and modify table instead of re-creating
upgradeDatabase(db);
}

/**
Expand Down
48 changes: 37 additions & 11 deletions src/com/michaldabski/msqlite/models/Column.java
@@ -1,10 +1,8 @@
package com.michaldabski.msqlite.models;

import java.io.NotSerializableException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Locale;

import android.database.Cursor;
import android.util.Log;

import com.michaldabski.msqlite.Annotations.ColumnName;
Expand All @@ -30,25 +28,48 @@ public class Column
dataType,
// table.field
uniqueName;

protected final Class<?> fieldClass;
private final int fieldType;

public Column(Field field)
public static Column fromCursor(Cursor cursor, Table table)
{
final int FIELD_NAME = 1,
FIELD_TYPE = 2,
FIELD_NOT_NULL = 3,
FIELD_DEF_VALUE = 4,
FIELD_PK = 5;
String name = cursor.getString(FIELD_NAME);
Column column = new Column(null, cursor.getInt(FIELD_NOT_NULL)==1, cursor.getInt(FIELD_PK)==1, name,
cursor.getString(FIELD_TYPE), table.getName()+"."+name, DataTypes.TYPE_NA);

return column;
}

private Column(Field field, boolean nOT_NULL, boolean pRIMARY_KEY,
String name, String dataType, String uniqueName,
int fieldType)
{
this.field = field;
NOT_NULL = nOT_NULL;
PRIMARY_KEY = pRIMARY_KEY;
this.name = name;
this.dataType = dataType;
this.uniqueName = uniqueName;
this.fieldType = fieldType;
}

public Column(Field field, Table table)
{
this.field =field;

if (field.isAnnotationPresent(ColumnName.class)) this.name = field.getAnnotation(ColumnName.class).value();
else this.name = field.getName();

this.fieldClass = field.getType();

this.uniqueName = String.format("%s.%s", field.getDeclaringClass().getSimpleName(), name);
this.uniqueName = String.format("%s.%s", table.getName(), name);

fieldType = DataTypes.getFieldType(fieldClass);
fieldType = DataTypes.getFieldType(field.getType());
if (fieldType == DataTypes.TYPE_OTHER)
{
Log.w("MSQLite", fieldClass.getSimpleName()+" is not supported as a table field yet. Consider making this field transient.");
Log.w("MSQLite", field.getType().getSimpleName()+" is not supported as a table field yet. Consider making this field transient.");
dataType = null;
return;
}
Expand Down Expand Up @@ -171,6 +192,11 @@ public int getFieldType()
return fieldType;
}

public boolean isPRIMARY_KEY()
{
return PRIMARY_KEY;
}

public void setValueFromString(Object object, String value) throws IllegalArgumentException
{
try
Expand Down
55 changes: 54 additions & 1 deletion src/com/michaldabski/msqlite/models/Table.java
Expand Up @@ -29,6 +29,59 @@ public class Table
protected final List<Column> columns;
protected final List<Column> primaryKeys;

/**
* Create table instance from cursor
* @param cursor PRAGMA table_info(TABLE_NAME);
* @return table model based on data from the cursor
*/
public static Table fromCursor(String tableName, Cursor cursor)
{
Table result = new Table(tableName, new ArrayList<Column>(cursor.getCount()));
while (cursor.moveToNext())
{
Column column = Column.fromCursor(cursor, result);
result.columns.add(column);
if (column.isPRIMARY_KEY())
result.primaryKeys.add(column);
}
return result;
}

/**
* Create upgrade statements according to sqlite rules:
* http://www.sqlite.org/lang_altertable.html
* only new columns are added.
* @return alter statements to alter upgradeFrom table into this table
*/
public List<String> upgradeTable(Table upgradeFrom)
{
List<String> result = new ArrayList<String>();

// add new columns
for (Column column : columns)
{
if (upgradeFrom.columns.contains(column) == false)
{
StringBuilder resultBuilder = new StringBuilder("Alter table `").append(this.name)
.append("` ADD COLUMN ").append(column.getBuilder()).append(';');
result.add(resultBuilder.toString());
}
}
return result;
}

public static List<String> upgradeTable(Table currentTable, Table newTable)
{
return newTable.upgradeTable(currentTable);
}

private Table(String name, List<Column> columns)
{
this.name = name;
this.columns = columns;
this.primaryKeys = new ArrayList<Column>(1);
}

/**
* Create Table from java class definition
*
Expand Down Expand Up @@ -57,7 +110,7 @@ public Table(Class<?> type)
for (Field field : fields)
{
if ((field.getModifiers() & (Modifier.TRANSIENT | Modifier.STATIC | Modifier.FINAL)) > 0) continue;
Column column = new Column(field);
Column column = new Column(field, this);
if (column.getDataType() == null) continue;
columns.add(column);
if (column.PRIMARY_KEY) primaryKeys.add(column);
Expand Down
7 changes: 6 additions & 1 deletion src/com/michaldabski/msqlite/queries/CreateTable.java
Expand Up @@ -11,11 +11,16 @@ public class CreateTable extends QueryBuilder
{
private boolean
IF_NOT_EXISTS = false;

public CreateTable(Class<?> type)
{
super(type);
}

public CreateTable(Table table)
{
super(table);
}

public CreateTable setIF_NOT_EXIST(boolean iF_NOT_EXIST)
{
Expand Down
12 changes: 9 additions & 3 deletions src/com/michaldabski/msqlite/queries/QueryBuilder.java
Expand Up @@ -5,17 +5,23 @@

public abstract class QueryBuilder
{
protected Class<?> type;
protected Table table;
protected String condition = "1";

@Deprecated
public QueryBuilder(Class<?> type)
{
this.type = type;
this.table = new Table(type);
}

public QueryBuilder(Table table)
{
this.table = table;
}

public Table getTable()
{
return new Table(type);
return table;
}

// public abstract <T> Result<T> execute(Class<T> type);
Expand Down

0 comments on commit 66c0d2d

Please sign in to comment.