AUI Framework  master
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
ASqlBuilder.h
    1/*
    2 * AUI Framework - Declarative UI toolkit for modern C++20
    3 * Copyright (C) 2020-2025 Alex2772 and Contributors
    4 *
    5 * SPDX-License-Identifier: MPL-2.0
    6 *
    7 * This Source Code Form is subject to the terms of the Mozilla Public
    8 * License, v. 2.0. If a copy of the MPL was not distributed with this
    9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
   10 */
   11
   12#pragma once
   13
   14#include <AUI/Autumn/Autumn.h>
   15#include <AUI/Common/AString.h>
   16#include <AUI/Common/AVariant.h>
   17#include <AUI/Common/AVector.h>
   18#include <AUI/Common/AMap.h>
   19#include <AUI/Common/AStringVector.h>
   20#include <AUI/Reflect/AField.h>
   21#include <AUI/Data/ASqlDatabase.h>
   22#include <AUI/Traits/parameter_pack.h>
   23
   24template<typename ModelType>
   25struct ASqlModel;
   26
   27template<class T>
   28struct AModelMeta;
   29
   30class API_AUI_DATA ASqlBuilder {
   31private:
   32    AString mTableName;
   33
   34public:
   35    class API_AUI_DATA Statement {
   36    protected:
   37        ASqlBuilder& mBuilder;
   38        AString mSql;
   39
   40        Statement(ASqlBuilder& builder, const AString& sql);
   41        Statement(const Statement&) = delete;
   42    public:
   43        virtual ~Statement() = default;
   44
   53        ASqlBuilder& also() {
   54            return mBuilder;
   55        }
   56    };
   57
   58    class API_AUI_DATA Insert: public Statement {
   59        friend class ASqlBuilder;
   60    private:
   61        AVector<AVariant> mData;
   62        bool mInsertDone = false;
   63
   64        Insert(ASqlBuilder& builder, const AString& sql);
   65        int doInsert();
   66
   67    public:
   68        Insert(const Insert&) = delete;
   69        Insert& row(const AVector<AVariant>& data);
   70        Insert& rows(const AVector<AVector<AVariant>>& data);
   71        id_t rowId();
   72        ~Insert() override;
   73    };
   74
   75    class API_AUI_DATA WhereStatement: public Statement {
   76    public:
   77        ~WhereStatement() override = default;
   78
   79        class API_AUI_DATA WhereExpr {
   80            friend class WhereStatement;
   81        private:
   82            AString mExprString;
   83            AVector<AVariant> mWhereParams;
   84
   85        public:
   86            WhereExpr() = default;
   87            explicit WhereExpr(const AString& exprString);
   88
   89            static std::tuple<AString, AVector<AVariant>> unpack(const WhereExpr& e) {
   90                return std::make_tuple(e.mExprString, e.mWhereParams);
   91            }
   92
   93            inline WhereExpr& operator>(const AVariant& other) {
   94                mExprString += " > ?";
   95                mWhereParams << other;
   96                return *this;
   97            }
   98            inline WhereExpr& operator>=(const AVariant& other) {
   99                mExprString += " >= ?";
  100                mWhereParams << other;
  101                return *this;
  102            }
  103            inline WhereExpr& operator<(const AVariant& other) {
  104                mExprString += " < ?";
  105                mWhereParams << other;
  106                return *this;
  107            }
  108            inline WhereExpr& operator<=(const AVariant& other) {
  109                mExprString += " <= ?";
  110                mWhereParams << other;
  111                return *this;
  112            }
  113            inline WhereExpr& operator==(const AVariant& other) {
  114                mExprString += " = ?";
  115                mWhereParams << other;
  116                return *this;
  117            }
  118            inline WhereExpr& operator!=(const AVariant& other) {
  119                mExprString += " != ?";
  120                mWhereParams << other;
  121                return *this;
  122            }
  123
  124            inline WhereExpr& operator&&(const WhereExpr& other) {
  125                mExprString += " and " + other.mExprString;
  126                mWhereParams.insertAll(other.mWhereParams);
  127                return *this;
  128            }
  129            inline WhereExpr& operator||(const WhereExpr& other) {
  130                mExprString += " or " + other.mExprString;
  131                mWhereParams.insertAll(other.mWhereParams);
  132                return *this;
  133            }
  134        };
  135
  136    protected:
  137        AString mWhereExpr;
  138        AVector<AVariant> mWhereParams;
  139
  140        WhereStatement(ASqlBuilder& builder, const AString& sql);
  141        void whereImpl(const WhereExpr& w);
  142    };
  143
  144    class API_AUI_DATA Select: public WhereStatement {
  145        friend class ASqlBuilder;
  146    private:
  147        AVector<AVariant> mData;
  148
  149        Select(ASqlBuilder& builder, const AString& sql);
  150
  151    public:
  152        Select(const Select&) = delete;
  153        ~Select() override = default;
  154
  155        Select& where(const WhereExpr& w) {
  156            whereImpl(w);
  157            return *this;
  158        }
  159
  165
  170        template<class Model>
  171        AVector<Model> as() {
  172            auto idField = AField<ASqlModel<Model>>::make(&ASqlModel<Model>::id);
  173            AVector<Model> result;
  174            result.reserve(0x100);
  175
  176            mSql += " ";
  177            mSql += mWhereExpr;
  178            auto dbResult = Autumn::get<ASqlDatabase>()->query(mSql, mWhereParams);
  179
  180            AVector<size_t> sqlColumnToModelFieldIndexMapping;
  181            AVector<_<AField<Model>>> fields;
  182            fields << AModelMeta<Model>::getFields().valueVector();
  183            /*
  184            {
  185                sqlColumnToModelFieldIndexMapping.resize(dbResult->getColumns().size());
  186                AMap<AString, size_t> columnNameToFieldIndexMapping;
  187                size_t counter = 0;
  188                for (auto& column : dbResult->getColumns()) {
  189                    columnNameToFieldIndexMapping[column.name] = counter++;
  190                }
  191
  192                for (std::pair<AString, _<AField<Model>>>& field : AModelMeta<Model>::fields) {
  193                    sqlColumnToModelFieldIndexMapping.push_back(columnNameToFieldIndexMapping[field.first]);
  194                    fields << field.second;
  195                }
  196            }*/
  197
  198            for (auto& row : dbResult) {
  199                Model m;
  200                idField->set(m, row->getValue(0));
  201                for (size_t columnIndex = 1; columnIndex < dbResult->getColumns().size(); ++columnIndex) {
  202                    fields[columnIndex - 1]->set(m, row->getValue(columnIndex));
  203                }
  204                result << std::move(m);
  205            }
  206
  207            return result;
  208        }
  209    };
  210
  211    class API_AUI_DATA Update: public WhereStatement {
  212        friend class ASqlBuilder;
  213    private:
  214        AMap<AString, AVariant> mValues;
  215
  216        Update(const AMap<AString, AVariant>& values, ASqlBuilder& builder, const AString& sql);
  217
  218    public:
  219        Update(const Update&) = delete;
  220        ~Update() override;
  221
  222        Update& where(const WhereExpr& w) {
  223            whereImpl(w);
  224            return *this;
  225        }
  226
  227        void set(const AString& key, const AVariant& value) {
  228            mValues[key] = value;
  229        }
  230    };
  231
  232    class API_AUI_DATA Delete: public WhereStatement {
  233        friend class ASqlBuilder;
  234    private:
  235        AVector<AVariant> mData;
  236
  237        Delete(ASqlBuilder& builder, const AString& sql);
  238
  239    public:
  240        Delete(const Delete&) = delete;
  241        ~Delete() override;
  242
  243        Delete& where(const WhereExpr& w) {
  244            whereImpl(w);
  245            return *this;
  246        }
  247    };
  248
  249    ASqlBuilder(const AString& tableName);
  250
  256    Insert insert(const AStringVector& columnNames);
  257
  258
  264    template<typename... Args>
  265    Insert ins(Args&&... args) {
  266        AStringVector v;
  267        aui::parameter_pack::for_each([&](const AString& s) {
  268            v << s;
  269        }, std::forward<Args>(args)...);
  270        return insert(v);
  271    }
  272
  273
  279    Select select(const AStringVector& columnNames = {});
  280
  286    template<typename... Args>
  287    Select sel(Args&&... args) {
  288        AStringVector v;
  289        aui::parameter_pack::for_each([&](const AString& s) {
  290            v << s;
  291        }, std::forward<Args>(args)...);
  292        return select(v);
  293    }
  294
  300    Update update(const AMap<AString, AVariant>& data = {});
  301
  307
  308
  315    template<typename Model>
  316    id_t insertORM(const Model& model) {
  317        Insert insertStatement = insert(AModelMeta<Model>::getFields().keyVector());
  318
  319        AVector<AVariant> row;
  320        for (std::pair<AString, _<AField<Model>>> field : AModelMeta<Model>::getFields()) {
  321            row << field.second->get(model);
  322        }
  323        insertStatement.row(row);
  324        return insertStatement.rowId();
  325    }
  326
  332    template<typename Model>
  333    void updateORM(const Model& model) {
  334        Update updateStatement = update();
  335
  336        AVector<AVariant> row;
  337        for (const std::pair<AString, _<AField<Model>>>& field : AModelMeta<Model>::getFields()) {
  338            if (field.first != "id")
  339                updateStatement.set(field.first, field.second->get(model));
  340        }
  341        updateStatement.where(WhereStatement::WhereExpr("id") == model.id);
  342    }
  343
  349    template<typename Model>
  350    void removeORM(const Model& model) {
  351        remove().where(WhereStatement::WhereExpr("id") == model.id);
  352    }
  353};
  354
  355
  356typedef ASqlBuilder table;
A std::map with AUI extensions.
Definition AMap.h:218
Definition ASqlBuilder.h:232
Definition ASqlBuilder.h:58
Definition ASqlBuilder.h:144
AVector< Model > as()
Gets query result in ORM.
Definition ASqlBuilder.h:171
AVector< AVector< AVariant > > get()
Gets query result.
ASqlBuilder & also()
Does the another request to the same table.
Definition ASqlBuilder.h:53
Definition ASqlBuilder.h:211
Definition ASqlBuilder.h:79
Definition ASqlBuilder.h:30
Insert ins(Args &&... args)
Does the INSERT query to DB.
Definition ASqlBuilder.h:265
Select select(const AStringVector &columnNames={})
Does the SELECT query to DB.
void removeORM(const Model &model)
Removes ORM object.
Definition ASqlBuilder.h:350
Delete remove()
Does the DELETE query to DB.
Insert insert(const AStringVector &columnNames)
Does the INSERT query to DB.
void updateORM(const Model &model)
Updates ORM object.
Definition ASqlBuilder.h:333
Select sel(Args &&... args)
Does the SELECT query to DB.
Definition ASqlBuilder.h:287
Update update(const AMap< AString, AVariant > &data={})
Does the UPDATE query to DB.
id_t insertORM(const Model &model)
Inserts ORM object.
Definition ASqlBuilder.h:316
An AVector with string-related functions.
Definition AStringVector.h:22
Represents a Unicode character string.
Definition AString.h:38
void insertAll(const OtherContainer &c) noexcept
Inserts all values of the specified container to the end.
Definition AString.h:294
A std::vector with AUI extensions.
Definition AVector.h:39
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:179
Defines model metadata (list of fields, name of appropriate sql table, etc...)
Definition AModelMeta.h:52
Defines a model that can be stored in an SQL database. Implements queries for this type to the databa...
Definition ASqlModel.h:26