react-native-sqlite-storage icon indicating copy to clipboard operation
react-native-sqlite-storage copied to clipboard

[ios] app doesn't find pre-populated database

Open mjstelly opened this issue 4 years ago • 5 comments

Based on the output here, can someone advise me what I am doing wrong?

I followed the steps in the doc to use a pre-populated database for ios. I have no idea why the app is creating and using an identically-named database file.

Assuming all other setup is correct, the file path is <root>/www/appData.sqlite Screen Shot 2020-06-15 at 2 18 27 PM

I have my config

const dbConfig = {
  name: 'appData.sqlite',
  createFromLocation: 1, //ios only
};

I have 2 callbacks

  onSuccess = () => {
    console.log('========= DB opened successfully ========');
  };

  onError = () => {
    console.log('========= Error opening db ========');
  };

I have two rows of data

partner_id,partner_name,icon,color,text_color
1,ferguson,AppImages.badgeFerguson,colors.ferguson,colors.white05
2,ecobee,AppImages.badgeFerguson,colors.ecobee,colors.white05

I have a function to fetch the data

  async getPartners() {
    const partners = await this.database.executeSql(queries.fetchPartners);

    return partners[0].rows.raw();
  }
}

using the following query SELECT * FROM partners;

And I have the actual call this.database = await SQLite.openDatabase(dbConfig, this.onSuccess(), this.onError());

Expected Behavior

Given this setup, I would expect that

  1. either the onsuccess or onerror message would display
  2. two pre-existing rows would output.

Current Behavior

What actually happens Both the success and error messages display

Promise based runtime ready
========= DB opened successfully ========
========= Error opening db ========

Some unknown appData.sqlite file is opened

OPEN database: appData.sqlite
SQLite.open({"name":"appData.sqlite","createFromLocation":1,"dblocation":"nosync","assetFilename":"1"})
new transaction is waiting for open operation
Built path to pre-populated DB asset from app bundle www subdirectory: /Users/michaelstelly/Library/Developer/CoreSimulator/Devices/23EA4039-E854-4FF6-B296-03E1BA488F1A/data/Containers/Bundle/Application/368707F9-DD7F-40EB-A6A0-6326D2BF12DF/HomeeProvider.app/www/appData.sqlite
target database location: nosync
Opening db in mode READ_WRITE, full path: /Users/michaelstelly/Library/Developer/CoreSimulator/Devices/23EA4039-E854-4FF6-B296-03E1BA488F1A/data/Containers/Data/Application/3178FFD8-7A73-4030-AA63-B07CDEB4E633/Library/LocalDatabase/appData.sqlite
Database opened
Good news: SQLite is thread safe!
DB opened: appData.sqlite

And when I output the partners table to a console table, I get 2 rows added from inside that app.

┌─────────┬──────┬───────┐
│ (index) │  id  │ name  │
├─────────┼──────┼───────┤
│    0    │ null │ 'PED' │
│    1    │ null │ 'PED' │
└─────────┴──────┴───────┘

Your Environment

  • React Native SQLite Storage Version used: "react-native-sqlite-storage": "^5.0.0",
  • React Native version used:
    "react": "16.11.0",
    "react-native": "0.62.2",
  • Operating System and version (simulator or device): ios 13.4.1
  • IDE used: Visual Studio Code

mjstelly avatar Jun 15 '20 20:06 mjstelly

this.database = await SQLite.openDatabase(dbConfig, this.onSuccess(), this.onError());

should it not be just a function pointer ?

this.database = await SQLite.openDatabase(dbConfig, this.onSuccess, this.onError);

you are invoking callbacks...you are supposed to pass them in...

andpor avatar Jun 15 '20 20:06 andpor

the module will only create a database from your provided database once. It creates a copy in well defined location - see documentation. The location is quite frankly printed in your output: /Users/michaelstelly/Library/Developer/CoreSimulator/Devices/23EA4039-E854-4FF6-B296-03E1BA488F1A/data/Containers/Data/Application/3178FFD8-7A73-4030-AA63-B07CDEB4E633/Library/LocalDatabase/appData.sqlite

Once that database is created, module will no longer use your input database as template until you delete that database.

andpor avatar Jun 16 '20 09:06 andpor

should it not be just a function pointer?

You are correct. I obviously needed sleep. After looking at the same code for 8 hours, I got lost in the weeds.

Once that database is created, module will no longer use your input database as template until you delete that database.

Ok. I get that once created there's no need to recreate. However, I'm missing is the API doc. Am I simply not finding it? The README says how to create and open the database, but I need to know how to check for exists(), isOpen() or !isClosed(), etc. Where are the methods, properties, and functions documented? That would go a long way in helping me resolve my own issues.

mjstelly avatar Jun 16 '20 11:06 mjstelly

Why not did you save the result of the query into a state variable?

jcabrerazuniga avatar Nov 18 '20 22:11 jcabrerazuniga

Incase this can help someone avoid stressful days

For me, there was a little bit of subtlety getting this to work on iOS as I kept experiencing the infamous "no such table found" error. I assumed that all I had to do was create a www directory under my project through the file system and it would all work. I created the directory and placed my sqlite db there and verified it in the project viewer in Xcode. However, it did not copy my database into /Users..../Library/Developer/CoreSimulator/Devices/MyApp.app/HASH-ID/Library/LocalDatabase/my-sqlite-db.db

I only discovered the source of this issue when I used Xcode to step through the source code of react-native-sqlite-storage/platforms/ios/SQLite.m around line #159 which starts with

RCT_EXPORT_METHOD(open: (NSDictionary *) options success:(RCTResponseSenderBlock)success error:(RCTResponseSenderBlock)error)

"Step 3 - Add file to project in XCode, right click on the main folder and select Add Files to 'your project name"

in https://github.com/andpor/react-native-sqlite-storage is very important. Use Xcode to add the folder.

Good luck. Osupa.

osupa avatar Dec 21 '21 23:12 osupa