4

I don't seem to find any information on query, insert or any other SQL method returning null. But it does if error occurs.

I just wonder whether cursor being null means an error occurred or could it mean no rows were selected (for instance)? I don't know how I should treat it - as an error or something that may happen time to time.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Pijusn
  • 11,025
  • 7
  • 57
  • 76

3 Answers3

6

I don't believe you ever need to check if(cursor == null) {}.

First
If your query doesn't return any rows, you will receive an empty Cursor. The Cursor will not be null.

There are many ways to check if a Cursor is empty:

  • if(cursor.getCount == 0) {}
  • if(!cursor.moveToFirst()) {}

In fact all of the Cursor#moveTo...() methods return either true or false, if you receive false then the row that you requested does not exist.

Second
If an error occurs then you need to catch the error in a try-catch block, otherwise the app will crash from an unhandled exception.


Also insert(), update(), and delete() return an integer, not a Cursor. These methods return the number of rows affected by your statement, if no rows are affected these methods return 0.

Sam
  • 86,580
  • 20
  • 181
  • 179
  • So why do all example I see have code like `if (cursor != null && cursor.moveToFirst()) { ... }` ? – Pijusn Sep 21 '12 at 20:54
  • 1
    It is possible (but illogical) to catch the error from creating a bad Cursor and _not_ create an alternate Cursor. This is the only time I know of that could create a null Cursor. However I believe if you are going to take the time to catch the exception, you should create a "default" Cursor (like an empty one). – Sam Sep 21 '12 at 21:14
  • It already happened to me, that the cursor returned from a rawQuery is always null, I don't know what's going on, the database is there, and it's not empty, the return value is ALWAYS null, it's not an empty cursor, it's just null. Don't know why. And I don't have any exception output, except when I move the cursor. – cdytoby Jan 19 '16 at 11:14
  • @Sam: ContentResolver.query and SQLiteDatabase.query throw exceptions. However, android.database.sqlite.SqliteWrapper.query returns null for exceptions, and most custom wrappers follow this convention – Mooing Duck Jul 20 '16 at 19:08
  • It happens on android, so check cursor ==null is a good practice – huluyige Dec 08 '16 at 10:14
  • "A Cursor object, which is positioned before the first entry. May return null if the underlying content provider returns null, or if it crashes." https://developer.android.com/reference/android/content/ContentResolver#query(android.net.Uri,%20java.lang.String[],%20android.os.Bundle,%20android.os.CancellationSignal) – JohnyTex Jun 01 '22 at 11:33
0

If we look at the Android source code, from https://github.com/android/platform_frameworks_base/blob/master/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java, where most queries end up:

public Cursor query(CursorFactory factory, String[] selectionArgs) {
    final SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, mCancellationSignal);
    final Cursor cursor;
    try {
        query.bindAllArgsAsStrings(selectionArgs);

        if (factory == null) {
            cursor = new SQLiteCursor(this, mEditTable, query);
        } else {
            cursor = factory.newCursor(mDatabase, this, mEditTable, query);
        }
    } catch (RuntimeException ex) {
        query.close();
        throw ex;
    }

    mQuery = query;
    return cursor;
}

You can easily see that in the only case the local variable for the Cursor is not assigned then a RuntimeException will be thrown instead. Meaning this function can not ever return null.

You can hypothetically get a RuntimeException from the factory if used. Looking at the constructors for SQLiteQuery and SQLiteCursor no exceptions appear to be thrown. You can get an IllegalArgumentException if your bindings are incorrect during query.bindAllArgsAsStrings(selectionArgs);

Note an SQLiteException can be thrown later from the SQLiteQuery when the non-null Cursor is read.

That specific Android source code hasn't been updated since 2012. It is stable

Dave Thomas
  • 3,667
  • 2
  • 33
  • 41
-3

When a cursor results in no rows selected it returns (-1), if an error occurred the cursor can be null

Samer
  • 536
  • 3
  • 5