140 lines
4.2 KiB
C++
140 lines
4.2 KiB
C++
/*****************************************************************************
|
|
*
|
|
* This file is part of Mapnik (c++ mapping toolkit)
|
|
*
|
|
* Copyright (C) 2016 Artem Pavlenko
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifndef MAPNIK_SQLITE_PREPARED_HPP
|
|
#define MAPNIK_SQLITE_PREPARED_HPP
|
|
|
|
// mapnik
|
|
#include <mapnik/debug.hpp>
|
|
#include <mapnik/datasource.hpp>
|
|
#include <mapnik/params.hpp>
|
|
#include <mapnik/geometry/box2d.hpp>
|
|
#include <mapnik/util/noncopyable.hpp>
|
|
|
|
// boost
|
|
#include <memory>
|
|
|
|
// stl
|
|
#include <string.h>
|
|
|
|
#include "sqlite_connection.hpp"
|
|
|
|
// sqlite
|
|
extern "C" {
|
|
#include <sqlite3.h>
|
|
}
|
|
|
|
class prepared_index_statement : mapnik::util::noncopyable
|
|
{
|
|
|
|
public:
|
|
prepared_index_statement(std::shared_ptr<sqlite_connection> ds, std::string const& sql)
|
|
: ds_(ds),
|
|
stmt_(0)
|
|
{
|
|
|
|
const int rc = sqlite3_prepare_v2(*(*ds_),
|
|
sql.c_str(),
|
|
-1,
|
|
&stmt_,
|
|
0);
|
|
|
|
if (rc != SQLITE_OK)
|
|
{
|
|
std::ostringstream index_error;
|
|
index_error << "Sqlite Plugin: auto-index table creation failed: '"
|
|
<< sqlite3_errmsg(*(*ds_)) << "' query was: "
|
|
<< sql;
|
|
|
|
throw mapnik::datasource_exception(index_error.str());
|
|
}
|
|
}
|
|
|
|
~prepared_index_statement()
|
|
{
|
|
if (stmt_)
|
|
{
|
|
int res = sqlite3_finalize(stmt_);
|
|
if (res != SQLITE_OK)
|
|
{
|
|
if (*(*ds_))
|
|
{
|
|
MAPNIK_LOG_ERROR(sqlite) << "~prepared_index_statement:"
|
|
<< sqlite3_errmsg(*(*ds_));
|
|
}
|
|
else
|
|
{
|
|
MAPNIK_LOG_ERROR(sqlite) << "~prepared_index_statement:"
|
|
<< res;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void bind(sqlite_int64 const pkid)
|
|
{
|
|
if (sqlite3_bind_int64(stmt_, 1, pkid) != SQLITE_OK)
|
|
{
|
|
throw mapnik::datasource_exception("SQLite Plugin: invalid value for for key field while generating index");
|
|
}
|
|
|
|
}
|
|
|
|
void bind(mapnik::box2d<double> const& bbox)
|
|
{
|
|
if ((sqlite3_bind_double(stmt_, 2, bbox.minx()) != SQLITE_OK) ||
|
|
(sqlite3_bind_double(stmt_, 3, bbox.maxx()) != SQLITE_OK) ||
|
|
(sqlite3_bind_double(stmt_, 4, bbox.miny()) != SQLITE_OK) ||
|
|
(sqlite3_bind_double(stmt_, 5, bbox.maxy()) != SQLITE_OK))
|
|
{
|
|
throw mapnik::datasource_exception("SQLite Plugin: invalid value for for extent while generating index");
|
|
}
|
|
}
|
|
|
|
bool step_next ()
|
|
{
|
|
const int status = sqlite3_step(stmt_);
|
|
if (status != SQLITE_DONE)
|
|
{
|
|
std::ostringstream s;
|
|
s << "SQLite Plugin: inserting bbox into rtree index failed";
|
|
std::string msg(sqlite3_errmsg(sqlite3_db_handle(stmt_)));
|
|
if (msg != "unknown error")
|
|
{
|
|
s << ": " << msg;
|
|
}
|
|
throw mapnik::datasource_exception(s.str());
|
|
}
|
|
sqlite3_clear_bindings(stmt_);
|
|
if (sqlite3_reset(stmt_) != SQLITE_OK)
|
|
{
|
|
throw mapnik::datasource_exception("sqlite3_reset failed");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
std::shared_ptr<sqlite_connection> ds_;
|
|
sqlite3_stmt * stmt_;
|
|
};
|
|
|
|
#endif // MAPNIK_SQLITE_PREPARED_HPP
|