mirror of
https://github.com/yasuhirokimura/db18
synced 2026-06-08 18:29:23 +00:00
162 lines
3.4 KiB
C
162 lines
3.4 KiB
C
/*-
|
|
* Copyright (c) 1997, 2019 Oracle and/or its affiliates. All rights reserved.
|
|
*
|
|
* See the file EXAMPLES-LICENSE for license information.
|
|
*
|
|
*/
|
|
|
|
#include "ex_sql_utils.h"
|
|
|
|
/*
|
|
* This example shows how to create, maintain, and query an R-Tree index.
|
|
*
|
|
* A new R*Tree index is created as follows:
|
|
* CREATE VIRTUAL TABLE <name> USING rtree(<column-names>);
|
|
*
|
|
* The usual INSERT, UPDATE, and DELETE commands work on an R*Tree index just
|
|
* like on regular tables.
|
|
*
|
|
* Any valid query will work against an R*Tree index. Especially, you can
|
|
* efficiently do inequality queries against the coordinate ranges with an
|
|
* R-Tree index.
|
|
*/
|
|
|
|
const double data[8][4] = {{1, 4, 2, 4}, {3, 6, 4, 7},
|
|
{5, 7, 1, 8}, {11, 14, 2, 4}, {10, 15, 1, 5},
|
|
{8, 12,3, 6}, {9, 11, 7, 9}, {9, 14, 7, 10}};
|
|
|
|
|
|
/* Create a 2-dimention rtree index. */
|
|
int create_rtree(db)
|
|
db_handle *db;
|
|
{
|
|
const char* sql;
|
|
|
|
/*
|
|
* create an rtree which has 5 cloumns: id, minx, maxX, minY, maxY.
|
|
|
|
*/
|
|
|
|
sql = "DROP TABLE IF EXISTS rtree_index;\n"
|
|
"\tCREATE VIRTUAL TABLE rtree_index USING rtree(\n"
|
|
"\tid,\n"
|
|
"\tminX, maxX,\n"
|
|
"\tminY, maxY\n"
|
|
"\t);";
|
|
|
|
return exec_sql(db, sql);
|
|
}
|
|
|
|
/* Insert rectangles into the rtree-index. */
|
|
int populate_data(db)
|
|
db_handle *db;
|
|
{
|
|
int i, j, rc, errflag;
|
|
const char* sql;
|
|
sqlite3_stmt* stmt;
|
|
|
|
/* Prepare a statement for rtree insert. */
|
|
sql = "INSERT INTO rtree_index VALUES(?, ?, ?, ?, ?)";
|
|
|
|
sqlite3_prepare_v2(db, sql, (int)strlen(sql), &stmt, NULL);
|
|
error_handler(db);
|
|
|
|
errflag = 0;
|
|
|
|
/* Insert 8 rectangles with the id from 1-8 into the rtree-index. */
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
/* Bind id with the value i+1. */
|
|
sqlite3_bind_int(stmt, 1, i + 1);
|
|
error_handler(db);
|
|
|
|
/*
|
|
* Get the values of minX, maxX, minY, maxY from data[i] and
|
|
* bind them.
|
|
*/
|
|
for (j = 0; j < 4; j++) {
|
|
sqlite3_bind_double(stmt, j+2, data[i][j]);
|
|
error_handler(db);
|
|
}
|
|
|
|
/* Execute the query expression. */
|
|
sqlite3_step(stmt);
|
|
|
|
/* Reset stmt when SQLITE_DONE. The sqlite3_reset() function
|
|
* is called to reset a prepared statement object back to its
|
|
* initial state, ready to be re-executed. Any SQL statement
|
|
* variables that had values bound to them using the
|
|
* sqlite3_bind_*() API retain their values.
|
|
*/
|
|
rc = sqlite3_errcode(db);
|
|
switch(rc) {
|
|
case SQLITE_DONE:
|
|
sqlite3_reset(stmt);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "ERROR: %s. ERRCODE: %d\n",
|
|
sqlite3_errmsg(db), rc);
|
|
errflag = 1;
|
|
break;
|
|
}
|
|
if (errflag)
|
|
break;
|
|
}
|
|
|
|
/* Final cleanup. */
|
|
sqlite3_finalize(stmt);
|
|
error_handler(db);
|
|
|
|
return errflag;
|
|
}
|
|
|
|
/* Query the rtree-index. */
|
|
int query_rtree(db)
|
|
db_handle *db;
|
|
{
|
|
const char* sql;
|
|
|
|
/* Select all records in rtree_index. */
|
|
sql = "SELECT * FROM rtree_index";
|
|
exec_sql(db, sql);
|
|
|
|
/*
|
|
* Select the IDs of rectangles which are contained within the query
|
|
* box (5, 15, 1, 8).
|
|
*/
|
|
sql = "SELECT id FROM rtree_index\n"
|
|
"\tWHERE minX >= 5 AND maxX <= 15\n"
|
|
"\tAND minY >= 1 AND maxY <= 8";
|
|
exec_sql(db, sql);
|
|
|
|
/*
|
|
* Select the IDs of rectangles which overlap the query box
|
|
* (5, 15, 1, 8).
|
|
*/
|
|
sql = "SELECT id FROM rtree_index\n"
|
|
"\tWHERE maxX >= 5 AND minX <= 12\n"
|
|
"\tAND maxY >= 3 AND minY <= 7";
|
|
exec_sql(db, sql);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main()
|
|
{
|
|
db_handle *db;
|
|
|
|
/* Setup environment */
|
|
db = setup("./ex_rtree.db");
|
|
|
|
create_rtree(db);
|
|
|
|
populate_data(db);
|
|
|
|
query_rtree(db);
|
|
|
|
/* End. */
|
|
cleanup(db);
|
|
return 0;
|
|
}
|