kalaLokia
kalaLokia

Reputation: 131

How do I read data from a existing database in the assets folder on Flutter, I am stuck with errors

I am trying to read data from a database which is already made outside and placed in assets folder in my project. I have quiet checked some tutorials to build code. Here am simply copying database in my assets folder to application documents directory and trying to get (debugprint to console) the count of data in the column "father" using the rawQuery method, my table name is "items". I am getting an error saying, No such table. So am guessing I have a broken code on my database helper class.

  static DatabaseHelper _databaseHelper; // Singleton DatabaseHelper
  static Database _database; // Singleton Database
  static String _path;

  DatabaseHelper._createInstance(); // Named constructor to create instance of DatabaseHelper

  factory DatabaseHelper() {
    if (_databaseHelper == null) {
      _databaseHelper = DatabaseHelper
          ._createInstance(); // This is executed only once, singleton object
    }
    return _databaseHelper;
  }

  Future<Database> get database async {
    if (_database == null) {
      _database = await initializeDatabase();
    }
    return _database;
  }

  Future<Database> initializeDatabase() async {
    // Get the directory path for both Android and iOS to store database.
    Directory directory = await getApplicationDocumentsDirectory();
    _path = directory.path + 'bomdb.sqlite';

    // Open/create the database at a given path
    var bomDatabase = await openDatabase(
        _path, version: 1, onCreate: _createDb);
    return bomDatabase;
  }

  void _createDb(Database db, int newVersion) async {
    ByteData data = await rootBundle.load('assets/bomdb.sqlite');
    List<int> bytes =
    data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
    debugPrint('Database is in path:  ' + _path);
    await new File(_path).writeAsBytes(bytes);
  }

  Future<int> sampleData() async {
    Database db = await this.database;
    List<Map<String, dynamic>> x = await db.rawQuery(
        'SELECT COUNT(father) FROM items');
    var res = await db.rawQuery('SELECT COUNT(father) FROM items');
    int result = Sqflite.firstIntValue(x);
    debugPrint(result.toString());
    return result;
  }
}

Upvotes: 1

Views: 2884

Answers (1)

kalaLokia
kalaLokia

Reputation: 131

I refer the sqflite doc provided by Mr. Tommie C, I changed my initializeDatabase to the following and removed _createDb function that is not require in here:

Future<Database> initializeDatabase() async {
var databasesPath = await getDatabasesPath();
var path = join(databasesPath, "bomdb.sqlite");

// Check if the database exists
var exists = await databaseExists(path);

if (!exists) {
  // Should happen only the first time you launch your application
  print("Creating new copy from asset");

  // Make sure the parent directory exists
  try {
    await Directory(dirname(path)).create(recursive: true);
  } catch (_) {}

  // Copy from asset
  ByteData data = await rootBundle.load(join("assets", "bomdb.sqlite"));
  List<int> bytes =
      data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);

  // Write and flush the bytes written
  await File(path).writeAsBytes(bytes, flush: true);
} else {
  print("Opening existing database");
}
// open the database
var bomDataTable = await openDatabase(path, readOnly: true);

return bomDataTable;
}

I still not figured why it is not worked with oncreate statement with opendatabase, but no issues with this as it is described in the document: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_asset_db.md

Upvotes: 4

Related Questions