Moor: Random nulls on aliased innerJoin

Created on 11 Jul 2019  路  8Comments  路  Source: simolus3/moor

I have this stream:

    final monsterStatsNormal = alias(db.monsterStats, 'monster_stats_normal');
    final monsterStatsElite = alias(db.monsterStats, 'monster_stats_elite');
    return select(activeMonster).join(
      [
        innerJoin(db.monster, db.monster.id.equalsExp(activeMonster.id)),
        innerJoin(monsterStatsNormal, and(and(
          monsterStatsNormal.monsterId.equalsExp(db.monster.id),
          monsterStatsNormal.scenarioLevelId.equalsExp(activeMonster.scenarioLevelId)),
          monsterStatsNormal.type.equals('normal'),
        )),
        innerJoin(monsterStatsElite, and(and(
          monsterStatsElite.monsterId.equalsExp(db.monster.id),
          monsterStatsElite.scenarioLevelId.equalsExp(activeMonster.scenarioLevelId)),
          monsterStatsElite.type.equals('elite'),
        )),
      ]
    ).watch().map((rows) {
      return rows.map((row) {
        row.rawData.data.forEach((key, value) {
          print('$key: $value');
        });
        return ActiveMonsterInfo(
          row.readTable(activeMonster),
          row.readTable(db.monster),
          row.readTable(monsterStatsNormal),
          row.readTable(monsterStatsElite),
        );
      }).toList();
    });

The row.readTable(monsterStatsNormal) and row.readTable(monsterStatsElite) will randomly return a null value.

However

        row.rawData.data.forEach((key, value) {
          print('$key: $value');
        });

will print out all columns correctly.

Its actually not that random. 1st time I press hot reload i'll get data, 2nd time null, 3rd time data etc

bug

All 8 comments

Ha, this one was interesting, thanks for the report! All the tables are mapped correctly, this is due to how moor caches streams. The rows instance will survive hot reloads as the last query is still cached, but the alias method creates a new table every time, so we can't get the old instance.

Fixed by making tables override hashCode and equals, this will be part of 1.6 which will be released soon.

I couldn't reproduce the effect that it works every second time - I think this was another minor bug that will also be fixed in 1.6

Just gave it a test and its working! Thanks

@simolus3 I can create another issue for this but seems related. My app is watching a couple of streams (both single and multi) and it works great, but when I do a hot reload, any db updates don't get propagated to the streams. When I do a 2nd hot reload it starts working again.

Just to be sure - is this still happening when on the beta branch? Can you try to put

dependency_overrides:
  moor:
    git:
      url: https://github.com/simolus3/moor.git
      ref: beta
      path: moor/

in your pubspec, run flutter packages upgrade and then flutter clean?

Still happening on beta branch.

moor:
    dependency: "direct overridden"
    description:
      path: "moor/"
      ref: beta
      resolved-ref: f0e5ed9a8785d174c86adf51481a99f06f406f2d
      url: "https://github.com/simolus3/moor.git"
    source: git
    version: "1.5.1+1"

Steps:

  1. I'm watching a list.
  2. Update an item in the list
  3. It updates
  4. Hot reload
  5. Update an item in the list
  6. Doesn't update
  7. Hot reload
  8. Item updates

Not sure if this is helpful, but I ran into similar issues with my custom sqflite/stream cache implementation when the stream was removed from the cache while inert listeners were still holding a reference to it. Something like:

var stream = getMyQueryStream();
var stream2 = getMyQueryStream();
await stream.first; // listens and cancels - stream is now removed from cache and won't receive updates
stream2.listen(...) // will never receive updates

I solved it with something like this

@Mike278 Thanks! I forked this and merged the latest changes and it works great

Good idea @Mike278, I've went for a very similar approach to fix this in moor at 3407c8e90ee98e0f05e44a572250391c045363e6

Was this page helpful?
0 / 5 - 0 ratings