blob: 5d7af69d256ab0b70b6a1431b3b56f2dfdb84513 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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.sqlite;
18
19import android.content.ContentValues;
20import android.database.Cursor;
21import android.database.DatabaseUtils;
22import android.database.SQLException;
23import android.os.Debug;
24import android.os.SystemClock;
25import android.text.TextUtils;
26import android.util.Config;
27import android.util.Log;
28import android.util.EventLog;
29
30import java.io.File;
31import java.util.HashMap;
32import java.util.Iterator;
33import java.util.Locale;
34import java.util.Map;
35import java.util.Set;
36import java.util.WeakHashMap;
37import java.util.concurrent.locks.ReentrantLock;
38
39/**
40 * Exposes methods to manage a SQLite database.
41 * <p>SQLiteDatabase has methods to create, delete, execute SQL commands, and
42 * perform other common database management tasks.
43 * <p>See the Notepad sample application in the SDK for an example of creating
44 * and managing a database.
45 * <p> Database names must be unique within an application, not across all
46 * applications.
47 *
48 * <h3>Localized Collation - ORDER BY</h3>
49 * <p>In addition to SQLite's default <code>BINARY</code> collator, Android supplies
50 * two more, <code>LOCALIZED</code>, which changes with the system's current locale
51 * if you wire it up correctly (XXX a link needed!), and <code>UNICODE</code>, which
52 * is the Unicode Collation Algorithm and not tailored to the current locale.
53 */
54public class SQLiteDatabase extends SQLiteClosable {
55 private static final String TAG = "Database";
56 private static final int DB_OPERATION_EVENT = 52000;
57
58 /**
59 * Algorithms used in ON CONFLICT clause
60 * http://www.sqlite.org/lang_conflict.html
61 * @hide
62 */
63 public enum ConflictAlgorithm {
64 /**
65 * When a constraint violation occurs, an immediate ROLLBACK occurs,
66 * thus ending the current transaction, and the command aborts with a
67 * return code of SQLITE_CONSTRAINT. If no transaction is active
68 * (other than the implied transaction that is created on every command)
69 * then this algorithm works the same as ABORT.
70 */
71 ROLLBACK("ROLLBACK"),
72
73 /**
74 * When a constraint violation occurs,no ROLLBACK is executed
75 * so changes from prior commands within the same transaction
76 * are preserved. This is the default behavior.
77 */
78 ABORT("ABORT"),
79
80 /**
81 * When a constraint violation occurs, the command aborts with a return
82 * code SQLITE_CONSTRAINT. But any changes to the database that
83 * the command made prior to encountering the constraint violation
84 * are preserved and are not backed out.
85 */
86 FAIL("FAIL"),
87
88 /**
89 * When a constraint violation occurs, the one row that contains
90 * the constraint violation is not inserted or changed.
91 * But the command continues executing normally. Other rows before and
92 * after the row that contained the constraint violation continue to be
93 * inserted or updated normally. No error is returned.
94 */
95 IGNORE("IGNORE"),
96
97 /**
98 * When a UNIQUE constraint violation occurs, the pre-existing rows that
99 * are causing the constraint violation are removed prior to inserting
100 * or updating the current row. Thus the insert or update always occurs.
101 * The command continues executing normally. No error is returned.
102 * If a NOT NULL constraint violation occurs, the NULL value is replaced
103 * by the default value for that column. If the column has no default
104 * value, then the ABORT algorithm is used. If a CHECK constraint
105 * violation occurs then the IGNORE algorithm is used. When this conflict
106 * resolution strategy deletes rows in order to satisfy a constraint,
107 * it does not invoke delete triggers on those rows.
108 * This behavior might change in a future release.
109 */
110 REPLACE("REPLACE");
111
112 private final String mValue;
113 ConflictAlgorithm(String value) {
114 mValue = value;
115 }
116 public String value() {
117 return mValue;
118 }
119 }
120
121 /**
122 * Maximum Length Of A LIKE Or GLOB Pattern
123 * The pattern matching algorithm used in the default LIKE and GLOB implementation
124 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
125 * the pattern) for certain pathological cases. To avoid denial-of-service attacks
126 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
127 * The default value of this limit is 50000. A modern workstation can evaluate
128 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
129 * The denial of service problem only comes into play when the pattern length gets
130 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
131 * are at most a few dozen bytes in length, paranoid application developers may
132 * want to reduce this parameter to something in the range of a few hundred
133 * if they know that external users are able to generate arbitrary patterns.
134 */
135 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
136
137 /**
138 * Flag for {@link #openDatabase} to open the database for reading and writing.
139 * If the disk is full, this may fail even before you actually write anything.
140 *
141 * {@more} Note that the value of this flag is 0, so it is the default.
142 */
143 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
144
145 /**
146 * Flag for {@link #openDatabase} to open the database for reading only.
147 * This is the only reliable way to open a database if the disk may be full.
148 */
149 public static final int OPEN_READONLY = 0x00000001; // update native code if changing
150
151 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
152
153 /**
154 * Flag for {@link #openDatabase} to open the database without support for localized collators.
155 *
156 * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
157 * You must be consistent when using this flag to use the setting the database was
158 * created with. If this is set, {@link #setLocale} will do nothing.
159 */
160 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
161
162 /**
163 * Flag for {@link #openDatabase} to create the database file if it does not already exist.
164 */
165 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
166
167 /**
168 * Indicates whether the most-recently started transaction has been marked as successful.
169 */
170 private boolean mInnerTransactionIsSuccessful;
171
172 /**
173 * Valid during the life of a transaction, and indicates whether the entire transaction (the
174 * outer one and all of the inner ones) so far has been successful.
175 */
176 private boolean mTransactionIsSuccessful;
177
178 /** Synchronize on this when accessing the database */
179 private final ReentrantLock mLock = new ReentrantLock(true);
180
181 private long mLockAcquiredWallTime = 0L;
182 private long mLockAcquiredThreadTime = 0L;
183
184 // limit the frequency of complaints about each database to one within 20 sec
185 // unless run command adb shell setprop log.tag.Database VERBOSE
186 private static final int LOCK_WARNING_WINDOW_IN_MS = 20000;
187 /** If the lock is held this long then a warning will be printed when it is released. */
188 private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS = 300;
189 private static final int LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS = 100;
190 private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT = 2000;
191
192 private long mLastLockMessageTime = 0L;
193
194 /** Used by native code, do not rename */
195 /* package */ int mNativeHandle = 0;
196
197 /** Used to make temp table names unique */
198 /* package */ int mTempTableSequence = 0;
199
200 /** The path for the database file */
201 private String mPath;
202
203 /** The flags passed to open/create */
204 private int mFlags;
205
206 /** The optional factory to use when creating new Cursors */
207 private CursorFactory mFactory;
208
209 private WeakHashMap<SQLiteClosable, Object> mPrograms;
210
211 private final RuntimeException mLeakedException;
212
213 // package visible, since callers will access directly to minimize overhead in the case
214 // that logging is not enabled.
215 /* package */ final boolean mLogStats;
216
217 /**
218 * @param closable
219 */
220 void addSQLiteClosable(SQLiteClosable closable) {
221 lock();
222 try {
223 mPrograms.put(closable, null);
224 } finally {
225 unlock();
226 }
227 }
228
229 void removeSQLiteClosable(SQLiteClosable closable) {
230 lock();
231 try {
232 mPrograms.remove(closable);
233 } finally {
234 unlock();
235 }
236 }
237
238 @Override
239 protected void onAllReferencesReleased() {
240 if (isOpen()) {
241 dbclose();
242 }
243 }
244
245 /**
246 * Attempts to release memory that SQLite holds but does not require to
247 * operate properly. Typically this memory will come from the page cache.
248 *
249 * @return the number of bytes actually released
250 */
251 static public native int releaseMemory();
252
253 /**
254 * Control whether or not the SQLiteDatabase is made thread-safe by using locks
255 * around critical sections. This is pretty expensive, so if you know that your
256 * DB will only be used by a single thread then you should set this to false.
257 * The default is true.
258 * @param lockingEnabled set to true to enable locks, false otherwise
259 */
260 public void setLockingEnabled(boolean lockingEnabled) {
261 mLockingEnabled = lockingEnabled;
262 }
263
264 /**
265 * If set then the SQLiteDatabase is made thread-safe by using locks
266 * around critical sections
267 */
268 private boolean mLockingEnabled = true;
269
270 /* package */ void onCorruption() {
271 try {
272 // Close the database (if we can), which will cause subsequent operations to fail.
273 close();
274 } finally {
275 Log.e(TAG, "Removing corrupt database: " + mPath);
276 // Delete the corrupt file. Don't re-create it now -- that would just confuse people
277 // -- but the next time someone tries to open it, they can set it up from scratch.
278 new File(mPath).delete();
279 }
280 }
281
282 /**
283 * Locks the database for exclusive access. The database lock must be held when
284 * touch the native sqlite3* object since it is single threaded and uses
285 * a polling lock contention algorithm. The lock is recursive, and may be acquired
286 * multiple times by the same thread. This is a no-op if mLockingEnabled is false.
287 *
288 * @see #unlock()
289 */
290 /* package */ void lock() {
291 if (!mLockingEnabled) return;
292 mLock.lock();
293 if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
294 if (mLock.getHoldCount() == 1) {
295 // Use elapsed real-time since the CPU may sleep when waiting for IO
296 mLockAcquiredWallTime = SystemClock.elapsedRealtime();
297 mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
298 }
299 }
300 }
301
302 /**
303 * Locks the database for exclusive access. The database lock must be held when
304 * touch the native sqlite3* object since it is single threaded and uses
305 * a polling lock contention algorithm. The lock is recursive, and may be acquired
306 * multiple times by the same thread.
307 *
308 * @see #unlockForced()
309 */
310 private void lockForced() {
311 mLock.lock();
312 if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
313 if (mLock.getHoldCount() == 1) {
314 // Use elapsed real-time since the CPU may sleep when waiting for IO
315 mLockAcquiredWallTime = SystemClock.elapsedRealtime();
316 mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
317 }
318 }
319 }
320
321 /**
322 * Releases the database lock. This is a no-op if mLockingEnabled is false.
323 *
324 * @see #unlock()
325 */
326 /* package */ void unlock() {
327 if (!mLockingEnabled) return;
328 if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
329 if (mLock.getHoldCount() == 1) {
330 checkLockHoldTime();
331 }
332 }
333 mLock.unlock();
334 }
335
336 /**
337 * Releases the database lock.
338 *
339 * @see #unlockForced()
340 */
341 private void unlockForced() {
342 if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
343 if (mLock.getHoldCount() == 1) {
344 checkLockHoldTime();
345 }
346 }
347 mLock.unlock();
348 }
349
350 private void checkLockHoldTime() {
351 // Use elapsed real-time since the CPU may sleep when waiting for IO
352 long elapsedTime = SystemClock.elapsedRealtime();
353 long lockedTime = elapsedTime - mLockAcquiredWallTime;
354 if (lockedTime < LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT &&
355 !Log.isLoggable(TAG, Log.VERBOSE) &&
356 (elapsedTime - mLastLockMessageTime) < LOCK_WARNING_WINDOW_IN_MS) {
357 return;
358 }
359 if (lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS) {
360 int threadTime = (int)
361 ((Debug.threadCpuTimeNanos() - mLockAcquiredThreadTime) / 1000000);
362 if (threadTime > LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS ||
363 lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT) {
364 mLastLockMessageTime = elapsedTime;
365 String msg = "lock held on " + mPath + " for " + lockedTime + "ms. Thread time was "
366 + threadTime + "ms";
367 if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING_STACK_TRACE) {
368 Log.d(TAG, msg, new Exception());
369 } else {
370 Log.d(TAG, msg);
371 }
372 }
373 }
374 }
375
376 /**
377 * Begins a transaction. Transactions can be nested. When the outer transaction is ended all of
378 * the work done in that transaction and all of the nested transactions will be committed or
379 * rolled back. The changes will be rolled back if any transaction is ended without being
380 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
381 *
382 * <p>Here is the standard idiom for transactions:
383 *
384 * <pre>
385 * db.beginTransaction();
386 * try {
387 * ...
388 * db.setTransactionSuccessful();
389 * } finally {
390 * db.endTransaction();
391 * }
392 * </pre>
393 */
394 public void beginTransaction() {
395 lockForced();
396 boolean ok = false;
397 try {
398 // If this thread already had the lock then get out
399 if (mLock.getHoldCount() > 1) {
400 if (mInnerTransactionIsSuccessful) {
401 String msg = "Cannot call beginTransaction between "
402 + "calling setTransactionSuccessful and endTransaction";
403 IllegalStateException e = new IllegalStateException(msg);
404 Log.e(TAG, "beginTransaction() failed", e);
405 throw e;
406 }
407 ok = true;
408 return;
409 }
410
411 // This thread didn't already have the lock, so begin a database
412 // transaction now.
413 execSQL("BEGIN EXCLUSIVE;");
414 mTransactionIsSuccessful = true;
415 mInnerTransactionIsSuccessful = false;
416 ok = true;
417 } finally {
418 if (!ok) {
419 // beginTransaction is called before the try block so we must release the lock in
420 // the case of failure.
421 unlockForced();
422 }
423 }
424 }
425
426 /**
427 * End a transaction. See beginTransaction for notes about how to use this and when transactions
428 * are committed and rolled back.
429 */
430 public void endTransaction() {
431 if (!mLock.isHeldByCurrentThread()) {
432 throw new IllegalStateException("no transaction pending");
433 }
434 try {
435 if (mInnerTransactionIsSuccessful) {
436 mInnerTransactionIsSuccessful = false;
437 } else {
438 mTransactionIsSuccessful = false;
439 }
440 if (mLock.getHoldCount() != 1) {
441 return;
442 }
443 if (mTransactionIsSuccessful) {
444 execSQL("COMMIT;");
445 } else {
446 try {
447 execSQL("ROLLBACK;");
448 } catch (SQLException e) {
449 if (Config.LOGD) {
450 Log.d(TAG, "exception during rollback, maybe the DB previously "
451 + "performed an auto-rollback");
452 }
453 }
454 }
455 } finally {
456 unlockForced();
457 if (Config.LOGV) {
458 Log.v(TAG, "unlocked " + Thread.currentThread()
459 + ", holdCount is " + mLock.getHoldCount());
460 }
461 }
462 }
463
464 /**
465 * Marks the current transaction as successful. Do not do any more database work between
466 * calling this and calling endTransaction. Do as little non-database work as possible in that
467 * situation too. If any errors are encountered between this and endTransaction the transaction
468 * will still be committed.
469 *
470 * @throws IllegalStateException if the current thread is not in a transaction or the
471 * transaction is already marked as successful.
472 */
473 public void setTransactionSuccessful() {
474 if (!mLock.isHeldByCurrentThread()) {
475 throw new IllegalStateException("no transaction pending");
476 }
477 if (mInnerTransactionIsSuccessful) {
478 throw new IllegalStateException(
479 "setTransactionSuccessful may only be called once per call to beginTransaction");
480 }
481 mInnerTransactionIsSuccessful = true;
482 }
483
484 /**
485 * return true if there is a transaction pending
486 */
487 public boolean inTransaction() {
488 return mLock.getHoldCount() > 0;
489 }
490
491 /**
492 * Checks if the database lock is held by this thread.
493 *
494 * @return true, if this thread is holding the database lock.
495 */
496 public boolean isDbLockedByCurrentThread() {
497 return mLock.isHeldByCurrentThread();
498 }
499
500 /**
501 * Checks if the database is locked by another thread. This is
502 * just an estimate, since this status can change at any time,
503 * including after the call is made but before the result has
504 * been acted upon.
505 *
506 * @return true, if the database is locked by another thread
507 */
508 public boolean isDbLockedByOtherThreads() {
509 return !mLock.isHeldByCurrentThread() && mLock.isLocked();
510 }
511
512 /**
513 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
514 * successful so far. Do not call setTransactionSuccessful before calling this. When this
515 * returns a new transaction will have been created but not marked as successful.
516 * @return true if the transaction was yielded
517 * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
518 * will not be yielded. Use yieldIfContendedSafely instead.
519 */
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700520 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521 public boolean yieldIfContended() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700522 return yieldIfContendedHelper(false /* do not check yielding */,
523 -1 /* sleepAfterYieldDelay */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 }
525
526 /**
527 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
528 * successful so far. Do not call setTransactionSuccessful before calling this. When this
529 * returns a new transaction will have been created but not marked as successful. This assumes
530 * that there are no nested transactions (beginTransaction has only been called once) and will
Fred Quintana5c7aede2009-08-27 21:41:27 -0700531 * throw an exception if that is not the case.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 * @return true if the transaction was yielded
533 */
534 public boolean yieldIfContendedSafely() {
Fred Quintana5c7aede2009-08-27 21:41:27 -0700535 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 }
537
Fred Quintana5c7aede2009-08-27 21:41:27 -0700538 /**
539 * Temporarily end the transaction to let other threads run. The transaction is assumed to be
540 * successful so far. Do not call setTransactionSuccessful before calling this. When this
541 * returns a new transaction will have been created but not marked as successful. This assumes
542 * that there are no nested transactions (beginTransaction has only been called once) and will
543 * throw an exception if that is not the case.
544 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
545 * the lock was actually yielded. This will allow other background threads to make some
546 * more progress than they would if we started the transaction immediately.
547 * @return true if the transaction was yielded
548 */
549 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
550 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay);
551 }
552
553 private boolean yieldIfContendedHelper(boolean checkFullyYielded, long sleepAfterYieldDelay) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 if (mLock.getQueueLength() == 0) {
555 // Reset the lock acquire time since we know that the thread was willing to yield
556 // the lock at this time.
557 mLockAcquiredWallTime = SystemClock.elapsedRealtime();
558 mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
559 return false;
560 }
561 setTransactionSuccessful();
562 endTransaction();
563 if (checkFullyYielded) {
564 if (this.isDbLockedByCurrentThread()) {
565 throw new IllegalStateException(
566 "Db locked more than once. yielfIfContended cannot yield");
567 }
568 }
Fred Quintana5c7aede2009-08-27 21:41:27 -0700569 if (sleepAfterYieldDelay > 0) {
570 try {
571 Thread.sleep(sleepAfterYieldDelay);
572 } catch (InterruptedException e) {
573 Thread.interrupted();
574 }
575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576 beginTransaction();
577 return true;
578 }
579
580 /** Maps table names to info about what to which _sync_time column to set
581 * to NULL on an update. This is used to support syncing. */
582 private final Map<String, SyncUpdateInfo> mSyncUpdateInfo =
583 new HashMap<String, SyncUpdateInfo>();
584
585 public Map<String, String> getSyncedTables() {
586 synchronized(mSyncUpdateInfo) {
587 HashMap<String, String> tables = new HashMap<String, String>();
588 for (String table : mSyncUpdateInfo.keySet()) {
589 SyncUpdateInfo info = mSyncUpdateInfo.get(table);
590 if (info.deletedTable != null) {
591 tables.put(table, info.deletedTable);
592 }
593 }
594 return tables;
595 }
596 }
597
598 /**
599 * Internal class used to keep track what needs to be marked as changed
600 * when an update occurs. This is used for syncing, so the sync engine
601 * knows what data has been updated locally.
602 */
603 static private class SyncUpdateInfo {
604 /**
605 * Creates the SyncUpdateInfo class.
606 *
607 * @param masterTable The table to set _sync_time to NULL in
608 * @param deletedTable The deleted table that corresponds to the
609 * master table
610 * @param foreignKey The key that refers to the primary key in table
611 */
612 SyncUpdateInfo(String masterTable, String deletedTable,
613 String foreignKey) {
614 this.masterTable = masterTable;
615 this.deletedTable = deletedTable;
616 this.foreignKey = foreignKey;
617 }
618
619 /** The table containing the _sync_time column */
620 String masterTable;
621
622 /** The deleted table that corresponds to the master table */
623 String deletedTable;
624
625 /** The key in the local table the row in table. It may be _id, if table
626 * is the local table. */
627 String foreignKey;
628 }
629
630 /**
631 * Used to allow returning sub-classes of {@link Cursor} when calling query.
632 */
633 public interface CursorFactory {
634 /**
635 * See
636 * {@link SQLiteCursor#SQLiteCursor(SQLiteDatabase, SQLiteCursorDriver,
637 * String, SQLiteQuery)}.
638 */
639 public Cursor newCursor(SQLiteDatabase db,
640 SQLiteCursorDriver masterQuery, String editTable,
641 SQLiteQuery query);
642 }
643
644 /**
645 * Open the database according to the flags {@link #OPEN_READWRITE}
646 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
647 *
648 * <p>Sets the locale of the database to the the system's current locale.
649 * Call {@link #setLocale} if you would like something else.</p>
650 *
651 * @param path to database file to open and/or create
652 * @param factory an optional factory class that is called to instantiate a
653 * cursor when query is called, or null for default
654 * @param flags to control database access mode
655 * @return the newly opened database
656 * @throws SQLiteException if the database cannot be opened
657 */
658 public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) {
659 SQLiteDatabase db = null;
660 try {
661 // Open the database.
662 return new SQLiteDatabase(path, factory, flags);
663 } catch (SQLiteDatabaseCorruptException e) {
664 // Try to recover from this, if we can.
665 // TODO: should we do this for other open failures?
666 Log.e(TAG, "Deleting and re-creating corrupt database " + path, e);
667 new File(path).delete();
668 return new SQLiteDatabase(path, factory, flags);
669 }
670 }
671
672 /**
673 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
674 */
675 public static SQLiteDatabase openOrCreateDatabase(File file, CursorFactory factory) {
676 return openOrCreateDatabase(file.getPath(), factory);
677 }
678
679 /**
680 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
681 */
682 public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) {
683 return openDatabase(path, factory, CREATE_IF_NECESSARY);
684 }
685
686 /**
687 * Create a memory backed SQLite database. Its contents will be destroyed
688 * when the database is closed.
689 *
690 * <p>Sets the locale of the database to the the system's current locale.
691 * Call {@link #setLocale} if you would like something else.</p>
692 *
693 * @param factory an optional factory class that is called to instantiate a
694 * cursor when query is called
695 * @return a SQLiteDatabase object, or null if the database can't be created
696 */
697 public static SQLiteDatabase create(CursorFactory factory) {
698 // This is a magic string with special meaning for SQLite.
699 return openDatabase(":memory:", factory, CREATE_IF_NECESSARY);
700 }
701
702 /**
703 * Close the database.
704 */
705 public void close() {
706 lock();
707 try {
708 closeClosable();
709 releaseReference();
710 } finally {
711 unlock();
712 }
713 }
714
715 private void closeClosable() {
716 Iterator<Map.Entry<SQLiteClosable, Object>> iter = mPrograms.entrySet().iterator();
717 while (iter.hasNext()) {
718 Map.Entry<SQLiteClosable, Object> entry = iter.next();
719 SQLiteClosable program = entry.getKey();
720 if (program != null) {
721 program.onAllReferencesReleasedFromContainer();
722 }
723 }
724 }
725
726 /**
727 * Native call to close the database.
728 */
729 private native void dbclose();
730
731 /**
732 * Gets the database version.
733 *
734 * @return the database version
735 */
736 public int getVersion() {
737 SQLiteStatement prog = null;
738 lock();
739 try {
740 prog = new SQLiteStatement(this, "PRAGMA user_version;");
741 long version = prog.simpleQueryForLong();
742 return (int) version;
743 } finally {
744 if (prog != null) prog.close();
745 unlock();
746 }
747 }
748
749 /**
750 * Sets the database version.
751 *
752 * @param version the new database version
753 */
754 public void setVersion(int version) {
755 execSQL("PRAGMA user_version = " + version);
756 }
757
758 /**
759 * Returns the maximum size the database may grow to.
760 *
761 * @return the new maximum database size
762 */
763 public long getMaximumSize() {
764 SQLiteStatement prog = null;
765 lock();
766 try {
767 prog = new SQLiteStatement(this,
768 "PRAGMA max_page_count;");
769 long pageCount = prog.simpleQueryForLong();
770 return pageCount * getPageSize();
771 } finally {
772 if (prog != null) prog.close();
773 unlock();
774 }
775 }
776
777 /**
778 * Sets the maximum size the database will grow to. The maximum size cannot
779 * be set below the current size.
780 *
781 * @param numBytes the maximum database size, in bytes
782 * @return the new maximum database size
783 */
784 public long setMaximumSize(long numBytes) {
785 SQLiteStatement prog = null;
786 lock();
787 try {
788 long pageSize = getPageSize();
789 long numPages = numBytes / pageSize;
790 // If numBytes isn't a multiple of pageSize, bump up a page
791 if ((numBytes % pageSize) != 0) {
792 numPages++;
793 }
794 prog = new SQLiteStatement(this,
795 "PRAGMA max_page_count = " + numPages);
796 long newPageCount = prog.simpleQueryForLong();
797 return newPageCount * pageSize;
798 } finally {
799 if (prog != null) prog.close();
800 unlock();
801 }
802 }
803
804 /**
805 * Returns the current database page size, in bytes.
806 *
807 * @return the database page size, in bytes
808 */
809 public long getPageSize() {
810 SQLiteStatement prog = null;
811 lock();
812 try {
813 prog = new SQLiteStatement(this,
814 "PRAGMA page_size;");
815 long size = prog.simpleQueryForLong();
816 return size;
817 } finally {
818 if (prog != null) prog.close();
819 unlock();
820 }
821 }
822
823 /**
824 * Sets the database page size. The page size must be a power of two. This
825 * method does not work if any data has been written to the database file,
826 * and must be called right after the database has been created.
827 *
828 * @param numBytes the database page size, in bytes
829 */
830 public void setPageSize(long numBytes) {
831 execSQL("PRAGMA page_size = " + numBytes);
832 }
833
834 /**
835 * Mark this table as syncable. When an update occurs in this table the
836 * _sync_dirty field will be set to ensure proper syncing operation.
837 *
838 * @param table the table to mark as syncable
839 * @param deletedTable The deleted table that corresponds to the
840 * syncable table
841 */
842 public void markTableSyncable(String table, String deletedTable) {
843 markTableSyncable(table, "_id", table, deletedTable);
844 }
845
846 /**
847 * Mark this table as syncable, with the _sync_dirty residing in another
848 * table. When an update occurs in this table the _sync_dirty field of the
849 * row in updateTable with the _id in foreignKey will be set to
850 * ensure proper syncing operation.
851 *
852 * @param table an update on this table will trigger a sync time removal
853 * @param foreignKey this is the column in table whose value is an _id in
854 * updateTable
855 * @param updateTable this is the table that will have its _sync_dirty
856 */
857 public void markTableSyncable(String table, String foreignKey,
858 String updateTable) {
859 markTableSyncable(table, foreignKey, updateTable, null);
860 }
861
862 /**
863 * Mark this table as syncable, with the _sync_dirty residing in another
864 * table. When an update occurs in this table the _sync_dirty field of the
865 * row in updateTable with the _id in foreignKey will be set to
866 * ensure proper syncing operation.
867 *
868 * @param table an update on this table will trigger a sync time removal
869 * @param foreignKey this is the column in table whose value is an _id in
870 * updateTable
871 * @param updateTable this is the table that will have its _sync_dirty
872 * @param deletedTable The deleted table that corresponds to the
873 * updateTable
874 */
875 private void markTableSyncable(String table, String foreignKey,
876 String updateTable, String deletedTable) {
877 lock();
878 try {
879 native_execSQL("SELECT _sync_dirty FROM " + updateTable
880 + " LIMIT 0");
881 native_execSQL("SELECT " + foreignKey + " FROM " + table
882 + " LIMIT 0");
883 } finally {
884 unlock();
885 }
886
887 SyncUpdateInfo info = new SyncUpdateInfo(updateTable, deletedTable,
888 foreignKey);
889 synchronized (mSyncUpdateInfo) {
890 mSyncUpdateInfo.put(table, info);
891 }
892 }
893
894 /**
895 * Call for each row that is updated in a cursor.
896 *
897 * @param table the table the row is in
898 * @param rowId the row ID of the updated row
899 */
900 /* package */ void rowUpdated(String table, long rowId) {
901 SyncUpdateInfo info;
902 synchronized (mSyncUpdateInfo) {
903 info = mSyncUpdateInfo.get(table);
904 }
905 if (info != null) {
906 execSQL("UPDATE " + info.masterTable
907 + " SET _sync_dirty=1 WHERE _id=(SELECT " + info.foreignKey
908 + " FROM " + table + " WHERE _id=" + rowId + ")");
909 }
910 }
911
912 /**
913 * Finds the name of the first table, which is editable.
914 *
915 * @param tables a list of tables
916 * @return the first table listed
917 */
918 public static String findEditTable(String tables) {
919 if (!TextUtils.isEmpty(tables)) {
920 // find the first word terminated by either a space or a comma
921 int spacepos = tables.indexOf(' ');
922 int commapos = tables.indexOf(',');
923
924 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
925 return tables.substring(0, spacepos);
926 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
927 return tables.substring(0, commapos);
928 }
929 return tables;
930 } else {
931 throw new IllegalStateException("Invalid tables");
932 }
933 }
934
935 /**
936 * Compiles an SQL statement into a reusable pre-compiled statement object.
937 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
938 * statement and fill in those values with {@link SQLiteProgram#bindString}
939 * and {@link SQLiteProgram#bindLong} each time you want to run the
940 * statement. Statements may not return result sets larger than 1x1.
941 *
942 * @param sql The raw SQL statement, may contain ? for unknown values to be
943 * bound later.
944 * @return a pre-compiled statement object.
945 */
946 public SQLiteStatement compileStatement(String sql) throws SQLException {
947 lock();
948 try {
949 return new SQLiteStatement(this, sql);
950 } finally {
951 unlock();
952 }
953 }
954
955 /**
956 * Query the given URL, returning a {@link Cursor} over the result set.
957 *
958 * @param distinct true if you want each row to be unique, false otherwise.
959 * @param table The table name to compile the query against.
960 * @param columns A list of which columns to return. Passing null will
961 * return all columns, which is discouraged to prevent reading
962 * data from storage that isn't going to be used.
963 * @param selection A filter declaring which rows to return, formatted as an
964 * SQL WHERE clause (excluding the WHERE itself). Passing null
965 * will return all rows for the given table.
966 * @param selectionArgs You may include ?s in selection, which will be
967 * replaced by the values from selectionArgs, in order that they
968 * appear in the selection. The values will be bound as Strings.
969 * @param groupBy A filter declaring how to group rows, formatted as an SQL
970 * GROUP BY clause (excluding the GROUP BY itself). Passing null
971 * will cause the rows to not be grouped.
972 * @param having A filter declare which row groups to include in the cursor,
973 * if row grouping is being used, formatted as an SQL HAVING
974 * clause (excluding the HAVING itself). Passing null will cause
975 * all row groups to be included, and is required when row
976 * grouping is not being used.
977 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
978 * (excluding the ORDER BY itself). Passing null will use the
979 * default sort order, which may be unordered.
980 * @param limit Limits the number of rows returned by the query,
981 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
982 * @return A Cursor object, which is positioned before the first entry
983 * @see Cursor
984 */
985 public Cursor query(boolean distinct, String table, String[] columns,
986 String selection, String[] selectionArgs, String groupBy,
987 String having, String orderBy, String limit) {
988 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
989 groupBy, having, orderBy, limit);
990 }
991
992 /**
993 * Query the given URL, returning a {@link Cursor} over the result set.
994 *
995 * @param cursorFactory the cursor factory to use, or null for the default factory
996 * @param distinct true if you want each row to be unique, false otherwise.
997 * @param table The table name to compile the query against.
998 * @param columns A list of which columns to return. Passing null will
999 * return all columns, which is discouraged to prevent reading
1000 * data from storage that isn't going to be used.
1001 * @param selection A filter declaring which rows to return, formatted as an
1002 * SQL WHERE clause (excluding the WHERE itself). Passing null
1003 * will return all rows for the given table.
1004 * @param selectionArgs You may include ?s in selection, which will be
1005 * replaced by the values from selectionArgs, in order that they
1006 * appear in the selection. The values will be bound as Strings.
1007 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1008 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1009 * will cause the rows to not be grouped.
1010 * @param having A filter declare which row groups to include in the cursor,
1011 * if row grouping is being used, formatted as an SQL HAVING
1012 * clause (excluding the HAVING itself). Passing null will cause
1013 * all row groups to be included, and is required when row
1014 * grouping is not being used.
1015 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1016 * (excluding the ORDER BY itself). Passing null will use the
1017 * default sort order, which may be unordered.
1018 * @param limit Limits the number of rows returned by the query,
1019 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
1020 * @return A Cursor object, which is positioned before the first entry
1021 * @see Cursor
1022 */
1023 public Cursor queryWithFactory(CursorFactory cursorFactory,
1024 boolean distinct, String table, String[] columns,
1025 String selection, String[] selectionArgs, String groupBy,
1026 String having, String orderBy, String limit) {
1027 String sql = SQLiteQueryBuilder.buildQueryString(
1028 distinct, table, columns, selection, groupBy, having, orderBy, limit);
1029
1030 return rawQueryWithFactory(
1031 cursorFactory, sql, selectionArgs, findEditTable(table));
1032 }
1033
1034 /**
1035 * Query the given table, returning a {@link Cursor} over the result set.
1036 *
1037 * @param table The table name to compile the query against.
1038 * @param columns A list of which columns to return. Passing null will
1039 * return all columns, which is discouraged to prevent reading
1040 * data from storage that isn't going to be used.
1041 * @param selection A filter declaring which rows to return, formatted as an
1042 * SQL WHERE clause (excluding the WHERE itself). Passing null
1043 * will return all rows for the given table.
1044 * @param selectionArgs You may include ?s in selection, which will be
1045 * replaced by the values from selectionArgs, in order that they
1046 * appear in the selection. The values will be bound as Strings.
1047 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1048 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1049 * will cause the rows to not be grouped.
1050 * @param having A filter declare which row groups to include in the cursor,
1051 * if row grouping is being used, formatted as an SQL HAVING
1052 * clause (excluding the HAVING itself). Passing null will cause
1053 * all row groups to be included, and is required when row
1054 * grouping is not being used.
1055 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1056 * (excluding the ORDER BY itself). Passing null will use the
1057 * default sort order, which may be unordered.
1058 * @return A {@link Cursor} object, which is positioned before the first entry
1059 * @see Cursor
1060 */
1061 public Cursor query(String table, String[] columns, String selection,
1062 String[] selectionArgs, String groupBy, String having,
1063 String orderBy) {
1064
1065 return query(false, table, columns, selection, selectionArgs, groupBy,
1066 having, orderBy, null /* limit */);
1067 }
1068
1069 /**
1070 * Query the given table, returning a {@link Cursor} over the result set.
1071 *
1072 * @param table The table name to compile the query against.
1073 * @param columns A list of which columns to return. Passing null will
1074 * return all columns, which is discouraged to prevent reading
1075 * data from storage that isn't going to be used.
1076 * @param selection A filter declaring which rows to return, formatted as an
1077 * SQL WHERE clause (excluding the WHERE itself). Passing null
1078 * will return all rows for the given table.
1079 * @param selectionArgs You may include ?s in selection, which will be
1080 * replaced by the values from selectionArgs, in order that they
1081 * appear in the selection. The values will be bound as Strings.
1082 * @param groupBy A filter declaring how to group rows, formatted as an SQL
1083 * GROUP BY clause (excluding the GROUP BY itself). Passing null
1084 * will cause the rows to not be grouped.
1085 * @param having A filter declare which row groups to include in the cursor,
1086 * if row grouping is being used, formatted as an SQL HAVING
1087 * clause (excluding the HAVING itself). Passing null will cause
1088 * all row groups to be included, and is required when row
1089 * grouping is not being used.
1090 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
1091 * (excluding the ORDER BY itself). Passing null will use the
1092 * default sort order, which may be unordered.
1093 * @param limit Limits the number of rows returned by the query,
1094 * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
1095 * @return A {@link Cursor} object, which is positioned before the first entry
1096 * @see Cursor
1097 */
1098 public Cursor query(String table, String[] columns, String selection,
1099 String[] selectionArgs, String groupBy, String having,
1100 String orderBy, String limit) {
1101
1102 return query(false, table, columns, selection, selectionArgs, groupBy,
1103 having, orderBy, limit);
1104 }
1105
1106 /**
1107 * Runs the provided SQL and returns a {@link Cursor} over the result set.
1108 *
1109 * @param sql the SQL query. The SQL string must not be ; terminated
1110 * @param selectionArgs You may include ?s in where clause in the query,
1111 * which will be replaced by the values from selectionArgs. The
1112 * values will be bound as Strings.
1113 * @return A {@link Cursor} object, which is positioned before the first entry
1114 */
1115 public Cursor rawQuery(String sql, String[] selectionArgs) {
1116 return rawQueryWithFactory(null, sql, selectionArgs, null);
1117 }
1118
1119 /**
1120 * Runs the provided SQL and returns a cursor over the result set.
1121 *
1122 * @param cursorFactory the cursor factory to use, or null for the default factory
1123 * @param sql the SQL query. The SQL string must not be ; terminated
1124 * @param selectionArgs You may include ?s in where clause in the query,
1125 * which will be replaced by the values from selectionArgs. The
1126 * values will be bound as Strings.
1127 * @param editTable the name of the first table, which is editable
1128 * @return A {@link Cursor} object, which is positioned before the first entry
1129 */
1130 public Cursor rawQueryWithFactory(
1131 CursorFactory cursorFactory, String sql, String[] selectionArgs,
1132 String editTable) {
1133 long timeStart = 0;
1134
1135 if (Config.LOGV) {
1136 timeStart = System.currentTimeMillis();
1137 }
1138
1139 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable);
1140
1141 try {
1142 return driver.query(
1143 cursorFactory != null ? cursorFactory : mFactory,
1144 selectionArgs);
1145 } finally {
1146 if (Config.LOGV) {
1147 long duration = System.currentTimeMillis() - timeStart;
1148
1149 Log.v(SQLiteCursor.TAG,
1150 "query (" + duration + " ms): " + driver.toString() + ", args are "
1151 + (selectionArgs != null
1152 ? TextUtils.join(",", selectionArgs)
1153 : "<null>"));
1154 }
1155 }
1156 }
1157
1158 /**
1159 * Runs the provided SQL and returns a cursor over the result set.
1160 * The cursor will read an initial set of rows and the return to the caller.
1161 * It will continue to read in batches and send data changed notifications
1162 * when the later batches are ready.
1163 * @param sql the SQL query. The SQL string must not be ; terminated
1164 * @param selectionArgs You may include ?s in where clause in the query,
1165 * which will be replaced by the values from selectionArgs. The
1166 * values will be bound as Strings.
1167 * @param initialRead set the initial count of items to read from the cursor
1168 * @param maxRead set the count of items to read on each iteration after the first
1169 * @return A {@link Cursor} object, which is positioned before the first entry
Andy Stadlerf8a7cea2009-04-10 16:24:47 -07001170 *
1171 * This work is incomplete and not fully tested or reviewed, so currently
1172 * hidden.
1173 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 */
1175 public Cursor rawQuery(String sql, String[] selectionArgs,
1176 int initialRead, int maxRead) {
1177 SQLiteCursor c = (SQLiteCursor)rawQueryWithFactory(
1178 null, sql, selectionArgs, null);
1179 c.setLoadStyle(initialRead, maxRead);
1180 return c;
1181 }
1182
1183 /**
1184 * Convenience method for inserting a row into the database.
1185 *
1186 * @param table the table to insert the row into
1187 * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
1188 * so if initialValues is empty this column will explicitly be
1189 * assigned a NULL value
1190 * @param values this map contains the initial column values for the
1191 * row. The keys should be the column names and the values the
1192 * column values
1193 * @return the row ID of the newly inserted row, or -1 if an error occurred
1194 */
1195 public long insert(String table, String nullColumnHack, ContentValues values) {
1196 try {
1197 return insertWithOnConflict(table, nullColumnHack, values, null);
1198 } catch (SQLException e) {
1199 Log.e(TAG, "Error inserting " + values, e);
1200 return -1;
1201 }
1202 }
1203
1204 /**
1205 * Convenience method for inserting a row into the database.
1206 *
1207 * @param table the table to insert the row into
1208 * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
1209 * so if initialValues is empty this column will explicitly be
1210 * assigned a NULL value
1211 * @param values this map contains the initial column values for the
1212 * row. The keys should be the column names and the values the
1213 * column values
1214 * @throws SQLException
1215 * @return the row ID of the newly inserted row, or -1 if an error occurred
1216 */
1217 public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
1218 throws SQLException {
1219 return insertWithOnConflict(table, nullColumnHack, values, null);
1220 }
1221
1222 /**
1223 * Convenience method for replacing a row in the database.
1224 *
1225 * @param table the table in which to replace the row
1226 * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
1227 * so if initialValues is empty this row will explicitly be
1228 * assigned a NULL value
1229 * @param initialValues this map contains the initial column values for
1230 * the row. The key
1231 * @return the row ID of the newly inserted row, or -1 if an error occurred
1232 */
1233 public long replace(String table, String nullColumnHack, ContentValues initialValues) {
1234 try {
1235 return insertWithOnConflict(table, nullColumnHack, initialValues,
1236 ConflictAlgorithm.REPLACE);
1237 } catch (SQLException e) {
1238 Log.e(TAG, "Error inserting " + initialValues, e);
1239 return -1;
1240 }
1241 }
1242
1243 /**
1244 * Convenience method for replacing a row in the database.
1245 *
1246 * @param table the table in which to replace the row
1247 * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
1248 * so if initialValues is empty this row will explicitly be
1249 * assigned a NULL value
1250 * @param initialValues this map contains the initial column values for
1251 * the row. The key
1252 * @throws SQLException
1253 * @return the row ID of the newly inserted row, or -1 if an error occurred
1254 */
1255 public long replaceOrThrow(String table, String nullColumnHack,
1256 ContentValues initialValues) throws SQLException {
1257 return insertWithOnConflict(table, nullColumnHack, initialValues,
1258 ConflictAlgorithm.REPLACE);
1259 }
1260
1261 /**
1262 * General method for inserting a row into the database.
1263 *
1264 * @param table the table to insert the row into
1265 * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
1266 * so if initialValues is empty this column will explicitly be
1267 * assigned a NULL value
1268 * @param initialValues this map contains the initial column values for the
1269 * row. The keys should be the column names and the values the
1270 * column values
1271 * @param algorithm {@link ConflictAlgorithm} for insert conflict resolver
1272 * @return the row ID of the newly inserted row, or -1 if an error occurred
1273 * @hide
1274 */
1275 public long insertWithOnConflict(String table, String nullColumnHack,
1276 ContentValues initialValues, ConflictAlgorithm algorithm) {
1277 if (!isOpen()) {
1278 throw new IllegalStateException("database not open");
1279 }
1280
1281 // Measurements show most sql lengths <= 152
1282 StringBuilder sql = new StringBuilder(152);
1283 sql.append("INSERT");
1284 if (algorithm != null) {
1285 sql.append(" OR ");
1286 sql.append(algorithm.value());
1287 }
1288 sql.append(" INTO ");
1289 sql.append(table);
1290 // Measurements show most values lengths < 40
1291 StringBuilder values = new StringBuilder(40);
1292
1293 Set<Map.Entry<String, Object>> entrySet = null;
1294 if (initialValues != null && initialValues.size() > 0) {
1295 entrySet = initialValues.valueSet();
1296 Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
1297 sql.append('(');
1298
1299 boolean needSeparator = false;
1300 while (entriesIter.hasNext()) {
1301 if (needSeparator) {
1302 sql.append(", ");
1303 values.append(", ");
1304 }
1305 needSeparator = true;
1306 Map.Entry<String, Object> entry = entriesIter.next();
1307 sql.append(entry.getKey());
1308 values.append('?');
1309 }
1310
1311 sql.append(')');
1312 } else {
1313 sql.append("(" + nullColumnHack + ") ");
1314 values.append("NULL");
1315 }
1316
1317 sql.append(" VALUES(");
1318 sql.append(values);
1319 sql.append(");");
1320
1321 lock();
1322 SQLiteStatement statement = null;
1323 try {
1324 statement = compileStatement(sql.toString());
1325
1326 // Bind the values
1327 if (entrySet != null) {
1328 int size = entrySet.size();
1329 Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
1330 for (int i = 0; i < size; i++) {
1331 Map.Entry<String, Object> entry = entriesIter.next();
1332 DatabaseUtils.bindObjectToProgram(statement, i + 1, entry.getValue());
1333 }
1334 }
1335
1336 // Run the program and then cleanup
1337 statement.execute();
1338
1339 long insertedRowId = lastInsertRow();
1340 if (insertedRowId == -1) {
1341 Log.e(TAG, "Error inserting " + initialValues + " using " + sql);
1342 } else {
1343 if (Config.LOGD && Log.isLoggable(TAG, Log.VERBOSE)) {
1344 Log.v(TAG, "Inserting row " + insertedRowId + " from "
1345 + initialValues + " using " + sql);
1346 }
1347 }
1348 return insertedRowId;
1349 } catch (SQLiteDatabaseCorruptException e) {
1350 onCorruption();
1351 throw e;
1352 } finally {
1353 if (statement != null) {
1354 statement.close();
1355 }
1356 unlock();
1357 }
1358 }
1359
1360 /**
1361 * Convenience method for deleting rows in the database.
1362 *
1363 * @param table the table to delete from
1364 * @param whereClause the optional WHERE clause to apply when deleting.
1365 * Passing null will delete all rows.
1366 * @return the number of rows affected if a whereClause is passed in, 0
1367 * otherwise. To remove all rows and get a count pass "1" as the
1368 * whereClause.
1369 */
1370 public int delete(String table, String whereClause, String[] whereArgs) {
1371 if (!isOpen()) {
1372 throw new IllegalStateException("database not open");
1373 }
1374 lock();
1375 SQLiteStatement statement = null;
1376 try {
1377 statement = compileStatement("DELETE FROM " + table
1378 + (!TextUtils.isEmpty(whereClause)
1379 ? " WHERE " + whereClause : ""));
1380 if (whereArgs != null) {
1381 int numArgs = whereArgs.length;
1382 for (int i = 0; i < numArgs; i++) {
1383 DatabaseUtils.bindObjectToProgram(statement, i + 1, whereArgs[i]);
1384 }
1385 }
1386 statement.execute();
1387 statement.close();
1388 return lastChangeCount();
1389 } catch (SQLiteDatabaseCorruptException e) {
1390 onCorruption();
1391 throw e;
1392 } finally {
1393 if (statement != null) {
1394 statement.close();
1395 }
1396 unlock();
1397 }
1398 }
1399
1400 /**
1401 * Convenience method for updating rows in the database.
1402 *
1403 * @param table the table to update in
1404 * @param values a map from column names to new column values. null is a
1405 * valid value that will be translated to NULL.
1406 * @param whereClause the optional WHERE clause to apply when updating.
1407 * Passing null will update all rows.
1408 * @return the number of rows affected
1409 */
1410 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
1411 return updateWithOnConflict(table, values, whereClause, whereArgs, null);
1412 }
1413
1414 /**
1415 * Convenience method for updating rows in the database.
1416 *
1417 * @param table the table to update in
1418 * @param values a map from column names to new column values. null is a
1419 * valid value that will be translated to NULL.
1420 * @param whereClause the optional WHERE clause to apply when updating.
1421 * Passing null will update all rows.
1422 * @param algorithm {@link ConflictAlgorithm} for update conflict resolver
1423 * @return the number of rows affected
1424 * @hide
1425 */
1426 public int updateWithOnConflict(String table, ContentValues values,
1427 String whereClause, String[] whereArgs, ConflictAlgorithm algorithm) {
1428 if (!isOpen()) {
1429 throw new IllegalStateException("database not open");
1430 }
1431
1432 if (values == null || values.size() == 0) {
1433 throw new IllegalArgumentException("Empty values");
1434 }
1435
1436 StringBuilder sql = new StringBuilder(120);
1437 sql.append("UPDATE ");
1438 if (algorithm != null) {
Bjorn Bringert7f4c2ea2009-07-22 12:49:17 +01001439 sql.append("OR ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 sql.append(algorithm.value());
Bjorn Bringert7f4c2ea2009-07-22 12:49:17 +01001441 sql.append(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 }
1443
1444 sql.append(table);
1445 sql.append(" SET ");
1446
1447 Set<Map.Entry<String, Object>> entrySet = values.valueSet();
1448 Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
1449
1450 while (entriesIter.hasNext()) {
1451 Map.Entry<String, Object> entry = entriesIter.next();
1452 sql.append(entry.getKey());
1453 sql.append("=?");
1454 if (entriesIter.hasNext()) {
1455 sql.append(", ");
1456 }
1457 }
1458
1459 if (!TextUtils.isEmpty(whereClause)) {
1460 sql.append(" WHERE ");
1461 sql.append(whereClause);
1462 }
1463
1464 lock();
1465 SQLiteStatement statement = null;
1466 try {
1467 statement = compileStatement(sql.toString());
1468
1469 // Bind the values
1470 int size = entrySet.size();
1471 entriesIter = entrySet.iterator();
1472 int bindArg = 1;
1473 for (int i = 0; i < size; i++) {
1474 Map.Entry<String, Object> entry = entriesIter.next();
1475 DatabaseUtils.bindObjectToProgram(statement, bindArg, entry.getValue());
1476 bindArg++;
1477 }
1478
1479 if (whereArgs != null) {
1480 size = whereArgs.length;
1481 for (int i = 0; i < size; i++) {
1482 statement.bindString(bindArg, whereArgs[i]);
1483 bindArg++;
1484 }
1485 }
1486
1487 // Run the program and then cleanup
1488 statement.execute();
1489 statement.close();
1490 int numChangedRows = lastChangeCount();
1491 if (Config.LOGD && Log.isLoggable(TAG, Log.VERBOSE)) {
1492 Log.v(TAG, "Updated " + numChangedRows + " using " + values + " and " + sql);
1493 }
1494 return numChangedRows;
1495 } catch (SQLiteDatabaseCorruptException e) {
1496 onCorruption();
1497 throw e;
1498 } catch (SQLException e) {
1499 Log.e(TAG, "Error updating " + values + " using " + sql);
1500 throw e;
1501 } finally {
1502 if (statement != null) {
1503 statement.close();
1504 }
1505 unlock();
1506 }
1507 }
1508
1509 /**
1510 * Execute a single SQL statement that is not a query. For example, CREATE
1511 * TABLE, DELETE, INSERT, etc. Multiple statements separated by ;s are not
1512 * supported. it takes a write lock
1513 *
1514 * @throws SQLException If the SQL string is invalid for some reason
1515 */
1516 public void execSQL(String sql) throws SQLException {
1517 boolean logStats = mLogStats;
1518 long timeStart = logStats ? SystemClock.elapsedRealtime() : 0;
1519 lock();
1520 try {
1521 native_execSQL(sql);
1522 } catch (SQLiteDatabaseCorruptException e) {
1523 onCorruption();
1524 throw e;
1525 } finally {
1526 unlock();
1527 }
1528 if (logStats) {
1529 logTimeStat(false /* not a read */, timeStart, SystemClock.elapsedRealtime());
1530 }
1531 }
1532
1533 /**
1534 * Execute a single SQL statement that is not a query. For example, CREATE
1535 * TABLE, DELETE, INSERT, etc. Multiple statements separated by ;s are not
1536 * supported. it takes a write lock,
1537 *
1538 * @param sql
1539 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
1540 * @throws SQLException If the SQL string is invalid for some reason
1541 */
1542 public void execSQL(String sql, Object[] bindArgs) throws SQLException {
1543 if (bindArgs == null) {
1544 throw new IllegalArgumentException("Empty bindArgs");
1545 }
1546
1547 boolean logStats = mLogStats;
1548 long timeStart = logStats ? SystemClock.elapsedRealtime() : 0;
1549 lock();
1550 SQLiteStatement statement = null;
1551 try {
1552 statement = compileStatement(sql);
1553 if (bindArgs != null) {
1554 int numArgs = bindArgs.length;
1555 for (int i = 0; i < numArgs; i++) {
1556 DatabaseUtils.bindObjectToProgram(statement, i + 1, bindArgs[i]);
1557 }
1558 }
1559 statement.execute();
1560 } catch (SQLiteDatabaseCorruptException e) {
1561 onCorruption();
1562 throw e;
1563 } finally {
1564 if (statement != null) {
1565 statement.close();
1566 }
1567 unlock();
1568 }
1569 if (logStats) {
1570 logTimeStat(false /* not a read */, timeStart, SystemClock.elapsedRealtime());
1571 }
1572 }
1573
1574 @Override
1575 protected void finalize() {
1576 if (isOpen()) {
1577 if (mPrograms.isEmpty()) {
1578 Log.e(TAG, "Leak found", mLeakedException);
1579 } else {
1580 IllegalStateException leakProgram = new IllegalStateException(
1581 "mPrograms size " + mPrograms.size(), mLeakedException);
1582 Log.e(TAG, "Leak found", leakProgram);
1583 }
1584 closeClosable();
1585 onAllReferencesReleased();
1586 }
1587 }
1588
1589 /**
1590 * Private constructor. See {@link #create} and {@link #openDatabase}.
1591 *
1592 * @param path The full path to the database
1593 * @param factory The factory to use when creating cursors, may be NULL.
1594 * @param flags 0 or {@link #NO_LOCALIZED_COLLATORS}. If the database file already
1595 * exists, mFlags will be updated appropriately.
1596 */
1597 private SQLiteDatabase(String path, CursorFactory factory, int flags) {
1598 if (path == null) {
1599 throw new IllegalArgumentException("path should not be null");
1600 }
1601 mFlags = flags;
1602 mPath = path;
1603 mLogStats = "1".equals(android.os.SystemProperties.get("db.logstats"));
1604
1605 mLeakedException = new IllegalStateException(path +
1606 " SQLiteDatabase created and never closed");
1607 mFactory = factory;
1608 dbopen(mPath, mFlags);
1609 mPrograms = new WeakHashMap<SQLiteClosable,Object>();
1610 try {
1611 setLocale(Locale.getDefault());
1612 } catch (RuntimeException e) {
1613 Log.e(TAG, "Failed to setLocale() when constructing, closing the database", e);
1614 dbclose();
1615 throw e;
1616 }
1617 }
1618
1619 /**
1620 * return whether the DB is opened as read only.
1621 * @return true if DB is opened as read only
1622 */
1623 public boolean isReadOnly() {
1624 return (mFlags & OPEN_READ_MASK) == OPEN_READONLY;
1625 }
1626
1627 /**
1628 * @return true if the DB is currently open (has not been closed)
1629 */
1630 public boolean isOpen() {
1631 return mNativeHandle != 0;
1632 }
1633
1634 public boolean needUpgrade(int newVersion) {
1635 return newVersion > getVersion();
1636 }
1637
1638 /**
1639 * Getter for the path to the database file.
1640 *
1641 * @return the path to our database file.
1642 */
1643 public final String getPath() {
1644 return mPath;
1645 }
1646
1647 /* package */ void logTimeStat(boolean read, long begin, long end) {
1648 EventLog.writeEvent(DB_OPERATION_EVENT, mPath, read ? 0 : 1, end - begin);
1649 }
1650
1651 /**
1652 * Sets the locale for this database. Does nothing if this database has
1653 * the NO_LOCALIZED_COLLATORS flag set or was opened read only.
1654 * @throws SQLException if the locale could not be set. The most common reason
1655 * for this is that there is no collator available for the locale you requested.
1656 * In this case the database remains unchanged.
1657 */
1658 public void setLocale(Locale locale) {
1659 lock();
1660 try {
1661 native_setLocale(locale.toString(), mFlags);
1662 } finally {
1663 unlock();
1664 }
1665 }
1666
1667 /**
1668 * Native call to open the database.
1669 *
1670 * @param path The full path to the database
1671 */
1672 private native void dbopen(String path, int flags);
1673
1674 /**
1675 * Native call to execute a raw SQL statement. {@link #lock} must be held
1676 * when calling this method.
1677 *
1678 * @param sql The raw SQL string
1679 * @throws SQLException
1680 */
1681 /* package */ native void native_execSQL(String sql) throws SQLException;
1682
1683 /**
1684 * Native call to set the locale. {@link #lock} must be held when calling
1685 * this method.
1686 * @throws SQLException
1687 */
1688 /* package */ native void native_setLocale(String loc, int flags);
1689
1690 /**
1691 * Returns the row ID of the last row inserted into the database.
1692 *
1693 * @return the row ID of the last row inserted into the database.
1694 */
1695 /* package */ native long lastInsertRow();
1696
1697 /**
1698 * Returns the number of changes made in the last statement executed.
1699 *
1700 * @return the number of changes made in the last statement executed.
1701 */
1702 /* package */ native int lastChangeCount();
1703}