Closed KsaRedFx closed 5 years ago
Forcing data into it afterwords does successfully trigger an update, and make it start to build the view... However the view just returns null.
body: StreamBuilder<List<Map>>(
stream: bloc.items,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
// the select query has not found anything
if (snapshot.data.length == 0) {
return Center(
child: Text(
"No data. Use the + in the appbar to insert an item"),
);
}
var sData = snapshot.data;
print("SNAPSHOT DATA: $sData");
// the select query has results
new ListView.builder(
itemCount: sData.length,
itemBuilder: (context, i) => new Text(sData[i])
);
} else {
// the select query is still running
return CircularProgressIndicator();
}
}
),
Hi, thanks for reporting. The problem here is that the database has not been initialized when trying to build a SelectBloc
. My fault: it is supposed to not let you do that in such a case: I added a defensive assertion that should have been there in the first place b47dc1453da8b46c3fdd3d6f6141f40409eac8cd . The program will now crash if you start a select bloc when the database is not ready. Thanks for catching this.
About you code: the init
method is aync and the database needs some time to initialize. You are supposed to initialize you database before all. The example does it in a brutal way but you can handle this differently inside you app:
void main() {
initDb().then((_) {
runApp(MyApp());
});
}
The second problem in your code is that you initialize an empty database with no create table query. This should only be possible if initializing from an asset database. I'll add a check to prevent this.
I need to work on the error handling for the user to get a more pleasant experience with detailled error messages about what is going wrong. Thinking about custom exceptions.
In my particular case I am running it without a create because I already know the table exists (And I can actively query it)
I was using table create queries on initialization but I found that your initializer ignores my queries after first creation, and I was trying to drop a table and recreate it on each init for testing purposes.
Obviously it isn't ideal for production but I had to use
db.database.rawQuery()
just after init to create my tables.
I'll try to shoehorn everything in before the app runs.
I'm not sure why StreamBuilder is returning null when I do get it working properly.
On Sun, Feb 17, 2019, 12:17 PM synw <notifications@github.com wrote:
Hi, thanks for reporting. The problem here is that the database has not been initialized when trying to build a SelectBloc. My fault: it is supposed to not let you do that in such a case: I added a defensive assertion that should have been there in the first place b47dc14 https://github.com/synw/sqlcool/commit/b47dc1453da8b46c3fdd3d6f6141f40409eac8cd . The program will now crash if you start a select bloc when the database is not ready. Thanks for catching this.
About you code: the init method is aync and the database needs some time to initialize. You are supposed to initialize you database before all. The example does it in a brutal way but you can handle this differently inside you app:
void main() { initDb().then((_) { runApp(MyApp()); }); }
The second problem in your code is that you initialize an empty database with no create table query. This should only be possible if initializing from an asset database. I'll add a check to prevent this.
I need to work on the error handling for the user to get a more pleasant experience with detailled error messages about what is going wrong. Thinking about custom exceptions.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/synw/sqlcool/issues/1#issuecomment-464483369, or mute the thread https://github.com/notifications/unsubscribe-auth/ABtSGqFIxPfrPLrajbnuIKXVK1tm3hovks5vOY6mgaJpZM4a_aBB .
In my particular case I am running it without a create because I already know the table exists (And I can actively query it)
I see. I should not force at least a query on init
then.
I found that your initializer ignores my queries after first creation
Yes the queries only run on database file creation. For running queries after any initialization we may add a afterInitQueries
list of queries to run or something like that. Would it satisfy your use case or do you have different ideas? Or we can just wrap db.database.rawQuery()
in a db.query
method for convenience and let the developer handle this: I tend to prefer this solution but I'm not sure.
I'll try to shoehorn everything in before the app runs.
You don't have to do that. You can start the app, run init
async and handle the database state yourself in the app to speed up the things. Like:
db.init(path: dbpath, verbose: true).then((_) {
myDbIsReady = true;
});
For the StreamBuilder
not getting any data there might be a problem somewhere: I need more context. Could you please post more code so that we can sort this out once you've done the initialization part right?
I ended up figuring out what I was missing for StreamBuilder.
I appreciate your help with this, I'm rather new to Dart and it's been... an experience jumping straight into things.
I think a db.query()
method would be the easiest for raw queries, In my use case I actually create a table for each set of data that I receive instead of storing everything in a single table for possibly-insane reasons so I have to use db.database.rawQuery()
with a CREATE TABLE IF NOT EXISTS
since I also can't check if a table exists and is empty.
Good that it works for you now. We'll go for the query
method, I'll add this.
I'm reexamining things in order to prevent errors and add useful warnings and information for the developer. I started by madding the database
parameter required for SelectBloc
in order to start getting rid of the global Db
instance I provide: it was a mistake and bad practice, the package should not hold any state or data. There will be a 2.0.0 with these breaking changes.
This does not solve the problem of making sure that the database is ready before firing any query. I need to think about this to find what suits best for the job.
Your intervention was useful to me to get a user perspective point of view on the package. Thanks. Do not hesitate to open issues if you find something weird or encounter problems. This package is still very young and is just starting to stabilize and go after maturity
I also can't check if a table exists and is empty
You can check if a table exists this way: https://github.com/tekartik/sqflite/blob/master/doc/dev_tips.md#list-existing-tables . Maybe wrapping this is a tables
getter would be useful
Good to know that's a way to do it!
I would suggest you change db.exists()
to have where as an optional field.
That way it will check if the table exists without a where, and if the row exists with an ID
That would feel "natural" to me, at least.
In my case, checking for tables then deciding to create or not was actually more calls than an IF NOT EXISTS
so I opted for a NOOP instead of a if for speed reasons.
Following your example for SelectBloc, I'm unable to get data from it. It's just infinitely stuck on the
CircularProgressIndicator()
Changefeed doesn't seem to notice changes, and there is data present in the table before and after SelectBloc is initialized, but despite that fact I cannot get it to build my Listview.
Timing everything out, it actually looks like my database is initialized after SelectBloc queries against it. I'm not sure if that effects how it works.