11be35a165
To do so, a few dependencies have been imported: * external/bsd/lutok * external/mit/lua * external/public-domain/sqlite * external/public-domain/xz The Kyua framework is the new generation of ATF (Automated Test Framework), it is composed of: * external/bsd/atf * external/bsd/kyua-atf-compat * external/bsd/kyua-cli * external/bsd/kyua-tester * tests Kyua/ATF being written in C++, it depends on libstdc++ which is provided by GCC. As this is not part of the sources, Kyua is only compiled when the native GCC utils are installed. To install Kyua do the following: * In a cross-build enviromnent, add the following to the build.sh commandline: -V MKBINUTILS=yes -V MKGCCCMDS=yes WARNING: At this point the import is still experimental, and not supported on native builds (a.k.a make build). Change-Id: I26aee23c5bbd2d64adcb7c1beb98fe0d479d7ada
615 lines
18 KiB
C++
615 lines
18 KiB
C++
// Copyright 2011 Google Inc.
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are
|
|
// met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of Google Inc. nor the names of its contributors
|
|
// may be used to endorse or promote products derived from this software
|
|
// without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
#include "utils/sqlite/statement.hpp"
|
|
|
|
extern "C" {
|
|
#include <sqlite3.h>
|
|
}
|
|
|
|
#include <map>
|
|
|
|
#include "utils/defs.hpp"
|
|
#include "utils/format/macros.hpp"
|
|
#include "utils/logging/macros.hpp"
|
|
#include "utils/sanity.hpp"
|
|
#include "utils/sqlite/c_gate.hpp"
|
|
#include "utils/sqlite/exceptions.hpp"
|
|
|
|
namespace sqlite = utils::sqlite;
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
static sqlite::type c_type_to_cxx(const int) UTILS_PURE;
|
|
|
|
|
|
/// Maps a SQLite 3 data type to our own representation.
|
|
///
|
|
/// \param original The native SQLite 3 data type.
|
|
///
|
|
/// \return Our internal representation for the native data type.
|
|
static sqlite::type
|
|
c_type_to_cxx(const int original)
|
|
{
|
|
switch (original) {
|
|
case SQLITE_BLOB: return sqlite::type_blob;
|
|
case SQLITE_FLOAT: return sqlite::type_float;
|
|
case SQLITE_INTEGER: return sqlite::type_integer;
|
|
case SQLITE_NULL: return sqlite::type_null;
|
|
case SQLITE_TEXT: return sqlite::type_text;
|
|
default: UNREACHABLE_MSG("Unknown data type returned by SQLite 3");
|
|
}
|
|
UNREACHABLE;
|
|
}
|
|
|
|
|
|
/// Handles the return value of a sqlite3_bind_* call.
|
|
///
|
|
/// \param db The database the call was made on.
|
|
/// \param api_function The name of the sqlite3_bind_* function called.
|
|
/// \param error The error code returned by the function; can be SQLITE_OK.
|
|
///
|
|
/// \throw std::bad_alloc If there was no memory for the binding.
|
|
/// \throw api_error If the binding fails for any other reason.
|
|
static void
|
|
handle_bind_error(sqlite::database& db, const char* api_function,
|
|
const int error)
|
|
{
|
|
switch (error) {
|
|
case SQLITE_OK:
|
|
return;
|
|
case SQLITE_RANGE:
|
|
UNREACHABLE_MSG("Invalid index for bind argument");
|
|
case SQLITE_NOMEM:
|
|
throw std::bad_alloc();
|
|
default:
|
|
throw sqlite::api_error::from_database(db, api_function);
|
|
}
|
|
}
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
/// Internal implementation for sqlite::statement.
|
|
struct utils::sqlite::statement::impl {
|
|
/// The database this statement belongs to.
|
|
sqlite::database& db;
|
|
|
|
/// The SQLite 3 internal statement.
|
|
::sqlite3_stmt* stmt;
|
|
|
|
/// Cache for the column names in a statement; lazily initialized.
|
|
std::map< std::string, int > column_cache;
|
|
|
|
/// Constructor.
|
|
///
|
|
/// \param db_ The database this statement belongs to. Be aware that we
|
|
/// keep a *reference* to the database; in other words, if the database
|
|
/// vanishes, this object will become invalid. (It'd be trivial to keep
|
|
/// a shallow copy here instead, but I feel that statements that outlive
|
|
/// their database represents sloppy programming.)
|
|
/// \param stmt_ The SQLite internal statement.
|
|
impl(database& db_, ::sqlite3_stmt* stmt_) :
|
|
db(db_),
|
|
stmt(stmt_)
|
|
{
|
|
}
|
|
|
|
/// Destructor.
|
|
///
|
|
/// It is important to keep this as part of the 'impl' class instead of the
|
|
/// container class. The 'impl' class is destroyed exactly once (because it
|
|
/// is managed by a shared_ptr) and thus releasing the resources here is
|
|
/// OK. However, the container class is potentially released many times,
|
|
/// which means that we would be double-freeing the internal object and
|
|
/// reusing invalid data.
|
|
~impl(void)
|
|
{
|
|
(void)::sqlite3_finalize(stmt);
|
|
}
|
|
};
|
|
|
|
|
|
/// Initializes a statement object.
|
|
///
|
|
/// This is an internal function. Use database::create_statement() to
|
|
/// instantiate one of these objects.
|
|
///
|
|
/// \param db The database this statement belongs to.
|
|
/// \param raw_stmt A void pointer representing a SQLite native statement of
|
|
/// type sqlite3_stmt.
|
|
sqlite::statement::statement(database& db, void* raw_stmt) :
|
|
_pimpl(new impl(db, static_cast< ::sqlite3_stmt* >(raw_stmt)))
|
|
{
|
|
}
|
|
|
|
|
|
/// Destructor for the statement.
|
|
///
|
|
/// Remember that statements are reference-counted, so the statement will only
|
|
/// cease to be valid once its last copy is destroyed.
|
|
sqlite::statement::~statement(void)
|
|
{
|
|
}
|
|
|
|
|
|
/// Executes a statement that is not supposed to return any data.
|
|
///
|
|
/// Use this function to execute DDL and INSERT statements; i.e. statements that
|
|
/// only have one processing step and deliver no rows. This frees the caller
|
|
/// from having to deal with the return value of the step() function.
|
|
///
|
|
/// \pre The statement to execute will not produce any rows.
|
|
void
|
|
sqlite::statement::step_without_results(void)
|
|
{
|
|
const bool data = step();
|
|
INV_MSG(!data, "The statement should not have produced any rows, but it "
|
|
"did");
|
|
}
|
|
|
|
|
|
/// Performs a processing step on the statement.
|
|
///
|
|
/// \return True if the statement returned a row; false if the processing has
|
|
/// finished.
|
|
///
|
|
/// \throw api_error If the processing of the step raises an error.
|
|
bool
|
|
sqlite::statement::step(void)
|
|
{
|
|
const int error = ::sqlite3_step(_pimpl->stmt);
|
|
switch (error) {
|
|
case SQLITE_DONE:
|
|
LD("Step statement; no more rows");
|
|
return false;
|
|
case SQLITE_ROW:
|
|
LD("Step statement; row available for processing");
|
|
return true;
|
|
default:
|
|
throw api_error::from_database(_pimpl->db, "sqlite3_step");
|
|
}
|
|
UNREACHABLE;
|
|
}
|
|
|
|
|
|
/// Returns the number of columns in the step result.
|
|
///
|
|
/// \return The number of columns available for data retrieval.
|
|
int
|
|
sqlite::statement::column_count(void)
|
|
{
|
|
return ::sqlite3_column_count(_pimpl->stmt);
|
|
}
|
|
|
|
|
|
/// Returns the name of a particular column in the result.
|
|
///
|
|
/// \param index The column to request the name of.
|
|
///
|
|
/// \return The name of the requested column.
|
|
std::string
|
|
sqlite::statement::column_name(const int index)
|
|
{
|
|
const char* name = ::sqlite3_column_name(_pimpl->stmt, index);
|
|
if (name == NULL)
|
|
throw api_error::from_database(_pimpl->db, "sqlite3_column_name");
|
|
return name;
|
|
}
|
|
|
|
|
|
/// Returns the type of a particular column in the result.
|
|
///
|
|
/// \param index The column to request the type of.
|
|
///
|
|
/// \return The type of the requested column.
|
|
sqlite::type
|
|
sqlite::statement::column_type(const int index)
|
|
{
|
|
return c_type_to_cxx(::sqlite3_column_type(_pimpl->stmt, index));
|
|
}
|
|
|
|
|
|
/// Finds a column by name.
|
|
///
|
|
/// \param name The name of the column to search for.
|
|
///
|
|
/// \return The column identifier.
|
|
///
|
|
/// \throw value_error If the name cannot be found.
|
|
int
|
|
sqlite::statement::column_id(const char* name)
|
|
{
|
|
std::map< std::string, int >& cache = _pimpl->column_cache;
|
|
|
|
if (cache.empty()) {
|
|
for (int i = 0; i < column_count(); i++) {
|
|
const std::string aux_name = column_name(i);
|
|
INV(cache.find(aux_name) == cache.end());
|
|
cache[aux_name] = i;
|
|
}
|
|
}
|
|
|
|
const std::map< std::string, int >::const_iterator iter = cache.find(name);
|
|
if (iter == cache.end())
|
|
throw invalid_column_error(name);
|
|
else
|
|
return (*iter).second;
|
|
}
|
|
|
|
|
|
/// Returns a particular column in the result as a blob.
|
|
///
|
|
/// \param index The column to retrieve.
|
|
///
|
|
/// \return A block of memory with the blob contents. Note that the pointer
|
|
/// returned by this call will be invalidated on the next call to any SQLite API
|
|
/// function.
|
|
sqlite::blob
|
|
sqlite::statement::column_blob(const int index)
|
|
{
|
|
PRE(column_type(index) == type_blob);
|
|
return blob(::sqlite3_column_blob(_pimpl->stmt, index),
|
|
::sqlite3_column_bytes(_pimpl->stmt, index));
|
|
}
|
|
|
|
|
|
/// Returns a particular column in the result as a double.
|
|
///
|
|
/// \param index The column to retrieve.
|
|
///
|
|
/// \return The double value.
|
|
double
|
|
sqlite::statement::column_double(const int index)
|
|
{
|
|
PRE(column_type(index) == type_float);
|
|
return ::sqlite3_column_double(_pimpl->stmt, index);
|
|
}
|
|
|
|
|
|
/// Returns a particular column in the result as an integer.
|
|
///
|
|
/// \param index The column to retrieve.
|
|
///
|
|
/// \return The integer value. Note that the value may not fit in an integer
|
|
/// depending on the platform. Use column_int64 to retrieve the integer without
|
|
/// truncation.
|
|
int
|
|
sqlite::statement::column_int(const int index)
|
|
{
|
|
PRE(column_type(index) == type_integer);
|
|
return ::sqlite3_column_int(_pimpl->stmt, index);
|
|
}
|
|
|
|
|
|
/// Returns a particular column in the result as a 64-bit integer.
|
|
///
|
|
/// \param index The column to retrieve.
|
|
///
|
|
/// \return The integer value.
|
|
int64_t
|
|
sqlite::statement::column_int64(const int index)
|
|
{
|
|
PRE(column_type(index) == type_integer);
|
|
return ::sqlite3_column_int64(_pimpl->stmt, index);
|
|
}
|
|
|
|
|
|
/// Returns a particular column in the result as a double.
|
|
///
|
|
/// \param index The column to retrieve.
|
|
///
|
|
/// \return A C string with the contents. Note that the pointer returned by
|
|
/// this call will be invalidated on the next call to any SQLite API function.
|
|
/// If you want to be extra safe, store the result in a std::string to not worry
|
|
/// about this.
|
|
std::string
|
|
sqlite::statement::column_text(const int index)
|
|
{
|
|
PRE(column_type(index) == type_text);
|
|
return reinterpret_cast< const char* >(::sqlite3_column_text(
|
|
_pimpl->stmt, index));
|
|
}
|
|
|
|
|
|
/// Returns the number of bytes stored in the column.
|
|
///
|
|
/// \pre This is only valid for columns of type blob and text.
|
|
///
|
|
/// \param index The column to retrieve the size of.
|
|
///
|
|
/// \return The number of bytes in the column. Remember that strings are stored
|
|
/// in their UTF-8 representation; this call returns the number of *bytes*, not
|
|
/// characters.
|
|
int
|
|
sqlite::statement::column_bytes(const int index)
|
|
{
|
|
PRE(column_type(index) == type_blob || column_type(index) == type_text);
|
|
return ::sqlite3_column_bytes(_pimpl->stmt, index);
|
|
}
|
|
|
|
|
|
/// Type-checked version of column_blob.
|
|
///
|
|
/// \param name The name of the column to retrieve.
|
|
///
|
|
/// \return The same as column_blob if the value can be retrieved.
|
|
///
|
|
/// \throw error If the type of the cell to retrieve is invalid.
|
|
/// \throw invalid_column_error If name is invalid.
|
|
sqlite::blob
|
|
sqlite::statement::safe_column_blob(const char* name)
|
|
{
|
|
const int column = column_id(name);
|
|
if (column_type(column) != sqlite::type_blob)
|
|
throw sqlite::error(F("Column '%s' is not a blob") % name);
|
|
return column_blob(column);
|
|
}
|
|
|
|
|
|
/// Type-checked version of column_double.
|
|
///
|
|
/// \param name The name of the column to retrieve.
|
|
///
|
|
/// \return The same as column_double if the value can be retrieved.
|
|
///
|
|
/// \throw error If the type of the cell to retrieve is invalid.
|
|
/// \throw invalid_column_error If name is invalid.
|
|
double
|
|
sqlite::statement::safe_column_double(const char* name)
|
|
{
|
|
const int column = column_id(name);
|
|
if (column_type(column) != sqlite::type_float)
|
|
throw sqlite::error(F("Column '%s' is not a float") % name);
|
|
return column_double(column);
|
|
}
|
|
|
|
|
|
/// Type-checked version of column_int.
|
|
///
|
|
/// \param name The name of the column to retrieve.
|
|
///
|
|
/// \return The same as column_int if the value can be retrieved.
|
|
///
|
|
/// \throw error If the type of the cell to retrieve is invalid.
|
|
/// \throw invalid_column_error If name is invalid.
|
|
int
|
|
sqlite::statement::safe_column_int(const char* name)
|
|
{
|
|
const int column = column_id(name);
|
|
if (column_type(column) != sqlite::type_integer)
|
|
throw sqlite::error(F("Column '%s' is not an integer") % name);
|
|
return column_int(column);
|
|
}
|
|
|
|
|
|
/// Type-checked version of column_int64.
|
|
///
|
|
/// \param name The name of the column to retrieve.
|
|
///
|
|
/// \return The same as column_int64 if the value can be retrieved.
|
|
///
|
|
/// \throw error If the type of the cell to retrieve is invalid.
|
|
/// \throw invalid_column_error If name is invalid.
|
|
int64_t
|
|
sqlite::statement::safe_column_int64(const char* name)
|
|
{
|
|
const int column = column_id(name);
|
|
if (column_type(column) != sqlite::type_integer)
|
|
throw sqlite::error(F("Column '%s' is not an integer") % name);
|
|
return column_int64(column);
|
|
}
|
|
|
|
|
|
/// Type-checked version of column_text.
|
|
///
|
|
/// \param name The name of the column to retrieve.
|
|
///
|
|
/// \return The same as column_text if the value can be retrieved.
|
|
///
|
|
/// \throw error If the type of the cell to retrieve is invalid.
|
|
/// \throw invalid_column_error If name is invalid.
|
|
std::string
|
|
sqlite::statement::safe_column_text(const char* name)
|
|
{
|
|
const int column = column_id(name);
|
|
if (column_type(column) != sqlite::type_text)
|
|
throw sqlite::error(F("Column '%s' is not a string") % name);
|
|
return column_text(column);
|
|
}
|
|
|
|
|
|
/// Type-checked version of column_bytes.
|
|
///
|
|
/// \param name The name of the column to retrieve the size of.
|
|
///
|
|
/// \return The same as column_bytes if the value can be retrieved.
|
|
///
|
|
/// \throw error If the type of the cell to retrieve the size of is invalid.
|
|
/// \throw invalid_column_error If name is invalid.
|
|
int
|
|
sqlite::statement::safe_column_bytes(const char* name)
|
|
{
|
|
const int column = column_id(name);
|
|
if (column_type(column) != sqlite::type_blob &&
|
|
column_type(column) != sqlite::type_text)
|
|
throw sqlite::error(F("Column '%s' is not a blob or a string") % name);
|
|
return column_bytes(column);
|
|
}
|
|
|
|
|
|
/// Resets a statement to allow further processing.
|
|
void
|
|
sqlite::statement::reset(void)
|
|
{
|
|
(void)::sqlite3_reset(_pimpl->stmt);
|
|
}
|
|
|
|
|
|
/// Binds a blob to a prepared statement.
|
|
///
|
|
/// \param index The index of the binding.
|
|
/// \param b Description of the blob, which must remain valid during the
|
|
/// execution of the statement.
|
|
///
|
|
/// \throw api_error If the binding fails.
|
|
void
|
|
sqlite::statement::bind(const int index, const blob& b)
|
|
{
|
|
const int error = ::sqlite3_bind_blob(_pimpl->stmt, index, b.memory, b.size,
|
|
SQLITE_STATIC);
|
|
handle_bind_error(_pimpl->db, "sqlite3_bind_blob", error);
|
|
}
|
|
|
|
|
|
/// Binds a double value to a prepared statement.
|
|
///
|
|
/// \param index The index of the binding.
|
|
/// \param value The double value to bind.
|
|
///
|
|
/// \throw api_error If the binding fails.
|
|
void
|
|
sqlite::statement::bind(const int index, const double value)
|
|
{
|
|
const int error = ::sqlite3_bind_double(_pimpl->stmt, index, value);
|
|
handle_bind_error(_pimpl->db, "sqlite3_bind_double", error);
|
|
}
|
|
|
|
|
|
/// Binds an integer value to a prepared statement.
|
|
///
|
|
/// \param index The index of the binding.
|
|
/// \param value The integer value to bind.
|
|
///
|
|
/// \throw api_error If the binding fails.
|
|
void
|
|
sqlite::statement::bind(const int index, const int value)
|
|
{
|
|
const int error = ::sqlite3_bind_int(_pimpl->stmt, index, value);
|
|
handle_bind_error(_pimpl->db, "sqlite3_bind_int", error);
|
|
}
|
|
|
|
|
|
/// Binds a 64-bit integer value to a prepared statement.
|
|
///
|
|
/// \param index The index of the binding.
|
|
/// \param value The 64-bin integer value to bind.
|
|
///
|
|
/// \throw api_error If the binding fails.
|
|
void
|
|
sqlite::statement::bind(const int index, const int64_t value)
|
|
{
|
|
const int error = ::sqlite3_bind_int64(_pimpl->stmt, index, value);
|
|
handle_bind_error(_pimpl->db, "sqlite3_bind_int64", error);
|
|
}
|
|
|
|
|
|
/// Binds a NULL value to a prepared statement.
|
|
///
|
|
/// \param index The index of the binding.
|
|
/// \param unused_null An instance of the null class.
|
|
///
|
|
/// \throw api_error If the binding fails.
|
|
void
|
|
sqlite::statement::bind(const int index,
|
|
const null& UTILS_UNUSED_PARAM(null))
|
|
{
|
|
const int error = ::sqlite3_bind_null(_pimpl->stmt, index);
|
|
handle_bind_error(_pimpl->db, "sqlite3_bind_null", error);
|
|
}
|
|
|
|
|
|
/// Binds a text string to a prepared statement.
|
|
///
|
|
/// \param index The index of the binding.
|
|
/// \param text The string to bind. SQLite generates an internal copy of this
|
|
/// string, so the original string object does not have to remain live. We
|
|
/// do this because handling the lifetime of std::string objects is very
|
|
/// hard (think about implicit conversions), so it is very easy to shoot
|
|
/// ourselves in the foot if we don't do this.
|
|
///
|
|
/// \throw api_error If the binding fails.
|
|
void
|
|
sqlite::statement::bind(const int index, const std::string& text)
|
|
{
|
|
const int error = ::sqlite3_bind_text(_pimpl->stmt, index, text.c_str(),
|
|
text.length(), SQLITE_TRANSIENT);
|
|
handle_bind_error(_pimpl->db, "sqlite3_bind_text", error);
|
|
}
|
|
|
|
|
|
/// Returns the index of the highest parameter.
|
|
///
|
|
/// \return A parameter index.
|
|
int
|
|
sqlite::statement::bind_parameter_count(void)
|
|
{
|
|
return ::sqlite3_bind_parameter_count(_pimpl->stmt);
|
|
}
|
|
|
|
|
|
/// Returns the index of a named parameter.
|
|
///
|
|
/// \param name The name of the parameter to be queried; must exist.
|
|
///
|
|
/// \return A parameter index.
|
|
int
|
|
sqlite::statement::bind_parameter_index(const std::string& name)
|
|
{
|
|
const int index = ::sqlite3_bind_parameter_index(_pimpl->stmt,
|
|
name.c_str());
|
|
PRE_MSG(index > 0, "Parameter name not in statement");
|
|
return index;
|
|
}
|
|
|
|
|
|
/// Returns the name of a parameter by index.
|
|
///
|
|
/// \param index The index to query; must be valid.
|
|
///
|
|
/// \return The name of the parameter.
|
|
std::string
|
|
sqlite::statement::bind_parameter_name(const int index)
|
|
{
|
|
const char* name = ::sqlite3_bind_parameter_name(_pimpl->stmt, index);
|
|
PRE_MSG(name != NULL, "Index value out of range or nameless parameter");
|
|
return std::string(name);
|
|
}
|
|
|
|
|
|
/// Clears any bindings and releases their memory.
|
|
void
|
|
sqlite::statement::clear_bindings(void)
|
|
{
|
|
const int error = ::sqlite3_clear_bindings(_pimpl->stmt);
|
|
PRE_MSG(error == SQLITE_OK, "SQLite3 contract has changed; it should "
|
|
"only return SQLITE_OK");
|
|
}
|