在react-native中打开预先填充的SQLite数据库,在哪里放置数据库?

时间:2018-02-28 16:46:55

标签: ios sqlite react-native

我正在遵循将现有数据库导入我的应用程序的说明 (对于IOS):https://www.npmjs.com/package/react-native-sqlite

在myProject目录中创建了www文件夹,将myDataBase放在那里 添加了xcode文件夹。

这是我的src代码,用于打开它并进行查询:

import SQLite from 'react-native-sqlite-storage'

function errorCB(err) {
  console.log("SQL Error: " + err);
}

function successCB() {
  console.log("SQL executed fine");
}

function openCB() {
  console.log("Database OPENED");
}

console.log('database.js')

var db = null;

export function openDB() {
// var db = SQLite.openDatabase("test.db", "1.0", "Test Database", 200000, openCB, errorCB);
db = SQLite.openDatabase({name : "words", createFromLocation : 1}, openCB,errorCB);

}

export function getWord(str) {
  db.transaction((tx) => {
    tx.executeSql("SELECT * FROM words", [], (tx, results) => {
        console.log("Query completed");

        // Get rows with Web SQL Database spec compliance.

        var len = results.rows.length;
        console.log('len' + len)
        for (let i = 0; i < len; i++) {
          let row = results.rows.item(i);
          console.log(`word: ${row.str}, Dept Name: ${row.smth}`);
        }

        // Alternatively, you can use the non-standard raw method.

        /*
          let rows = results.rows.raw(); // shallow copy of rows Array

          rows.map(row => console.log(`Employee name: ${row.name}, Dept Name: ${row.deptName}`));
        */
      });
  });
}

我得到了:

Built path to pre-populated DB asset from app bundle www subdirectory: /Users/mac/Library/Developer/CoreSimulator/Devices/06420F74-0E1C-47C1-BCAC-5D3574577349/data/Containers/Bundle/Application/75EE8E9A-276F-402F-982A-DBF30DE80802/MyApp.app/www/words
RCTLog.js:48 target database location: nosync
RCTLog.js:48 Opening db in mode READ_WRITE, full path: /Users/mac/Library/Developer/CoreSimulator/Devices/06420F74-0E1C-47C1-BCAC-5D3574577349/data/Containers/Data/Application/67D2451F-3D72-4B82-AC90-AD6DB9A82566/Library/LocalDatabase/words

Database opened
RCTLog.js:48 Good news: SQLite is thread safe!
dataBase.js:13 Database OPENED
RCTLog.js:48 open cb finished ok
sqlite.core.js:475 Error handler not provided:  {message: "no such table: words", code: 5}
sqlite.core.js:572 warning - exception while invoking a callback: {"code":5}

不知道这个错误的原因是什么?
我已经在DB浏览器中检查了SQLite数据库是否正确,并且表中存在“单词”并且其中包含行 我为db文件尝试了不同的名称:'words','words.db','words.sqlite'没有任何帮助。

我正在从控制台运行我的应用程序:

react-native run-ios

2 个答案:

答案 0 :(得分:1)

SQLite.openDatabase({name:"testDB.sqlite3", createFromLocation:1,location:'Library'})

这解决了我的问题。 testDB.sqlite3文件大小为24 MB。 testDB.sqlitetestDB.db无效,但是testDB.sqlite3有效。

答案 1 :(得分:0)

我在这里建立了一个存储库,希望它可以帮助您

import BaseModule from '../baseModule';
import * as SQLite from 'expo-sqlite';
import * as MediaLibrary from 'expo-media-library';
import * as FileSystem from 'expo-file-system';
import * as Permissions from 'expo-permissions';
import DetaliItemsSettings from '../detaliItemSettings';
import ChapterSettings from '../chapterSettings';
import httpClient from '../http';

export type NovelReaderSettingsType = (items: BaseModule) => void;
export type Find = (foundItems: BaseModule[]) => void;
export default class Repository {
  static dbIni: Boolean;
  databaseName: string;
  constructor() {
    this.databaseName = 'test.db';
  }

  importSettings = async (uri: string) => {
    try {
      const {status} = await Permissions.askAsync(Permissions.MEDIA_LIBRARY);
      if (status === 'granted') {
        var json = await FileSystem.readAsStringAsync(uri, {encoding: 'utf8'});
        if (json) console.log(json);
        var item = JSON.parse(json) as {
          applicationSettings: any;
          items: DetaliItemsSettings[];
        };
        var appSettings = await this.where('ApplicationSettings');
        if (item.applicationSettings) {
          item.applicationSettings = httpClient.cloneItem(
            appSettings.length > 0 ? appSettings[0] : {},
            item.applicationSettings,
            ['id', 'tableName'],
          );
          await this.save(
            item.applicationSettings,
            undefined,
            'ApplicationSettings',
          );
        }

        if (item.items && item.items.length > 0) {
          for (var i = 0; i < item.items.length; i++) {
            var a = item.items[i];
            var b = (await this.where('DetaliItems', {
              novel: a.novel,
            })) as DetaliItemsSettings[];
            var aChapterSettings =
              a.chapterSettings ?? ([] as ChapterSettings[]);
            var bChaptersSettings =
              b && b.length > 0
                ? ((await this.where('Chapters', {
                    detaliItem_Id: b[0].id,
                  })) as ChapterSettings[])
                : ([] as ChapterSettings[]);
            var updatedChapterSettings = [] as ChapterSettings[];
            if (b && b.length > 0) {
              if (a.chapterIndex) b[0].chapterIndex = a.chapterIndex;
              b[0].isFavorit = true;
              a = b[0];
            }

            aChapterSettings.forEach((x) => {
              var bCh = bChaptersSettings.find(
                (a) => a.chapterUrl === x.chapterUrl,
              );
              if (bCh)
                updatedChapterSettings.push(
                  httpClient.cloneItem(bCh, x, ['id', 'tableName']),
                );
              else updatedChapterSettings.push(x);
            });

            let detaliItemSettings = await this.save(
              a,
              undefined,
              'DetaliItems',
            );

            for (var y = 0; y <= aChapterSettings.length - 1; y++) {
              let m = aChapterSettings[y];
              m.detaliItem_Id = detaliItemSettings.id;
              await this.save(m, undefined, 'Chapters');
            }
          }
        }

        return true;
      }
    } catch (error) {
      console.log(error);
    }
    return false;
  };

  exportFileToDownloadFolder = async () => {
    try {
      const {status} = await Permissions.askAsync(Permissions.MEDIA_LIBRARY);
      if (status === 'granted') {
        var favoriteData = (await this.where('DetaliItems', {
          isFavorit: true,
        })) as DetaliItemsSettings[];
        for (var i = 0; i < favoriteData.length; i++) {
          var item = favoriteData[i];

          item.chapterSettings = (await this.where('Chapters', {
            detaliItem_Id: item.id,
          })) as ChapterSettings[];
          item.id = 0;
          item.chapterSettings.forEach((x) => {
            x.id = 0;
            x.detaliItem_Id = 0;
          });
        }

        var result = {
          applicationSettings:
            (await this.where('ApplicationSettings')).length > 0
              ? (await this.where('ApplicationSettings'))[0]
              : undefined,
          items: favoriteData,
        };

        let fileUri = FileSystem.documentDirectory + 'NovelManager.db';
        await FileSystem.writeAsStringAsync(fileUri, JSON.stringify(result), {
          encoding: FileSystem.EncodingType.UTF8,
        });
        const asset = await MediaLibrary.createAssetAsync(fileUri);
        await MediaLibrary.createAlbumAsync('Download', asset, false);

        return true;
      }
    } catch (error) {
      console.log(error);
    }
    return false;
  };

  dataBasePath = () => {
    return FileSystem.documentDirectory + this.databaseName;
  };
  createConnection = () => {
    return SQLite.openDatabase(this.databaseName);
  };

  allowedKeys = (tableName: string) => {
    return new Promise((resolve, reject) => {
      this.createConnection().transaction(
        (x) =>
          x.executeSql(
            `PRAGMA table_info(${tableName})`,
            undefined,
            (trans, data) => {
              var keys = [] as string[];
              for (var i = 0; i < data.rows.length; i++) {
                if (data.rows.item(i).name != 'id')
                  keys.push(data.rows.item(i).name);
              }
              resolve(keys);
            },
          ),
        (error) => {
          reject(error);
        },
      );
    }) as Promise<string[]>;
  };

  selectLastRecord = async (item: BaseModule) => {
    console.log('Executing SelectLastRecord...');
    return (
      await this.find(
        item.id <= 0
          ? `SELECT * FROM ${item.tableName} ORDER BY id DESC LIMIT 1;`
          : `SELECT * FROM ${item.tableName} WHERE id=?;`,
        item.id > 0 ? [item.id] : undefined,
      )
    ).map((x) => {
      x.tableName = item.tableName;
      return x;
    });
  };

  delete = async (item: BaseModule, tableName?: string) => {
    tableName = item.tableName ?? tableName;
    var q = `DELETE FROM ${tableName} WHERE id=?`;
    await this.execute(q, [item.id]);
  };

  public save = (
    item: BaseModule,
    insertOnly?: Boolean,
    tableName?: string,
  ) => {
    if (!item.tableName) item.tableName = tableName ?? '';
    return new Promise(async (resolve, reject) => {
      try {
        await this.setUpDataBase();
        console.log('Executing Save...');
        var items = await this.where(item.tableName, {id: item.id});
        var keys = (await this.allowedKeys(item.tableName)).filter((x) =>
          Object.keys(item).includes(x),
        );
        let query = '';
        let args = [] as any[];
        if (items.length > 0) {
          if (insertOnly) return;
          query = `UPDATE ${item.tableName} SET `;
          keys.forEach((k, i) => {
            query += ` ${k}=? ` + (i < keys.length - 1 ? ',' : '');
          });
          query += ' WHERE id=?';
        } else {
          query = `INSERT INTO ${item.tableName} (`;
          keys.forEach((k, i) => {
            query += k + (i < keys.length - 1 ? ',' : '');
          });
          query += ') values(';
          keys.forEach((k, i) => {
            query += '?' + (i < keys.length - 1 ? ',' : '');
          });
          query += ')';
        }
        keys.forEach((k: string, i) => {
          args.push(item[k] ?? null);
        });
        if (items.length > 0) args.push(item.id);

        await this.execute(query, args);
        resolve((await this.selectLastRecord(item))[0]);
      } catch (error) {
        console.log(error);
        reject(error);
      }
    }) as Promise<BaseModule>;
  };

  public find = (query: string, args?: any[]) => {
    return new Promise((resolve, reject) => {
      this.createConnection().transaction(
        async (x) => {
          await this.setUpDataBase();
          console.log('Executing Find..');
          x.executeSql(
            query,
            args,
            async (trans, data) => {
              console.log('query executed:' + query);
              var items = [] as BaseModule[];
              for (var i = 0; i < data.rows.length; i++) {
                var t = data.rows.item(i);
                items.push(t);
              }
              resolve(items);
            },
            (_ts, error) => {
              console.log('Could not execute query:' + query);
              console.log(error);
              reject(error);
              return false;
            },
          );
        },
        (error) => {
          console.log(error);
          reject(error);
        },
      );
    }) as Promise<BaseModule[]>;
  };

  where = async (tableName: string, query?: any) => {
    var q = `SELECT * FROM ${tableName} ${query ? 'WHERE ' : ''}`;
    var values = [] as any[];
    if (query) {
      Object.keys(query).forEach((x, i) => {
        q += x + '=? ' + (i < Object.keys(query).length - 1 ? 'AND ' : '');
        values.push(query[x]);
      });
    }
    return (await this.find(q, values)).map((x) => {
      x.tableName = tableName;
      return x;
    });
  };

  findOne = async (tableName: string, query?: any) => {
    var items = await this.where(tableName, query);
    return items && items.length > 0 ? items[0] : undefined;
  };

  execute = async (query: string, args?: any[]) => {
    return new Promise((resolve, reject) => {
      this.createConnection().transaction(
        (tx) => {
          console.log('Execute Query:' + query);
          tx.executeSql(
            query,
            args,
            (tx, results) => {
              console.log('Statment has been executed....' + query);
              resolve(true);
            },
            (_ts, error) => {
              console.log('Could not execute query');
              console.log(args);
              console.log(error);
              reject(error);
              return false;
            },
          );
        },
        (error) => {
          console.log('db executing statement, has been termineted');
          console.log(args);
          console.log(error);
          reject(error);
          throw 'db executing statement, has been termineted';
        },
      );
    });
  };

  public dropTables = async () => {
    await this.execute(`DROP TABLE if exists ApplicationSettings`);
    await this.execute(`DROP TABLE if exists DetaliItems`);
    await this.execute(`DROP TABLE if exists Chapters`);
    Repository.dbIni = false;
    await this.setUpDataBase();
  };

  setUpDataBase = async () => {
    let applicationSetupQuery = `CREATE TABLE if not exists ApplicationSettings (
      id    INTEGER NOT NULL UNIQUE,
      backGroundColor   TEXT NOT NULL,
      fontSize INTEGER NOT NULL,
      lineHeight INTEGER NOT NULL,
      fontFamily TEXT NOT NULL,
      marginLeft INTEGER NOT NULL,
      marginRight INTEGER NOT NULL,
      detaliItem_Id INTEGER,
      selectedParserIndex INTEGER,
      PRIMARY KEY(id AUTOINCREMENT)
    );`;

    let detaliItemsQuery = `CREATE TABLE if not exists DetaliItems (
      image TEXT NOT NULL,
      title TEXT NOT NULL,
      description   TEXT NOT NULL,
      novel TEXT NOT NULL,
      parserName TEXT NOT NULL,
      chapterIndex INTEGER NOT NULL,
      id INTEGER NOT NULL,
      isFavorit INTEGER NOT NULL,
      PRIMARY KEY(id AUTOINCREMENT)
    );`;

    let chapterQuery = `CREATE TABLE if not exists Chapters (
      id INTEGER NOT NULL UNIQUE,
      chapterUrl TEXT NOT NULL,
      isViewed INTEGER NOT NULL,
      currentProgress   NUMERIC NOT NULL,
      finished INTEGER NOT NULL,
      detaliItem_Id INTEGER NOT NULL,
      PRIMARY KEY(id AUTOINCREMENT),
      CONSTRAINT "fk_detaliItem_id" FOREIGN KEY(detaliItem_Id) REFERENCES DetaliItems(id)
    );`;

    if (!Repository.dbIni) {
      console.log('dbIni= false, setUpDataBase');
      await this.execute(applicationSetupQuery);
      await this.execute(detaliItemsQuery);
      await this.execute(chapterQuery);
      Repository.dbIni = true;
    } else {
      console.log('dbIni= true, setUpDataBase');
    }
  };
}