Jaguar-dart / jaguar_orm

Source-generated ORM with relations (one-to-one, one-to-many, many-to-many), preloading, cascading, polymorphic relations, etc
https://jaguar-dart.github.io
BSD 3-Clause "New" or "Revised" License
217 stars 54 forks source link

insert/upsert cascade 'newModel' isn't used (one to many) #166

Closed dongjian closed 2 years ago

dongjian commented 4 years ago

source code image gen code - class _SmokeDataBean image

jaumard commented 4 years ago

What version do you use ?

dongjian commented 4 years ago

What version do you use ?

Hello! sqflite: ^1.1.7+1 jaguar_orm: ^2.2.6 jaguar_query_sqflite: ^2.2.10

build_runner: jaguar_orm_gen:

jaumard commented 4 years ago

Thanks ! Can you share the source code ? Screenshot are not super to create a reproducible case ^^ I'll try to take a look at that

dongjian commented 4 years ago

Thanks ! Can you share the source code ? Screenshot are not super to create a reproducible case ^^ I'll try to take a look at that

OK source code

import 'dart:async';
import 'package:jaguar_query/jaguar_query.dart';
import 'package:jaguar_orm/jaguar_orm.dart';

part 'dbmodel.jorm.dart';
//flutter pub run build_runner build

class User {
  User({this.id, this.userName, this.gender, this.email});

  @PrimaryKey()
  int id;
  String userName;
  String gender;
  String email;
  @HasMany(SmokeDataBean)
  List<SmokeData> smokeDatas;

  @override
  String toString() {
    return "User($id , $userName , $gender , $email)";
  }
}

@GenBean()
class UserBean extends Bean<User> with _UserBean {
  final SmokeDataBean smokeDataBean;
  UserBean(Adapter adapter)
      : smokeDataBean = SmokeDataBean(adapter),
        super(adapter);
  @override
  String get tableName => 'User';
}

class SmokeData {
  SmokeData({this.id, this.taste, this.duration, this.date});

  @PrimaryKey(auto: true)
  int id;
  int smokeId;
  int taste;
  int duration;
  DateTime date;

  @BelongsTo(UserBean)
  int userd;

  @override
  String toString() {
    return "SmokeData (id: $id ,taste: $taste ,date: $date)";
  }
}

@GenBean()
class SmokeDataBean extends Bean<SmokeData> with _SmokeDataBean {
  SmokeDataBean(Adapter adapter) : super(adapter);

  UserBean _userBean;
  UserBean get userBean => _userBean??=UserBean(adapter);

  @override
  String get tableName => 'SmokeData';
}

gencode

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'dbmodel.dart';

// **************************************************************************
// BeanGenerator
// **************************************************************************

abstract class _UserBean implements Bean<User> {
  final id = IntField('id');
  final userName = StrField('user_name');
  final gender = StrField('gender');
  final email = StrField('email');
  Map<String, Field> _fields;
  Map<String, Field> get fields => _fields ??= {
        id.name: id,
        userName.name: userName,
        gender.name: gender,
        email.name: email,
      };
  User fromMap(Map map) {
    User model = User();
    model.id = adapter.parseValue(map['id']);
    model.userName = adapter.parseValue(map['user_name']);
    model.gender = adapter.parseValue(map['gender']);
    model.email = adapter.parseValue(map['email']);

    return model;
  }

  List<SetColumn> toSetColumns(User model,
      {bool update = false, Set<String> only, bool onlyNonNull = false}) {
    List<SetColumn> ret = [];

    if (only == null && !onlyNonNull) {
      ret.add(id.set(model.id));
      ret.add(userName.set(model.userName));
      ret.add(gender.set(model.gender));
      ret.add(email.set(model.email));
    } else if (only != null) {
      if (only.contains(id.name)) ret.add(id.set(model.id));
      if (only.contains(userName.name)) ret.add(userName.set(model.userName));
      if (only.contains(gender.name)) ret.add(gender.set(model.gender));
      if (only.contains(email.name)) ret.add(email.set(model.email));
    } else /* if (onlyNonNull) */ {
      if (model.id != null) {
        ret.add(id.set(model.id));
      }
      if (model.userName != null) {
        ret.add(userName.set(model.userName));
      }
      if (model.gender != null) {
        ret.add(gender.set(model.gender));
      }
      if (model.email != null) {
        ret.add(email.set(model.email));
      }
    }

    return ret;
  }

  Future<void> createTable({bool ifNotExists = false}) async {
    final st = Sql.create(tableName, ifNotExists: ifNotExists);
    st.addInt(id.name, primary: true, isNullable: false);
    st.addStr(userName.name, isNullable: false);
    st.addStr(gender.name, isNullable: false);
    st.addStr(email.name, isNullable: false);
    return adapter.createTable(st);
  }

  Future<dynamic> insert(User model,
      {bool cascade = false,
      bool onlyNonNull = false,
      Set<String> only}) async {
    final Insert insert = inserter
        .setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull));
    var retId = await adapter.insert(insert);
    if (cascade) {
      User newModel;
      if (model.smokeDatas != null) {
        newModel ??= await find(model.id);
        model.smokeDatas
            .forEach((x) => smokeDataBean.associateUser(x, newModel));
        for (final child in model.smokeDatas) {
          await smokeDataBean.insert(child, cascade: cascade);
        }
      }
    }
    return retId;
  }

  Future<void> insertMany(List<User> models,
      {bool cascade = false,
      bool onlyNonNull = false,
      Set<String> only}) async {
    if (cascade) {
      final List<Future> futures = [];
      for (var model in models) {
        futures.add(insert(model, cascade: cascade));
      }
      await Future.wait(futures);
      return;
    } else {
      final List<List<SetColumn>> data = models
          .map((model) =>
              toSetColumns(model, only: only, onlyNonNull: onlyNonNull))
          .toList();
      final InsertMany insert = inserters.addAll(data);
      await adapter.insertMany(insert);
      return;
    }
  }

  Future<dynamic> upsert(User model,
      {bool cascade = false,
      Set<String> only,
      bool onlyNonNull = false}) async {
    final Upsert upsert = upserter
        .setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull));
    var retId = await adapter.upsert(upsert);
    if (cascade) {
      User newModel;
      if (model.smokeDatas != null) {
        newModel ??= await find(model.id);
        model.smokeDatas
            .forEach((x) => smokeDataBean.associateUser(x, newModel));
        for (final child in model.smokeDatas) {
          await smokeDataBean.upsert(child, cascade: cascade);
        }
      }
    }
    return retId;
  }

  Future<void> upsertMany(List<User> models,
      {bool cascade = false,
      bool onlyNonNull = false,
      Set<String> only}) async {
    if (cascade) {
      final List<Future> futures = [];
      for (var model in models) {
        futures.add(upsert(model, cascade: cascade));
      }
      await Future.wait(futures);
      return;
    } else {
      final List<List<SetColumn>> data = [];
      for (var i = 0; i < models.length; ++i) {
        var model = models[i];
        data.add(
            toSetColumns(model, only: only, onlyNonNull: onlyNonNull).toList());
      }
      final UpsertMany upsert = upserters.addAll(data);
      await adapter.upsertMany(upsert);
      return;
    }
  }

  Future<int> update(User model,
      {bool cascade = false,
      bool associate = false,
      Set<String> only,
      bool onlyNonNull = false}) async {
    final Update update = updater
        .where(this.id.eq(model.id))
        .setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull));
    final ret = adapter.update(update);
    if (cascade) {
      User newModel;
      if (model.smokeDatas != null) {
        if (associate) {
          newModel ??= await find(model.id);
          model.smokeDatas
              .forEach((x) => smokeDataBean.associateUser(x, newModel));
        }
        for (final child in model.smokeDatas) {
          await smokeDataBean.update(child,
              cascade: cascade, associate: associate);
        }
      }
    }
    return ret;
  }

  Future<void> updateMany(List<User> models,
      {bool cascade = false,
      bool onlyNonNull = false,
      Set<String> only}) async {
    if (cascade) {
      final List<Future> futures = [];
      for (var model in models) {
        futures.add(update(model, cascade: cascade));
      }
      await Future.wait(futures);
      return;
    } else {
      final List<List<SetColumn>> data = [];
      final List<Expression> where = [];
      for (var i = 0; i < models.length; ++i) {
        var model = models[i];
        data.add(
            toSetColumns(model, only: only, onlyNonNull: onlyNonNull).toList());
        where.add(this.id.eq(model.id));
      }
      final UpdateMany update = updaters.addAll(data, where);
      await adapter.updateMany(update);
      return;
    }
  }

  Future<User> find(int id,
      {bool preload = false, bool cascade = false}) async {
    final Find find = finder.where(this.id.eq(id));
    final User model = await findOne(find);
    if (preload && model != null) {
      await this.preload(model, cascade: cascade);
    }
    return model;
  }

  Future<int> remove(int id, {bool cascade = false}) async {
    if (cascade) {
      final User newModel = await find(id);
      if (newModel != null) {
        await smokeDataBean.removeByUser(newModel.id);
      }
    }
    final Remove remove = remover.where(this.id.eq(id));
    return adapter.remove(remove);
  }

  Future<int> removeMany(List<User> models) async {
// Return if models is empty. If this is not done, all records will be removed!
    if (models == null || models.isEmpty) return 0;
    final Remove remove = remover;
    for (final model in models) {
      remove.or(this.id.eq(model.id));
    }
    return adapter.remove(remove);
  }

  Future<User> preload(User model, {bool cascade = false}) async {
    model.smokeDatas = await smokeDataBean.findByUser(model.id,
        preload: cascade, cascade: cascade);
    return model;
  }

  Future<List<User>> preloadAll(List<User> models,
      {bool cascade = false}) async {
    models.forEach((User model) => model.smokeDatas ??= []);
    await OneToXHelper.preloadAll<User, SmokeData>(
        models,
        (User model) => [model.id],
        smokeDataBean.findByUserList,
        (SmokeData model) => [model.userd],
        (User model, SmokeData child) =>
            model.smokeDatas = List.from(model.smokeDatas)..add(child),
        cascade: cascade);
    return models;
  }

  SmokeDataBean get smokeDataBean;
}

abstract class _SmokeDataBean implements Bean<SmokeData> {
  final id = IntField('id');
  final smokeId = IntField('smoke_id');
  final taste = IntField('taste');
  final duration = IntField('duration');
  final date = DateTimeField('date');
  final userd = IntField('userd');
  Map<String, Field> _fields;
  Map<String, Field> get fields => _fields ??= {
        id.name: id,
        smokeId.name: smokeId,
        taste.name: taste,
        duration.name: duration,
        date.name: date,
        userd.name: userd,
      };
  SmokeData fromMap(Map map) {
    SmokeData model = SmokeData();
    model.id = adapter.parseValue(map['id']);
    model.smokeId = adapter.parseValue(map['smoke_id']);
    model.taste = adapter.parseValue(map['taste']);
    model.duration = adapter.parseValue(map['duration']);
    model.date = adapter.parseValue(map['date']);
    model.userd = adapter.parseValue(map['userd']);

    return model;
  }

  List<SetColumn> toSetColumns(SmokeData model,
      {bool update = false, Set<String> only, bool onlyNonNull = false}) {
    List<SetColumn> ret = [];

    if (only == null && !onlyNonNull) {
      if (model.id != null) {
        ret.add(id.set(model.id));
      }
      ret.add(smokeId.set(model.smokeId));
      ret.add(taste.set(model.taste));
      ret.add(duration.set(model.duration));
      ret.add(date.set(model.date));
      ret.add(userd.set(model.userd));
    } else if (only != null) {
      if (model.id != null) {
        if (only.contains(id.name)) ret.add(id.set(model.id));
      }
      if (only.contains(smokeId.name)) ret.add(smokeId.set(model.smokeId));
      if (only.contains(taste.name)) ret.add(taste.set(model.taste));
      if (only.contains(duration.name)) ret.add(duration.set(model.duration));
      if (only.contains(date.name)) ret.add(date.set(model.date));
      if (only.contains(userd.name)) ret.add(userd.set(model.userd));
    } else /* if (onlyNonNull) */ {
      if (model.id != null) {
        ret.add(id.set(model.id));
      }
      if (model.smokeId != null) {
        ret.add(smokeId.set(model.smokeId));
      }
      if (model.taste != null) {
        ret.add(taste.set(model.taste));
      }
      if (model.duration != null) {
        ret.add(duration.set(model.duration));
      }
      if (model.date != null) {
        ret.add(date.set(model.date));
      }
      if (model.userd != null) {
        ret.add(userd.set(model.userd));
      }
    }

    return ret;
  }

  Future<void> createTable({bool ifNotExists = false}) async {
    final st = Sql.create(tableName, ifNotExists: ifNotExists);
    st.addInt(id.name, primary: true, autoIncrement: true, isNullable: false);
    st.addInt(smokeId.name, isNullable: false);
    st.addInt(taste.name, isNullable: false);
    st.addInt(duration.name, isNullable: false);
    st.addDateTime(date.name, isNullable: false);
    st.addInt(userd.name,
        foreignTable: userBean.tableName, foreignCol: 'id', isNullable: false);
    return adapter.createTable(st);
  }

  Future<dynamic> insert(SmokeData model,
      {bool cascade = false,
      bool onlyNonNull = false,
      Set<String> only}) async {
    final Insert insert = inserter
        .setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull))
        .id(id.name);
    var retId = await adapter.insert(insert);
    if (cascade) {
      SmokeData newModel;//<=========================================here
    }
    return retId;
  }

  Future<void> insertMany(List<SmokeData> models,
      {bool onlyNonNull = false, Set<String> only}) async {
    final List<List<SetColumn>> data = models
        .map((model) =>
            toSetColumns(model, only: only, onlyNonNull: onlyNonNull))
        .toList();
    final InsertMany insert = inserters.addAll(data);
    await adapter.insertMany(insert);
    return;
  }

  Future<dynamic> upsert(SmokeData model,
      {bool cascade = false,
      Set<String> only,
      bool onlyNonNull = false}) async {
    final Upsert upsert = upserter
        .setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull))
        .id(id.name);
    var retId = await adapter.upsert(upsert);
    if (cascade) {
      SmokeData newModel;//<=========================================here
    }
    return retId;
  }

  Future<void> upsertMany(List<SmokeData> models,
      {bool onlyNonNull = false, Set<String> only}) async {
    final List<List<SetColumn>> data = [];
    for (var i = 0; i < models.length; ++i) {
      var model = models[i];
      data.add(
          toSetColumns(model, only: only, onlyNonNull: onlyNonNull).toList());
    }
    final UpsertMany upsert = upserters.addAll(data);
    await adapter.upsertMany(upsert);
    return;
  }

  Future<int> update(SmokeData model,
      {bool cascade = false,
      bool associate = false,
      Set<String> only,
      bool onlyNonNull = false}) async {
    final Update update = updater
        .where(this.id.eq(model.id))
        .setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull));
    return adapter.update(update);
  }

  Future<void> updateMany(List<SmokeData> models,
      {bool onlyNonNull = false, Set<String> only}) async {
    final List<List<SetColumn>> data = [];
    final List<Expression> where = [];
    for (var i = 0; i < models.length; ++i) {
      var model = models[i];
      data.add(
          toSetColumns(model, only: only, onlyNonNull: onlyNonNull).toList());
      where.add(this.id.eq(model.id));
    }
    final UpdateMany update = updaters.addAll(data, where);
    await adapter.updateMany(update);
    return;
  }

  Future<SmokeData> find(int id,
      {bool preload = false, bool cascade = false}) async {
    final Find find = finder.where(this.id.eq(id));
    return await findOne(find);
  }

  Future<int> remove(int id) async {
    final Remove remove = remover.where(this.id.eq(id));
    return adapter.remove(remove);
  }

  Future<int> removeMany(List<SmokeData> models) async {
// Return if models is empty. If this is not done, all records will be removed!
    if (models == null || models.isEmpty) return 0;
    final Remove remove = remover;
    for (final model in models) {
      remove.or(this.id.eq(model.id));
    }
    return adapter.remove(remove);
  }

  Future<List<SmokeData>> findByUser(int userd,
      {bool preload = false, bool cascade = false}) async {
    final Find find = finder.where(this.userd.eq(userd));
    return findMany(find);
  }

  Future<List<SmokeData>> findByUserList(List<User> models,
      {bool preload = false, bool cascade = false}) async {
// Return if models is empty. If this is not done, all the records will be returned!
    if (models == null || models.isEmpty) return [];
    final Find find = finder;
    for (User model in models) {
      find.or(this.userd.eq(model.id));
    }
    return findMany(find);
  }

  Future<int> removeByUser(int userd) async {
    final Remove rm = remover.where(this.userd.eq(userd));
    return await adapter.remove(rm);
  }

  void associateUser(SmokeData child, User parent) {
    child.userd = parent.id;
  }

  UserBean get userBean;
}

warning: The value of the local variable 'newModel' isn't used. Try removing the variable, or using it.dart(unused_local_variable) gencode line 361 and line 386