Anyway, the obvious solution to this problem is to create the frequency number as a new field in the question table. This will be a one-off exercise, using the existing code which reads in the data, and the update logic which we implemented yesterday.
So - let's take a look at the code:
for (Question question : rows) {
// The counter is used as the sequentially assigned frequency number.
cntr++;
// null questions mean they haven't been seen yet
if (null == question.nextReviewDate_YYYY_MM_DD) {
// this will need to change to checking question.freq_sequence number
if ((cntr >= startNum) && (cntr <= endNum)) {
// question.number is like an id
quizSequence.add(new Integer(question.number));
}
} else {
// it automatically adds the row if it's not null
// because a scheduled date exists for it and
// that date is .le. the parameter date (should be
// today's date unless testing)
quizSequence.add(new Integer(question.number));
}
}
Ok, first, lets bring up RazorSQL and add the field. Ok, done. I love wizards.
Ok, now, lets modify this code to update the question with a freq_seq:
public void updateFreqSequence(int id, int freqSequence) {
// private static final String UPDATE = "update " + WORD_REVIEW_SCHEDULE
// + "set freq_sequence = ?) where _id = ?";
ContentValues contentValues = new ContentValues();
contentValues.put("last_review_date", lastReviewDate);
contentValues.put("next_review_date", nextReviewDate);
this.myDataBase.update(DataBaseHelper.WORD_REVIEW_SCHEDULE,
contentValues, "_id=?", new String[] { Integer.toString(id) });
}
How does this look:
public void updateFreqSequence(int id, int freqSequence) {
ContentValues contentValues = new ContentValues();
contentValues.put("freq_sequence", freqSequence);
this.myDataBase.update(DataBaseHelper.ALL_WORDS_TABLE,
contentValues, "_id=?", new String[] { Integer.toString(id) });
}
We'll have to clear the schedule table to make sure all the questions make it through the quiz. That could be an argument for keeping it as a separate table. The strongest argument against is the time it takes to insert vs. the time it takes to update. And update must be faster.
Actually, we can just comment out all the filters for now.
Let's create a select on everything:
public ArrayList
// Cursor cursor = this.myDataBase.query("all_words",
// new String[] { "english" }, null, null, null, null, null);
// todo change to join view to pick up next - or not
Cursor cursor = this.myDataBase.query(VIEW_BY_FREQ, new String[] {
"_id", "level", "number", "kanji", "hiragana", "english",
"freq" }, null, null, null, null,
null);
ArrayList
I added a view to the DB to just select on frequency, without the level.
Ok, how about this for the code:
public void initQuizSequence(Context context, int startNum, int endNum) {
Log.d(TAG, "initQuizSequence");
quizSequence.clear();
DataBaseHelper dbHelper = DataBaseHelper.createDB(context);
//ArrayList
// jlptLevel, "2011-11-17");
ArrayList
dbHelper.close();
int cntr = 0;
for (Question question : rows) {
cntr++;
dbHelper = DataBaseHelper.createDB(context);
dbHelper.updateFreqSequence(question.id, cntr);
dbHelper.close();
}
Ok, it's going to be a while. For some reason, if I don't run the dbHelper open/close after each update, I get some kind of corrupt image malfromed exception. But in the meantime it's taking about 1 second per update. So, at 5 or 6 thousand words, 6000/60 = 600/6 = 100 minutest - an hour and 1/2.
Well while that's running, let's see how long it takes to run that same routine on the mac.
Well, it's not so simple. A lot of the code is Android specific...I need a driver, probably. I just really dislike it when things take so long. I wonder if there's a way to do it using, like an _id number on the view or something?
Here's a post highly recommended on SO:
http://stackoverflow.com/questions/41233/java-and-sqlite
Ok, pretty good. It created a table called test.db in the root.
Let's see if I can get it to list the table by freq:
Let's try this:
ResultSet rs = stat.executeQuery("select * from v_all_words_by_freq;");
while (rs.next()) {
System.out.println("english = " + rs.getString("english"));
System.out.println("freq = " + rs.getString("freq"));
}
Wow. Now that was fast!
Ok, how about we try out the update statement?
How does this look?
PreparedStatement prep = conn.prepareStatement(
"update all_words set freq_sequence = ? where _id = ?;");
int cntr = 1;
ResultSet rs = stat.executeQuery("select * from v_all_words_by_freq;");
while (rs.next()) {
System.out.println("english = " + rs.getString("english"));
System.out.println("freq = " + rs.getString("freq"));
int _id = rs.getInt("_id");
prep.setInt(1, cntr);
prep.setInt(2, _id);
prep.addBatch();
cntr++;
//prep.setString(2, "politics");
}
conn.setAutoCommit(false);
prep.executeBatch();
conn.setAutoCommit(true);
And we are done!
The update on the phone is still crawling around at 2500.
Ok, let's kill that and move the updated database into the project. That was great. What a dramatic exhibition of the difference in processing power between a phone and a laptop/macbook.
Ok, that's a wrap for now. I'll pick this up in the next post.
For prosperity, here is the body of the SO post:
http://stackoverflow.com/questions/41233/java-and-sqlite
Hey I found your questions while search for information with SQLite and Java. Just thought I add my answer which I also posted on my blog.
I have been coding in Java for a while know. I have also known about SQLite but never used it… Well I have have used it through other applications but never in an app that I coded. So I needed it for a project this week and its so simple use!
First I found the website of David Crawshaw who has a Java JDBC driver for SQLite. Just add his JAR file to your classpath and import java.sql.*
His test app will create a database file, send some SQL commands to create a table, store some data in the table, and read it back and display on console. It will create the test.db file in the root directory of the project.
public class Test {
public static void main(String[] args) throws Exception {
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:test.db");
Statement stat = conn.createStatement();
stat.executeUpdate("drop table if exists people;");
stat.executeUpdate("create table people (name, occupation);");
PreparedStatement prep = conn.prepareStatement(
"insert into people values (?, ?);");
prep.setString(1, "Gandhi");
prep.setString(2, "politics");
prep.addBatch();
prep.setString(1, "Turing");
prep.setString(2, "computers");
prep.addBatch();
prep.setString(1, "Wittgenstein");
prep.setString(2, "smartypants");
prep.addBatch();
conn.setAutoCommit(false);
prep.executeBatch();
conn.setAutoCommit(true);
ResultSet rs = stat.executeQuery("select * from people;");
while (rs.next()) {
System.out.println("name = " + rs.getString("name"));
System.out.println("job = " + rs.getString("occupation"));
}
rs.close();
conn.close();
}
}
No comments:
Post a Comment