Trouble loading existing database.

Really at my wits end here trying to load an existing database into expo SQLite. The example project included w/ the expo bundles doesn’t show an example of SQLite being loaded from a pre-existing DB, nor does the boilerplate code shown on the expo-sqlite docs work as given.

Currently, I’m trying to rework the example project to load from a pre-existing DB rather than one generated the first time the app loads. So aside from calling the snippet below from within a useEffect function my code is exactly the same as the example.

async function openDatabase(pathToDatabaseFile: string): SQLite.WebSQLDatabase {
  if (!(await FileSystem.getInfoAsync(FileSystem.documentDirectory + 'SQLite')).exists) {
    await FileSystem.makeDirectoryAsync(FileSystem.documentDirectory + 'SQLite');
  }
  await FileSystem.downloadAsync(
    Asset.fromModule(require(pathToDatabaseFile)).uri,
    FileSystem.documentDirectory + 'SQLite/myDatabaseName.db'
  );
  return SQLite.openDatabase('myDatabaseName.db');
}

Simply copying the snippet doesn’t seem to be working for me and the particular sequence “(pathToDatabaseFile: string): SQLite.WebSQLDatabase” seems to be an issue. Left as is my code will reply “App.js: App.js:Invalid call at line 15: require(pathToDatabaseFile)”

If I were to change the “pathToDatabaseFile” to refer to a string that actually was the static path of the db file I am then given the same error.

I’ve found all kinds of similar links to functions but never the functions implementation en-situ. For example one, to be called in componentDidMount that seemed promising:

  async openExistingDatabase() {
    const internalDbName = "dbInStorage.db"
    const sqlDir = FileSystem.documentDirectory + "SQLite/";
    if (!(await FileSystem.getInfoAsync(sqlDir + internalDbName)).exists) {
        await FileSystem.makeDirectoryAsync(sqlDir, {intermediates: true});
        const asset = Asset.fromModule(require("../assets/db/sqlite3.db"));
        await FileSystem.downloadAsync(asset.uri, sqlDir + internalDbName);
    }
    this.database = SQLite.openDatabase(internalDbName);
}

However this gives the common error:

None of these files exist:
  * sqlite3.db
  * ../assets/db/sqlite3.db/index(.native|.ios.expo.ts|.native.expo.ts|.expo.ts|.ios.expo.tsx|.native.expo.tsx|.expo.tsx|.ios.expo.js|.native.expo.js|.expo.js|.ios.expo.jsx|.native.expo.jsx|.expo.jsx|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx|.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json)

And yes I already made the changes to my metro.config.js.

Most of the topics asking the same question are just left without answer, which is super ironic because the expo-sqlite documentation has NO full working examples of a preloaded SQLite database. Which strikes me as incredibly ironic because from my experience with SQL databases, prepopulation is the exception rather than the rule. It’s a bit of a glaring omission. Am I to assume that creating AND seeding the DB the first time an app launches, rather than having it already existing is best practice when using expo?

I’ve been working on this for 1 week as well, trying both ‘expo-sqlite’ and ‘react-native-sqlite-storage’ and I finally made it work on my dictionary app by editing the code on this expo forum: Cannot read from Bundled Database

That openDatabase code on Expo didn’t work on my app either.

Prior to this, I put the SQL data into ./asset/db/

import * as SQLite from 'expo-sqlite';
import * as FileSystem from 'expo-file-system';
import {Asset} from 'expo-asset';
import { openDatabase } from 'expo-sqlite';

export class DictionaryScreen extends React.Component{
    state = {inputValue: "Look up the word"};

    _handleTextChange = inputValue => {
        this.setState({inputValue});
    };

    async openDatabase() {
        if (!(await FileSystem.getInfoAsync(FileSystem.documentDirectory + 'SQLite')).exists) {
          await FileSystem.makeDirectoryAsync(FileSystem.documentDirectory + 'SQLite');
        }
        await FileSystem.downloadAsync(
          Asset.fromModule(require('/Users/***/***/assets/db/test.db')).uri,
          FileSystem.documentDirectory + 'SQLite/test.db'
        );
        return SQLite.openDatabase('test.db');
    }

    db = openDatabase('test.db');

    searchWord() {
        this.db.transaction((tx) => {
        tx.executeSql(
            'SELECT word, mean FROM items WHERE word LIKE "%?%";',
            [this.state.inputValue],
            () => {
                console.log("success");
            },
            () => {
                console.log("failed");
            }
            
         );
        });
    };
    
    render() {
        return(
            <SafeAreaView style={styles.container}>
                <View style={styles.searchContainer}>
                    <MaterialCommunityIcons name="text-search" size={20}/>
                    <TextInput
                        style={styles.input}
                        onChangeText={this._handleTextChange}
                        onSubmitEditing={(inputValue) => this.searchWord(inputValue)}
                        value={this.inputValue}
                        placeholder='Look up the word'
                        keyboardType="default"
                    />
                <StatusBar style='light' />
                </View>
            </SafeAreaView>
        );
        }
    }

Make sure all props are defined.

Hope this will help you.

Hi,
I am getting an error, None of these file exists

The problem is your metro configuration, it requires you to stop and restart the application

Same error still. I am using "expo": "~41.0.1","expo-asset": "~8.3.1", "expo-file-system": "~11.0.2", "metro-config": "^0.59.0",

My app.json has "packagerOpts": { "config": "metro.config.js" }

And my metro.config.js has `const { getDefaultConfig } = require("@expo/metro-config");

const defaultConfig = getDefaultConfig(__dirname);

defaultConfig.resolver.assetExts.push(“db”);

module.exports = defaultConfig;
`

Super stumped, because I’m following the expo docs and it seems like nothing is wrong?

EDIT: Apologies folks, seemed like my metro.config.js was actually 'metro.config.js ’ so there was a typo. All works now.

Hi, I having a problem, please help me :slight_smile:

metro.config.ts

const { getDefaultConfig } = require('@expo/metro-config');

const defaultConfig = getDefaultConfig(__dirname);

module.exports = {
  resolver: {
    assetExts: [...defaultConfig.resolver.assetExts, 'db'],
  },
};

SQLiteDatabase.ts

import * as SQLite from 'expo-sqlite';
import * as FileSystem from 'expo-file-system';
import { Asset } from 'expo-asset';

async function openDatabase() {
  console.log('Bruno')
  if (!(await FileSystem.getInfoAsync(FileSystem.documentDirectory + 'SQLite')).exists) {
    await FileSystem.makeDirectoryAsync(FileSystem.documentDirectory + 'SQLite');
  }
  await FileSystem.downloadAsync(
    Asset.fromModule(require('../../assets/SQLite/PocketNewTestament.db')).uri,
    FileSystem.documentDirectory + 'SQLite/PocketNewTestament.db'
  );
  return SQLite.openDatabase('PocketNewTestament.db');
}

const db = openDatabase();
export default db;

app.json

{
  "expo": {
    "name": "Mobile",
    "packagerOpts": {
      "config": "metro.config.js"
    },
    "slug": "Mobile",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "updates": {
      "fallbackToCacheTimeout": 0
    },
    "assetBundlePatterns": [
      "**/*"
    ],
    "ios": {
      "supportsTablet": true
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#FFFFFF"
      }
    },
    "web": {
      "favicon": "./assets/favicon.png"
    }
  }
}

My Database

Error

INFO
09:45
Starting Metro Bundler
ERROR
09:46
Building JavaScript bundle: error
ERROR
09:46
Unable to resolve module ../../assets/SQLite/PocketNewTestament.db from E:\Programação\Github\SPNT-SajermannPocketNewTestament\Mobile\src\services\sqlite\SQLiteDatabase2.ts: 

None of these files exist:
  * src\assets\SQLite\PocketNewTestament.db(.native|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json)
  * src\assets\SQLite\PocketNewTestament.db\index(.native|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json)
  10 |   }
  11 |   await FileSystem.downloadAsync(
> 12 |     Asset.fromModule(require('../../assets/SQLite/PocketNewTestament.db')).uri,
     |                               ^
  13 |     FileSystem.documentDirectory + 'SQLite/PocketNewTestament.db'
  14 |   );
  15 |   return SQLite.openDatabase('PocketNewTestament.db');

The error is most likely due to how you wrote the uri of your database. Make sure the uri follows the actual dependency tree properly. Maybe you might have accidentally omitted /src/ or something else.

Do you have an example in github for me? I really need initialize app with database pre-populated :’(