DatabaseGeneralTest.java revision 85f08f9eaeae6b04c6ce42e5b9dc097ac3e70fc5
1/* 2 * Copyright (C) 2006 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 static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_COLUMNNAME_INDEX; 20import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_DEFAULT_INDEX; 21import android.content.ContentValues; 22import android.content.Context; 23import android.database.sqlite.SQLiteDatabase; 24import android.database.sqlite.SQLiteStatement; 25import android.os.Handler; 26import android.os.Parcel; 27import android.test.AndroidTestCase; 28import android.test.PerformanceTestCase; 29import android.test.suitebuilder.annotation.LargeTest; 30import android.test.suitebuilder.annotation.MediumTest; 31import android.test.suitebuilder.annotation.SmallTest; 32import android.util.Log; 33import android.util.Pair; 34 35import junit.framework.Assert; 36 37import java.io.File; 38import java.util.ArrayList; 39import java.util.Arrays; 40import java.util.Locale; 41 42public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceTestCase { 43 private static final String TAG = "DatabaseGeneralTest"; 44 45 private static final String sString1 = "this is a test"; 46 private static final String sString2 = "and yet another test"; 47 private static final String sString3 = "this string is a little longer, but still a test"; 48 private static final String PHONE_NUMBER = "16175551212"; 49 50 private static final int CURRENT_DATABASE_VERSION = 42; 51 private SQLiteDatabase mDatabase; 52 private File mDatabaseFile; 53 54 @Override 55 protected void setUp() throws Exception { 56 super.setUp(); 57 File dbDir = getContext().getDir(this.getClass().getName(), Context.MODE_PRIVATE); 58 mDatabaseFile = new File(dbDir, "database_test.db"); 59 if (mDatabaseFile.exists()) { 60 mDatabaseFile.delete(); 61 } 62 mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null); 63 assertNotNull(mDatabase); 64 mDatabase.setVersion(CURRENT_DATABASE_VERSION); 65 } 66 67 @Override 68 protected void tearDown() throws Exception { 69 mDatabase.close(); 70 mDatabaseFile.delete(); 71 super.tearDown(); 72 } 73 74 public boolean isPerformanceOnly() { 75 return false; 76 } 77 78 // These test can only be run once. 79 public int startPerformance(Intermediates intermediates) { 80 return 1; 81 } 82 83 private void populateDefaultTable() { 84 mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); 85 86 mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString1 + "');"); 87 mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString2 + "');"); 88 mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString3 + "');"); 89 } 90 91 @MediumTest 92 public void testVersion() throws Exception { 93 assertEquals(CURRENT_DATABASE_VERSION, mDatabase.getVersion()); 94 mDatabase.setVersion(11); 95 assertEquals(11, mDatabase.getVersion()); 96 } 97 98 @MediumTest 99 public void testUpdate() throws Exception { 100 populateDefaultTable(); 101 102 ContentValues values = new ContentValues(1); 103 values.put("data", "this is an updated test"); 104 assertEquals(1, mDatabase.update("test", values, "_id=1", null)); 105 Cursor c = mDatabase.query("test", null, "_id=1", null, null, null, null); 106 assertNotNull(c); 107 assertEquals(1, c.getCount()); 108 c.moveToFirst(); 109 String value = c.getString(c.getColumnIndexOrThrow("data")); 110 assertEquals("this is an updated test", value); 111 } 112 113 @MediumTest 114 public void testPhoneNumbersEqual() throws Exception { 115 mDatabase.execSQL("CREATE TABLE phones (num TEXT);"); 116 mDatabase.execSQL("INSERT INTO phones (num) VALUES ('911');"); 117 mDatabase.execSQL("INSERT INTO phones (num) VALUES ('5555');"); 118 mDatabase.execSQL("INSERT INTO phones (num) VALUES ('+" + PHONE_NUMBER + "');"); 119 120 String number; 121 Cursor c; 122 123 c = mDatabase.query("phones", null, 124 "PHONE_NUMBERS_EQUAL(num, '504-555-7683')", null, null, null, null); 125 assertTrue(c == null || c.getCount() == 0); 126 c.close(); 127 128 c = mDatabase.query("phones", null, 129 "PHONE_NUMBERS_EQUAL(num, '911')", null, null, null, null); 130 assertNotNull(c); 131 assertEquals(1, c.getCount()); 132 c.moveToFirst(); 133 number = c.getString(c.getColumnIndexOrThrow("num")); 134 assertEquals("911", number); 135 c.close(); 136 137 c = mDatabase.query("phones", null, 138 "PHONE_NUMBERS_EQUAL(num, '5555')", null, null, null, null); 139 assertNotNull(c); 140 assertEquals(1, c.getCount()); 141 c.moveToFirst(); 142 number = c.getString(c.getColumnIndexOrThrow("num")); 143 assertEquals("5555", number); 144 c.close(); 145 146 c = mDatabase.query("phones", null, 147 "PHONE_NUMBERS_EQUAL(num, '180055555555')", null, null, null, null); 148 assertTrue(c == null || c.getCount() == 0); 149 c.close(); 150 151 c = mDatabase.query("phones", null, 152 "PHONE_NUMBERS_EQUAL(num, '+" + PHONE_NUMBER + "')", null, null, null, null); 153 assertNotNull(c); 154 assertEquals(1, c.getCount()); 155 c.moveToFirst(); 156 number = c.getString(c.getColumnIndexOrThrow("num")); 157 assertEquals("+" + PHONE_NUMBER, number); 158 c.close(); 159 160 c = mDatabase.query("phones", null, 161 "PHONE_NUMBERS_EQUAL(num, '+1 (617).555-1212')", null, null, null, null); 162 assertNotNull(c); 163 assertEquals(1, c.getCount()); 164 c.moveToFirst(); 165 number = c.getString(c.getColumnIndexOrThrow("num")); 166 assertEquals("+" + PHONE_NUMBER, number); 167 c.close(); 168 169 c = mDatabase.query("phones", null, 170 "PHONE_NUMBERS_EQUAL(num, '" + PHONE_NUMBER + "')", null, null, null, null); 171 assertNotNull(c); 172 assertEquals(1, c.getCount()); 173 c.moveToFirst(); 174 number = c.getString(c.getColumnIndexOrThrow("num")); 175 assertEquals("+" + PHONE_NUMBER, number); 176 c.close(); 177 178 /* 179 c = mDatabase.query("phones", null, 180 "PHONE_NUMBERS_EQUAL(num, '5551212')", null, null, null, null); 181 assertNotNull(c); 182 assertEquals(1, c.getCount()); 183 c.moveToFirst(); 184 number = c.getString(c.getColumnIndexOrThrow("num")); 185 assertEquals("+" + PHONE_NUMBER, number); 186 c.close(); 187 */ 188 189 c = mDatabase.query("phones", null, 190 "PHONE_NUMBERS_EQUAL(num, '011" + PHONE_NUMBER + "')", null, null, null, null); 191 assertNotNull(c); 192 assertEquals(1, c.getCount()); 193 c.moveToFirst(); 194 number = c.getString(c.getColumnIndexOrThrow("num")); 195 assertEquals("+" + PHONE_NUMBER, number); 196 c.close(); 197 198 c = mDatabase.query("phones", null, 199 "PHONE_NUMBERS_EQUAL(num, '00" + PHONE_NUMBER + "')", null, null, null, null); 200 assertNotNull(c); 201 assertEquals(1, c.getCount()); 202 c.moveToFirst(); 203 number = c.getString(c.getColumnIndexOrThrow("num")); 204 assertEquals("+" + PHONE_NUMBER, number); 205 c.close(); 206 } 207 208 private void phoneNumberCompare(String phone1, String phone2, boolean equal, 209 boolean useStrictComparation) { 210 String[] temporalPhoneNumbers = new String[2]; 211 temporalPhoneNumbers[0] = phone1; 212 temporalPhoneNumbers[1] = phone2; 213 214 Cursor cursor = mDatabase.rawQuery( 215 String.format( 216 "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?, %d) " + 217 "THEN 'equal' ELSE 'not equal' END", 218 (useStrictComparation ? 1 : 0)), 219 temporalPhoneNumbers); 220 try { 221 assertNotNull(cursor); 222 assertTrue(cursor.moveToFirst()); 223 if (equal) { 224 assertEquals(String.format("Unexpectedly, \"%s != %s\".", phone1, phone2), 225 "equal", cursor.getString(0)); 226 } else { 227 assertEquals(String.format("Unexpectedly, \"%s\" == \"%s\".", phone1, phone2), 228 "not equal", cursor.getString(0)); 229 } 230 } finally { 231 if (cursor != null) { 232 cursor.close(); 233 } 234 } 235 } 236 237 private void assertPhoneNumberEqual(String phone1, String phone2) throws Exception { 238 assertPhoneNumberEqual(phone1, phone2, true); 239 assertPhoneNumberEqual(phone1, phone2, false); 240 } 241 242 private void assertPhoneNumberEqual(String phone1, String phone2, boolean useStrict) 243 throws Exception { 244 phoneNumberCompare(phone1, phone2, true, useStrict); 245 } 246 247 private void assertPhoneNumberNotEqual(String phone1, String phone2) throws Exception { 248 assertPhoneNumberNotEqual(phone1, phone2, true); 249 assertPhoneNumberNotEqual(phone1, phone2, false); 250 } 251 252 private void assertPhoneNumberNotEqual(String phone1, String phone2, boolean useStrict) 253 throws Exception { 254 phoneNumberCompare(phone1, phone2, false, useStrict); 255 } 256 257 /** 258 * Tests international matching issues for the PHONE_NUMBERS_EQUAL function. 259 * 260 * @throws Exception 261 */ 262 @SmallTest 263 public void testPhoneNumbersEqualInternationl() throws Exception { 264 assertPhoneNumberEqual("1", "1"); 265 assertPhoneNumberEqual("123123", "123123"); 266 assertPhoneNumberNotEqual("123123", "923123"); 267 assertPhoneNumberNotEqual("123123", "123129"); 268 assertPhoneNumberNotEqual("123123", "1231234"); 269 assertPhoneNumberNotEqual("123123", "0123123", false); 270 assertPhoneNumberNotEqual("123123", "0123123", true); 271 assertPhoneNumberEqual("650-253-0000", "6502530000"); 272 assertPhoneNumberEqual("650-253-0000", "650 253 0000"); 273 assertPhoneNumberEqual("650 253 0000", "6502530000"); 274 assertPhoneNumberEqual("+1 650-253-0000", "6502530000"); 275 assertPhoneNumberEqual("001 650-253-0000", "6502530000"); 276 assertPhoneNumberEqual("0111 650-253-0000", "6502530000"); 277 278 // Russian trunk digit 279 assertPhoneNumberEqual("+79161234567", "89161234567"); 280 281 // French trunk digit 282 assertPhoneNumberEqual("+33123456789", "0123456789"); 283 284 // Trunk digit for city codes in the Netherlands 285 assertPhoneNumberEqual("+31771234567", "0771234567"); 286 287 // Test broken caller ID seen on call from Thailand to the US 288 assertPhoneNumberEqual("+66811234567", "166811234567"); 289 290 // Test the same in-country number with different country codes 291 assertPhoneNumberNotEqual("+33123456789", "+1123456789"); 292 293 // Test one number with country code and the other without 294 assertPhoneNumberEqual("5125551212", "+15125551212"); 295 296 // Test two NANP numbers that only differ in the area code 297 assertPhoneNumberNotEqual("5125551212", "6505551212"); 298 299 // Japanese phone numbers 300 assertPhoneNumberEqual("090-1234-5678", "+819012345678"); 301 assertPhoneNumberEqual("090(1234)5678", "+819012345678"); 302 assertPhoneNumberEqual("090-1234-5678", "+81-90-1234-5678"); 303 304 // Equador 305 assertPhoneNumberEqual("+593(800)123-1234", "8001231234"); 306 assertPhoneNumberEqual("+593-2-1234-123", "21234123"); 307 308 // Two continuous 0 at the beginning of the phone string should not be 309 // treated as trunk prefix in the strict comparation. 310 assertPhoneNumberEqual("008001231234", "8001231234", false); 311 assertPhoneNumberNotEqual("008001231234", "8001231234", true); 312 313 // Confirm that the bug found before does not re-appear in the strict compalation 314 assertPhoneNumberEqual("080-1234-5678", "+819012345678", false); 315 assertPhoneNumberNotEqual("080-1234-5678", "+819012345678", true); 316 } 317 318 @MediumTest 319 public void testCopyString() throws Exception { 320 mDatabase.execSQL("CREATE TABLE guess (numi INTEGER, numf FLOAT, str TEXT);"); 321 mDatabase.execSQL( 322 "INSERT INTO guess (numi,numf,str) VALUES (0,0.0,'ZoomZoomZoomZoom');"); 323 mDatabase.execSQL("INSERT INTO guess (numi,numf,str) VALUES (2000000000,3.1415926535,'');"); 324 String chinese = "\u4eac\u4ec5 \u5c3d\u5f84\u60ca"; 325 String[] arr = new String[1]; 326 arr[0] = chinese; 327 mDatabase.execSQL("INSERT INTO guess (numi,numf,str) VALUES (-32768,-1.0,?)", arr); 328 329 Cursor c; 330 331 c = mDatabase.rawQuery("SELECT * FROM guess", null); 332 333 c.moveToFirst(); 334 335 CharArrayBuffer buf = new CharArrayBuffer(14); 336 337 String compareTo = c.getString(c.getColumnIndexOrThrow("numi")); 338 int numiIdx = c.getColumnIndexOrThrow("numi"); 339 int numfIdx = c.getColumnIndexOrThrow("numf"); 340 int strIdx = c.getColumnIndexOrThrow("str"); 341 342 c.copyStringToBuffer(numiIdx, buf); 343 assertEquals(1, buf.sizeCopied); 344 assertEquals(compareTo, new String(buf.data, 0, buf.sizeCopied)); 345 346 c.copyStringToBuffer(strIdx, buf); 347 assertEquals("ZoomZoomZoomZoom", new String(buf.data, 0, buf.sizeCopied)); 348 349 c.moveToNext(); 350 compareTo = c.getString(numfIdx); 351 352 c.copyStringToBuffer(numfIdx, buf); 353 assertEquals(compareTo, new String(buf.data, 0, buf.sizeCopied)); 354 c.copyStringToBuffer(strIdx, buf); 355 assertEquals(0, buf.sizeCopied); 356 357 c.moveToNext(); 358 c.copyStringToBuffer(numfIdx, buf); 359 assertEquals(-1.0, Double.valueOf( 360 new String(buf.data, 0, buf.sizeCopied)).doubleValue()); 361 362 c.copyStringToBuffer(strIdx, buf); 363 compareTo = c.getString(strIdx); 364 assertEquals(chinese, compareTo); 365 366 assertEquals(chinese, new String(buf.data, 0, buf.sizeCopied)); 367 c.close(); 368 } 369 370 @MediumTest 371 public void testSchemaChange1() throws Exception { 372 SQLiteDatabase db1 = mDatabase; 373 Cursor cursor; 374 375 db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);"); 376 377 cursor = db1.query("db1", null, null, null, null, null, null); 378 assertNotNull("Cursor is null", cursor); 379 380 db1.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);"); 381 382 assertEquals(0, cursor.getCount()); 383 cursor.deactivate(); 384 } 385 386 @MediumTest 387 public void testSchemaChange2() throws Exception { 388 SQLiteDatabase db1 = mDatabase; 389 SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile, null); 390 Cursor cursor; 391 392 db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);"); 393 394 cursor = db1.query("db1", null, null, null, null, null, null); 395 assertNotNull("Cursor is null", cursor); 396 assertEquals(0, cursor.getCount()); 397 cursor.deactivate(); 398 // this cause exception because we're still using sqlite_prepate16 and not 399 // sqlite_prepare16_v2. The v2 variant added the ability to check the 400 // schema version and handle the case when the schema has changed 401 // Marco Nelissen claim it was 2x slower to compile SQL statements so 402 // I reverted back to the v1 variant. 403 /* db2.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);"); 404 405 cursor = db1.query("db1", null, null, null, null, null, null); 406 assertNotNull("Cursor is null", cursor); 407 assertEquals(0, cursor.count()); 408 cursor.deactivate(); 409 */ 410 } 411 412 @MediumTest 413 public void testSchemaChange3() throws Exception { 414 SQLiteDatabase db1 = mDatabase; 415 SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile, null); 416 Cursor cursor; 417 418 419 db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);"); 420 db1.execSQL("INSERT INTO db1 (data) VALUES ('test');"); 421 422 cursor = db1.query("db1", null, null, null, null, null, null); 423 // this cause exception because we're still using sqlite_prepate16 and not 424 // sqlite_prepare16_v2. The v2 variant added the ability to check the 425 // schema version and handle the case when the schema has changed 426 // Marco Nelissen claim it was 2x slower to compile SQL statements so 427 // I reverted back to the v1 variant. 428 /* db2.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);"); 429 430 assertNotNull("Cursor is null", cursor); 431 assertEquals(1, cursor.count()); 432 assertTrue(cursor.first()); 433 assertEquals("test", cursor.getString(cursor.getColumnIndexOrThrow("data"))); 434 cursor.deactivate(); 435 */ 436 } 437 438 private class ChangeObserver extends ContentObserver { 439 private int mCursorNotificationCount = 0; 440 private int mNotificationCount = 0; 441 442 public int getCursorNotificationCount() { 443 return mCursorNotificationCount; 444 } 445 446 public int getNotificationCount() { 447 return mNotificationCount; 448 } 449 450 public ChangeObserver(boolean cursor) { 451 super(new Handler()); 452 mCursor = cursor; 453 } 454 455 @Override 456 public boolean deliverSelfNotifications() { 457 return true; 458 } 459 460 @Override 461 public void onChange(boolean selfChange) { 462 if (mCursor) { 463 mCursorNotificationCount++; 464 } else { 465 mNotificationCount++; 466 } 467 } 468 469 boolean mCursor; 470 } 471 472 @MediumTest 473 public void testSelectionArgs() throws Exception { 474 mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); 475 ContentValues values = new ContentValues(1); 476 values.put("data", "don't forget to handled 's"); 477 mDatabase.insert("test", "data", values); 478 values.clear(); 479 values.put("data", "no apostrophes here"); 480 mDatabase.insert("test", "data", values); 481 Cursor c = mDatabase.query( 482 "test", null, "data GLOB ?", new String[]{"*'*"}, null, null, null); 483 assertEquals(1, c.getCount()); 484 assertTrue(c.moveToFirst()); 485 assertEquals("don't forget to handled 's", c.getString(1)); 486 c.deactivate(); 487 488 // make sure code should checking null string properly so that 489 // it won't crash 490 try { 491 mDatabase.query("test", new String[]{"_id"}, 492 "_id=?", new String[]{null}, null, null, null); 493 fail("expected exception not thrown"); 494 } catch (IllegalArgumentException e) { 495 // expected 496 } 497 } 498 499 @MediumTest 500 public void testTokenize() throws Exception { 501 Cursor c; 502 mDatabase.execSQL("CREATE TABLE tokens (" + 503 "token TEXT COLLATE unicode," + 504 "source INTEGER," + 505 "token_index INTEGER," + 506 "tag TEXT" + 507 ");"); 508 mDatabase.execSQL("CREATE TABLE tokens_no_index (" + 509 "token TEXT COLLATE unicode," + 510 "source INTEGER" + 511 ");"); 512 513 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 514 "SELECT _TOKENIZE(NULL, NULL, NULL, NULL)", null)); 515 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 516 "SELECT _TOKENIZE('tokens', NULL, NULL, NULL)", null)); 517 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 518 "SELECT _TOKENIZE('tokens', 10, NULL, NULL)", null)); 519 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 520 "SELECT _TOKENIZE('tokens', 10, 'some string', NULL)", null)); 521 522 Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, 523 "SELECT _TOKENIZE('tokens', 11, 'some string ok', ' ', 1, 'foo')", null)); 524 Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, 525 "SELECT _TOKENIZE('tokens', 11, 'second field', ' ', 1, 'bar')", null)); 526 527 Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, 528 "SELECT _TOKENIZE('tokens_no_index', 20, 'some string ok', ' ')", null)); 529 Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, 530 "SELECT _TOKENIZE('tokens_no_index', 21, 'foo bar baz', ' ', 0)", null)); 531 532 // test Chinese 533 String chinese = new String("\u4eac\u4ec5 \u5c3d\u5f84\u60ca"); 534 Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, 535 "SELECT _TOKENIZE('tokens', 12,'" + chinese + "', ' ', 1)", null)); 536 537 String icustr = new String("Fr\u00e9d\u00e9ric Hj\u00f8nnev\u00e5g"); 538 539 Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, 540 "SELECT _TOKENIZE('tokens', 13, '" + icustr + "', ' ', 1)", null)); 541 542 Assert.assertEquals(9, DatabaseUtils.longForQuery(mDatabase, 543 "SELECT count(*) from tokens;", null)); 544 545 String key = DatabaseUtils.getHexCollationKey("Frederic Hjonneva"); 546 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 547 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); 548 Assert.assertEquals(13, DatabaseUtils.longForQuery(mDatabase, 549 "SELECT source from tokens where token GLOB '" + key + "*'", null)); 550 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 551 "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); 552 key = DatabaseUtils.getHexCollationKey("Hjonneva"); 553 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 554 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); 555 Assert.assertEquals(13, DatabaseUtils.longForQuery(mDatabase, 556 "SELECT source from tokens where token GLOB '" + key + "*'", null)); 557 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 558 "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); 559 560 key = DatabaseUtils.getHexCollationKey("some string ok"); 561 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 562 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); 563 Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, 564 "SELECT source from tokens where token GLOB '" + key + "*'", null)); 565 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 566 "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); 567 Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase, 568 "SELECT tag from tokens where token GLOB '" + key + "*'", null)); 569 key = DatabaseUtils.getHexCollationKey("string"); 570 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 571 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); 572 Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, 573 "SELECT source from tokens where token GLOB '" + key + "*'", null)); 574 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 575 "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); 576 Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase, 577 "SELECT tag from tokens where token GLOB '" + key + "*'", null)); 578 key = DatabaseUtils.getHexCollationKey("ok"); 579 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 580 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); 581 Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, 582 "SELECT source from tokens where token GLOB '" + key + "*'", null)); 583 Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, 584 "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); 585 Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase, 586 "SELECT tag from tokens where token GLOB '" + key + "*'", null)); 587 588 key = DatabaseUtils.getHexCollationKey("second field"); 589 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 590 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); 591 Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, 592 "SELECT source from tokens where token GLOB '" + key + "*'", null)); 593 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 594 "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); 595 Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase, 596 "SELECT tag from tokens where token GLOB '" + key + "*'", null)); 597 key = DatabaseUtils.getHexCollationKey("field"); 598 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 599 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); 600 Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, 601 "SELECT source from tokens where token GLOB '" + key + "*'", null)); 602 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 603 "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); 604 Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase, 605 "SELECT tag from tokens where token GLOB '" + key + "*'", null)); 606 607 key = DatabaseUtils.getHexCollationKey(chinese); 608 String[] a = new String[1]; 609 a[0] = key; 610 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 611 "SELECT count(*) from tokens where token= ?", a)); 612 Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, 613 "SELECT source from tokens where token= ?", a)); 614 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 615 "SELECT token_index from tokens where token= ?", a)); 616 a[0] += "*"; 617 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 618 "SELECT count(*) from tokens where token GLOB ?", a)); 619 Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, 620 "SELECT source from tokens where token GLOB ?", a)); 621 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 622 "SELECT token_index from tokens where token GLOB ?", a)); 623 624 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 625 "SELECT count(*) from tokens where token= '" + key + "'", null)); 626 Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, 627 "SELECT source from tokens where token= '" + key + "'", null)); 628 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 629 "SELECT token_index from tokens where token= '" + key + "'", null)); 630 631 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 632 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); 633 Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, 634 "SELECT source from tokens where token GLOB '" + key + "*'", null)); 635 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 636 "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); 637 638 key = DatabaseUtils.getHexCollationKey("\u4eac\u4ec5"); 639 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 640 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); 641 Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, 642 "SELECT source from tokens where token GLOB '" + key + "*'", null)); 643 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 644 "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); 645 646 key = DatabaseUtils.getHexCollationKey("\u5c3d\u5f84\u60ca"); 647 Log.d("DatabaseGeneralTest", "key = " + key); 648 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 649 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); 650 Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, 651 "SELECT source from tokens where token GLOB '" + key + "*'", null)); 652 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 653 "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); 654 655 Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, 656 "SELECT count(*) from tokens where token GLOB 'ab*'", null)); 657 658 key = DatabaseUtils.getHexCollationKey("some string ok"); 659 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 660 "SELECT count(*) from tokens_no_index where token GLOB '" + key + "*'", null)); 661 Assert.assertEquals(20, DatabaseUtils.longForQuery(mDatabase, 662 "SELECT source from tokens_no_index where token GLOB '" + key + "*'", null)); 663 664 key = DatabaseUtils.getHexCollationKey("bar"); 665 Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 666 "SELECT count(*) from tokens_no_index where token GLOB '" + key + "*'", null)); 667 Assert.assertEquals(21, DatabaseUtils.longForQuery(mDatabase, 668 "SELECT source from tokens_no_index where token GLOB '" + key + "*'", null)); 669 } 670 671 @MediumTest 672 public void testTransactions() throws Exception { 673 mDatabase.execSQL("CREATE TABLE test (num INTEGER);"); 674 mDatabase.execSQL("INSERT INTO test (num) VALUES (0)"); 675 676 // Make sure that things work outside an explicit transaction. 677 setNum(1); 678 checkNum(1); 679 680 // Test a single-level transaction. 681 setNum(0); 682 mDatabase.beginTransaction(); 683 setNum(1); 684 mDatabase.setTransactionSuccessful(); 685 mDatabase.endTransaction(); 686 checkNum(1); 687 Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); 688 689 // Test a rolled-back transaction. 690 setNum(0); 691 mDatabase.beginTransaction(); 692 setNum(1); 693 mDatabase.endTransaction(); 694 checkNum(0); 695 Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); 696 697 // We should get an error if we end a non-existent transaction. 698 assertThrowsIllegalState(new Runnable() { public void run() { 699 mDatabase.endTransaction(); 700 }}); 701 702 // We should get an error if a set a non-existent transaction as clean. 703 assertThrowsIllegalState(new Runnable() { public void run() { 704 mDatabase.setTransactionSuccessful(); 705 }}); 706 707 mDatabase.beginTransaction(); 708 mDatabase.setTransactionSuccessful(); 709 // We should get an error if we mark a transaction as clean twice. 710 assertThrowsIllegalState(new Runnable() { public void run() { 711 mDatabase.setTransactionSuccessful(); 712 }}); 713 // We should get an error if we begin a transaction after marking the parent as clean. 714 assertThrowsIllegalState(new Runnable() { public void run() { 715 mDatabase.beginTransaction(); 716 }}); 717 mDatabase.endTransaction(); 718 Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); 719 720 // Test a two-level transaction. 721 setNum(0); 722 mDatabase.beginTransaction(); 723 mDatabase.beginTransaction(); 724 setNum(1); 725 mDatabase.setTransactionSuccessful(); 726 mDatabase.endTransaction(); 727 mDatabase.setTransactionSuccessful(); 728 mDatabase.endTransaction(); 729 checkNum(1); 730 Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); 731 732 // Test rolling back an inner transaction. 733 setNum(0); 734 mDatabase.beginTransaction(); 735 mDatabase.beginTransaction(); 736 setNum(1); 737 mDatabase.endTransaction(); 738 mDatabase.setTransactionSuccessful(); 739 mDatabase.endTransaction(); 740 checkNum(0); 741 Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); 742 743 // Test rolling back an outer transaction. 744 setNum(0); 745 mDatabase.beginTransaction(); 746 mDatabase.beginTransaction(); 747 setNum(1); 748 mDatabase.setTransactionSuccessful(); 749 mDatabase.endTransaction(); 750 mDatabase.endTransaction(); 751 checkNum(0); 752 Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); 753 } 754 755 private void setNum(int num) { 756 mDatabase.execSQL("UPDATE test SET num = " + num); 757 } 758 759 private void checkNum(int num) { 760 Assert.assertEquals( 761 num, DatabaseUtils.longForQuery(mDatabase, "SELECT num FROM test", null)); 762 } 763 764 private void assertThrowsIllegalState(Runnable r) { 765 boolean ok = false; 766 try { 767 r.run(); 768 } catch (IllegalStateException e) { 769 ok = true; 770 } 771 Assert.assertTrue(ok); 772 } 773 774 // Disable these until we can explicitly mark them as stress tests 775 public void xxtestMem1() throws Exception { 776 populateDefaultTable(); 777 778 for (int i = 0; i < 50000; i++) { 779 Cursor cursor = mDatabase.query("test", null, null, null, null, null, null); 780 cursor.moveToFirst(); 781 cursor.close(); 782// Log.i("~~~~", "Finished round " + i); 783 } 784 } 785 786 // Disable these until we can explicitly mark them as stress tests 787 public void xxtestMem2() throws Exception { 788 populateDefaultTable(); 789 790 for (int i = 0; i < 50000; i++) { 791 Cursor cursor = mDatabase.query("test", null, null, null, null, null, null); 792 cursor.close(); 793// Log.i("~~~~", "Finished round " + i); 794 } 795 } 796 797 // Disable these until we can explicitly mark them as stress tests 798 public void xxtestMem3() throws Exception { 799 populateDefaultTable(); 800 801 for (int i = 0; i < 50000; i++) { 802 Cursor cursor = mDatabase.query("test", null, null, null, null, null, null); 803 cursor.deactivate(); 804// Log.i("~~~~", "Finished round " + i); 805 } 806 } 807 808 @MediumTest 809 public void testContentValues() throws Exception { 810 ContentValues values = new ContentValues(); 811 values.put("string", "value"); 812 assertEquals("value", values.getAsString("string")); 813 byte[] bytes = new byte[42]; 814 Arrays.fill(bytes, (byte) 0x28); 815 values.put("byteArray", bytes); 816 assertTrue(Arrays.equals(bytes, values.getAsByteArray("byteArray"))); 817 818 // Write the ContentValues to a Parcel and then read them out 819 Parcel p = Parcel.obtain(); 820 values.writeToParcel(p, 0); 821 p.setDataPosition(0); 822 values = ContentValues.CREATOR.createFromParcel(p); 823 824 // Read the values out again and make sure they're the same 825 assertTrue(Arrays.equals(bytes, values.getAsByteArray("byteArray"))); 826 assertEquals("value", values.get("string")); 827 } 828 829 @MediumTest 830 public void testTableInfoPragma() throws Exception { 831 mDatabase.execSQL("CREATE TABLE pragma_test (" + 832 "i INTEGER DEFAULT 1234, " + 833 "j INTEGER, " + 834 "s TEXT DEFAULT 'hello', " + 835 "t TEXT, " + 836 "'select' TEXT DEFAULT \"hello\")"); 837 try { 838 Cursor cur = mDatabase.rawQuery("PRAGMA table_info(pragma_test)", null); 839 Assert.assertEquals(5, cur.getCount()); 840 841 Assert.assertTrue(cur.moveToNext()); 842 Assert.assertEquals("i", 843 cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); 844 Assert.assertEquals("1234", 845 cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); 846 847 Assert.assertTrue(cur.moveToNext()); 848 Assert.assertEquals("j", 849 cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); 850 Assert.assertNull(cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); 851 852 Assert.assertTrue(cur.moveToNext()); 853 Assert.assertEquals("s", 854 cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); 855 Assert.assertEquals("'hello'", 856 cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); 857 858 Assert.assertTrue(cur.moveToNext()); 859 Assert.assertEquals("t", 860 cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); 861 Assert.assertNull(cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); 862 863 Assert.assertTrue(cur.moveToNext()); 864 Assert.assertEquals("select", 865 cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); 866 Assert.assertEquals("\"hello\"", 867 cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); 868 869 cur.close(); 870 } catch (Throwable t) { 871 throw new RuntimeException( 872 "If you see this test fail, it's likely that something about " + 873 "sqlite's PRAGMA table_info(...) command has changed.", t); 874 } 875 } 876 877 @MediumTest 878 public void testInsertHelper() throws Exception { 879 Cursor cur; 880 ContentValues cv; 881 long row; 882 883 mDatabase.execSQL("CREATE TABLE insert_test (" + 884 "_id INTEGER PRIMARY KEY, " + 885 "s TEXT NOT NULL UNIQUE, " + 886 "t TEXT NOT NULL DEFAULT 'hello world', " + 887 "i INTEGER, " + 888 "j INTEGER NOT NULL DEFAULT 1234, " + 889 "'select' TEXT)"); 890 891 DatabaseUtils.InsertHelper ih = 892 new DatabaseUtils.InsertHelper(mDatabase, "insert_test"); 893 894 cv = new ContentValues(); 895 cv.put("s", "one"); 896 row = ih.insert(cv); 897 cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); 898 Assert.assertTrue(cur.moveToFirst()); 899 Assert.assertEquals("one", cur.getString(1)); 900 Assert.assertEquals("hello world", cur.getString(2)); 901 Assert.assertNull(cur.getString(3)); 902 Assert.assertEquals(1234, cur.getLong(4)); 903 Assert.assertNull(cur.getString(5)); 904 cur.close(); 905 906 cv = new ContentValues(); 907 cv.put("s", "two"); 908 cv.put("t", "goodbye world"); 909 row = ih.insert(cv); 910 cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); 911 Assert.assertTrue(cur.moveToFirst()); 912 Assert.assertEquals("two", cur.getString(1)); 913 Assert.assertEquals("goodbye world", cur.getString(2)); 914 Assert.assertNull(cur.getString(3)); 915 Assert.assertEquals(1234, cur.getLong(4)); 916 Assert.assertNull(cur.getString(5)); 917 cur.close(); 918 919 cv = new ContentValues(); 920 cv.put("t", "goodbye world"); 921 row = ih.insert(cv); 922 Assert.assertEquals(-1, row); 923 924 cv = new ContentValues(); 925 cv.put("s", "three"); 926 cv.put("i", 2345); 927 cv.put("j", 3456); 928 cv.put("select", "tricky"); 929 row = ih.insert(cv); 930 cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); 931 Assert.assertTrue(cur.moveToFirst()); 932 Assert.assertEquals("three", cur.getString(1)); 933 Assert.assertEquals("hello world", cur.getString(2)); 934 Assert.assertEquals(2345, cur.getLong(3)); 935 Assert.assertEquals(3456, cur.getLong(4)); 936 Assert.assertEquals("tricky", cur.getString(5)); 937 cur.close(); 938 939 cv = new ContentValues(); 940 cv.put("s", "three"); 941 cv.put("i", 6789); 942 row = ih.insert(cv); 943 Assert.assertEquals(-1, row); 944 row = ih.replace(cv); 945 cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); 946 Assert.assertTrue(cur.moveToFirst()); 947 Assert.assertEquals("three", cur.getString(1)); 948 Assert.assertEquals("hello world", cur.getString(2)); 949 Assert.assertEquals(6789, cur.getLong(3)); 950 cur.close(); 951 952 ih.close(); 953 } 954 955 @MediumTest 956 public void testDbCloseReleasingAllCachedSql() { 957 mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, text1 TEXT, text2 TEXT, " + 958 "num1 INTEGER, num2 INTEGER, image BLOB);"); 959 final String statement = "DELETE FROM test WHERE _id=?;"; 960 SQLiteStatement statementDoNotClose = mDatabase.compileStatement(statement); 961 assertTrue(statementDoNotClose.getUniqueId() > 0); 962 int nStatement = statementDoNotClose.getUniqueId(); 963 assertTrue(statementDoNotClose.getUniqueId() == nStatement); 964 /* do not close statementDoNotClose object. 965 * That should leave it in SQLiteDatabase.mPrograms. 966 * mDatabase.close() in tearDown() should release it. 967 */ 968 } 969 970 @MediumTest 971 public void testSemicolonsInStatements() throws Exception { 972 mDatabase.execSQL("CREATE TABLE pragma_test (" + 973 "i INTEGER DEFAULT 1234, " + 974 "j INTEGER, " + 975 "s TEXT DEFAULT 'hello', " + 976 "t TEXT, " + 977 "'select' TEXT DEFAULT \"hello\")"); 978 try { 979 // ending the sql statement with semicolons shouldn't be a problem. 980 Cursor cur = mDatabase.rawQuery("PRAGMA database_list;", null); 981 cur.close(); 982 // two semicolons in the statement shouldn't be a problem. 983 cur = mDatabase.rawQuery("PRAGMA database_list;;", null); 984 cur.close(); 985 } catch (Throwable t) { 986 fail("unexpected, of course"); 987 } 988 } 989 990 @MediumTest 991 public void testUnionsWithBindArgs() { 992 /* make sure unions with bindargs work http://b/issue?id=1061291 */ 993 mDatabase.execSQL("CREATE TABLE A (i int);"); 994 mDatabase.execSQL("create table B (k int);"); 995 mDatabase.execSQL("create table C (n int);"); 996 mDatabase.execSQL("insert into A values(1);"); 997 mDatabase.execSQL("insert into A values(2);"); 998 mDatabase.execSQL("insert into A values(3);"); 999 mDatabase.execSQL("insert into B values(201);"); 1000 mDatabase.execSQL("insert into B values(202);"); 1001 mDatabase.execSQL("insert into B values(203);"); 1002 mDatabase.execSQL("insert into C values(901);"); 1003 mDatabase.execSQL("insert into C values(902);"); 1004 String s = "select i from A where i > 2 " + 1005 "UNION select k from B where k > 201 " + 1006 "UNION select n from C where n !=900;"; 1007 Cursor c = mDatabase.rawQuery(s, null); 1008 int n = c.getCount(); 1009 c.close(); 1010 String s1 = "select i from A where i > ? " + 1011 "UNION select k from B where k > ? " + 1012 "UNION select n from C where n != ?;"; 1013 Cursor c1 = mDatabase.rawQuery(s1, new String[]{"2", "201", "900"}); 1014 assertEquals(n, c1.getCount()); 1015 c1.close(); 1016 } 1017 1018 /** 1019 * This test is available only when the platform has a locale with the language "ja". 1020 * It finishes without failure when it is not available. 1021 */ 1022 @MediumTest 1023 public void testCollateLocalizedForJapanese() throws Exception { 1024 final String testName = "DatabaseGeneralTest#testCollateLocalizedForJapanese()"; 1025 final Locale[] localeArray = Locale.getAvailableLocales(); 1026 final String japanese = Locale.JAPANESE.getLanguage(); 1027 final String english = Locale.ENGLISH.getLanguage(); 1028 Locale japaneseLocale = null; 1029 Locale englishLocale = null; 1030 for (Locale locale : localeArray) { 1031 if (locale != null) { 1032 final String language = locale.getLanguage(); 1033 if (language == null) { 1034 continue; 1035 } else if (language.equals(japanese)) { 1036 japaneseLocale = locale; 1037 } else if (language.equals(english)) { 1038 englishLocale = locale; 1039 } 1040 } 1041 1042 if (japaneseLocale != null && englishLocale != null) { 1043 break; 1044 } 1045 } 1046 1047 if (japaneseLocale == null || englishLocale == null) { 1048 Log.d(TAG, testName + "n is silently skipped since " + 1049 (englishLocale == null ? 1050 (japaneseLocale == null ? 1051 "Both English and Japanese locales do not exist." : 1052 "English locale does not exist.") : 1053 (japaneseLocale == null ? 1054 "Japanese locale does not exist." : 1055 "...why?"))); 1056 return; 1057 } 1058 1059 Locale originalLocale = Locale.getDefault(); 1060 try { 1061 1062 final String dbName = "collate_localized_test"; 1063 mDatabase.execSQL("CREATE TABLE " + dbName + " (" + 1064 "_id INTEGER PRIMARY KEY, " + 1065 "s TEXT COLLATE LOCALIZED) "); 1066 DatabaseUtils.InsertHelper ih = 1067 new DatabaseUtils.InsertHelper(mDatabase, dbName); 1068 ContentValues cv = new ContentValues(); 1069 1070 cv = new ContentValues(); // 1071 cv.put("s", "\uFF75\uFF77\uFF85\uFF9C"); // O-ki-na-wa in half-width Katakana 1072 ih.insert(cv); 1073 1074 cv = new ContentValues(); // 1075 cv.put("s", "\u306B\u307B\u3093"); // Ni-ho-n in Hiragana 1076 ih.insert(cv); 1077 1078 cv = new ContentValues(); // 1079 cv.put("s", "\u30A2\u30E1\u30EA\u30AB"); // A-me-ri-ca in hull-width Katakana 1080 ih.insert(cv); 1081 1082 // Assume setLocale() does REINDEX and an English locale does not consider 1083 // Japanese-specific LOCALIZED order. 1084 Locale.setDefault(englishLocale); 1085 Locale.setDefault(japaneseLocale); 1086 1087 Cursor cur = mDatabase.rawQuery( 1088 "SELECT * FROM " + dbName + " ORDER BY s", null); 1089 assertTrue(cur.moveToFirst()); 1090 assertEquals("\u30A2\u30E1\u30EA\u30AB", cur.getString(1)); 1091 assertTrue(cur.moveToNext()); 1092 assertEquals("\uFF75\uFF77\uFF85\uFF9C", cur.getString(1)); 1093 assertTrue(cur.moveToNext()); 1094 assertEquals("\u306B\u307B\u3093", cur.getString(1)); 1095 } finally { 1096 if (originalLocale != null) { 1097 try { 1098 Locale.setDefault(originalLocale); 1099 } catch (Exception e) { 1100 } 1101 } 1102 } 1103 } 1104 1105 @SmallTest 1106 public void testLruCachingOfSqliteCompiledSqlObjs() { 1107 mDatabase.execSQL("CREATE TABLE test (i int, j int);"); 1108 mDatabase.execSQL("insert into test values(1,1);"); 1109 // set cache size 1110 int N = SQLiteDatabase.MAX_SQL_CACHE_SIZE; 1111 mDatabase.setMaxSqlCacheSize(N); 1112 1113 // do N+1 queries - and when the 0th entry is removed from LRU cache due to the 1114 // insertion of (N+1)th entry, make sure 0th entry is closed 1115 ArrayList<SQLiteStatement> stmtObjs = new ArrayList<SQLiteStatement>(); 1116 for (int i = 0; i < N+1; i++) { 1117 SQLiteStatement c = mDatabase.compileStatement("select * from test where i = " + i); 1118 c.close(); 1119 stmtObjs.add(i, c); 1120 } 1121 1122 assertEquals(0, stmtObjs.get(0).getUniqueId()); 1123 for (int i = 1; i < N+1; i++) { 1124 assertTrue(stmtObjs.get(i).getUniqueId() > 0); 1125 } 1126 } 1127 1128 @SmallTest 1129 public void testSetMaxCahesize() { 1130 mDatabase.execSQL("CREATE TABLE test (i int, j int);"); 1131 mDatabase.execSQL("insert into test values(1,1);"); 1132 // set cache size 1133 int N = SQLiteDatabase.MAX_SQL_CACHE_SIZE; 1134 mDatabase.setMaxSqlCacheSize(N); 1135 1136 // try reduce cachesize 1137 try { 1138 mDatabase.setMaxSqlCacheSize(1); 1139 } catch (IllegalStateException e) { 1140 assertTrue(e.getMessage().contains("cannot set cacheSize to a value less than")); 1141 } 1142 } 1143 1144 @LargeTest 1145 public void testDefaultDatabaseErrorHandler() { 1146 DefaultDatabaseErrorHandler errorHandler = new DefaultDatabaseErrorHandler(); 1147 1148 // close the database. and call corruption handler. 1149 // it should delete the database file. 1150 File dbfile = new File(mDatabase.getPath()); 1151 mDatabase.close(); 1152 assertFalse(mDatabase.isOpen()); 1153 assertTrue(dbfile.exists()); 1154 try { 1155 errorHandler.onCorruption(mDatabase); 1156 assertFalse(dbfile.exists()); 1157 } catch (Exception e) { 1158 fail("unexpected"); 1159 } 1160 1161 // create an in-memory database. and corruption handler shouldn't try to delete it 1162 SQLiteDatabase memoryDb = SQLiteDatabase.openOrCreateDatabase(":memory:", null); 1163 assertNotNull(memoryDb); 1164 memoryDb.close(); 1165 assertFalse(memoryDb.isOpen()); 1166 try { 1167 errorHandler.onCorruption(memoryDb); 1168 } catch (Exception e) { 1169 fail("unexpected"); 1170 } 1171 1172 // create a database, keep it open, call corruption handler. database file should be deleted 1173 SQLiteDatabase dbObj = SQLiteDatabase.openOrCreateDatabase(mDatabase.getPath(), null); 1174 assertTrue(dbfile.exists()); 1175 assertNotNull(dbObj); 1176 assertTrue(dbObj.isOpen()); 1177 try { 1178 errorHandler.onCorruption(dbObj); 1179 assertFalse(dbfile.exists()); 1180 } catch (Exception e) { 1181 fail("unexpected"); 1182 } 1183 1184 // create a database, attach 2 more databases to it 1185 // attached database # 1: ":memory:" 1186 // attached database # 2: mDatabase.getPath() + "1"; 1187 // call corruption handler. database files including the one for attached database # 2 1188 // should be deleted 1189 String attachedDb1File = mDatabase.getPath() + "1"; 1190 dbObj = SQLiteDatabase.openOrCreateDatabase(mDatabase.getPath(), null); 1191 dbObj.execSQL("ATTACH DATABASE ':memory:' as memoryDb"); 1192 dbObj.execSQL("ATTACH DATABASE '" + attachedDb1File + "' as attachedDb1"); 1193 assertTrue(dbfile.exists()); 1194 assertTrue(new File(attachedDb1File).exists()); 1195 assertNotNull(dbObj); 1196 assertTrue(dbObj.isOpen()); 1197 ArrayList<Pair<String, String>> attachedDbs = dbObj.getAttachedDbs(); 1198 try { 1199 errorHandler.onCorruption(dbObj); 1200 assertFalse(dbfile.exists()); 1201 assertFalse(new File(attachedDb1File).exists()); 1202 } catch (Exception e) { 1203 fail("unexpected"); 1204 } 1205 1206 // same as above, except this is a bit of stress testing. attach 5 database files 1207 // and make sure they are all removed. 1208 int N = 5; 1209 ArrayList<String> attachedDbFiles = new ArrayList<String>(N); 1210 for (int i = 0; i < N; i++) { 1211 attachedDbFiles.add(mDatabase.getPath() + i); 1212 } 1213 dbObj = SQLiteDatabase.openOrCreateDatabase(mDatabase.getPath(), null); 1214 dbObj.execSQL("ATTACH DATABASE ':memory:' as memoryDb"); 1215 for (int i = 0; i < N; i++) { 1216 dbObj.execSQL("ATTACH DATABASE '" + attachedDbFiles.get(i) + "' as attachedDb" + i); 1217 } 1218 assertTrue(dbfile.exists()); 1219 for (int i = 0; i < N; i++) { 1220 assertTrue(new File(attachedDbFiles.get(i)).exists()); 1221 } 1222 assertNotNull(dbObj); 1223 assertTrue(dbObj.isOpen()); 1224 attachedDbs = dbObj.getAttachedDbs(); 1225 try { 1226 errorHandler.onCorruption(dbObj); 1227 assertFalse(dbfile.exists()); 1228 for (int i = 0; i < N; i++) { 1229 assertFalse(new File(attachedDbFiles.get(i)).exists()); 1230 } 1231 } catch (Exception e) { 1232 fail("unexpected"); 1233 } 1234 } 1235} 1236