3 #ifndef __SQLITEXX_SQLITE_STATEMENT_H__
4 #define __SQLITEXX_SQLITE_STATEMENT_H__
34 virtual ~
reader() =
default;
40 int get_int(
const int column)
const noexcept
42 return sqlite3_column_int(static_cast<T const *>(
this)->handle(), column);
49 int get_int(
const std::string& name)
const noexcept
61 return sqlite3_column_int64(static_cast<T const *>(
this)->handle(), column);
68 int64_t
get_int64(
const std::string& name)
const noexcept
78 unsigned int get_uint(
const int column)
const noexcept
80 return static_cast<unsigned int>(
get_int64(column));
87 unsigned int get_uint(
const std::string& name)
const noexcept
99 return sqlite3_column_double(static_cast<T const *>(
this)->handle(), column);
118 const void *
blob = sqlite3_column_blob(static_cast<T const *>(
this)->handle(), column);
136 const std::string
get_string(
const int column)
const noexcept
138 const char *txt = get_text(column);
139 return std::string(txt, get_text_length(column));
146 const std::string
get_string(
const std::string& name)
const noexcept
158 const char16_t *txt = get_text16(column);
159 return std::u16string(txt, get_text16_length(column));
178 return value(sqlite3_column_value(static_cast<T const *>(
this)->handle(), column));
198 return sqlite3_column_bytes(static_cast<T const *>(
this)->handle(), column);
217 return static_cast<datatype>(sqlite3_column_type(static_cast<T const *>(
this)->handle(), column));
236 return sqlite3_column_count(static_cast<T const *>(
this)->handle());
245 return sqlite3_column_name(static_cast<T const *>(
this)->handle(), index);
254 return sqlite3_column_name16(static_cast<T const *>(
this)->handle(), index);
263 std::map<std::string, int> columnNamesToIndex;
266 for (
int i = 0; i < columnCount; ++i) {
267 const char* columnName = sqlite3_column_name(static_cast<T const *>(
this)->handle(), i);
268 columnNamesToIndex[columnName] = i;
271 const std::map<std::string, int>::const_iterator index = columnNamesToIndex.find(name);
272 if (index == columnNamesToIndex.end())
274 throw SQLiteXXException(
"No column was found with that name");
276 return index->second;
281 const char* get_text(
const int column)
const noexcept
283 return reinterpret_cast<char const *
>(sqlite3_column_text(
284 static_cast<T const *>(
this)->handle(), column));
287 const char16_t* get_text16(
const int column)
const noexcept
289 return reinterpret_cast<char16_t
const *
>(sqlite3_column_text16(
290 static_cast<T const *>(
this)->handle(), column));
293 int get_text_length(
const int column)
const noexcept
295 return sqlite3_column_bytes(static_cast<T const *>(
this)->handle(), column);
298 int get_text16_length(
const int column)
const noexcept
300 return sqlite3_column_bytes16(static_cast<T const *>(
this)->handle(), column) /
sizeof(char16_t);
343 sqlite3_stmt* m_statement =
nullptr;
363 template <
typename ... Values>
366 const std::string&
text,
367 Values&& ... values) :
368 m_handle(nullptr, sqlite3_finalize),
371 prepare(connection, text, std::forward<Values>(values) ...);
380 template <
typename ... Values>
383 const std::u16string&
text,
384 Values&& ... values) :
385 m_handle(nullptr, sqlite3_finalize),
388 prepare(connection, text, std::forward<Values>(values) ...);
394 operator bool() const noexcept;
400 sqlite3_stmt*
handle() const noexcept;
407 template <typename ... Values>
410 const std::
string&
text,
413 internal_prepare(connection, sqlite3_prepare_v2, text.c_str(), std::forward<Values>(values) ...);
421 template <
typename ... Values>
424 const std::u16string&
text,
427 internal_prepare(connection, sqlite3_prepare16_v2, text.c_str(), std::forward<Values>(values) ...);
446 void bind(
const int index,
const int value)
const;
452 void bind(
const int index,
const double value)
const;
488 void bind(
const int index,
const std::string&
value)
const;
494 void bind(
const int index,
const std::u16string&
value)
const;
500 template <
typename T>
503 const int index = sqlite3_bind_parameter_index(
handle(), name.c_str());
510 template <
typename ... Values>
513 internal_bind(1, std::forward<Values>(values) ...);
519 template <
typename ... Values>
522 if (SQLITE_OK != sqlite3_clear_bindings(
handle()))
537 if (SQLITE_OK != sqlite3_reset(
handle()))
545 using statement_handle = std::unique_ptr<sqlite3_stmt, decltype(&sqlite3_finalize)>;
546 statement_handle m_handle;
550 template <
typename F,
typename C,
typename ... Values>
551 void internal_prepare(
554 const C *
const text,
562 const int errcode = sqlite3_extended_errcode(connection.
handle());
563 const std::string message = sqlite3_errmsg(connection.
handle());
564 sqlite3_finalize(statement);
565 throw_error_code(errcode, message);
568 m_handle.reset(statement);
569 bind_all(std::forward<Values>(values) ...);
572 void internal_bind(
int) const noexcept
575 template <
typename First,
typename ... Rest>
576 void internal_bind(
const int index, First&& first, Rest&& ... rest)
const
578 bind(index, std::forward<First>(first));
579 internal_bind(index + 1, std::forward<Rest>(rest) ...);
582 void throw_last_error()
const;
584 statement(
const statement& other) =
delete;
585 statement& operator=(statement& other) =
delete;
619 const statement* m_statement =
nullptr;
641 template <
typename ... Values>
644 const std::string& text,
647 return statement(connection, text.c_str(), std::forward<Values>(values) ...).execute();
656 template <
typename ... Values>
659 const std::u16string& text,
662 return statement(connection, text.c_str(), std::forward<Values>(values) ...).execute();
665 template <
typename Call>
666 inline int internal_execute_callback(
672 Call *userCallback =
static_cast<Call *
>(data);
674 std::vector<std::string> columnData;
675 std::vector<std::string> columnName;
676 for (
int i = 0; i < numColumns; i++) {
677 columnData.push_back(colData[i]? colData[i]:
"");
678 columnName.push_back(colNames[i]? colNames[i]:
"");
681 (*userCallback)(columnData, columnName);
685 template <
typename F,
typename ... Args>
686 inline void execute_callback(
687 const dbconnection& connection,
688 const std::string& sql,
700 std::forward<F>(callback),
701 std::placeholders::_1,
702 std::placeholders::_2,
703 std::forward<Args>(args)...);
705 typedef decltype(userCallback) Call;
707 char *errmsgPtr =
nullptr;
708 sqlite3_exec(connection.handle(), sql.c_str(), internal_execute_callback<Call>, (
void *)&userCallback,
nullptr);
711 throw_error_code(connection.handle());
const std::u16string get_u16string(const int column) const noexcept
Returns the specified column value as a UTF-16 string.
Base class used to help with reading "sqlite3_stmt" information.
sqlite3 * handle() const noexcept
Returns pointer to the underlying "sqlite3" object.
row operator*() const noexcept
Dereference operation.
A SQLite dynamically typed value object, aka "sqlite3_value".
unsigned int get_uint(const std::string &name) const noexcept
Returns the specified column value as an unsigned integer.
const std::u16string get_u16string(const std::string &name) const noexcept
Returns the specified column value as a UTF-16 string.
void prepare(const dbconnection &connection, const std::u16string &text, Values &&...values)
Turn an SQL query into byte code.
bool operator!=(const row_iterator &other) const noexcept
Comparison operation.
int execute(const dbconnection &connection, const std::string &text, Values &&...values)
Executes an SQL query on a database connection.
const char16_t * get_column_wide_name(const int index) const noexcept
Returns the name assigned to a particular column.
void bind_name(const std::string &name, T &&value)
Binds an value to a parameter in an SQL prepared statement.
means that the content will likely change in the near future and that SQLite should make its own priv...
const blob get_blob(const int column) const noexcept
Returns the specified column value as a blob object.
bool step() const
Evaluates a prepared statement.
unsigned int get_uint(const int column) const noexcept
Returns the specified column value as an unsigned integer.
const char * get_column_name(const int index) const noexcept
Returns the name assigned to a particular column.
int get_column_index(const std::string &name) const
Returns the position of a column with the specified name.
value get_value(const int column) const noexcept
Returns the specified column value as a value object.
statement(const dbconnection &connection, const std::u16string &text, Values &&...values)
Creates, prepares, and binds values into an SQL statement.
void bind(const int index, const int value) const
Binds an integer value to a parameter in an SQL prepared statement.
datatype get_type(const int column) const noexcept
Returns the type of the specified column.
sqlite3_stmt * handle() const noexcept
Returns pointer to the underlying "sqlite3_stmt" object.
Helps when iterating over rows in a "SELECT" statement.
row(sqlite3_stmt *const statement) noexcept
Constructs a row object from a sqlite3_stmt.
int execute() const
Executes a prepared statement and will return the number of changes to the database.
bindtype
Used to specify the way to bind a value to a statement.
datatype
Every value in SQLite has one of the following fundamental datatypes.
value get_value(const std::string &name) const
Returns the specified column value as a value object.
int column_count() const noexcept
Returns the number of columns in the result set returned by the prepared statement.
void reset() const
Resets a prepared statement object back to its initial state.
statement(const dbconnection &connection, const std::string &text, Values &&...values)
Creates, prepares, and binds values into an SQL statement.
int get_bytes(const std::string &name) const noexcept
Returns the size in bytes of the column value.
void bind_all(Values &&...values) const
Binds values to parameters in an SQL prepared statement.
const std::string get_string(const std::string &name) const noexcept
Returns the specified column value as a string.
value operator[](int column) const
Access specified element of a row.
Represents a single SQL statement that has been compiled into binary form and is ready to be evaluate...
const blob get_blob(const std::string &name) const noexcept
Returns the specified column value as a Blob object.
Represents a returned row when stepping through a "SELECT" statement.
datatype get_type(const std::string &name) const noexcept
Returns the type of the specified column.
void clear_bindings(Values &&...values) const
Resets all SQL parameters to NULL.
row_iterator() noexcept=default
Default constructor.
double get_double(const std::string &name) const noexcept
Returns the specified column value as a double.
row_iterator end(const statement &statement) noexcept
Returns an iterator to the end.
row_iterator begin(const statement &statement) noexcept
Returns an iterator to the first row of a statement.
int64_t get_int64(const std::string &name) const noexcept
Returns the specified column value as a 64-bit integer.
int get_bytes(const int column) const noexcept
Returns the size in bytes of the column value.
value operator[](const std::string &name) const
Access specified element of a row.
sqlite3_stmt * handle() const noexcept
Returns pointer to the underlying "sqlite3_stmt" object.
int get_int(const std::string &name) const noexcept
Returns the specified column value as an integer.
double get_double(const int column) const noexcept
Returns the specified column value as a double.
int64_t get_int64(const int column) const noexcept
Returns the specified column value as a 64-bit integer.
statement() noexcept
Default constructor.
const std::string get_string(const int column) const noexcept
Returns the specified column value as a string.
Class that represents a connection to a database.
row_iterator & operator++() noexcept
Increment iterator to the next row object of the statement.
int get_int(const int column) const noexcept
Returns the specified column value as an integer.
void prepare(dbconnection const &connection, const std::string &text, Values &&...values)
Turn an SQL query into byte code.