It was okay until I tried to upgrade it to add one more column to it - sql

I was learning to use sqlflite in my flutter application..when i upgraded it for the first time it worked absolutely fine..but then I wanted to add one more column but i actually don't know query for that.. so I tried the query shown below, but when I try to save my data, I get this error:
E/SQLiteLog(22556): (1) table tbl_employee has no column named employee_gender
I/flutter (22556): DatabaseException(table tbl_employee has no column named employee_gender (code 1 SQLITE_ERROR): , while compiling: INSERT OR REPLACE INTO tbl_employee (employee_name, employee_Student, employee_depertment, employee_DOB, employee_gender) VALUES (?, ?, ?, ?, ?)) sql 'INSERT OR REPLACE INTO tbl_employee (employee_name, employee_Student, employee_depertment, employee_DOB, employee_gender) VALUES (?, ?, ?, ?, ?)' args [Adrita, teacher, CMT, 19/00/2020, 2]}
This is my database class:
class DBHelper{
static final String CREATE_TABLE_EMPLOYEE = '''
create table $TABLE_EMPLOYEE(
$COL_EMP_ID integer primary key autoincrement,
$COL_EMP_NAME text not null,
$COL_EMP_PROFESSION text not null,
$COL_EMP_DEPARTMENT text not null
)
''';
static Future<Database> open() async{// to initialize data we used this method
final dbpath = await getDatabasesPath();//directory
final path = Path.join(dbpath,'employee.db');//main Path
return openDatabase(path,version: 3,onCreate: (db, version) async{
await db.execute(CREATE_TABLE_EMPLOYEE);
}, onUpgrade: (db, oldVersion, newVersion) async{
if(newVersion == 2){
db.execute(''' alter table $TABLE_EMPLOYEE add column $COL_EMP_DOB text ''');
}
if(newVersion == 3){
db.execute('''alter table $TABLE_EMPLOYEE add column $COL_RADIO_BUTTON integer ''');
}
},);
}
static Future<int> insertEmployee(String table, Map<String, dynamic> map) async {// insert method
final db = await open();
return await db.insert(table, map, conflictAlgorithm: ConflictAlgorithm.replace);
}
static Future<int> updateEmployee(EmployeeTeacherModel employeemodel) async{
final db = await open();
return await db.update(TABLE_EMPLOYEE, employeemodel.toMap(), where: '$COL_EMP_ID = ?', whereArgs: [employeemodel.id]);
}
static Future<int> DeleteEmployee(int id) async{
final db = await open();
return await db.delete(TABLE_EMPLOYEE,where: '$COL_EMP_ID = ?', whereArgs: [id]);
}
static Future<List<EmployeeTeacherModel>> getAllEmployees() async{
final db = await open();
final List<Map<String, dynamic>> map = await db.query(TABLE_EMPLOYEE, orderBy: COL_EMP_NAME);
return List.generate(map.length, (index){
return EmployeeTeacherModel.fromMap(map[index]);
});
}
static Future<EmployeeTeacherModel> getEmployeeByid(int id) async{
final db = await open();
final List<Map<String, dynamic>> emps = await db.query(TABLE_EMPLOYEE, where: '$COL_EMP_ID=?',whereArgs: [id]);
if(emps.length>0){
return EmployeeTeacherModel.fromMap(emps.first);
}
return null;
}
}
Here's the Model class:
final String TABLE_EMPLOYEE = "tbl_employee";
final String COL_EMP_ID = "employee_id";
final String COL_EMP_NAME = "employee_name";
final String COL_EMP_DEPARTMENT = "employee_depertment";
final String COL_EMP_PROFESSION = "employee_Student";
final String COL_EMP_DOB = "employee_DOB";
final String COL_RADIO_BUTTON = "employee_gender";
class EmployeeTeacherModel {
int id;
String name;
String depertment;
String Dob;
String profession;
int gender;
EmployeeTeacherModel({this.id, this.name, this.depertment, this.profession, this.Dob, this.gender});
Map<String,dynamic> toMap(){//method to insert data into database
var map = <String, dynamic>{//method
COL_EMP_NAME : name,
COL_EMP_PROFESSION: profession,
COL_EMP_DEPARTMENT: depertment,
COL_EMP_DOB: Dob,
COL_RADIO_BUTTON: gender,
};
if(id !=null){
map[COL_EMP_ID] = id;
}
return map;
}
EmployeeTeacherModel.fromMap(Map<String,dynamic> map){//named constructor to return emoloyee model obj
id = map[COL_EMP_ID];
name = map[COL_EMP_NAME];
profession = map[COL_EMP_PROFESSION];
depertment = map[COL_EMP_DEPARTMENT];
Dob = map[COL_EMP_DOB];
gender = map[COL_RADIO_BUTTON];
}
#override
String toString() {
return 'EmployeeTeacherModel{id: $id, name: $name, depertment: $depertment, Dob: $Dob, profession: $profession, gender: $gender}';
}
}

Related

DatabaseException(FOREIGN KEY constraint failed (code 787)) sql 'INSERT OR FAIL INTO

I'm having problem with foreign key while adding a new habit and inserting it's data in db and I don't really know why, because everything seems right. the error is:
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: DatabaseException(FOREIGN KEY constraint failed (code 787)) sql 'INSERT OR FAIL INTO Habits (userId, text, emoji, period, startPeriod) VALUES (?, ?, ?, ?, NULL)' args [1, habit, ☺, [1,2,3,4,5,6,7]]
error accrued here:
class DataService {...
late final Database db;
Future<void> addHabit(Habit newHabit) async {
final newHabitId = await HabitsDb.createHabit(db, newHabit);//error accrued here
final days = (await HabitsDb.getAllDays(db)).map((e) => Day.fromDb(e, []));
for (final day in days) {
if (newHabit.startPeriod != null &&
newHabit.startPeriod!.compareTo(day.date) > 0) {
continue;
}
if (newHabit.period.contains(day.date.weekday)) {
await HabitsDb.createHabitDay(
db, day.date.millisecondsSinceEpoch, newHabitId);
}
}
await _reloadDaysInCache();
_loadHabits();
} ...}
then:
class HabitsDb{...
static Future<int> createHabit(Database db, Habit habit) async {
return db.insert(HabitsTable.tableName, await habit.toDb(),
conflictAlgorithm: ConflictAlgorithm.fail);
}...}
model:
class Habit {
late final int id;
late final int userId;
late String text;
late String emoji;
late final List<int> period;
late final DateTime? startPeriod;
...
Future<Map<String, dynamic>> toDb() async {
print(text);
print(userId);
return {
//HabitsTable.id: id,
HabitsTable.userId: userId,
HabitsTable.text: text,
HabitsTable.emoji: emoji,
HabitsTable.period: jsonEncode(period),
HabitsTable.startPeriod: startPeriod?.millisecondsSinceEpoch
};
}...}
creating table:
class HabitsTable {
static const String tableName = 'Habits';
static const String id = 'id';
static const String userId = 'userId';
static const String text = 'text';
static const String emoji = 'emoji';
static const String period = 'period';
static const String startPeriod = 'startPeriod';
static const String createQuery = '''
CREATE TABLE IF NOT EXISTS $tableName (
$id INTEGER PRIMARY KEY AUTOINCREMENT,
$userId INTEGER NOT NULL,
$text TEXT NOT NULL,
$emoji TEXT NOT NULL,
$period TEXT NOT NULL,
$startPeriod INTEGER,
FOREIGN KEY($userId) REFERENCES ${UsersTable.tableName}(id));''';
}
if more code is needed you can check https://github.com/sarasoltan/habit_tracker
plz help if you know how to solve this error.

null userId, Unhandled Exception: Null check operator used on a null value

I have an issue with userId in Habits table. it is a foreign key from id in Users Table. but I keep getting the error "Unhandled Exception: Null check operator used on a null value " from AddHabitDialogController class.
obviously userId should never be null. where is the issue? how can I solve it?
if more code is needed you can check : https://github.com/sarasoltan/habit_tracker
Users Table:
class UsersTable {
static const String tableName = 'Users';
static const String id = 'id';
static const String email = 'email';
static const String createQuery = '''
CREATE TABLE IF NOT EXISTS $tableName (
$id integer primary key autoincrement,
$email text not null unique);''';
#override
String toString() => 'Person, ID: $id, email: $email';
#override
bool operator ==(covariant Users other) => id == other.id;
#override
int get hashCode => id.hashCode;
}
Habits table:
class HabitsTable {
static const String tableName = 'Habits';
static const String id = 'id';
static const String userId = 'userId';
static const String text = 'text';
static const String emoji = 'emoji';
static const String period = 'period';
static const String startPeriod = 'startPeriod';
static const String createQuery = '''
CREATE TABLE IF NOT EXISTS $tableName (
$id integer primary key autoincrement,
$userId integer not null,
$text text not null,
$emoji text not null,
$period text not null,
$startPeriod integer,
FOREIGN Key($userId) REFERENCES ${UsersTable.tableName}(${UsersTable.id}));''';
User model class:
class Users {
late final int id;
late String email;
Users({
required this.id,
required this.email,
});
Users.fromDb(Map<String, dynamic> map) {
id = map[UsersTable.id];
email = map[UsersTable.email];
}
}
Habit model class:
class Habit {
late final int id;
late final int userId;
late String text;
late String emoji;
late final List<int> period;
late final DateTime? startPeriod;
Habit(
{
//required this.id,
required this.userId,
required this.text,
required this.emoji,
required this.period,
this.startPeriod});
Habit.fromDb(Map<String, dynamic> map) {
id = map[HabitsTable.id] as int;
userId = map[HabitsTable.userId] as int;
text = map[HabitsTable.text] as String;
emoji = map[HabitsTable.emoji];
period = (jsonDecode(map[HabitsTable.period]) as List<dynamic>)
.map((e) => e as int)
.toList();
if (map[HabitsTable.startPeriod] != null) {
startPeriod =
DateTime.fromMillisecondsSinceEpoch(map[HabitsTable.startPeriod]);
} else {
startPeriod = null;
}
}
Map<String, dynamic> toDb() {
Users? owner;
return {
//HabitsTable.id: id,
HabitsTable.userId: owner!.id,
HabitsTable.text: text,
HabitsTable.emoji: emoji,
HabitsTable.period: jsonEncode(period),
HabitsTable.startPeriod: startPeriod?.millisecondsSinceEpoch
};
}
AddHabitDialogController(error):
class AddHabitDialogController {
Users? owner;
//final user = FirebaseAuth.instance.currentUser;
//String get owneruserId => AuthService.firebase().currentUser!.id;
final List<bool> period = [true, true, true, true, true, true, true];
int? id;
int? userId;
String? emoji;
String? text;
StartPeriod startPeriod = StartPeriod.none;
final StreamController<bool> _addBtnEnabledCtrl = StreamController();
Stream<bool> get addBtnEnabled => _addBtnEnabledCtrl.stream;
final StreamController<StartPeriod> _selectedStartPeriodCtrl =
StreamController();
Stream<StartPeriod> get selectedStartPeriod =>
_selectedStartPeriodCtrl.stream;
final StreamController<bool> _loadingCtrl = StreamController();
Stream<bool> get loading => _loadingCtrl.stream;
void changePeriodValue(int index, bool newValue) {
period[index] = newValue;
_updateAddBtnEnabledState();
}
void changeTextValue(String newValue) {
text = newValue;
_updateAddBtnEnabledState();
}
void changeEmojiValue(String newEmoji) {
emoji = newEmoji;
_updateAddBtnEnabledState();
}
void changeStartPeriod(StartPeriod newValue) {
startPeriod = newValue;
_selectedStartPeriodCtrl.add(startPeriod);
}
Future<void> addHabit(BuildContext context) async {
_loadingCtrl.add(true);
final dataService = GetIt.I.get<DataService>();
final List<int> forPeriod = [];
for (int i = 0; i < period.length; i++) {
if (period[i]) {
forPeriod.add(i + 1);
}
}
final habit = Habit(
//id: id!,
userId: owner!.id, //error from here
emoji: emoji!,
text: text!,
period: forPeriod,
startPeriod: _calculateStartPeriodDateTime());
await dataService.addHabit(habit);
_loadingCtrl.add(false);
Navigator.of(context).pop();
}
void _updateAddBtnEnabledState() {
_addBtnEnabledCtrl.add((text?.isNotEmpty ?? false) &&
(emoji?.isNotEmpty ?? false) &&
period.where((e) => e).isNotEmpty);
}
DateTime? _calculateStartPeriodDateTime() {
final now = DateTime.now();
switch (startPeriod) {
case StartPeriod.today:
return DateTime(now.year, now.month, now.day);
case StartPeriod.thisMonth:
return DateTime(now.year, now.month);
case StartPeriod.thisYear:
return DateTime(now.year);
case StartPeriod.none:
default:
return null;
}
}
void dispose() {
_addBtnEnabledCtrl.close();
_loadingCtrl.close();
_selectedStartPeriodCtrl.close();
}
}
enum StartPeriod { none, today, thisMonth, thisYear }
Because the local variable of AddHabitDialogController owner can't be referenced before it is declared
class AddHabitDialogController {
Users? owner; // -> you did not assign this owner?

MediaStore select query returns only one row

I'm trying to develop music player, I've made a loader and adapter for my data retreiving from mediastore, but when I call query from my app it only returns one row, I don't know wat's wrong with my code, would u help me fixing that problem?
That's my loader which should return a list I'll use in another place
public static List<Song> getAllArtistSongs(Context context, long artist_id){
List<Song> ArtistSongList = new ArrayList<>();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = new String[]{
"_id",
"title",
"album_id",
"album",
"artist",
"duration",
"track"
};
String sortorder = MediaStore.Audio.Media.DEFAULT_SORT_ORDER;
String selection = "is_music=1 and artist_id="+artist_id;
Cursor cursor = context.getContentResolver().query(uri, projection, selection, null, sortorder);
assert cursor != null;
if (cursor.moveToFirst()) {
do {
int trackNumber = cursor.getInt(6);
while (trackNumber >= 1000) {
trackNumber -= 1000;
}
Long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));
String title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
Long albumid = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
String albumname = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
String artistname = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
int duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
ArtistSongList.add(new Song(id, title, albumid, albumname, artist_id, artistname, duration, trackNumber));
} while (cursor.moveToNext());
cursor.close();
}
return ArtistSongList;
}
And this is the adapter which I use to bind to a recyclerview
public void onBindViewHolder(#NonNull VH holder, int position) {
Song song = artistSongList.get(position);
if(song!=null){
holder.ttv.setText(song.title);
holder.dtv.setText(song.artistName);
int trackN = song.trackNumber;
if(trackN==0){
holder.ntv.setText("_");
}else holder.ntv.setText(String.valueOf(trackN));
}
}
And this is where I call the query func
private void setupAlbumList() {
System.out.println(artistId);
songList = ArtistSongLoader.getAllArtistSongs(getActivity(), artistId);
adapter = new ArtistSongAdapter(getActivity(), songList);
recy.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL));
recy.setAdapter(new ArtistSongAdapter(getActivity(), songList));
}
Thx in advance for helping
My example to retrieve all tracks:
private final String track_id = MediaStore.Audio.Media._ID;
private final String track_no = MediaStore.Audio.Media.TRACK;
private final String track_name = MediaStore.Audio.Media.TITLE;
private final String artist = MediaStore.Audio.Media.ARTIST;
private final String artist_id = MediaStore.Audio.Media.ARTIST_ID;
private final String duration = MediaStore.Audio.Media.DURATION;
private final String album = MediaStore.Audio.Media.ALBUM;
private final String composer = MediaStore.Audio.Media.COMPOSER;
private final String year = MediaStore.Audio.Media.YEAR;
private final String path = MediaStore.Audio.Media.DATA;
private final String date_added = MediaStore.Audio.Media.DATE_ADDED;
public Cursor getAllTracks(Context context) {
// gets all tracks
if (context != null) {
ContentResolver cr = context.getContentResolver();
final String[] columns = {track_id, track_no, artist, track_name,
album, duration, path, year, composer};
return cr.query(uri, columns, null, null, null);
} else {
return null;
}
}
then you have
String selection = "is_music=1"
first, you do not need is_music=1. For multiple tracks you of course need more than 1 track by the same artist
The adapter is irrelevant, the query does the selection
To return albums for an artist
public Cursor getArtistsAlbumcursor(Context context, String artistId) {
ContentResolver cr = context.getContentResolver();
final String _id = MediaStore.Audio.Media._ID;
final String album_id = MediaStore.Audio.Media.ALBUM_ID;
final String artistid = MediaStore.Audio.Media.ARTIST_ID;
final String[] columns = {_id, album_id, artistid};
if (artistId != null) {
String where = artistid + " =?";
String[] aId = {artistId};
return cr.query(uri, columns, where, aId, null);
} else {
return null;
}
}

int isn't a type

on passing the version to the on create method and integer(int) of the id that i want to fetch from the database,i get an error saying "int isn't a type"error Image
class NewsDbProvider {
Database db;
int() async {
Directory documentsDirectory =await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, "items.db");
db = await openDatabase(
path,
version: 1,
onCreate: (Database newDb,int version){
newDb.execute("""
CREATE TABLE Items
(
)
""");
}
);
}
fetchItem(int id) async{
db.query(
"Items",
columns: null,
where: 'id = ?',
whereArgs: {id},
);
}
}
You named a method of NewsDbProvider as int, which is why the keyword isn't being recognised anymore. Try renaming it.

Rhino Mock and Method Not Returning Correct Value

Does anyone know why UsernameExists wont return True. I must have my syntax messed up somewhere.
[TestMethod()]
public void GenerateUsername_AppendTwoCharacters_ReturnUsernameWithTwoAppendedCharacters()
{
var usersRepository = MockRepository.GenerateStub<IUsersRepository>();
var target = new StudentsService(null, null, usersRepository, null, null, null, null);
usersRepository.Expect(q => q.UsernameExists("", null)).Return(true);
var actual = target.GenerateUsername("test", "student", "280000");
Assert.AreEqual("A", actual);
}
public string GenerateUsername(string firstName, string lastName, string studentNumber)
{
var originalusername = new StudentUsernameGenerator(firstName, lastName, studentNumber).Generate(2, 2, 4);
var username = originalusername;
if (!string.IsNullOrWhiteSpace(username))
{
decimal maxCharacters = 26;
var counter = 0;
var overflow = 1;
while (_usersRepository.UsernameExists(username, null))
{
counter++;
if (counter > maxCharacters)
{
overflow++;
counter = 1;
}
username = GetCharacterPaddingForDuplicateUsername(counter, overflow, originalusername);
}
}
return username;
}
I had to add IgnoreArguments
usersRepository.Stub(q => q.UsernameExists("", null)).IgnoreArguments().Return(true);