I'm trying to fix a DB issue I had in Ankidroid. The following statement was executed:
SELECT count(*) FROM cards c WHERE type = 1 AND combinedDue <
1335153600.000000
It was generated there. The code executed is the following (github link):
cursor = mDatabase.rawQuery(query, null);
if (!cursor.moveToNext()) {
throw new SQLException("No result for query: " + query);
}
I can't understand how I can get no record, I should get either 1 or 0. The call stack in the log was the following:
at com.ichi2.anki.Deck.rebuildRevCount(Deck.java:1351)
Caused by: android.database.SQLException: No result for query: ……
at com.ichi2.anki.AnkiDb.queryScalar(AnkiDb.java:129)
at com.ichi2.anki.Deck._rebuildRevCount(Deck.java:1621)
Any idea?
In fact, I was more looking at a similar case. We have a table «Stats» with a column "global", in which there can be one global record and many daily records. If we don't find (a simple select) the global record, we create it. On my phone, it seems that sometime the global record is not found, so we create an additional one, which break things.
It really look like the case I showed above.
Edit:
I found why. In another thread, an AsyncTask closes the DB at the same time the query is being made (because a lot of processing triggered by the GUI is done asynchronously). And it returns a cursor with no record.
I saw that by adding traces to a file.
Try if (cursor.moveToFirst == false) instead of using the ! operator. I think that the way you are currently doing it is always going to.pass you into the body of the if. And the cursor isn' t properly initialized.without a.moveToFirst.
Related
I am building an Android app that uses a SQLite database.
For this one task I have to run a query that looks like this:
SELECT item.id, item.price, t1.quantity
FROM item, (SELECT id, price
FROM list
WHERE list.state = 'sold') t1
WHERE item.id = t1.id
So far, I have tried:
Cursor c = resolver.query(uriRawQuery, null, selection, null, null)
where uriRawQuery is used to tell the ContentProvider that it should perform a db.rawQuery(selection, null) and selection is a string similar to the query above.
The problem is no data is returned into the Cursor. When I call c.moveToFirst() I get false.
The weird thing is that if I open the database file in SQLite Manager and run the exact same query I get results.
I know I can modify the query to make a join between the original list and item tables but I find it to be less efficient that way.
Any ideas would be very appreciated as I have spent too man hours on this already.
EDIT
I know what a join is, what I said is that it is a lot more efficient if I do it like this instead of using the entire list table.
I forgot a very important aspect
The WHERE clause looks like
" WHERE list.state = 'sold' and list.name like '" + arg + "%'"
where arg is a string.
I managed to solve the problem, I still don't know why this was happening but at least I got the Cursor to actually select the rows.
After many trials I thought about ditching the syntax above and write this instead:
" WHERE list.state = 'sold' and list.name like ? "
and move the argument in
selectionArgs = new String[]{arg + "%"}
I am going to wait a while before accepting the answer, in case someone provides an explanation as to why even though both queries look exactly the same they get different results.
I have very strange problem.
After a lot of debugging I come to following line of code:
db.db.rawQuery("INSERT INTO goal_calendar(timestamp) VALUES(1)", null);
db.cursor = db.db.rawQuery("SELECT * FROM goal_calendar", null);
Log.e("SIZE", String.valueOf(db.cursor.getCount()));
The result is "Size 0".
There is no any errors at all. Everything worked just fine and suddenly it didn't want to store nothing in my table. It just stopped. What could be wrong?
According to me the result after these three lines of code SHOULD ALWAYS be error(exception) or SIZE should be greater than 0.
Because this
"INSERT INTO goal_calendar(timestamp) VALUES(1)"
is not a QUERY (SELECT),but a COMMAND.
For commands (INSERT, UPDATE, DELETE, ...), use this:
db.execSQL("INSERT INTO goal_calendar (timestamp) VALUES (1)", null);
I also have some doubts on why do you double "db."
I'd use "db.rawQuery" and "db.execSQL", instead of "db.db.rawQuery" and "db.db.execSQL".
Now two words of explanation:
Your INSERT statement doesn't work. That's why your query correctly returns a zero count.
I have to query three table, and display the data to my customerView.
My code is like this:
Log.v(TAG, System.CurrentTimeMillis())
int len = cursor.getCount();
Log.v(TAG, System.CurrentTimeMillis())
Product[] products = new Product[len];
int i = 0;
while(cursor.moveToNext()){
products[i] = new Product(cursor.getstring(0),.....);
}
Log.v(TAG, System.CurrentTimeMillis())
Sqlite query:
String sql = "SELECT T1.PRODUCT_ID, CODE, SHORT_DESCRIPTION, CATEGORY_CODE,
BRAND_CODE, FORM_CODE, DENOMINATOR, T1.PIECE_PRICE, T1.lowest_piece_price,
T2.sku_type, T1.master_sku " +
"FROM CUSTOMER_PROD_LIST_ITEMS T1 INNER JOIN PRODUCT T2 ON
T1.PRODUCT_ID = T2.ID INNER JOIN PRODUCT_UOMS ON T2.ID =
PRODUCT_UOMS.PRODUCT_ID"+
"WHERE T1.VALID = 1 AND PRODUCT_UOMS.VALID = 1 AND
CUSTOMER_PRODUCT_LIST_ID = " + customer_pdtlist_ID + "
ORDER BY T1.PRODUCT_ID ASC";
After my testing, if we have 1500rows in the cursor, we have to spend more than 30s to finish this line(cursor.getcount()) . If I delete this line, and use ArrayList to take place. i can find that we should spend more than 30s for Cursor.moveToNext().
So my question is why the first time cursor operation should take such long time? and how do we solve?
And this man have the same question Poor SQLite implementation? First time data access way too slow. but the answer is not working for me.
by the way, I find display same 1500rows in Iphone, just need amost 3s.
thanks in advance!!
This is an answer to why the first operation on your cursor is so slow. When a Cursor is backed by SQLite, Android uses the sqlite C library internally and creating a Cursor is analogous to creating a prepared statement in the C library. Creating a prepared statement is cheap and it does not perform any query. Taken from the C library's documentation:
sqlite3_prepare()
This routine converts SQL text into a prepared statement object and returns a pointer to that object. This interface requires a database connection pointer created by a prior call to sqlite3_open() and a text string containing the SQL statement to be prepared. This API does not actually evaluate the SQL statement. It merely prepares the SQL statement for evaluation.
When you call moveToNext() on the Cursor, that's when the query actually gets executed. moveToNext results in a call to the sqlite3_step() function in the C library. Again, taken from the documentation:
sqlite3_step()
This routine is used to evaluate a prepared statement that has been previously created by the sqlite3_prepare() interface. The statement is evaluated up to the point where the first row of results are available. To advance to the second row of results, invoke sqlite3_step() again. Continue invoking sqlite3_step() until the statement is complete. Statements that do not return results (ex: INSERT, UPDATE, or DELETE statements) run to completion on a single call to sqlite3_step().
So creating a Cursor is done lazily and the query is only evaluated when the cursor is first moved.
To find out why the query is taking such a long time, use EXPLAIN QUERY PLAN on your query and see where the bottleneck lies. Usually it's the lack of an appropriate index.
ok, guys, i have not been here for acouple days.And i found the solution that is you have to create index for your table which will improve the query speed. thanks all the same
I created a table in the database that has the data like this:
Now i have written a query that updates the contact field by concatinating name and email fields:
UPDATE MyContacts SET contact=(SELECT name||'--'||email FROM MyContacts);
Here the problem is after executing the query the table is as below:
Why is it happening like this? In oracle i never faced this problem. Please help me. Thank you
Right now you're not specifying the correct row to retrieve the values from. Try something like this:
UPDATE MyContacts SET contact = name||'--'||email;
EDIT: Glad it worked. Your first issue was that your sub-select uses a SELECT statement with no WHERE clause (SELECT name||'--'||email FROM MyContacts will return 3 rows). One possible solution would be for SQLite to throw an error and say You've tried to set a column to the result of an expression that returns more than 1 row: I've seen this with MySQL and SQL Server. However, in this case SQLite appears to just use only the very first value returned. However, your second error then kicks in: since you don't narrow your UPDATE statement with a WHERE clause, it uses that first value returned to update EVERY single row, which is what you see.
I verified using SQLite Database Browser that the table contains no rows. I stepped through the query builder code to get the generated query and ran the query in SQLite Database Broswer. The query returned zero rows. But still, the cursor returned by Android's SQLiteQueryBuilder.query method returns true on cursor.moveToFirst() call and returns null values.
Anyone seen something like this before?
OK: I figured this is because I'm using a MAX aggregation function in the query. This could be a bug, may be? I now use a sort with a limit clause instead of MAX and worked around.
I think you should do something like:
if (c.getCount()>0) {
c.moveToFirst();
moveToFirst is actually implemented as moveToPosition(0). moveToPosition is a final method defined in AbstractCursor. Looking at the code, you can see that the result is partially depentandt on getCount. and it seems that in your case getCount returns a non-zero value.
See what's the value of the '_id' column, and try to delete it. Alternatively, try to call that code after re-creating the database (calling 'drop table' and then 'create table').