Error importing and replacing Sqlite Database in Flutter - flutter

I have a .db file in the Documents on the device. It has a particular Sqlite database stored on it. How would I import that database file and replace the old one in Flutter? It always has the same name and the same destination in Documents. Here is the code in the DbHelper.dart that initializes the original database, what I'm looking for is replacing that one with the db file I have of another database in the Documents.
DatabaseProvider._();
static final DatabaseProvider db = DatabaseProvider._();
Database _database;
Future<Database> get database async {
print("database getter called");
if (_database != null) {
return _database;
}
_database = await createDatabase();
return _database;
}
Future<Database> createDatabase() async {
String dbPath = await getDatabasesPath();
return await openDatabase(
join(dbPath, 'oldDB.db'),
version: 1,
onCreate: (Database database, int version) async {
print("Creating table");
await database.execute(
"CREATE TABLE $TABLE_PERSON ("
"$COLUMN_ID INTEGER PRIMARY KEY,"
")",
);}
On another page I have a button, for example IMPORT where I would need to have a function that imports the new database file from Documents and replace the old one and persist. How would I go around doing that the most simple way?
This is function that I thought would work, but I am getting asynchronous errors and a lot more weird errors:
class DbHelper {
Future initDb() async {
final dbPath = await ExtStorage.getExternalStoragePublicDirectory(
ExtStorage.DIRECTORY_DOCUMENTS);
final path = join(dbPath, 'backup.db');
final exist = await databaseExists(path);
if (exist) {
print('db imported');
await openDatabase(path);
}
await openDatabase(path);
}
}

Related

how to initialize SQLite Database variable in my flutter app

I'm a beginner in flutter, i want to use SQlite database using sqflite package in my Flutter App, when I declare the _database variable with this syntax static Database _database; i got a compilation error saying that i must initialize _database, and when i use this syntax static Database? _database;, i have a compilation error under return _database saying A value of type 'Database?' can't be returned from the function 'database' because it has a return type of 'Future<Database>'. and when i put static late Database _database; i have an error in execution saying Error: LateInitializationError: Field '_database' has not been initialized.
my code is
class AnnonceDataBase {
AnnonceDataBase._();
static final AnnonceDataBase instance = AnnonceDataBase._();
static Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await initDB();
return _database;
}
}
I have modified it a bit but it works for you using a singleton to maintain the state of the database
class AnnonceDataBase {
AnnonceDataBase._();
static final AnnonceDataBase _instance = AnnonceDataBase._();
static Database? _database;
factory AnnonceDataBase() => _instance;
Future<Database> get database async {
if (_database != null) return _database!;
_database = await initDB();
return _database!;
}
Future<Database> initDB() async {
String table1 = "CREATE TABLE IF NOT EXISTS table1(id INTEGER PRIMARY KEY,key TEXT NOT NULL UNIQUE,name TEXT,phone NUMERIC)";
String table2 = "CREATE TABLE IF NOT EXISTS table2(id INTEGER PRIMARY KEY,key TEXT NOT NULL UNIQUE,name TEXT,phone NUMERIC)";
String path = await getDatabasesPath();
// Open the database and save the reference.
final Future<Database> database = openDatabase(
// Set the path to the database. Note: Using the `join` function of the
// plugin `path` is best practice to ensure the path is correct
// built for each platform.
p.join(path, 'admin.db'),
// When the database is first created, create a table to store data
onCreate: (db, version) {
db.execute(table1);
return db.execute(table2);
},
// Set the version. This runs the onCreate function and provides a
// path to perform updates and downgrades on the database.
version: 1,
);
return database;
}
}
You can use it like this
#override
void initState() {
AnnonceDataBase._instance.database; //Initialize when loading the application or in the singleton
super.initState();
}
Create a record
Future<void> addData() async {
Database database = AnnonceDataBase._database!;
database.transaction((txn) async {
await txn.rawInsert('INSERT INTO table1(id,key,name,phone) VALUES(?,?,?,?)', ["1", DateTime.now().toString(), "name", "+5555555"]);
});
}
Read all records
Future<void> readData() async {
Database database = AnnonceDataBase._database!;
List<Map> data = await database.rawQuery("SELECT * FROM table1");
debugPrint("data: $data");
}

How can get SQLite date in flutter?

How can get SQLite date in flutter?
In my project, I had used the sqlite and I had written the code, but I don't know how can get data when I need to read it.
class DatabaseHelper {
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
static Database? _database;
Future<Database> get database async => _database ??= await _initDatabase();
Future<Database> _initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, 'user.db');
return await openDatabase(path, version: 1, onCreate: _onCreate);
}
Future _onCreate(Database db, int version) async {
await db
.execute('''CREATE TABLE USER (id INTEGER PRIMARY KEY, badge TEXT)''');
}
Future<List<Grocery>> getGroceries() async {
Database db = await instance.database;
var groceries = await db.query('USER', orderBy: 'badge');
List<Grocery> groceryList = groceries.isNotEmpty
? groceries.map((e) => Grocery.fromMap(e)).toList()
: [];
return groceryList;
}
}
I had written this code and I need to got the badge data. How could I can got it?
The bage data only has one date, it was just recode the notification badge. so anytime was update it.
You can get the data calling the getGroceries() method in initState or using the FutureBuilder widget in flutter.

Why flutter don't detect the tables of my prepopulated sqlite database? (1) no such table

I have a prepopulated database in the assets of my app. The app makes the connection with the database properly, but when I try to make a simple rawQuery like ("Select * FROM empresa") it throw me an exception saying the table doesn't exist.
What can generate this problem and more important, how can I fix it?
This is the code of my class DBHelper. I only make an instance of this class in other page and there is the error.
class DBHelper {
static Database? _db;
Future<Database> get db async => _db ??= await initDB();
initDB() async {
Directory documentDirectory = await getApplicationDocumentsDirectory();
String path = join(documentDirectory.path, "ANUARIO.db");
bool dbExists = await File(path).exists();
if (!dbExists) {
try {
ByteData data = await rootBundle.load(join("assets", "ANUARIO.db"));
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await File(path).writeAsBytes(bytes, flush: true);
} catch (e) {
print(e);
}
}
var theDB = await openDatabase(path);
return theDB;
}
}
u must share ur code to see what go wrong with it
but i think that u create the same data base over every time u run ur function
and for example u must see if there is any database with the same name have been create before and if it create before do not create new one and make query
and u can use this may be helpful
sqflite_ffi.dart

how to avoid safety null

in this class while declaring the constructor Repository i get this error 'Non-nullable instance field '_database' must be initialized.
Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'' i added late but it doesn't work the same error while declaring the static Database _database .
this is the class Repository
import 'package:sqflite/sqflite.dart';
import 'package:todo/repositories/database_connection.dart';
class Repository {
DatabaseConnection _databaseConnection;
Repository() {
_databaseConnection = DatabaseConnection();
}
static Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await _databaseConnection.setDatabase();
return _database;
}
insertData(table, data) async {
var connection = await database;
return await connection.insert(table,data)
}
and this is the DatabaseConnection
class DatabaseConnection {
setDatabase() async {
var directory = await getApplicationDocumentsDirectory();
var path = join(directory.path, 'db_todo_sqflite');
var database =
await openDatabase(path, version: 1, onCreate: _onCreateDatabase);
return database;
}
_onCreateDatabase(Database database, int version) async {
await database.execute(
"CREATE TABLE categories(id INTEGER KEY , name TEXT , descrption TEXT");
}
}
Your database itself is nullable, so you add a ?
static Database? _database;
That makes the _database nullable, but in your getter you are returning a non nullable instance of Database.
The nullable instance would be Database?
Future<Database?> get database async {
...
}
If you are sure that the _database is initialized, and can't be null at that point you return the value, and tell dart that this value is never null.
static Database? _database;
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _databaseConnection.setDatabase();
return _database!;
}
Note the "!" at the return _database!
See also https://dart.dev/null-safety/understanding-null-safety
And https://dart.dev/tools/diagnostic-messages#unchecked_use_of_nullable_value
You are getting an error because
static Database _database is no nullable
Change the code to
static Database? _database
thank all for the response
this how i correct the code
import 'package:sqflite/sqflite.dart';
import 'package:todo/repositories/database_connection.dart';
class Repository {
DatabaseConnection? _databaseConnection;
Repository() {
_databaseConnection = DatabaseConnection();
}
static Database? _database;
Future<Database?> get database async {
if (_database != null) return _database;
_database = await _databaseConnection!.setDatabase();
return _database! ;
}
insertData(table, data) async {
var connection = await database;
return await connection!.insert(table, data);
}
}
You also can use the late modifier:
late DatabaseConnection _databaseConnection;
Just make sure you set this variable before you try to use it.

MissingPluginException(No implementation found for method getDatabasesPath on channel com.tekartik.sqflite)

I am using flutter in vs code. I have got this error when I am connecting to sqflite database.
I have added sqflite,path plugin in pubspec.yaml file. I have tried
flutter clean
flutter run command too but nothing worked.
This is my Database helper method
final databaseName = "notes.db";
final tableName = "notes";
DatabaseHelper._();
static final DatabaseHelper db = DatabaseHelper._();
static Database _database;
final fieldMap = {
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
"title": "TEXT",
"body": "TEXT",
"creation_date": "DATE",
};
Future<Database> get database async {
if (_database != null) return _database;
_database = await initDB();
return _database;
}
initDB() async {
var path = await getDatabasesPath();
var dbPath = join(path, 'notes.db');
// ignore: argument_type_not_assignable
Database dbConnection = await openDatabase(dbPath, version: 1,
onCreate: (Database db, int version) async {
print("executing create query from onCreate callback");
await db.execute(_buildCreateQuery());
});
await dbConnection.execute(_buildCreateQuery());
_buildCreateQuery();
return dbConnection;
}
The values are not getting stored in sqflite databse. It returns null. So what should I do?