mapnik/utils/pgsql2sqlite/sqlite.hpp

202 lines
4.9 KiB
C++
Raw Normal View History

/*****************************************************************************
2011-11-14 03:54:32 +00:00
*
* This file is part of Mapnik (c++ mapping toolkit)
*
2021-01-05 14:39:07 +00:00
* Copyright (C) 2021 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
*
*****************************************************************************/
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/util/variant.hpp>
// boost
#include <memory>
2016-03-10 19:44:44 +00:00
#include <mapnik/warning.hpp>
MAPNIK_DISABLE_WARNING_PUSH
2016-03-10 19:44:44 +00:00
#include <mapnik/warning_ignore.hpp>
#include <sqlite3.h>
MAPNIK_DISABLE_WARNING_POP
2022-01-26 19:41:37 +00:00
// stl
2014-08-12 18:10:32 +00:00
#ifdef MAPNIK_DEBUG
#include <cassert>
#endif
2014-08-12 19:08:52 +00:00
#include <iostream>
#include <string>
#include <vector>
2022-01-26 19:41:37 +00:00
namespace mapnik {
namespace sqlite {
2022-01-26 19:41:37 +00:00
class database : private util::noncopyable
{
friend class prepared_statement;
2011-11-14 03:54:32 +00:00
2022-01-26 19:41:37 +00:00
struct database_closer
{
void operator()(sqlite3* db)
2010-06-02 11:03:30 +00:00
{
#ifdef MAPNIK_DEBUG
2022-01-26 19:41:37 +00:00
std::cerr << "close database " << db << "\n";
#endif
2022-01-26 19:41:37 +00:00
sqlite3_close(db);
}
2010-06-02 11:03:30 +00:00
};
2022-01-26 19:41:37 +00:00
using sqlite_db = std::shared_ptr<sqlite3>;
sqlite_db db_;
public:
database(std::string const& name);
~database();
bool execute(std::string const& sql);
};
struct null_type
{};
struct blob
{
blob(const char* buf, unsigned size)
: buf_(buf)
, size_(size)
{}
const char* buf_;
unsigned size_;
};
using value_type = mapnik::util::variant<int, double, std::string, blob, null_type>;
using record_type = std::vector<value_type>;
class prepared_statement : util::noncopyable
{
struct binder
2010-06-02 11:03:30 +00:00
{
2022-01-26 19:41:37 +00:00
binder(sqlite3_stmt* stmt, unsigned index)
: stmt_(stmt)
, index_(index)
{}
2009-02-21 11:22:17 +00:00
2022-01-26 19:41:37 +00:00
bool operator()(null_type)
2010-06-02 11:03:30 +00:00
{
2022-01-26 19:41:37 +00:00
if (sqlite3_bind_null(stmt_, index_) != SQLITE_OK)
2010-06-02 11:03:30 +00:00
{
2022-01-26 19:41:37 +00:00
std::cerr << "cannot bind nullptr\n";
return false;
}
2022-01-26 19:41:37 +00:00
return true;
}
2011-11-14 03:54:32 +00:00
2022-01-26 19:41:37 +00:00
bool operator()(int val)
{
if (sqlite3_bind_int(stmt_, index_, val) != SQLITE_OK)
{
2022-01-26 19:41:37 +00:00
std::cerr << "cannot bind " << val << "\n";
return false;
}
2022-01-26 19:41:37 +00:00
return true;
}
2011-11-14 03:54:32 +00:00
2022-01-26 19:41:37 +00:00
bool operator()(double val)
{
if (sqlite3_bind_double(stmt_, index_, val) != SQLITE_OK)
{
2022-01-26 19:41:37 +00:00
std::cerr << "cannot bind " << val << "\n";
return false;
}
2022-01-26 19:41:37 +00:00
return true;
}
2011-11-14 03:54:32 +00:00
2022-01-26 19:41:37 +00:00
bool operator()(std::string const& val)
{
if (sqlite3_bind_text(stmt_, index_, val.c_str(), val.length(), SQLITE_STATIC) != SQLITE_OK)
2009-02-21 11:22:17 +00:00
{
2022-01-26 19:41:37 +00:00
std::cerr << "cannot bind " << val << "\n";
return false;
2009-02-21 11:22:17 +00:00
}
2022-01-26 19:41:37 +00:00
return true;
}
2011-11-14 03:54:32 +00:00
2022-01-26 19:41:37 +00:00
bool operator()(blob const& val)
2010-06-02 11:03:30 +00:00
{
2022-01-26 19:41:37 +00:00
if (sqlite3_bind_blob(stmt_, index_, val.buf_, val.size_, SQLITE_STATIC) != SQLITE_OK)
{
2022-01-26 19:41:37 +00:00
std::cerr << "cannot bind BLOB\n";
return false;
}
2022-01-26 19:41:37 +00:00
return true;
2010-06-02 11:03:30 +00:00
}
2011-11-14 03:54:32 +00:00
2022-01-26 19:41:37 +00:00
sqlite3_stmt* stmt_;
unsigned index_;
};
public:
prepared_statement(database& db, std::string const& sql)
: db_(db.db_.get())
, stmt_(0)
{
const char* tail;
// char * err_msg;
int res = sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt_, &tail);
if (res != SQLITE_OK)
2010-06-02 11:03:30 +00:00
{
2022-01-26 19:41:37 +00:00
std::cerr << "ERR:" << res << "\n";
throw;
2010-06-02 11:03:30 +00:00
}
2022-01-26 19:41:37 +00:00
}
2011-11-14 03:54:32 +00:00
2022-01-26 19:41:37 +00:00
~prepared_statement()
{
int res = sqlite3_finalize(stmt_);
if (res != SQLITE_OK)
2011-11-14 03:54:32 +00:00
{
2022-01-26 19:41:37 +00:00
std::cerr << "ERR:" << res << "\n";
}
}
bool insert_record(record_type const& rec) const
{
2009-02-21 00:23:41 +00:00
#ifdef MAPNIK_DEBUG
2022-01-26 19:41:37 +00:00
assert(unsigned(sqlite3_bind_parameter_count(stmt_)) == rec.size());
2009-02-21 00:23:41 +00:00
#endif
2022-01-26 19:41:37 +00:00
record_type::const_iterator itr = rec.begin();
record_type::const_iterator end = rec.end();
int count = 1;
for (; itr != end; ++itr)
{
binder op(stmt_, count++);
if (!util::apply_visitor(op, *itr))
{
2022-01-26 19:41:37 +00:00
return false;
}
2010-06-02 11:03:30 +00:00
}
2022-01-26 19:41:37 +00:00
sqlite3_step(stmt_);
sqlite3_reset(stmt_);
return true;
2010-06-02 11:03:30 +00:00
}
2022-01-26 19:41:37 +00:00
private:
sqlite3* db_;
sqlite3_stmt* stmt_;
};
} // namespace sqlite
} // namespace mapnik