최근 만들고 있는 앱에서 db를 사용해야 해서 sqflite라는 sqlite 라이브러리를 사용하고 있을 때 만난 문제다.

 

db를 열 때, database path에 db파일이 존재하지 않으면 assets에 있는 초기 db파일을 복사해서 database path에 붙여넣기를 하도록 onCreate함수를 만들고 있었다.

 

// 함수 부분 

late Database db;


  Future openDB() async{
    final databasePath = await getDatabasesPath();
    String path = join(databasePath, DB_FILE_NAME);

    db = await openDatabase(
      path,
      version: 1,
      onConfigure: (Database db) => {},
      onCreate: _onCreate,
      onUpgrade: _onUpgrade,
    );

    print('Opened!');
  }



  Future _onCreate(Database db, int version) async {

    await db.execute(CREATE_TABLE_QUERY);

    final databasePath = await getDatabasesPath();
    String path = join(databasePath, DB_FILE_NAME);

    var exists = await databaseExists(path);

    if (!exists) {
      print("Creating $DB_FILE_NAME from asset");
      try {
        await Directory(dirname(path)).create(recursive: true);
      } catch (_) {}
    }

    ByteData data = await rootBundle.load(join("assets", DB_FILE_NAME));
    List<int> bytes =
    data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
    await File(path).writeAsBytes(bytes, flush: true);

    print('create done');
  }

 

이렇게 함수들을 작성하고, test코드에서 openDB()를 실행하면

처음 실행 시, assets의 초기 db파일을 database path에 가져와서 db를 열고, 그것이 아니라면 database path에 있는 db를 연다. 

 

그런데 처음 실행하면 database path에 assets의 초기 db파일과 동일한 크기(용량)의 db 파일이 생기는데, 파일을 읽으면 db파일 안에 데이터가 없다고 뜬다.

 

실제로 .db파일을 읽는 플러그인을 설치해서 안을 들여다 봐도 데이터가 없다. 

 

해결한다고 한 3일 사용한 것 같은데

정확한 이유는 못 찾았지만 _onCreate함수 내에서 await db.execute()와 db파일 복붙 사이에서 충돌이 일어나서 그런 것 같다. 

(openDatabase 에서 path에 db파일이 없으니 _onCreate함수를 실행하는데, 여기서 db를 생성하는게 아니라 assets에서 초기 db를 복붙하는 작업을 하니 여기서 오류가 발생한게 아닌가 싶다.)

 

해결법은 openDB 함수에서 db파일이 있는지를 검사해서 없다면 초기 db파일을 database path에 복사 붙여넣기를 하는 것이다.

 

Future openDB() async{
    final databasePath = await getDatabasesPath();
    String path = join(databasePath, DB_FILE_NAME);
    var exists = await databaseExists(path);

    if (!exists) {
      print("Creating $DB_FILE_NAME from asset");

      try {
        await Directory(dirname(path)).create(recursive: true);
      } catch (_) {}

      ByteData data = await rootBundle.load(join("assets", DB_FILE_NAME));
      List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
      await File(path).writeAsBytes(bytes, flush: true);

      print('Created!');
    }

    db = await openDatabase(
      path,
      version: 1,
      onConfigure: (Database db) => {},
      onCreate: (Database db, int version) => {},
      onUpgrade: _onUpgrade,
    );

    print('Opened!');

  }

 

이렇게 하니까 해결 완료