1. 什么是sqlite?
sqlite 是一个小型,高速、高可靠性功能齐全的sql数据库引擎,并且是C语言开源的库,可以很方便的移植到各种嵌入式平台上。
官网如下:
地址:http://www3.sqlite.org/index.html
最新版本:3.3.52
2. sqlite 交叉编译
源码下载
tar -zxvf sqlite-autoconf-3350200.tar.gz
交叉编译
cd sqlite-autoconf-3350200 mkdir pc_out ./configure --prefix=~/work/github/sqlite-autoconf-3350200/pc_out make make install
安装完成文件如下:
- sqlite3:应用程序,直接可以打开和创建数据库
- include:头文件,开发用
- lib:sqlite3 的库,开发用
- share:共享文件和手册
编译完成可以直接在pc上运行 sqlite3。
mips
mips 交叉编译和 pc 差不多,不过有一点不同,我们需要配置工具链:
准备工作:
cd sqlite-autoconf-3350200 mkdir mips_out mkdir mips_out/glibc #创建glibc 目录 mkdir mips_out/uclibc#创建uclibc 目录 make distclean
编译glibc:
第一步:配置configure。设置工具链和安装路径
./configure --prefix=~/work/github/sqlite-autoconf-3350200/mips_out/glibc --host=mips-linux-gnu
- --prefix:指定安装路径。
- --host:指定工具链。注意,需要设置工具链的环境变量,否则检测不到工具链。
配置完成后,可以打开Makefile 验证:
第二步:编译和安装:
make make install
编译 uclibc:
第一步:配置configure。设置工具链和安装路径
# 需要手动修改Makefile CFLAGS += -muclibc ./configure --prefix=~/work/github/sqlite-autoconf-3350200/mips_out/uclibc --host=mips-linux-gnu # 或者 CFLAGS += -muclibc ./configure --prefix=~/work/github/sqlite-autoconf-3350200/mips_out/uclibc --host=mips-linux-gnu
- --prefix:指定安装路径。
- --host:指定工具链。注意,需要设置工具链的环境变量,否则检测不到工具链。
- CFLAGS += -muclibc:指定uclibc 环境
第二步:编译和安装
make make install
arm
arm 平台交叉编译类似。需要注意的点如下:
- 设置工具链的环境变量
- 指定交叉编译工具链为arm平台所用的工具链。比如 arm-linux-gnu(只要前缀)
3. sqlite 使用
当交叉编译后,就可以直接把sqlite3 拷贝到板子上运行。注意,glibc环境拷贝glibc的,uclibc环境拷贝uclibc的。
我们来看一个简单的示例:
#include <stdio.h> #include <pthread.h> #include <dlfcn.h> #include <stdlib.h> #include <string.h> #include <sqlite3.h> #define DATABASE_NAME "MyDBDemo.db" #define DATABASE_TABLE_NAME "table1" #define DATABASE_TABLE_MEMBER "name text, age int, note text, count int" #define DATABASE_TABLE_LABEL "name, age, note, count" #define CREATE 0 #define INSERT 1 #define DELETE 2 #define SELECT 3 #define UPDATE 4 #define DROP 5 #define VACUUM 6 #define PRAGMA 7 struct sqlite_db_str { char *sql; }; struct sqlite_db_str db_sqlstr[] = { [CREATE] = { .sql = "CREATE TABLE " }, [INSERT] = { .sql = "INSERT INTO " }, [DELETE] = { .sql = "DELETE FROM " }, [SELECT] = { .sql = "SELECT " }, [UPDATE] = { .sql = "UPDATE " }, [DROP] = { .sql = "DROP TABLE " }, [VACUUM] = { .sql = "VACUUM " }, [PRAGMA] = { .sql = "PRAGMA " }, }; int main(int argc, char *argv[]) { int ret = -1; int k = 0; sqlite3 *db_ctx = NULL; char *zErrMsg = NULL; /*Step1: create database */ ret = sqlite3_open_v2(DATABASE_NAME, &db_ctx, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE, NULL); if(ret){ printf("Open %s database errror!, ret: %d\n", DATABASE_NAME, ret); return -1; } /*Step2: create table */ char sql_buf[256] = {'\0'}; sprintf(sql_buf, "%s %s (%s);", db_sqlstr[CREATE].sql, DATABASE_TABLE_NAME, DATABASE_TABLE_LABEL); ret = sqlite3_exec(db_ctx, sql_buf, NULL, NULL, &zErrMsg); if( ret != SQLITE_OK ){ if( ret == 1 ){ /* table already exists */ printf("database [%s]: %s\n", DATABASE_NAME, zErrMsg); } else { fprintf(stderr, "SQL error: %s, ret: %d\n", zErrMsg, ret); sqlite3_free(zErrMsg); return -1; } } /*Step3: insert*/ for (k = 0; k < 10; k++) { char insert_buf[128] = {0}; sprintf(insert_buf, "'%s%d', %d, 'note_%d', %d", "Vinson", k, k, k, k); char sql_buf[1024] = {'\0'}; unsigned int sql_prefix_len = 0; sprintf(sql_buf, "%s %s (%s) VALUES (", db_sqlstr[INSERT].sql, DATABASE_TABLE_NAME, DATABASE_TABLE_LABEL); sql_prefix_len = strlen(sql_buf); memcpy(sql_buf+sql_prefix_len, insert_buf, strlen(insert_buf)); memcpy(sql_buf+sql_prefix_len + strlen(insert_buf), ");", strlen(");")); /* INSERT table1 (name age note count) VALUES (Vinson1,note1,1,1 )*/ ret = sqlite3_exec(db_ctx, sql_buf, NULL, NULL, &zErrMsg); if( ret != SQLITE_OK ){ fprintf(stderr, "SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); return -1; } if (ret < 0) { printf("insert table error! %d\n", ret); return -1; } } /*Step4: close*/ sqlite3_close(db_ctx); return 0; }
编译:
# 嵌入式设备 改成对应工具链:mips-linux-gun-gcc/arm-linux-gun-gcc gcc sqlite3_demo.c -o sqlite3_test -I./sqlite/include -L./sqlite/lib/ -lsqlite3 -ldl -lpthread -lm
- -I:指定sqlite 头文件包含
- -L:链接sqlite3 库。
- ldl:使用库需要
- lpthread:libsqlite3.a 使用。多线程相关
- lm:libsqlite3.a 使用。数学库
执行:将生成的程序拷到板子上可直接运行。(./sqlite3_test)生成 MyDBDemo.db 验证:通过交叉编译生成的bin文件 sqlite3,可直接打开查看,我们sqlite3_test生成的数据库。
./sqlite3 MyDBDemo.db
查看数据库信息:
.dump
查看数据库表:
.table
退出:
.quit
用 Navicat Premium 打开对比查看。
4. 总结
本文,主要就是嵌入式端sqlite3移植进行介绍,关于数据库的语法和使用,留待读者自行研究。有关sqlite3的接口使用,本文只给出了简单的示例,详细应用,见官网使用说明。