javascriptreact-nativesqlitereact-native-cli

Why can I not execute an SQL command on a react-native-sqlite-storage database?


As part of a university project, I am working with a team on a database application in react-native that uses the react-native-sqlite-storage API.

The goal at the moment is to make sure I can execute SQL commands on the database. Unfortunately, when I check the database for whether a table exists or not, I get an error about an unhandled promise rejection caused by the following error:

TypeError: db.executeSql is not a function (it is undefined)

I am not sure why this is. According to this tutorial, I should be able to call the executeSql(sql) function directly on the database object I get from the openDatabase function, and get a value from it.

How do I execute SQL in SQLite using the react-native-sqlite-storage package?

Here is our app so far:

import React from 'react';
import {Text, View} from 'react-native';
import {connectToDatabase, doesTableExist} from './code/DBAPI.js'
import {setupDBReceipts} from './code/DBAPI-receipts.js'
import {setupDBAttachments} from './code/DBAPI-attachments.js'

const App = () => {
    const db = connectToDatabase();
        if(!doesTableExist(db, "Receipts")){
        setupDBReceipts(db);
        setupDBAttachments(db)
        return (
            <View>
                <Text> Welcome to the app. The database has been set up for the first time :) </Text>
            </View>
        );
    }else{
        return (
            <View>
                <Text> Welcome to the app. The database has already been set up :) </Text>
            </View>
        );
    }
    
};

export default App;

And here is part of our database code so far:

import React from 'react';
import {openDatabase, SQLiteDatabase} from "react-native-sqlite-storage";

/**
 * Connect to the App database
 * 
 * @returns a database object
 */
export const connectToDatabase = async() => {
    return openDatabase({name: 'app.db', location: 'default'});
}

/**
 * Sanitises a string. Keep in mind that URIs and URLs may be part of our input fields, so this may be tricky...
 * @param the string input to sanitise
 * @returns the string that is sanitised
 * @alpha Not finished yet, do not use this function!
 */
export const sanitiseString = (input) => {
    return input;
}

/**
 * Tests whether the database contains the given table
 */
export const doesTableExist = async(db, tableName) => {
    tableName = sanitiseString(tableName);
    value = await db.executeSql("SELECT EXISTS (SELECT " + tableName + " FROM sqlite_schema WHERE type='table');");
    return value == 1;
}

p.s. this is my first time writing in react-native and I have almost no javascript experience so any extra pointers are appreciated!


Solution

  • The connectToDatabase and doesTableExist is an Async function that always returns Promise, You have to await or then it.

    Await MDN Documentation

    const App = async () => {
        const db = await connectToDatabase();
        
        if(await doesTableExist(db, "Receipts")){
             // Rest of your code
        } else {
             // Else part
        } 
    }
    

    Then() MDN Documentation

    const App = () => {
        const db = connectToDatabase();
        
        db.then(connection => {
            doesTableExist(connection, "Receipts").then(exist => {
                if (exist) {
                    // if exist
                } else {
                    // else
                }
            });
        });      
    }