Reputation: 1
I have a Database (.db) that I want to use to pre-populate my Android Room Database. But even with many tries and researches, I have the same problem. Here is the error :
Caused by: java.lang.IllegalStateException: Pre-packaged database has an invalid schema: countries(com.example.pays.Pays_DB).
Expected:
TableInfo{name='countries', columns={name=Column{name='name', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, phonecode=Column{name='phonecode', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, shortname=Column{name='shortname', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='countries', columns={}, foreignKeys=[], indices=[]}
For me, the problem is because my database is empty, but it is not. What is the issue?
Here is my code:
Pays_DB.java
@Entity(tableName = "countries")
public class Pays_DB {
@PrimaryKey(autoGenerate = true)
public int id;
@NonNull
public String shortname;
@NonNull
public String name;
@NonNull
public int phonecode;
}
Database.java
@androidx.room.Database(entities = {Pays_DB.class}, version = 2)
public abstract class Database extends RoomDatabase {
public abstract Pays_DAO dao();
}
MainActivity.java
...
public void DBCreate(){
if (db == null){
synchronized (Database.class){
if (db == null){
db = Room.databaseBuilder(this,
Database.class, "countries.db")
.allowMainThreadQueries()
.fallbackToDestructiveMigration()
.createFromAsset("countries.db")
.build();
SupportSQLiteDatabase sdb = db.getOpenHelper().getWritableDatabase();
}
}
}
}
And here is my Database : https://drive.google.com/file/d/1LPB07TQaDuwggs_DJ5QIfYdy6H4Ph-_6/view?usp=sharing
Upvotes: 0
Views: 1334
Reputation: 56938
Your issue is that the table name in the pre-packaged database is named tbl_country. Room is expecting to find a table called countries.
TableInfo{name='countries', columns={}, foreignKeys=[], indices=[]}
is saying that it didn't find a matching table at all as a table MUST have at least one column))You could use:-
@Entity(tableName = "tbl_country")
to overcome this issue (you would have to change Pays_DAO accordingly).
HOWEVER, you would then encounter ongoing issues as Room would still not find what it expects as then column names do not match what Room expects.
That is Room expects a table to exist in the pre-packaged database according to:-
CREATE TABLE IF NOT EXISTS `countries` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `shortname` TEXT NOT NULL, `name` TEXT NOT NULL, `phonecode` INTEGER NOT NULL)
The tbl_country table in your database is defined using :-
CREATE TABLE tbl_country (ID INTEGER PRIMARY KEY AUTOINCREMENT, NOM_PAYS TEXT, NOM_PAYS_SHORT TEXT, POPULATION INTEGER, CAPITALE TEXT)
They are worlds apart.
What you need to do is create a table in the pre-packaged database that matches what room expects (at present the first SQL statement above) and populate that with suitable data. The tbl_country would then be ignored as far as room is concerned.
If you want to actually use the tbl_countries then you additionally need to have a class, annotated with @Entity, that defines the columns as per the tbl_countries table.
e.g.
@Entity(tableName = "tbl_country")
class Country {
@PrimaryKey(autoGenerate = true)
Long ID=null;
String NOM_PAYS;
String NOM_PAYS_SHORT;
Integer POPULATION;
String CAPITALE;
}
Note before rerunning, it would be best to uninstall the App (noting that this deletes the database and thus any data is lost).
Example Fix (just getting it to run successfully)
countries
(id
INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, shortname
TEXT NOT NULL, name
TEXT NOT NULL, phonecode
INTEGER NOT NULL);Here's a screen shot that highlights some of the above
The database via App Inspection is:-
Stage Two - accessing tbl_countries
:-
@Entity(tableName = "tbl_country")
class Country {
@PrimaryKey(autoGenerate = true)
Long ID=null;
String NOM_PAYS;
String NOM_PAYS_SHORT;
Integer POPULATION;
String CAPITALE;
}
ID INTEGER PRIMARY KEY AUTOINCREMENT
i.e. NOT NULL hasn't been specified). When it comes to integer types for the primary key the rules/interpretations are more convoluted.:-
@androidx.room.Database(entities = {Pays_DB.class,Country.class}, version = 2)
:-
@Query("SELECT * FROM tbl_country")
abstract List<Country> getAllCountry();
abstract
:-
DBCreate();
Pays_DAO dao = db.dao();
for(Country c: dao.getAllCountry()) {
Log.d("DBINFO","Country is " + c.NOM_PAYS /* etc */);
}
:-
D/DBINFO: Country is Canada
D/DBINFO: Country is France
D/DBINFO: Country is Islande
D/DBINFO: Country is Japon
D/DBINFO: Country is Sample
D/DBINFO: Country is Sampl988
Upvotes: 1