SQLite Dynamic where-clause for ToggleButtons - android

I would like to create something like a dynamic where clause but struggle with it.
FrameWork:
I want to use 4 Togglebuttons, which obviously return me with "Togglebutton.ischecked()" a true or false boolean. According to that I want to choose the correct courser of my database.
The Togglebuttons have the values "Basic","Common","Uncommon" and "Rare".
If a Togglebuttons is pressed it calls the DB Method which than yields to setting up my layout with the data of the Database.
Issue: I have problems creating a correct Query which changes the whereArguments and whereClause accordingly. From my Understanding the whereClause needs a String and the whereSelection needs a StringArray.
What I tried:
I tried creating a StringArray accordingly, which yields the problem of having a fixed index. Therefore I had issues with creating a smart logic, which yields the correct StringArray,
e.g. if ToggleButton (tb) tbBasic = true, tbUncommon = false, tbCommon = true, tbRare = true, I would need something like String[] whereArgs = new String[] {"Basic","Common","Rare"} whereas I can not create that accordingly with a something like a "add" method.
Therefore I tried using an Arraylist which makes adding and deleting according to the toggles very easy.
E.g. if my DBHelper method getAllHeros is called I can create a new Arraylist each time which yields me the correct whereArgs.
ArrayList<String> whereArgsList = new ArrayList<>();
if(btnBasic){
whereArgsList.add("Basic");
}
if(btnCommon){
whereArgsList.add("Common");
}
if(btnUncommon){
whereArgsList.add("Uncommon");
}
if(btnRare){
whereArgsList.add("Rare");
}
Cursor c = db.query("TableHeros", null,whereClause, whereArgsList.toArray(new String[0]),null,null,null,null);
The Issue with that is that obviously the whereClause has to be updated accordingly aswell. So in a Case of the Arraylist being longer than one Element the whereClause would need the same amount of elements aswell.
I hope I made my point clear and I am open to try any Suggestions

You haven't specified what the WHERE clause should look like. However assuming that:
a) the buttons all apply to a single column (COL_TASK_TITLE (which equates to the String title) is used in the code below) and
b) that should multiple buttons be true that you want to select rows that contain both values and
c) also assuming that if none are selected that you want all rows then the following might be along the lines of what you want
:-
public Cursor getMyRows(boolean btnBasic, boolean btnCommon, boolean btnUncommon, boolean btnRare) {
ArrayList<String> whereArgsList = new ArrayList<>();
String whereclause = null;
String[] whereargs = null;
if(btnBasic){
whereArgsList.add("Basic");
}
if(btnCommon){
whereArgsList.add("Common");
}
if(btnUncommon){
whereArgsList.add("Uncommon");
}
if(btnRare){
whereArgsList.add("Rare");
}
StringBuilder whereclauseToBe = new StringBuilder();
for(String s: whereArgsList) {
if (whereclauseToBe.length() > 1) {
whereclauseToBe.append(" OR ");
}
whereclauseToBe.append(COL_TASK_TITLE); //<<<<<<<<< change to your column
whereclauseToBe.append(" = ? ");
}
if (whereclauseToBe.length() < 1) {
Log.d("WHERE CLAUSE","No selections so WHERE CLAUSE and WHERE ARGS have been set as null");
} else {
whereclause = whereclauseToBe.toString();
Log.d("WHERE CLAUSE ", "The generated WHERE CLAUSE would be... WHERE " + whereclauseToBe.toString());
}
if (whereArgsList.size() > 0) {
whereargs = new String[whereArgsList.size()];
whereargs = whereArgsList.toArray(whereargs);
}
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.query(TABLE, null,whereclause, whereargs ,null,null,null,null); //<<<<<<<<<< Change TABLE to table name
return c; //<<<<<<<<<< Could just do `return db.query(TABLE.........`
}
Note this is a method within a subclass of SQLiteOpenHelper aka the Database Helper.
The above was tested using (from an activity) :-
db.getMyRows(false,false,false,false);
db.getMyRows(true,false,false,false);
db.getMyRows(true,false,true,false);
db.getMyRows(false,true,true,false);
db.getMyRows(false,false,false,true);
db.getMyRows(true,true,true,true);
The results written to the log were :-
10-22 04:44:23.975 1429-1429/? D/WHERE CLAUSE: No selections so WHERE CLAUSE and WHERE ARGS have been set as null
10-22 04:44:23.975 1429-1429/? D/WHERE CLAUSE: The generated WHERE CLAUSE would be... WHERE title = ?
10-22 04:44:23.975 1429-1429/? D/WHERE CLAUSE: The generated WHERE CLAUSE would be... WHERE title = ? OR title = ?
10-22 04:44:23.975 1429-1429/? D/WHERE CLAUSE: The generated WHERE CLAUSE would be... WHERE title = ? OR title = ?
10-22 04:44:23.975 1429-1429/? D/WHERE CLAUSE: The generated WHERE CLAUSE would be... WHERE title = ?
10-22 04:44:23.975 1429-1429/? D/WHERE CLAUSE: The generated WHERE CLAUSE would be... WHERE title = ? OR title = ? OR title = ? OR title = ?
Note TABLE and COL_TASK_TITLE were from a table and would need to be changed.

Related

Android - Cursor not properly working

I have an app that inserts data into a database with 2 tables (project and alvara)
The insertion method for the second table depends on what type the first table gets. (1 or 2) for resumed idea.
This is a method that I made for looking into the second table with cursor. If it finds, it sets in setters from alvara_db class. And later on, I use getters to show info on textviews in another activity. The issue is that it's not setting info at all. Is anything wrong in my Cursor?
Thanks in advance!
public ArrayList<alvara_db> getAlvaras(){
SQLiteDatabase db = this.getReadableDatabase();
ArrayList<alvara_db> projects = new ArrayList<>();
String[] project = new String[]{String.valueOf(tipoprojetoid)};
Cursor cur = db.rawQuery("SELECT placa, proj_exec, resp_tec, rtnum, parecer FROM alvara WHERE projetoid = ?", project);
cur.moveToFirst();
alvara_db alvaras = new alvara_db();
alvaras.setPlaca(cur.getInt(cur.getColumnIndex("placa")));
alvaras.setProj_exec(cur.getInt(cur.getColumnIndex("proj_exec")));
alvaras.setResp_tec(cur.getString(cur.getColumnIndex("resp_tec")));
alvaras.setRtnum(cur.getInt(cur.getColumnIndex("rtnum")));
alvaras.setParecer(cur.getString(cur.getColumnIndex("parecer")));
projects.add(alvaras);
return projects;
}
Fragment where I call getAlvaras method:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detalhes_projeto_alvara);
db.getAlvaras();
placa = alvaras.getPlaca();
resp_tec = alvaras.getResp_tec();
proj_exec = alvaras.getProj_exec();
rtnum = alvaras.getRtnum();
}
You are not using the returned value from db.getAlvaras().
Instead the alvaras variable in your second snippet is something that is likely not initialized - the code you posted does not show that exactly.
(In addition, you might want to check the return value of moveToFirst() in case the query matches no rows, and add a do-while loop to retrieve more than one row.)

ORMLite alias in rawQuery

Is it possible to use an alias (AS) in a query for ORMLite in Android? I am trying to use it with the following code:
String query =
"SELECT *, (duration - elapsed) AS remaining FROM KitchenTimer ORDER BY remaining";
GenericRawResults<KitchenTimer> rawResults =
getHelper().getKitchenTimerDao().queryRaw(
query, getHelper().getKitchenTimerDao().getRawRowMapper());
But when this codes gets executed it gives the following error:
java.lang.IllegalArgumentException: Unknown column name 'remaining' in table kitchentimer
java.lang.IllegalArgumentException: Unknown column name 'remaining' in table kitchentimer
The raw-row-mapper associated with your KitchenTimerDao expects the results to correspond directly with the KitchenTimer entity columns. However, since you are adding your remaining column, it doesn't no where to put that result column, hence the exception. This is a raw-query so you will need to come up with your own results mapper -- you can't use the DAO's. See the docs on raw queries.
For instance, if you want to map the results into your own object Foo then you could do something like:
String query =
"SELECT *, (duration - elapsed) AS remaining FROM KitchenTimer ORDER BY remaining";
GenericRawResults<Foo> rawResults =
orderDao.queryRaw(query, new RawRowMapper<Foo>() {
public Foo mapRow(String[] columnNames, String[] resultColumns) {
// assuming 0th field is the * and 1st field is remaining
return new Foo(resultColumns[0], Integer.parseInt(resultColumns[1]));
}
});
// page through the results
for (Foo foo : rawResults) {
System.out.println("Name " + foo.name + " has " + foo.remaining + " remaining seconds");
}
rawResults.close();
I had the same problem. I wanted to get a list of objects but adding a new attribute with an alias.
To continue using the object mapper from OrmLite I used a RawRowMapper to receive columns and results. But instead of convert all columns manually I read the alias first and remove its reference in the column arrays. Then it is possible to use the OrmLite Dao mapper.
I write it in Kotlin code:
val rawResults = dao.queryRaw<Foo>(sql, RawRowMapper { columnNames, resultColumns ->
// convert array to list
val listNames = columnNames.toMutableList()
val listResults = resultColumns.toMutableList()
// get the index of the column not included in dao
val index = listNames.indexOf(ALIAS)
if (index == -1) {
// There is an error in the request because Alias was not received
return#RawRowMapper Foo()
}
// save the result
val aliasValue = listResults[index]
// remove the name and column
listNames.removeAt(index)
listResults.removeAt(index)
// map row
val foo = dao.rawRowMapper.mapRow(
listNames.toTypedArray(),
listResults.toTypedArray()
) as Foo
// add alias value. In my case I save it in the same object
// but another way is to create outside of mapping a list and
// add this value in the list if you don't want value and object together
foo.aliasValue = aliasValue
// return the generated object
return#RawRowMapper foo
})
It is not the shortest solution but for me it is very important to keep using the same mappers. It avoid errors when an attribute is added to a table and you don't remember to update the mapping.

How to build a Select query (more tables without join) in ORMLite

What is the best way for querying this in ORMLite?
SELECT JOB.TASK_JOB,
JOB.NAME_JOB,
JOB_SETTINGS.DAY1,
JOB_SETTINGS.DAY2,
JOB_SETTINGS.DAY3,
JOB_SETTINGS.DAY4,
JOB_SETTINGS.DAY5,
JOB_SETTINGS.DAY6,
JOB_SETTINGS.DAY7,
JOB_SETTINGS.HOURSPERWEEK,
JOB_SETTINGS.PAYPERHOUR,
JOB_SETTINGS.VARIABLEHOURS,
WORKINGDAY.DATE_WD,
WORKINGDAY.H_BREAK,
WORKINGDAY.H_REAL,
WORKINGDAY.H_IN,
WORKINGDAY.H_OUT
FROM JOB, JOB_SETTINGS,WORKINGDAY
WHERE JOB.ID_JOB = JOB_SETTINGS.ID_JOB
AND JOB_SETTINGS.ID_JOB = WORKINGDAY.ID_JOB
AND JOB.ID_JOB = 2
I have a class for every tables (standard ORMLite) but I don't understand how to build this query...
Thanks!!!
EDIT:
I wrote this code, but actually I can't continue because I'm confused about OrmLite syntax...
DbHelperJob queryDao = new DbHelperJob(getActivity());
QueryBuilder<Job, String> qJob = queryDao.getJobDao().queryBuilder();
qJob.selectColumns("NAME_JOB", "TASK_JOB");
QueryBuilder<JobSettings, String> qJobSett = queryDao.getJobSettDao().queryBuilder();
qJobSett.selectColumns("DAY1", "DAY2", "DAY3", "DAY4", "DAY5", "DAY6", "DAY7", "HOURSPERWEEK", "PAYPERHOUR", "VARIABLEHOURS");
QueryBuilder<WorkingDay, String> qWD = queryDao.getWDDao().queryBuilder();
qWD.selectColumns("DATE_WD", "H_BREAK", "H_REAL", "H_IN", "H_OUT");
You can use queryRaw() method of your Dao. For example
GenericRawResults<String[]> rawResults = queryDao.queryRaw("SELECT JOB.TASK_JOB,
JOB.NAME_JOB,
JOB_SETTINGS.DAY1,
JOB_SETTINGS.DAY2,
JOB_SETTINGS.DAY3,
JOB_SETTINGS.DAY4,
JOB_SETTINGS.DAY5,
JOB_SETTINGS.DAY6,
JOB_SETTINGS.DAY7,
JOB_SETTINGS.HOURSPERWEEK,
JOB_SETTINGS.PAYPERHOUR,
JOB_SETTINGS.VARIABLEHOURS,
WORKINGDAY.DATE_WD,
WORKINGDAY.H_BREAK,
WORKINGDAY.H_REAL,
WORKINGDAY.H_IN,
WORKINGDAY.H_OUT
FROM JOB, JOB_SETTINGS,WORKINGDAY
WHERE JOB.ID_JOB = JOB_SETTINGS.ID_JOB
AND JOB_SETTINGS.ID_JOB = WORKINGDAY.ID_JOB
AND JOB.ID_JOB = 2")
read more here enter link description here
This has nothing to do with ORMLite, but there's a really handy tool for doing query, right in SQLiteQueryBuilder. You can do this:
private static final String COLS = new String[] {
JOB.TASK_JOB,
JOB.NAME_JOB,
JOB_SETTINGS.DAY1,
JOB_SETTINGS.DAY2,
JOB_SETTINGS.DAY3,
JOB_SETTINGS.DAY4,
JOB_SETTINGS.DAY5,
JOB_SETTINGS.DAY6,
JOB_SETTINGS.DAY7,
JOB_SETTINGS.HOURSPERWEEK,
JOB_SETTINGS.PAYPERHOUR,
JOB_SETTINGS.VARIABLEHOURS,
WORKINGDAY.DATE_WD,
WORKINGDAY.H_BREAK,
WORKINGDAY.H_REAL,
WORKINGDAY.H_IN,
WORKINGDAY.H_OUT
}
private static String SEL =
"JOB.ID_JOB = JOB_SETTINGS.ID_JOB"
+ "AND JOB_SETTINGS.ID_JOB = WORKINGDAY.ID_JOB"
+ "AND JOB.ID_JOB = 2"
private static String TABLES = "JOB, JOB_SETTINGS, WORKINGDAY""
// in the query method...
db.execSQL(
SQLiteQueryBuilder.buildQueryString(
false, TABLES, COLS, SEL, null, null, null, null);
Android query have parameters:
columns - list of fields that we want to get
selection - string WHERE condition
selectionArgs - an array of arguments for
selection. In the selection, you can use the "?" And will be replaced by these values.
groupBy - grouping
having - the conditions for the use of aggregate functions
orderBy - sorting
Use it.

Recursive query with ordered values in SQLite Android

I have one group table with a recursive relation, so each record has a parent_id. Given a group, I need to get all the student (each belong to a group) names in all its subgroups, but ordered by student name.
Do you know if there is any "easy" way to do it? If I have to do multiple queries, then I should order the results of the different Cursors, but Cursor has no orderBy().
Any ideas? Thank you so much!
As SQLite does not support recursive queries I implemented the select with two steps:
First, I have a method called getRecursiveDiningGroupIdsAsString() that retreives all the group ids recursively whose parent id is the one you pass by parameter. The result is a String in the form of: "(2, 3, 4)" so you can later use it in an IN clause. The method looks like:
public String getRecursiveDiningGroupIdsAsString(int depth, long diningGroupId) {
Cursor childDiningGroups = mDatabase.query(
"group",
new String[] {"_id"},
"parent_id = "+diningGroupId,
null, null, null, null
);
String recursiveDiningGroupIds = "";
while (childDiningGroups.moveToNext()) {
long childDiningGroupId = childDiningGroups.getLong(childDiningGroups.getColumnIndex("_id"));
recursiveDiningGroupIds += getRecursiveDiningGroupIdsAsString(depth+1, childDiningGroupId);
}
recursiveDiningGroupIds += diningGroupId;
if (depth > 0) {
recursiveDiningGroupIds += ", ";
} else {
recursiveDiningGroupIds = "("+recursiveDiningGroupIds+")";
}
return recursiveDiningGroupIds;
}
Once I have the group ids I need, I just do a simple query using the ids returned by the previous method and that is it!
Hope it helps!

assign database value for variable in android

This is about Android and SQLite database.
Simply, I want to know, how can I assign value to variable that get from the Database table?
I have table called wish and colmns are date[date value string], phoneno[phone no string] and wishtype[simply a string].
All I want is get phoneno, and wishtype according to usergiven date[input to the query will be the date] and assign those two into seperate variable.
I tried out so many methods, but it gives me a runtime errors.
String phone_no;
String wish_type;
Cursor c = getContentResolver().query(your_table_uri,
new String[] {"_id", "phone_no", "wish_type", "date" /*these are your column names*/},
"date=?", your_date_filter, null);
if(c.moveToFirst()) { // checks if c retrieves anything. you may want to check first if c!=null
phone_no = c.getString(c.getColumnIndex("phone_no"));
wish_type = c.getString(c.getColumnIndex("wish_type"));
}

Categories

Resources