spatialite c samples 解析(1)


spatialite c samples 解析(1)


0.初始化spatialite扩展

由于spatialite是基于sqlite的扩展,所以在使用sqlite查询之前要先将sqatilate初始化。
代码如下
spatialite_init(0);

1.连接数据库

sqlite提供的连接数据库方法有三个:

 1    int sqlite3_open(
 2        const char *filename,   /* Database filename (UTF-8) */
 3        sqlite3 **ppDb          /* OUT: SQLite db handle */
 4    );
 5    int sqlite3_open16(
 6        const void *filename,   /* Database filename (UTF-16) */
 7        sqlite3 **ppDb          /* OUT: SQLite db handle */
 8    );
 9    int sqlite3_open_v2(
10      const char *filename,   /* Database filename (UTF-8) */
11      sqlite3 **ppDb,         /* OUT: SQLite db handle */
12      int flags,              /* Flags */
13      const char *zVfs        /* Name of VFS module to use */
14    );

数据库连接被放在在 *ppDb内,其他的查询操作可以通过它来找到所连接数据库。如果连接成功那么函数返回SQLITEOK;如果出现错误,
可以使用sqlite3
errmsg() 或者 sqlite3errmsg16()来获取错误的英文说明。需要注意的是,
不管是否连接成功,当不再需要数据库连接时,与连接数据库操作的资源都应该通过sqlite3
close()来释放。

其中 sqlite3openv2比另外两个多出的两个参数可以对所建立的连接进行额外的操作。
例如flags可以取SQLITEOPENREADONLY,SQLITEOPENREADWRITE,SQLITEOPENREADWRITE|SQLITEOPENCREATE 三个值,并且可以和SQLITEOPENNOMUTEX,
SQLITEOPENFULLMUTEX, SQLITEOPENSHAREDCACHE, SQLITEOPENPRIVATECACHE,
SQLITEOPENURI 共同使用(通过或、交(|,&)运算来操作);zVfs是与操作系统的接口,取NULL则为程序默认。

2.数据库查询

此处以sqlite3_prepare_v2为例:

1  int sqlite3_prepare_v2(
2      sqlite3 *db,            /* Database handle */
3      const char *zSql,       /* SQL statement, UTF-8 encoded */
4      int nByte,              /* Maximum length of zSql in bytes. */
5      sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
6      const char **pzTail     /* OUT: Pointer to unused portion of zSql */
7  );

其中 db即为上一步获取的ppDb,zSql是将要编译的SQL查询语句,**ppStmt为操作处理。

当执行prepare后,需要执行一次或多次

1    int sqlite_step(sqlite2_stmt*);

来读取数据。
通过执行

1    int sqlite3_column_count(sqlite3_stmt *pStmt);

可以查出总共查询到数据表的列数。

然后再执行spatialite中针对空间数据BLOB的方法来操作BLOB中的数据,下文再详细解释,先看代码:

 1    sqlite3 *handle;
 2    sqlite3_stmt *stmt;
 3    spatialite_init(0);
 4    ret = sqlite3_open_v2(path,&handle,SQLITE_OPEN_READONLY,NULL);
 5    if(ret != SQLITE_OK)
 6    { //ERROR HERE }
 7    sql = "SELECT * FROM mytable"
 8    ret = sqlite2_prepare_v2(handle,sql,strlen(sql),&stmt,NULL);
 9    if(ret != SQLITE_OK)
10    { //ERROR HERE }
11    n_columns = sqlite3_column_count(stmt);
12    while(true)
13    {
14        ret = sqlite3_step (stmt);
15        if (ret == SQLITE_DONE)
16            break;
17        if (ret == SQLITE_ROW)
18        {
19            row_no++;
20            printf ("row #%d\n", row_no);
21        }
22        for (ic = 0; ic < n_columns; ic++)
23        {
24            printf ("\t%-10s = ",sqlite3_column_name (stmt, ic));
25            switch (sqlite3_column_type (stmt, ic))
26            {
27                case SQLITE_INTEGER:
28                printf ("%d", sqlite3_column_int (stmt, ic));
29                    break;
30                case SQLITE_BLOB:
31                    blob = sqlite3_column_blob (stmt, ic);
32                    blob_size = sqlite3_column_bytes (stmt, ic);
33                    geom = gaiaFromSpatiaLiteBlobWkb (blob,blob_size);
34                    if (!geom)
35                        printf ("BLOB [%d bytes]", blob_size);
36                    else
37                    {
38                        geom_type = gaiaGeometryType (geom);
39                        if (geom_type == GAIA_UNKNOWN)
40                            printf ("EMPTY or NULL GEOMETRY");
41                        else
42                        {
43                            char *geom_name;
44                            if (geom_type == GAIA_POINT)
45                                geom_name = "POINT";               
46                            if (geom_type == GAIA_POLYGON)
47                                geom_name = "POLYGON";
48                            printf ("%s SRID=%d", geom_name,geom->Srid);
49                            if (geom_type == GAIA_POLYGON ||geom_type ==GAIA_MULTIPOLYGON)
50                            {
51                                gaiaGeomCollArea (geom, &measure);
52                                printf (" area=%1.2lf", measure);
53                            }
54                        }
55                        gaiaFreeGeomColl (geom);
56                    }
57                    break;
58                }
59    }

以上代码在列属性上只列出了两个case:Integer和BLOB,Geometry类型也只列出Point和Polygon,
更具体的参见sqlite c API
spatialite c API

此处解释上边代码中遇到的几个spatialite函数。
首先就是读取出BLOB数据:

1    const void * blob;
2    blob = sqlite3_column_blob (stmt, ic);

然后通过spatialite的方法读取为空间处理数据(以gaia开头的函数都是spatialite的方法,而以sqlite开通的为sqlite的方法,spatialite是sqlite的扩展即体现在此处)。

1    gaiaGeomCollPtr geom;
2    geom = gaiaFromSpatiaLiteBlobWkb (blob,blob_size);

gaiaGeomCollPtr的定义如下:

 1    typedef struct gaiaGeomCollStruct {
 2        int Srid;
 3        gaiaPointPtr FirstPoint;
 4        gaiaLinestringPtr FirstLinestring;
 5        gaiaPolygonPtr FirstPolygon;
 6        double MinX;
 7        double MinY;
 8        double MaxX;
 9        double MaxY;
10    } gaiaGeomColl;
11    typedef gaiaGeomColl * gaiaGeomCollPtr;

可见,gaiaGeomCollPtr 是指针形式,且其数据项包括该地理数据的MBR(Minimum Bounding Rectangle 最小外接矩形)。

gaiaFromSpatiaLiteBlobWkb函数的第一个参数是const unsigned char * blob_wkb,而WKB(Well Known Binary)
即为我们从数据库中读取的BLOB格式的数据。也就是说sqlite是将空间数据转换成WKB后存储。

代码后边的gaiaGeometryType gaiaGeomCollArea等方法在此不赘述,详见
spatialite c API

Powered by Engin & toto

comments powered by Disqus