diff --git a/include/orm/query/querybuilder.hpp b/include/orm/query/querybuilder.hpp index 8bbd06983..77fd1dc86 100644 --- a/include/orm/query/querybuilder.hpp +++ b/include/orm/query/querybuilder.hpp @@ -44,6 +44,7 @@ namespace Query /*! Virtual destructor. */ inline virtual ~Builder() = default; + /* Retrieving results */ /*! Execute the query as a "select" statement. */ QSqlQuery get(const QVector &columns = {ASTERISK}); /*! Execute a query for a single record by ID. */ @@ -66,21 +67,21 @@ namespace Query // { dd($this->toSql(), $this->getBindings()); } /* Insert, Update, Delete */ - /*! Insert a new record into the database. */ - std::optional - insert(const QVariantMap &values); /*! Insert new records into the database. */ std::optional insert(const QVector &values); + /*! Insert a new record into the database. */ + std::optional + insert(const QVariantMap &values); /*! Insert a new record and get the value of the primary key. */ quint64 insertGetId(const QVariantMap &values, const QString &sequence = ""); - /*! Insert a new record into the database while ignoring errors. */ - std::tuple> - insertOrIgnore(const QVariantMap &values); /*! Insert new records into the database while ignoring errors. */ std::tuple> insertOrIgnore(const QVector &values); + /*! Insert a new record into the database while ignoring errors. */ + std::tuple> + insertOrIgnore(const QVariantMap &values); /*! Update records in the database. */ std::tuple @@ -688,6 +689,8 @@ namespace Query std::variant m_lock {}; }; + /* Retrieving results */ + template std::map Builder::pluck(const QString &column, const QString &key) @@ -719,6 +722,29 @@ namespace Query return result; } + /* Insert, Update, Delete */ + + template + std::tuple Builder::deleteRow(T &&id) + { + return remove(std::forward(id)); + } + + template + std::tuple Builder::remove(T &&id) + { + /* If an ID is passed to the method, we will set the where clause to check the + ID to let developers to simply and quickly remove a single row from this + database without manually specifying the "where" clauses on the query. + m_from will be wrapped in the Grammar. */ + where(QStringLiteral("%1.id").arg(std::get(m_from)), EQ, + std::forward(id), AND); + + return remove(); + } + + /* Select */ + quint64 Builder::count(const QVector &columns) const { return aggregate(QStringLiteral("count"), columns).template value(); @@ -787,25 +813,6 @@ namespace Query bindings); } - template - std::tuple Builder::deleteRow(T &&id) - { - return remove(std::forward(id)); - } - - template - std::tuple Builder::remove(T &&id) - { - /* If an ID is passed to the method, we will set the where clause to check the - ID to let developers to simply and quickly remove a single row from this - database without manually specifying the "where" clauses on the query. - m_from will be wrapped in the Grammar. */ - where(QStringLiteral("%1.id").arg(std::get(m_from)), EQ, - std::forward(id), AND); - - return remove(); - } - template Builder & Builder::fromSub(T &&query, const QString &as) @@ -1096,6 +1103,8 @@ namespace Query return update(columns); } + /* Getters / Setters */ + ConnectionInterface &Builder::getConnection() const { return m_connection; @@ -1201,12 +1210,16 @@ namespace Query return m_lock; } + /* protected */ + QSharedPointer Builder::forSubQuery() const { return newQuery(); } + /* private */ + Builder & Builder::setFrom(const FromClause &from) { diff --git a/src/orm/query/querybuilder.cpp b/src/orm/query/querybuilder.cpp index c86ce9fee..211d7294c 100644 --- a/src/orm/query/querybuilder.cpp +++ b/src/orm/query/querybuilder.cpp @@ -14,6 +14,8 @@ Builder::Builder(ConnectionInterface &connection, const QueryGrammar &grammar) , m_grammar(grammar) {} +/* Retrieving results */ + QSqlQuery Builder::get(const QVector &columns) { @@ -92,12 +94,6 @@ QString Builder::toSql() return m_grammar.compileSelect(*this); } -std::optional -Builder::insert(const QVariantMap &values) -{ - return insert(QVector {values}); -} - namespace { const auto flatValuesForInsert = [](const auto &values) @@ -111,6 +107,8 @@ namespace }; } // namespace +/* Insert, Update, Delete */ + // TEST for insert silverqx std::optional Builder::insert(const QVector &values) @@ -128,6 +126,12 @@ Builder::insert(const QVector &values) cleanBindings(flatValuesForInsert(values))); } +std::optional +Builder::insert(const QVariantMap &values) +{ + return insert(QVector {values}); +} + // FEATURE dilemma primarykey, add support for Model::KeyType in QueryBuilder/TinyBuilder or should it be QVariant and runtime type check? 🤔 silverqx quint64 Builder::insertGetId(const QVariantMap &values, const QString &sequence) { @@ -190,6 +194,8 @@ void Builder::truncate() m_connection.statement(sql, bindings); } +/* Select */ + QVariant Builder::aggregate(const QString &function, const QVector &columns) const { @@ -615,6 +621,8 @@ Builder &Builder::forPage(const int page, const int perPage) return offset((page - 1) * perPage).limit(perPage); } +/* Pessimistic Locking */ + Builder &Builder::lockForUpdate() { return lock(true); @@ -660,6 +668,8 @@ Builder &Builder::lock(QString &&value) return *this; } +/* Getters / Setters */ + QVector Builder::getBindings() const { QVector flattenBindings; @@ -719,6 +729,8 @@ Builder &Builder::setBindings(QVector &&bindings, const BindingType ty return *this; } +/* Other methods */ + // TODO next revisit QSharedPointer, after few weeks I'm pretty sure that this can/should be std::unique_pre, like in the TinyBuilder, I need to check if more instances need to save this pointer at once, if don't then I have to change it silverqx QSharedPointer Builder::newQuery() const { @@ -827,6 +839,8 @@ Builder Builder::cloneWithoutBindings( return copy; } +/* protected */ + bool Builder::invalidOperator(const QString &comparison) const { const auto comparison_ = comparison.toLower(); @@ -912,7 +926,7 @@ Builder::onceWithColumns( if (original.isEmpty()) m_columns = columns; - const auto result = std::invoke(callback); + auto result = std::invoke(callback); // After running the callback, the columns are reset to the original value m_columns = original; @@ -977,6 +991,8 @@ QString Builder::stripTableForPluck(const QString &column) const return column.split(as).last().trimmed(); } +/* Getters / Setters */ + Builder &Builder::setAggregate(const QString &function, const QVector &columns) { // TODO clang13 doesn't support in_place construction of aggregates in std::optional.emplace() 😲, gcc and msvc are ok silverqx @@ -995,6 +1011,8 @@ Builder &Builder::setAggregate(const QString &function, const QVector &c return *this; } +/* private */ + QSqlQuery Builder::runSelect() { return m_connection.select(toSql(), getBindings());