Is it possible to compare two cursors? - android

I need to check if two cursors pointing at the same rows with the same values. Is it possible?
More details:
I'm loading data from my own ContentProvider
I'm sending request to server and then updating my data inside ContentProvider with new values.
If values is changed - I need to notify user that he can update data.

As per CommonsWare's deleted answer:
Iterate over the relevant columns in the Cursor, retrieve the values, and compare each.
Although you may not know in advance the type of each column, you can find out with Cursor.getType(). You can also use Cursor.getColumnNames() to get the name of each column, and the number of columns.
This information will allow you to then use the correct accessor method to obtain each value and compare.

In SQLite, rows do not have an identity separate from their column values (but the ROWID is one of these values).
What you want requires that your data has some unique column(s) as part of the cursor, either the ROWID, or some other key value that is guaranteed to have no duplicates.
Otherwise, you can never know if what you see is just two records that happen to have the same values in those columns.

Related

ContentProvider/ContentResolver Query Sorting by ID by default

I am working on an application that stores everything in a database and it is accessed using a ContentProvider. My scenario is as follows:
I make a web call and receive a list of integers which represent the ids of the objects I need to retrieve from my database on the device.
I make a call to ContentResolver.query() with the following Selection:
Selection: _id=? OR _id=? OR _id=?
Selection Ids: 30; 165; 149;
So, I need to get all items where the id is either 30, 165, or 149. And I need them in that exact order.
This is the exact call I am making on the ContentResolver:
Cursor cursor = mActivity.getContentResolver().query(myUri, null, selection, selectionIds, null);
As you can see, I do not pass in any sorting. However, the result gives me a Cursor with the order being the following: 30, 149, 165. So, it appears it is defaulting the sorting by _id even though I do not specify any sort order. My question is, does anyone know of a way to stop this from happening?
When you select rows, from any database, without specifying an ORDER BY clause, you should consider the order of the results as undefined, i.e. it could come back in any order. The reason you are seeing it sorted by _id here is just due to circumstance - they are likely to be in that order on the underlying database files so that is the order SQLite reads them back in. However it is not safe to assume that will always be so.
So the actual answer to your question is no, you can't assume SQLite will return your rows in any particular order without an ORDER BY clause. If you are unable to provide such a clause (which appears to be the case here) you'll have to sort them in code after getting all the data from the cursor.
It is not defaulting to _id, it is giving you the records as they are in the db (which happen to be sorted by id). Pass your own sorting order if you don't want this.

Column index order SQLite creates table

This is the query that I use to create a table
create table site_table(
_id integer primary key autoincrement,
name_site text,
url text,
login text,
pass text
);
I called Cursor.getColumnNames() and noticed that columns order are id, login, pass, name, url.
So, if I want a value I have to get it by the index Cursor.getString(index). Until I debugged I was messing up calling the wrong index, but now I wonder, why SQLite saves that way? Why it does not follow that way I created id, name_site, url, login and pass?
Thanks
So, if I want a value I have to get it by the index
Cursor.getString(index)
So for example for this reason you should always use
c.getString(c.getColumnIndex("ColName")); // or better getColumnIndex(CONSTANT)
This method saves all of us and ensure that you never get wrong results. Generally this method is recommended and also storing COLUMN_NAMES as CONSTANTS in separated class is very, very useful and efficient practise.
Note: Order depends on projection i.e. select name, lastname from table
That data is ordered by the order your requested it in your query, not the order you created the table with. So you probably changed the order in your query that generated said cursor.
Columns order in your cursor depends on projection. To be sure you use correct column index use c.getString(c.getColumnIndexOrThrow("COLUMN_NAME")) where c is your cursor.
I just made the experience first hand:
The indices of the columns of the cursor as a result of a
SELECT * FROM mytable WHERE ...
query have sometimes (not always) a different order that what SQLITE Database Browser shows as column order in the Database Structure tab. So referencing the columns via getColumnIndex seems to be the only safe way.

sql order by clause

Ok so in my database I have,
1,2,3,4
But what I really want is,
2,1,4,3.
so how do I order a column against a predefined set of sequence of strings or values?
Create a order by column, and order the results based on that.

Android: column '_id' does not exist

I am getting this error
IllegalArgumentException: column '_id' does not exist
When using a SimpleCursorAdapter to retrieve from my database, and the table does indeed have this _id column. Noticing this a common problem, I have tried to work around it given some of the solutions online but none of them work. This is my cursor query:
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this, R.layout.quoterow, myCursor, new String[]{"_id", "quote"}, new int[]{R.id.quote});
although I should mention the original did not include the _id column, I added this recently to try and solve the problem. Has anyone got any ideas that might help solve the problem?
Your database doesn't have to have a column called '_id' but the SimpleCursorAdaptor does need to have one returned. You can do this with an alias.
An example is that I have a table with columns...
uid,name,number
To query this for a SimpleCursorAdapter, I do this with a database rawQuery...
SELECT uid as _id,name,number FROM MY_TABLE
This works fine and supplies the necessary '_id' column to SimpleCursorAdapter.
EDIT: As far as I understand it the _id field is used as a unique key to make sure the data the cursor handles can be handled correctly by adapters and adapterviews etc.
Look at the data model in the docs for Content Providers.
Using a unique key in 'databases' of whatever kind is pretty much universal practice, and as far as I can tell, the use of the column name '_id' (or '_ID') is simply a way of standardizing and simplifying things across databases, content providers, cursors, adapters etc etc
In short, in order for these various components to work correctly, they need a data column with unique values but they must also 'know' what the name of that column is. They wouldn't 'know', so to speak, that my column name 'uid' is the one they need as opposed to my 'name' and 'number' columns.
You either don't have a column "_id" in your table or you are not including it in your query. That is what is causing the exception. You need to fix the following as well:
Your last argument for the CursorAdapter constructor is missing the to column reference for _id.
The int[] argument is an array of view ids to populate with values from the cursor. The String[] argument is an array of column names from a row the cursor points to.
You have to have an equal number of values in the from array as you do the to array. Because the data from the Cursor is being grabbed FROM the Cursor and placed TO the views. If there are not an equal number of values in each array, the adapter throws an exception because it doesn't have the right amount of information to map the data to the views.
Also, according to the JavaDoc for SimpleCursorAdapter, that constructor is deprecated because it causes queries to be executed in the UI thread. Which is bad. Use this one instead:
http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html#SimpleCursorAdapter%28android.content.Context,%20int,%20android.database.Cursor,%20java.lang.String[],%20int[],%20int%29
A simple fix would be to add ",0" to the end of the argument list.
If you are trying to use an existing sqlite database in your Android application then you need to do some prep work to get it to work properly. This blog post describes the process in detail.
http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/

Content Provider filtering query, filtering Cursor

I got following problem, I need to use a Content Provider to read a
Database of an other App.
first I want all rows, and after analyzing the data only e.g. the rows
from _id = 1, 3 and 5.
how can I call a Content provider and select only these rows?
or is it possible to create a subset Cursor form an given Cursor?
Thanks in advance.
If you're talking to another app, I assume you're querying the other app's ContentProvider to get the data from them in the first place.
In this situation, the cleanest answer seems not to build your own ContentProvider that filters/wraps theirs. Instead query their ContentProvider from your application directly, and use the select clause in your query() to specify the conditions that define the subset of data you want to be given.

Categories

Resources