@ohmi/react-native-sqlite-storage
v6.0.1-0.1.8
Published
SQLite3 bindings for React Native (Android & iOS)
Downloads
28
Readme
模板版本:v0.2.2
[!TIP] Github 地址
介绍
本项目是基于 react-native-sqlite-storage 6.0.0 鸿蒙化版本,
安装与使用
请到三方库的 Releases 发布地址查看配套的版本信息:@ohmi/react-native-sqlite-storage Releases 。对于未发布到npm的旧版本,请参考安装指南安装tgz包。
进入到工程目录并输入以下命令:
[!TIP] # 处替换为 tgz 包的路径
npm
npm install @ohmi/react-native-sqlite-storage@file:#yarn
yarn add @ohmi/react-native-sqlite-storage@file:#下面的代码展示了这个库的基本使用场景:
[!WARNING] 使用时 import 的库名不变。
/**
* @format
*/
import React, {Component} from 'react';
import { StyleSheet, Text, View, FlatList} from 'react-native';
import SQLite from 'react-native-sqlite-storage';
SQLite.DEBUG(true);
SQLite.enablePromise(false);
const database_name = 'Test.db';
const database_version = '1.0';
const database_displayname = 'SQLite Test Database';
const database_size = 200000;
let db;
const Item = ({title}) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
class SQLiteDemo extends Component {
constructor() {
super();
this.progress = [];
this.state = {
progress: [],
};
}
updateProgress = (text, resetState) => {
let progress = [];
if (!resetState) {
progress = [...this.progress];
}
progress.push(text);
this.progress = progress;
this.setState({
progress,
});
};
componentWillUnmount = () => {
this.closeDatabase();
};
errorCB = err => {
console.log('error: ', err);
this.updateProgress('Error: ' + (err.message || err));
return false;
};
successCB = () => {
console.log('SQL executed ...');
};
openCB = () => {
this.updateProgress('Database OPEN');
};
closeCB = () => {
this.updateProgress('Database CLOSED');
};
deleteCB = () => {
console.log('Database DELETED');
this.updateProgress('Database DELETED');
};
// eslint-disable-next-line no-shadow
populateDatabase = db => {
this.updateProgress('Database integrity check');
db.executeSql(
'SELECT 1 FROM Version LIMIT 1',
[],
() => {
this.updateProgress('Database is ready ... executing query ...');
db.transaction(this.queryEmployees, this.errorCB, () => {
this.updateProgress('Processing completed');
});
},
error => {
console.log('received version error:', error);
this.updateProgress('Database not yet ready ... populating data');
db.transaction(this.populateDB, this.errorCB, () => {
this.updateProgress('Database populated ... executing query ...');
db.transaction(this.queryEmployees, this.errorCB, () => {
console.log('Transaction is now finished');
this.updateProgress('Processing completed');
// this.closeDatabase();
});
});
},
);
};
populateDB = tx => {
this.updateProgress('Executing DROP stmts');
tx.executeSql('DROP TABLE IF EXISTS Employees;');
tx.executeSql('DROP TABLE IF EXISTS Offices;');
tx.executeSql('DROP TABLE IF EXISTS Departments;');
this.updateProgress('Executing CREATE stmts');
tx.executeSql(
'CREATE TABLE IF NOT EXISTS Version( ' +
'version_id INTEGER PRIMARY KEY NOT NULL); ',
[],
this.successCB,
this.errorCB,
);
tx.executeSql(
'CREATE TABLE IF NOT EXISTS Departments( ' +
'department_id INTEGER PRIMARY KEY NOT NULL, ' +
'name VARCHAR(30) ); ',
[],
this.successCB,
this.errorCB,
);
tx.executeSql(
'CREATE TABLE IF NOT EXISTS Offices( ' +
'office_id INTEGER PRIMARY KEY NOT NULL, ' +
'name VARCHAR(20), ' +
'longtitude FLOAT, ' +
'latitude FLOAT ) ; ',
[],
this.successCB,
this.errorCB,
);
tx.executeSql(
'CREATE TABLE IF NOT EXISTS Employees( ' +
'employe_id INTEGER PRIMARY KEY NOT NULL, ' +
'name VARCHAR(55), ' +
'office INTEGER, ' +
'department INTEGER, ' +
'custom_info TEXT DEFAULT "",' +
'FOREIGN KEY ( office ) REFERENCES Offices ( office_id ) ' +
'FOREIGN KEY ( department ) REFERENCES Departments ( department_id ));',
[],
);
this.updateProgress('Executing INSERT stmts');
tx.executeSql(
'INSERT INTO Departments (name) VALUES ("Client Services");',
[],
);
tx.executeSql(
'INSERT INTO Departments (name) VALUES ("Investor Services");',
[],
);
tx.executeSql('INSERT INTO Departments (name) VALUES ("Shipping");', []);
tx.executeSql(
'INSERT INTO Departments (name) VALUES ("Direct Sales");',
[],
);
tx.executeSql(
'INSERT INTO Offices (name, longtitude, latitude) VALUES ("Denver", 59.8, 34.);',
[],
);
tx.executeSql(
'INSERT INTO Offices (name, longtitude, latitude) VALUES ("Warsaw", 15.7, 54.);',
[],
);
tx.executeSql(
'INSERT INTO Offices (name, longtitude, latitude) VALUES ("Berlin", 35.3, 12.);',
[],
);
tx.executeSql(
'INSERT INTO Offices (name, longtitude, latitude) VALUES ("Paris", 10.7, 14.);',
[],
);
tx.executeSql(
'INSERT INTO Employees (name, office, department, custom_info) VALUES ("Sylvester Stallone", 2, 4, \'{"known": true}\')',
[],
);
tx.executeSql(
'INSERT INTO Employees (name, office, department, custom_info) VALUES ("Elvis Presley", 2, 4, \'{"known": true}\')',
[],
);
tx.executeSql(
'INSERT INTO Employees (name, office, department, custom_info) VALUES ("Leslie Nelson", 3, 4, \'{"known": true}\')',
[],
);
tx.executeSql(
'INSERT INTO Employees (name, office, department, custom_info) VALUES ("Fidel Castro", 3, 3, \'{"known": true}\')',
[],
);
tx.executeSql(
'INSERT INTO Employees (name, office, department, custom_info) VALUES ("Bill Clinton", 1, 3, \'{"known": false}\')',
[],
);
tx.executeSql(
'INSERT INTO Employees (name, office, department, custom_info) VALUES ("Margaret Thatcher", 1, 3, \'{"known": true}\')',
[],
);
tx.executeSql(
'INSERT INTO Employees (name, office, department, custom_info) VALUES ("Donald Trump", 2, 4, \'{"known": true, "impeached": true}\')',
[],
);
tx.executeSql(
'INSERT INTO Employees (name, office, department, custom_info) VALUES ("Dr DRE", 2, 2, \'{"known": true}\')',
[],
);
tx.executeSql(
'INSERT INTO Employees (name, office, department, custom_info) VALUES ("Samantha Fox", 2, 1, \'{"known": true}\')',
[],
);
console.log('all config SQL done');
};
queryEmployees = async tx => {
console.log('Executing JSON1 queries...');
// 1. JSON_OBJECT
await tx.executeSql(
"SELECT JSON_OBJECT('name', e.name, 'office_id', e.office, 'department_id', e.department) AS data FROM Employees e",
[],
this.querySuccess,
this.errorCB,
);
// 2. JSON_ARRAY
// Expected: [1,2,"3",4]
await tx.executeSql(
"SELECT JSON_ARRAY(1, 2, '3', 4) AS data ",
[],
this.querySuccess,
this.errorCB,
);
// 3. JSON_ARRAY_LENGTH
// Expected: 4
await tx.executeSql(
"SELECT JSON_ARRAY_LENGTH('[1, 2, 3, 4]') AS data",
[],
this.querySuccess,
this.errorCB,
);
// 4. JSON_EXTRACT
await tx.executeSql(
"SELECT JSON_EXTRACT(e.custom_info, '$.known') AS data FROM Employees e",
[],
this.querySuccess,
this.errorCB,
);
// 5. JSON_INSERT
// Expected: {"a":1,"b":2,"c":3}
await tx.executeSql(
'SELECT JSON_INSERT(\'{"a": 1, "b": 2}\', \'$.c\', 3) AS data',
[],
this.querySuccess,
this.errorCB,
);
// 6. JSON_REPLACE
// Expected: {"a":1,"b":3}
await tx.executeSql(
'SELECT JSON_REPLACE(\'{"a": 1, "b": 2}\', \'$.b\', 3) AS data',
[],
this.querySuccess,
this.errorCB,
);
// 7. JSON_SET
// Expected: {"a":1,"b":123}
await tx.executeSql(
'SELECT JSON_SET(\'{"a": 1, "b": 2}\', \'$.b\', 123) AS data',
[],
this.querySuccess,
this.errorCB,
);
// 8. JSON_REMOVE
// Expected: {"a":1"}
await tx.executeSql(
'SELECT JSON_REMOVE(\'{"a": 1, "b": 2}\', \'$.b\') AS data',
[],
this.querySuccess,
this.errorCB,
);
// 9. JSON_TYPE
// Expected: integer
await tx.executeSql(
'SELECT JSON_TYPE(\'{"a": 1, "b": 2}\', \'$.a\') AS data',
[],
this.querySuccess,
this.errorCB,
);
// 10. JSON_VALID
// Expected: 0
await tx.executeSql(
'SELECT JSON_VALID(\'{"a": 1, "b": 2\') AS data',
[],
this.querySuccess,
this.errorCB,
);
// 11. JSON_QUOTE
// Expected: "value"
await tx.executeSql(
"SELECT JSON_QUOTE('value') AS data",
[],
this.querySuccess,
this.errorCB,
);
};
querySuccess = (tx, results) => {
this.updateProgress('Query completed');
var len = results.rows.length;
for (let i = 0; i < len; i++) {
let row = results.rows.item(i);
this.updateProgress(`${row.data}`);
}
};
loadAndQueryDB = () => {
this.updateProgress('Opening database ...', true);
this.updateProgress('Database OPEN');
db = SQLite.openDatabase(
database_name,
database_version,
database_displayname,
database_size,
this.openCB,
this.errorCB,
);
this.populateDatabase(db);
};
deleteDatabase = () => {
this.updateProgress('Deleting database');
SQLite.deleteDatabase(database_name, this.deleteCB, this.errorCB);
};
closeDatabase = () => {
if (db) {
console.log('Closing database ...');
this.updateProgress('Closing database');
db.close(this.closeCB, this.errorCB);
} else {
this.updateProgress('Database CLOSE callback function error');
// this.updateProgress('Database was not OPENED');
}
};
runDemo = () => {
this.updateProgress('Starting SQLite Callback Demo', true);
this.loadAndQueryDB();
};
attachDatabase = () =>{
if (db!=null) {
this.updateProgress('Attach database ...');
let dbMaster = SQLite.openDatabase('test2.db',database_version,database_displayname,database_size,
() => {
dbMaster.attach( database_name, database_displayname, () => console.log("Database attached successfully"), () => console.log("ERROR"))
this.updateProgress('Attach database successfully');
},
this.errorCB,
);
} else {
this.updateProgress('Database not open');
}
}
renderProgressEntry = entry => {
return (
<View style={listStyles.li}>
<View>
<Text style={listStyles.liText}>{entry}</Text>
</View>
</View>
);
};
render = () => {
return (
<View style={styles.mainContainer}>
<View style={styles.toolbar}>
<Text style={styles.toolbarButton} onPress={this.runDemo}>
Run Demo
</Text>
<Text style={styles.toolbarButton} onPress={this.attachDatabase}>
Attach DB
</Text>
<Text style={styles.toolbarButton} onPress={this.closeDatabase}>
Close DB
</Text>
<Text style={styles.toolbarButton} onPress={this.deleteDatabase}>
Delete DB
</Text>
</View>
<FlatList
data={this.state.progress}
renderItem={({item}) => <Item title={item} />}
keyExtractor={item => item.i}
/>
</View>
);
};
}
var listStyles = StyleSheet.create({
li: {
borderBottomColor: '#c8c7cc',
borderBottomWidth: 0.5,
paddingTop: 15,
paddingRight: 15,
paddingBottom: 15,
},
liContainer: {
backgroundColor: '#fff',
flex: 1,
paddingLeft: 15,
},
liIndent: {
flex: 1,
},
liText: {
color: '#333',
fontSize: 17,
fontWeight: '400',
marginBottom: -3.5,
marginTop: -3.5,
},
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
toolbar: {
backgroundColor: '#51c04d',
paddingTop: 30,
paddingBottom: 10,
flexDirection: 'row',
},
toolbarButton: {
color: 'blue',
textAlign: 'center',
flex: 1,
},
mainContainer: {
flex: 1,
},
});
export default SQLiteDemo;
使用 Codegen
本库已经适配了 Codegen ,在使用前需要主动执行生成三方库桥接代码,详细请参考 Codegen 使用文档。
Link
目前HarmonyOS暂不支持 AutoLink,所以 Link 步骤需要手动配置。
首先需要使用 DevEco Studio 打开项目里的HarmonyOS工程 harmony
1.在工程根目录的 oh-package.json5 添加 overrides字段
{
...
"overrides": {
"@rnoh/react-native-openharmony" : "./react_native_openharmony"
}
}2.引入原生端代码
目前有两种方法:
- 通过 har 包引入(在 IDE 完善相关功能后该方法会被遗弃,目前首选此方法);
- 直接链接源码。
方法一:通过 har 包引入(推荐)
[!TIP] har 包位于三方库安装路径的
harmony文件夹下。
打开 entry/oh-package.json5,添加以下依赖
"dependencies": {
"@rnoh/react-native-openharmony": "file:../react_native_openharmony",
"@ohmi/react-native-sqlite-storage": "file:../../node_modules/@ohmi/react-native-sqlite-storage/platforms/harmony/sqlite_storage.har"
}点击右上角的 sync 按钮
或者在终端执行:
cd entry
ohpm install方法二:直接链接源码
[!TIP] 如需使用直接链接源码,请参考直接链接源码说明
3.在 ArkTs 侧引入 SQLitePluginPackage
打开 entry/src/main/ets/RNPackagesFactory.ts,添加:
...
+ import {SQLitePluginPackage} from '@ohmi/react-native-sqlite-storage/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
new SamplePackage(ctx),
+ new SQLitePluginPackage(ctx)
];
}4.配置 CMakeLists 和引入 SQLitePluginPackage
打开 entry/src/main/cpp/CMakeLists.txt,添加:
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(NODE_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../node_modules")
+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../react-native-harmony/harmony/cpp")
set(LOG_VERBOSITY_LEVEL 1)
set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use
add_compile_definitions(WITH_HITRACE_SYSTRACE)
add_subdirectory("${RNOH_CPP_DIR}" ./rn)
# RNOH_BEGIN: manual_package_linking_1
+ add_subdirectory("${OH_MODULES}/@ohmi/react-native-sqlite-storage/src/main/cpp" ./sqlite_storage)
# RNOH_END: manual_package_linking_1
file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")
add_library(rnoh_app SHARED
${GENERATED_CPP_FILES}
"./PackageProvider.cpp"
"${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
target_link_libraries(rnoh_app PUBLIC rnoh)
# RNOH_BEGIN: manual_package_linking_2
target_link_libraries(rnoh_app PUBLIC rnoh_sample_package)
+ target_link_libraries(rnoh_app PUBLIC rnoh_sqlite_storage)
# RNOH_END: manual_package_linking_2打开 entry/src/main/cpp/PackageProvider.cpp,添加:
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
+ #include "SQLitePluginPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<RNOHGeneratedPackage>(ctx),
+ std::make_shared<SQLitePluginPackage>(ctx),
};
}5.运行
点击右上角的 sync 按钮
或者在终端执行:
cd entry
ohpm install然后编译、运行即可。
兼容性
要使用此库,需要使用正确的 React-Native 和 RNOH 版本。另外,还需要使用配套的 DevEco Studio 和 手机 ROM。
请到三方库相应的 Releases 发布地址查看 Release 配套的版本信息:@ohmi/react-native-sqlite-storage Releases
静态方法
[!TIP] "HarmonyOS Support"列为 yes 表示 HarmonyOS 平台支持该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
| Name | Description | Type | Required | Platform | HarmonyOS Support | | ---- | ----------- | ---- | -------- | -------- | ------------------ | | openDatabase | Opens or initializes | void | yes |All | yes | | transaction | SQL transaction distribution | void | yes |All | yes | | close |Closes or releases a previously opened resource | void | yes |All | yes | | deleteDatabase |Deletes a resource |void | yes | All | yes | | attach | Connects or associates with an external resource or database | void | yes | All | yes| | executeSql |Executes a batch of SQL statements in the background without blocking the current thread or process | void | yes |All | yes |
遗留问题
其他
开源协议
本项目基于 The MIT License (MIT) ,请自由地享受和参与开源。
