6

I'm trying to understand why they would start the cursor before the first position in a row and why it would end after the last position. Is there an inherit advantage to doing it this way?

For example:

public abstract int getPosition () 

Since: API Level 1 Returns the current position of the cursor in the row set. The value is zero-based. When the row set is first returned the cursor will be at position -1, which is before the first row. After the last row is returned another call to next() will leave the cursor past the last entry, at a position of count().

returns the current cursor position.

Thank you.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
evt
  • 139
  • 2
  • 9

3 Answers3

9

Because a Cursor isn't guaranteed to be populated with rows. If you got a Cursor back from a database with 0 rows, the initial position being at 0 doesn't make sense since there isn't a row at position 0.

Jason Robinson
  • 31,005
  • 19
  • 77
  • 131
  • Why would this not make sense? If a cursor has 3 rows, and you've iterated through them using `while (c.moveToNext())`, it'll then be at 3, a position where there isn't a row. Why shouldn't the initial position on an empty cursor follow the same pattern? (You may be right, I'm just trying to understand the logic.) – LarsH Dec 01 '16 at 19:30
  • Because the cursor would be in an indeterminate state otherwise. Position '0' would be ambiguous if it could either mean it is empty or there is a row. The iterator used underneath the cursor *can't* be at position 0, because there isn't a position 0. In your example, the cursor won't ever show it's position as 3. It'll fail trying to move from 2 to 3, and thus stay at 2 and exit the loop. – Jason Robinson Dec 01 '16 at 21:21
  • My last point is wrong. It *does* show position 3. My only guess is to stay consistent with the logical beginning. -1 is the logical start of the cursor, and count() is the logical end of the cursor. I'm not in a position to test it, but from inspecting the source, I would guess that calling `moveToNext()` on an empty cursor would also show it's at position 0, which would be the logical end. – Jason Robinson Dec 01 '16 at 21:33
  • "Because the cursor would be in an indeterminate state otherwise. Position '0' would be ambiguous if it could either mean it is empty or there is a row." Just because the position doesn't tell you the row count doesn't mean the cursor is in an indeterminate state. Position -1 is just as ambiguous: it doesn't tell you whether the cursor is empty or there is a row. – LarsH Dec 01 '16 at 21:48
  • That's not its purpose to tell you those things. It's purpose is to mark the logical start of the cursor. It's a non-position used only to indicate that the iterator has been initialized or reset. – Jason Robinson Dec 01 '16 at 22:06
  • I agree with you, it's not the purpose of the cursor position to tell you whether there is a row. That's why I don't follow "If you got a Cursor back from a database with 0 rows, the initial position being at 0 doesn't make sense since there isn't a row at position 0." – LarsH Dec 02 '16 at 01:36
  • You misunderstand. I'm specifically talking about position -1, not all cursor positions. Position -1 and count() are special cases. – Jason Robinson Dec 02 '16 at 18:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/129657/discussion-between-larsh-and-jason-robinson). – LarsH Dec 02 '16 at 20:23
6

So you can do this:

Cursor c = db.rawQuery(...);
while (c.moveToNext()) {
    // deal with one row at a time
}

It's by far the neatest way to iterate over a Cursor's results (see What's the best way to iterate an Android Cursor?), and it wouldn't work if it didn't start before the first row.

Community
  • 1
  • 1
Graham Borland
  • 60,055
  • 21
  • 138
  • 179
  • 1
    Sorry but that is purely incidental. I agree that using `while (c.moveToNext()) {...}` is the neatest way to do things and is the way I always do it but I don't believe that's why a `Cursor` is always positioned before the first row. As Jason says, a `Cursor` may be returned with no results and as such it must be positioned at a 'neutral' position. Further to that, it is not the business of any query engine to assume the developer wants a `Cursor` returned set to any absolute position within the row set (first, last, somewhere in between etc). – Squonk Jul 13 '12 at 23:00
  • 1
    The OP asked about advantages, and I see this as advantage - and therefore a valid answer. – ban-geoengineering Jul 03 '14 at 17:00
0

Android SQLiteCursor is a wrapper object to native SQLite database cursor, which is a control structure that lets you traverse records in a database.
I assume, that before calling setPosition or moveToFirst native cursor even doesn't load query results to memory to save space.

vasart
  • 6,692
  • 38
  • 39
  • So were you suggesting that when you call `moveToFirst()` or `setPosition()`, the cursor goes ahead and loads query results (without waiting for a `getString()` or other direct data access)? – LarsH Dec 01 '16 at 21:52