Android use OrderBy in ORMLite - android

i'm trying to use chaining orderBy for this code:
List messages = G.messagesListsDao.queryBuilder().where().eq("group_id", group_id).query();
i can not find good document for how to use orderBy() chain for this code befor using .query() for example this code:
GenericRawResults<String[]> raw_result =G.messagesListsDao.queryRaw("SELECT * FROM messageslist WHERE group_id = " + group_id + " ORDER BY received_date");
to:
List messages = G.messagesListsDao.queryBuilder().where().eq("group_id", group_id).orderby("id",false).query();

You can call orderBy() more than once, like this:
List messages = G.messagesListsDao.queryBuilder().where().eq("group_id", group_id).orderBy("id",false).orderBy("received_date",false).query();
This is covered by the documentation. To quote:
Add "ORDER BY" clause to the SQL query statement to order the results
by the specified column name. Use the ascending boolean to get a
ascending or descending order. This can be called multiple times to
group by multiple columns.
Hope it works !

Related

Android Room inner join returns columns which are not used

I have a table for orders and customers. Customers contains an order ID and email. I wish to search for orders by customer email.
This is what I have come up with:
#RewriteQueriesToDropUnusedColumns
#Query(
"SELECT * FROM orders INNER JOIN order_customers ON order_customers.order_id = orders.id " +
"WHERE (order_customers.email LIKE '%' || :email || '%') ORDER BY orders.collection_time DESC"
)
protected abstract fun loadByEmail(email: String): LiveData<List<Order>>
I get a cursor mismatch warning "the query returns some columns which are not used" that I am loading all of the customer columns, when really all I want is orders. Adding the suggested #RewriteQueriesToDropUnusedColumns does not do anything. So what is the best syntax here? Should I just be embedding customers into the order DAO, or is there a simple solution without remodeling and migrating the data?
I can see that instead of saying SELECT * I can individually specify every order column but that is supposed to be the whole reason for Room...
You can use SELECT orders.* FROM orders INNER JOIN ....
Adding the suggested #RewriteQueriesToDropUnusedColumns does not do anything.
This could be because of the caveat:-
Note that Room will not rewrite the query if it has multiple columns that have the same name as it does not yet have a way to distinguish which one is necessary.
I'd suggest always using unique column names, doing so can avoid issues with ambiguities
Note that it appears that when there are duplicate column names, then the value of last column with the duplicated name is used by room. As can be seen in this example

Sort in GreenDAO

Raw query:
SELECT * FROM SAVED_JOB2 S, JOB J WHERE J._id=S._id ORDER BY DATE_SAVED DESC
How can I achieve sort for column in JOIN table. I have tried:
QueryBuilder<Job> queryBuilder = daoSession.queryBuilder(Job.class);
queryBuilder.join(JobDao.Properties.Id, SavedJob2.class, SavedJob2Dao.Properties.Id);
List<Job> list = queryBuilder1.list();
This normal JOIN works perfect. But I need to sort for date_saved column in table SavedJob.
I tried to add this line:
queryBuilder.orderDesc(SavedJob2Dao.Properties.date_saved);
But this line returns this error:
Property 'date_saved' is not part of com.xxx.xxx.db.JobDao
Table JobDao:
id (PK)
title
description
requirements
allowance
type
status
Table SavedJobDao:
id (PK autoincrement)
j_id (FK to JabDao)
date_saved
status
You don't need to do any JOIN with greenDao. It works with objects, so in your savedJob you should have an object Job instead job_id.
So you can order by date_saved, but searching in savedJob only, you don't need either JOIN.
There are a lot of examples. And the official doc is awesome!.

ORMLite search for rows with most common column

I'm using ORMLite for working with local database and have an issue with one custom query.
I need to get one row which's some column's value is most common in table.
E.g. I have a column text and I have 3 rows with value text0, 4 rows with value text1 and 5 rows with value text2. I need to get one of the rows which have value text2 of text column.
Can I do this with ORMLite's query builder or I should run a raw query?
This is raw sql query which works fine and returns array of strings.
Dao<Case, Long> caseDao = getHelper().getCaseDao();
GenericRawResults<String[]> cases = caseDao.queryRaw("SELECT * ," +
" COUNT('name') AS 'name_occurrence'" +
" FROM 'MEDICAL_CASE'" +
" GROUP BY 'name'" +
" ORDER BY 'name_occurrence' DESC" +
" LIMIT 1", new String[]{});
After getting strings I have to create an instance of my model, set values and do my jon with that object.
But it's a bit ugly that's why I'm asking if it's possible with methods of ormlite.
Can I do this with ORMLite's query builder or I should run a raw query?
Any results that aren't an entity need to be done through ORMLite's dao.queryRaw(...) methods. If you can do it with SQL then you can do it through those methods.
See: http://ormlite.com/docs/raw-queries
You can't use the standard entity mapper because you are doing a SELECT *, COUNT('name'). ORMLite wouldn't know what to do with the COUNT(...) field.

android update database column based on the current column value

In android, SQLiteDatabase has a update function
update(String table, ContentValues values, String whereClause, String[] whereArgs)
new values in put in values
If I want to update a column A by adding one to it, how should I prepare the ContentValues values variable? I don't think the following would work.
cv.put("A", "A" + 1);
I can sure run execSQL with raw sql, but it does not return num of row updated
If you'd execute a raw query, something like this should work to increment the current value in the column:
UPDATE table_name SET column_a = column_a + 1 WHERE _id = 1
(where 1 is just an example to illustrate how to apply it to a specific row)
The same probably wouldn't work with ContentValues, since (as the name indicates) it takes the values to set the column to. That means it needs to have been evaluated before building the ContentValues, whereas with a raw query the value isn't evaluated until the query actually runs on the database.
You can of course retrieve the current value first and then increment that accordingly when issuing an update; that requires a select query first. Quite commonly though, you're working with objects in Java, where the column value for a row is bound up to a member field of the object. If you've got a setup like that, then you probably already have the current value at the moment you want to run an update query.
As such, it would just look somewhat like:
SomeObject object = ...;
cv.put("column_a", object.getSomeValue() + 1);
(where I'm assuming object.getSomeValue() will return an int)
// edit: here's some more examples for the raw query approach:
SQLite - increase value by a certain number
// edit2: You've edited your original question and added:
I can sure run execSQL with raw sql, but it does not return num of
row updated
If knowing how many rows the query changed is a must, then you can potentially leverage the changes() function. It still means you're going to have to run a second query though.
SELECT changes() FROM table_name
The docs say:
The changes() function returns the number of database rows that were
changed or inserted or deleted by the most recently completed INSERT,
DELETE, or UPDATE statement, exclusive of statements in lower-level
triggers. The changes() SQL function is a wrapper around the
sqlite3_changes() C/C++ function and hence follows the same rules for
counting changes.
Alternatively, you could look into the rawQuery() method that takes an SQL statement and returns the result as a Cursor. Not sure if it that even works for an update query, or whether the result would be anything sensible, but if you're really lucky, you may find that Cursor.getCount() gives you the number of affected rows.
To expand upon #MH's solution, there actually is a way to do a raw update AND get back the number of rows updated (because I'm doing the same thing in one of my projects). You have to use a compiled SQLiteStatement and then call the method executeUpdateDelete(). From the documentation:
public int executeUpdateDelete ()
Execute this SQL statement, if the the number of rows affected by execution of this SQL statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements.
Returns
the number of rows affected by this SQL statement execution.
See the following sample code where I add a new column to my table and then update each column similarly to how you were asking:
db.beginTransaction();
try {
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN "
+ COLUMN_NAME_LOCALTIME + " INTEGER");
String stmtString = "UPDATE " + TABLE_NAME + " SET "
+ COLUMN_NAME_LOCALTIME + "="
+ COLUMN_NAME_TIME + "+ (" + tzOffset + ")";
SQLiteStatement sqlStmt = db.compileStatement(stmtString);
int rows = sqlStmt.executeUpdateDelete();
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
I'm using a transaction here because in case I add the new column but CANNOT update the values, I want everything to rollback so I can attempt something else.

ORMLITE ORDER_BY with multiple columns

I am using ormlite in my recent android project. I want to order by on a query on multiple columns in a table (say two columns). How can I achieve that??
Here is the code for a single order by...
QueryBuilder<Visit, Integer> qb = getHelper().getVisitDao().queryBuilder();
qb.where().eq("FOREIGN_ID", id);
qb.orderBy("VISIT_DATE", false);
I want to order by on a query on multiple columns in a table(say two columns). How can i achieve that??
All you need to do is to call orderBy(...) multiple times.
qb.orderBy("VISIT_DATE", false);
qb.orderBy("order-column", false);
...
This is covered by the documentation. To quote:
Add "ORDER BY" clause to the SQL query statement to order the results by the specified column name. Use the ascending boolean to get a ascending or descending order. This can be called multiple times to group by multiple columns.
Also the javadocs:
Add "ORDER BY" clause to the SQL query statement. This can be called multiple times to add additional "ORDER BY" clauses. Ones earlier are applied first.

Categories

Resources