Sqflite Database exception no such table in flutter - database

I have loaded json data in a list of objects. Whenever I try to insert data into a table my console says "Unhandled Exception: DatabaseException(no such table: Album (code 1 SQLITE_ERROR): , while compiling: INSERT OR REPLACE INTO Album...." . I know before inserting data I have to create database and table. I have done that in my code. But for some unknown reason the table doesn't get build. Here is my database helper class -
class DatabaseHelper {
static final _dbName = "myDatabase.db";
static final _dbVersion = 1;
static final _tableAlbum = "Album";
static final columnAlbum = '_fetched_album';
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
static Database? _database;
Future<Database?> get database async {
if (_database == null) {
print("instance.db null");
_database ??= await _initiateDatabase();
return _database;
}else{
print("instance.db not null");
return _database; }
}
Future<Database> _initiateDatabase() async {
String directory = await getDatabasesPath();
String path = join(directory, _dbName);
return await openDatabase(
path,
version: _dbVersion,
onCreate:(Database db,int version) async {
await db.execute('''
CREATE TABLE $_tableAlbum (
$columnAlbum TEXT
)''');
},
);
}
Future<int?> insertAlbum(ModelAlbum list) async {
Database? db = await instance.database;
return await db?.insert(
_tableAlbum,list.toMap(),conflictAlgorithm: ConflictAlgorithm.replace);
}
Future<int?> insertPhoto(ModelPhoto list) async {
Database? db = await instance.database;
return await db?.insert(
_tablePhoto,list.toMap(),conflictAlgorithm: ConflictAlgorithm.replace);
}
Future<List<Map<String, dynamic>>> queryAlbum() async {
Database? db = await instance.database;
return await db!.query(_tableAlbum);
}
Future<List<Map<String, dynamic>>> queryPhoto() async {
Database? db = await instance.database;
return await db!.query(_tableAlbum);
}
Future<List<ModelAlbum>> retrieveAlbum() async {
final Database? db = await database;
final List<Map> maps = await db!.query(_tableAlbum);
return List.generate(maps.length, (i) {
return ModelAlbum(
id: maps[i]['id'],
title: maps[i]['title'],
userId: maps[i]['userId'],
);
});
}
Future<List<ModelPhoto>> retrievePhoto() async {
final Database? db = await database;
final List<Map> maps = await db!.query(_tablePhoto);
return List.generate(maps.length, (i) {
return ModelPhoto(
albumId: maps[i]['albumId'],
thumbnailUrl: maps[i]['thumbnailUrl'],
url: maps[i]['url'],
id: maps[i]['id'],
title: maps[i]['title'],
);
});
}
}
Whenever Database.instance.insert(object); gets called the database and table should be automatically created. But it doesn't.

You are referring to static fields from instance methods. this may a problem try removing static keyword from the fields as,
final _dbName = "myDatabase.db";
final _dbVersion = 1;
final _tableAlbum = "Album";
final columnAlbum = '_fetched_album';

Related

Flutter Sqflite database DatabaseException no such table Is Occur

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: DatabaseException(no such table: MST_University (code 1 SQLITE_ERROR): , while compiling: SELECT * FROM MST_University) sql 'SELECT * FROM MST_University' args []
import 'dart:developer';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DataBaseHelper {
static var _database;
DataBaseHelper._privateConstructor();
static final DataBaseHelper instance = DataBaseHelper._privateConstructor();
Future<Database> get database async {
if (_database != null) {
log("Database new is not creatred and retuned ");
return _database;
}
// Call init Databasee method for New Database Creation
log("new Database is create");
_database = await _initDatabase();
return _database;
}
Future<Database> _initDatabase() async {
Directory appDocDir = await getApplicationDocumentsDirectory();
log("new dAta");
String databasePath = join(appDocDir.path, 'pharmacy2.db');
return await openDatabase(
databasePath,
version: 2,
);
}
Future<void> copyPasteAssetFileToRoot() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
log("assets database is loading");
String path = join(documentsDirectory.path, "pharmacy2.db");
if (FileSystemEntity.typeSync(path) == FileSystemEntityType.notFound) {
ByteData data =
await rootBundle.load(join('assests/database', 'pharmacy2.db'));
List<int> bytes =
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await File(path).writeAsBytes(bytes);
}
}
Future<void> getAllUniversity() async {
Database db = await instance.database;
var result = await db.query("MST_University");
log(result.toString());
}
}
I try a privet constructor for single instance and also load database from a assets
I cannot see where you call copyPasteAssetFileToRoot, so maybe never?
assests/database looks very much like a typo.
Even if that all is correct, the database you open has no such table.
Why don't you set a few breakpoints in your debugger and find out what steps work and which don't. Whether you path is set correctly and your file gets copied or not. Whether you open the correct file. Whether that file actually has such a table.

Unhandled Exception: LateInitializationError: Field '_database#91313886' has not been initialized

I'm a beginner in flutter
I want to link the db file that I have.
There is an error related to initialization, but I don't know what the problem is
2022-02-16 17:47:47.530 20199-20218/com.example.flower_sunset_2 E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: LateInitializationError: Field '_database#91313886' has not been initialized.
#0 DatabaseProvider._database (package:flower_sunset_2/database.dart)
#1 DatabaseProvider.database (package:flower_sunset_2/database.dart:19:9)
class DatabaseProvider {
static final DatabaseProvider provider = DatabaseProvider();
late Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await createDatabase();
return _database;
}
createDatabase() async {
// Directory docsDir = await getApplicationDocumentsDirectory();
// String path = join(docsDir.path, "repo_db_senior.db");
var databasePath = await getDatabasesPath();
var path = join(databasePath, "repo_db_senior.db");
// Check if the database exists
var exists = await databaseExists(path);
print("database start");
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('repo', 'db', 'senior.db'));
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");
}
var database = await openDatabase(path, readOnly: true);
// var database = await openDatabase(path, version: 1, onCreate: initDB, onUpgrade: onUpgrade);
return database;
}
}
pubspec.yaml
assets:
- repo/db/senior.db
your database file names are not matching. In pubspec.yaml file you have it as 'senior.db' while in your code you are looking for 'repo_db_senior.db'.

How to fix "The non-nullable variable '_db' must be initialized. Try adding an initializer expression"

"The non-nullable variable '_db' must be initialized. Try adding an initializer expression"
Could anyone help me with this non-nullable error?
I am using flutter to make an android app and while using the 'sqflite' and making a database, this error pops up I don't know how to really fix this
Here is my Code below,
I am using the last version of Flutter & Dart,
import 'dart:io';
import 'package:newtodoapp/taskmodel.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
class DatabaseHelper {
static final DatabaseHelper instance = DatabaseHelper._instance();
static Database _db;
DatabaseHelper._instance();
String tasksTable = 'task_table';
String colId = 'id';
String colTitle = 'title';
String colDate = 'date';
String colPriority = 'priority';
String colStatus = 'status';
// Task Tables
// Id | Title | Date | Priority | Status
// 0 '' '' '' 0
// 2 '' '' '' 0
// 3 '' '' '' 0
Future<Database> get db async {
if (_db == null) {
_db = await _initDb();
}
return _db;
}
Future<Database> _initDb() async {
Directory dir = await getApplicationDocumentsDirectory();
String path = dir.path + '/todo_list.db';
final todoListDb =
await openDatabase(path, version: 1, onCreate: _createDb);
return todoListDb;
}
void _createDb(Database db, int version) async {
await db.execute(
'CREATE TABLE $tasksTable($colId INTEGER PRIMARY KEY AUTOINCREMENT,'
' $colTitle TEXT, $colDate TEXT, $colPriority TEXT, $colStatus INTEGER)',
);
}
Future<List<Map<String, dynamic>>> getTaskMapList() async {
Database db = await this.db;
final List<Map<String, dynamic>> result = await db.query(tasksTable);
return result;
}
Future<List<Task>> getTaskList() async {
final List<Map<String, dynamic>> taskMapList = await getTaskMapList();
final List<Task> taskList = [];
taskMapList.forEach((taskMap) {
taskList.add(Task.fromMap(taskMap));
});
taskList.sort((taskA, taskB) => taskA.date.compareTo(taskB.date));
return taskList;
}
Future<int> insertTask(Task task) async {
Database db = await this.db;
final int result = await db.insert(tasksTable, task.toMap());
return result;
}
Future<int> updateTask(Task task) async {
Database db = await this.db;
final int result = await db.update(
tasksTable,
task.toMap(),
where: '$colId = ?',
whereArgs: [task.id],
);
return result;
}
Future<int> deleteTask(int id) async {
Database db = await this.db;
final int result = await db.delete(
tasksTable,
where: '$colId = ?',
whereArgs: [id],
);
return result;
}
}
declare your variable like this.
static Database? _db;

The method was called on null even though method was already declared

I was making an app and it keeps showing an error the method was called on null. When I looked up for answers it was specified that this occurs when method is not declared but in my case method has been already declared.
Due to this error I am not able to save data in my app.
initialiseDatabase is the function it states as called on null.
Here is the code-
static DatabaseHelper _databaseHelper; // singleton
static Database _database;
String noteTable = 'note_Table';
String colId = 'id';
String colTitle = 'title';
String colDescription = 'description';
String colPriority = 'priority';
String colDate = 'date';
DatabaseHelper._createInstance();// named constructor to create dbms helper
factory DatabaseHelper(){
if(DatabaseHelper == null) {
_databaseHelper = DatabaseHelper._createInstance();
}
return _databaseHelper;
}
Future<Database> get database async{
if(_database == null){
_database = await initializeDatabase();
}
return _database;
}
Future<Database> initializeDatabase() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path + 'notes.db';
var notesDatabase = await openDatabase(path, version: 1, onCreate: _createDb);
return notesDatabase;
}
void _createDb(Database db, int newVersion) async{
await db.execute('CREATE TABLE $noteTable($colId INTEGER PRIMARY KEY AUTOINCREMENT, $colTitle TEXT.'
'$colDescription TEXT, $colPriority INTEGER, $colDate TEXT');
}
// Fetch Operation: Get all note objects from database
Future<List<Map<String, dynamic>>> getNoteMapList() async {
Database db = await this.database;
// var result = await db.rawQuery('SELECT * FROM $noteTable order by $colPriority ASC');
var result = await db.query(noteTable, orderBy: '$colPriority ASC');
return result;
}
// Insert Operation: Insert a Note object to database
Future<int> insertNote(Note note) async {
Database db = await this.database;
var result = await db.insert(noteTable, note.toMap());
return result;
}
// Update Operation: Update a Note object and save it to database
Future<int> updateNote(Note note) async {
var db = await this.database;
var result = await db.update(noteTable, note.toMap(), where: '$colId = ?', whereArgs: [note.id]);
return result;
}
// Delete Operation: Delete a Note object from database
Future<int> deleteNote(int id) async {
var db = await this.database;
int result = await db.rawDelete('DELETE FROM $noteTable WHERE $colId = $id');
return result;
}
// Get number of Note objects in database
Future<int> getCount() async {
Database db = await this.database;
List<Map<String, dynamic>> x = await db.rawQuery('SELECT COUNT (*) from $noteTable');
int result = Sqflite.firstIntValue(x);
return result;
}
// Get the 'Map List' [ List<Map> ] and convert it to 'Note List' [ List<Note> ]
Future<List<Note>> getNoteList() async {
var noteMapList = await getNoteMapList(); // Get 'Map List' from database
int count = noteMapList.length; // Count the number of map entries in db table
List<Note> noteList = List<Note>();
// For loop to create a 'Note List' from a 'Map List'
for (int i = 0; i < count; i++) {
noteList.add(Note.fromMapObject(noteMapList[i]));
}
return noteList;
}
}
While this is the function which it states as not declared
Future<Database> get database async{
if(_database == null){
_database = await initializeDatabase();
}
return _database;
}
Future<Database> initializeDatabase() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path + 'notes.db';
var notesDatabase = await openDatabase(path, version: 1, onCreate: _createDb);
return notesDatabase;
}

How to create multiple table in Sqlite database at different times in Flutter

So Initially I created a table named "TABLE" in the database. I wanted to add another table. So I added another query to create a table. However I get an error saying "TABLE1 does not exist" when I run the app.
I do feel like there is a flaw in my code. I think the _onCreate() method will only be called the first time I run the app. So any code I add on _onCreate() method afterwards will not run. Any help will be appreciated.
class DBHelper {
static Database _db;
static const String DB_NAME = 'employeeDB';
static const String ID = 'id';
static const String NAME = 'name';
static const String TABLE = 'Employee';
static const String ID1 = 'id1';
static const String NAME1 = 'name1';
static const String TABLE1 = 'Employee1';
Future<Database> get db async {
if (_db != null) {
return _db;
}
_db = await initDb();
return _db;
}
initDb() async {
io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, DB_NAME);
var db = await openDatabase(path, version: 1, onCreate: _onCreate);
return db;
}
_onCreate(Database db, int version) async {
await db.execute("CREATE TABLE $TABLE ($ID INTEGER PRIMARY KEY,$NAME TEXT)");
await db.execute("CREATE TABLE $TABLE1 ($ID1 INTEGER PRIMARY KEY,$NAME1 TEXT)");
}
Future<Employee> save(Employee employee) async {
var dbClient = await db;
employee.id = await dbClient.insert(TABLE, employee.toMap());
return employee;
}
Future<Employee1> saveEmp1(Employee1 employee) async {
var dbClient = await db;
employee.id = await dbClient.insert(TABLE1, employee.toMap());
return employee;
}
Future<List<Employee>> getEmployees() async {
var dbClient = await db;
List<Map> maps = await dbClient.query(TABLE, columns: [ID, NAME]);
List<Employee> employees = [];
if (maps.length > 0) {
for (int i = 0; i < maps.length; i++) {
employees.add(Employee.fromMap(maps[i]));
}
}
return employees;
}
Future<List<Employee1>> getEmployees1() async {
var dbClient = await db;
List<Map> maps = await dbClient.query(TABLE1, columns: [ID1,
NAME1]);
List<Employee1> employees = [];
if (maps.length > 0) {
for (int i = 0; i < maps.length; i++) {
employees.add(Employee.fromMap(maps[i]));
}
}
return employees;
}
}
The first time run this app and initDb() in emulator, the db file employeeDB has created.
and it will not be created again
For only test app execution,
you can change
String DB_NAME = 'employeeDB'
to another name
String DB_NAME = 'employeeDB1'
or you can uninstall this app from Emulator first then run it again.
source code snippet of https://github.com/tekartik/sqflite/blob/master/sqflite/lib/sqlite_api.dart
/// Called when the database is created.
OnDatabaseCreateFn onCreate;
For schema migration, you can use OnUpgrade, detail reference https://efthymis.com/migrating-a-mobile-database-in-flutter-sqlite/
code snippet
await openDatabase(path,
version: 1,
onCreate: (Database db, int version) async {
await db.execute(initialSchema));
},
onUpgrade: (Database db, int oldVersion, int newVersion) async {
await db.execute(migrationScript));
});
You have to create migrations and run them against your existing database using the onUpgrade handler. Basically you need to check the existing database version and upgrade if the version is smaller than the migration number.
You can check out the detail steps/code tutorial here.
I needed to create more than just multiple tables; but multiple database. I have since developed a dart package; sqlite_at_runtime that stretches to as far as creating all these entities at run time.
Below is an example code that creates three tables with similar attributes.
await Sqlartime.tableCreate(['sample1','sample2','sample3'],['name TEXT','age INTEGER','temp REAL']);

Resources