13#include <unordered_map>
89 namespace details::sqlite {
93 statement(sqlite3 *db_handle, std::string_view query);
95 sqlite3_stmt *
data() const noexcept;
104 template <typename T>
107 static_assert(std::false_type::value,
"Unsupported type for get method");
157 bind_map.merge(b.bind_map);
162 bind_map.emplace(index, std::move(v));
166 std::unordered_map<int, db_value> bind_map;
172 template <
typename T>
174 { x.to_query_string() } -> std::same_as<std::string>;
175 { x.get_binder() } -> std::same_as<binder &>;
181 template <Queryable A, Queryable B>
185 explicit logic_gate(A &&a, B &&b, std::string
const &gate) : a_(std::move(a)), b_(std::move(b)), gate_(gate)
187 binder_.
merge(a_.get_binder());
188 binder_.
merge(b_.get_binder());
193 return std::format(
"{} {} {}", a_.to_query_string(), gate_, b_.to_query_string());
216 template <Queryable A, Queryable B>
228 template <Queryable A, Queryable B>
246 std::string
const &json_query,
247 std::string
const &op,
250 binder_.
add(index_, std::move(value));
254 std::string
const &json_query,
255 std::string
const &op,
256 nullptr_t) : var_(json_query), op_(op), index_(-1)
263 auto json_query = var_.size() > 0 && var_[0] ==
'$';
264 auto is_value_null = index_ == -1;
269 return std::format(
"json_type(body, '{0}') IS NOT NULL AND json_extract(body, '{0}') {1} NULL", var_, op_);
271 return std::format(
"[{}] {} NULL", var_, op_);
275 return std::format(
"(json_extract(body, '{}') {} ?{})", var_, op_, index_);
277 return std::format(
"([{}] {} ?{})", var_, op_, index_);
303 std::string
const &name,
304 std::string
const &val) :
binary_op(name,
"LIKE", val) {}
313 std::string
const &name,
314 std::string
const &val) :
binary_op(name,
"REGEXP", val) {}
323 std::string
const &name,
327 std::string
const &name,
328 nullptr_t) :
binary_op(name,
"IS", nullptr) {}
337 std::string
const &name,
341 std::string
const &name,
342 nullptr_t) :
binary_op(name,
"IS NOT", nullptr) {}
351 std::string
const &name,
361 std::string
const &name,
371 std::string
const &name,
381 std::string
const &name,
385 template <Queryable A, Queryable B>
391 template <Queryable A, Queryable B>
412 template <Queryable T>
419 return obj_.to_query_string();
424 return obj_.get_binder();
436 template <Queryable T>
442 return ptr_->to_query_string();
447 return ptr_->get_binder();
451 std::unique_ptr<queryable_base> ptr_;
457 : field_(
field), ascending_(ascending) {}
459 std::string
const&
field()
const {
return field_; }
460 std::string_view
direction()
const {
return ascending_ ?
"ASC" :
"DESC"; }
531 db_document_ref(std::string_view table_name, std::string_view doc_id, sqlite3 *db_handle);
538 std::string
id()
const;
555 std::string table_name;
569 std::string
id()
const;
682 std::double_t
get_real(std::string_view query)
const;
694 template <
typename... Types>
695 std::tuple<Types...>
get(
const std::vector<std::string>& fields)
const {
696 if (fields.size() !=
sizeof...(Types)) {
697 throw std::invalid_argument(
"Number of fields does not match the number of types.");
700 auto stmt = get_value_stmt_impl(fields);
701 auto ret = get_values_impl<Types...>(stmt, std::index_sequence_for<Types...>{});
712 template <
typename... Types, std::size_t... Indices>
715 return std::make_tuple(stmt.
get<Types>(Indices)...);
722 std::string table_name;
723 mutable std::string body_data;
737 db_document(std::string_view table_name, std::string_view doc_id, std::string_view
body, sqlite3 *db_handle);
738 db_document(std::string_view table, std::string_view doc_id, sqlite3 *db_handle);
769 std::string
name() const noexcept;
806 std::
size_t count(query::queryable_type_eraser q) const;
830 std::vector<
db_document_ref>
find(query::queryable_type_eraser q, std::optional<query::order_by> order_by = std::nullopt, std::optional<
int> limit = std::nullopt) const;
857 std::vector<std::pair<std::
string, std::
string>> const &columns,
861 std::
string table_name;
885 explicit database(std::string_view connection_string);
895 std::string_view connection_string,
943 std::
string filename_journal() const noexcept;
949 std::
string filename_wal() const noexcept;
Represents a queryable object.
logic_or< A, B > operator||(A &&a, B &&b)
logic_and< A, B > operator&&(A &&a, B &&b)
thread_local int bind_counter
std::string get_version() noexcept
Gets the version of the library.
open_mode
Specifies the database file open mode.
@ read_write
Open the database for reading and writing. The database must already exist.
@ read_write_create
Open the database for reading and writing, and create it if it does not exist.
@ read_only
Open the database for read-only access. The database must already exist.
threading_mode
Specifies the threading mode for the database connection.
@ multi_thread
The new database connection will use the multi-thread threading mode.
@ default_mode
Use the default threading mode. If you need single-thread mode, SQLite must be compiled accordingly....
@ serialized
The new database connection will use the serialized threading mode.
std::string get_build_timestamp() noexcept
Gets the build timestamp.
std::variant< std::float_t, std::double_t, std::int32_t, std::int64_t, std::nullptr_t, std::string > db_value
Types supported.
void backup_to(database &dest, std::function< void(int, int)> progress=[](int, int){}) const
Backup the current database into the destination database.
void load_extensions() const
Load docudb's sqlite3 extensions (e.g. regexp)
std::string filename_database() const noexcept
Returns the database file name.
database()=default
Constructs an empty database object.
std::vector< db_collection > collections() const
Gets all collections.
db_collection collection(std::string_view name) const
Gets a collection by name.
database(std::string_view connection_string)
Constructs a new database object.
database & operator=(database &&)
database(std::string_view connection_string, open_mode mode, threading_mode thread_mode)
Constructs a new database object.
database(database const &)=delete
database & operator=(database const &)=delete
~database()
Destroys the database object.
Represents a collection of documents in the database.
db_collection & operator=(db_collection const &)=delete
db_document create(std::string_view doc_id)
Creates a new document with the given ID.
db_collection()=default
Constructs an empty db_collection object.
std::string name() const noexcept
Gets the collection name.
db_collection(db_collection const &)=delete
db_collection & index(std::string_view column_name, std::string_view query, bool unique=false)
Indexes the document based on the specified column and query.
void remove(std::string_view doc_id)
Removes a document by ID.
db_document doc()
Creates a new document with a generated UUID.
db_collection(std::string_view name, sqlite3 *db_handle)
Constructs a new db_collection object.
std::size_t count() const
Gets the number of documents in the collection.
db_collection & operator=(db_collection &&)=default
std::vector< db_document_ref > find(query::queryable_type_eraser q, std::optional< query::order_by > order_by=std::nullopt, std::optional< int > limit=std::nullopt) const
Searches documents by query.
db_collection(db_collection &&)=default
std::vector< db_document_ref > docs() const
Gets all documents in the collection.
Reference to a database document.
db_document_ref(db_document const &doc)
Constructs a new db_document_ref object from a db_document object.
db_document_ref(std::string_view table_name, std::string_view doc_id, sqlite3 *db_handle)
Constructs a new db_document_ref object.
std::string id() const
Gets the document ID.
db_document doc() const
Gets the full document object.
void erase()
Removes the document from the collection.
Represents a database document.
std::double_t get_real(std::string_view query) const
std::string get_string(std::string_view query) const
db_document & set(std::string_view query, std::float_t value)
db_document & insert(std::string_view query, std::nullptr_t value)
db_document & patch(std::string_view json)
Patches the JSON body of the document.
db_document & insert(std::string_view query, std::int32_t value)
db_document & insert(std::string_view query, std::float_t value)
db_document & insert(std::string_view query, std::int64_t value)
db_document & body(std::string_view body)
Sets the full body of the document.
db_document & set(std::string_view query, std::string const &value)
db_document & set(std::string_view query, std::string_view value)
std::string id() const
Gets the document ID.
db_document & replace(std::string_view query, std::string const &value)
Replace a value in the json body.
db_document & replace(std::string_view query, std::double_t value)
Replace a value in the json body.
std::int64_t get_number(std::string_view query) const
db_document & replace(std::string_view query, std::float_t value)
Replace a value in the json body.
db_document & replace(std::string_view query, std::int64_t value)
Replace a value in the json body.
std::vector< std::string > get_object_keys(std::string_view query) const
db_document & set(std::string_view query, std::int32_t value)
db_document & insert(std::string_view query, std::string_view value)
db_document & insert(std::string_view query, std::string const &value)
void erase()
Removes the document from the collection.
std::tuple< Types... > get(const std::vector< std::string > &fields) const
std::size_t get_array_length(std::string_view query) const
std::string body() const
Gets the full body of the document.
db_document & insert(std::string_view query, std::double_t value)
db_document & set(std::string_view query, std::nullptr_t value)
json_type get_type(std::string_view query) const
db_document & set(std::string_view query, std::int64_t value)
db_document & replace(std::string_view query, std::string_view value)
Replace a value in the json body.
db_document & set(std::string_view query, std::double_t value)
db_document & replace(std::string_view query, std::int32_t value)
Replace a value in the json body.
db_document & replace(std::string_view query, std::nullptr_t value)
Replace a value in the json body.
Exception class for database errors.
db_exception(sqlite3 *db_handle, std::string_view msg)
Constructs a new db_exception object.
json_type get_type(int index) const noexcept
bool is_result_null(int index) const noexcept
int result_code() const noexcept
statement & bind(int index, std::int16_t value)
statement(sqlite3 *db_handle, std::string_view query)
sqlite3_stmt * data() const noexcept
statement & step() noexcept
Represents a binary operation for querying.
binary_op(std::string const &json_query, std::string const &op, db_value &&value)
binder const & get_binder() const
binary_op(std::string const &json_query, std::string const &op, nullptr_t)
std::string to_query_string() const
Represents a binder for query parameters.
const std::unordered_map< int, db_value > & get_parameters() const
void add(int index, db_value &&v)
Represents an EQUAL operation for querying.
eq(std::string const &name, db_value &&val)
eq(std::string const &name, nullptr_t)
Represents a GREATER THAN operation for querying.
gt(std::string const &name, db_value &&val)
Represents a GREATER OR EQUAL THAN operation for querying.
gte(std::string const &name, db_value &&val)
Represents a LIKE operation for querying.
like(std::string const &name, std::string const &val)
Represents a LOGIC AND gate.
Represents a logic gate for combining two queryable objects.
logic_gate(A &&a, B &&b, std::string const &gate)
binder const & get_binder() const
std::string to_query_string() const
Represents a LOGIC OR gate.
Represents a LESSER THAN operation for querying.
lt(std::string const &name, db_value &&val)
Represents a LESSER OR EQUAL THAN operation for querying.
lte(std::string const &name, db_value &&val)
Represents a NOT EQUAL operation for querying.
neq(std::string const &name, db_value &&val)
neq(std::string const &name, nullptr_t)
std::string_view direction() const
order_by(std::string const &field, bool ascending=true)
std::string const & field() const
Abstract base class for Queryable objects.
virtual ~queryable_base()=default
virtual std::string to_query_string() const =0
virtual binder get_binder() const =0
Type-erased Queryable object.
std::string to_query_string() const
binder get_binder() const
queryable_type_eraser(T &&obj)
Concrete wrapper for erasing the type of a Queryable object.
std::string to_query_string() const override
binder get_binder() const override
queryable_wrapper(T &&obj)
Represents a REGEXP operation for querying.
regexp(std::string const &name, std::string const &val)
Exception class for database errors.
stmt_exception(sqlite3 *db_handle, std::string_view sql)
Constructs a new db_exception object.