itopen组织
1、提供OpenHarmony优雅实用的小工具
2、手把手适配riscv + qemu + linux的三方库移植
3、未来计划riscv + qemu + ohos的三方库移植 + 小程序开发
4、一切拥抱开源,拥抱国产化
一、sqlite3库介绍
sqlite3库可从官网下载,当前版本为sqlite3 3.45.3
https://www.sqlite.org/download.html
二、sqlite3编译
2.1 x86_64架构安装
2.1.1 命令安装
sudo apt-get install sqlite3
sudo apt-get install libsqlite3-dev
2.1.2 源码编译安装
./configure
make -j$(nproc)
sudo make install
2.2 基于arm架构编译
2.2.1 下载工具链并安装
# 下载工具链
wget https://repo.huaweicloud.com/openharmony/compiler/prebuilts_gcc_linux-x86_arm_gcc-linaro-7.5.0-arm-linux-gnueabi/1.0/prebuilts_gcc_linux-x86_arm_gcc-linaro-7.5.0-arm-linux-gnueabi.tar.gz
tar -xvf prebuilts_gcc_linux-x86_arm_gcc-linaro-7.5.0-arm-linux-gnueabi.tar.gz
# 设置工具链的路径
vim ~/.bashrc
# 最后一行添加
export PATH=~/bin/prebuilts_gcc_linux-x86_arm_gcc-linaro-7.5.0-arm-linux-gnueabi/bin:$PATH
# 重置.bashrc
source ~/.bashrc
2.2.2 编译sqlite3
export CC=aarch64-linux-gnu-gcc
./configure --prefix=$PWD/_install CC=aarch64-linux-gnu-gcc --host=aarch64-linux
./configure --prefix=$PWD/_install
make -j$(nproc)
make install
2.3 基于riscv64架构编译
2.3.1 工具链安装
sudo apt-get install gcc-riscv64-linux-gnu
2.3.2 编译sqlite3
./configure --prefix=$PWD/_install CC=riscv64-linux-gnu-gcc --host=riscv64-linux
make -j$(nproc)
make install
三、接口介绍
参考链接:
https://geek-docs.com/sqlite
3.1 打开/创建数据库
int sqlite3_open(const char *filename, sqlite3 **ppDb);
3.2 关闭数据库
int sqlite3_close(sqlite3 *db);
3.3 执行sql语句
int sqlite3_exec(sqlite3*,
const char *sql,
int (*callback)(void *, int, char **, char **),
void *arg,
char **errmsg);
3.4 获取结果内容
int sqlite3_get_table(sqlite3 *db,
const char *zSql,
char ***pazResult,
int *pnRow,
int *pnColumn,
char **pzErrmsg);
3.5 获取错误信息
const char *sqlite3_errmsg(sqlite3 *db);
3.6 释放表空间
void sqlite3_free_table(char **result);
四、sqlite3语句
4.1 sqlite数据类型
NULL:标识一个NULL值
INTEGER(intger):整数类型 int
REAL(real):浮点数 float,double
TEXT(text):字符串 ""
CHAR(char):字符''
4.2 创建表
create if not exists table table_name(column1 type1, column2 type2, column3 type3……);
# 例如创建一个名为dictory的表(sheet),里面有word、translation等字段
create table if not exists table_name(word text, translation text);
# not null 指定列不允许为NULL值
create table if not exists student(student_name txt not NULL, id txt not NULL, sex char);
# default 在insert into语句没有提供特定的值时,为列提供一个默认值
create table if not exists student(student_name txt not NULL, id txt not NULL, sex char, grade integer default 99);
# unique 约束防止一个特定的列存在两个相同的值
create table if not exists student(student_name txt not NULL unique, id txt not NULL, sex char);
# check 约束 启用输入一条记录要检查值的条件。如果条件值为false,则记录违反了约束,且不能输入到表
create table if not exists student(student_name txt not NULL, id txt not NULL, sex char, grade intger check(grade > 0));
4.3 添加记录
insert into table_name(column1, column2, column3) values(val1, val2, val3);
insert into student(student_name, id, sex) values ('z3', '123', 'm');
或者
insert into student values('z3', '123', 'm');
4.4 查询
4.4.1 查看表结构
.schema
4.4.2 查看所有表
.tables
4.4.3 查看记录
# 获取所有数据记录
select * from table_name;
# 限制输出数据记录数量
select * from table_name limit val;
# 升序输出数据记录
select * from table_name order by column asc;
select * from dictory order by word asc;
# 降序输出数据记录
select * from table_name order by column desc;
select * from dictory order by word desc;
# 条件查询
select * from table_name where expression;
select * from table_name where column in ('val1', 'val2', 'val3');
select * from table_name where column = 'val1' or column = 'val2';
select * from table_name where column between val1 and val2;
select * from people where age>=10 and age <=15;
select name, age from people where age>= 10 and age<=15;
select * from table_name where column like 'xx%' or 'xxx_';
百分号(%)代表零个、一个或者多个数字或字符
下划线(_)代表一个单一数字或字符
4.5 修改数据记录
update table_name set column1=val1, column2=val2 where expression;
update student_info set id=0002, name=hencai where id=0001;
4.6 表中添加字段
alter table <table_name> add column <field> <type>;
alter table stu add column age integer;
4.7 删除数据记录
delete from table_name [where expression];
delete from stu where id=123;
4.8 删除表
drop table table_name;
drop table student;
4.9 删除指定字段
# step1:备份为temp id , name , age , sex
alter table info rename to temp;
# step2:创建新表
create table info(id, name, age);
#step3:导出到新表
insert into info select id, name, age from temp;
4.10 退出sqlite3
.quit
五、sqlite3库封装
5.1 封装库代码
代码来源 itopen组织: test
sqlite3_lib.c代码
#include "sqlite3_lib.h"
struct Sqlite3SyncOps sqlite3Sync[] = {
{SQLITE3_SYNC_MODE_FULL, "PRAGMA synchronous = FULL"},
{SQLITE3_SYNC_MODE_NORMAL, "PRAGMA synchronous = NORMAL"},
{SQLITE3_SYNC_MODE_OFF, "PRAGMA synchronous = OFF"},
};
int CreateDatabase(char *dbname, sqlite3 **db)
{
int ret = sqlite3_open(dbname, db);
if (ret != SQLITE_OK) {
printf("sqlite3_open error: %s\n", sqlite3_errmsg(*db));
return -1;
}
return SQLITE_OK;
}
int SetDatabaseSync(sqlite3 *db, enum Sqlite3SyncMode mode)
{
char *errmsg = NULL;
if (db == NULL) {
printf("db is NULL\n");
return -1;
}
if (sqlite3_exec(db, sqlite3Sync[mode].sql, NULL, NULL, &errmsg)) {
printf("sqlite3_exec error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
return SQLITE_OK;
}
int CreateDataSheet(sqlite3 *db, const char *sql)
{
char *errmsg = NULL;
if (db == NULL) {
printf("db is NULL\n");
return -1;
}
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg)) {
printf("sqlite3_exec error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
return SQLITE_OK;
}
int InsertDataValue(sqlite3 *db, const char *sheet, const char *column, const char *value)
{
int i;
char sql[1024];
char *errmsg = NULL;
if (db == NULL) {
printf("db is NULL\n");
return -1;
}
sprintf(sql, "insert into %s(%s) values (%s);", sheet, column, value);
printf("sql: %s\n", sql);
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg)) {
printf("sqlite3_exec error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
return SQLITE_OK;
}
int CloseDatabase(sqlite3 *db)
{
if (db == NULL) {
return 0;
}
return sqlite3_close(db);
}
sqlite3_lib.h代码
#ifndef __SQLITE3_LIB_H__
#define __SQLITE3_LIB_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
enum Sqlite3SyncMode {
// 在每次写入操作完成之前,会等待数据被写入磁盘后再继续下一步操作。这种模式具有最高的数据完整性和可靠性,但性能会受到一定影响
SQLITE3_SYNC_MODE_FULL = 0,
// 在写入操作完成之后,会等待数据被写入磁盘的操作系统缓存中后再继续下一步操作。这种模式在数据完整性和性能之间达到了一种平衡,适用于大多数场景
SQLITE3_SYNC_MODE_NORMAL,
// 在写入操作完成后,不会等待数据被写入磁盘,直接继续下一步操作。这种模式具有最高的性能,但数据的完整性和可靠性可能会受到一定影响。适用于对数据完整性要求不高的场景,例如缓存数据
SQLITE3_SYNC_MODE_OFF
};
struct Sqlite3SyncOps {
int id;
char *sql;
};
int CreateDatabase(char *dbname, sqlite3 **db);
int SetDatabaseSync(sqlite3 *db, enum Sqlite3SyncMode mode);
int CreateDataSheet(sqlite3 *db, const char *sql);
int InsertDataValue(sqlite3 *db, const char *sheet, const char *column, const char *value);
int CloseDatabase(sqlite3 *db);
#endif /* end of __SQLITE3_LIB_H__ */
Makefile代码
#************************************************************************
#> File Name: Makefile.c
#> Author: Wenfei6316
#> Mail: wen_fei@hoperun.com
#> Created Time: 2024年07月1日 星期一 03时44分36秒
#************************************************************************
sqlite3_lib:
gcc sqlite3_lib.c -fPIC -shared -o libsqlite3_lib.so
all: sqlite3_lib ECHO
gcc main.c -o main -lsqlite3 -L./ -lsqlite3_lib
ECHO:
@echo $(SUBDIR)
@echo "========>begin compile"
clean:
find ./ -name "*.o" -exec rm {} \;
六、Demo样例
6.1 dictory创建
#include "sqlite3_lib.h"
#define CREATE_TABLE "create table if not exists dict(word text primary key, translation text);"
int main(int argc, char **argv)
{
int i;
int cnt = 1;
int ret;
FILE *fp = NULL;
sqlite3 *db = NULL;
char buf[1024] = {0};
char value[1024] = {0};
printf("start create database\n");
// 1. 创建数据库
ret = CreateDatabase("dictionary.db", &db);
if (ret != SQLITE_OK) {
printf("CreateDatabase error: %s\n", sqlite3_errmsg(db));
return -1;
}
// 2. 设置数据库同步模式
ret = SetDatabaseSync(db, SQLITE3_SYNC_MODE_FULL);
if (ret != SQLITE_OK) {
printf("SetDatabaseSync error: %s\n", sqlite3_errmsg(db));
return -1;
}
// 3. 常见表格
ret = CreateDataSheet(db, CREATE_TABLE);
if (ret != SQLITE_OK) {
printf("CreateDataSheet error: %s\n", sqlite3_errmsg(db));
return -1;
}
// 4. 插入数据
fp = fopen("dict.txt", "r");
if (fp == NULL) {
printf("open dict.txt error\n");
return -1;
}
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (buf[strlen(buf)-1] == '\n') {
buf[strlen(buf)-1] = '\0';
}
// 获取单词结尾地方并设置为\0, 以及翻译起始位置
for (i = 0; buf[i] != ' '; i++);
buf[i] = '\0';
for(; buf[++i] == ' ';);
// 插入数据到数据库
snprintf(value, 1024, "\"%s\", \"%s\"", &buf[0], &buf[i]);
printf("%d: value: %s\n", cnt++, value);
ret = InsertDataValue(db, "dict", "word, translation", value);
if (ret != SQLITE_OK) {
printf("InsertDataValue error: %s\n", sqlite3_errmsg(db));
return -1;
}
memset(buf, '\0', sizeof(buf));
memset(value, '\0', sizeof(value));
}
fclose(fp);
CloseDatabase(db);
printf("close database success\n");
return 0;
}
附录
另有Python简单封装的sqlite3操作可参见 itopen组织: module_code