mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Fix handling of null values in AndroidDatabase
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015-2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.database;
|
||||||
|
|
||||||
|
import android.database.sqlite.*;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.*;
|
||||||
|
import org.isoron.uhabits.core.database.*;
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
|
import static org.hamcrest.core.IsEqual.*;
|
||||||
|
|
||||||
|
|
||||||
|
public class AndroidDatabaseTest extends BaseAndroidTest
|
||||||
|
{
|
||||||
|
private AndroidDatabase db;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
db = new AndroidDatabase(SQLiteDatabase.create(null));
|
||||||
|
db.execute("create table test(color int, name string)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsert() throws Exception
|
||||||
|
{
|
||||||
|
HashMap<String, Object> map = new HashMap<>();
|
||||||
|
map.put("name", "asd");
|
||||||
|
map.put("color", null);
|
||||||
|
db.insert("test", map);
|
||||||
|
|
||||||
|
Cursor c = db.query("select * from test");
|
||||||
|
c.moveToNext();
|
||||||
|
assertNull(c.getInt(0));
|
||||||
|
assertThat(c.getString(1), equalTo("asd"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.database;
|
package org.isoron.uhabits.database;
|
||||||
|
|
||||||
|
import android.support.annotation.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.core.database.*;
|
import org.isoron.uhabits.core.database.*;
|
||||||
|
|
||||||
public class AndroidCursor implements Cursor
|
public class AndroidCursor implements Cursor
|
||||||
@@ -45,26 +47,34 @@ public class AndroidCursor implements Cursor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Nullable
|
||||||
public Integer getInt(int index)
|
public Integer getInt(int index)
|
||||||
{
|
{
|
||||||
return cursor.getInt(index);
|
if(cursor.isNull(index)) return null;
|
||||||
|
else return cursor.getInt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Nullable
|
||||||
public Long getLong(int index)
|
public Long getLong(int index)
|
||||||
{
|
{
|
||||||
return cursor.getLong(index);
|
if(cursor.isNull(index)) return null;
|
||||||
|
else return cursor.getLong(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Nullable
|
||||||
public Double getDouble(int index)
|
public Double getDouble(int index)
|
||||||
{
|
{
|
||||||
return cursor.getDouble(index);
|
if(cursor.isNull(index)) return null;
|
||||||
|
else return cursor.getDouble(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Nullable
|
||||||
public String getString(int index)
|
public String getString(int index)
|
||||||
{
|
{
|
||||||
return cursor.getString(index);
|
if(cursor.isNull(index)) return null;
|
||||||
|
else return cursor.getString(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,8 +107,9 @@ public class AndroidDatabase implements Database
|
|||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
for (Map.Entry<String, Object> entry : map.entrySet())
|
for (Map.Entry<String, Object> entry : map.entrySet())
|
||||||
{
|
{
|
||||||
if (entry.getValue() == null) continue;
|
if (entry.getValue() == null)
|
||||||
if (entry.getValue() instanceof Integer)
|
values.putNull(entry.getKey());
|
||||||
|
else if (entry.getValue() instanceof Integer)
|
||||||
values.put(entry.getKey(), (Integer) entry.getValue());
|
values.put(entry.getKey(), (Integer) entry.getValue());
|
||||||
else if (entry.getValue() instanceof Long)
|
else if (entry.getValue() instanceof Long)
|
||||||
values.put(entry.getKey(), (Long) entry.getValue());
|
values.put(entry.getKey(), (Long) entry.getValue());
|
||||||
|
|||||||
@@ -19,18 +19,50 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.core.database;
|
package org.isoron.uhabits.core.database;
|
||||||
|
|
||||||
|
import android.support.annotation.*;
|
||||||
|
|
||||||
public interface Cursor extends AutoCloseable
|
public interface Cursor extends AutoCloseable
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the cursor forward one row from its current position. Returns
|
||||||
|
* true if the current position is valid, or false if the cursor is already
|
||||||
|
* past the last row. The cursor start at position -1, so this method must
|
||||||
|
* be called first.
|
||||||
|
*/
|
||||||
boolean moveToNext();
|
boolean moveToNext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the designated column in the current row of this
|
||||||
|
* Cursor as an Integer. If the value is null, returns null. The first
|
||||||
|
* column has index zero.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
Integer getInt(int index);
|
Integer getInt(int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the designated column in the current row of this
|
||||||
|
* Cursor as a Long. If the value is null, returns null. The first
|
||||||
|
* column has index zero.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
Long getLong(int index);
|
Long getLong(int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the designated column in the current row of this
|
||||||
|
* Cursor as a Double. If the value is null, returns null. The first
|
||||||
|
* column has index zero.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
Double getDouble(int index);
|
Double getDouble(int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the designated column in the current row of this
|
||||||
|
* Cursor as a String. If the value is null, returns null. The first
|
||||||
|
* column has index zero.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
String getString(int index);
|
String getString(int index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,9 @@ public class JdbcCursor implements Cursor
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return resultSet.getInt(index + 1);
|
Integer value = resultSet.getInt(index + 1);
|
||||||
|
if(resultSet.wasNull()) return null;
|
||||||
|
else return value;
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (SQLException e)
|
||||||
{
|
{
|
||||||
@@ -76,7 +78,9 @@ public class JdbcCursor implements Cursor
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return resultSet.getLong(index + 1);
|
Long value = resultSet.getLong(index + 1);
|
||||||
|
if(resultSet.wasNull()) return null;
|
||||||
|
else return value;
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (SQLException e)
|
||||||
{
|
{
|
||||||
@@ -89,7 +93,9 @@ public class JdbcCursor implements Cursor
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return resultSet.getDouble(index + 1);
|
Double value = resultSet.getDouble(index + 1);
|
||||||
|
if(resultSet.wasNull()) return null;
|
||||||
|
else return value;
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (SQLException e)
|
||||||
{
|
{
|
||||||
@@ -102,7 +108,9 @@ public class JdbcCursor implements Cursor
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return resultSet.getString(index + 1);
|
String value = resultSet.getString(index + 1);
|
||||||
|
if(resultSet.wasNull()) return null;
|
||||||
|
else return value;
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (SQLException e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class RepositoryTest extends BaseUnitTest
|
|||||||
db.execute("create table tests(" +
|
db.execute("create table tests(" +
|
||||||
"id integer not null primary key autoincrement, " +
|
"id integer not null primary key autoincrement, " +
|
||||||
"color_number integer not null, score float not null, " +
|
"color_number integer not null, score float not null, " +
|
||||||
"name string not null)");
|
"name string)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -82,6 +82,21 @@ public class RepositoryTest extends BaseUnitTest
|
|||||||
assertThat(record, equalTo(repository.find(50L)));
|
assertThat(record, equalTo(repository.find(50L)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSave_withNull() throws Exception
|
||||||
|
{
|
||||||
|
ThingRecord record = new ThingRecord();
|
||||||
|
record.color = 50;
|
||||||
|
record.name = null;
|
||||||
|
record.score = 12.0;
|
||||||
|
repository.save(record);
|
||||||
|
|
||||||
|
ThingRecord retrieved = repository.find(record.id);
|
||||||
|
assertNotNull(retrieved);
|
||||||
|
assertNull(retrieved.name);
|
||||||
|
assertThat(record, equalTo(retrieved));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSave_withoutId() throws Exception
|
public void testSave_withoutId() throws Exception
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class HabitRecordTest extends BaseUnitTest
|
|||||||
{
|
{
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCopyFrom()
|
public void testCopyRestore1()
|
||||||
{
|
{
|
||||||
Habit original = modelFactory.buildHabit();
|
Habit original = modelFactory.buildHabit();
|
||||||
original.setName("Hello world");
|
original.setName("Hello world");
|
||||||
@@ -52,4 +52,30 @@ public class HabitRecordTest extends BaseUnitTest
|
|||||||
|
|
||||||
assertThat(original.getData(), equalTo(duplicate.getData()));
|
assertThat(original.getData(), equalTo(duplicate.getData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyRestore2()
|
||||||
|
{
|
||||||
|
Habit original = modelFactory.buildHabit();
|
||||||
|
original.setName("Hello world");
|
||||||
|
original.setDescription("Did you greet the world today?");
|
||||||
|
original.setColor(5);
|
||||||
|
original.setArchived(false);
|
||||||
|
original.setFrequency(Frequency.DAILY);
|
||||||
|
original.setReminder(null);
|
||||||
|
original.setId(1L);
|
||||||
|
original.setPosition(15);
|
||||||
|
original.setType(Habit.NUMBER_HABIT);
|
||||||
|
original.setTargetValue(100);
|
||||||
|
original.setTargetType(Habit.AT_LEAST);
|
||||||
|
original.setUnit("miles");
|
||||||
|
|
||||||
|
HabitRecord record = new HabitRecord();
|
||||||
|
record.copyFrom(original);
|
||||||
|
|
||||||
|
Habit duplicate = modelFactory.buildHabit();
|
||||||
|
record.copyTo(duplicate);
|
||||||
|
|
||||||
|
assertThat(original.getData(), equalTo(duplicate.getData()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user