Where in clause in Flutter sqflite - flutter

I'm trying to use where in clasue but i get this error:
Invalid argument [1, 2, 3] with type List Only num, String and
Uint8List are supported.
My code:
Database db = await instance.database;
List<Map> maps = await db.query('table',
where: 'categoryID in (?)', whereArgs: [ [1,2,3]]);
From this document
Particulary, lists (expect for blob content) are not supported. A
common mistake is to expect to use IN (?) and give a list of values.
This does not work. Instead you should list each argument one by one:
var list = await db.rawQuery('SELECT * FROM my_table WHERE name IN (?, ?, ?)', ['cat', 'dog', 'fish']);
But my categories can change any moment so I cant list each argument one by one.

While I understand that it could sound painful, that is unfortunately the way SQLite works and sqflite does not do any SQL parsing.
You could try the following solution that I personnaly use to build the proper number of ?.
List.filled(inArgsCount, '?').join(',')
For example:
var inArgs = ['cat', 'dog', 'fish'];
var list = await db.query('my_table',
where: 'name IN (${List.filled(inArgs.length, '?').join(',')})',
whereArgs: inArgs);

Related

How to combine 2 or more Sqflite queries with logical operators?

Im currently trying to combine the results of 2 queries in flutter. These are the queries:
Future<List> filterExercises({
List<String> equipmentFilter,
List<String> muscleFilter,
int custom, //0 = false, 1 = true
int recent, //0 = false, 1 = true
String orderBy,
}) async {
Database db = await initDatabase();
final muscleRes = await db.query(
'exercises',
where: "targetMuscle IN (${('?' * (muscleFilter.length)).split('').join(', ')})",
whereArgs: muscleFilter,
);
final equipmentRes = await db.query(
'exercises',
where: "equipment IN (${('?' * (equipmentFilter.length)).split('').join(', ')})",
whereArgs: equipmentFilter,
);
return finalResult; //need to combine the results with a logical AND somehow
}
I know there's the option the use a rawQuery with logical OR / AND, but that doesn't work for my case.
It should be possible for the user to select different attributes and thus filter the list. Im looking for a way to pass arguments to this function and query my table accordingly to the passed arguments but I already fail when merging the first two queries.
How to add a logical AND to these two queries?
And furthermore: How to add even more attributes with a logical AND and order the final result?
I managed to find a way to the first question:
List<String> muscleFilter = ['Chest', 'Biceps'];
List<String> equipmentFilter = ['Machine', 'Cable'];
return db.rawQuery('''
select * from exercises
where targetMuscle in (${('?' * (muscleFilter.length)).split('').join(', ')})
and equipment in (${('?' * (equipmentFilter.length)).split('').join(', ')})
''',
muscleFilter + equipmentFilter
);

Dart remove square brackets and add single quotation mark

I have a list of strings pulled from database as a string
[name 1, name2, name3, ...]
i am trying to convert it to this:
'name 1', 'name2', 'name3', '...'
so far no success.
method with which i am getting data. The method is just fine since I am using it beforehand for other part of code.
Future<List<String>> getNames() async {
var url = _api + "get_names.php?key=" + _key;
http.Response response = await http.get(url);
var resp = jsonDecode(response.body);
return resp.map<String>((m) => m['names'] as String).toList();
}
list is pulled from database as a String.
Basicaly I am using a part of formbuilder code which uses initialValue as dynamic.
so if I set initialValue: [widget.names] and the widget.names contains 'name1','name2' it is ok
if it is a list of string but It needs to be ofcourse single or double quoted and seperated with comma.
Thank you
void main() {
final input = '[name 1, name2, name3, ...]';
final removedBrackets = input.substring(1, input.length - 1);
final parts = removedBrackets.split(', ');
var joined = parts.map((part) => "'$part'").join(', ');
print(joined);
}
Using: https://api.flutter.dev/flutter/dart-core/String/split.html
Prints:
'name 1', 'name2', 'name3', '...'
That said... maybe you should find a better way to get your data. Maybe as Json or something, so you don't have to reinvent serialization. What happens for example if "name 1" has a comma in it? Or let's say it's d'Artagnan?

Query a specific cell of sqflite data table in Flutter

There are already some questions and answers like "query a specific row". But I want a specific cell that means I need a specific row with a specific column from the sqflite data table in Flutter. My table has three columns which are id, fname, fid. But I need only fid. Here is my row selection code:
queryfid() async {
Database db = await DatabaseHelper.instance.database;
List<String> columnsToSelect = [
DatabaseHelper.columnId,
DatabaseHelper.columnfname,
DatabaseHelper.columnfid,
];
String whereString = '${DatabaseHelper.columnId} = ?';
int rowId = 1;
List<dynamic> whereArguments = [rowId];
List<Map> result = await db.query(DatabaseHelper.tableid,
columns: columnsToSelect,
where: whereString,
whereArgs: whereArguments);
result.forEach((row) => print(row));
}

Check which PKs in List of PKs is present within SQFLITE database

For a list of PKs of length k:
listPK = [1,2,3...k]
I'm currently running a for loop, and querying the database k times to check whether the item is present within the database or not.
List<bool> isPresent(List listPK)async{
final db = await database;
List<bool> output = List.filled(listPK.length, false)
for (var i = 0; i<listPk.length; i++){
List<Map> result = await db.query('elements', where: "id = ?", whereArgs: listPk[i]);
if (result[0] != null) {output[i] = true}
}
}
Was wondering if there was a more efficient way to do this. I only want to know if the id is present within the database or not.
Use a WHERE ... IN to check against all the IDs in one call.
String listQuery = listPK.join(', '); // "1, 2, 3, ..., k"
String query = 'SELECT * FROM table_name WHERE id IN ($listQuery);`;
List<Map> result = await db.rawQuery(query);
It would be more efficient to query the database once and get all the id's in the 'elements' table. Once you have all the id's in the 'elements' table you can iterate through and find which id's are present and which are not.

Multiple arguments in sqllite in flutter

I would like to know how to pass multiple arguments to a raw query in sqllite.
My code is below
query() async {
// get a reference to the database
Database db = await DatabaseHelper.instance.database;
// raw query
List<Map> result = await db.rawQuery('SELECT * FROM my_table WHERE name=?', ['Peter']);
// print the results
result.forEach((row) => print(row));
}
In the above code i am passing one argument 'Peter' but what if I want to pass multiple arguments, for example:
List<Map> result = await db.rawQuery('SELECT * FROM my_table WHERE name=? and last_name=? and year=?', ['Peter'], ['Smith'],[2019]);
If I do the code above, I get error "Too many positional arguments: 2 expected, but 4 found." can someone show me how to pass multiple arguments to a query in sqllite flutter?
I'm assuming you're using sqflite.
You need to put all your arguments into one list and not multiple.
The code below should work like this:
List<Map> result = await db.rawQuery(
'SELECT * FROM my_table WHERE name=? and last_name=? and year=?',
['Peter', 'Smith', 2019]
);
For more examples how to use raw queries see their examples on their pub.dev page.
Or if you want to use the query function you can do it like this:
String strVal = 'str';
int intVal = 0;
String likeVal = 'str';
final List<Map<String, dynamic>> maps = await db.query('my_table',
where: "col1 LIKE ? and col2 = ? and col3 = ?",
whereArgs: ['$likeVal%', strVal, intVal],
orderBy: 'id',
limit: 10);