private void loadAllUnlockOnWindowBounds(Cursor cursor, CursorWindow window, List<T> list) { int windowEnd = window.getStartPosition() + window.getNumRows(); for (int row = 0; ; row++) { list.add(loadCurrent(cursor, 0, false)); row++; if (row >= windowEnd) { window = moveToNextUnlocked(cursor); if (window == null) { break; } windowEnd = window.getStartPosition() + window.getNumRows(); } else { if (!cursor.moveToNext()) { break; } } } }
/** * Executes a statement and populates the specified {@link CursorWindow} * with a range of results. Returns the number of rows that were counted * during query execution. * * @param sql The SQL statement to execute. * @param bindArgs The arguments to bind, or null if none. * @param window The cursor window to clear and fill. * @param startPos The start position for filling the window. * @param requiredPos The position of a row that MUST be in the window. * If it won't fit, then the query should discard part of what it filled * so that it does. Must be greater than or equal to <code>startPos</code>. * @param countAllRows True to count all rows that the query would return * regagless of whether they fit in the window. * @param connectionFlags The connection flags to use if a connection must be * acquired by this operation. Refer to {@link SQLiteConnectionPool}. * @param cancellationSignal A signal to cancel the operation in progress, or null if none. * @return The number of rows that were counted during query execution. Might * not be all rows in the result set unless <code>countAllRows</code> is true. * @throws SQLiteException if an error occurs, such as a syntax error * or invalid number of bind arguments. * @throws OperationCanceledException if the operation was canceled. */ public int executeForCursorWindow(String sql, Object[] bindArgs, CursorWindow window, int startPos, int requiredPos, boolean countAllRows, int connectionFlags, CancellationSignal cancellationSignal) { if (sql == null) { throw new IllegalArgumentException("sql must not be null."); } if (window == null) { throw new IllegalArgumentException("window must not be null."); } if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) { window.clear(); return 0; } acquireConnection(sql, connectionFlags, cancellationSignal); // might throw try { return mConnection.executeForCursorWindow(sql, bindArgs, window, startPos, requiredPos, countAllRows, cancellationSignal); // might throw } finally { releaseConnection(); // might throw } }
/** * Put the value in given window. If the value type is other than Long, * String, byte[] or Double, the NULL will be filled. * * @return true if succeeded. */ private boolean putValue(CursorWindow window, Object value, int pos, int column) { if (value == null) { return window.putNull(pos, column); } else if (value instanceof Long) { return window.putLong((Long) value, pos, column); } else if (value instanceof String) { return window.putString((String) value, pos, column); } else if (value instanceof byte[] && ((byte[]) value).length > 0) { return window.putBlob((byte[]) value, pos, column); } else if (value instanceof Double) { return window.putDouble((Double) value, pos, column); } else { return window.putNull(pos, column); } }
private void bindPreHoneycomb(JSONObject row, String key, Cursor cursor, int i) throws JSONException { // Since cursor.getType() is not available pre-honeycomb, this is // a workaround so we don't have to bind everything as a string // Details here: http://stackoverflow.com/q/11658239 SQLiteCursor sqLiteCursor = (SQLiteCursor) cursor; CursorWindow cursorWindow = sqLiteCursor.getWindow(); int pos = cursor.getPosition(); if (cursorWindow.isNull(pos, i)) { row.put(key, JSONObject.NULL); } else if (cursorWindow.isLong(pos, i)) { row.put(key, cursor.getLong(i)); } else if (cursorWindow.isFloat(pos, i)) { row.put(key, cursor.getDouble(i)); /* ** Read BLOB as Base-64 DISABLED in this branch: } else if (cursorWindow.isBlob(pos, i)) { row.put(key, new String(Base64.encode(cursor.getBlob(i), Base64.DEFAULT))); // ** Read BLOB as Base-64 DISABLED to HERE. */ } else { // string row.put(key, cursor.getString(i)); } }
/** * Executes a statement and populates the specified {@link CursorWindow} * with a range of results. Returns the number of rows that were counted * during query execution. * * @param sql The SQL statement to execute. * @param bindArgs The arguments to bind, or null if none. * @param window The cursor window to clear and fill. * @param startPos The start position for filling the window. * @param requiredPos The position of a row that MUST be in the window. * If it won't fit, then the query should discard part of what it filled * so that it does. Must be greater than or equal to <code>startPos</code>. * @param countAllRows True to count all rows that the query would return * regagless of whether they fit in the window. * @param connectionFlags The connection flags to use if a connection must be * acquired by this operation. Refer to {@link SQLiteConnectionPool}. * @param cancellationSignal A signal to cancel the operation in progress, or null if none. * @return The number of rows that were counted during query execution. Might * not be all rows in the result set unless <code>countAllRows</code> is true. * * @throws SQLiteException if an error occurs, such as a syntax error * or invalid number of bind arguments. * @throws OperationCanceledException if the operation was canceled. */ public int executeForCursorWindow(String sql, Object[] bindArgs, CursorWindow window, int startPos, int requiredPos, boolean countAllRows, int connectionFlags, CancellationSignal cancellationSignal) { if (sql == null) { throw new IllegalArgumentException("sql must not be null."); } if (window == null) { throw new IllegalArgumentException("window must not be null."); } if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) { window.clear(); return 0; } acquireConnection(sql, connectionFlags, cancellationSignal); // might throw try { return mConnection.executeForCursorWindow(sql, bindArgs, window, startPos, requiredPos, countAllRows, cancellationSignal); // might throw } finally { releaseConnection(); // might throw } }
@SuppressWarnings("deprecation") @SuppressLint("NewApi") static int getCursorType(Cursor cursor, int i) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { return cursor.getType(i); } if (cursor instanceof AbstractWindowedCursor) { CursorWindow cursorWindow = ((AbstractWindowedCursor) cursor).getWindow(); int pos = cursor.getPosition(); int type = -1; if (cursorWindow.isNull(pos, i)) { type = FIELD_TYPE_NULL; } else if (cursorWindow.isLong(pos, i)) { type = FIELD_TYPE_INTEGER; } else if (cursorWindow.isFloat(pos, i)) { type = FIELD_TYPE_FLOAT; } else if (cursorWindow.isString(pos, i)) { type = FIELD_TYPE_STRING; } else if (cursorWindow.isBlob(pos, i)) { type = FIELD_TYPE_BLOB; } return type; } throw new RuntimeException("Unsupported cursor on this platform!"); }
@SuppressWarnings("deprecation") private final void fillGingerbread(ExtendedJSONObject o, Cursor c, String f, int i) { if (!(c instanceof AbstractWindowedCursor)) { throw new IllegalStateException("Unable to handle cursors that don't have a CursorWindow!"); } final AbstractWindowedCursor sqc = (AbstractWindowedCursor) c; final CursorWindow w = sqc.getWindow(); final int pos = c.getPosition(); if (w.isNull(pos, i)) { putNull(o, f); } else if (w.isString(pos, i)) { put(o, f, c.getString(i)); } else if (w.isLong(pos, i)) { put(o, f, c.getLong(i)); } else if (w.isFloat(pos, i)) { o.put(f, c.getDouble(i)); } else if (w.isBlob(pos, i)) { // TODO: this probably doesn't serialize correctly. o.put(f, c.getBlob(i)); } }
@Test public void shouldFillWindowWithCursor() throws Exception { CursorWindow window = new CursorWindow("name"); MatrixCursor testCursor = new MatrixCursor(new String[] { "a", "b", "c", "d"}); testCursor.addRow(new Object[] { 12, "hello", null, new byte[] {(byte) 0xba, (byte) 0xdc, (byte) 0xaf, (byte) 0xfe} }); testCursor.addRow(new Object[] { 34, "baz", 1.2, null }); DatabaseUtils.cursorFillWindow(testCursor, 0, window); assertThat(window.getNumRows()).isEqualTo(2); assertThat(window.getString(0, 1)).isEqualTo("hello"); assertThat(window.getInt(0, 0)).isEqualTo(12); assertThat(window.getString(0, 2)).isNull(); assertThat(window.getBlob(0, 3)).isEqualTo(new byte[] {(byte) 0xba, (byte) 0xdc, (byte) 0xaf, (byte) 0xfe}); assertThat(window.getString(1, 1)).isEqualTo("baz"); assertThat(window.getInt(1, 0)).isEqualTo(34); assertThat(window.getFloat(1, 2)).isEqualTo(1.2f); }
private ArrayList<V> loadAllFromCursor(Cursor cursor) { int count = cursor.getCount(); ArrayList<V> list = new ArrayList<V>(count); if (cursor instanceof CrossProcessCursor) { CursorWindow window = ((CrossProcessCursor) cursor).getWindow(); if (window != null) { if (window.getNumRows() == count) { cursor = new FastCursor(window); } } } final long start = System.currentTimeMillis(); if (cursor.moveToFirst()) { do { list.add(loadCurrent(cursor)); } while (cursor.moveToNext()); } return list; }
/** * Compat method so we can get type of column on API < 11. * Source: http://stackoverflow.com/a/20685546/2643666 */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static int getColumnType(Cursor cursor, int col) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { SQLiteCursor sqLiteCursor = (SQLiteCursor) cursor; CursorWindow cursorWindow = sqLiteCursor.getWindow(); int pos = cursor.getPosition(); int type = -1; if (cursorWindow.isNull(pos, col)) { type = FIELD_TYPE_NULL; } else if (cursorWindow.isLong(pos, col)) { type = FIELD_TYPE_INTEGER; } else if (cursorWindow.isFloat(pos, col)) { type = FIELD_TYPE_FLOAT; } else if (cursorWindow.isString(pos, col)) { type = FIELD_TYPE_STRING; } else if (cursorWindow.isBlob(pos, col)) { type = FIELD_TYPE_BLOB; } return type; } else { return cursor.getType(col); } }
@Override public boolean onMove(int oldPosition, int newPosition){ boolean requiresFill = mWindow == null || newPosition < mWindow.getStartPosition() || newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows()); CursorWindow window = mWindow; int sp = mWindow.getStartPosition(); int gnr = mWindow.getNumRows(); if(requiresFill){ d("onMove(%d,%d)",oldPosition, newPosition); d(" mWindow.getStartPosition = %d",mWindow.getStartPosition()); d(" mWindow.getNumRows = %d",mWindow.getNumRows()); d(" requiresFill = "+requiresFill); d(" inTransaction = " + _db.inTransaction()); d(" begin super.OnMove"); boolean b = super.onMove(oldPosition, newPosition); d(" end super.OnMove"); d(" inTransaction = " + _db.inTransaction()); return b; } return true; }
public CursorWindow getWindow(int position) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IBulkCursor.descriptor); data.writeInt(position); mRemote.transact(GET_CURSOR_WINDOW_TRANSACTION, data, reply, 0); DatabaseUtils.readExceptionFromParcel(reply); CursorWindow window = null; if (reply.readInt() == 1) { window = CursorWindow.newFromParcel(reply); } return window; } finally { data.recycle(); reply.recycle(); } }
/** * Unlock identityScope during cursor.moveToNext() when it is about to fill the window (needs a db connection): * We should not hold the lock while trying to acquire a db connection to avoid deadlocks. */ private CursorWindow moveToNextUnlocked(Cursor cursor) { identityScope.unlock(); try { if (cursor.moveToNext()) { return ((CrossProcessCursor) cursor).getWindow(); } else { return null; } } finally { identityScope.lock(); } }
private static int getType(Cursor cursor, int columnIndex) throws Exception { if (Build.VERSION.SDK_INT >= 11) { return cursor.getType(columnIndex); } SQLiteCursor sqLiteCursor = (SQLiteCursor) cursor; CursorWindow cursorWindow = sqLiteCursor.getWindow(); int pos = cursor.getPosition(); int type = -1; if (cursorWindow.isNull(pos, columnIndex)) { type = Cursor.FIELD_TYPE_NULL; } else if (cursorWindow.isLong(pos, columnIndex)) { type = Cursor.FIELD_TYPE_INTEGER; } else if (cursorWindow.isFloat(pos, columnIndex)) { type = Cursor.FIELD_TYPE_FLOAT; } else if (cursorWindow.isString(pos, columnIndex)) { type = Cursor.FIELD_TYPE_STRING; } else if (cursorWindow.isBlob(pos, columnIndex)) { type = Cursor.FIELD_TYPE_BLOB; } return type; }
/** * Fill row with the given value. If the value type is other than Long, * String, byte[] or Double, the NULL will be filled. * * @return true if succeeded, false if window is full. */ private boolean fillRow(CursorWindow window, Object value, int pos, int column) { if (putValue(window, value, pos, column)) { return true; } else { window.freeLastRow(); return false; } }
@Override public void fillWindow(int position, CursorWindow window) { if (mCursor instanceof CrossProcessCursor) { final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor; crossProcessCursor.fillWindow(position, window); return; } DatabaseUtils.cursorFillWindow(mCursor, position, window); }
@Override public CursorWindow getWindow() { if (mCursor instanceof CrossProcessCursor) { final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor; return crossProcessCursor.getWindow(); } return null; }
@SmallTest public void testConstructor_WithName() { CursorWindow window = new CursorWindow("MyWindow"); assertEquals("MyWindow", window.getName()); assertEquals(0, window.getStartPosition()); window.close(); }
@SmallTest public void testConstructorWithEmptyName() { CursorWindow window = new CursorWindow(""); assertEquals("<unnamed>", window.getName()); assertEquals(0, window.getStartPosition()); window.close(); }
@SmallTest public void testConstructorWithNullName() { CursorWindow window = new CursorWindow(null); assertEquals("<unnamed>", window.getName()); assertEquals(0, window.getStartPosition()); window.close(); }
@SmallTest public void testDeprecatedConstructor() { @SuppressWarnings("deprecation") CursorWindow window = new CursorWindow(true /*this argument is ignored*/); assertEquals("<unnamed>", window.getName()); assertEquals(0, window.getStartPosition()); window.close(); }
private void doTestValues(CursorWindow window) { assertTrue(window.setNumColumns(7)); assertTrue(window.allocRow()); double db1 = 1.26; assertTrue(window.putDouble(db1, 0, 0)); double db2 = window.getDouble(0, 0); assertEquals(db1, db2); long int1 = Long.MAX_VALUE; assertTrue(window.putLong(int1, 0, 1)); long int2 = window.getLong(0, 1); assertEquals(int1, int2); assertTrue(window.putString("1198032740000", 0, 3)); assertEquals("1198032740000", window.getString(0, 3)); assertEquals(1198032740000L, window.getLong(0, 3)); assertTrue(window.putString(Long.toString(1198032740000L), 0, 3)); assertEquals(Long.toString(1198032740000L), window.getString(0, 3)); assertEquals(1198032740000L, window.getLong(0, 3)); assertTrue(window.putString(Double.toString(42.0), 0, 4)); assertEquals(Double.toString(42.0), window.getString(0, 4)); assertEquals(42.0, window.getDouble(0, 4)); // put blob byte[] blob = new byte[1000]; byte value = 99; Arrays.fill(blob, value); assertTrue(window.putBlob(blob, 0, 6)); assertTrue(Arrays.equals(blob, window.getBlob(0, 6))); }
public static SubjectFactory<CursorWindowSubject, CursorWindow> type() { return new SubjectFactory<CursorWindowSubject, CursorWindow>() { @Override public CursorWindowSubject getSubject(FailureStrategy fs, CursorWindow that) { return new CursorWindowSubject(fs, that); } }; }
public static DataHolder createFromParcel(Parcel paramParcel) { int i = 0; Bundle localBundle = null; int j = zza.zzbc(paramParcel); CursorWindow[] arrayOfCursorWindow = null; String[] arrayOfString = null; int k = 0; while (paramParcel.dataPosition() < j) { int m = paramParcel.readInt(); switch (0xFFFF & m) { default: zza.zzb(paramParcel, m); break; case 1: arrayOfString = zza.zzC(paramParcel, m); break; case 1000: k = zza.zzg(paramParcel, m); break; case 2: arrayOfCursorWindow = (CursorWindow[])zza.zzb(paramParcel, m, CursorWindow.CREATOR); break; case 3: i = zza.zzg(paramParcel, m); break; case 4: localBundle = zza.zzs(paramParcel, m); } } if (paramParcel.dataPosition() != j) { throw new zza.zza("Overread allowed size end=" + j, paramParcel); } DataHolder localDataHolder = new DataHolder(k, arrayOfString, arrayOfCursorWindow, i, localBundle); localDataHolder.validateContents(); return localDataHolder; }
public DataHolder(int paramInt1, String[] paramArrayOfString, CursorWindow[] paramArrayOfCursorWindow, int paramInt2, Bundle paramBundle) { this.a = paramInt1; this.b = paramArrayOfString; this.d = paramArrayOfCursorWindow; this.e = paramInt2; this.f = paramBundle; }
/** * Closes the data holder, releasing all of its resources and making it completely invalid. */ @Override public void close() { synchronized (this) { if (!closed) { closed = true; for (CursorWindow window : windows) { window.close(); } } } }
/** * Gets the number of rows in the data holder. * * @return the number of rows in the data holder. */ public int getCount() { int c = 0; if (windows != null) { for (CursorWindow window : windows) { c += window.getNumRows(); } } return c; }
@Override public void fillWindow(int position, CursorWindow window) { if (position < 0 || position > getCount()) { return; } window.acquireReference(); try { moveToPosition(position - 1); window.clear(); window.setStartPosition(position); int columnNum = getColumnCount(); window.setNumColumns(columnNum); boolean isFull = false; int numRows = 10; while (!isFull && --numRows > 0 && moveToNext() && window.allocRow()) { for (int i = 0; i < columnNum; i++) { String field = getString(i); if (field != null) { if (!window.putString(field, getPosition(), i)) { window.freeLastRow(); isFull = true; break; } } else { if (!window.putNull(getPosition(), i)) { window.freeLastRow(); isFull = true; break; } } } } } catch (IllegalStateException e) { // simply ignore it } finally { window.releaseReference(); } }
public DataHolder createFromParcel(Parcel paramParcel) { int i = a.n(paramParcel); int j = 0; String[] arrayOfString = null; CursorWindow[] arrayOfCursorWindow = null; int k = 0; Bundle localBundle = null; while (paramParcel.dataPosition() < i) { int m = a.m(paramParcel); switch (a.M(m)) { default: break; case 1: arrayOfString = a.x(paramParcel, m); break; case 1000: j = a.g(paramParcel, m); break; case 2: arrayOfCursorWindow = (CursorWindow[])a.b(paramParcel, m, CursorWindow.CREATOR); break; case 3: k = a.g(paramParcel, m); break; case 4: localBundle = a.o(paramParcel, m); continue; a.b(paramParcel, m); } } if (paramParcel.dataPosition() != i) throw new a.a("Overread allowed size end=" + i, paramParcel); DataHolder localDataHolder = new DataHolder(j, arrayOfString, arrayOfCursorWindow, k, localBundle); localDataHolder.validateContents(); return localDataHolder; }
public void fillWindow(int position, CursorWindow window) { int count = getCount(); if (position < 0 || position > count + 1) { return; } window.acquireReference(); try { int oldpos = getPosition(); int pos = position; window.clear(); window.setStartPosition(position); int columnNum = getColumnCount(); window.setNumColumns(columnNum); while (moveToPosition(pos) && window.allocRow()) { for (int i = 0; i < columnNum; i++) { String field = getString(i); if (field != null) { if (!window.putString(field, pos, i)) { window.freeLastRow(); break; } } else { if (!window.putNull(pos, i)) { window.freeLastRow(); break; } } } ++pos; } moveToPosition(oldpos); } catch (IllegalStateException e){ // simply ignore it } finally { window.releaseReference(); } }