SQLiteCursor.java revision f3ca9a5c7e87319c934b5815566054d2e5c2085f
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.database.sqlite; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.AbstractWindowedCursor; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.CursorWindow; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.DataSetObserver; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.SQLException; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Iterator; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.concurrent.locks.ReentrantLock; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A Cursor implementation that exposes results from a query on a 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SQLiteDatabase}. 39f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * 40f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * SQLiteCursor is not internally synchronized so code using a SQLiteCursor from multiple 41f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * threads should perform its own synchronization when using the SQLiteCursor. 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SQLiteCursor extends AbstractWindowedCursor { 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final String TAG = "Cursor"; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int NO_COUNT = -1; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The name of the table to edit */ 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mEditTable; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The names of the columns in the rows */ 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String[] mColumns; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The query object for the cursor */ 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SQLiteQuery mQuery; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The database the cursor was created from */ 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SQLiteDatabase mDatabase; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The compiled query this cursor came from */ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SQLiteCursorDriver mDriver; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The number of rows in the cursor */ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mCount = NO_COUNT; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** A mapping of column names to column indices, to speed up lookups */ 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Map<String, Integer> mColumnNameMap; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Used to find out where a cursor was allocated in case it never got 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * released. */ 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private StackTraceElement[] mStackTraceElements; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * mMaxRead is the max items that each cursor window reads 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default to a very high value 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMaxRead = Integer.MAX_VALUE; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mInitialRead = Integer.MAX_VALUE; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mCursorState = 0; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ReentrantLock mLock = null; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mPendingData = false; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * support for a cursor variant that doesn't always read all results 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * initialRead is the initial number of items that cursor window reads 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if query contains more than this number of items, a thread will be 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * created and handle the left over items so that caller can show 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * results as soon as possible 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param initialRead initial number of items that cursor read 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param maxRead leftover items read at maxRead items per time 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setLoadStyle(int initialRead, int maxRead) { 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMaxRead = maxRead; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInitialRead = initialRead; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock = new ReentrantLock(true); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void queryThreadLock() { 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLock != null) { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.lock(); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void queryThreadUnlock() { 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLock != null) { 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.unlock(); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final private class QueryThread implements Runnable { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final int mThreadState; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project QueryThread(int version) { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThreadState = version; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendMessage() { 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mNotificationHandler != null) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNotificationHandler.sendEmptyMessage(1); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPendingData = false; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPendingData = true; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // use cached mWindow, to avoid get null mWindow 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CursorWindow cw = mWindow; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Process.setThreadPriority(Process.myTid(), Process.THREAD_PRIORITY_BACKGROUND); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the cursor's state doesn't change 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.lock(); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCursorState != mThreadState) { 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.unlock(); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mQuery.fillWindow(cw, mMaxRead, mCount); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // return -1 means not finished 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count != 0) { 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == NO_COUNT){ 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCount += mMaxRead; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessage(); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCount = count; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessage(); 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // end the tread when the cursor is close 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.unlock(); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected class MainThreadNotificationHandler extends Handler { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notifyDataSetChange(); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected MainThreadNotificationHandler mNotificationHandler; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void registerDataSetObserver(DataSetObserver observer) { 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.registerDataSetObserver(observer); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((Integer.MAX_VALUE != mMaxRead || Integer.MAX_VALUE != mInitialRead) && 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNotificationHandler == null) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project queryThreadLock(); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNotificationHandler = new MainThreadNotificationHandler(); 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPendingData) { 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notifyDataSetChange(); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPendingData = false; 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project queryThreadUnlock(); 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a query and provide access to its result set through a Cursor 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * interface. For a query such as: {@code SELECT name, birth, phone FROM 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth, 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * phone) would be in the projection argument and everything from 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@code FROM} onward would be in the params argument. This constructor 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * has package scope. 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param db a reference to a Database object that is already constructed 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and opened 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param editTable the name of the table used for this query 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param query the rest of the query terms 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cursor is finalized 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SQLiteCursor(SQLiteDatabase db, SQLiteCursorDriver driver, 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String editTable, SQLiteQuery query) { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The AbstractCursor constructor needs to do some setup. 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStackTraceElements = new Exception().getStackTrace(); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase = db; 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDriver = driver; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEditTable = editTable; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mColumnNameMap = null; 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mQuery = query; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project db.lock(); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Setup the list of columns 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int columnCount = mQuery.columnCountLocked(); 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mColumns = new String[columnCount]; 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Read in all column names 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < columnCount; i++) { 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String columnName = mQuery.columnNameLocked(i); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mColumns[i] = columnName; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v("DatabaseWindow", "mColumns[" + i + "] is " 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + mColumns[i]); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make note of the row ID column index for quick access to it 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ("_id".equals(columnName)) { 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRowIdColumnIndex = i; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project db.unlock(); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the SQLiteDatabase that this cursor is associated with. 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SQLiteDatabase getDatabase() { 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDatabase; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onMove(int oldPosition, int newPosition) { 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make sure the row at newPosition is present in the window 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mWindow == null || newPosition < mWindow.getStartPosition() || 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) { 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillWindow(newPosition); 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getCount() { 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCount == NO_COUNT) { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillWindow(0); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mCount; 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void fillWindow (int startPos) { 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mWindow == null) { 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If there isn't a window set already it will only be accessed locally 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindow = new CursorWindow(true /* the window is local only */); 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCursorState++; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project queryThreadLock(); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindow.clear(); 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project queryThreadUnlock(); 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindow.setStartPosition(startPos); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCount = mQuery.fillWindow(mWindow, mInitialRead, 0); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // return -1 means not finished 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCount == NO_COUNT){ 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCount = startPos + mInitialRead; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Thread t = new Thread(new QueryThread(mCursorState), "query thread"); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.start(); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getColumnIndex(String columnName) { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Create mColumnNameMap on demand 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mColumnNameMap == null) { 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] columns = mColumns; 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int columnCount = columns.length; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HashMap<String, Integer> map = new HashMap<String, Integer>(columnCount, 1); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < columnCount; i++) { 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(columns[i], i); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mColumnNameMap = map; 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Hack according to bug 903852 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int periodIndex = columnName.lastIndexOf('.'); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (periodIndex != -1) { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Exception e = new Exception(); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "requesting column name with table name -- " + columnName, e); 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project columnName = columnName.substring(periodIndex + 1); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer i = mColumnNameMap.get(columnName); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i != null) { 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return i.intValue(); 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @deprecated 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean deleteRow() { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkPosition(); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Only allow deletes if there is an ID column, and the ID has been read from it 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mRowIdColumnIndex == -1 || mCurrentRowID == null) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Could not delete row because either the row ID column is not available or it" + 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "has not been read."); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean success; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Ensure we don't change the state of the database when another 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * thread is holding the database lock. requery() and moveTo() are also 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * synchronized here to make sure they get the state of the database 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * immediately following the DELETE. 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase.lock(); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase.delete(mEditTable, mColumns[mRowIdColumnIndex] + "=?", 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new String[] {mCurrentRowID.toString()}); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project success = true; 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLException e) { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project success = false; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int pos = mPos; 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requery(); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Ensure proper cursor state. Note that mCurrentRowID changes 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in this call. 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moveToPosition(pos); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase.unlock(); 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (success) { 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onChange(true); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String[] getColumnNames() { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mColumns; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @deprecated 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean supportsUpdates() { 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.supportsUpdates() && !TextUtils.isEmpty(mEditTable); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @deprecated 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean commitUpdates(Map<? extends Long, 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? extends Map<String, Object>> additionalValues) { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!supportsUpdates()) { 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "commitUpdates not supported on this cursor, did you " 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + "include the _id column?"); 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Prevent other threads from changing the updated rows while they're 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * being processed here. 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mUpdatedRows) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (additionalValues != null) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUpdatedRows.putAll(additionalValues); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mUpdatedRows.size() == 0) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Prevent other threads from changing the database state while 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we process the updated rows, and prevents us from changing the 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * database behind the back of another thread. 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase.beginTransaction(); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sql = new StringBuilder(128); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // For each row that has been updated 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<Long, Map<String, Object>> rowEntry : 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUpdatedRows.entrySet()) { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map<String, Object> values = rowEntry.getValue(); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Long rowIdObj = rowEntry.getKey(); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rowIdObj == null || values == null) { 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("null rowId or values found! rowId = " 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + rowIdObj + ", values = " + values); 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (values.size() == 0) { 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long rowId = rowIdObj.longValue(); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Map.Entry<String, Object>> valuesIter = 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project values.entrySet().iterator(); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.setLength(0); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append("UPDATE " + mEditTable + " SET "); 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // For each column value that has been updated 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] bindings = new Object[values.size()]; 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i = 0; 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (valuesIter.hasNext()) { 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map.Entry<String, Object> entry = valuesIter.next(); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(entry.getKey()); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append("=?"); 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bindings[i] = entry.getValue(); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (valuesIter.hasNext()) { 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(", "); 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i++; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(" WHERE " + mColumns[mRowIdColumnIndex] 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + '=' + rowId); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sql.append(';'); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase.execSQL(sql.toString(), bindings); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase.rowUpdated(mEditTable, rowId); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase.setTransactionSuccessful(); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase.endTransaction(); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUpdatedRows.clear(); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Let any change observers know about the update 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onChange(true); 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void deactivateCommon() { 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) Log.v(TAG, "<<< Releasing cursor " + this); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCursorState = 0; 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mWindow != null) { 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindow.close(); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindow = null; 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) Log.v("DatabaseWindow", "closing window in release()"); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void deactivate() { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.deactivate(); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project deactivateCommon(); 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDriver.cursorDeactivated(); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() { 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.close(); 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project deactivateCommon(); 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mQuery.close(); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDriver.cursorClosed(); 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean requery() { 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isClosed()) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long timeStart = 0; 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) { 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project timeStart = System.currentTimeMillis(); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Synchronize on the database lock to ensure that mCount matches the 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * results of mQuery.requery(). 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase.lock(); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mWindow != null) { 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindow.clear(); 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPos = -1; 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This one will recreate the temp table, and get its count 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDriver.cursorRequeried(this); 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCount = NO_COUNT; 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCursorState++; 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project queryThreadLock(); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mQuery.requery(); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project queryThreadUnlock(); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDatabase.unlock(); 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v("DatabaseWindow", "closing window in requery()"); 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "--- Requery()ed cursor " + this + ": " + mQuery); 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean result = super.requery(); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) { 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long timeEnd = System.currentTimeMillis(); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "requery (" + (timeEnd - timeStart) + " ms): " + mDriver.toString()); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setWindow(CursorWindow window) { 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mWindow != null) { 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCursorState++; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project queryThreadLock(); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindow.close(); 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project queryThreadUnlock(); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCount = NO_COUNT; 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindow = window; 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Changes the selection arguments. The new values take effect after a call to requery(). 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSelectionArguments(String[] selectionArgs) { 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDriver.setBindArguments(selectionArgs); 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Release the native resources, if they haven't been released yet. 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() { 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mWindow != null) { 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String message = "Finalizing cursor " + this + " on " + mEditTable 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " that has not been deactivated or closed"; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, message + "\nThis cursor was created in:"); 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (StackTraceElement ste : mStackTraceElements) { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, " " + ste); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteDebug.notifyActiveCursorFinalized(); 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException(message); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) { 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "Finalizing cursor " + this + " on " + mEditTable); 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 610