在ROS系统中,因为消息种类太多,要对这些消息进行统一存储并且允许检索,就面临一个问题:如何存储,用什么存储,如何检索?
鉴于我们第一阶段使用了统一数据模型对各种消息进行了统一封装:将所有消息共有的部分提取出来生成各个字段,而将差异部分作为blob进行存储。这个模型存在的一个重要问题就是不能对差异部分进行检索。
为了解决或者部分解决上述问题,我们进行了调研,发现sqlite3存在json扩展,这个是从sliqte3.09版本之后就自带的。所以我们开始考虑进一步扩展统一数据封装模型,将差异性的部分放进去以支持检索。
由于目前sqlite3支持的数据格式还是传统的5种,json还没有独立升格为一种数据类型,所以目前仍然以text类型存储json数据,如{"key1":"1", "key2":"2"}这种样式存储。我们在原来的表设计基础上增加一个text字段来存储json数据。而ros中的各种msg使用我们前面的博客中介绍的ROS的msssage的Printer类和我们开发的msg2Json方法来实现ros消息到json的格式转换(里面的数组我们暂时不处理)。
后面的借助json1的函数实现json部分数据的检索,同时支持传统的sql检索和json检索混合模式检索。下面是我们使用json扩展的过程(摸索中出现了很多错误,很多所谓的介绍只是说了sqlite扩展是啥,怎么写一个扩展,怎么用并不清楚,官网给出的说明以及网上的使用教程基本没有):
1. 编译json库生成libjson.so
2. 打开数据库,获取数据库的句柄
3. 开启load_extension功能
4. 加载json库和入口函数
5. 使用json扩展
上述顺序中,2和3的顺序不能错,也就是说load_extension是要指定为哪个db加载扩展,这时候db不能是NULL,所以要先打开数据库获得句柄。这个是我不断调试摸索出来的(sqlite的扩展使用错误的话,只会报段错误,没有其他任何有用的提示信息)。
下面分别按上述步骤介绍:
1. 编译json扩展得到库文件
在Ubuntu16.04里面使用apt-get install sqlite3 libsqlite3的时候安装的是sqlite3 3.11.0-1ubuntu1.2这一版的二进制包。我调研后发现这里面也是开启了json功能的,至于怎么验证,请参考我的另一个博客。因为要加载扩展,所以首先要存在json库文件,所以我先编译它。那么第一步,我们要去下载对应版本的sqlite3的源码。具体地址: https://launchpad.net/ubuntu/+source/sqlite3/3.11.0-1ubuntu1.2 从下面的介绍我们还可以发现,我们使用apt-get 安装sqlite3中其实并没有json扩展的库文件,但是我们可以在sqlite3命令行中使用json扩展的相关函数。经过调研发现这其实是2套东西,一套sqlite3的sql扩展,一套是sqlite3的C-API扩展。sql扩展默认安装了,所以可以直接在命令行中使用json函数。但C-API扩展并没有安装,所以我们要手动编译得到库文件。
我们下载sqlite3_3.11.0.orig.tar.xz文件(sqlite3_3.11.0.orig-www.tar.xz是html版的api说明)。源码包里面有ext目录,里面是各种扩展,我们要使用的是misc下面的json1.c这个文件。进入到这个目录,执行如下命令
cp ../../sqlite3ext.h ./
gcc -fPIC -shared json1.c sqlite3ext.h -o libjson.so
注意:这里有的教程说不用sqlite3ext.h编译进去,这个为了安全考虑,我还是编译进入了,因为打开json1.c看一下,发现它上来就加载了sqlite3exe.h这个文件。
这样就可以得到json扩展的库文件了,接下来把它复制到/usr/lib/下面(也可以把它放到某个具体路径下)。
2. 打开数据库,得到数据库句柄

这里使用了spatialite插件,其作用是让sqlite3支持地理信息系统,支持二维空间索引,对应的需要安装spatialite和libspatialite包。
3. 启用json扩展
![]()
4. 加载json扩展
![]()
这里sqlite3_json_init是库文件的入口,可以打开json1.c来查看它的入口(这个是在很多教程里面介绍了的,默认的是sqlite3_extension_init)。根据说明文件来看,如果前面提供的库文件名字以lib开头和.so结尾,那么也可以不写入口函数名,它会先找sqlite3_extension_init,如果不存在,则会找库文件名lib和.so之间的名字x对应的入口sqlite3_x_init。如果库文件不是以lib或so结尾,也它考虑先去掉lib头和.so尾,然后把剩余部分当作x,找sqlite3_x_init作为入口函数。
5. 使用json扩展进行查询:
![]()

最低0.47元/天 解锁文章
15万+





