DatabaseStatementTest.java revision 1a44d5dcabc18cd5ef111f732ccff91683a1a093
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.database;
18
19import android.content.Context;
20import android.database.Cursor;
21import android.database.sqlite.SQLiteConstraintException;
22import android.database.sqlite.SQLiteDatabase;
23import android.database.sqlite.SQLiteDoneException;
24import android.database.sqlite.SQLiteStatement;
25import android.test.AndroidTestCase;
26import android.test.PerformanceTestCase;
27import android.test.suitebuilder.annotation.MediumTest;
28import android.test.suitebuilder.annotation.SmallTest;
29import junit.framework.TestCase;
30
31import java.io.File;
32
33public class DatabaseStatementTest extends AndroidTestCase implements PerformanceTestCase {
34
35    private static final String sString1 = "this is a test";
36    private static final String sString2 = "and yet another test";
37    private static final String sString3 = "this string is a little longer, but still a test";
38
39    private static final int CURRENT_DATABASE_VERSION = 42;
40    private SQLiteDatabase mDatabase;
41    private File mDatabaseFile;
42
43    @Override
44    protected void setUp() throws Exception {
45        super.setUp();
46	File dbDir = getContext().getDir("tests", Context.MODE_PRIVATE);
47	mDatabaseFile = new File(dbDir, "database_test.db");
48
49        if (mDatabaseFile.exists()) {
50            mDatabaseFile.delete();
51        }
52        mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
53        assertNotNull(mDatabase);
54        mDatabase.setVersion(CURRENT_DATABASE_VERSION);
55    }
56
57    @Override
58    protected void tearDown() throws Exception {
59        mDatabase.close();
60        mDatabaseFile.delete();
61        super.tearDown();
62    }
63
64    public boolean isPerformanceOnly() {
65        return false;
66    }
67
68    // These test can only be run once.
69    public int startPerformance(Intermediates intermediates) {
70        return 1;
71    }
72
73    private void populateDefaultTable() {
74        mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);");
75
76        mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString1 + "');");
77        mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString2 + "');");
78        mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString3 + "');");
79    }
80
81    @MediumTest
82    public void testExecuteStatement() throws Exception {
83        populateDefaultTable();
84        SQLiteStatement statement = mDatabase.compileStatement("DELETE FROM test");
85        statement.execute();
86
87        Cursor c = mDatabase.query("test", null, null, null, null, null, null);
88        assertEquals(0, c.getCount());
89        c.deactivate();
90        statement.close();
91    }
92
93    @MediumTest
94    public void testSimpleQuery() throws Exception {
95        mDatabase.execSQL("CREATE TABLE test (num INTEGER NOT NULL, str TEXT NOT NULL);");
96        mDatabase.execSQL("INSERT INTO test VALUES (1234, 'hello');");
97        SQLiteStatement statement1 =
98                mDatabase.compileStatement("SELECT num FROM test WHERE str = ?");
99        SQLiteStatement statement2 =
100                mDatabase.compileStatement("SELECT str FROM test WHERE num = ?");
101
102        try {
103            statement1.bindString(1, "hello");
104            long value = statement1.simpleQueryForLong();
105            assertEquals(1234, value);
106
107            statement1.bindString(1, "world");
108            statement1.simpleQueryForLong();
109            fail("shouldn't get here");
110        } catch (SQLiteDoneException e) {
111            // expected
112        }
113
114        try {
115            statement2.bindLong(1, 1234);
116            String value = statement1.simpleQueryForString();
117            assertEquals("hello", value);
118
119            statement2.bindLong(1, 5678);
120            statement1.simpleQueryForString();
121            fail("shouldn't get here");
122        } catch (SQLiteDoneException e) {
123            // expected
124        }
125
126        statement1.close();
127        statement2.close();
128    }
129
130    @MediumTest
131    public void testStatementLongBinding() throws Exception {
132        mDatabase.execSQL("CREATE TABLE test (num INTEGER);");
133        SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)");
134
135        for (int i = 0; i < 10; i++) {
136            statement.bindLong(1, i);
137            statement.execute();
138        }
139        statement.close();
140
141        Cursor c = mDatabase.query("test", null, null, null, null, null, null);
142        int numCol = c.getColumnIndexOrThrow("num");
143        c.moveToFirst();
144        for (long i = 0; i < 10; i++) {
145            long num = c.getLong(numCol);
146            assertEquals(i, num);
147            c.moveToNext();
148        }
149        c.close();
150    }
151
152    @MediumTest
153    public void testStatementStringBinding() throws Exception {
154        mDatabase.execSQL("CREATE TABLE test (num TEXT);");
155        SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)");
156
157        for (long i = 0; i < 10; i++) {
158            statement.bindString(1, Long.toHexString(i));
159            statement.execute();
160        }
161        statement.close();
162
163        Cursor c = mDatabase.query("test", null, null, null, null, null, null);
164        int numCol = c.getColumnIndexOrThrow("num");
165        c.moveToFirst();
166        for (long i = 0; i < 10; i++) {
167            String num = c.getString(numCol);
168            assertEquals(Long.toHexString(i), num);
169            c.moveToNext();
170        }
171        c.close();
172    }
173
174    @MediumTest
175    public void testStatementClearBindings() throws Exception {
176        mDatabase.execSQL("CREATE TABLE test (num INTEGER);");
177        SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)");
178
179        for (long i = 0; i < 10; i++) {
180            statement.bindLong(1, i);
181            statement.clearBindings();
182            statement.execute();
183        }
184        statement.close();
185
186        Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID");
187        int numCol = c.getColumnIndexOrThrow("num");
188        assertTrue(c.moveToFirst());
189        for (long i = 0; i < 10; i++) {
190            assertTrue(c.isNull(numCol));
191            c.moveToNext();
192        }
193        c.close();
194    }
195
196    @MediumTest
197    public void testSimpleStringBinding() throws Exception {
198        mDatabase.execSQL("CREATE TABLE test (num TEXT, value TEXT);");
199        String statement = "INSERT INTO test (num, value) VALUES (?,?)";
200
201        String[] args = new String[2];
202        for (int i = 0; i < 2; i++) {
203            args[i] = Integer.toHexString(i);
204        }
205
206        mDatabase.execSQL(statement, args);
207
208        Cursor c = mDatabase.query("test", null, null, null, null, null, null);
209        int numCol = c.getColumnIndexOrThrow("num");
210        int valCol = c.getColumnIndexOrThrow("value");
211        c.moveToFirst();
212        String num = c.getString(numCol);
213        assertEquals(Integer.toHexString(0), num);
214
215        String val = c.getString(valCol);
216        assertEquals(Integer.toHexString(1), val);
217        c.close();
218    }
219
220    @MediumTest
221    public void testStatementMultipleBindings() throws Exception {
222        mDatabase.execSQL("CREATE TABLE test (num INTEGER, str TEXT);");
223        SQLiteStatement statement =
224                mDatabase.compileStatement("INSERT INTO test (num, str) VALUES (?, ?)");
225
226        for (long i = 0; i < 10; i++) {
227            statement.bindLong(1, i);
228            statement.bindString(2, Long.toHexString(i));
229            statement.execute();
230        }
231        statement.close();
232
233        Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID");
234        int numCol = c.getColumnIndexOrThrow("num");
235        int strCol = c.getColumnIndexOrThrow("str");
236        assertTrue(c.moveToFirst());
237        for (long i = 0; i < 10; i++) {
238            long num = c.getLong(numCol);
239            String str = c.getString(strCol);
240            assertEquals(i, num);
241            assertEquals(Long.toHexString(i), str);
242            c.moveToNext();
243        }
244        c.close();
245    }
246
247    private static class StatementTestThread extends Thread {
248        private SQLiteDatabase mDatabase;
249        private SQLiteStatement mStatement;
250
251        public StatementTestThread(SQLiteDatabase db, SQLiteStatement statement) {
252            super();
253            mDatabase = db;
254            mStatement = statement;
255        }
256
257        @Override
258        public void run() {
259            mDatabase.beginTransaction();
260            for (long i = 0; i < 10; i++) {
261                mStatement.bindLong(1, i);
262                mStatement.bindString(2, Long.toHexString(i));
263                mStatement.execute();
264            }
265            mDatabase.setTransactionSuccessful();
266            mDatabase.endTransaction();
267
268            Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID");
269            int numCol = c.getColumnIndexOrThrow("num");
270            int strCol = c.getColumnIndexOrThrow("str");
271            assertTrue(c.moveToFirst());
272            for (long i = 0; i < 10; i++) {
273                long num = c.getLong(numCol);
274                String str = c.getString(strCol);
275                assertEquals(i, num);
276                assertEquals(Long.toHexString(i), str);
277                c.moveToNext();
278            }
279            c.close();
280        }
281    }
282
283    @MediumTest
284    public void testStatementMultiThreaded() throws Exception {
285        mDatabase.execSQL("CREATE TABLE test (num INTEGER, str TEXT);");
286        SQLiteStatement statement =
287                mDatabase.compileStatement("INSERT INTO test (num, str) VALUES (?, ?)");
288
289        StatementTestThread thread = new StatementTestThread(mDatabase, statement);
290        thread.start();
291        try {
292            thread.join();
293        } finally {
294            statement.close();
295        }
296    }
297
298    @MediumTest
299    public void testStatementConstraint() throws Exception {
300        mDatabase.execSQL("CREATE TABLE test (num INTEGER NOT NULL);");
301        SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)");
302
303        // Try to insert NULL, which violates the constraint
304        try {
305            statement.clearBindings();
306            statement.execute();
307            fail("expected exception not thrown");
308        } catch (SQLiteConstraintException e) {
309            // expected
310        }
311
312        // Make sure the statement can still be used
313        statement.bindLong(1, 1);
314        statement.execute();
315        statement.close();
316
317        Cursor c = mDatabase.query("test", null, null, null, null, null, null);
318        int numCol = c.getColumnIndexOrThrow("num");
319        c.moveToFirst();
320        long num = c.getLong(numCol);
321        assertEquals(1, num);
322        c.close();
323    }
324}
325