diff --git a/native/android/app/CMakeLists.txt b/native/android/app/CMakeLists.txt
--- a/native/android/app/CMakeLists.txt
+++ b/native/android/app/CMakeLists.txt
@@ -187,9 +187,6 @@
   # SQLCipher amalgamation
   ${_node_modules_dir}/@commapp/sqlcipher-amalgamation/src
 
-  # SQLite ORM
-  ../../cpp/third-party/sqlite_orm
-
   # symlinked React Native headers
   ../headers
 
diff --git a/native/cpp/CommonCpp/DatabaseManagers/CMakeLists.txt b/native/cpp/CommonCpp/DatabaseManagers/CMakeLists.txt
--- a/native/cpp/CommonCpp/DatabaseManagers/CMakeLists.txt
+++ b/native/cpp/CommonCpp/DatabaseManagers/CMakeLists.txt
@@ -36,8 +36,6 @@
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../Tools>
   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
-  # TODO: Remove once native/cpp has a CMakeLists.txt
-  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../third-party/sqlite_orm>
   PRIVATE
   # HACK
   "../../../node_modules/react-native/ReactCommon/jsi"
diff --git a/native/cpp/third-party/sqlite_orm/CMakeLists.txt b/native/cpp/third-party/sqlite_orm/CMakeLists.txt
deleted file mode 100644
--- a/native/cpp/third-party/sqlite_orm/CMakeLists.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-project(comm-sqlite-orm)
-cmake_minimum_required(VERSION 3.4)
-
-include(GNUInstallDirs)
-
-find_package(PkgConfig)
-pkg_check_modules(sqlite REQUIRED sqlite3)
-
-set(SQLITE_HDRS
-  "sqlite_orm.h"
-)
-
-add_library(comm-sqlite-orm
-  INTERFACE
-  ${SQLITE_HDRS}
-)
-
-# Reference local directory when building, use installation path when installing
-target_include_directories(comm-sqlite-orm
-  PUBLIC INTERFACE
-  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
-  $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
-)
-
-install(TARGETS comm-sqlite-orm EXPORT comm-sqlite-orm-export
-  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT comm-sqlite-orm
-  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT comm-sqlite-orm
-  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT comm-sqlite-orm
-)
-
-install(FILES ${SQLITE_HDRS} DESTINATION include)
-
-set(_cmake_dir "cmake/comm-sqlite-orm")
-export(TARGETS comm-sqlite-orm
-  NAMESPACE comm-sqlite-orm::
-  FILE ${CMAKE_CURRENT_BINARY_DIR}/${_cmake_dir}/comm-sqlite-orm-targets.cmake
-)
-
-# For installation
-install(EXPORT comm-sqlite-orm-export
-  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/comm-sqlite-orm
-  NAMESPACE comm-sqlite-orm::
-)
diff --git a/native/cpp/third-party/sqlite_orm/LICENSE b/native/cpp/third-party/sqlite_orm/LICENSE
deleted file mode 100644
--- a/native/cpp/third-party/sqlite_orm/LICENSE
+++ /dev/null
@@ -1,661 +0,0 @@
-                    GNU AFFERO GENERAL PUBLIC LICENSE
-                       Version 3, 19 November 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU Affero General Public License is a free, copyleft license for
-software and other kinds of works, specifically designed to ensure
-cooperation with the community in the case of network server software.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-our General Public Licenses are intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  Developers that use our General Public Licenses protect your rights
-with two steps: (1) assert copyright on the software, and (2) offer
-you this License which gives you legal permission to copy, distribute
-and/or modify the software.
-
-  A secondary benefit of defending all users' freedom is that
-improvements made in alternate versions of the program, if they
-receive widespread use, become available for other developers to
-incorporate.  Many developers of free software are heartened and
-encouraged by the resulting cooperation.  However, in the case of
-software used on network servers, this result may fail to come about.
-The GNU General Public License permits making a modified version and
-letting the public access it on a server without ever releasing its
-source code to the public.
-
-  The GNU Affero General Public License is designed specifically to
-ensure that, in such cases, the modified source code becomes available
-to the community.  It requires the operator of a network server to
-provide the source code of the modified version running there to the
-users of that server.  Therefore, public use of a modified version, on
-a publicly accessible server, gives the public access to the source
-code of the modified version.
-
-  An older license, called the Affero General Public License and
-published by Affero, was designed to accomplish similar goals.  This is
-a different license, not a version of the Affero GPL, but Affero has
-released a new version of the Affero GPL which permits relicensing under
-this license.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU Affero General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Remote Network Interaction; Use with the GNU General Public License.
-
-  Notwithstanding any other provision of this License, if you modify the
-Program, your modified version must prominently offer all users
-interacting with it remotely through a computer network (if your version
-supports such interaction) an opportunity to receive the Corresponding
-Source of your version by providing access to the Corresponding Source
-from a network server at no charge, through some standard or customary
-means of facilitating copying of software.  This Corresponding Source
-shall include the Corresponding Source for any work covered by version 3
-of the GNU General Public License that is incorporated pursuant to the
-following paragraph.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the work with which it is combined will remain governed by version
-3 of the GNU General Public License.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU Affero General Public License from time to time.  Such new versions
-will be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU Affero General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU Affero General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU Affero General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published
-    by the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source.  For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code.  There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for the
-specific requirements.
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU AGPL, see
-<https://www.gnu.org/licenses/>.
diff --git a/native/cpp/third-party/sqlite_orm/sqlite_orm.h b/native/cpp/third-party/sqlite_orm/sqlite_orm.h
deleted file mode 100644
--- a/native/cpp/third-party/sqlite_orm/sqlite_orm.h
+++ /dev/null
@@ -1,13690 +0,0 @@
-#pragma once
-
-#if defined(_MSC_VER)
-#if defined(min)
-__pragma(push_macro("min"))
-#undef min
-#define __RESTORE_MIN__
-#endif
-#if defined(max)
-    __pragma(push_macro("max"))
-#undef max
-#define __RESTORE_MAX__
-#endif
-#endif // defined(_MSC_VER)
-
-#include <ciso646> //  due to #166
-
-#if __cplusplus >= 201703L // use of C++17 or higher
-// Enables use of std::optional in SQLITE_ORM.
-#define SQLITE_ORM_OPTIONAL_SUPPORTED
-#endif
-#pragma once
-
-#include <sqlite3.h>
-#include <sstream> //  std::ostringstream
-#include <stdexcept>
-#include <string>       //  std::string
-#include <system_error> // std::error_code, std::system_error
-
-        namespace sqlite_orm {
-
-  enum class orm_error_code {
-    not_found = 1,
-    type_is_not_mapped_to_storage,
-    trying_to_dereference_null_iterator,
-    too_many_tables_specified,
-    incorrect_set_fields_specified,
-    column_not_found,
-    table_has_no_primary_key_column,
-    cannot_start_a_transaction_within_a_transaction,
-    no_active_transaction,
-    incorrect_journal_mode_string,
-    invalid_collate_argument_enum,
-    failed_to_init_a_backup,
-    unknown_member_value,
-    incorrect_order,
-  };
-}
-
-namespace sqlite_orm {
-
-class orm_error_category : public std::error_category {
-public:
-  const char *name() const noexcept override final {
-    return "ORM error";
-  }
-
-  std::string message(int c) const override final {
-    switch (static_cast<orm_error_code>(c)) {
-    case orm_error_code::not_found:
-      return "Not found";
-    case orm_error_code::type_is_not_mapped_to_storage:
-      return "Type is not mapped to storage";
-    case orm_error_code::trying_to_dereference_null_iterator:
-      return "Trying to dereference null iterator";
-    case orm_error_code::too_many_tables_specified:
-      return "Too many tables specified";
-    case orm_error_code::incorrect_set_fields_specified:
-      return "Incorrect set fields specified";
-    case orm_error_code::column_not_found:
-      return "Column not found";
-    case orm_error_code::table_has_no_primary_key_column:
-      return "Table has no primary key column";
-    case orm_error_code::cannot_start_a_transaction_within_a_transaction:
-      return "Cannot start a transaction within a transaction";
-    case orm_error_code::no_active_transaction:
-      return "No active transaction";
-    case orm_error_code::invalid_collate_argument_enum:
-      return "Invalid collate_argument enum";
-    case orm_error_code::failed_to_init_a_backup:
-      return "Failed to init a backup";
-    case orm_error_code::unknown_member_value:
-      return "Unknown member value";
-    case orm_error_code::incorrect_order:
-      return "Incorrect order";
-    default:
-      return "unknown error";
-    }
-  }
-};
-
-class sqlite_error_category : public std::error_category {
-public:
-  const char *name() const noexcept override final {
-    return "SQLite error";
-  }
-
-  std::string message(int c) const override final {
-    return sqlite3_errstr(c);
-  }
-};
-
-inline const orm_error_category &get_orm_error_category() {
-  static orm_error_category res;
-  return res;
-}
-
-inline const sqlite_error_category &get_sqlite_error_category() {
-  static sqlite_error_category res;
-  return res;
-}
-
-template <typename... T>
-std::string get_error_message(sqlite3 *db, T &&... args) {
-  std::ostringstream stream;
-  using unpack = int[];
-  static_cast<void>(
-      unpack{0, (static_cast<void>(static_cast<void>(stream << args)), 0)...});
-  stream << sqlite3_errmsg(db);
-  return stream.str();
-}
-
-template <typename... T>
-[[noreturn]] void throw_error(sqlite3 *db, T &&... args) {
-  throw std::system_error(
-      std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-      get_error_message(db, std::forward<T>(args)...));
-}
-} // namespace sqlite_orm
-
-namespace std {
-template <>
-struct is_error_code_enum<sqlite_orm::orm_error_code> : std::true_type {};
-
-inline std::error_code make_error_code(sqlite_orm::orm_error_code errorCode) {
-  return std::error_code(
-      static_cast<int>(errorCode), sqlite_orm::get_orm_error_category());
-}
-} // namespace std
-#pragma once
-
-#include <tuple>       //  std::tuple, std::get
-#include <type_traits> //  std::false_type, std::true_type
-
-// #include "static_magic.h"
-
-#include <type_traits> //  std::false_type, std::true_type, std::integral_constant
-
-namespace sqlite_orm {
-
-//  got from here
-//  https://stackoverflow.com/questions/37617677/implementing-a-compile-time-static-if-logic-for-different-string-types-in-a-co
-namespace internal {
-
-static inline decltype(auto) empty_callable() {
-  static auto res = [](auto &&...) {};
-  return (res);
-}
-
-template <typename T, typename F>
-decltype(auto) static_if(std::true_type, const T &t, const F &) {
-  return (t);
-}
-
-template <typename T, typename F>
-decltype(auto) static_if(std::false_type, const T &, const F &f) {
-  return (f);
-}
-
-template <bool B, typename T, typename F>
-decltype(auto) static_if(const T &t, const F &f) {
-  return static_if(std::integral_constant<bool, B>{}, t, f);
-}
-
-template <bool B, typename T> decltype(auto) static_if(const T &t) {
-  return static_if(std::integral_constant<bool, B>{}, t, empty_callable());
-}
-
-template <typename T>
-using static_not = std::integral_constant<bool, !T::value>;
-} // namespace internal
-
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-//  got from here
-//  http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type
-namespace tuple_helper {
-
-template <typename T, typename Tuple> struct has_type;
-
-template <typename T> struct has_type<T, std::tuple<>> : std::false_type {};
-
-template <typename T, typename U, typename... Ts>
-struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};
-
-template <typename T, typename... Ts>
-struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};
-
-template <typename T, typename Tuple>
-using tuple_contains_type = typename has_type<T, Tuple>::type;
-
-template <size_t N, class... Args> struct iterator {
-
-  template <class L>
-  void
-  operator()(const std::tuple<Args...> &t, const L &l, bool reverse = true) {
-    if (reverse) {
-      l(std::get<N>(t));
-      iterator<N - 1, Args...>()(t, l, reverse);
-    } else {
-      iterator<N - 1, Args...>()(t, l, reverse);
-      l(std::get<N>(t));
-    }
-  }
-};
-
-template <class... Args> struct iterator<0, Args...> {
-
-  template <class L>
-  void operator()(
-      const std::tuple<Args...> &t,
-      const L &l,
-      bool /*reverse*/ = true) {
-    l(std::get<0>(t));
-  }
-};
-
-template <size_t N> struct iterator<N> {
-
-  template <class L>
-  void operator()(const std::tuple<> &, const L &, bool /*reverse*/ = true) {
-    //..
-  }
-};
-
-template <size_t N, size_t I, class L, class R>
-void move_tuple_impl(L &lhs, R &rhs) {
-  std::get<I>(lhs) = std::move(std::get<I>(rhs));
-  internal::static_if<std::integral_constant<bool, N != I + 1>{}>(
-      [](auto &l, auto &r) { move_tuple_impl<N, I + 1>(l, r); })(lhs, rhs);
-}
-} // namespace tuple_helper
-
-namespace internal {
-
-template <size_t N, class L, class R> void move_tuple(L &lhs, R &rhs) {
-  using bool_type = std::integral_constant<bool, N != 0>;
-  static_if<bool_type{}>([](auto &l, auto &r) {
-    tuple_helper::move_tuple_impl<N, 0>(l, r);
-  })(lhs, rhs);
-}
-
-template <class L, class... Args>
-void iterate_tuple(const std::tuple<Args...> &t, const L &l) {
-  using tuple_type = std::tuple<Args...>;
-  tuple_helper::iterator<std::tuple_size<tuple_type>::value - 1, Args...>()(
-      t, l, false);
-}
-
-template <typename... input_t>
-using tuple_cat_t = decltype(std::tuple_cat(std::declval<input_t>()...));
-
-template <class... Args> struct conc_tuple {
-  using type = tuple_cat_t<Args...>;
-};
-
-template <class T, template <class> class C> struct count_tuple;
-
-template <template <class> class C> struct count_tuple<std::tuple<>, C> {
-  static constexpr const int value = 0;
-};
-
-template <class H, class... Args, template <class> class C>
-struct count_tuple<std::tuple<H, Args...>, C> {
-  static constexpr const int value =
-      C<H>::value + count_tuple<std::tuple<Args...>, C>::value;
-};
-} // namespace internal
-} // namespace sqlite_orm
-#pragma once
-
-#include <memory> //  std::shared_ptr, std::unique_ptr
-#include <string> //  std::string
-#include <vector> //  std::vector
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-#include <optional> // std::optional
-#endif              // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-namespace sqlite_orm {
-
-/**
- *  This class accepts c++ type and transfers it to sqlite name (int -> INTEGER,
- * std::string -> TEXT)
- */
-template <class T, typename Enable = void> struct type_printer;
-
-struct integer_printer {
-  inline const std::string &print() {
-    static const std::string res = "INTEGER";
-    return res;
-  }
-};
-
-struct text_printer {
-  inline const std::string &print() {
-    static const std::string res = "TEXT";
-    return res;
-  }
-};
-
-struct real_printer {
-  inline const std::string &print() {
-    static const std::string res = "REAL";
-    return res;
-  }
-};
-
-struct blob_printer {
-  inline const std::string &print() {
-    static const std::string res = "BLOB";
-    return res;
-  }
-};
-
-// Note unsigned/signed char and simple char used for storing integer values,
-// not char values.
-template <>
-struct type_printer<unsigned char, void> : public integer_printer {};
-
-template <> struct type_printer<signed char, void> : public integer_printer {};
-
-template <> struct type_printer<char, void> : public integer_printer {};
-
-template <>
-struct type_printer<unsigned short int, void> : public integer_printer {};
-
-template <> struct type_printer<short, void> : public integer_printer {};
-
-template <> struct type_printer<unsigned int, void> : public integer_printer {};
-
-template <> struct type_printer<int, void> : public integer_printer {};
-
-template <>
-struct type_printer<unsigned long, void> : public integer_printer {};
-
-template <> struct type_printer<long, void> : public integer_printer {};
-
-template <>
-struct type_printer<unsigned long long, void> : public integer_printer {};
-
-template <> struct type_printer<long long, void> : public integer_printer {};
-
-template <> struct type_printer<bool, void> : public integer_printer {};
-
-template <> struct type_printer<std::string, void> : public text_printer {};
-
-template <> struct type_printer<std::wstring, void> : public text_printer {};
-
-template <> struct type_printer<const char *, void> : public text_printer {};
-
-template <> struct type_printer<float, void> : public real_printer {};
-
-template <> struct type_printer<double, void> : public real_printer {};
-
-template <class T>
-struct type_printer<std::shared_ptr<T>, void> : public type_printer<T> {};
-
-template <class T>
-struct type_printer<std::unique_ptr<T>, void> : public type_printer<T> {};
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <class T>
-struct type_printer<std::optional<T>, void> : public type_printer<T> {};
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-template <>
-struct type_printer<std::vector<char>, void> : public blob_printer {};
-} // namespace sqlite_orm
-#pragma once
-
-namespace sqlite_orm {
-
-namespace internal {
-
-enum class collate_argument {
-  binary,
-  nocase,
-  rtrim,
-};
-}
-
-} // namespace sqlite_orm
-#pragma once
-
-#include <ostream>     //  std::ostream
-#include <sstream>     //  std::stringstream
-#include <string>      //  std::string
-#include <tuple>       //  std::tuple, std::make_tuple
-#include <type_traits> //  std::is_base_of, std::false_type, std::true_type
-
-namespace sqlite_orm {
-
-namespace constraints {
-
-/**
- *  AUTOINCREMENT constraint class.
- */
-struct autoincrement_t {
-
-  operator std::string() const {
-    return "AUTOINCREMENT";
-  }
-};
-
-struct primary_key_base {
-  enum class order_by {
-    unspecified,
-    ascending,
-    descending,
-  };
-
-  order_by asc_option = order_by::unspecified;
-
-  operator std::string() const {
-    std::string res = "PRIMARY KEY";
-    switch (this->asc_option) {
-    case order_by::ascending:
-      res += " ASC";
-      break;
-    case order_by::descending:
-      res += " DESC";
-      break;
-    default:
-      break;
-    }
-    return res;
-  }
-};
-
-/**
- *  PRIMARY KEY constraint class.
- *  Cs is parameter pack which contains columns (member pointers and/or function
- * pointers). Can be empty when used withen `make_column` function.
- */
-template <class... Cs> struct primary_key_t : primary_key_base {
-  using order_by = primary_key_base::order_by;
-  using columns_tuple = std::tuple<Cs...>;
-
-  columns_tuple columns;
-
-  primary_key_t(decltype(columns) c) : columns(move(c)) {
-  }
-
-  primary_key_t<Cs...> asc() const {
-    auto res = *this;
-    res.asc_option = order_by::ascending;
-    return res;
-  }
-
-  primary_key_t<Cs...> desc() const {
-    auto res = *this;
-    res.asc_option = order_by::descending;
-    return res;
-  }
-};
-
-struct unique_base {
-  operator std::string() const {
-    return "UNIQUE";
-  }
-};
-
-/**
- *  UNIQUE constraint class.
- */
-template <class... Args> struct unique_t : unique_base {
-  using columns_tuple = std::tuple<Args...>;
-
-  columns_tuple columns;
-
-  unique_t(columns_tuple columns_) : columns(move(columns_)) {
-  }
-};
-
-/**
- *  DEFAULT constraint class.
- *  T is a value type.
- */
-template <class T> struct default_t {
-  using value_type = T;
-
-  value_type value;
-
-  operator std::string() const {
-    return "DEFAULT";
-  }
-};
-
-#if SQLITE_VERSION_NUMBER >= 3006019
-
-/**
- *  FOREIGN KEY constraint class.
- *  Cs are columns which has foreign key
- *  Rs are column which C references to
- *  Available in SQLite 3.6.19 or higher
- */
-
-template <class A, class B> struct foreign_key_t;
-
-enum class foreign_key_action {
-  none, //  not specified
-  no_action,
-  restrict_,
-  set_null,
-  set_default,
-  cascade,
-};
-
-inline std::ostream &operator<<(std::ostream &os, foreign_key_action action) {
-  switch (action) {
-  case decltype(action)::no_action:
-    os << "NO ACTION";
-    break;
-  case decltype(action)::restrict_:
-    os << "RESTRICT";
-    break;
-  case decltype(action)::set_null:
-    os << "SET NULL";
-    break;
-  case decltype(action)::set_default:
-    os << "SET DEFAULT";
-    break;
-  case decltype(action)::cascade:
-    os << "CASCADE";
-    break;
-  case decltype(action)::none:
-    break;
-  }
-  return os;
-}
-
-struct on_update_delete_base {
-  const bool update; //  true if update and false if delete
-
-  operator std::string() const {
-    if (this->update) {
-      return "ON UPDATE";
-    } else {
-      return "ON DELETE";
-    }
-  }
-};
-
-/**
- *  F - foreign key class
- */
-template <class F> struct on_update_delete_t : on_update_delete_base {
-  using foreign_key_type = F;
-
-  const foreign_key_type &fk;
-
-  on_update_delete_t(
-      decltype(fk) fk_,
-      decltype(update) update_,
-      foreign_key_action action_)
-      : on_update_delete_base{update_}, fk(fk_), _action(action_) {
-  }
-
-  foreign_key_action _action = foreign_key_action::none;
-
-  foreign_key_type no_action() const {
-    auto res = this->fk;
-    if (update) {
-      res.on_update._action = foreign_key_action::no_action;
-    } else {
-      res.on_delete._action = foreign_key_action::no_action;
-    }
-    return res;
-  }
-
-  foreign_key_type restrict_() const {
-    auto res = this->fk;
-    if (update) {
-      res.on_update._action = foreign_key_action::restrict_;
-    } else {
-      res.on_delete._action = foreign_key_action::restrict_;
-    }
-    return res;
-  }
-
-  foreign_key_type set_null() const {
-    auto res = this->fk;
-    if (update) {
-      res.on_update._action = foreign_key_action::set_null;
-    } else {
-      res.on_delete._action = foreign_key_action::set_null;
-    }
-    return res;
-  }
-
-  foreign_key_type set_default() const {
-    auto res = this->fk;
-    if (update) {
-      res.on_update._action = foreign_key_action::set_default;
-    } else {
-      res.on_delete._action = foreign_key_action::set_default;
-    }
-    return res;
-  }
-
-  foreign_key_type cascade() const {
-    auto res = this->fk;
-    if (update) {
-      res.on_update._action = foreign_key_action::cascade;
-    } else {
-      res.on_delete._action = foreign_key_action::cascade;
-    }
-    return res;
-  }
-
-  operator bool() const {
-    return this->_action != decltype(this->_action)::none;
-  }
-};
-
-template <class... Cs, class... Rs>
-struct foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>> {
-  using columns_type = std::tuple<Cs...>;
-  using references_type = std::tuple<Rs...>;
-  using self = foreign_key_t<columns_type, references_type>;
-
-  columns_type columns;
-  references_type references;
-
-  on_update_delete_t<self> on_update;
-  on_update_delete_t<self> on_delete;
-
-  static_assert(
-      std::tuple_size<columns_type>::value ==
-          std::tuple_size<references_type>::value,
-      "Columns size must be equal to references tuple");
-
-  foreign_key_t(columns_type columns_, references_type references_)
-      : columns(std::move(columns_)),
-        references(std::move(references_)),
-        on_update(*this, true, foreign_key_action::none),
-        on_delete(*this, false, foreign_key_action::none) {
-  }
-
-  foreign_key_t(const self &other)
-      : columns(other.columns),
-        references(other.references),
-        on_update(*this, true, other.on_update._action),
-        on_delete(*this, false, other.on_delete._action) {
-  }
-
-  self &operator=(const self &other) {
-    this->columns = other.columns;
-    this->references = other.references;
-    this->on_update = {*this, true, other.on_update._action};
-    this->on_delete = {*this, false, other.on_delete._action};
-    return *this;
-  }
-
-  template <class L> void for_each_column(const L &) {
-  }
-
-  template <class... Opts> constexpr bool has_every() const {
-    return false;
-  }
-};
-
-/**
- *  Cs can be a class member pointer, a getter function member pointer or setter
- *  func member pointer
- *  Available in SQLite 3.6.19 or higher
- */
-template <class... Cs> struct foreign_key_intermediate_t {
-  using tuple_type = std::tuple<Cs...>;
-
-  tuple_type columns;
-
-  foreign_key_intermediate_t(tuple_type columns_)
-      : columns(std::move(columns_)) {
-  }
-
-  template <class... Rs>
-  foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>> references(Rs... refs) {
-    return {
-        std::move(this->columns), std::make_tuple(std::forward<Rs>(refs)...)};
-  }
-};
-#endif
-
-struct collate_t {
-  internal::collate_argument argument = internal::collate_argument::binary;
-
-  collate_t(internal::collate_argument argument_) : argument(argument_) {
-  }
-
-  operator std::string() const {
-    std::string res =
-        "COLLATE " + this->string_from_collate_argument(this->argument);
-    return res;
-  }
-
-  static std::string
-  string_from_collate_argument(internal::collate_argument argument) {
-    switch (argument) {
-    case decltype(argument)::binary:
-      return "BINARY";
-    case decltype(argument)::nocase:
-      return "NOCASE";
-    case decltype(argument)::rtrim:
-      return "RTRIM";
-    }
-    throw std::system_error(
-        std::make_error_code(orm_error_code::invalid_collate_argument_enum));
-  }
-};
-
-struct check_string {
-  operator std::string() const {
-    return "CHECK";
-  }
-};
-
-template <class T> struct check_t : check_string {
-  using expression_type = T;
-
-  expression_type expression;
-
-  check_t(expression_type expression_) : expression(std::move(expression_)) {
-  }
-};
-
-template <class T> struct is_constraint : std::false_type {};
-
-template <> struct is_constraint<autoincrement_t> : std::true_type {};
-
-template <class... Cs>
-struct is_constraint<primary_key_t<Cs...>> : std::true_type {};
-
-template <class... Args>
-struct is_constraint<unique_t<Args...>> : std::true_type {};
-
-template <class T> struct is_constraint<default_t<T>> : std::true_type {};
-
-template <class C, class R>
-struct is_constraint<foreign_key_t<C, R>> : std::true_type {};
-
-template <> struct is_constraint<collate_t> : std::true_type {};
-
-template <class T> struct is_constraint<check_t<T>> : std::true_type {};
-
-template <class... Args> struct constraints_size;
-
-template <> struct constraints_size<> { static constexpr const int value = 0; };
-
-template <class H, class... Args> struct constraints_size<H, Args...> {
-  static constexpr const int value =
-      is_constraint<H>::value + constraints_size<Args...>::value;
-};
-} // namespace constraints
-
-#if SQLITE_VERSION_NUMBER >= 3006019
-
-/**
- *  FOREIGN KEY constraint construction function that takes member pointer as
- * argument Available in SQLite 3.6.19 or higher
- */
-template <class... Cs>
-constraints::foreign_key_intermediate_t<Cs...> foreign_key(Cs... columns) {
-  return {std::make_tuple(std::forward<Cs>(columns)...)};
-}
-#endif
-
-/**
- *  UNIQUE constraint builder function.
- */
-template <class... Args> constraints::unique_t<Args...> unique(Args... args) {
-  return {std::make_tuple(std::forward<Args>(args)...)};
-}
-
-inline constraints::unique_t<> unique() {
-  return {{}};
-}
-
-inline constraints::autoincrement_t autoincrement() {
-  return {};
-}
-
-template <class... Cs> constraints::primary_key_t<Cs...> primary_key(Cs... cs) {
-  return {std::make_tuple(std::forward<Cs>(cs)...)};
-}
-
-inline constraints::primary_key_t<> primary_key() {
-  return {{}};
-}
-
-template <class T> constraints::default_t<T> default_value(T t) {
-  return {std::move(t)};
-}
-
-inline constraints::collate_t collate_nocase() {
-  return {internal::collate_argument::nocase};
-}
-
-inline constraints::collate_t collate_binary() {
-  return {internal::collate_argument::binary};
-}
-
-inline constraints::collate_t collate_rtrim() {
-  return {internal::collate_argument::rtrim};
-}
-
-template <class T> constraints::check_t<T> check(T t) {
-  return {std::move(t)};
-}
-
-namespace internal {
-
-/**
- *  FOREIGN KEY traits. Common case
- */
-template <class T> struct is_foreign_key : std::false_type {};
-
-/**
- *  FOREIGN KEY traits. Specialized case
- */
-template <class C, class R>
-struct is_foreign_key<constraints::foreign_key_t<C, R>> : std::true_type {};
-
-/**
- *  PRIMARY KEY traits. Common case
- */
-template <class T> struct is_primary_key : public std::false_type {};
-
-/**
- *  PRIMARY KEY traits. Specialized case
- */
-template <class... Cs>
-struct is_primary_key<constraints::primary_key_t<Cs...>>
-    : public std::true_type {};
-} // namespace internal
-
-} // namespace sqlite_orm
-#pragma once
-
-#include <memory>      //  std::shared_ptr, std::unique_ptr
-#include <type_traits> //  std::false_type, std::true_type
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-#include <optional> // std::optional
-#endif              // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-namespace sqlite_orm {
-
-/**
- *  This is class that tells `sqlite_orm` that type is nullable. Nullable types
- *  are mapped to sqlite database as `NULL` and not-nullable are mapped as `NOT
- * NULL`. Default nullability status for all types is `NOT NULL`. So if you want
- * to map custom type as `NULL` (for example: boost::optional) you have to
- * create a specialiation of type_is_nullable for your type and derive from
- * `std::true_type`.
- */
-template <class T> struct type_is_nullable : public std::false_type {
-  bool operator()(const T &) const {
-    return true;
-  }
-};
-
-/**
- *  This is a specialization for std::shared_ptr. std::shared_ptr is nullable in
- * sqlite_orm.
- */
-template <class T>
-struct type_is_nullable<std::shared_ptr<T>> : public std::true_type {
-  bool operator()(const std::shared_ptr<T> &t) const {
-    return static_cast<bool>(t);
-  }
-};
-
-/**
- *  This is a specialization for std::unique_ptr. std::unique_ptr is nullable
- * too.
- */
-template <class T>
-struct type_is_nullable<std::unique_ptr<T>> : public std::true_type {
-  bool operator()(const std::unique_ptr<T> &t) const {
-    return static_cast<bool>(t);
-  }
-};
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-/**
- *  This is a specialization for std::optional. std::optional is nullable.
- */
-template <class T>
-struct type_is_nullable<std::optional<T>> : public std::true_type {
-  bool operator()(const std::optional<T> &t) const {
-    return t.has_value();
-  }
-};
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-} // namespace sqlite_orm
-#pragma once
-
-#include <memory>  //  std::unique_ptr
-#include <sstream> //  std::stringstream
-#include <string>  //  std::string
-
-// #include "constraints.h"
-
-// #include "serializator_context.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct serializator_context_base {
-  bool replace_bindable_with_question = false;
-  bool skip_table_name = true;
-  bool use_parentheses = true;
-
-  template <class O, class F> std::string column_name(F O::*) const {
-    return {};
-  }
-};
-
-template <class I> struct serializator_context : serializator_context_base {
-  using impl_type = I;
-
-  const impl_type &impl;
-
-  serializator_context(const impl_type &impl_) : impl(impl_) {
-  }
-
-  template <class O, class F> std::string column_name(F O::*m) const {
-    return this->impl.column_name(m);
-  }
-};
-
-template <class S> struct serializator_context_builder {
-  using storage_type = S;
-  using impl_type = typename storage_type::impl_type;
-
-  serializator_context_builder(const storage_type &storage_)
-      : storage(storage_) {
-  }
-
-  serializator_context<impl_type> operator()() const {
-    return {this->storage.impl};
-  }
-
-  const storage_type &storage;
-};
-
-} // namespace internal
-
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class T> std::string serialize(const T &t);
-
-/**
- *  This class is used in tuple interation to know whether tuple constains
- * `default_value_t` constraint class and what it's value if it is
- */
-struct default_value_extractor {
-
-  template <class A> std::unique_ptr<std::string> operator()(const A &) {
-    return {};
-  }
-
-  template <class T>
-  std::unique_ptr<std::string> operator()(const constraints::default_t<T> &t) {
-    serializator_context_base context;
-    return std::make_unique<std::string>(serialize(t.value, context));
-  }
-};
-
-} // namespace internal
-
-} // namespace sqlite_orm
-#pragma once
-
-#include <type_traits> //  std::false_type, std::true_type
-
-// #include "negatable.h"
-
-namespace sqlite_orm {
-namespace internal {
-struct negatable_t {};
-} // namespace internal
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- *  Inherit this class to support arithmetic types overloading
- */
-struct arithmetic_t {};
-
-template <class L, class R, class... Ds> struct binary_operator : Ds... {
-  using left_type = L;
-  using right_type = R;
-
-  left_type lhs;
-  right_type rhs;
-
-  binary_operator(left_type lhs_, right_type rhs_)
-      : lhs(std::move(lhs_)), rhs(std::move(rhs_)) {
-  }
-};
-
-struct conc_string {
-  operator std::string() const {
-    return "||";
-  }
-};
-
-/**
- *  Result of concatenation || operator
- */
-template <class L, class R> using conc_t = binary_operator<L, R, conc_string>;
-
-struct add_string {
-  operator std::string() const {
-    return "+";
-  }
-};
-
-/**
- *  Result of addition + operator
- */
-template <class L, class R>
-using add_t = binary_operator<L, R, add_string, arithmetic_t, negatable_t>;
-
-struct sub_string {
-  operator std::string() const {
-    return "-";
-  }
-};
-
-/**
- *  Result of substitute - operator
- */
-template <class L, class R>
-using sub_t = binary_operator<L, R, sub_string, arithmetic_t, negatable_t>;
-
-struct mul_string {
-  operator std::string() const {
-    return "*";
-  }
-};
-
-/**
- *  Result of multiply * operator
- */
-template <class L, class R>
-using mul_t = binary_operator<L, R, mul_string, arithmetic_t, negatable_t>;
-
-struct div_string {
-  operator std::string() const {
-    return "/";
-  }
-};
-
-/**
- *  Result of divide / operator
- */
-template <class L, class R>
-using div_t = binary_operator<L, R, div_string, arithmetic_t, negatable_t>;
-
-struct mod_string {
-  operator std::string() const {
-    return "%";
-  }
-};
-
-/**
- *  Result of mod % operator
- */
-template <class L, class R>
-using mod_t = binary_operator<L, R, mod_string, arithmetic_t, negatable_t>;
-
-struct bitwise_shift_left_string {
-  operator std::string() const {
-    return "<<";
-  }
-};
-
-/**
- * Result of bitwise shift left << operator
- */
-template <class L, class R>
-using bitwise_shift_left_t =
-    binary_operator<L, R, bitwise_shift_left_string, arithmetic_t, negatable_t>;
-
-struct bitwise_shift_right_string {
-  operator std::string() const {
-    return ">>";
-  }
-};
-
-/**
- * Result of bitwise shift right >> operator
- */
-template <class L, class R>
-using bitwise_shift_right_t = binary_operator<
-    L,
-    R,
-    bitwise_shift_right_string,
-    arithmetic_t,
-    negatable_t>;
-
-struct bitwise_and_string {
-  operator std::string() const {
-    return "&";
-  }
-};
-
-/**
- * Result of bitwise and & operator
- */
-template <class L, class R>
-using bitwise_and_t =
-    binary_operator<L, R, bitwise_and_string, arithmetic_t, negatable_t>;
-
-struct bitwise_or_string {
-  operator std::string() const {
-    return "|";
-  }
-};
-
-/**
- * Result of bitwise or | operator
- */
-template <class L, class R>
-using bitwise_or_t =
-    binary_operator<L, R, bitwise_or_string, arithmetic_t, negatable_t>;
-
-struct bitwise_not_string {
-  operator std::string() const {
-    return "~";
-  }
-};
-
-/**
- * Result of bitwise not ~ operator
- */
-template <class T>
-struct bitwise_not_t : bitwise_not_string, arithmetic_t, negatable_t {
-  using argument_type = T;
-
-  argument_type argument;
-
-  bitwise_not_t(argument_type argument_) : argument(std::move(argument_)) {
-  }
-};
-
-struct assign_string {
-  operator std::string() const {
-    return "=";
-  }
-};
-/**
- *  Result of assign = operator
- */
-template <class L, class R>
-using assign_t = binary_operator<L, R, assign_string>;
-
-/**
- *  Assign operator traits. Common case
- */
-template <class T> struct is_assign_t : public std::false_type {};
-
-/**
- *  Assign operator traits. Specialized case
- */
-template <class L, class R>
-struct is_assign_t<assign_t<L, R>> : public std::true_type {};
-
-/**
- *  Is not an operator but a result of c(...) function. Has operator= overloaded
- * which returns assign_t
- */
-template <class T> struct expression_t {
-  T t;
-
-  expression_t(T t_) : t(std::move(t_)) {
-  }
-
-  template <class R> assign_t<T, R> operator=(R r) const {
-    return {this->t, std::move(r)};
-  }
-
-  assign_t<T, std::nullptr_t> operator=(std::nullptr_t) const {
-    return {this->t, nullptr};
-  }
-};
-
-} // namespace internal
-
-/**
- *  Public interface for syntax sugar for columns. Example: `where(c(&User::id)
- * == 5)` or `storage.update(set(c(&User::name) = "Dua Lipa"));
- */
-template <class T> internal::expression_t<T> c(T t) {
-  return {std::move(t)};
-}
-
-/**
- *  Public interface for || concatenation operator. Example:
- * `select(conc(&User::name, "@gmail.com"));` => SELECT name || '@gmail.com'
- * FROM users
- */
-template <class L, class R> internal::conc_t<L, R> conc(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-/**
- *  Public interface for + operator. Example: `select(add(&User::age, 100));` =>
- * SELECT age + 100 FROM users
- */
-template <class L, class R> internal::add_t<L, R> add(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-/**
- *  Public interface for - operator. Example: `select(add(&User::age, 1));` =>
- * SELECT age - 1 FROM users
- */
-template <class L, class R> internal::sub_t<L, R> sub(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R> internal::mul_t<L, R> mul(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R> internal::div_t<L, R> div(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R> internal::mod_t<L, R> mod(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R>
-internal::bitwise_shift_left_t<L, R> bitwise_shift_left(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R>
-internal::bitwise_shift_right_t<L, R> bitwise_shift_right(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R>
-internal::bitwise_and_t<L, R> bitwise_and(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R> internal::bitwise_or_t<L, R> bitwise_or(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class T> internal::bitwise_not_t<T> bitwise_not(T t) {
-  return {std::move(t)};
-}
-
-template <class L, class R> internal::assign_t<L, R> assign(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-} // namespace sqlite_orm
-#pragma once
-
-#include <memory>      //  std::unique_ptr
-#include <string>      //  std::string
-#include <tuple>       //  std::tuple
-#include <type_traits> //  std::true_type, std::false_type, std::is_same, std::enable_if, std::is_member_pointer, std::is_member_function_pointer
-
-// #include "type_is_nullable.h"
-
-// #include "tuple_helper.h"
-
-// #include "default_value_extractor.h"
-
-// #include "constraints.h"
-
-// #include "getter_traits.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class T, class SFINAE = void>
-struct is_field_member_pointer : std::false_type {};
-
-template <class T>
-struct is_field_member_pointer<
-    T,
-    typename std::enable_if<
-        std::is_member_pointer<T>::value &&
-        !std::is_member_function_pointer<T>::value>::type> : std::true_type {};
-
-template <class T, class SFINAE = void> struct field_member_traits;
-
-template <class O, class F>
-struct field_member_traits<
-    F O::*,
-    typename std::enable_if<is_field_member_pointer<F O::*>::value>::type> {
-  using object_type = O;
-  using field_type = F;
-};
-
-/**
- *  Getters aliases
- */
-template <class O, class T> using getter_by_value_const = T (O::*)() const;
-
-template <class O, class T> using getter_by_value = T (O::*)();
-
-template <class O, class T> using getter_by_ref_const = T &(O::*)() const;
-
-template <class O, class T> using getter_by_ref = T &(O::*)();
-
-template <class O, class T>
-using getter_by_const_ref_const = const T &(O::*)() const;
-
-template <class O, class T> using getter_by_const_ref = const T &(O::*)();
-
-/**
- *  Setters aliases
- */
-template <class O, class T> using setter_by_value = void (O::*)(T);
-
-template <class O, class T> using setter_by_ref = void (O::*)(T &);
-
-template <class O, class T> using setter_by_const_ref = void (O::*)(const T &);
-
-template <class T> struct is_getter : std::false_type {};
-
-template <class O, class T>
-struct is_getter<getter_by_value_const<O, T>> : std::true_type {};
-
-template <class O, class T>
-struct is_getter<getter_by_value<O, T>> : std::true_type {};
-
-template <class O, class T>
-struct is_getter<getter_by_ref_const<O, T>> : std::true_type {};
-
-template <class O, class T>
-struct is_getter<getter_by_ref<O, T>> : std::true_type {};
-
-template <class O, class T>
-struct is_getter<getter_by_const_ref_const<O, T>> : std::true_type {};
-
-template <class O, class T>
-struct is_getter<getter_by_const_ref<O, T>> : std::true_type {};
-
-template <class T> struct is_setter : std::false_type {};
-
-template <class O, class T>
-struct is_setter<setter_by_value<O, T>> : std::true_type {};
-
-template <class O, class T>
-struct is_setter<setter_by_ref<O, T>> : std::true_type {};
-
-template <class O, class T>
-struct is_setter<setter_by_const_ref<O, T>> : std::true_type {};
-
-template <class T> struct getter_traits;
-
-template <class O, class T> struct getter_traits<getter_by_value_const<O, T>> {
-  using object_type = O;
-  using field_type = T;
-
-  static constexpr const bool returns_lvalue = false;
-};
-
-template <class O, class T> struct getter_traits<getter_by_value<O, T>> {
-  using object_type = O;
-  using field_type = T;
-
-  static constexpr const bool returns_lvalue = false;
-};
-
-template <class O, class T> struct getter_traits<getter_by_ref_const<O, T>> {
-  using object_type = O;
-  using field_type = T;
-
-  static constexpr const bool returns_lvalue = true;
-};
-
-template <class O, class T> struct getter_traits<getter_by_ref<O, T>> {
-  using object_type = O;
-  using field_type = T;
-
-  static constexpr const bool returns_lvalue = true;
-};
-
-template <class O, class T>
-struct getter_traits<getter_by_const_ref_const<O, T>> {
-  using object_type = O;
-  using field_type = T;
-
-  static constexpr const bool returns_lvalue = true;
-};
-
-template <class O, class T> struct getter_traits<getter_by_const_ref<O, T>> {
-  using object_type = O;
-  using field_type = T;
-
-  static constexpr const bool returns_lvalue = true;
-};
-
-template <class T> struct setter_traits;
-
-template <class O, class T> struct setter_traits<setter_by_value<O, T>> {
-  using object_type = O;
-  using field_type = T;
-};
-
-template <class O, class T> struct setter_traits<setter_by_ref<O, T>> {
-  using object_type = O;
-  using field_type = T;
-};
-
-template <class O, class T> struct setter_traits<setter_by_const_ref<O, T>> {
-  using object_type = O;
-  using field_type = T;
-};
-
-template <class T, class SFINAE = void> struct member_traits;
-
-template <class T>
-struct member_traits<
-    T,
-    typename std::enable_if<is_field_member_pointer<T>::value>::type> {
-  using object_type = typename field_member_traits<T>::object_type;
-  using field_type = typename field_member_traits<T>::field_type;
-};
-
-template <class T>
-struct member_traits<T, typename std::enable_if<is_getter<T>::value>::type> {
-  using object_type = typename getter_traits<T>::object_type;
-  using field_type = typename getter_traits<T>::field_type;
-};
-
-template <class T>
-struct member_traits<T, typename std::enable_if<is_setter<T>::value>::type> {
-  using object_type = typename setter_traits<T>::object_type;
-  using field_type = typename setter_traits<T>::field_type;
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct column_base {
-
-  /**
-   *  Column name. Specified during construction in `make_column`.
-   */
-  const std::string name;
-};
-
-/**
- *  This class stores single column info. column_t is a pair of
- * [column_name:member_pointer] mapped to a storage O is a mapped class, e.g.
- * User T is a mapped class'es field type, e.g. &User::name Op... is a
- * constraints pack, e.g. primary_key_t, autoincrement_t etc
- */
-template <
-    class O,
-    class T,
-    class G /* = const T& (O::*)() const*/,
-    class S /* = void (O::*)(T)*/,
-    class... Op>
-struct column_t : column_base {
-  using object_type = O;
-  using field_type = T;
-  using constraints_type = std::tuple<Op...>;
-  using member_pointer_t = field_type object_type::*;
-  using getter_type = G;
-  using setter_type = S;
-
-  /**
-   *  Member pointer used to read/write member
-   */
-  member_pointer_t member_pointer /* = nullptr*/;
-
-  /**
-   *  Getter member function pointer to get a value. If member_pointer is null
-   * than `getter` and `setter` must be not null
-   */
-  getter_type getter /* = nullptr*/;
-
-  /**
-   *  Setter member function
-   */
-  setter_type setter /* = nullptr*/;
-
-  /**
-   *  Constraints tuple
-   */
-  constraints_type constraints;
-
-  column_t(
-      std::string name_,
-      member_pointer_t member_pointer_,
-      getter_type getter_,
-      setter_type setter_,
-      constraints_type constraints_)
-      : column_base{std::move(name_)},
-        member_pointer(member_pointer_),
-        getter(getter_),
-        setter(setter_),
-        constraints(move(constraints_)) {
-  }
-
-  /**
-   *  Simplified interface for `NOT NULL` constraint
-   */
-  bool not_null() const {
-    return !type_is_nullable<field_type>::value;
-  }
-
-  template <class Opt> constexpr bool has() const {
-    return tuple_helper::tuple_contains_type<Opt, constraints_type>::value;
-  }
-
-  template <class O1, class O2, class... Opts>
-  constexpr bool has_every() const {
-    if (has<O1>() && has<O2>()) {
-      return true;
-    } else {
-      return has_every<Opts...>();
-    }
-  }
-
-  template <class O1> constexpr bool has_every() const {
-    return has<O1>();
-  }
-
-  /**
-   *  Simplified interface for `DEFAULT` constraint
-   *  @return string representation of default value if it exists otherwise
-   * nullptr
-   */
-  std::unique_ptr<std::string> default_value() const {
-    std::unique_ptr<std::string> res;
-    iterate_tuple(this->constraints, [&res](auto &v) {
-      auto dft = internal::default_value_extractor()(v);
-      if (dft) {
-        res = std::move(dft);
-      }
-    });
-    return res;
-  }
-};
-
-/**
- *  Column traits. Common case.
- */
-template <class T> struct is_column : public std::false_type {};
-
-/**
- *  Column traits. Specialized case case.
- */
-template <class O, class T, class... Op>
-struct is_column<column_t<O, T, Op...>> : public std::true_type {};
-
-template <class T> struct column_field_type { using type = void; };
-
-template <class O, class T, class... Op>
-struct column_field_type<column_t<O, T, Op...>> {
-  using type = typename column_t<O, T, Op...>::field_type;
-};
-
-template <class T> struct column_constraints_type {
-  using type = std::tuple<>;
-};
-
-template <class O, class T, class... Op>
-struct column_constraints_type<column_t<O, T, Op...>> {
-  using type = typename column_t<O, T, Op...>::constraints_type;
-};
-
-} // namespace internal
-
-/**
- *  Column builder function. You should use it to create columns instead of
- * constructor
- */
-template <
-    class O,
-    class T,
-    typename = typename std::enable_if<
-        !std::is_member_function_pointer<T O::*>::value>::type,
-    class... Op>
-internal::column_t<O, T, const T &(O::*)() const, void (O::*)(T), Op...>
-make_column(const std::string &name, T O::*m, Op... constraints) {
-  static_assert(
-      constraints::template constraints_size<Op...>::value ==
-          std::tuple_size<std::tuple<Op...>>::value,
-      "Incorrect constraints pack");
-  static_assert(
-      internal::is_field_member_pointer<T O::*>::value,
-      "second argument expected as a member field pointer, not member function "
-      "pointer");
-  return {name, m, nullptr, nullptr, std::make_tuple(constraints...)};
-}
-
-/**
- *  Column builder function with setter and getter. You should use it to create
- * columns instead of constructor
- */
-template <
-    class G,
-    class S,
-    typename = typename std::enable_if<internal::is_getter<G>::value>::type,
-    typename = typename std::enable_if<internal::is_setter<S>::value>::type,
-    class... Op>
-internal::column_t<
-    typename internal::setter_traits<S>::object_type,
-    typename internal::setter_traits<S>::field_type,
-    G,
-    S,
-    Op...>
-make_column(const std::string &name, S setter, G getter, Op... constraints) {
-  static_assert(
-      std::is_same<
-          typename internal::setter_traits<S>::field_type,
-          typename internal::getter_traits<G>::field_type>::value,
-      "Getter and setter must get and set same data type");
-  static_assert(
-      constraints::template constraints_size<Op...>::value ==
-          std::tuple_size<std::tuple<Op...>>::value,
-      "Incorrect constraints pack");
-  return {name, nullptr, getter, setter, std::make_tuple(constraints...)};
-}
-
-/**
- *  Column builder function with getter and setter (reverse order). You should
- * use it to create columns instead of constructor
- */
-template <
-    class G,
-    class S,
-    typename = typename std::enable_if<internal::is_getter<G>::value>::type,
-    typename = typename std::enable_if<internal::is_setter<S>::value>::type,
-    class... Op>
-internal::column_t<
-    typename internal::setter_traits<S>::object_type,
-    typename internal::setter_traits<S>::field_type,
-    G,
-    S,
-    Op...>
-make_column(const std::string &name, G getter, S setter, Op... constraints) {
-  static_assert(
-      std::is_same<
-          typename internal::setter_traits<S>::field_type,
-          typename internal::getter_traits<G>::field_type>::value,
-      "Getter and setter must get and set same data type");
-  static_assert(
-      constraints::template constraints_size<Op...>::value ==
-          std::tuple_size<std::tuple<Op...>>::value,
-      "Incorrect constraints pack");
-  return {name, nullptr, getter, setter, std::make_tuple(constraints...)};
-}
-
-} // namespace sqlite_orm
-#pragma once
-
-#include <cstddef> //  std::nullptr_t
-#include <memory>  //  std::shared_ptr, std::unique_ptr
-#include <sstream> //  std::stringstream
-#include <string>  //  std::string
-#include <vector>  //  std::vector
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-#include <optional> // std::optional
-#endif              // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-namespace sqlite_orm {
-
-/**
- *  Is used to print members mapped to objects in storage_t::dump member
- * function. Other developers can create own specialization to map custom types
- */
-template <class T> struct field_printer {
-  std::string operator()(const T &t) const {
-    std::stringstream stream;
-    stream << t;
-    return stream.str();
-  }
-};
-
-/**
- *  Upgrade to integer is required when using unsigned char(uint8_t)
- */
-template <> struct field_printer<unsigned char> {
-  std::string operator()(const unsigned char &t) const {
-    std::stringstream stream;
-    stream << +t;
-    return stream.str();
-  }
-};
-
-/**
- *  Upgrade to integer is required when using signed char(int8_t)
- */
-template <> struct field_printer<signed char> {
-  std::string operator()(const signed char &t) const {
-    std::stringstream stream;
-    stream << +t;
-    return stream.str();
-  }
-};
-
-/**
- *  char is neigher signer char nor unsigned char so it has its own
- * specialization
- */
-template <> struct field_printer<char> {
-  std::string operator()(const char &t) const {
-    std::stringstream stream;
-    stream << +t;
-    return stream.str();
-  }
-};
-
-template <> struct field_printer<std::string> {
-  std::string operator()(const std::string &t) const {
-    return t;
-  }
-};
-
-template <> struct field_printer<std::vector<char>> {
-  std::string operator()(const std::vector<char> &t) const {
-    std::stringstream ss;
-    ss << std::hex;
-    for (auto c : t) {
-      ss << c;
-    }
-    return ss.str();
-  }
-};
-
-template <> struct field_printer<std::nullptr_t> {
-  std::string operator()(const std::nullptr_t &) const {
-    return "null";
-  }
-};
-
-template <class T> struct field_printer<std::shared_ptr<T>> {
-  std::string operator()(const std::shared_ptr<T> &t) const {
-    if (t) {
-      return field_printer<T>()(*t);
-    } else {
-      return field_printer<std::nullptr_t>()(nullptr);
-    }
-  }
-};
-
-template <class T> struct field_printer<std::unique_ptr<T>> {
-  std::string operator()(const std::unique_ptr<T> &t) const {
-    if (t) {
-      return field_printer<T>()(*t);
-    } else {
-      return field_printer<std::nullptr_t>()(nullptr);
-    }
-  }
-};
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <class T> struct field_printer<std::optional<T>> {
-  std::string operator()(const std::optional<T> &t) const {
-    if (t.has_value()) {
-      return field_printer<T>()(*t);
-    } else {
-      return field_printer<std::nullptr_t>()(nullptr);
-    }
-  }
-};
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-} // namespace sqlite_orm
-#pragma once
-
-#include <string>      //  std::string
-#include <tuple>       //  std::tuple
-#include <type_traits> //  std::enable_if, std::is_same
-#include <vector>      //  std::vector
-
-// #include "collate_argument.h"
-
-// #include "constraints.h"
-
-// #include "optional_container.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- *  This is a cute class which allows storing something or nothing
- *  depending on template argument. Useful for optional class members
- */
-template <class T> struct optional_container {
-  using type = T;
-
-  type field;
-
-  template <class L> void apply(const L &l) const {
-    l(this->field);
-  }
-};
-
-template <> struct optional_container<void> {
-  using type = void;
-
-  template <class L> void apply(const L &) const {
-    //..
-  }
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "negatable.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-struct arithmetic_t;
-}
-
-namespace internal {
-
-struct limit_string {
-  operator std::string() const {
-    return "LIMIT";
-  }
-};
-
-/**
- *  Stores LIMIT/OFFSET info
- */
-template <class T, bool has_offset, bool offset_is_implicit, class O>
-struct limit_t : limit_string {
-  T lim;
-  internal::optional_container<O> off;
-
-  limit_t() = default;
-
-  limit_t(decltype(lim) lim_) : lim(std::move(lim_)) {
-  }
-
-  limit_t(decltype(lim) lim_, decltype(off) off_)
-      : lim(std::move(lim_)), off(std::move(off_)) {
-  }
-};
-
-template <class T> struct is_limit : std::false_type {};
-
-template <class T, bool has_offset, bool offset_is_implicit, class O>
-struct is_limit<limit_t<T, has_offset, offset_is_implicit, O>>
-    : std::true_type {};
-
-/**
- *  Stores OFFSET only info
- */
-template <class T> struct offset_t { T off; };
-
-template <class T> struct is_offset : std::false_type {};
-
-template <class T> struct is_offset<offset_t<T>> : std::true_type {};
-
-/**
- *  Inherit from this class if target class can be chained with other conditions
- * with '&&' and '||' operators
- */
-struct condition_t {};
-
-/**
- *  Collated something
- */
-template <class T> struct collate_t : public condition_t {
-  T expr;
-  internal::collate_argument argument;
-
-  collate_t(T expr_, internal::collate_argument argument_)
-      : expr(std::move(expr_)), argument(argument_) {
-  }
-
-  operator std::string() const {
-    return constraints::collate_t{this->argument};
-  }
-};
-
-struct named_collate_base {
-  std::string name;
-
-  operator std::string() const {
-    return "COLLATE " + this->name;
-  }
-};
-
-/**
- *  Collated something with custom collate function
- */
-template <class T> struct named_collate : named_collate_base {
-  T expr;
-
-  named_collate(T expr_, std::string name_)
-      : named_collate_base{std::move(name_)}, expr(std::move(expr_)) {
-  }
-};
-
-struct negated_condition_string {
-  operator std::string() const {
-    return "NOT";
-  }
-};
-
-/**
- *  Result of not operator
- */
-template <class C>
-struct negated_condition_t : condition_t, negated_condition_string {
-  C c;
-
-  negated_condition_t(C c_) : c(std::move(c_)) {
-  }
-};
-
-/**
- *  Base class for binary conditions
- */
-template <class L, class R> struct binary_condition : public condition_t {
-  using left_type = L;
-  using right_type = R;
-
-  left_type l;
-  right_type r;
-
-  binary_condition() = default;
-
-  binary_condition(left_type l_, right_type r_)
-      : l(std::move(l_)), r(std::move(r_)) {
-  }
-};
-
-struct and_condition_string {
-  operator std::string() const {
-    return "AND";
-  }
-};
-
-/**
- *  Result of and operator
- */
-template <class L, class R>
-struct and_condition_t : binary_condition<L, R>, and_condition_string {
-  using super = binary_condition<L, R>;
-
-  using super::super;
-};
-
-struct or_condition_string {
-  operator std::string() const {
-    return "OR";
-  }
-};
-
-/**
- *  Result of or operator
- */
-template <class L, class R>
-struct or_condition_t : binary_condition<L, R>, or_condition_string {
-  using super = binary_condition<L, R>;
-
-  using super::super;
-};
-
-struct is_equal_string {
-  operator std::string() const {
-    return "=";
-  }
-};
-
-/**
- *  = and == operators object
- */
-template <class L, class R>
-struct is_equal_t : binary_condition<L, R>,
-                    is_equal_string,
-                    internal::negatable_t {
-  using self = is_equal_t<L, R>;
-
-  using binary_condition<L, R>::binary_condition;
-
-  collate_t<self> collate_binary() const {
-    return {*this, internal::collate_argument::binary};
-  }
-
-  collate_t<self> collate_nocase() const {
-    return {*this, internal::collate_argument::nocase};
-  }
-
-  collate_t<self> collate_rtrim() const {
-    return {*this, internal::collate_argument::rtrim};
-  }
-
-  named_collate<self> collate(std::string name) const {
-    return {*this, std::move(name)};
-  }
-};
-
-struct is_not_equal_string {
-  operator std::string() const {
-    return "!=";
-  }
-};
-
-/**
- *  != operator object
- */
-template <class L, class R>
-struct is_not_equal_t : binary_condition<L, R>,
-                        is_not_equal_string,
-                        internal::negatable_t {
-  using self = is_not_equal_t<L, R>;
-
-  using binary_condition<L, R>::binary_condition;
-
-  collate_t<self> collate_binary() const {
-    return {*this, internal::collate_argument::binary};
-  }
-
-  collate_t<self> collate_nocase() const {
-    return {*this, internal::collate_argument::nocase};
-  }
-
-  collate_t<self> collate_rtrim() const {
-    return {*this, internal::collate_argument::rtrim};
-  }
-};
-
-struct greater_than_string {
-  operator std::string() const {
-    return ">";
-  }
-};
-
-/**
- *  > operator object.
- */
-template <class L, class R>
-struct greater_than_t : binary_condition<L, R>,
-                        greater_than_string,
-                        internal::negatable_t {
-  using self = greater_than_t<L, R>;
-
-  using binary_condition<L, R>::binary_condition;
-
-  collate_t<self> collate_binary() const {
-    return {*this, internal::collate_argument::binary};
-  }
-
-  collate_t<self> collate_nocase() const {
-    return {*this, internal::collate_argument::nocase};
-  }
-
-  collate_t<self> collate_rtrim() const {
-    return {*this, internal::collate_argument::rtrim};
-  }
-};
-
-struct greater_or_equal_string {
-  operator std::string() const {
-    return ">=";
-  }
-};
-
-/**
- *  >= operator object.
- */
-template <class L, class R>
-struct greater_or_equal_t : binary_condition<L, R>,
-                            greater_or_equal_string,
-                            internal::negatable_t {
-  using self = greater_or_equal_t<L, R>;
-
-  using binary_condition<L, R>::binary_condition;
-
-  collate_t<self> collate_binary() const {
-    return {*this, internal::collate_argument::binary};
-  }
-
-  collate_t<self> collate_nocase() const {
-    return {*this, internal::collate_argument::nocase};
-  }
-
-  collate_t<self> collate_rtrim() const {
-    return {*this, internal::collate_argument::rtrim};
-  }
-};
-
-struct lesser_than_string {
-  operator std::string() const {
-    return "<";
-  }
-};
-
-/**
- *  < operator object.
- */
-template <class L, class R>
-struct lesser_than_t : binary_condition<L, R>,
-                       lesser_than_string,
-                       internal::negatable_t {
-  using self = lesser_than_t<L, R>;
-
-  using binary_condition<L, R>::binary_condition;
-
-  collate_t<self> collate_binary() const {
-    return {*this, internal::collate_argument::binary};
-  }
-
-  collate_t<self> collate_nocase() const {
-    return {*this, internal::collate_argument::nocase};
-  }
-
-  collate_t<self> collate_rtrim() const {
-    return {*this, internal::collate_argument::rtrim};
-  }
-};
-
-struct lesser_or_equal_string {
-  operator std::string() const {
-    return "<=";
-  }
-};
-
-/**
- *  <= operator object.
- */
-template <class L, class R>
-struct lesser_or_equal_t : binary_condition<L, R>,
-                           lesser_or_equal_string,
-                           internal::negatable_t {
-  using self = lesser_or_equal_t<L, R>;
-
-  using binary_condition<L, R>::binary_condition;
-
-  collate_t<self> collate_binary() const {
-    return {*this, internal::collate_argument::binary};
-  }
-
-  collate_t<self> collate_nocase() const {
-    return {*this, internal::collate_argument::nocase};
-  }
-
-  collate_t<self> collate_rtrim() const {
-    return {*this, internal::collate_argument::rtrim};
-  }
-};
-
-struct in_base {
-  bool negative = false; //  used in not_in
-
-  operator std::string() const {
-    if (!this->negative) {
-      return "IN";
-    } else {
-      return "NOT IN";
-    }
-  }
-};
-
-/**
- *  IN operator object.
- */
-template <class L, class A>
-struct in_t : condition_t, in_base, internal::negatable_t {
-  using self = in_t<L, A>;
-
-  L l;   //  left expression
-  A arg; //  in arg
-
-  in_t(L l_, A arg_, bool negative_)
-      : in_base{negative_}, l(l_), arg(std::move(arg_)) {
-  }
-};
-
-struct is_null_string {
-  operator std::string() const {
-    return "IS NULL";
-  }
-};
-
-/**
- *  IS NULL operator object.
- */
-template <class T> struct is_null_t : is_null_string, internal::negatable_t {
-  using self = is_null_t<T>;
-
-  T t;
-
-  is_null_t(T t_) : t(std::move(t_)) {
-  }
-};
-
-struct is_not_null_string {
-  operator std::string() const {
-    return "IS NOT NULL";
-  }
-};
-
-/**
- *  IS NOT NULL operator object.
- */
-template <class T>
-struct is_not_null_t : is_not_null_string, internal::negatable_t {
-  using self = is_not_null_t<T>;
-
-  T t;
-
-  is_not_null_t(T t_) : t(std::move(t_)) {
-  }
-};
-
-struct where_string {
-  operator std::string() const {
-    return "WHERE";
-  }
-};
-
-/**
- *  WHERE argument holder.
- *  C is conditions type. Can be any condition like: is_equal_t, is_null_t,
- * exists_t etc
- */
-template <class C> struct where_t : where_string {
-  C c;
-
-  where_t(C c_) : c(std::move(c_)) {
-  }
-};
-
-template <class T> struct is_where : std::false_type {};
-
-template <class T> struct is_where<where_t<T>> : std::true_type {};
-
-struct order_by_base {
-  int asc_desc = 0; //  1: asc, -1: desc
-  std::string _collate_argument;
-};
-
-struct order_by_string {
-  operator std::string() const {
-    return "ORDER BY";
-  }
-};
-
-/**
- *  ORDER BY argument holder.
- */
-template <class O> struct order_by_t : order_by_base, order_by_string {
-  using self = order_by_t<O>;
-
-  O o;
-
-  order_by_t(O o_) : o(std::move(o_)) {
-  }
-
-  self asc() {
-    auto res = *this;
-    res.asc_desc = 1;
-    return res;
-  }
-
-  self desc() {
-    auto res = *this;
-    res.asc_desc = -1;
-    return res;
-  }
-
-  self collate_binary() const {
-    auto res = *this;
-    res._collate_argument =
-        constraints::collate_t::string_from_collate_argument(
-            sqlite_orm::internal::collate_argument::binary);
-    return res;
-  }
-
-  self collate_nocase() const {
-    auto res = *this;
-    res._collate_argument =
-        constraints::collate_t::string_from_collate_argument(
-            sqlite_orm::internal::collate_argument::nocase);
-    return res;
-  }
-
-  self collate_rtrim() const {
-    auto res = *this;
-    res._collate_argument =
-        constraints::collate_t::string_from_collate_argument(
-            sqlite_orm::internal::collate_argument::rtrim);
-    return res;
-  }
-
-  self collate(std::string name) const {
-    auto res = *this;
-    res._collate_argument = std::move(name);
-    return res;
-  }
-};
-
-/**
- *  ORDER BY pack holder.
- */
-template <class... Args> struct multi_order_by_t : order_by_string {
-  using args_type = std::tuple<Args...>;
-
-  args_type args;
-
-  multi_order_by_t(args_type &&args_) : args(std::move(args_)) {
-  }
-};
-
-struct dynamic_order_by_entry_t : order_by_base {
-  std::string name;
-
-  dynamic_order_by_entry_t(
-      decltype(name) name_,
-      int asc_desc_,
-      std::string collate_argument_)
-      : order_by_base{asc_desc_, move(collate_argument_)}, name(move(name_)) {
-  }
-};
-
-/**
- *  C - serializator context class
- */
-template <class C> struct dynamic_order_by_t : order_by_string {
-  using context_t = C;
-  using entry_t = dynamic_order_by_entry_t;
-  using const_iterator = typename std::vector<entry_t>::const_iterator;
-
-  dynamic_order_by_t(const context_t &context_) : context(context_) {
-  }
-
-  template <class O> void push_back(order_by_t<O> order_by) {
-    auto newContext = this->context;
-    newContext.skip_table_name = true;
-    auto columnName = serialize(order_by.o, newContext);
-    entries.emplace_back(
-        move(columnName), order_by.asc_desc, move(order_by._collate_argument));
-  }
-
-  const_iterator begin() const {
-    return this->entries.begin();
-  }
-
-  const_iterator end() const {
-    return this->entries.end();
-  }
-
-  void clear() {
-    this->entries.clear();
-  }
-
-protected:
-  std::vector<entry_t> entries;
-  context_t context;
-};
-
-template <class T> struct is_order_by : std::false_type {};
-
-template <class O> struct is_order_by<order_by_t<O>> : std::true_type {};
-
-template <class... Args>
-struct is_order_by<multi_order_by_t<Args...>> : std::true_type {};
-
-template <class C>
-struct is_order_by<dynamic_order_by_t<C>> : std::true_type {};
-
-struct group_by_string {
-  operator std::string() const {
-    return "GROUP BY";
-  }
-};
-
-/**
- *  GROUP BY pack holder.
- */
-template <class... Args> struct group_by_t : group_by_string {
-  using args_type = std::tuple<Args...>;
-  args_type args;
-
-  group_by_t(args_type &&args_) : args(std::move(args_)) {
-  }
-};
-
-template <class T> struct is_group_by : std::false_type {};
-
-template <class... Args>
-struct is_group_by<group_by_t<Args...>> : std::true_type {};
-
-struct between_string {
-  operator std::string() const {
-    return "BETWEEN";
-  }
-};
-
-/**
- *  BETWEEN operator object.
- */
-template <class A, class T> struct between_t : condition_t, between_string {
-  using expression_type = A;
-  using lower_type = T;
-  using upper_type = T;
-
-  expression_type expr;
-  lower_type b1;
-  upper_type b2;
-
-  between_t(expression_type expr_, lower_type b1_, upper_type b2_)
-      : expr(std::move(expr_)), b1(std::move(b1_)), b2(std::move(b2_)) {
-  }
-};
-
-struct like_string {
-  operator std::string() const {
-    return "LIKE";
-  }
-};
-
-/**
- *  LIKE operator object.
- */
-template <class A, class T, class E>
-struct like_t : condition_t, like_string, internal::negatable_t {
-  using self = like_t<A, T, E>;
-  using arg_t = A;
-  using pattern_t = T;
-  using escape_t = E;
-
-  arg_t arg;
-  pattern_t pattern;
-  sqlite_orm::internal::optional_container<escape_t>
-      arg3; //  not escape cause escape exists as a function here
-
-  like_t(
-      arg_t arg_,
-      pattern_t pattern_,
-      sqlite_orm::internal::optional_container<escape_t> escape_)
-      : arg(std::move(arg_)),
-        pattern(std::move(pattern_)),
-        arg3(std::move(escape_)) {
-  }
-
-  template <class C> like_t<A, T, C> escape(C c) const {
-    sqlite_orm::internal::optional_container<C> newArg3{std::move(c)};
-    return {std::move(this->arg), std::move(this->pattern), std::move(newArg3)};
-  }
-};
-
-struct glob_string {
-  operator std::string() const {
-    return "GLOB";
-  }
-};
-
-template <class A, class T>
-struct glob_t : condition_t, glob_string, internal::negatable_t {
-  using self = glob_t<A, T>;
-  using arg_t = A;
-  using pattern_t = T;
-
-  arg_t arg;
-  pattern_t pattern;
-
-  glob_t(arg_t arg_, pattern_t pattern_)
-      : arg(std::move(arg_)), pattern(std::move(pattern_)) {
-  }
-};
-
-struct cross_join_string {
-  operator std::string() const {
-    return "CROSS JOIN";
-  }
-};
-
-/**
- *  CROSS JOIN holder.
- *  T is joined type which represents any mapped table.
- */
-template <class T> struct cross_join_t : cross_join_string { using type = T; };
-
-struct natural_join_string {
-  operator std::string() const {
-    return "NATURAL JOIN";
-  }
-};
-
-/**
- *  NATURAL JOIN holder.
- *  T is joined type which represents any mapped table.
- */
-template <class T> struct natural_join_t : natural_join_string {
-  using type = T;
-};
-
-struct left_join_string {
-  operator std::string() const {
-    return "LEFT JOIN";
-  }
-};
-
-/**
- *  LEFT JOIN holder.
- *  T is joined type which represents any mapped table.
- *  O is on(...) argument type.
- */
-template <class T, class O> struct left_join_t : left_join_string {
-  using type = T;
-  using on_type = O;
-
-  on_type constraint;
-
-  left_join_t(on_type constraint_) : constraint(std::move(constraint_)) {
-  }
-};
-
-struct join_string {
-  operator std::string() const {
-    return "JOIN";
-  }
-};
-
-/**
- *  Simple JOIN holder.
- *  T is joined type which represents any mapped table.
- *  O is on(...) argument type.
- */
-template <class T, class O> struct join_t : join_string {
-  using type = T;
-  using on_type = O;
-
-  on_type constraint;
-
-  join_t(on_type constraint_) : constraint(std::move(constraint_)) {
-  }
-};
-
-struct left_outer_join_string {
-  operator std::string() const {
-    return "LEFT OUTER JOIN";
-  }
-};
-
-/**
- *  LEFT OUTER JOIN holder.
- *  T is joined type which represents any mapped table.
- *  O is on(...) argument type.
- */
-template <class T, class O> struct left_outer_join_t : left_outer_join_string {
-  using type = T;
-  using on_type = O;
-
-  on_type constraint;
-
-  left_outer_join_t(on_type constraint_) : constraint(std::move(constraint_)) {
-  }
-};
-
-struct on_string {
-  operator std::string() const {
-    return "ON";
-  }
-};
-
-/**
- *  on(...) argument holder used for JOIN, LEFT JOIN, LEFT OUTER JOIN and INNER
- * JOIN T is on type argument.
- */
-template <class T> struct on_t : on_string {
-  using arg_type = T;
-
-  arg_type arg;
-
-  on_t(arg_type arg_) : arg(std::move(arg_)) {
-  }
-};
-
-/**
- *  USING argument holder.
- */
-template <class F, class O> struct using_t {
-  F O::*column = nullptr;
-
-  operator std::string() const {
-    return "USING";
-  }
-};
-
-struct inner_join_string {
-  operator std::string() const {
-    return "INNER JOIN";
-  }
-};
-
-/**
- *  INNER JOIN holder.
- *  T is joined type which represents any mapped table.
- *  O is on(...) argument type.
- */
-template <class T, class O> struct inner_join_t : inner_join_string {
-  using type = T;
-  using on_type = O;
-
-  on_type constraint;
-
-  inner_join_t(on_type constraint_) : constraint(std::move(constraint_)) {
-  }
-};
-
-struct exists_string {
-  operator std::string() const {
-    return "EXISTS";
-  }
-};
-
-template <class T>
-struct exists_t : condition_t, exists_string, internal::negatable_t {
-  using type = T;
-  using self = exists_t<type>;
-
-  type t;
-
-  exists_t(T t_) : t(std::move(t_)) {
-  }
-};
-
-struct having_string {
-  operator std::string() const {
-    return "HAVING";
-  }
-};
-
-/**
- *  HAVING holder.
- *  T is having argument type.
- */
-template <class T> struct having_t : having_string {
-  using type = T;
-
-  type t;
-
-  having_t(type t_) : t(std::move(t_)) {
-  }
-};
-
-template <class T> struct is_having : std::false_type {};
-
-template <class T> struct is_having<having_t<T>> : std::true_type {};
-
-struct cast_string {
-  operator std::string() const {
-    return "CAST";
-  }
-};
-
-/**
- *  CAST holder.
- *  T is a type to cast to
- *  E is an expression type
- *  Example: cast<std::string>(&User::id)
- */
-template <class T, class E> struct cast_t : cast_string {
-  using to_type = T;
-  using expression_type = E;
-
-  expression_type expression;
-
-  cast_t(expression_type expression_) : expression(std::move(expression_)) {
-  }
-};
-
-} // namespace internal
-
-template <
-    class T,
-    typename = typename std::enable_if<
-        std::is_base_of<internal::negatable_t, T>::value>::type>
-internal::negated_condition_t<T> operator!(T arg) {
-  return {std::move(arg)};
-}
-
-/**
- *  Cute operators for columns
- */
-template <class T, class R>
-internal::lesser_than_t<T, R> operator<(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::lesser_than_t<L, T> operator<(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class T, class R>
-internal::lesser_or_equal_t<T, R>
-operator<=(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::lesser_or_equal_t<L, T>
-operator<=(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class T, class R>
-internal::greater_than_t<T, R> operator>(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::greater_than_t<L, T> operator>(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class T, class R>
-internal::greater_or_equal_t<T, R>
-operator>=(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::greater_or_equal_t<L, T>
-operator>=(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class T, class R>
-internal::is_equal_t<T, R> operator==(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::is_equal_t<L, T> operator==(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class T, class R>
-internal::is_not_equal_t<T, R> operator!=(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::is_not_equal_t<L, T> operator!=(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class T, class R>
-internal::conc_t<T, R> operator||(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::conc_t<L, T> operator||(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class L, class R>
-internal::conc_t<L, R>
-operator||(internal::expression_t<L> l, internal::expression_t<R> r) {
-  return {std::move(l.t), std::move(r.t)};
-}
-
-template <class T, class R>
-internal::add_t<T, R> operator+(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::add_t<L, T> operator+(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class L, class R>
-internal::add_t<L, R>
-operator+(internal::expression_t<L> l, internal::expression_t<R> r) {
-  return {std::move(l.t), std::move(r.t)};
-}
-
-template <class T, class R>
-internal::sub_t<T, R> operator-(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::sub_t<L, T> operator-(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class L, class R>
-internal::sub_t<L, R>
-operator-(internal::expression_t<L> l, internal::expression_t<R> r) {
-  return {std::move(l.t), std::move(r.t)};
-}
-
-template <class T, class R>
-internal::mul_t<T, R> operator*(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::mul_t<L, T> operator*(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class L, class R>
-internal::mul_t<L, R>
-operator*(internal::expression_t<L> l, internal::expression_t<R> r) {
-  return {std::move(l.t), std::move(r.t)};
-}
-
-template <class T, class R>
-internal::div_t<T, R> operator/(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::div_t<L, T> operator/(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class L, class R>
-internal::div_t<L, R>
-operator/(internal::expression_t<L> l, internal::expression_t<R> r) {
-  return {std::move(l.t), std::move(r.t)};
-}
-
-template <class T, class R>
-internal::mod_t<T, R> operator%(internal::expression_t<T> expr, R r) {
-  return {std::move(expr.t), std::move(r)};
-}
-
-template <class L, class T>
-internal::mod_t<L, T> operator%(L l, internal::expression_t<T> expr) {
-  return {std::move(l), std::move(expr.t)};
-}
-
-template <class L, class R>
-internal::mod_t<L, R>
-operator%(internal::expression_t<L> l, internal::expression_t<R> r) {
-  return {std::move(l.t), std::move(r.t)};
-}
-
-template <class F, class O> internal::using_t<F, O> using_(F O::*p) {
-  return {std::move(p)};
-}
-
-template <class T> internal::on_t<T> on(T t) {
-  return {std::move(t)};
-}
-
-template <class T> internal::cross_join_t<T> cross_join() {
-  return {};
-}
-
-template <class T> internal::natural_join_t<T> natural_join() {
-  return {};
-}
-
-template <class T, class O> internal::left_join_t<T, O> left_join(O o) {
-  return {std::move(o)};
-}
-
-template <class T, class O> internal::join_t<T, O> join(O o) {
-  return {std::move(o)};
-}
-
-template <class T, class O>
-internal::left_outer_join_t<T, O> left_outer_join(O o) {
-  return {std::move(o)};
-}
-
-template <class T, class O> internal::inner_join_t<T, O> inner_join(O o) {
-  return {std::move(o)};
-}
-
-template <class T> internal::offset_t<T> offset(T off) {
-  return {std::move(off)};
-}
-
-template <class T> internal::limit_t<T, false, false, void> limit(T lim) {
-  return {std::move(lim)};
-}
-
-template <class T, class O>
-typename std::enable_if<
-    !internal::is_offset<T>::value,
-    internal::limit_t<T, true, true, O>>::type
-limit(O off, T lim) {
-  return {std::move(lim), {std::move(off)}};
-}
-
-template <class T, class O>
-internal::limit_t<T, true, false, O> limit(T lim, internal::offset_t<O> offt) {
-  return {std::move(lim), {std::move(offt.off)}};
-}
-
-template <
-    class L,
-    class R,
-    typename = typename std::enable_if<
-        std::is_base_of<internal::condition_t, L>::value ||
-        std::is_base_of<internal::condition_t, R>::value>::type>
-internal::and_condition_t<L, R> operator&&(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <
-    class L,
-    class R,
-    typename = typename std::enable_if<
-        std::is_base_of<internal::condition_t, L>::value ||
-        std::is_base_of<internal::condition_t, R>::value>::type>
-internal::or_condition_t<L, R> operator||(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class T> internal::is_not_null_t<T> is_not_null(T t) {
-  return {std::move(t)};
-}
-
-template <class T> internal::is_null_t<T> is_null(T t) {
-  return {std::move(t)};
-}
-
-template <class L, class E>
-internal::in_t<L, std::vector<E>> in(L l, std::vector<E> values) {
-  return {std::move(l), std::move(values), false};
-}
-
-template <class L, class E>
-internal::in_t<L, std::vector<E>> in(L l, std::initializer_list<E> values) {
-  return {std::move(l), std::move(values), false};
-}
-
-template <class L, class A> internal::in_t<L, A> in(L l, A arg) {
-  return {std::move(l), std::move(arg), false};
-}
-
-template <class L, class E>
-internal::in_t<L, std::vector<E>> not_in(L l, std::vector<E> values) {
-  return {std::move(l), std::move(values), true};
-}
-
-template <class L, class E>
-internal::in_t<L, std::vector<E>> not_in(L l, std::initializer_list<E> values) {
-  return {std::move(l), std::move(values), true};
-}
-
-template <class L, class A> internal::in_t<L, A> not_in(L l, A arg) {
-  return {std::move(l), std::move(arg), true};
-}
-
-template <class L, class R> internal::is_equal_t<L, R> is_equal(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R> internal::is_equal_t<L, R> eq(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R>
-internal::is_not_equal_t<L, R> is_not_equal(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R> internal::is_not_equal_t<L, R> ne(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R>
-internal::greater_than_t<L, R> greater_than(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R> internal::greater_than_t<L, R> gt(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R>
-internal::greater_or_equal_t<L, R> greater_or_equal(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R> internal::greater_or_equal_t<L, R> ge(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R>
-internal::lesser_than_t<L, R> lesser_than(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R> internal::lesser_than_t<L, R> lt(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R>
-internal::lesser_or_equal_t<L, R> lesser_or_equal(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class L, class R> internal::lesser_or_equal_t<L, R> le(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <class C> internal::where_t<C> where(C c) {
-  return {std::move(c)};
-}
-
-/**
- * ORDER BY column
- * Example: storage.select(&User::name, order_by(&User::id))
- */
-template <class O> internal::order_by_t<O> order_by(O o) {
-  return {std::move(o)};
-}
-
-/**
- * ORDER BY column1, column2
- * Example:
- * storage.get_all<Singer>(multi_order_by(order_by(&Singer::name).asc(),
- * order_by(&Singer::gender).desc())
- */
-template <class... Args>
-internal::multi_order_by_t<Args...> multi_order_by(Args &&... args) {
-  return {std::make_tuple(std::forward<Args>(args)...)};
-}
-
-/**
- * ORDER BY column1, column2
- * Difference from `multi_order_by` is that `dynamic_order_by` can be changed at
- * runtime using `push_back` member function Example: auto orderBy =
- * dynamic_order_by(storage); if(someCondition) { orderBy.push_back(&User::id);
- *  } else {
- *      orderBy.push_back(&User::name);
- *      orderBy.push_back(&User::birthDate);
- *  }
- */
-template <class S>
-internal::dynamic_order_by_t<
-    internal::serializator_context<typename S::impl_type>>
-dynamic_order_by(const S &storage) {
-  internal::serializator_context_builder<S> builder(storage);
-  return builder();
-}
-
-/**
- *  GROUP BY column.
- *  Example: storage.get_all<Employee>(group_by(&Employee::name))
- */
-template <class... Args>
-internal::group_by_t<Args...> group_by(Args &&... args) {
-  return {std::make_tuple(std::forward<Args>(args)...)};
-}
-
-/**
- *  X BETWEEN Y AND Z
- *  Example: storage.select(between(&User::id, 10, 20))
- */
-template <class A, class T>
-internal::between_t<A, T> between(A expr, T b1, T b2) {
-  return {std::move(expr), std::move(b1), std::move(b2)};
-}
-
-/**
- *  X LIKE Y
- *  Example: storage.select(like(&User::name, "T%"))
- */
-template <class A, class T> internal::like_t<A, T, void> like(A a, T t) {
-  return {std::move(a), std::move(t), {}};
-}
-
-/**
- *  X GLOB Y
- *  Example: storage.select(glob(&User::name, "*S"))
- */
-template <class A, class T> internal::glob_t<A, T> glob(A a, T t) {
-  return {std::move(a), std::move(t)};
-}
-
-/**
- *  X LIKE Y ESCAPE Z
- *  Example: storage.select(like(&User::name, "T%", "%"))
- */
-template <class A, class T, class E>
-internal::like_t<A, T, E> like(A a, T t, E e) {
-  return {std::move(a), std::move(t), {std::move(e)}};
-}
-
-/**
- *  EXISTS(condition).
- *  Example: storage.select(columns(&Agent::code, &Agent::name,
- &Agent::workingArea, &Agent::comission),
-     where(exists(select(asterisk<Customer>(),
-     where(is_equal(&Customer::grade, 3) and
-     is_equal(&Agent::code, &Customer::agentCode))))),
-     order_by(&Agent::comission));
- */
-template <class T> internal::exists_t<T> exists(T t) {
-  return {std::move(t)};
-}
-
-/**
- *  HAVING(expression).
- *  Example: storage.get_all<Employee>(group_by(&Employee::name),
- * having(greater_than(count(&Employee::name), 2)));
- */
-template <class T> internal::having_t<T> having(T t) {
-  return {std::move(t)};
-}
-
-/**
- *  CAST(X AS type).
- *  Example: cast<std::string>(&User::id)
- */
-template <class T, class E> internal::cast_t<T, E> cast(E e) {
-  return {std::move(e)};
-}
-} // namespace sqlite_orm
-#pragma once
-
-#include <sstream>     //  std::stringstream
-#include <string>      //  std::string
-#include <type_traits> //  std::enable_if, std::is_base_of, std::is_member_pointer
-
-namespace sqlite_orm {
-
-/**
- *  This is base class for every class which is used as a custom table alias.
- *  For more information please look through self_join.cpp example
- */
-struct alias_tag {};
-
-namespace internal {
-
-/**
- *  This is a common built-in class used for custom single character table
- * aliases. Also you can use language aliases `alias_a`, `alias_b` etc. instead
- */
-template <class T, char A> struct table_alias : alias_tag {
-  using type = T;
-
-  static char get() {
-    return A;
-  }
-};
-
-/**
- *  Column expression with table alias attached like 'C.ID'. This is not a
- * column alias
- */
-template <class T, class C> struct alias_column_t {
-  using alias_type = T;
-  using column_type = C;
-
-  column_type column;
-
-  alias_column_t(){};
-
-  alias_column_t(column_type column_) : column(column_) {
-  }
-};
-
-template <class T, class SFINAE = void> struct alias_extractor;
-
-template <class T>
-struct alias_extractor<
-    T,
-    typename std::enable_if<std::is_base_of<alias_tag, T>::value>::type> {
-  static std::string get() {
-    std::stringstream ss;
-    ss << T::get();
-    return ss.str();
-  }
-};
-
-template <class T>
-struct alias_extractor<
-    T,
-    typename std::enable_if<!std::is_base_of<alias_tag, T>::value>::type> {
-  static std::string get() {
-    return {};
-  }
-};
-
-template <class T, class E> struct as_t {
-  using alias_type = T;
-  using expression_type = E;
-
-  expression_type expression;
-};
-
-template <class T> struct alias_holder { using type = T; };
-} // namespace internal
-
-/**
- *  @return column with table alias attached. Place it instead of a column
- * statement in case you need to specify a column with table alias prefix like
- * 'a.column'. For more information please look through self_join.cpp example
- */
-template <class T, class C> internal::alias_column_t<T, C> alias_column(C c) {
-  static_assert(
-      std::is_member_pointer<C>::value,
-      "alias_column argument must be a member pointer mapped to a storage");
-  return {c};
-}
-
-template <class T, class E> internal::as_t<T, E> as(E expression) {
-  return {std::move(expression)};
-}
-
-template <class T> internal::alias_holder<T> get() {
-  return {};
-}
-
-template <class T> using alias_a = internal::table_alias<T, 'a'>;
-template <class T> using alias_b = internal::table_alias<T, 'b'>;
-template <class T> using alias_c = internal::table_alias<T, 'c'>;
-template <class T> using alias_d = internal::table_alias<T, 'd'>;
-template <class T> using alias_e = internal::table_alias<T, 'e'>;
-template <class T> using alias_f = internal::table_alias<T, 'f'>;
-template <class T> using alias_g = internal::table_alias<T, 'g'>;
-template <class T> using alias_h = internal::table_alias<T, 'h'>;
-template <class T> using alias_i = internal::table_alias<T, 'i'>;
-template <class T> using alias_j = internal::table_alias<T, 'j'>;
-template <class T> using alias_k = internal::table_alias<T, 'k'>;
-template <class T> using alias_l = internal::table_alias<T, 'l'>;
-template <class T> using alias_m = internal::table_alias<T, 'm'>;
-template <class T> using alias_n = internal::table_alias<T, 'n'>;
-template <class T> using alias_o = internal::table_alias<T, 'o'>;
-template <class T> using alias_p = internal::table_alias<T, 'p'>;
-template <class T> using alias_q = internal::table_alias<T, 'q'>;
-template <class T> using alias_r = internal::table_alias<T, 'r'>;
-template <class T> using alias_s = internal::table_alias<T, 's'>;
-template <class T> using alias_t = internal::table_alias<T, 't'>;
-template <class T> using alias_u = internal::table_alias<T, 'u'>;
-template <class T> using alias_v = internal::table_alias<T, 'v'>;
-template <class T> using alias_w = internal::table_alias<T, 'w'>;
-template <class T> using alias_x = internal::table_alias<T, 'x'>;
-template <class T> using alias_y = internal::table_alias<T, 'y'>;
-template <class T> using alias_z = internal::table_alias<T, 'z'>;
-} // namespace sqlite_orm
-#pragma once
-
-// #include "conditions.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class... Args> struct join_iterator {
-
-  template <class L> void operator()(const L &) {
-    //..
-  }
-};
-
-template <> struct join_iterator<> {
-
-  template <class L> void operator()(const L &) {
-    //..
-  }
-};
-
-template <class H, class... Tail>
-struct join_iterator<H, Tail...> : public join_iterator<Tail...> {
-  using super = join_iterator<Tail...>;
-
-  template <class L> void operator()(const L &l) {
-    this->super::operator()(l);
-  }
-};
-
-template <class T, class... Tail>
-struct join_iterator<cross_join_t<T>, Tail...> : public join_iterator<Tail...> {
-  using super = join_iterator<Tail...>;
-  using join_type = cross_join_t<T>;
-
-  template <class L> void operator()(const L &l) {
-    l(*this);
-    this->super::operator()(l);
-  }
-};
-
-template <class T, class... Tail>
-struct join_iterator<natural_join_t<T>, Tail...>
-    : public join_iterator<Tail...> {
-  using super = join_iterator<Tail...>;
-  using join_type = natural_join_t<T>;
-
-  template <class L> void operator()(const L &l) {
-    l(*this);
-    this->super::operator()(l);
-  }
-};
-
-template <class T, class O, class... Tail>
-struct join_iterator<left_join_t<T, O>, Tail...>
-    : public join_iterator<Tail...> {
-  using super = join_iterator<Tail...>;
-  using join_type = left_join_t<T, O>;
-
-  template <class L> void operator()(const L &l) {
-    l(*this);
-    this->super::operator()(l);
-  }
-};
-
-template <class T, class O, class... Tail>
-struct join_iterator<join_t<T, O>, Tail...> : public join_iterator<Tail...> {
-  using super = join_iterator<Tail...>;
-  using join_type = join_t<T, O>;
-
-  template <class L> void operator()(const L &l) {
-    l(*this);
-    this->super::operator()(l);
-  }
-};
-
-template <class T, class O, class... Tail>
-struct join_iterator<left_outer_join_t<T, O>, Tail...>
-    : public join_iterator<Tail...> {
-  using super = join_iterator<Tail...>;
-  using join_type = left_outer_join_t<T, O>;
-
-  template <class L> void operator()(const L &l) {
-    l(*this);
-    this->super::operator()(l);
-  }
-};
-
-template <class T, class O, class... Tail>
-struct join_iterator<inner_join_t<T, O>, Tail...>
-    : public join_iterator<Tail...> {
-  using super = join_iterator<Tail...>;
-  using join_type = inner_join_t<T, O>;
-
-  template <class L> void operator()(const L &l) {
-    l(*this);
-    this->super::operator()(l);
-  }
-};
-} // namespace internal
-} // namespace sqlite_orm
-#pragma once
-
-#include <memory>      //  std::unique_ptr
-#include <string>      //  std::string
-#include <tuple>       //  std::make_tuple, std::tuple_size
-#include <type_traits> //  std::forward, std::is_base_of, std::enable_if
-#include <vector>      //  std::vector
-
-// #include "conditions.h"
-
-// #include "operators.h"
-
-// #include "is_base_of_template.h"
-
-#include <type_traits> //  std::true_type, std::false_type, std::declval
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/*
- * This is because of bug in MSVC, for more information, please visit
- * https://stackoverflow.com/questions/34672441/stdis-base-of-for-template-classes/34672753#34672753
- */
-#if defined(_MSC_VER)
-template <template <typename...> class Base, typename Derived>
-struct is_base_of_template_impl {
-  template <typename... Ts>
-  static constexpr std::true_type test(const Base<Ts...> *);
-
-  static constexpr std::false_type test(...);
-
-  using type = decltype(test(std::declval<Derived *>()));
-};
-
-template <typename Derived, template <typename...> class Base>
-using is_base_of_template =
-    typename is_base_of_template_impl<Base, Derived>::type;
-
-#else
-template <template <typename...> class C, typename... Ts>
-std::true_type is_base_of_template_impl(const C<Ts...> *);
-
-template <template <typename...> class C>
-std::false_type is_base_of_template_impl(...);
-
-template <typename T, template <typename...> class C>
-using is_base_of_template =
-    decltype(is_base_of_template_impl<C>(std::declval<T *>()));
-#endif
-} // namespace internal
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class T> struct unique_ptr_result_of {};
-
-/**
- *  Base class for operator overloading
- *  R - return type
- *  S - class with operator std::string
- *  Args - function arguments types
- */
-template <class R, class S, class... Args>
-struct core_function_t : S, internal::arithmetic_t {
-  using return_type = R;
-  using string_type = S;
-  using args_type = std::tuple<Args...>;
-
-  static constexpr const size_t args_size = std::tuple_size<args_type>::value;
-
-  args_type args;
-
-  core_function_t(args_type &&args_) : args(std::move(args_)) {
-  }
-};
-
-struct length_string {
-  operator std::string() const {
-    return "LENGTH";
-  }
-};
-
-struct abs_string {
-  operator std::string() const {
-    return "ABS";
-  }
-};
-
-struct lower_string {
-  operator std::string() const {
-    return "LOWER";
-  }
-};
-
-struct upper_string {
-  operator std::string() const {
-    return "UPPER";
-  }
-};
-
-struct changes_string {
-  operator std::string() const {
-    return "CHANGES";
-  }
-};
-
-struct trim_string {
-  operator std::string() const {
-    return "TRIM";
-  }
-};
-
-struct ltrim_string {
-  operator std::string() const {
-    return "LTRIM";
-  }
-};
-
-struct rtrim_string {
-  operator std::string() const {
-    return "RTRIM";
-  }
-};
-
-struct hex_string {
-  operator std::string() const {
-    return "HEX";
-  }
-};
-
-struct quote_string {
-  operator std::string() const {
-    return "QUOTE";
-  }
-};
-
-struct randomblob_string {
-  operator std::string() const {
-    return "RANDOMBLOB";
-  }
-};
-
-struct instr_string {
-  operator std::string() const {
-    return "INSTR";
-  }
-};
-
-struct replace_string {
-  operator std::string() const {
-    return "REPLACE";
-  }
-};
-
-struct round_string {
-  operator std::string() const {
-    return "ROUND";
-  }
-};
-
-#if SQLITE_VERSION_NUMBER >= 3007016
-
-struct char_string {
-  operator std::string() const {
-    return "CHAR";
-  }
-};
-
-struct random_string {
-  operator std::string() const {
-    return "RANDOM";
-  }
-};
-
-#endif
-
-struct coalesce_string {
-  operator std::string() const {
-    return "COALESCE";
-  }
-};
-
-struct date_string {
-  operator std::string() const {
-    return "DATE";
-  }
-};
-
-struct time_string {
-  operator std::string() const {
-    return "TIME";
-  }
-};
-
-struct datetime_string {
-  operator std::string() const {
-    return "DATETIME";
-  }
-};
-
-struct julianday_string {
-  operator std::string() const {
-    return "JULIANDAY";
-  }
-};
-
-struct strftime_string {
-  operator std::string() const {
-    return "STRFTIME";
-  }
-};
-
-struct zeroblob_string {
-  operator std::string() const {
-    return "ZEROBLOB";
-  }
-};
-
-struct substr_string {
-  operator std::string() const {
-    return "SUBSTR";
-  }
-};
-#ifdef SQLITE_SOUNDEX
-struct soundex_string {
-  operator std::string() const {
-    return "SOUNDEX";
-  }
-};
-#endif
-struct total_string {
-  operator std::string() const {
-    return "TOTAL";
-  }
-};
-
-struct sum_string {
-  operator std::string() const {
-    return "SUM";
-  }
-};
-
-struct count_string {
-  operator std::string() const {
-    return "COUNT";
-  }
-};
-
-/**
- *  T is use to specify type explicitly for queries like
- *  SELECT COUNT(*) FROM table_name;
- *  T can be omitted with void.
- */
-template <class T> struct count_asterisk_t : count_string { using type = T; };
-
-/**
- *  The same thing as count<T>() but without T arg.
- *  Is used in cases like this:
- *    SELECT cust_code, cust_name, cust_city, grade
- *    FROM customer
- *    WHERE grade=2 AND EXISTS
- *        (SELECT COUNT(*)
- *        FROM customer
- *        WHERE grade=2
- *        GROUP BY grade
- *        HAVING COUNT(*)>2);
- *  `c++`
- *  auto rows =
- *      storage.select(columns(&Customer::code, &Customer::name,
- * &Customer::city, &Customer::grade), where(is_equal(&Customer::grade, 2) and
- * exists(select(count<Customer>(), where(is_equal(&Customer::grade, 2)),
- *          group_by(&Customer::grade),
- *          having(greater_than(count(), 2))))));
- */
-struct count_asterisk_without_type : count_string {};
-
-struct avg_string {
-  operator std::string() const {
-    return "AVG";
-  }
-};
-
-struct max_string {
-  operator std::string() const {
-    return "MAX";
-  }
-};
-
-struct min_string {
-  operator std::string() const {
-    return "MIN";
-  }
-};
-
-struct group_concat_string {
-  operator std::string() const {
-    return "GROUP_CONCAT";
-  }
-};
-
-} // namespace internal
-
-/**
- *  Cute operators for core functions
- */
-
-template <
-    class F,
-    class R,
-    typename = typename std::enable_if<
-        internal::is_base_of_template<F, internal::core_function_t>::value>::
-        type>
-internal::lesser_than_t<F, R> operator<(F f, R r) {
-  return {std::move(f), std::move(r)};
-}
-
-template <
-    class F,
-    class R,
-    typename = typename std::enable_if<
-        internal::is_base_of_template<F, internal::core_function_t>::value>::
-        type>
-internal::lesser_or_equal_t<F, R> operator<=(F f, R r) {
-  return {std::move(f), std::move(r)};
-}
-
-template <
-    class F,
-    class R,
-    typename = typename std::enable_if<
-        internal::is_base_of_template<F, internal::core_function_t>::value>::
-        type>
-internal::greater_than_t<F, R> operator>(F f, R r) {
-  return {std::move(f), std::move(r)};
-}
-
-template <
-    class F,
-    class R,
-    typename = typename std::enable_if<
-        internal::is_base_of_template<F, internal::core_function_t>::value>::
-        type>
-internal::greater_or_equal_t<F, R> operator>=(F f, R r) {
-  return {std::move(f), std::move(r)};
-}
-
-template <
-    class F,
-    class R,
-    typename = typename std::enable_if<
-        internal::is_base_of_template<F, internal::core_function_t>::value>::
-        type>
-internal::is_equal_t<F, R> operator==(F f, R r) {
-  return {std::move(f), std::move(r)};
-}
-
-template <
-    class F,
-    class R,
-    typename = typename std::enable_if<
-        internal::is_base_of_template<F, internal::core_function_t>::value>::
-        type>
-internal::is_not_equal_t<F, R> operator!=(F f, R r) {
-  return {std::move(f), std::move(r)};
-}
-
-/**
- *  LENGTH(x) function https://sqlite.org/lang_corefunc.html#length
- */
-template <class T>
-internal::core_function_t<int, internal::length_string, T> length(T t) {
-  std::tuple<T> args{std::forward<T>(t)};
-  return {move(args)};
-}
-
-/**
- *  ABS(x) function https://sqlite.org/lang_corefunc.html#abs
- */
-template <class T>
-internal::core_function_t<std::unique_ptr<double>, internal::abs_string, T>
-abs(T t) {
-  std::tuple<T> args{std::forward<T>(t)};
-  return {move(args)};
-}
-
-/**
- *  LOWER(x) function https://sqlite.org/lang_corefunc.html#lower
- */
-template <class T>
-internal::core_function_t<std::string, internal::lower_string, T> lower(T t) {
-  std::tuple<T> args{std::forward<T>(t)};
-  return {move(args)};
-}
-
-/**
- *  UPPER(x) function https://sqlite.org/lang_corefunc.html#upper
- */
-template <class T>
-internal::core_function_t<std::string, internal::upper_string, T> upper(T t) {
-  std::tuple<T> args{std::forward<T>(t)};
-  return {move(args)};
-}
-
-/**
- *  CHANGES() function https://sqlite.org/lang_corefunc.html#changes
- */
-inline internal::core_function_t<int, internal::changes_string> changes() {
-  return {{}};
-}
-
-/**
- *  TRIM(X) function https://sqlite.org/lang_corefunc.html#trim
- */
-template <class T>
-internal::core_function_t<std::string, internal::trim_string, T> trim(T t) {
-  std::tuple<T> args{std::forward<T>(t)};
-  return {move(args)};
-}
-
-/**
- *  TRIM(X,Y) function https://sqlite.org/lang_corefunc.html#trim
- */
-template <class X, class Y>
-internal::core_function_t<std::string, internal::trim_string, X, Y>
-trim(X x, Y y) {
-  std::tuple<X, Y> args{std::forward<X>(x), std::forward<Y>(y)};
-  return {move(args)};
-}
-
-/**
- *  LTRIM(X) function https://sqlite.org/lang_corefunc.html#ltrim
- */
-template <class X>
-internal::core_function_t<std::string, internal::ltrim_string, X> ltrim(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  LTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#ltrim
- */
-template <class X, class Y>
-internal::core_function_t<std::string, internal::ltrim_string, X, Y>
-ltrim(X x, Y y) {
-  std::tuple<X, Y> args{std::forward<X>(x), std::forward<Y>(y)};
-  return {move(args)};
-}
-
-/**
- *  RTRIM(X) function https://sqlite.org/lang_corefunc.html#rtrim
- */
-template <class X>
-internal::core_function_t<std::string, internal::rtrim_string, X> rtrim(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  RTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#rtrim
- */
-template <class X, class Y>
-internal::core_function_t<std::string, internal::rtrim_string, X, Y>
-rtrim(X x, Y y) {
-  std::tuple<X, Y> args{std::forward<X>(x), std::forward<Y>(y)};
-  return {move(args)};
-}
-
-/**
- *  HEX(X) function https://sqlite.org/lang_corefunc.html#hex
- */
-template <class X>
-internal::core_function_t<std::string, internal::hex_string, X> hex(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  QUOTE(X) function https://sqlite.org/lang_corefunc.html#quote
- */
-template <class X>
-internal::core_function_t<std::string, internal::quote_string, X> quote(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  RANDOMBLOB(X) function https://sqlite.org/lang_corefunc.html#randomblob
- */
-template <class X>
-internal::core_function_t<std::vector<char>, internal::randomblob_string, X>
-randomblob(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  INSTR(X) function https://sqlite.org/lang_corefunc.html#instr
- */
-template <class X, class Y>
-internal::core_function_t<int, internal::instr_string, X, Y> instr(X x, Y y) {
-  std::tuple<X, Y> args{std::forward<X>(x), std::forward<Y>(y)};
-  return {move(args)};
-}
-
-/**
- *  REPLACE(X) function https://sqlite.org/lang_corefunc.html#replace
- */
-template <class X, class Y, class Z>
-internal::core_function_t<std::string, internal::replace_string, X, Y, Z>
-replace(X x, Y y, Z z) {
-  std::tuple<X, Y, Z> args{
-      std::forward<X>(x), std::forward<Y>(y), std::forward<Z>(z)};
-  return {move(args)};
-}
-
-/**
- *  ROUND(X) function https://sqlite.org/lang_corefunc.html#round
- */
-template <class X>
-internal::core_function_t<double, internal::round_string, X> round(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  ROUND(X, Y) function https://sqlite.org/lang_corefunc.html#round
- */
-template <class X, class Y>
-internal::core_function_t<double, internal::round_string, X, Y>
-round(X x, Y y) {
-  std::tuple<X, Y> args{std::forward<X>(x), std::forward<Y>(y)};
-  return {move(args)};
-}
-
-#if SQLITE_VERSION_NUMBER >= 3007016
-
-/**
- *  CHAR(X1,X2,...,XN) function https://sqlite.org/lang_corefunc.html#char
- */
-template <class... Args>
-internal::core_function_t<std::string, internal::char_string, Args...>
-char_(Args... args) {
-  return {std::make_tuple(std::forward<Args>(args)...)};
-}
-
-/**
- *  RANDOM() function https://www.sqlite.org/lang_corefunc.html#random
- */
-inline internal::core_function_t<int, internal::random_string> random() {
-  return {{}};
-}
-
-#endif
-
-/**
- *  COALESCE(X,Y,...) function
- * https://www.sqlite.org/lang_corefunc.html#coalesce
- */
-template <class R, class... Args>
-internal::core_function_t<R, internal::coalesce_string, Args...>
-coalesce(Args... args) {
-  return {std::make_tuple(std::forward<Args>(args)...)};
-}
-
-/**
- *  DATE(timestring, modifier, modifier, ...) function
- * https://www.sqlite.org/lang_datefunc.html
- */
-template <class... Args>
-internal::core_function_t<std::string, internal::date_string, Args...>
-date(Args... args) {
-  std::tuple<Args...> t{std::forward<Args>(args)...};
-  return {move(t)};
-}
-
-/**
- *  TIME(timestring, modifier, modifier, ...) function
- * https://www.sqlite.org/lang_datefunc.html
- */
-template <class... Args>
-internal::core_function_t<std::string, internal::time_string, Args...>
-time(Args... args) {
-  std::tuple<Args...> t{std::forward<Args>(args)...};
-  return {move(t)};
-}
-
-/**
- *  DATETIME(timestring, modifier, modifier, ...) function
- * https://www.sqlite.org/lang_datefunc.html
- */
-template <class... Args>
-internal::core_function_t<std::string, internal::datetime_string, Args...>
-datetime(Args... args) {
-  std::tuple<Args...> t{std::forward<Args>(args)...};
-  return {move(t)};
-}
-
-/**
- *  JULIANDAY(timestring, modifier, modifier, ...) function
- * https://www.sqlite.org/lang_datefunc.html
- */
-template <class... Args>
-internal::core_function_t<double, internal::julianday_string, Args...>
-julianday(Args... args) {
-  std::tuple<Args...> t{std::forward<Args>(args)...};
-  return {move(t)};
-}
-
-/**
- *  STRFTIME(timestring, modifier, modifier, ...) function
- * https://www.sqlite.org/lang_datefunc.html
- */
-template <class... Args>
-internal::core_function_t<std::string, internal::strftime_string, Args...>
-strftime(Args... args) {
-  std::tuple<Args...> t{std::forward<Args>(args)...};
-  return {move(t)};
-}
-
-/**
- *  ZEROBLOB(N) function https://www.sqlite.org/lang_corefunc.html#zeroblob
- */
-template <class N>
-internal::core_function_t<std::vector<char>, internal::zeroblob_string, N>
-zeroblob(N n) {
-  std::tuple<N> args{std::forward<N>(n)};
-  return {move(args)};
-}
-
-/**
- *  SUBSTR(X,Y) function https://www.sqlite.org/lang_corefunc.html#substr
- */
-template <class X, class Y>
-internal::core_function_t<std::string, internal::substr_string, X, Y>
-substr(X x, Y y) {
-  std::tuple<X, Y> args{std::forward<X>(x), std::forward<Y>(y)};
-  return {move(args)};
-}
-
-/**
- *  SUBSTR(X,Y,Z) function https://www.sqlite.org/lang_corefunc.html#substr
- */
-template <class X, class Y, class Z>
-internal::core_function_t<std::string, internal::substr_string, X, Y, Z>
-substr(X x, Y y, Z z) {
-  std::tuple<X, Y, Z> args{
-      std::forward<X>(x), std::forward<Y>(y), std::forward<Z>(z)};
-  return {move(args)};
-}
-
-#ifdef SQLITE_SOUNDEX
-/**
- *  SOUNDEX(X) function https://www.sqlite.org/lang_corefunc.html#soundex
- */
-template <class X>
-internal::core_function_t<std::string, internal::soundex_string, X>
-soundex(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-#endif
-
-/**
- *  TOTAL(X) aggregate function.
- */
-template <class X>
-internal::core_function_t<double, internal::total_string, X> total(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  SUM(X) aggregate function.
- */
-template <class X>
-internal::core_function_t<std::unique_ptr<double>, internal::sum_string, X>
-sum(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  COUNT(X) aggregate function.
- */
-template <class X>
-internal::core_function_t<int, internal::count_string, X> count(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  COUNT(*) without FROM function.
- */
-inline internal::count_asterisk_without_type count() {
-  return {};
-}
-
-/**
- *  COUNT(*) with FROM function. Specified type T will be serializeed as
- *  a from argument.
- */
-template <class T> internal::count_asterisk_t<T> count() {
-  return {};
-}
-
-/**
- *  AVG(X) aggregate function.
- */
-template <class X>
-internal::core_function_t<double, internal::avg_string, X> avg(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  MAX(X) aggregate function.
- */
-template <class X>
-internal::
-    core_function_t<internal::unique_ptr_result_of<X>, internal::max_string, X>
-    max(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  MIN(X) aggregate function.
- */
-template <class X>
-internal::
-    core_function_t<internal::unique_ptr_result_of<X>, internal::min_string, X>
-    min(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  GROUP_CONCAT(X) aggregate function.
- */
-template <class X>
-internal::core_function_t<std::string, internal::group_concat_string, X>
-group_concat(X x) {
-  std::tuple<X> args{std::forward<X>(x)};
-  return {move(args)};
-}
-
-/**
- *  GROUP_CONCAT(X, Y) aggregate function.
- */
-template <class X, class Y>
-internal::core_function_t<std::string, internal::group_concat_string, X, Y>
-group_concat(X x, Y y) {
-  std::tuple<X, Y> args{std::forward<X>(x), std::forward<Y>(y)};
-  return {move(args)};
-}
-
-template <
-    class L,
-    class R,
-    typename = typename std::enable_if<
-        (std::is_base_of<internal::arithmetic_t, L>::value +
-             std::is_base_of<internal::arithmetic_t, R>::value >
-         0)>::type>
-internal::add_t<L, R> operator+(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <
-    class L,
-    class R,
-    typename = typename std::enable_if<
-        (std::is_base_of<internal::arithmetic_t, L>::value +
-             std::is_base_of<internal::arithmetic_t, R>::value >
-         0)>::type>
-internal::sub_t<L, R> operator-(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <
-    class L,
-    class R,
-    typename = typename std::enable_if<
-        (std::is_base_of<internal::arithmetic_t, L>::value +
-             std::is_base_of<internal::arithmetic_t, R>::value >
-         0)>::type>
-internal::mul_t<L, R> operator*(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <
-    class L,
-    class R,
-    typename = typename std::enable_if<
-        (std::is_base_of<internal::arithmetic_t, L>::value +
-             std::is_base_of<internal::arithmetic_t, R>::value >
-         0)>::type>
-internal::div_t<L, R> operator/(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-
-template <
-    class L,
-    class R,
-    typename = typename std::enable_if<
-        (std::is_base_of<internal::arithmetic_t, L>::value +
-             std::is_base_of<internal::arithmetic_t, R>::value >
-         0)>::type>
-internal::mod_t<L, R> operator%(L l, R r) {
-  return {std::move(l), std::move(r)};
-}
-} // namespace sqlite_orm
-#pragma once
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- *  Cute class used to compare setters/getters and member pointers with each
- * other.
- */
-template <class L, class R> struct typed_comparator {
-  bool operator()(const L &, const R &) const {
-    return false;
-  }
-};
-
-template <class O> struct typed_comparator<O, O> {
-  bool operator()(const O &lhs, const O &rhs) const {
-    return lhs == rhs;
-  }
-};
-
-template <class L, class R> bool compare_any(const L &lhs, const R &rhs) {
-  return typed_comparator<L, R>()(lhs, rhs);
-}
-} // namespace internal
-} // namespace sqlite_orm
-#pragma once
-
-#include <string>  //  std::string
-#include <tuple>   //  std::tuple, std::get, std::tuple_size
-#include <utility> //  std::declval
-
-// #include "is_base_of_template.h"
-
-// #include "tuple_helper.h"
-
-// #include "optional_container.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- *  DISCTINCT generic container.
- */
-template <class T> struct distinct_t {
-  T t;
-
-  operator std::string() const {
-    return "DISTINCT";
-  }
-};
-
-/**
- *  ALL generic container.
- */
-template <class T> struct all_t {
-  T t;
-
-  operator std::string() const {
-    return "ALL";
-  }
-};
-
-template <class... Args> struct columns_t {
-  using columns_type = std::tuple<Args...>;
-
-  columns_type columns;
-  bool distinct = false;
-
-  static constexpr const int count = std::tuple_size<columns_type>::value;
-};
-
-struct set_string {
-  operator std::string() const {
-    return "SET";
-  }
-};
-
-template <class... Args> struct set_t : set_string {
-  using assigns_type = std::tuple<Args...>;
-
-  assigns_type assigns;
-
-  set_t(assigns_type assigns_) : assigns(move(assigns_)) {
-  }
-};
-
-/**
- *  This class is used to store explicit mapped type T and its column descriptor
- * (member pointer/getter/setter). Is useful when mapped type is derived from
- * other type and base class has members mapped to a storage.
- */
-template <class T, class F> struct column_pointer {
-  using type = T;
-  using field_type = F;
-
-  field_type field;
-};
-
-/**
- *  Subselect object type.
- */
-template <class T, class... Args> struct select_t {
-  using return_type = T;
-  using conditions_type = std::tuple<Args...>;
-
-  return_type col;
-  conditions_type conditions;
-  bool highest_level = false;
-};
-
-/**
- *  Base for UNION, UNION ALL, EXCEPT and INTERSECT
- */
-template <class L, class R> struct compound_operator {
-  using left_type = L;
-  using right_type = R;
-
-  left_type left;
-  right_type right;
-
-  compound_operator(left_type l, right_type r)
-      : left(std::move(l)), right(std::move(r)) {
-    this->left.highest_level = true;
-    this->right.highest_level = true;
-  }
-};
-
-struct union_base {
-  bool all = false;
-
-  operator std::string() const {
-    if (!this->all) {
-      return "UNION";
-    } else {
-      return "UNION ALL";
-    }
-  }
-};
-
-/**
- *  UNION object type.
- */
-template <class L, class R>
-struct union_t : public compound_operator<L, R>, union_base {
-  using left_type = typename compound_operator<L, R>::left_type;
-  using right_type = typename compound_operator<L, R>::right_type;
-
-  union_t(left_type l, right_type r, decltype(all) all_)
-      : compound_operator<L, R>(std::move(l), std::move(r)), union_base{all_} {
-  }
-
-  union_t(left_type l, right_type r)
-      : union_t(std::move(l), std::move(r), false) {
-  }
-};
-
-/**
- *  EXCEPT object type.
- */
-template <class L, class R> struct except_t : public compound_operator<L, R> {
-  using super = compound_operator<L, R>;
-  using left_type = typename super::left_type;
-  using right_type = typename super::right_type;
-
-  using super::super;
-
-  operator std::string() const {
-    return "EXCEPT";
-  }
-};
-
-/**
- *  INTERSECT object type.
- */
-template <class L, class R>
-struct intersect_t : public compound_operator<L, R> {
-  using super = compound_operator<L, R>;
-  using left_type = typename super::left_type;
-  using right_type = typename super::right_type;
-
-  using super::super;
-
-  operator std::string() const {
-    return "INTERSECT";
-  }
-};
-
-/**
- *  Generic way to get DISTINCT value from any type.
- */
-template <class T> bool get_distinct(const T &) {
-  return false;
-}
-
-template <class... Args> bool get_distinct(const columns_t<Args...> &cols) {
-  return cols.distinct;
-}
-
-template <class T> struct asterisk_t { using type = T; };
-
-template <class T> struct object_t { using type = T; };
-
-template <class T> struct then_t {
-  using expression_type = T;
-
-  expression_type expression;
-};
-
-template <class R, class T, class E, class... Args> struct simple_case_t {
-  using return_type = R;
-  using case_expression_type = T;
-  using args_type = std::tuple<Args...>;
-  using else_expression_type = E;
-
-  optional_container<case_expression_type> case_expression;
-  args_type args;
-  optional_container<else_expression_type> else_expression;
-};
-
-/**
- *  T is a case expression type
- *  E is else type (void is ELSE is omitted)
- *  Args... is a pack of WHEN expressions
- */
-template <class R, class T, class E, class... Args> struct simple_case_builder {
-  using return_type = R;
-  using case_expression_type = T;
-  using args_type = std::tuple<Args...>;
-  using else_expression_type = E;
-
-  optional_container<case_expression_type> case_expression;
-  args_type args;
-  optional_container<else_expression_type> else_expression;
-
-  template <class W, class Th>
-  simple_case_builder<R, T, E, Args..., std::pair<W, Th>>
-  when(W w, then_t<Th> t) {
-    using result_args_type = std::tuple<Args..., std::pair<W, Th>>;
-    std::pair<W, Th> newPair{std::move(w), std::move(t.expression)};
-    result_args_type result_args = std::tuple_cat(
-        std::move(this->args), std::move(std::make_tuple(newPair)));
-    std::get<std::tuple_size<result_args_type>::value - 1>(result_args) =
-        std::move(newPair);
-    return {
-        std::move(this->case_expression),
-        std::move(result_args),
-        std::move(this->else_expression)};
-  }
-
-  simple_case_t<R, T, E, Args...> end() {
-    return {
-        std::move(this->case_expression),
-        std::move(args),
-        std::move(this->else_expression)};
-  }
-
-  template <class El> simple_case_builder<R, T, El, Args...> else_(El el) {
-    return {
-        {std::move(this->case_expression)}, std::move(args), {std::move(el)}};
-  }
-};
-
-template <class T> void validate_conditions() {
-  static_assert(
-      count_tuple<T, is_where>::value <= 1,
-      "a single query cannot contain > 1 WHERE blocks");
-  static_assert(
-      count_tuple<T, is_group_by>::value <= 1,
-      "a single query cannot contain > 1 GROUP BY blocks");
-  static_assert(
-      count_tuple<T, is_order_by>::value <= 1,
-      "a single query cannot contain > 1 ORDER BY blocks");
-  static_assert(
-      count_tuple<T, is_limit>::value <= 1,
-      "a single query cannot contain > 1 LIMIT blocks");
-}
-} // namespace internal
-
-template <class T> internal::then_t<T> then(T t) {
-  return {std::move(t)};
-}
-
-template <class R, class T>
-internal::simple_case_builder<R, T, void> case_(T t) {
-  return {{std::move(t)}};
-}
-
-template <class R> internal::simple_case_builder<R, void, void> case_() {
-  return {};
-}
-
-template <class T> internal::distinct_t<T> distinct(T t) {
-  return {std::move(t)};
-}
-
-template <class T> internal::all_t<T> all(T t) {
-  return {std::move(t)};
-}
-
-template <class... Args>
-internal::columns_t<Args...> distinct(internal::columns_t<Args...> cols) {
-  cols.distinct = true;
-  return cols;
-}
-
-/**
- *  SET keyword used in UPDATE ... SET queries.
- *  Args must have `assign_t` type. E.g. set(assign(&User::id, 5)) or
- * set(c(&User::id) = 5)
- */
-template <class... Args> internal::set_t<Args...> set(Args... args) {
-  using arg_tuple = std::tuple<Args...>;
-  static_assert(
-      std::tuple_size<arg_tuple>::value ==
-          internal::count_tuple<arg_tuple, internal::is_assign_t>::value,
-      "set function accepts assign operators only");
-  return {std::make_tuple(std::forward<Args>(args)...)};
-}
-
-template <class... Args> internal::columns_t<Args...> columns(Args... args) {
-  return {std::make_tuple<Args...>(std::forward<Args>(args)...)};
-}
-
-/**
- *  Use it like this:
- *  struct MyType : BaseType { ... };
- *  storage.select(column<MyType>(&BaseType::id));
- */
-template <class T, class F> internal::column_pointer<T, F> column(F f) {
-  return {std::move(f)};
-}
-
-/**
- *  Public function for subselect query. Is useful in UNION queries.
- */
-template <class T, class... Args>
-internal::select_t<T, Args...> select(T t, Args... args) {
-  using args_tuple = std::tuple<Args...>;
-  internal::validate_conditions<args_tuple>();
-  return {std::move(t), std::make_tuple(std::forward<Args>(args)...)};
-}
-
-/**
- *  Public function for UNION operator.
- *  lhs and rhs are subselect objects.
- *  Look through example in examples/union.cpp
- */
-template <class L, class R> internal::union_t<L, R> union_(L lhs, R rhs) {
-  return {std::move(lhs), std::move(rhs)};
-}
-
-/**
- *  Public function for EXCEPT operator.
- *  lhs and rhs are subselect objects.
- *  Look through example in examples/except.cpp
- */
-template <class L, class R> internal::except_t<L, R> except(L lhs, R rhs) {
-  return {std::move(lhs), std::move(rhs)};
-}
-
-template <class L, class R>
-internal::intersect_t<L, R> intersect(L lhs, R rhs) {
-  return {std::move(lhs), std::move(rhs)};
-}
-
-/**
- *  Public function for UNION ALL operator.
- *  lhs and rhs are subselect objects.
- *  Look through example in examples/union.cpp
- */
-template <class L, class R> internal::union_t<L, R> union_all(L lhs, R rhs) {
-  return {std::move(lhs), std::move(rhs), true};
-}
-
-/**
- * SELECT * FROM T function.
- * T is typed mapped to a storage.
- * Example: auto rows = storage.select(asterisk<User>());
- * // decltype(rows) is std::vector<std::tuple<...all column typed in declared
- * in make_table order...>> If you need to fetch result as objects not tuple
- * please use `object<T>` instead.
- */
-template <class T> internal::asterisk_t<T> asterisk() {
-  return {};
-}
-
-/**
- * SELECT * FROM T function.
- * T is typed mapped to a storage.
- * Example: auto rows = storage.select(object<User>());
- * // decltype(rows) is std::vector<User>
- * If you need to fetch result as tuples not objects please use `asterisk<T>`
- * instead.
- */
-template <class T> internal::object_t<T> object() {
-  return {};
-}
-} // namespace sqlite_orm
-#pragma once
-
-#include <type_traits> //  std::enable_if, std::is_member_pointer
-
-// #include "select_constraints.h"
-
-// #include "column.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- *  Trait class used to define table mapped type by setter/getter/member
- *  T - member pointer
- */
-template <class T, class SFINAE = void> struct table_type;
-
-template <class O, class F>
-struct table_type<
-    F O::*,
-    typename std::enable_if<
-        std::is_member_pointer<F O::*>::value &&
-        !std::is_member_function_pointer<F O::*>::value>::type> {
-  using type = O;
-};
-
-template <class T>
-struct table_type<T, typename std::enable_if<is_getter<T>::value>::type> {
-  using type = typename getter_traits<T>::object_type;
-};
-
-template <class T>
-struct table_type<T, typename std::enable_if<is_setter<T>::value>::type> {
-  using type = typename setter_traits<T>::object_type;
-};
-
-template <class T, class F> struct table_type<column_pointer<T, F>, void> {
-  using type = T;
-};
-} // namespace internal
-} // namespace sqlite_orm
-#pragma once
-
-#include <string> //  std::string
-
-namespace sqlite_orm {
-
-struct table_info {
-  int cid = 0;
-  std::string name;
-  std::string type;
-  bool notnull = false;
-  std::string dflt_value;
-  int pk = 0;
-};
-
-} // namespace sqlite_orm
-#pragma once
-
-#include <sqlite3.h>
-
-namespace sqlite_orm {
-
-/**
- *  Guard class which finalizes `sqlite3_stmt` in dtor
- */
-struct statement_finalizer {
-  sqlite3_stmt *stmt = nullptr;
-
-  statement_finalizer(decltype(stmt) stmt_) : stmt(stmt_) {
-  }
-
-  inline ~statement_finalizer() {
-    sqlite3_finalize(this->stmt);
-  }
-};
-} // namespace sqlite_orm
-#pragma once
-
-namespace sqlite_orm {
-
-/**
- *  Helper classes used by statement_binder and row_extractor.
- */
-struct int_or_smaller_tag {};
-struct bigint_tag {};
-struct real_tag {};
-
-template <class V> struct arithmetic_tag {
-  using type = std::conditional_t<
-      std::is_integral<V>::value,
-      // Integer class
-      std::conditional_t<
-          sizeof(V) <= sizeof(int),
-          int_or_smaller_tag,
-          bigint_tag>,
-      // Floating-point class
-      real_tag>;
-};
-
-template <class V> using arithmetic_tag_t = typename arithmetic_tag<V>::type;
-} // namespace sqlite_orm
-#pragma once
-
-#include <sqlite3.h>
-#include <string>      //  std::string, std::wstring
-#include <type_traits> //  std::enable_if_t, std::is_arithmetic, std::is_same, std::true_type, std::false_type
-#ifndef SQLITE_ORM_OMITS_CODECVT
-#include <codecvt> //  std::codecvt_utf8_utf16
-#endif             //  SQLITE_ORM_OMITS_CODECVT
-#include <cstddef> //  std::nullptr_t
-#include <locale>  //  std::wstring_convert
-#include <utility> //  std::declval
-#include <vector>  //  std::vector
-
-// #include "is_std_ptr.h"
-
-namespace sqlite_orm {
-
-/**
- *  Specialization for optional type (std::shared_ptr / std::unique_ptr).
- */
-template <typename T> struct is_std_ptr : std::false_type {};
-
-template <typename T> struct is_std_ptr<std::shared_ptr<T>> : std::true_type {
-  using element_type = T;
-
-  static std::shared_ptr<T> make(const T &v) {
-    return std::make_shared<T>(v);
-  }
-};
-
-template <typename T> struct is_std_ptr<std::unique_ptr<T>> : std::true_type {
-  using element_type = T;
-
-  static std::unique_ptr<T> make(const T &v) {
-    return std::make_unique<T>(v);
-  }
-};
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-/**
- *  Helper class used for binding fields to sqlite3 statements.
- */
-template <class V, typename Enable = void>
-struct statement_binder : std::false_type {};
-
-/**
- *  Specialization for arithmetic types.
- */
-template <class V>
-struct statement_binder<V, std::enable_if_t<std::is_arithmetic<V>::value>> {
-  int bind(sqlite3_stmt *stmt, int index, const V &value) {
-    return bind(stmt, index, value, tag());
-  }
-
-private:
-  using tag = arithmetic_tag_t<V>;
-
-  int bind(
-      sqlite3_stmt *stmt,
-      int index,
-      const V &value,
-      const int_or_smaller_tag &) {
-    return sqlite3_bind_int(stmt, index, static_cast<int>(value));
-  }
-
-  int bind(sqlite3_stmt *stmt, int index, const V &value, const bigint_tag &) {
-    return sqlite3_bind_int64(stmt, index, static_cast<sqlite3_int64>(value));
-  }
-
-  int bind(sqlite3_stmt *stmt, int index, const V &value, const real_tag &) {
-    return sqlite3_bind_double(stmt, index, static_cast<double>(value));
-  }
-};
-
-/**
- *  Specialization for std::string and C-string.
- */
-template <class V>
-struct statement_binder<
-    V,
-    std::enable_if_t<
-        std::is_same<V, std::string>::value ||
-        std::is_same<V, const char *>::value>> {
-  int bind(sqlite3_stmt *stmt, int index, const V &value) {
-    return sqlite3_bind_text(
-        stmt, index, string_data(value), -1, SQLITE_TRANSIENT);
-  }
-
-private:
-  const char *string_data(const std::string &s) const {
-    return s.c_str();
-  }
-
-  const char *string_data(const char *s) const {
-    return s;
-  }
-};
-
-#ifndef SQLITE_ORM_OMITS_CODECVT
-/**
- *  Specialization for std::wstring and C-wstring.
- */
-template <class V>
-struct statement_binder<
-    V,
-    std::enable_if_t<
-        std::is_same<V, std::wstring>::value ||
-        std::is_same<V, const wchar_t *>::value>> {
-  int bind(sqlite3_stmt *stmt, int index, const V &value) {
-    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
-    std::string utf8Str = converter.to_bytes(value);
-    return statement_binder<decltype(utf8Str)>().bind(stmt, index, utf8Str);
-  }
-};
-#endif //  SQLITE_ORM_OMITS_CODECVT
-
-/**
- *  Specialization for std::nullptr_t.
- */
-template <> struct statement_binder<std::nullptr_t, void> {
-  int bind(sqlite3_stmt *stmt, int index, const std::nullptr_t &) {
-    return sqlite3_bind_null(stmt, index);
-  }
-};
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <> struct statement_binder<std::nullopt_t, void> {
-  int bind(sqlite3_stmt *stmt, int index, const std::nullopt_t &) {
-    return sqlite3_bind_null(stmt, index);
-  }
-};
-#endif //  SQLITE_ORM_OPTIONAL_SUPPORTED
-
-template <class V>
-struct statement_binder<V, std::enable_if_t<is_std_ptr<V>::value>> {
-  using value_type = typename is_std_ptr<V>::element_type;
-
-  int bind(sqlite3_stmt *stmt, int index, const V &value) {
-    if (value) {
-      return statement_binder<value_type>().bind(stmt, index, *value);
-    } else {
-      return statement_binder<std::nullptr_t>().bind(stmt, index, nullptr);
-    }
-  }
-};
-
-/**
- *  Specialization for optional type (std::vector<char>).
- */
-template <> struct statement_binder<std::vector<char>, void> {
-  int bind(sqlite3_stmt *stmt, int index, const std::vector<char> &value) {
-    if (value.size()) {
-      return sqlite3_bind_blob(
-          stmt,
-          index,
-          (const void *)&value.front(),
-          int(value.size()),
-          SQLITE_TRANSIENT);
-    } else {
-      return sqlite3_bind_blob(stmt, index, "", 0, SQLITE_TRANSIENT);
-    }
-  }
-};
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <class T> struct statement_binder<std::optional<T>, void> {
-  using value_type = T;
-
-  int bind(sqlite3_stmt *stmt, int index, const std::optional<T> &value) {
-    if (value) {
-      return statement_binder<value_type>().bind(stmt, index, *value);
-    } else {
-      return statement_binder<std::nullopt_t>().bind(stmt, index, std::nullopt);
-    }
-  }
-};
-#endif //  SQLITE_ORM_OPTIONAL_SUPPORTED
-
-namespace internal {
-
-template <class T>
-using is_bindable = std::integral_constant<
-    bool,
-    !std::is_base_of<std::false_type, statement_binder<T>>::value>;
-
-struct conditional_binder_base {
-  sqlite3_stmt *stmt = nullptr;
-  int &index;
-
-  conditional_binder_base(decltype(stmt) stmt_, decltype(index) index_)
-      : stmt(stmt_), index(index_) {
-  }
-};
-
-template <class T, class C> struct conditional_binder;
-
-template <class T>
-struct conditional_binder<T, std::true_type> : conditional_binder_base {
-
-  using conditional_binder_base::conditional_binder_base;
-
-  int operator()(const T &t) const {
-    return statement_binder<T>().bind(this->stmt, this->index++, t);
-  }
-};
-
-template <class T>
-struct conditional_binder<T, std::false_type> : conditional_binder_base {
-  using conditional_binder_base::conditional_binder_base;
-
-  int operator()(const T &) const {
-    return SQLITE_OK;
-  }
-};
-
-template <class T, class SFINAE = void> struct bindable_filter_single;
-
-template <class T>
-struct bindable_filter_single<
-    T,
-    typename std::enable_if<is_bindable<T>::value>::type> {
-  using type = std::tuple<T>;
-};
-
-template <class T>
-struct bindable_filter_single<
-    T,
-    typename std::enable_if<!is_bindable<T>::value>::type> {
-  using type = std::tuple<>;
-};
-
-template <class T> struct bindable_filter;
-
-template <class... Args> struct bindable_filter<std::tuple<Args...>> {
-  using type =
-      typename conc_tuple<typename bindable_filter_single<Args>::type...>::type;
-};
-} // namespace internal
-} // namespace sqlite_orm
-#pragma once
-
-#include <sqlite3.h>
-#include <stdlib.h> //  atof, atoi, atoll
-#include <string>   //  std::string, std::wstring
-#include <type_traits> //  std::enable_if_t, std::is_arithmetic, std::is_same, std::enable_if
-#ifndef SQLITE_ORM_OMITS_CODECVT
-#include <codecvt>   //  std::wstring_convert, std::codecvt_utf8_utf16
-#endif               //  SQLITE_ORM_OMITS_CODECVT
-#include <algorithm> //  std::copy
-#include <cstring>   //  strlen
-#include <iterator>  //  std::back_inserter
-#include <tuple>     //  std::tuple, std::tuple_size, std::tuple_element
-#include <vector>    //  std::vector
-
-// #include "arithmetic_tag.h"
-
-// #include "journal_mode.h"
-
-#include <algorithm> //  std::transform
-#include <array>     //  std::array
-#include <cctype>    // std::toupper
-#include <memory>    //  std::unique_ptr
-#include <string>    //  std::string
-
-namespace sqlite_orm {
-
-/**
- *  Caps case cause of 1) delete keyword; 2)
- * https://www.sqlite.org/pragma.html#pragma_journal_mode original spelling
- */
-#ifdef DELETE
-#undef DELETE
-#endif
-enum class journal_mode : signed char {
-  DELETE = 0,
-  TRUNCATE = 1,
-  PERSIST = 2,
-  MEMORY = 3,
-  WAL = 4,
-  OFF = 5,
-};
-
-namespace internal {
-
-inline const std::string &to_string(journal_mode j) {
-  static std::string res[] = {
-      "DELETE",
-      "TRUNCATE",
-      "PERSIST",
-      "MEMORY",
-      "WAL",
-      "OFF",
-  };
-  return res[static_cast<int>(j)];
-}
-
-inline std::unique_ptr<journal_mode>
-journal_mode_from_string(const std::string &str) {
-  std::string upper_str;
-  std::transform(
-      str.begin(), str.end(), std::back_inserter(upper_str), [](char c) {
-        return static_cast<char>(std::toupper(static_cast<int>(c)));
-      });
-  static std::array<journal_mode, 6> all = {{
-      journal_mode::DELETE,
-      journal_mode::TRUNCATE,
-      journal_mode::PERSIST,
-      journal_mode::MEMORY,
-      journal_mode::WAL,
-      journal_mode::OFF,
-  }};
-  for (auto j : all) {
-    if (to_string(j) == upper_str) {
-      return std::make_unique<journal_mode>(j);
-    }
-  }
-  return {};
-}
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "error_code.h"
-
-namespace sqlite_orm {
-
-/**
- *  Helper class used to cast values from argv to V class
- *  which depends from column type.
- *
- */
-template <class V, typename Enable = void> struct row_extractor {
-  //  used in sqlite3_exec (select)
-  V extract(const char *row_value);
-
-  //  used in sqlite_column (iteration, get_all)
-  V extract(sqlite3_stmt *stmt, int columnIndex);
-};
-
-/**
- *  Specialization for arithmetic types.
- */
-template <class V>
-struct row_extractor<V, std::enable_if_t<std::is_arithmetic<V>::value>> {
-  V extract(const char *row_value) {
-    return extract(row_value, tag());
-  }
-
-  V extract(sqlite3_stmt *stmt, int columnIndex) {
-    return extract(stmt, columnIndex, tag());
-  }
-
-private:
-  using tag = arithmetic_tag_t<V>;
-
-  V extract(const char *row_value, const int_or_smaller_tag &) {
-    return static_cast<V>(atoi(row_value));
-  }
-
-  V extract(sqlite3_stmt *stmt, int columnIndex, const int_or_smaller_tag &) {
-    return static_cast<V>(sqlite3_column_int(stmt, columnIndex));
-  }
-
-  V extract(const char *row_value, const bigint_tag &) {
-    return static_cast<V>(atoll(row_value));
-  }
-
-  V extract(sqlite3_stmt *stmt, int columnIndex, const bigint_tag &) {
-    return static_cast<V>(sqlite3_column_int64(stmt, columnIndex));
-  }
-
-  V extract(const char *row_value, const real_tag &) {
-    return static_cast<V>(atof(row_value));
-  }
-
-  V extract(sqlite3_stmt *stmt, int columnIndex, const real_tag &) {
-    return static_cast<V>(sqlite3_column_double(stmt, columnIndex));
-  }
-};
-
-/**
- *  Specialization for std::string.
- */
-template <> struct row_extractor<std::string, void> {
-  std::string extract(const char *row_value) {
-    if (row_value) {
-      return row_value;
-    } else {
-      return {};
-    }
-  }
-
-  std::string extract(sqlite3_stmt *stmt, int columnIndex) {
-    auto cStr = (const char *)sqlite3_column_text(stmt, columnIndex);
-    if (cStr) {
-      return cStr;
-    } else {
-      return {};
-    }
-  }
-};
-#ifndef SQLITE_ORM_OMITS_CODECVT
-/**
- *  Specialization for std::wstring.
- */
-template <> struct row_extractor<std::wstring, void> {
-  std::wstring extract(const char *row_value) {
-    if (row_value) {
-      std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
-      return converter.from_bytes(row_value);
-    } else {
-      return {};
-    }
-  }
-
-  std::wstring extract(sqlite3_stmt *stmt, int columnIndex) {
-    auto cStr = (const char *)sqlite3_column_text(stmt, columnIndex);
-    if (cStr) {
-      std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
-      return converter.from_bytes(cStr);
-    } else {
-      return {};
-    }
-  }
-};
-#endif //  SQLITE_ORM_OMITS_CODECVT
-
-template <class V>
-struct row_extractor<V, std::enable_if_t<is_std_ptr<V>::value>> {
-  using value_type = typename is_std_ptr<V>::element_type;
-
-  V extract(const char *row_value) {
-    if (row_value) {
-      return is_std_ptr<V>::make(
-          row_extractor<value_type>().extract(row_value));
-    } else {
-      return {};
-    }
-  }
-
-  V extract(sqlite3_stmt *stmt, int columnIndex) {
-    auto type = sqlite3_column_type(stmt, columnIndex);
-    if (type != SQLITE_NULL) {
-      return is_std_ptr<V>::make(
-          row_extractor<value_type>().extract(stmt, columnIndex));
-    } else {
-      return {};
-    }
-  }
-};
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <class T> struct row_extractor<std::optional<T>, void> {
-  using value_type = T;
-
-  std::optional<T> extract(const char *row_value) {
-    if (row_value) {
-      return std::make_optional(row_extractor<value_type>().extract(row_value));
-    } else {
-      return std::nullopt;
-    }
-  }
-
-  std::optional<T> extract(sqlite3_stmt *stmt, int columnIndex) {
-    auto type = sqlite3_column_type(stmt, columnIndex);
-    if (type != SQLITE_NULL) {
-      return std::make_optional(
-          row_extractor<value_type>().extract(stmt, columnIndex));
-    } else {
-      return std::nullopt;
-    }
-  }
-};
-#endif //  SQLITE_ORM_OPTIONAL_SUPPORTED
-/**
- *  Specialization for std::vector<char>.
- */
-template <> struct row_extractor<std::vector<char>> {
-  std::vector<char> extract(const char *row_value) {
-    if (row_value) {
-      auto len = ::strlen(row_value);
-      return this->go(row_value, len);
-    } else {
-      return {};
-    }
-  }
-
-  std::vector<char> extract(sqlite3_stmt *stmt, int columnIndex) {
-    auto bytes =
-        static_cast<const char *>(sqlite3_column_blob(stmt, columnIndex));
-    auto len = static_cast<size_t>(sqlite3_column_bytes(stmt, columnIndex));
-    return this->go(bytes, len);
-  }
-
-protected:
-  std::vector<char> go(const char *bytes, size_t len) {
-    if (len) {
-      std::vector<char> res;
-      res.reserve(len);
-      std::copy(bytes, bytes + len, std::back_inserter(res));
-      return res;
-    } else {
-      return {};
-    }
-  }
-};
-
-template <class... Args> struct row_extractor<std::tuple<Args...>> {
-
-  std::tuple<Args...> extract(char **argv) {
-    std::tuple<Args...> res;
-    this->extract<std::tuple_size<decltype(res)>::value>(res, argv);
-    return res;
-  }
-
-  std::tuple<Args...> extract(sqlite3_stmt *stmt, int /*columnIndex*/) {
-    std::tuple<Args...> res;
-    this->extract<std::tuple_size<decltype(res)>::value>(res, stmt);
-    return res;
-  }
-
-protected:
-  template <size_t I, typename std::enable_if<I != 0>::type * = nullptr>
-  void extract(std::tuple<Args...> &t, sqlite3_stmt *stmt) {
-    using tuple_type =
-        typename std::tuple_element<I - 1, typename std::tuple<Args...>>::type;
-    std::get<I - 1>(t) = row_extractor<tuple_type>().extract(stmt, I - 1);
-    this->extract<I - 1>(t, stmt);
-  }
-
-  template <size_t I, typename std::enable_if<I == 0>::type * = nullptr>
-  void extract(std::tuple<Args...> &, sqlite3_stmt *) {
-    //..
-  }
-
-  template <size_t I, typename std::enable_if<I != 0>::type * = nullptr>
-  void extract(std::tuple<Args...> &t, char **argv) {
-    using tuple_type =
-        typename std::tuple_element<I - 1, typename std::tuple<Args...>>::type;
-    std::get<I - 1>(t) = row_extractor<tuple_type>().extract(argv[I - 1]);
-    this->extract<I - 1>(t, argv);
-  }
-
-  template <size_t I, typename std::enable_if<I == 0>::type * = nullptr>
-  void extract(std::tuple<Args...> &, char **) {
-    //..
-  }
-};
-
-/**
- *  Specialization for journal_mode.
- */
-template <> struct row_extractor<journal_mode, void> {
-  journal_mode extract(const char *row_value) {
-    if (row_value) {
-      if (auto res = internal::journal_mode_from_string(row_value)) {
-        return std::move(*res);
-      } else {
-        throw std::system_error(std::make_error_code(
-            orm_error_code::incorrect_journal_mode_string));
-      }
-    } else {
-      throw std::system_error(
-          std::make_error_code(orm_error_code::incorrect_journal_mode_string));
-    }
-  }
-
-  journal_mode extract(sqlite3_stmt *stmt, int columnIndex) {
-    auto cStr = (const char *)sqlite3_column_text(stmt, columnIndex);
-    return this->extract(cStr);
-  }
-};
-} // namespace sqlite_orm
-#pragma once
-
-#include <ostream>
-
-namespace sqlite_orm {
-
-enum class sync_schema_result {
-
-  /**
-   *  created new table, table with the same tablename did not exist
-   */
-  new_table_created,
-
-  /**
-   *  table schema is the same as storage, nothing to be done
-   */
-  already_in_sync,
-
-  /**
-   *  removed excess columns in table (than storage) without dropping a table
-   */
-  old_columns_removed,
-
-  /**
-   *  lacking columns in table (than storage) added without dropping a table
-   */
-  new_columns_added,
-
-  /**
-   *  both old_columns_removed and new_columns_added
-   */
-  new_columns_added_and_old_columns_removed,
-
-  /**
-   *  old table is dropped and new is recreated. Reasons :
-   *      1. delete excess columns in the table than storage if preseve = false
-   *      2. Lacking columns in the table cannot be added due to NULL and
-   * DEFAULT constraint
-   *      3. Reasons 1 and 2 both together
-   *      4. data_type mismatch between table and storage.
-   */
-  dropped_and_recreated,
-};
-
-inline std::ostream &operator<<(std::ostream &os, sync_schema_result value) {
-  switch (value) {
-  case sync_schema_result::new_table_created:
-    return os << "new table created";
-  case sync_schema_result::already_in_sync:
-    return os << "table and storage is already in sync.";
-  case sync_schema_result::old_columns_removed:
-    return os << "old excess columns removed";
-  case sync_schema_result::new_columns_added:
-    return os << "new columns added";
-  case sync_schema_result::new_columns_added_and_old_columns_removed:
-    return os << "old excess columns removed and new columns added";
-  case sync_schema_result::dropped_and_recreated:
-    return os << "old table dropped and recreated";
-  }
-  return os;
-}
-} // namespace sqlite_orm
-#pragma once
-
-#include <string>  //  std::string
-#include <tuple>   //  std::tuple, std::make_tuple
-#include <utility> //  std::forward
-
-// #include "indexed_column.h"
-
-#include <string> //  std::string
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class C> struct indexed_column_t {
-  using column_type = C;
-
-  column_type column_or_expression;
-  std::string _collation_name;
-  int _order = 0; //  -1 = desc, 1 = asc, 0 = not specified
-
-  indexed_column_t<column_type> collate(std::string name) {
-    auto res = std::move(*this);
-    res._collation_name = move(name);
-    return res;
-  }
-
-  indexed_column_t<column_type> asc() {
-    auto res = std::move(*this);
-    res._order = 1;
-    return res;
-  }
-
-  indexed_column_t<column_type> desc() {
-    auto res = std::move(*this);
-    res._order = -1;
-    return res;
-  }
-};
-
-template <class C> struct indexed_column_maker {
-  using type = indexed_column_t<C>;
-
-  indexed_column_t<C> operator()(C col) const {
-    return {std::move(col)};
-  }
-};
-
-template <class C> struct indexed_column_maker<indexed_column_t<C>> {
-  using type = indexed_column_t<C>;
-
-  indexed_column_t<C> operator()(indexed_column_t<C> col) const {
-    return std::move(col);
-  }
-};
-
-template <class C> auto make_indexed_column(C col) {
-  indexed_column_maker<C> maker;
-  return maker(std::move(col));
-}
-
-} // namespace internal
-
-/**
- * Use this function to specify indexed column inside `make_index` function
- * call. Example: make_index("index_name", indexed_column(&User::id).asc())
- */
-template <class C>
-internal::indexed_column_t<C> indexed_column(C column_or_expression) {
-  return {std::move(column_or_expression)};
-}
-
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct index_base {
-  std::string name;
-  bool unique = false;
-};
-
-template <class... Cols> struct index_t : index_base {
-  using columns_type = std::tuple<Cols...>;
-  using object_type = void;
-
-  index_t(std::string name_, bool unique_, columns_type columns_)
-      : index_base{move(name_), unique_}, columns(move(columns_)) {
-  }
-
-  columns_type columns;
-};
-} // namespace internal
-
-template <class... Cols>
-internal::index_t<typename internal::indexed_column_maker<Cols>::type...>
-make_index(const std::string &name, Cols... cols) {
-  return {name, false, std::make_tuple(internal::make_indexed_column(cols)...)};
-}
-
-template <class... Cols>
-internal::index_t<typename internal::indexed_column_maker<Cols>::type...>
-make_unique_index(const std::string &name, Cols... cols) {
-  return {name, true, std::make_tuple(internal::make_indexed_column(cols)...)};
-}
-} // namespace sqlite_orm
-#pragma once
-
-// #include "alias.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- *  If T is alias than mapped_type_proxy<T>::type is alias::type
- *  otherwise T is T.
- */
-template <class T, class sfinae = void> struct mapped_type_proxy {
-  using type = T;
-};
-
-template <class T>
-struct mapped_type_proxy<
-    T,
-    typename std::enable_if<std::is_base_of<alias_tag, T>::value>::type> {
-  using type = typename T::type;
-};
-} // namespace internal
-} // namespace sqlite_orm
-#pragma once
-
-#include <string> //  std::string
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct rowid_t {
-  operator std::string() const {
-    return "rowid";
-  }
-};
-
-struct oid_t {
-  operator std::string() const {
-    return "oid";
-  }
-};
-
-struct _rowid_t {
-  operator std::string() const {
-    return "_rowid_";
-  }
-};
-
-template <class T> struct table_rowid_t : public rowid_t { using type = T; };
-
-template <class T> struct table_oid_t : public oid_t { using type = T; };
-template <class T> struct table__rowid_t : public _rowid_t { using type = T; };
-
-} // namespace internal
-
-inline internal::rowid_t rowid() {
-  return {};
-}
-
-inline internal::oid_t oid() {
-  return {};
-}
-
-inline internal::_rowid_t _rowid_() {
-  return {};
-}
-
-template <class T> internal::table_rowid_t<T> rowid() {
-  return {};
-}
-
-template <class T> internal::table_oid_t<T> oid() {
-  return {};
-}
-
-template <class T> internal::table__rowid_t<T> _rowid_() {
-  return {};
-}
-} // namespace sqlite_orm
-#pragma once
-
-#include <functional> //  std::reference_wrapper
-#include <tuple>      //  std::tuple
-#include <type_traits> //  std::enable_if, std::is_same, std::decay, std::is_arithmetic
-
-// #include "core_functions.h"
-
-// #include "select_constraints.h"
-
-// #include "operators.h"
-
-// #include "rowid.h"
-
-// #include "alias.h"
-
-// #include "column.h"
-
-// #include "storage_traits.h"
-#include <tuple>       //  std::tuple
-#include <type_traits> //  std::is_same, std::enable_if, std::true_type, std::false_type, std::integral_constant
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class... Ts> struct storage_impl;
-
-template <class T, class... Args> struct table_t;
-
-namespace storage_traits {
-
-/**
- *  S - storage_impl type
- *  T - mapped or not mapped data type
- */
-template <class S, class T, class SFINAE = void> struct type_is_mapped_impl;
-
-/**
- *  S - storage
- *  T - mapped or not mapped data type
- */
-template <class S, class T>
-struct type_is_mapped : type_is_mapped_impl<typename S::impl_type, T> {};
-
-/**
- *  Final specialisation
- */
-template <class T>
-struct type_is_mapped_impl<storage_impl<>, T, void> : std::false_type {};
-
-template <class S, class T>
-struct type_is_mapped_impl<
-    S,
-    T,
-    typename std::enable_if<
-        std::is_same<T, typename S::table_type::object_type>::value>::type>
-    : std::true_type {};
-
-template <class S, class T>
-struct type_is_mapped_impl<
-    S,
-    T,
-    typename std::enable_if<
-        !std::is_same<T, typename S::table_type::object_type>::value>::type>
-    : type_is_mapped_impl<typename S::super, T> {};
-
-/**
- *  S - storage_impl type
- *  T - mapped or not mapped data type
- */
-template <class S, class T, class SFINAE = void>
-struct storage_columns_count_impl;
-
-/**
- *  S - storage
- *  T - mapped or not mapped data type
- */
-template <class S, class T>
-struct storage_columns_count
-    : storage_columns_count_impl<typename S::impl_type, T> {};
-
-/**
- *  Final specialisation
- */
-template <class T>
-struct storage_columns_count_impl<storage_impl<>, T, void>
-    : std::integral_constant<int, 0> {};
-
-template <class S, class T>
-struct storage_columns_count_impl<
-    S,
-    T,
-    typename std::enable_if<
-        std::is_same<T, typename S::table_type::object_type>::value>::type>
-    : std::integral_constant<int, S::table_type::columns_count> {};
-
-template <class S, class T>
-struct storage_columns_count_impl<
-    S,
-    T,
-    typename std::enable_if<
-        !std::is_same<T, typename S::table_type::object_type>::value>::type>
-    : storage_columns_count_impl<typename S::super, T> {};
-
-/**
- *  T - table type.
- */
-template <class T> struct table_types;
-
-/**
- *  type is std::tuple of field types of mapped colums.
- */
-template <class T, class... Args> struct table_types<table_t<T, Args...>> {
-  using type = std::tuple<typename Args::field_type...>;
-};
-
-/**
- *  S - storage_impl type
- *  T - mapped or not mapped data type
- */
-template <class S, class T, class SFINAE = void>
-struct storage_mapped_columns_impl;
-
-/**
- *  S - storage
- *  T - mapped or not mapped data type
- */
-template <class S, class T>
-struct storage_mapped_columns
-    : storage_mapped_columns_impl<typename S::impl_type, T> {};
-
-/**
- *  Final specialisation
- */
-template <class T> struct storage_mapped_columns_impl<storage_impl<>, T, void> {
-  using type = std::tuple<>;
-};
-
-template <class S, class T>
-struct storage_mapped_columns_impl<
-    S,
-    T,
-    typename std::enable_if<
-        std::is_same<T, typename S::table_type::object_type>::value>::type> {
-  using table_type = typename S::table_type;
-  using type = typename table_types<table_type>::type;
-};
-
-template <class S, class T>
-struct storage_mapped_columns_impl<
-    S,
-    T,
-    typename std::enable_if<
-        !std::is_same<T, typename S::table_type::object_type>::value>::type>
-    : storage_mapped_columns_impl<typename S::super, T> {};
-
-} // namespace storage_traits
-} // namespace internal
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-using int64 = sqlite_int64;
-using uint64 = sqlite_uint64;
-
-namespace internal {
-
-/**
- *  This is a proxy class used to define what type must have result type
- * depending on select arguments (member pointer, aggregate functions, etc).
- * Below you can see specializations for different types. E.g. specialization
- * for internal::length_t has `type` int cause LENGTH returns INTEGER in sqlite.
- * Every column_result_t must have `type` type that equals c++ SELECT return
- * type for T T - C++ type SFINAE - sfinae argument
- */
-template <class St, class T, class SFINAE = void> struct column_result_t;
-
-template <class St, class O, class F>
-struct column_result_t<
-    St,
-    F O::*,
-    typename std::enable_if<
-        std::is_member_pointer<F O::*>::value &&
-        !std::is_member_function_pointer<F O::*>::value>::type> {
-  using type = F;
-};
-
-/**
- *  Common case for all getter types. Getter types are defined in column.h file
- */
-template <class St, class T>
-struct column_result_t<
-    St,
-    T,
-    typename std::enable_if<is_getter<T>::value>::type> {
-  using type = typename getter_traits<T>::field_type;
-};
-
-/**
- *  Common case for all setter types. Setter types are defined in column.h file
- */
-template <class St, class T>
-struct column_result_t<
-    St,
-    T,
-    typename std::enable_if<is_setter<T>::value>::type> {
-  using type = typename setter_traits<T>::field_type;
-};
-
-template <class St, class R, class S, class... Args>
-struct column_result_t<St, internal::core_function_t<R, S, Args...>, void> {
-  using type = R;
-};
-
-template <class St, class X, class S>
-struct column_result_t<
-    St,
-    core_function_t<internal::unique_ptr_result_of<X>, S, X>,
-    void> {
-  using type = std::unique_ptr<typename column_result_t<St, X>::type>;
-};
-
-template <class St, class T>
-struct column_result_t<St, count_asterisk_t<T>, void> {
-  using type = int;
-};
-
-template <class St>
-struct column_result_t<St, count_asterisk_without_type, void> {
-  using type = int;
-};
-
-template <class St, class T> struct column_result_t<St, distinct_t<T>, void> {
-  using type = typename column_result_t<St, T>::type;
-};
-
-template <class St, class T> struct column_result_t<St, all_t<T>, void> {
-  using type = typename column_result_t<St, T>::type;
-};
-
-template <class St, class L, class R>
-struct column_result_t<St, conc_t<L, R>, void> {
-  using type = std::string;
-};
-
-template <class St, class L, class R>
-struct column_result_t<St, add_t<L, R>, void> {
-  using type = double;
-};
-
-template <class St, class L, class R>
-struct column_result_t<St, sub_t<L, R>, void> {
-  using type = double;
-};
-
-template <class St, class L, class R>
-struct column_result_t<St, mul_t<L, R>, void> {
-  using type = double;
-};
-
-template <class St, class L, class R>
-struct column_result_t<St, internal::div_t<L, R>, void> {
-  using type = double;
-};
-
-template <class St, class L, class R>
-struct column_result_t<St, mod_t<L, R>, void> {
-  using type = double;
-};
-
-template <class St, class L, class R>
-struct column_result_t<St, bitwise_shift_left_t<L, R>, void> {
-  using type = int;
-};
-
-template <class St, class L, class R>
-struct column_result_t<St, bitwise_shift_right_t<L, R>, void> {
-  using type = int;
-};
-
-template <class St, class L, class R>
-struct column_result_t<St, bitwise_and_t<L, R>, void> {
-  using type = int;
-};
-
-template <class St, class L, class R>
-struct column_result_t<St, bitwise_or_t<L, R>, void> {
-  using type = int;
-};
-
-template <class St, class T>
-struct column_result_t<St, bitwise_not_t<T>, void> {
-  using type = int;
-};
-
-template <class St> struct column_result_t<St, rowid_t, void> {
-  using type = int64;
-};
-
-template <class St> struct column_result_t<St, oid_t, void> {
-  using type = int64;
-};
-
-template <class St> struct column_result_t<St, _rowid_t, void> {
-  using type = int64;
-};
-
-template <class St, class T>
-struct column_result_t<St, table_rowid_t<T>, void> {
-  using type = int64;
-};
-
-template <class St, class T> struct column_result_t<St, table_oid_t<T>, void> {
-  using type = int64;
-};
-
-template <class St, class T>
-struct column_result_t<St, table__rowid_t<T>, void> {
-  using type = int64;
-};
-
-template <class St, class T, class C>
-struct column_result_t<St, alias_column_t<T, C>, void> {
-  using type = typename column_result_t<St, C>::type;
-};
-
-template <class St, class T, class F>
-struct column_result_t<St, column_pointer<T, F>>
-    : column_result_t<St, F, void> {};
-
-template <class St, class... Args>
-struct column_result_t<St, columns_t<Args...>, void> {
-  using type = std::tuple<
-      typename column_result_t<St, typename std::decay<Args>::type>::type...>;
-};
-
-template <class St, class T, class... Args>
-struct column_result_t<St, select_t<T, Args...>>
-    : column_result_t<St, T, void> {};
-
-template <class St, class T>
-struct column_result_t<
-    St,
-    T,
-    typename std::enable_if<
-        is_base_of_template<T, compound_operator>::value>::type> {
-  using left_type = typename T::left_type;
-  using right_type = typename T::right_type;
-  using left_result = typename column_result_t<St, left_type>::type;
-  using right_result = typename column_result_t<St, right_type>::type;
-  static_assert(
-      std::is_same<left_result, right_result>::value,
-      "Compound subselect queries must return same types");
-  using type = left_result;
-};
-
-/**
- *  Result for the most simple queries like `SELECT 1`
- */
-template <class St, class T>
-struct column_result_t<
-    St,
-    T,
-    typename std::enable_if<std::is_arithmetic<T>::value>::type> {
-  using type = T;
-};
-
-/**
- *  Result for the most simple queries like `SELECT 'ototo'`
- */
-template <class St> struct column_result_t<St, const char *, void> {
-  using type = std::string;
-};
-
-template <class St> struct column_result_t<St, std::string, void> {
-  using type = std::string;
-};
-
-template <class St, class T, class E>
-struct column_result_t<St, as_t<T, E>, void>
-    : column_result_t<St, typename std::decay<E>::type, void> {};
-
-template <class St, class T> struct column_result_t<St, asterisk_t<T>, void> {
-  using type = typename storage_traits::storage_mapped_columns<St, T>::type;
-};
-
-template <class St, class T> struct column_result_t<St, object_t<T>, void> {
-  using type = T;
-};
-
-template <class St, class T, class E>
-struct column_result_t<St, cast_t<T, E>, void> {
-  using type = T;
-};
-
-template <class St, class R, class T, class E, class... Args>
-struct column_result_t<St, simple_case_t<R, T, E, Args...>, void> {
-  using type = R;
-};
-
-template <class St, class A, class T, class E>
-struct column_result_t<St, like_t<A, T, E>, void> {
-  using type = bool;
-};
-
-template <class St, class A, class T>
-struct column_result_t<St, glob_t<A, T>, void> {
-  using type = bool;
-};
-
-template <class St, class C>
-struct column_result_t<St, negated_condition_t<C>, void> {
-  using type = bool;
-};
-
-template <class St, class T>
-struct column_result_t<St, std::reference_wrapper<T>, void>
-    : column_result_t<St, T, void> {};
-} // namespace internal
-} // namespace sqlite_orm
-#pragma once
-
-#include <algorithm>   //  std::reverse, std::find_if
-#include <string>      //  std::string
-#include <tuple>       //  std::tuple_size, std::tuple_element
-#include <type_traits> //  std::remove_reference, std::is_same, std::is_base_of
-#include <vector>      //  std::vector
-
-// #include "column_result.h"
-
-// #include "static_magic.h"
-
-// #include "typed_comparator.h"
-
-// #include "constraints.h"
-
-// #include "tuple_helper.h"
-
-// #include "table_info.h"
-
-// #include "type_printer.h"
-
-// #include "column.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct table_base {
-
-  /**
-   *  Table name.
-   */
-  std::string name;
-
-  bool _without_rowid = false;
-};
-
-/**
- *  Table interface class. Implementation is hidden in `table_impl` class.
- */
-template <class T, class... Cs> struct table_t : table_base {
-  using object_type = T;
-  using columns_type = std::tuple<Cs...>;
-
-  static constexpr const int columns_count =
-      static_cast<int>(std::tuple_size<columns_type>::value);
-
-  columns_type columns;
-
-  table_t(decltype(name) name_, columns_type columns_)
-      : table_base{std::move(name_)}, columns(std::move(columns_)) {
-  }
-
-  table_t<T, Cs...> without_rowid() const {
-    auto res = *this;
-    res._without_rowid = true;
-    return res;
-  }
-
-  /**
-   *  Function used to get field value from object by mapped member
-   * pointer/setter/getter
-   */
-  template <class F, class C>
-  const F *get_object_field_pointer(const object_type &obj, C c) const {
-    const F *res = nullptr;
-    this->for_each_column_with_field_type<F>([&res, &c, &obj](auto &col) {
-      using column_type = typename std::remove_reference<decltype(col)>::type;
-      using member_pointer_t = typename column_type::member_pointer_t;
-      using getter_type = typename column_type::getter_type;
-      using setter_type = typename column_type::setter_type;
-      // Make static_if have at least one input as a workaround for GCC bug:
-      // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095
-      if (!res) {
-        static_if<std::is_same<C, member_pointer_t>{}>(
-            [&res, &obj, &col](const C &c_) {
-              if (compare_any(col.member_pointer, c_)) {
-                res = &(obj.*col.member_pointer);
-              }
-            })(c);
-      }
-      if (!res) {
-        static_if<std::is_same<C, getter_type>{}>(
-            [&res, &obj, &col](const C &c_) {
-              if (compare_any(col.getter, c_)) {
-                res = &((obj).*(col.getter))();
-              }
-            })(c);
-      }
-      if (!res) {
-        static_if<std::is_same<C, setter_type>{}>(
-            [&res, &obj, &col](const C &c_) {
-              if (compare_any(col.setter, c_)) {
-                res = &((obj).*(col.getter))();
-              }
-            })(c);
-      }
-    });
-    return res;
-  }
-
-  /**
-   *  @return vector of column names of table.
-   */
-  std::vector<std::string> column_names() const {
-    std::vector<std::string> res;
-    this->for_each_column([&res](auto &c) { res.push_back(c.name); });
-    return res;
-  }
-
-  /**
-   *  Calls **l** with every primary key dedicated constraint
-   */
-  template <class L> void for_each_primary_key(const L &l) const {
-    iterate_tuple(this->columns, [&l](auto &column) {
-      using column_type = typename std::decay<decltype(column)>::type;
-      static_if<internal::is_primary_key<column_type>{}>(l)(column);
-    });
-  }
-
-  std::vector<std::string> composite_key_columns_names() const {
-    std::vector<std::string> res;
-    this->for_each_primary_key(
-        [this, &res](auto &c) { res = this->composite_key_columns_names(c); });
-    return res;
-  }
-
-  std::vector<std::string> primary_key_column_names() const {
-    std::vector<std::string> res;
-    this->for_each_column_with<constraints::primary_key_t<>>(
-        [&res](auto &c) { res.push_back(c.name); });
-    if (!res.size()) {
-      res = this->composite_key_columns_names();
-    }
-    return res;
-  }
-
-  template <class... Args>
-  std::vector<std::string> composite_key_columns_names(
-      const constraints::primary_key_t<Args...> &pk) const {
-    std::vector<std::string> res;
-    using pk_columns_tuple = decltype(pk.columns);
-    res.reserve(std::tuple_size<pk_columns_tuple>::value);
-    iterate_tuple(pk.columns, [this, &res](auto &v) {
-      res.push_back(this->find_column_name(v));
-    });
-    return res;
-  }
-
-  /**
-   *  Searches column name by class member pointer passed as the first argument.
-   *  @return column name or empty string if nothing found.
-   */
-  template <
-      class F,
-      class O,
-      typename = typename std::enable_if<
-          std::is_member_pointer<F O::*>::value &&
-          !std::is_member_function_pointer<F O::*>::value>::type>
-  std::string find_column_name(F O::*m) const {
-    std::string res;
-    this->template for_each_column_with_field_type<F>([&res, m](auto &c) {
-      if (c.member_pointer == m) {
-        res = c.name;
-      }
-    });
-    return res;
-  }
-
-  /**
-   *  Searches column name by class getter function member pointer passed as
-   * first argument.
-   *  @return column name or empty string if nothing found.
-   */
-  template <class G>
-  std::string find_column_name(
-      G getter,
-      typename std::enable_if<is_getter<G>::value>::type * = nullptr) const {
-    std::string res;
-    using field_type = typename getter_traits<G>::field_type;
-    this->template for_each_column_with_field_type<field_type>(
-        [&res, getter](auto &c) {
-          if (compare_any(c.getter, getter)) {
-            res = c.name;
-          }
-        });
-    return res;
-  }
-
-  /**
-   *  Searches column name by class setter function member pointer passed as
-   * first argument.
-   *  @return column name or empty string if nothing found.
-   */
-  template <class S>
-  std::string find_column_name(
-      S setter,
-      typename std::enable_if<is_setter<S>::value>::type * = nullptr) const {
-    std::string res;
-    using field_type = typename setter_traits<S>::field_type;
-    this->template for_each_column_with_field_type<field_type>(
-        [&res, setter](auto &c) {
-          if (compare_any(c.setter, setter)) {
-            res = c.name;
-          }
-        });
-    return res;
-  }
-
-  /**
-   *  Iterates all columns and fires passed lambda. Lambda must have one and
-   * only templated argument Otherwise code will not compile. Excludes table
-   * constraints (e.g. foreign_key_t) at the end of the columns list. To iterate
-   * columns with table constraints use iterate_tuple(columns, ...) instead. L
-   * is lambda type. Do not specify it explicitly.
-   *  @param l Lambda to be called per column itself. Must have signature like
-   * this [] (auto col) -> void {}
-   */
-  template <class L> void for_each_column(const L &l) const {
-    iterate_tuple(this->columns, [&l](auto &column) {
-      using column_type = typename std::decay<decltype(column)>::type;
-      static_if<is_column<column_type>{}>(l)(column);
-    });
-  }
-
-  template <class F, class L>
-  void for_each_column_with_field_type(const L &l) const {
-    iterate_tuple(this->columns, [&l](auto &column) {
-      using column_type = typename std::decay<decltype(column)>::type;
-      using field_type = typename column_field_type<column_type>::type;
-      static_if<std::is_same<F, field_type>{}>(l)(column);
-    });
-  }
-
-  /**
-   *  Iterates all columns that have specified constraints and fires passed
-   * lambda. Lambda must have one and only templated argument Otherwise code
-   * will not compile. L is lambda type. Do not specify it explicitly.
-   *  @param l Lambda to be called per column itself. Must have signature like
-   * this [] (auto col) -> void {}
-   */
-  template <class Op, class L> void for_each_column_with(const L &l) const {
-    using tuple_helper::tuple_contains_type;
-    iterate_tuple(this->columns, [&l](auto &column) {
-      using column_type = typename std::decay<decltype(column)>::type;
-      using constraints_type =
-          typename column_constraints_type<column_type>::type;
-      static_if<tuple_contains_type<Op, constraints_type>{}>(l)(column);
-    });
-  }
-
-  std::vector<table_info> get_table_info() const {
-    std::vector<table_info> res;
-    res.reserve(size_t(this->columns_count));
-    this->for_each_column([&res](auto &col) {
-      std::string dft;
-      using field_type = typename std::decay<decltype(col)>::type::field_type;
-      if (auto d = col.default_value()) {
-        dft = *d;
-      }
-      table_info i{
-          -1,
-          col.name,
-          type_printer<field_type>().print(),
-          col.not_null(),
-          dft,
-          col.template has<constraints::primary_key_t<>>(),
-      };
-      res.emplace_back(i);
-    });
-    auto compositeKeyColumnNames = this->composite_key_columns_names();
-    for (size_t i = 0; i < compositeKeyColumnNames.size(); ++i) {
-      auto &columnName = compositeKeyColumnNames[i];
-      auto it = std::find_if(
-          res.begin(), res.end(), [&columnName](const table_info &ti) {
-            return ti.name == columnName;
-          });
-      if (it != res.end()) {
-        it->pk = static_cast<int>(i + 1);
-      }
-    }
-    return res;
-  }
-};
-} // namespace internal
-
-/**
- *  Function used for table creation. Do not use table constructor - use this
- * function cause table class is templated and its constructing too (just like
- * std::make_unique or std::make_pair).
- */
-template <
-    class... Cs,
-    class T =
-        typename std::tuple_element<0, std::tuple<Cs...>>::type::object_type>
-internal::table_t<T, Cs...> make_table(const std::string &name, Cs... args) {
-  return {name, std::make_tuple<Cs...>(std::forward<Cs>(args)...)};
-}
-
-template <class T, class... Cs>
-internal::table_t<T, Cs...> make_table(const std::string &name, Cs... args) {
-  return {name, std::make_tuple<Cs...>(std::forward<Cs>(args)...)};
-}
-} // namespace sqlite_orm
-#pragma once
-
-#include <sqlite3.h>
-#include <stdlib.h>     //  std::atoi
-#include <algorithm>    //  std::find_if
-#include <cstddef>      //  std::nullptr_t
-#include <sstream>      //  std::stringstream
-#include <string>       //  std::string
-#include <system_error> //  std::system_error, std::error_code
-#include <type_traits> //  std::forward, std::enable_if, std::is_same, std::remove_reference, std::false_type, std::true_type
-#include <typeindex>   //  std::type_index
-#include <utility>     //  std::pair, std::make_pair
-#include <vector>      //  std::vector
-
-// #include "error_code.h"
-
-// #include "statement_finalizer.h"
-
-// #include "row_extractor.h"
-
-// #include "constraints.h"
-
-// #include "select_constraints.h"
-
-// #include "field_printer.h"
-
-// #include "table_info.h"
-
-// #include "sync_schema_result.h"
-
-// #include "field_value_holder.h"
-
-#include <type_traits> //  std::enable_if
-
-// #include "column.h"
-
-namespace sqlite_orm {
-namespace internal {
-
-template <class T, class SFINAE = void> struct field_value_holder;
-
-template <class T>
-struct field_value_holder<
-    T,
-    typename std::enable_if<getter_traits<T>::returns_lvalue>::type> {
-  using type = typename getter_traits<T>::field_type;
-
-  const type &value;
-};
-
-template <class T>
-struct field_value_holder<
-    T,
-    typename std::enable_if<!getter_traits<T>::returns_lvalue>::type> {
-  using type = typename getter_traits<T>::field_type;
-
-  type value;
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct storage_impl_base {
-
-  bool table_exists(const std::string &tableName, sqlite3 *db) const {
-    auto result = false;
-    std::stringstream ss;
-    ss << "SELECT COUNT(*) FROM sqlite_master WHERE type = '"
-       << "table"
-       << "' AND name = '" << tableName << "'";
-    auto query = ss.str();
-    auto rc = sqlite3_exec(
-        db,
-        query.c_str(),
-        [](void *data, int argc, char **argv, char ** /*azColName*/) -> int {
-          auto &res = *(bool *)data;
-          if (argc) {
-            res = !!std::atoi(argv[0]);
-          }
-          return 0;
-        },
-        &result,
-        nullptr);
-    if (rc != SQLITE_OK) {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-    return result;
-  }
-
-  void rename_table(
-      sqlite3 *db,
-      const std::string &oldName,
-      const std::string &newName) const {
-    std::stringstream ss;
-    ss << "ALTER TABLE " << oldName << " RENAME TO " << newName;
-    auto query = ss.str();
-    sqlite3_stmt *stmt;
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      statement_finalizer finalizer{stmt};
-      if (sqlite3_step(stmt) == SQLITE_DONE) {
-        //  done..
-      } else {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  static bool get_remove_add_columns(
-      std::vector<table_info *> &columnsToAdd,
-      std::vector<table_info> &storageTableInfo,
-      std::vector<table_info> &dbTableInfo) {
-    bool notEqual = false;
-
-    //  iterate through storage columns
-    for (size_t storageColumnInfoIndex = 0;
-         storageColumnInfoIndex < storageTableInfo.size();
-         ++storageColumnInfoIndex) {
-
-      //  get storage's column info
-      auto &storageColumnInfo = storageTableInfo[storageColumnInfoIndex];
-      auto &columnName = storageColumnInfo.name;
-
-      //  search for a column in db eith the same name
-      auto dbColumnInfoIt = std::find_if(
-          dbTableInfo.begin(), dbTableInfo.end(), [&columnName](auto &ti) {
-            return ti.name == columnName;
-          });
-      if (dbColumnInfoIt != dbTableInfo.end()) {
-        auto &dbColumnInfo = *dbColumnInfoIt;
-        auto columnsAreEqual =
-            dbColumnInfo.name == storageColumnInfo.name &&
-            dbColumnInfo.notnull == storageColumnInfo.notnull &&
-            (dbColumnInfo.dflt_value.length() > 0) ==
-                (storageColumnInfo.dflt_value.length() > 0) &&
-            dbColumnInfo.pk == storageColumnInfo.pk;
-        if (!columnsAreEqual) {
-          notEqual = true;
-          break;
-        }
-        dbTableInfo.erase(dbColumnInfoIt);
-        storageTableInfo.erase(
-            storageTableInfo.begin() +
-            static_cast<ptrdiff_t>(storageColumnInfoIndex));
-        --storageColumnInfoIndex;
-      } else {
-        columnsToAdd.push_back(&storageColumnInfo);
-      }
-    }
-    return notEqual;
-  }
-
-  std::vector<table_info>
-  get_table_info(const std::string &tableName, sqlite3 *db) const {
-    std::vector<table_info> result;
-    auto query = "PRAGMA table_info('" + tableName + "')";
-    auto rc = sqlite3_exec(
-        db,
-        query.c_str(),
-        [](void *data, int argc, char **argv, char **) -> int {
-          auto &res = *(std::vector<table_info> *)data;
-          if (argc) {
-            auto index = 0;
-            auto cid = std::atoi(argv[index++]);
-            std::string name = argv[index++];
-            std::string type = argv[index++];
-            bool notnull = !!std::atoi(argv[index++]);
-            std::string dflt_value = argv[index] ? argv[index] : "";
-            index++;
-            auto pk = std::atoi(argv[index++]);
-            res.push_back(table_info{cid, name, type, notnull, dflt_value, pk});
-          }
-          return 0;
-        },
-        &result,
-        nullptr);
-    if (rc != SQLITE_OK) {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-    return result;
-  }
-};
-
-/**
- *  This is a generic implementation. Used as a tail in storage_impl inheritance
- * chain
- */
-template <class... Ts> struct storage_impl;
-
-template <class H, class... Ts>
-struct storage_impl<H, Ts...> : public storage_impl<Ts...> {
-  using table_type = H;
-  using super = storage_impl<Ts...>;
-
-  storage_impl(H h, Ts... ts)
-      : super(std::forward<Ts>(ts)...), table(std::move(h)) {
-  }
-
-  table_type table;
-
-  template <class L> void for_each(const L &l) {
-    this->super::for_each(l);
-    l(*this);
-  }
-
-#if SQLITE_VERSION_NUMBER >= 3006019
-
-  /**
-   *  Returns foreign keys count in table definition
-   */
-  int foreign_keys_count() {
-    auto res = 0;
-    iterate_tuple(this->table.columns, [&res](auto &c) {
-      if (internal::is_foreign_key<
-              typename std::decay<decltype(c)>::type>::value) {
-        ++res;
-      }
-    });
-    return res;
-  }
-
-#endif
-
-  /**
-   *  Is used to get column name by member pointer to a base class.
-   *  Main difference between `column_name` and `column_name_simple` is that
-   *  `column_name` has SFINAE check for type equality but `column_name_simple`
-   * has not.
-   */
-  template <class O, class F> std::string column_name_simple(F O::*m) const {
-    return this->table.find_column_name(m);
-  }
-
-  /**
-   *  Cute function used to find column name by its type and member pointer.
-   * Uses SFINAE to skip inequal type O.
-   */
-  template <class O, class F, class HH = typename H::object_type>
-  std::string column_name(
-      F O::*m,
-      typename std::enable_if<std::is_same<O, HH>::value>::type * =
-          nullptr) const {
-    return this->table.find_column_name(m);
-  }
-
-  /**
-   *  Opposite version of function defined above. Just calls same function in
-   * superclass.
-   */
-  template <class O, class F, class HH = typename H::object_type>
-  std::string column_name(
-      F O::*m,
-      typename std::enable_if<!std::is_same<O, HH>::value>::type * =
-          nullptr) const {
-    return this->super::column_name(m);
-  }
-
-  template <class T, class F, class HH = typename H::object_type>
-  std::string column_name(
-      const column_pointer<T, F> &c,
-      typename std::enable_if<std::is_same<T, HH>::value>::type * =
-          nullptr) const {
-    return this->column_name_simple(c.field);
-  }
-
-  template <class T, class F, class HH = typename H::object_type>
-  std::string column_name(
-      const column_pointer<T, F> &c,
-      typename std::enable_if<!std::is_same<T, HH>::value>::type * =
-          nullptr) const {
-    return this->super::column_name(c);
-  }
-
-  template <class O, class HH = typename H::object_type>
-  const auto &get_impl(
-      typename std::enable_if<std::is_same<O, HH>::value>::type * =
-          nullptr) const {
-    return *this;
-  }
-
-  template <class O, class HH = typename H::object_type>
-  const auto &get_impl(
-      typename std::enable_if<!std::is_same<O, HH>::value>::type * =
-          nullptr) const {
-    return this->super::template get_impl<O>();
-  }
-
-  template <class O, class HH = typename H::object_type>
-  auto &get_impl(
-      typename std::enable_if<std::is_same<O, HH>::value>::type * = nullptr) {
-    return *this;
-  }
-
-  template <class O, class HH = typename H::object_type>
-  auto &get_impl(
-      typename std::enable_if<!std::is_same<O, HH>::value>::type * = nullptr) {
-    return this->super::template get_impl<O>();
-  }
-
-  template <class O, class HH = typename H::object_type>
-  const auto *find_table(
-      typename std::enable_if<std::is_same<O, HH>::value>::type * =
-          nullptr) const {
-    return &this->table;
-  }
-
-  template <class O, class HH = typename H::object_type>
-  const auto *find_table(
-      typename std::enable_if<!std::is_same<O, HH>::value>::type * =
-          nullptr) const {
-    return this->super::template find_table<O>();
-  }
-
-  std::string find_table_name(std::type_index ti) const {
-    std::type_index thisTypeIndex{typeid(typename H::object_type)};
-    if (thisTypeIndex == ti) {
-      return this->table.name;
-    } else {
-      return this->super::find_table_name(ti);
-    }
-  }
-
-  void add_column(const table_info &ti, sqlite3 *db) const {
-    std::stringstream ss;
-    ss << "ALTER TABLE " << this->table.name << " ADD COLUMN " << ti.name
-       << " ";
-    ss << ti.type << " ";
-    if (ti.pk) {
-      ss << "PRIMARY KEY ";
-    }
-    if (ti.notnull) {
-      ss << "NOT NULL ";
-    }
-    if (ti.dflt_value.length()) {
-      ss << "DEFAULT " << ti.dflt_value << " ";
-    }
-    auto query = ss.str();
-    sqlite3_stmt *stmt;
-    auto prepareResult =
-        sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr);
-    if (prepareResult == SQLITE_OK) {
-      statement_finalizer finalizer{stmt};
-      if (sqlite3_step(stmt) == SQLITE_DONE) {
-        //..
-      } else {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  /**
-   *  Copies current table to another table with a given **name**.
-   *  Performs CREATE TABLE %name% AS SELECT %this->table.columns_names()% FROM
-   * &this->table.name%;
-   */
-  void copy_table(
-      sqlite3 *db,
-      const std::string &name,
-      const std::vector<table_info *> &columnsToIgnore) const {
-    std::ignore = columnsToIgnore;
-
-    std::stringstream ss;
-    std::vector<std::string> columnNames;
-    this->table.for_each_column([&columnNames, &columnsToIgnore](auto &c) {
-      auto &columnName = c.name;
-      auto columnToIgnoreIt = std::find_if(
-          columnsToIgnore.begin(),
-          columnsToIgnore.end(),
-          [&columnName](auto tableInfoPointer) {
-            return columnName == tableInfoPointer->name;
-          });
-      if (columnToIgnoreIt == columnsToIgnore.end()) {
-        columnNames.emplace_back(columnName);
-      }
-    });
-    auto columnNamesCount = columnNames.size();
-    ss << "INSERT INTO " << name << " (";
-    for (size_t i = 0; i < columnNamesCount; ++i) {
-      ss << columnNames[i];
-      if (i < columnNamesCount - 1) {
-        ss << ",";
-      }
-      ss << " ";
-    }
-    ss << ") ";
-    ss << "SELECT ";
-    for (size_t i = 0; i < columnNamesCount; ++i) {
-      ss << columnNames[i];
-      if (i < columnNamesCount - 1) {
-        ss << ",";
-      }
-      ss << " ";
-    }
-    ss << "FROM '" << this->table.name << "' ";
-    auto query = ss.str();
-    sqlite3_stmt *stmt;
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      statement_finalizer finalizer{stmt};
-      if (sqlite3_step(stmt) == SQLITE_DONE) {
-        //..
-      } else {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  sync_schema_result schema_status(sqlite3 *db, bool preserve) const {
-
-    auto res = sync_schema_result::already_in_sync;
-
-    //  first let's see if table with such name exists..
-    auto gottaCreateTable = !this->table_exists(this->table.name, db);
-    if (!gottaCreateTable) {
-
-      //  get table info provided in `make_table` call..
-      auto storageTableInfo = this->table.get_table_info();
-
-      //  now get current table info from db using `PRAGMA table_info` query..
-      auto dbTableInfo = this->get_table_info(this->table.name, db);
-
-      //  this vector will contain pointers to columns that gotta be added..
-      std::vector<table_info *> columnsToAdd;
-
-      if (this->get_remove_add_columns(
-              columnsToAdd, storageTableInfo, dbTableInfo)) {
-        gottaCreateTable = true;
-      }
-
-      if (!gottaCreateTable) { //  if all storage columns are equal to actual db
-                               //  columns but there are
-        //  excess columns at the db..
-        if (dbTableInfo.size() > 0) {
-          // extra table columns than storage columns
-          if (!preserve) {
-            gottaCreateTable = true;
-          } else {
-            res = decltype(res)::old_columns_removed;
-          }
-        }
-      }
-      if (gottaCreateTable) {
-        res = decltype(res)::dropped_and_recreated;
-      } else {
-        if (columnsToAdd.size()) {
-          // extra storage columns than table columns
-          for (auto columnPointer : columnsToAdd) {
-            if (columnPointer->notnull && columnPointer->dflt_value.empty()) {
-              gottaCreateTable = true;
-              break;
-            }
-          }
-          if (!gottaCreateTable) {
-            if (res == decltype(res)::old_columns_removed) {
-              res = decltype(res)::new_columns_added_and_old_columns_removed;
-            } else {
-              res = decltype(res)::new_columns_added;
-            }
-          } else {
-            res = decltype(res)::dropped_and_recreated;
-          }
-        } else {
-          if (res != decltype(res)::old_columns_removed) {
-            res = decltype(res)::already_in_sync;
-          }
-        }
-      }
-    } else {
-      res = decltype(res)::new_table_created;
-    }
-    return res;
-  }
-
-private:
-  using self = storage_impl<H, Ts...>;
-};
-
-template <> struct storage_impl<> : storage_impl_base {
-
-  std::string find_table_name(std::type_index) const {
-    return {};
-  }
-
-  template <class L> void for_each(const L &) {
-  }
-
-  int foreign_keys_count() {
-    return 0;
-  }
-
-  template <class O> const void *find_table() const {
-    return nullptr;
-  }
-};
-
-template <class T> struct is_storage_impl : std::false_type {};
-
-template <class... Ts>
-struct is_storage_impl<storage_impl<Ts...>> : std::true_type {};
-} // namespace internal
-} // namespace sqlite_orm
-#pragma once
-
-#include <sqlite3.h>
-#include <algorithm>  //  std::find
-#include <cstddef>    //  std::ptrdiff_t
-#include <functional> //  std::function
-#include <iterator> //  std::input_iterator_tag, std::iterator_traits, std::distance
-#include <map>      //  std::map
-#include <memory>      //  std::unique/shared_ptr, std::make_unique/shared
-#include <sstream>     //  std::stringstream
-#include <string>      //  std::string
-#include <tuple>       //  std::tuple_size, std::tuple, std::make_tuple
-#include <type_traits> //  std::remove_reference, std::is_base_of, std::decay, std::false_type, std::true_type
-#include <utility>     //  std::forward, std::pair
-#include <vector>      //  std::vector
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-#include <optional> // std::optional
-#endif              // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-// #include "alias.h"
-
-// #include "row_extractor_builder.h"
-
-// #include "row_extractor.h"
-
-// #include "mapped_row_extractor.h"
-
-#include <sqlite3.h>
-
-// #include "object_from_column_builder.h"
-
-#include <sqlite3.h>
-
-// #include "row_extractor.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct object_from_column_builder_base {
-  sqlite3_stmt *stmt = nullptr;
-  mutable int index = 0;
-};
-
-/**
- * This is a cute lambda replacement which is used in several places.
- */
-template <class O>
-struct object_from_column_builder : object_from_column_builder_base {
-  using object_type = O;
-
-  object_type &object;
-
-  object_from_column_builder(object_type &object_, sqlite3_stmt *stmt_)
-      : object_from_column_builder_base{stmt_}, object(object_) {
-  }
-
-  template <class C> void operator()(const C &c) const {
-    using field_type = typename C::field_type;
-    auto value = row_extractor<field_type>().extract(this->stmt, this->index++);
-    if (c.member_pointer) {
-      this->object.*c.member_pointer = std::move(value);
-    } else {
-      ((this->object).*(c.setter))(std::move(value));
-    }
-  }
-};
-
-} // namespace internal
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- * This is a private row extractor class. It is used for extracting rows as
- * objects instead of tuple. Main difference from regular `row_extractor` is
- * that this class takes table info which is required for constructing objects
- * by member pointers. To construct please use `row_extractor_builder` class
- * Type arguments:
- * V is value type just like regular `row_extractor` has
- * T is table info class `table_t`
- */
-template <class V, class T> struct mapped_row_extractor {
-  using table_info_t = T;
-
-  mapped_row_extractor(const table_info_t &tableInfo_) : tableInfo(tableInfo_) {
-  }
-
-  V extract(sqlite3_stmt *stmt, int /*columnIndex*/) {
-    V res;
-    object_from_column_builder<V> builder{res, stmt};
-    this->tableInfo.for_each_column(builder);
-    return res;
-  }
-
-  const table_info_t &tableInfo;
-};
-
-} // namespace internal
-
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- * This builder is used to construct different row extractors depending on type.
- * It has two specializations: for mapped to storage types (e.g. User, Visit
- * etc) and for non-mapped (e.g. std::string, QString, int etc). For non mapped
- * its operator() returns generic `row_extractor`, for mapped it returns
- * `mapped_row_extractor` instance.
- */
-template <class T, bool IsMapped, class I> struct row_extractor_builder;
-
-template <class T, class I> struct row_extractor_builder<T, false, I> {
-
-  row_extractor<T> operator()(const I * /*tableInfo*/) const {
-    return {};
-  }
-};
-
-template <class T, class I> struct row_extractor_builder<T, true, I> {
-
-  mapped_row_extractor<T, I> operator()(const I *tableInfo) const {
-    return {*tableInfo};
-  }
-};
-
-template <class T, bool IsMapped, class I>
-auto make_row_extractor(const I *tableInfo) {
-  using builder_t = row_extractor_builder<T, IsMapped, I>;
-  return builder_t{}(tableInfo);
-}
-
-} // namespace internal
-
-} // namespace sqlite_orm
-
-// #include "error_code.h"
-
-// #include "type_printer.h"
-
-// #include "tuple_helper.h"
-
-// #include "constraints.h"
-
-// #include "type_is_nullable.h"
-
-// #include "field_printer.h"
-
-// #include "rowid.h"
-
-// #include "operators.h"
-
-// #include "select_constraints.h"
-
-// #include "core_functions.h"
-
-// #include "conditions.h"
-
-// #include "statement_binder.h"
-
-// #include "column_result.h"
-
-// #include "mapped_type_proxy.h"
-
-// #include "sync_schema_result.h"
-
-// #include "table_info.h"
-
-// #include "storage_impl.h"
-
-// #include "journal_mode.h"
-
-// #include "field_value_holder.h"
-
-// #include "view.h"
-
-#include <sqlite3.h>
-#include <memory>       //  std::shared_ptr
-#include <string>       //  std::string
-#include <system_error> //  std::system_error
-#include <tuple>        //  std::tuple, std::make_tuple
-#include <utility>      //  std::forward, std::move
-
-// #include "row_extractor.h"
-
-// #include "statement_finalizer.h"
-
-// #include "error_code.h"
-
-// #include "iterator.h"
-
-#include <sqlite3.h>
-#include <cstddef>      //  std::ptrdiff_t
-#include <ios>          //  std::make_error_code
-#include <iterator>     //  std::input_iterator_tag
-#include <memory>       //  std::shared_ptr, std::unique_ptr, std::make_shared
-#include <system_error> //  std::system_error
-#include <type_traits>  //  std::decay
-#include <utility>      //  std::move
-
-// #include "row_extractor.h"
-
-// #include "statement_finalizer.h"
-
-// #include "error_code.h"
-
-// #include "object_from_column_builder.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class V> struct iterator_t {
-  using view_type = V;
-  using value_type = typename view_type::mapped_type;
-
-protected:
-  /**
-   *  The double-indirection is so that copies of the iterator
-   *  share the same sqlite3_stmt from a sqlite3_prepare_v2()
-   *  call. When one finishes iterating it the pointer
-   *  inside the shared_ptr is nulled out in all copies.
-   */
-  std::shared_ptr<sqlite3_stmt *> stmt;
-  view_type &view;
-
-  /**
-   *  shared_ptr is used over unique_ptr here
-   *  so that the iterator can be copyable.
-   */
-  std::shared_ptr<value_type> current;
-
-  void extract_value(std::unique_ptr<value_type> &temp) {
-    temp = std::make_unique<value_type>();
-    auto &storage = this->view.storage;
-    auto &impl = storage.template get_impl<value_type>();
-    object_from_column_builder<value_type> builder{*temp, *this->stmt};
-    impl.table.for_each_column(builder);
-  }
-
-public:
-  using difference_type = std::ptrdiff_t;
-  using pointer = value_type *;
-  using reference = value_type &;
-  using iterator_category = std::input_iterator_tag;
-
-  iterator_t(sqlite3_stmt *stmt_, view_type &view_)
-      : stmt(std::make_shared<sqlite3_stmt *>(stmt_)), view(view_) {
-    this->operator++();
-  }
-
-  iterator_t(const iterator_t &) = default;
-
-  iterator_t(iterator_t &&) = default;
-
-  iterator_t &operator=(iterator_t &&) = default;
-
-  iterator_t &operator=(const iterator_t &) = default;
-
-  ~iterator_t() {
-    if (this->stmt) {
-      statement_finalizer f{*this->stmt};
-    }
-  }
-
-  value_type &operator*() {
-    if (!this->stmt) {
-      throw std::system_error(std::make_error_code(
-          orm_error_code::trying_to_dereference_null_iterator));
-    }
-    if (!this->current) {
-      std::unique_ptr<value_type> value;
-      this->extract_value(value);
-      this->current = move(value);
-    }
-    return *this->current;
-  }
-
-  value_type *operator->() {
-    return &(this->operator*());
-  }
-
-  void operator++() {
-    if (this->stmt && *this->stmt) {
-      auto ret = sqlite3_step(*this->stmt);
-      switch (ret) {
-      case SQLITE_ROW:
-        this->current = nullptr;
-        break;
-      case SQLITE_DONE: {
-        statement_finalizer f{*this->stmt};
-        *this->stmt = nullptr;
-      } break;
-      default: {
-        auto db = this->view.connection.get();
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-      }
-    }
-  }
-
-  void operator++(int) {
-    this->operator++();
-  }
-
-  bool operator==(const iterator_t &other) const {
-    if (this->stmt && other.stmt) {
-      return *this->stmt == *other.stmt;
-    } else {
-      if (!this->stmt && !other.stmt) {
-        return true;
-      } else {
-        return false;
-      }
-    }
-  }
-
-  bool operator!=(const iterator_t &other) const {
-    return !(*this == other);
-  }
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "ast_iterator.h"
-
-#include <functional> //  std::reference_wrapper
-#include <vector>     //  std::vector
-
-// #include "conditions.h"
-
-// #include "select_constraints.h"
-
-// #include "operators.h"
-
-// #include "tuple_helper.h"
-
-// #include "core_functions.h"
-
-// #include "prepared_statement.h"
-
-#include <sqlite3.h>
-#include <iterator>    //  std::iterator_traits
-#include <string>      //  std::string
-#include <type_traits> //  std::true_type, std::false_type
-#include <utility>     //  std::pair
-
-// #include "connection_holder.h"
-
-#include <sqlite3.h>
-#include <string>       //  std::string
-#include <system_error> //  std::system_error
-
-// #include "error_code.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct connection_holder {
-
-  connection_holder(std::string filename_) : filename(move(filename_)) {
-  }
-
-  void retain() {
-    ++this->_retain_count;
-    if (1 == this->_retain_count) {
-      auto rc = sqlite3_open(this->filename.c_str(), &this->db);
-      if (rc != SQLITE_OK) {
-        throw std::system_error(
-            std::error_code(
-                sqlite3_errcode(this->db), get_sqlite_error_category()),
-            sqlite3_errmsg(this->db));
-      }
-    }
-  }
-
-  void release() {
-    --this->_retain_count;
-    if (0 == this->_retain_count) {
-      auto rc = sqlite3_close(this->db);
-      if (rc != SQLITE_OK) {
-        throw std::system_error(
-            std::error_code(
-                sqlite3_errcode(this->db), get_sqlite_error_category()),
-            sqlite3_errmsg(this->db));
-      }
-    }
-  }
-
-  sqlite3 *get() const {
-    return this->db;
-  }
-
-  int retain_count() const {
-    return this->_retain_count;
-  }
-
-  const std::string filename;
-
-protected:
-  sqlite3 *db = nullptr;
-  int _retain_count = 0;
-};
-
-struct connection_ref {
-  connection_ref(connection_holder &holder_) : holder(holder_) {
-    this->holder.retain();
-  }
-
-  connection_ref(const connection_ref &other) : holder(other.holder) {
-    this->holder.retain();
-  }
-
-  connection_ref(connection_ref &&other) : holder(other.holder) {
-    this->holder.retain();
-  }
-
-  ~connection_ref() {
-    this->holder.release();
-  }
-
-  sqlite3 *get() const {
-    return this->holder.get();
-  }
-
-protected:
-  connection_holder &holder;
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "select_constraints.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct prepared_statement_base {
-  sqlite3_stmt *stmt = nullptr;
-  connection_ref con;
-
-  ~prepared_statement_base() {
-    if (this->stmt) {
-      sqlite3_finalize(this->stmt);
-      this->stmt = nullptr;
-    }
-  }
-
-  std::string sql() const {
-    if (this->stmt) {
-      if (auto res = sqlite3_sql(this->stmt)) {
-        return res;
-      } else {
-        return {};
-      }
-    } else {
-      return {};
-    }
-  }
-
-#if SQLITE_VERSION_NUMBER >= 3014000
-  std::string expanded_sql() const {
-    if (this->stmt) {
-      if (auto res = sqlite3_expanded_sql(this->stmt)) {
-        std::string result = res;
-        sqlite3_free(res);
-        return result;
-      } else {
-        return {};
-      }
-    } else {
-      return {};
-    }
-  }
-#endif
-#if SQLITE_VERSION_NUMBER >= 3026000 and defined(SQLITE_ENABLE_NORMALIZE)
-  std::string normalized_sql() const {
-    if (this->stmt) {
-      if (auto res = sqlite3_normalized_sql(this->stmt)) {
-        return res;
-      } else {
-        return {};
-      }
-    } else {
-      return {};
-    }
-  }
-#endif
-};
-
-template <class T> struct prepared_statement_t : prepared_statement_base {
-  using expression_type = T;
-
-  expression_type t;
-
-  prepared_statement_t(T t_, sqlite3_stmt *stmt_, connection_ref con_)
-      : prepared_statement_base{stmt_, std::move(con_)}, t(std::move(t_)) {
-  }
-};
-
-template <class T> struct is_prepared_statement : std::false_type {};
-
-template <class T>
-struct is_prepared_statement<prepared_statement_t<T>> : std::true_type {};
-
-/**
- *  T - type of object to obtain from a database
- */
-template <class T, class R, class... Args> struct get_all_t {
-  using type = T;
-  using return_type = R;
-
-  using conditions_type = std::tuple<Args...>;
-
-  conditions_type conditions;
-};
-
-template <class T, class R, class... Args> struct get_all_pointer_t {
-  using type = T;
-  using return_type = R;
-
-  using conditions_type = std::tuple<Args...>;
-
-  conditions_type conditions;
-};
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <class T, class R, class... Args> struct get_all_optional_t {
-  using type = T;
-  using return_type = R;
-
-  using conditions_type = std::tuple<Args...>;
-
-  conditions_type conditions;
-};
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-template <class T, class... Wargs> struct update_all_t;
-
-template <class... Args, class... Wargs>
-struct update_all_t<set_t<Args...>, Wargs...> {
-  using set_type = set_t<Args...>;
-  using conditions_type = std::tuple<Wargs...>;
-
-  set_type set;
-  conditions_type conditions;
-};
-
-template <class T, class... Args> struct remove_all_t {
-  using type = T;
-  using conditions_type = std::tuple<Args...>;
-
-  conditions_type conditions;
-};
-
-template <class T, class... Ids> struct get_t {
-  using type = T;
-  using ids_type = std::tuple<Ids...>;
-
-  ids_type ids;
-};
-
-template <class T, class... Ids> struct get_pointer_t {
-  using type = T;
-  using ids_type = std::tuple<Ids...>;
-
-  ids_type ids;
-};
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <class T, class... Ids> struct get_optional_t {
-  using type = T;
-  using ids_type = std::tuple<Ids...>;
-
-  ids_type ids;
-};
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-template <class T> struct update_t {
-  using type = T;
-
-  type obj;
-};
-
-template <class T, class... Ids> struct remove_t {
-  using type = T;
-  using ids_type = std::tuple<Ids...>;
-
-  ids_type ids;
-};
-
-template <class T> struct insert_t {
-  using type = T;
-
-  type obj;
-};
-
-template <class T, class... Cols> struct insert_explicit {
-  using type = T;
-  using columns_type = columns_t<Cols...>;
-
-  type obj;
-  columns_type columns;
-};
-
-template <class T> struct replace_t {
-  using type = T;
-
-  type obj;
-};
-
-template <class It> struct insert_range_t {
-  using iterator_type = It;
-  using object_type = typename std::iterator_traits<iterator_type>::value_type;
-
-  std::pair<iterator_type, iterator_type> range;
-};
-
-template <class It> struct replace_range_t {
-  using iterator_type = It;
-  using object_type = typename std::iterator_traits<iterator_type>::value_type;
-
-  std::pair<iterator_type, iterator_type> range;
-};
-} // namespace internal
-
-/**
- *  Create a replace range statement
- */
-template <class It>
-internal::replace_range_t<It> replace_range(It from, It to) {
-  return {{std::move(from), std::move(to)}};
-}
-
-/**
- *  Create an insert range statement
- */
-template <class It> internal::insert_range_t<It> insert_range(It from, It to) {
-  return {{std::move(from), std::move(to)}};
-}
-
-/**
- *  Create a replace statement.
- *  T is an object type mapped to a storage.
- *  Usage: storage.replace(myUserInstance);
- *  Parameter obj is accepted by value. If you want to accept it by ref
- *  please use std::ref function: storage.replace(std::ref(myUserInstance));
- */
-template <class T> internal::replace_t<T> replace(T obj) {
-  return {std::move(obj)};
-}
-
-/**
- *  Create an insert statement.
- *  T is an object type mapped to a storage.
- *  Usage: storage.insert(myUserInstance);
- *  Parameter obj is accepted by value. If you want to accept it by ref
- *  please use std::ref function: storage.insert(std::ref(myUserInstance));
- */
-template <class T> internal::insert_t<T> insert(T obj) {
-  return {std::move(obj)};
-}
-
-/**
- *  Create an explicit insert statement.
- *  T is an object type mapped to a storage.
- *  Cols is columns types aparameter pack. Must contain member pointers
- *  Usage: storage.insert(myUserInstance, columns(&User::id, &User::name));
- *  Parameter obj is accepted by value. If you want to accept it by ref
- *  please use std::ref function: storage.insert(std::ref(myUserInstance),
- * columns(&User::id, &User::name));
- */
-template <class T, class... Cols>
-internal::insert_explicit<T, Cols...>
-insert(T obj, internal::columns_t<Cols...> cols) {
-  return {std::move(obj), std::move(cols)};
-}
-
-/**
- *  Create a remove statement
- *  T is an object type mapped to a storage.
- *  Usage: remove<User>(5);
- */
-template <class T, class... Ids>
-internal::remove_t<T, Ids...> remove(Ids... ids) {
-  std::tuple<Ids...> idsTuple{std::forward<Ids>(ids)...};
-  return {move(idsTuple)};
-}
-
-/**
- *  Create an update statement.
- *  T is an object type mapped to a storage.
- *  Usage: storage.update(myUserInstance);
- *  Parameter obj is accepted by value. If you want to accept it by ref
- *  please use std::ref function: storage.update(std::ref(myUserInstance));
- */
-template <class T> internal::update_t<T> update(T obj) {
-  return {std::move(obj)};
-}
-
-/**
- *  Create a get statement.
- *  T is an object type mapped to a storage.
- *  Usage: get<User>(5);
- */
-template <class T, class... Ids> internal::get_t<T, Ids...> get(Ids... ids) {
-  std::tuple<Ids...> idsTuple{std::forward<Ids>(ids)...};
-  return {move(idsTuple)};
-}
-
-/**
- *  Create a get pointer statement.
- *  T is an object type mapped to a storage.
- *  Usage: get_pointer<User>(5);
- */
-template <class T, class... Ids>
-internal::get_pointer_t<T, Ids...> get_pointer(Ids... ids) {
-  std::tuple<Ids...> idsTuple{std::forward<Ids>(ids)...};
-  return {move(idsTuple)};
-}
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-/**
- *  Create a get optional statement.
- *  T is an object type mapped to a storage.
- *  Usage: get_optional<User>(5);
- */
-template <class T, class... Ids>
-internal::get_optional_t<T, Ids...> get_optional(Ids... ids) {
-  std::tuple<Ids...> idsTuple{std::forward<Ids>(ids)...};
-  return {move(idsTuple)};
-}
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-/**
- *  Create a remove all statement.
- *  T is an object type mapped to a storage.
- *  Usage: storage.remove_all<User>(...);
- */
-template <class T, class... Args>
-internal::remove_all_t<T, Args...> remove_all(Args... args) {
-  using args_tuple = std::tuple<Args...>;
-  internal::validate_conditions<args_tuple>();
-  args_tuple conditions{std::forward<Args>(args)...};
-  return {move(conditions)};
-}
-
-/**
- *  Create a get all statement.
- *  T is an object type mapped to a storage.
- *  Usage: storage.get_all<User>(...);
- */
-template <class T, class... Args>
-internal::get_all_t<T, std::vector<T>, Args...> get_all(Args... args) {
-  using args_tuple = std::tuple<Args...>;
-  internal::validate_conditions<args_tuple>();
-  args_tuple conditions{std::forward<Args>(args)...};
-  return {move(conditions)};
-}
-
-/**
- *  Create a get all statement.
- *  T is an object type mapped to a storage.
- *  R is a container type. std::vector<T> is default
- *  Usage: storage.get_all<User>(...);
- */
-template <class T, class R, class... Args>
-internal::get_all_t<T, R, Args...> get_all(Args... args) {
-  using args_tuple = std::tuple<Args...>;
-  internal::validate_conditions<args_tuple>();
-  args_tuple conditions{std::forward<Args>(args)...};
-  return {move(conditions)};
-}
-
-/**
- *  Create an update all statement.
- *  Usage: storage.update_all(set(...), ...);
- */
-template <class... Args, class... Wargs>
-internal::update_all_t<internal::set_t<Args...>, Wargs...>
-update_all(internal::set_t<Args...> set, Wargs... wh) {
-  using args_tuple = std::tuple<Wargs...>;
-  internal::validate_conditions<args_tuple>();
-  args_tuple conditions{std::forward<Wargs>(wh)...};
-  return {std::move(set), move(conditions)};
-}
-
-/**
- *  Create a get all pointer statement.
- *  T is an object type mapped to a storage.
- *  Usage: storage.get_all_pointer<User>(...);
- */
-template <class T, class... Args>
-internal::get_all_pointer_t<T, std::vector<std::unique_ptr<T>>, Args...>
-get_all_pointer(Args... args) {
-  using args_tuple = std::tuple<Args...>;
-  internal::validate_conditions<args_tuple>();
-  args_tuple conditions{std::forward<Args>(args)...};
-  return {move(conditions)};
-}
-/**
- *  Create a get all pointer statement.
- *  T is an object type mapped to a storage.
- *  R is a container return type. std::vector<std::unique_ptr<T>> is default
- *  Usage: storage.get_all_pointer<User>(...);
- */
-template <class T, class R, class... Args>
-internal::get_all_pointer_t<T, R, Args...> get_all_pointer(Args... args) {
-  using args_tuple = std::tuple<Args...>;
-  internal::validate_conditions<args_tuple>();
-  args_tuple conditions{std::forward<Args>(args)...};
-  return {move(conditions)};
-}
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-/**
- *  Create a get all optional statement.
- *  T is an object type mapped to a storage.
- *  Usage: storage.get_all_optional<User>(...);
- */
-template <class T, class... Args>
-internal::get_all_optional_t<T, std::vector<std::optional<T>>, Args...>
-get_all_optional(Args... args) {
-  using args_tuple = std::tuple<Args...>;
-  internal::validate_conditions<args_tuple>();
-  args_tuple conditions{std::forward<Args>(args)...};
-  return {move(conditions)};
-}
-
-/**
- *  Create a get all optional statement.
- *  T is an object type mapped to a storage.
- *  R is a container return type. std::vector<std::optional<T>> is default
- *  Usage: storage.get_all_optional<User>(...);
- */
-template <class T, class R, class... Args>
-internal::get_all_optional_t<T, R, Args...> get_all_optional(Args... args) {
-  using args_tuple = std::tuple<Args...>;
-  internal::validate_conditions<args_tuple>();
-  args_tuple conditions{std::forward<Args>(args)...};
-  return {move(conditions)};
-}
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-} // namespace sqlite_orm
-
-// #include "values.h"
-
-#include <initializer_list>
-#include <tuple>  //  std::tuple
-#include <vector> //  std::vector
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class... Args> struct values_t { std::tuple<Args...> tuple; };
-
-template <class T> struct dynamic_values_t { std::vector<T> vector; };
-
-} // namespace internal
-
-template <class... Args> internal::values_t<Args...> values(Args... args) {
-  return {{std::forward<Args>(args)...}};
-}
-
-template <class T> internal::dynamic_values_t<T> values(std::vector<T> vector) {
-  return {{move(vector)}};
-}
-
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- *  ast_iterator accepts any expression and a callable object
- *  which will be called for any node of provided expression.
- *  E.g. if we pass `where(is_equal(5, max(&User::id, 10))` then
- *  callable object will be called with 5, &User::id and 10.
- *  ast_iterator is used mostly in finding literals to be bound to
- *  a statement. To use it just call `iterate_ast(object, callable);`
- *  T is an ast element. E.g. where_t
- */
-template <class T, class SFINAE = void> struct ast_iterator {
-  using node_type = T;
-
-  /**
-   *  L is a callable type. Mostly is a templated lambda
-   */
-  template <class L> void operator()(const T &t, const L &l) const {
-    l(t);
-  }
-};
-
-/**
- *  Simplified API
- */
-template <class T, class L> void iterate_ast(const T &t, const L &l) {
-  ast_iterator<T> iterator;
-  iterator(t, l);
-}
-
-template <class T> struct ast_iterator<std::reference_wrapper<T>, void> {
-  using node_type = std::reference_wrapper<T>;
-
-  template <class L> void operator()(const node_type &r, const L &l) const {
-    iterate_ast(r.get(), l);
-  }
-};
-
-template <class C> struct ast_iterator<where_t<C>, void> {
-  using node_type = where_t<C>;
-
-  template <class L> void operator()(const node_type &where, const L &l) const {
-    iterate_ast(where.c, l);
-  }
-};
-
-template <class T>
-struct ast_iterator<
-    T,
-    typename std::enable_if<
-        is_base_of_template<T, binary_condition>::value>::type> {
-  using node_type = T;
-
-  template <class L>
-  void operator()(const node_type &binaryCondition, const L &l) const {
-    iterate_ast(binaryCondition.l, l);
-    iterate_ast(binaryCondition.r, l);
-  }
-};
-
-template <class L, class R, class... Ds>
-struct ast_iterator<binary_operator<L, R, Ds...>, void> {
-  using node_type = binary_operator<L, R, Ds...>;
-
-  template <class C>
-  void operator()(const node_type &binaryOperator, const C &l) const {
-    iterate_ast(binaryOperator.lhs, l);
-    iterate_ast(binaryOperator.rhs, l);
-  }
-};
-
-template <class... Args> struct ast_iterator<columns_t<Args...>, void> {
-  using node_type = columns_t<Args...>;
-
-  template <class L> void operator()(const node_type &cols, const L &l) const {
-    iterate_ast(cols.columns, l);
-  }
-};
-
-template <class L, class A> struct ast_iterator<in_t<L, A>, void> {
-  using node_type = in_t<L, A>;
-
-  template <class C> void operator()(const node_type &in, const C &l) const {
-    iterate_ast(in.l, l);
-    iterate_ast(in.arg, l);
-  }
-};
-
-template <class T> struct ast_iterator<std::vector<T>, void> {
-  using node_type = std::vector<T>;
-
-  template <class L> void operator()(const node_type &vec, const L &l) const {
-    for (auto &i : vec) {
-      iterate_ast(i, l);
-    }
-  }
-};
-
-template <> struct ast_iterator<std::vector<char>, void> {
-  using node_type = std::vector<char>;
-
-  template <class L> void operator()(const node_type &vec, const L &l) const {
-    l(vec);
-  }
-};
-
-template <class T>
-struct ast_iterator<
-    T,
-    typename std::enable_if<
-        is_base_of_template<T, compound_operator>::value>::type> {
-  using node_type = T;
-
-  template <class L> void operator()(const node_type &c, const L &l) const {
-    iterate_ast(c.left, l);
-    iterate_ast(c.right, l);
-  }
-};
-
-template <class T, class... Args>
-struct ast_iterator<select_t<T, Args...>, void> {
-  using node_type = select_t<T, Args...>;
-
-  template <class L> void operator()(const node_type &sel, const L &l) const {
-    iterate_ast(sel.col, l);
-    iterate_ast(sel.conditions, l);
-  }
-};
-
-template <class T, class R, class... Args>
-struct ast_iterator<get_all_t<T, R, Args...>, void> {
-  using node_type = get_all_t<T, R, Args...>;
-
-  template <class L> void operator()(const node_type &get, const L &l) const {
-    iterate_ast(get.conditions, l);
-  }
-};
-
-template <class T, class... Args>
-struct ast_iterator<get_all_pointer_t<T, Args...>, void> {
-  using node_type = get_all_pointer_t<T, Args...>;
-
-  template <class L> void operator()(const node_type &get, const L &l) const {
-    iterate_ast(get.conditions, l);
-  }
-};
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <class T, class... Args>
-struct ast_iterator<get_all_optional_t<T, Args...>, void> {
-  using node_type = get_all_optional_t<T, Args...>;
-
-  template <class L> void operator()(const node_type &get, const L &l) const {
-    iterate_ast(get.conditions, l);
-  }
-};
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-template <class... Args, class... Wargs>
-struct ast_iterator<update_all_t<set_t<Args...>, Wargs...>, void> {
-  using node_type = update_all_t<set_t<Args...>, Wargs...>;
-
-  template <class L> void operator()(const node_type &u, const L &l) const {
-    iterate_ast(u.set, l);
-    iterate_ast(u.conditions, l);
-  }
-};
-
-template <class T, class... Args>
-struct ast_iterator<remove_all_t<T, Args...>, void> {
-  using node_type = remove_all_t<T, Args...>;
-
-  template <class L> void operator()(const node_type &r, const L &l) const {
-    iterate_ast(r.conditions, l);
-  }
-};
-
-template <class... Args> struct ast_iterator<set_t<Args...>, void> {
-  using node_type = set_t<Args...>;
-
-  template <class L> void operator()(const node_type &s, const L &l) const {
-    iterate_ast(s.assigns, l);
-  }
-};
-
-template <class... Args> struct ast_iterator<std::tuple<Args...>, void> {
-  using node_type = std::tuple<Args...>;
-
-  template <class L> void operator()(const node_type &tuple, const L &l) const {
-    iterate_tuple(tuple, [&l](auto &v) { iterate_ast(v, l); });
-  }
-};
-
-template <class T> struct ast_iterator<having_t<T>, void> {
-  using node_type = having_t<T>;
-
-  template <class L> void operator()(const node_type &hav, const L &l) const {
-    iterate_ast(hav.t, l);
-  }
-};
-
-template <class T, class E> struct ast_iterator<cast_t<T, E>, void> {
-  using node_type = cast_t<T, E>;
-
-  template <class L> void operator()(const node_type &c, const L &l) const {
-    iterate_ast(c.expression, l);
-  }
-};
-
-template <class T> struct ast_iterator<exists_t<T>, void> {
-  using node_type = exists_t<T>;
-
-  template <class L> void operator()(const node_type &e, const L &l) const {
-    iterate_ast(e.t, l);
-  }
-};
-
-template <class A, class T, class E>
-struct ast_iterator<like_t<A, T, E>, void> {
-  using node_type = like_t<A, T, E>;
-
-  template <class L> void operator()(const node_type &lk, const L &l) const {
-    iterate_ast(lk.arg, l);
-    iterate_ast(lk.pattern, l);
-    lk.arg3.apply([&l](auto &value) { iterate_ast(value, l); });
-  }
-};
-
-template <class A, class T> struct ast_iterator<glob_t<A, T>, void> {
-  using node_type = glob_t<A, T>;
-
-  template <class L> void operator()(const node_type &lk, const L &l) const {
-    iterate_ast(lk.arg, l);
-    iterate_ast(lk.pattern, l);
-  }
-};
-
-template <class A, class T> struct ast_iterator<between_t<A, T>, void> {
-  using node_type = between_t<A, T>;
-
-  template <class L> void operator()(const node_type &b, const L &l) const {
-    iterate_ast(b.expr, l);
-    iterate_ast(b.b1, l);
-    iterate_ast(b.b2, l);
-  }
-};
-
-template <class T> struct ast_iterator<named_collate<T>, void> {
-  using node_type = named_collate<T>;
-
-  template <class L> void operator()(const node_type &col, const L &l) const {
-    iterate_ast(col.expr, l);
-  }
-};
-
-template <class C> struct ast_iterator<negated_condition_t<C>, void> {
-  using node_type = negated_condition_t<C>;
-
-  template <class L> void operator()(const node_type &neg, const L &l) const {
-    iterate_ast(neg.c, l);
-  }
-};
-
-template <class T> struct ast_iterator<is_null_t<T>, void> {
-  using node_type = is_null_t<T>;
-
-  template <class L> void operator()(const node_type &i, const L &l) const {
-    iterate_ast(i.t, l);
-  }
-};
-
-template <class T> struct ast_iterator<is_not_null_t<T>, void> {
-  using node_type = is_not_null_t<T>;
-
-  template <class L> void operator()(const node_type &i, const L &l) const {
-    iterate_ast(i.t, l);
-  }
-};
-
-template <class R, class S, class... Args>
-struct ast_iterator<core_function_t<R, S, Args...>, void> {
-  using node_type = core_function_t<R, S, Args...>;
-
-  template <class L> void operator()(const node_type &f, const L &l) const {
-    iterate_ast(f.args, l);
-  }
-};
-
-template <class T, class O> struct ast_iterator<left_join_t<T, O>, void> {
-  using node_type = left_join_t<T, O>;
-
-  template <class L> void operator()(const node_type &j, const L &l) const {
-    iterate_ast(j.constraint, l);
-  }
-};
-
-template <class T> struct ast_iterator<on_t<T>, void> {
-  using node_type = on_t<T>;
-
-  template <class L> void operator()(const node_type &o, const L &l) const {
-    iterate_ast(o.arg, l);
-  }
-};
-
-template <class T, class O> struct ast_iterator<join_t<T, O>, void> {
-  using node_type = join_t<T, O>;
-
-  template <class L> void operator()(const node_type &j, const L &l) const {
-    iterate_ast(j.constraint, l);
-  }
-};
-
-template <class T, class O> struct ast_iterator<left_outer_join_t<T, O>, void> {
-  using node_type = left_outer_join_t<T, O>;
-
-  template <class L> void operator()(const node_type &j, const L &l) const {
-    iterate_ast(j.constraint, l);
-  }
-};
-
-template <class T, class O> struct ast_iterator<inner_join_t<T, O>, void> {
-  using node_type = inner_join_t<T, O>;
-
-  template <class L> void operator()(const node_type &j, const L &l) const {
-    iterate_ast(j.constraint, l);
-  }
-};
-
-template <class R, class T, class E, class... Args>
-struct ast_iterator<simple_case_t<R, T, E, Args...>, void> {
-  using node_type = simple_case_t<R, T, E, Args...>;
-
-  template <class L> void operator()(const node_type &c, const L &l) const {
-    c.case_expression.apply([&l](auto &c_) { iterate_ast(c_, l); });
-    iterate_tuple(c.args, [&l](auto &pair) {
-      iterate_ast(pair.first, l);
-      iterate_ast(pair.second, l);
-    });
-    c.else_expression.apply([&l](auto &el) { iterate_ast(el, l); });
-  }
-};
-
-template <class T, class E> struct ast_iterator<as_t<T, E>, void> {
-  using node_type = as_t<T, E>;
-
-  template <class L> void operator()(const node_type &a, const L &l) const {
-    iterate_ast(a.expression, l);
-  }
-};
-
-template <class T, bool OI>
-struct ast_iterator<limit_t<T, false, OI, void>, void> {
-  using node_type = limit_t<T, false, OI, void>;
-
-  template <class L> void operator()(const node_type &a, const L &l) const {
-    iterate_ast(a.lim, l);
-  }
-};
-
-template <class T, class O>
-struct ast_iterator<limit_t<T, true, false, O>, void> {
-  using node_type = limit_t<T, true, false, O>;
-
-  template <class L> void operator()(const node_type &a, const L &l) const {
-    iterate_ast(a.lim, l);
-    a.off.apply([&l](auto &value) { iterate_ast(value, l); });
-  }
-};
-
-template <class T, class O>
-struct ast_iterator<limit_t<T, true, true, O>, void> {
-  using node_type = limit_t<T, true, true, O>;
-
-  template <class L> void operator()(const node_type &a, const L &l) const {
-    a.off.apply([&l](auto &value) { iterate_ast(value, l); });
-    iterate_ast(a.lim, l);
-  }
-};
-
-template <class T> struct ast_iterator<distinct_t<T>, void> {
-  using node_type = distinct_t<T>;
-
-  template <class L> void operator()(const node_type &a, const L &l) const {
-    iterate_ast(a.t, l);
-  }
-};
-
-template <class T> struct ast_iterator<all_t<T>, void> {
-  using node_type = all_t<T>;
-
-  template <class L> void operator()(const node_type &a, const L &l) const {
-    iterate_ast(a.t, l);
-  }
-};
-
-template <class T> struct ast_iterator<bitwise_not_t<T>, void> {
-  using node_type = bitwise_not_t<T>;
-
-  template <class L> void operator()(const node_type &a, const L &l) const {
-    iterate_ast(a.argument, l);
-  }
-};
-
-template <class... Args> struct ast_iterator<values_t<Args...>, void> {
-  using node_type = values_t<Args...>;
-
-  template <class L> void operator()(const node_type &node, const L &l) const {
-    iterate_ast(node.tuple, l);
-  }
-};
-
-template <class T> struct ast_iterator<dynamic_values_t<T>, void> {
-  using node_type = dynamic_values_t<T>;
-
-  template <class L> void operator()(const node_type &node, const L &l) const {
-    iterate_ast(node.vector, l);
-  }
-};
-
-template <class T> struct ast_iterator<collate_t<T>, void> {
-  using node_type = collate_t<T>;
-
-  template <class L> void operator()(const node_type &node, const L &l) const {
-    iterate_ast(node.expr, l);
-  }
-};
-
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "prepared_statement.h"
-
-// #include "connection_holder.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class T, class S, class... Args> struct view_t {
-  using mapped_type = T;
-  using storage_type = S;
-  using self = view_t<T, S, Args...>;
-
-  storage_type &storage;
-  connection_ref connection;
-  get_all_t<T, std::vector<T>, Args...> args;
-
-  view_t(storage_type &stor, decltype(connection) conn, Args &&... args_)
-      : storage(stor),
-        connection(std::move(conn)),
-        args{std::make_tuple(std::forward<Args>(args_)...)} {
-  }
-
-  size_t size() {
-    return this->storage.template count<T>();
-  }
-
-  bool empty() {
-    return !this->size();
-  }
-
-  iterator_t<self> end() {
-    return {nullptr, *this};
-  }
-
-  iterator_t<self> begin() {
-    sqlite3_stmt *stmt = nullptr;
-    auto db = this->connection.get();
-    using context_t = serializator_context<typename storage_type::impl_type>;
-    context_t context{this->storage.impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(this->args, context);
-    auto ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr);
-    if (ret == SQLITE_OK) {
-      auto index = 1;
-      iterate_ast(this->args.conditions, [&index, stmt, db](auto &node) {
-        using node_type = typename std::decay<decltype(node)>::type;
-        conditional_binder<node_type, is_bindable<node_type>> binder{
-            stmt, index};
-        if (SQLITE_OK != binder(node)) {
-          throw std::system_error(
-              std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-              sqlite3_errmsg(db));
-        }
-      });
-      return {stmt, *this};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "ast_iterator.h"
-
-// #include "storage_base.h"
-
-#include <sqlite3.h>
-#include <algorithm>  //  std::iter_swap
-#include <functional> //  std::function, std::bind
-#include <map>        //  std::map
-#include <memory>     //  std::make_shared, std::shared_ptr
-#include <sstream>    //  std::stringstream
-#include <string>     //  std::string
-#include <system_error> //  std::system_error, std::error_code, std::make_error_code
-#include <type_traits> //  std::decay, std::is_same
-#include <utility>     //  std::move
-#include <vector>      //  std::vector
-
-// #include "pragma.h"
-
-#include <sqlite3.h>
-#include <functional> //  std::function
-#include <memory>     // std::shared_ptr
-#include <string>     //  std::string
-
-// #include "error_code.h"
-
-// #include "row_extractor.h"
-
-// #include "journal_mode.h"
-
-// #include "connection_holder.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-struct storage_base;
-}
-
-struct pragma_t {
-  using get_connection_t = std::function<internal::connection_ref()>;
-
-  pragma_t(get_connection_t get_connection_)
-      : get_connection(std::move(get_connection_)) {
-  }
-
-  void busy_timeout(int value) {
-    this->set_pragma("busy_timeout", value);
-  }
-
-  int busy_timeout() {
-    return this->get_pragma<int>("busy_timeout");
-  }
-
-  sqlite_orm::journal_mode journal_mode() {
-    return this->get_pragma<sqlite_orm::journal_mode>("journal_mode");
-  }
-
-  void journal_mode(sqlite_orm::journal_mode value) {
-    this->_journal_mode = -1;
-    this->set_pragma("journal_mode", value);
-    this->_journal_mode = static_cast<decltype(this->_journal_mode)>(value);
-  }
-
-  int synchronous() {
-    return this->get_pragma<int>("synchronous");
-  }
-
-  void synchronous(int value) {
-    this->_synchronous = -1;
-    this->set_pragma("synchronous", value);
-    this->_synchronous = value;
-  }
-
-  int user_version() {
-    return this->get_pragma<int>("user_version");
-  }
-
-  void user_version(int value) {
-    this->set_pragma("user_version", value);
-  }
-
-  int auto_vacuum() {
-    return this->get_pragma<int>("auto_vacuum");
-  }
-
-  void auto_vacuum(int value) {
-    this->set_pragma("auto_vacuum", value);
-  }
-
-protected:
-  friend struct storage_base;
-
-public:
-  int _synchronous = -1;
-  signed char _journal_mode =
-      -1; //  if != -1 stores
-          //  static_cast<sqlite_orm::journal_mode>(journal_mode)
-  get_connection_t get_connection;
-
-  template <class T> T get_pragma(const std::string &name) {
-    auto connection = this->get_connection();
-    auto query = "PRAGMA " + name;
-    T result;
-    auto db = connection.get();
-    auto rc = sqlite3_exec(
-        db,
-        query.c_str(),
-        [](void *data, int argc, char **argv, char **) -> int {
-          auto &res = *(T *)data;
-          if (argc) {
-            res = row_extractor<T>().extract(argv[0]);
-          }
-          return 0;
-        },
-        &result,
-        nullptr);
-    if (rc == SQLITE_OK) {
-      return result;
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  /**
-   *  Yevgeniy Zakharov: I wanted to refactore this function with statements and
-   * value bindings but it turns out that bindings in pragma statements are not
-   * supported.
-   */
-  template <class T>
-  void
-  set_pragma(const std::string &name, const T &value, sqlite3 *db = nullptr) {
-    auto con = this->get_connection();
-    if (!db) {
-      db = con.get();
-    }
-    std::stringstream ss;
-    ss << "PRAGMA " << name << " = " << value;
-    auto query = ss.str();
-    auto rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr);
-    if (rc != SQLITE_OK) {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  void set_pragma(
-      const std::string &name,
-      const sqlite_orm::journal_mode &value,
-      sqlite3 *db = nullptr) {
-    auto con = this->get_connection();
-    if (!db) {
-      db = con.get();
-    }
-    std::stringstream ss;
-    ss << "PRAGMA " << name << " = " << internal::to_string(value);
-    auto query = ss.str();
-    auto rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr);
-    if (rc != SQLITE_OK) {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-};
-} // namespace sqlite_orm
-
-// #include "limit_accesor.h"
-
-#include <sqlite3.h>
-#include <functional> //  std::function
-#include <map>        //  std::map
-#include <memory>     //  std::shared_ptr
-
-// #include "connection_holder.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct limit_accesor {
-  using get_connection_t = std::function<connection_ref()>;
-
-  limit_accesor(get_connection_t get_connection_)
-      : get_connection(std::move(get_connection_)) {
-  }
-
-  int length() {
-    return this->get(SQLITE_LIMIT_LENGTH);
-  }
-
-  void length(int newValue) {
-    this->set(SQLITE_LIMIT_LENGTH, newValue);
-  }
-
-  int sql_length() {
-    return this->get(SQLITE_LIMIT_SQL_LENGTH);
-  }
-
-  void sql_length(int newValue) {
-    this->set(SQLITE_LIMIT_SQL_LENGTH, newValue);
-  }
-
-  int column() {
-    return this->get(SQLITE_LIMIT_COLUMN);
-  }
-
-  void column(int newValue) {
-    this->set(SQLITE_LIMIT_COLUMN, newValue);
-  }
-
-  int expr_depth() {
-    return this->get(SQLITE_LIMIT_EXPR_DEPTH);
-  }
-
-  void expr_depth(int newValue) {
-    this->set(SQLITE_LIMIT_EXPR_DEPTH, newValue);
-  }
-
-  int compound_select() {
-    return this->get(SQLITE_LIMIT_COMPOUND_SELECT);
-  }
-
-  void compound_select(int newValue) {
-    this->set(SQLITE_LIMIT_COMPOUND_SELECT, newValue);
-  }
-
-  int vdbe_op() {
-    return this->get(SQLITE_LIMIT_VDBE_OP);
-  }
-
-  void vdbe_op(int newValue) {
-    this->set(SQLITE_LIMIT_VDBE_OP, newValue);
-  }
-
-  int function_arg() {
-    return this->get(SQLITE_LIMIT_FUNCTION_ARG);
-  }
-
-  void function_arg(int newValue) {
-    this->set(SQLITE_LIMIT_FUNCTION_ARG, newValue);
-  }
-
-  int attached() {
-    return this->get(SQLITE_LIMIT_ATTACHED);
-  }
-
-  void attached(int newValue) {
-    this->set(SQLITE_LIMIT_ATTACHED, newValue);
-  }
-
-  int like_pattern_length() {
-    return this->get(SQLITE_LIMIT_LIKE_PATTERN_LENGTH);
-  }
-
-  void like_pattern_length(int newValue) {
-    this->set(SQLITE_LIMIT_LIKE_PATTERN_LENGTH, newValue);
-  }
-
-  int variable_number() {
-    return this->get(SQLITE_LIMIT_VARIABLE_NUMBER);
-  }
-
-  void variable_number(int newValue) {
-    this->set(SQLITE_LIMIT_VARIABLE_NUMBER, newValue);
-  }
-
-  int trigger_depth() {
-    return this->get(SQLITE_LIMIT_TRIGGER_DEPTH);
-  }
-
-  void trigger_depth(int newValue) {
-    this->set(SQLITE_LIMIT_TRIGGER_DEPTH, newValue);
-  }
-
-#if SQLITE_VERSION_NUMBER >= 3008007
-  int worker_threads() {
-    return this->get(SQLITE_LIMIT_WORKER_THREADS);
-  }
-
-  void worker_threads(int newValue) {
-    this->set(SQLITE_LIMIT_WORKER_THREADS, newValue);
-  }
-#endif
-
-protected:
-  get_connection_t get_connection;
-
-  friend struct storage_base;
-
-  /**
-   *  Stores limit set between connections.
-   */
-  std::map<int, int> limits;
-
-  int get(int id) {
-    auto connection = this->get_connection();
-    return sqlite3_limit(connection.get(), id, -1);
-  }
-
-  void set(int id, int newValue) {
-    this->limits[id] = newValue;
-    auto connection = this->get_connection();
-    sqlite3_limit(connection.get(), id, newValue);
-  }
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "transaction_guard.h"
-
-#include <functional> //  std::function
-
-// #include "connection_holder.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- *  Class used as a guard for a transaction. Calls `ROLLBACK` in destructor.
- *  Has explicit `commit()` and `rollback()` functions. After explicit function
- * is fired guard won't do anything in d-tor. Also you can set
- * `commit_on_destroy` to true to make it call `COMMIT` on destroy.
- */
-struct transaction_guard_t {
-  /**
-   *  This is a public lever to tell a guard what it must do in its destructor
-   *  if `gotta_fire` is true
-   */
-  bool commit_on_destroy = false;
-
-  transaction_guard_t(
-      connection_ref connection_,
-      std::function<void()> commit_func_,
-      std::function<void()> rollback_func_)
-      : connection(std::move(connection_)),
-        commit_func(std::move(commit_func_)),
-        rollback_func(std::move(rollback_func_)) {
-  }
-
-  ~transaction_guard_t() {
-    if (this->gotta_fire) {
-      if (!this->commit_on_destroy) {
-        this->rollback_func();
-      } else {
-        this->commit_func();
-      }
-    }
-  }
-
-  /**
-   *  Call `COMMIT` explicitly. After this call
-   *  guard will not call `COMMIT` or `ROLLBACK`
-   *  in its destructor.
-   */
-  void commit() {
-    this->commit_func();
-    this->gotta_fire = false;
-  }
-
-  /**
-   *  Call `ROLLBACK` explicitly. After this call
-   *  guard will not call `COMMIT` or `ROLLBACK`
-   *  in its destructor.
-   */
-  void rollback() {
-    this->rollback_func();
-    this->gotta_fire = false;
-  }
-
-protected:
-  connection_ref connection;
-  std::function<void()> commit_func;
-  std::function<void()> rollback_func;
-  bool gotta_fire = true;
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "statement_finalizer.h"
-
-// #include "type_printer.h"
-
-// #include "tuple_helper.h"
-
-// #include "row_extractor.h"
-
-// #include "connection_holder.h"
-
-// #include "backup.h"
-
-#include <sqlite3.h>
-#include <memory>
-#include <string> //  std::string
-
-// #include "error_code.h"
-
-// #include "connection_holder.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- *  A backup class. Don't construct it as is, call storage.make_backup_from or
- * storage.make_backup_to instead. An instance of this class represents a
- * wrapper around sqlite3_backup pointer. Use this class to have maximum control
- * on a backup operation. In case you need a single backup in one line you can
- * skip creating a backup_t instance and just call storage.backup_from or
- * storage.backup_to function.
- */
-struct backup_t {
-  backup_t(
-      connection_ref to_,
-      const std::string &zDestName,
-      connection_ref from_,
-      const std::string &zSourceName,
-      std::unique_ptr<connection_holder> holder_)
-      : handle(sqlite3_backup_init(
-            to_.get(),
-            zDestName.c_str(),
-            from_.get(),
-            zSourceName.c_str())),
-        to(to_),
-        from(from_),
-        holder(move(holder_)) {
-    if (!this->handle) {
-      throw std::system_error(
-          std::make_error_code(orm_error_code::failed_to_init_a_backup));
-    }
-  }
-
-  backup_t(backup_t &&other)
-      : handle(other.handle),
-        to(other.to),
-        from(other.from),
-        holder(move(other.holder)) {
-    other.handle = nullptr;
-  }
-
-  ~backup_t() {
-    if (this->handle) {
-      (void)sqlite3_backup_finish(this->handle);
-      this->handle = nullptr;
-    }
-  }
-
-  /**
-   *  Calls sqlite3_backup_step with pages argument
-   */
-  int step(int pages) {
-    return sqlite3_backup_step(this->handle, pages);
-  }
-
-  /**
-   *  Returns sqlite3_backup_remaining result
-   */
-  int remaining() const {
-    return sqlite3_backup_remaining(this->handle);
-  }
-
-  /**
-   *  Returns sqlite3_backup_pagecount result
-   */
-  int pagecount() const {
-    return sqlite3_backup_pagecount(this->handle);
-  }
-
-protected:
-  sqlite3_backup *handle = nullptr;
-  connection_ref to;
-  connection_ref from;
-  std::unique_ptr<connection_holder> holder;
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct storage_base {
-  using collating_function =
-      std::function<int(int, const void *, int, const void *)>;
-
-  std::function<void(sqlite3 *)> on_open;
-  pragma_t pragma;
-  limit_accesor limit;
-
-  transaction_guard_t transaction_guard() {
-    this->begin_transaction();
-    auto commitFunc = std::bind(
-        static_cast<void (storage_base::*)()>(&storage_base::commit), this);
-    auto rollbackFunc = std::bind(
-        static_cast<void (storage_base::*)()>(&storage_base::rollback), this);
-    return {this->get_connection(), move(commitFunc), move(rollbackFunc)};
-  }
-
-  void drop_index(const std::string &indexName) {
-    auto con = this->get_connection();
-    auto db = con.get();
-    std::stringstream ss;
-    ss << "DROP INDEX '" << indexName + "'";
-    auto query = ss.str();
-    sqlite3_stmt *stmt;
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      statement_finalizer finalizer{stmt};
-      if (sqlite3_step(stmt) == SQLITE_DONE) {
-        //  done..
-      } else {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  void vacuum() {
-    auto con = this->get_connection();
-    auto db = con.get();
-    std::string query = "VACUUM";
-    sqlite3_stmt *stmt;
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      statement_finalizer finalizer{stmt};
-      if (sqlite3_step(stmt) == SQLITE_DONE) {
-        //  done..
-      } else {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  /**
-   *  Drops table with given name.
-   */
-  void drop_table(const std::string &tableName) {
-    auto con = this->get_connection();
-    this->drop_table_internal(tableName, con.get());
-  }
-
-  /**
-   * Rename table named `from` to `to`.
-   */
-  void rename_table(const std::string &from, const std::string &to) {
-    auto con = this->get_connection();
-    std::stringstream ss;
-    ss << "ALTER TABLE '" << from << "' RENAME TO '" << to << "'";
-    this->perform_query_without_result(ss.str(), con.get());
-  }
-
-  /**
-   *  sqlite3_changes function.
-   */
-  int changes() {
-    auto con = this->get_connection();
-    return sqlite3_changes(con.get());
-  }
-
-  /**
-   *  sqlite3_total_changes function.
-   */
-  int total_changes() {
-    auto con = this->get_connection();
-    return sqlite3_total_changes(con.get());
-  }
-
-  int64 last_insert_rowid() {
-    auto con = this->get_connection();
-    return sqlite3_last_insert_rowid(con.get());
-  }
-
-  int busy_timeout(int ms) {
-    auto con = this->get_connection();
-    return sqlite3_busy_timeout(con.get(), ms);
-  }
-
-  /**
-   *  Returns libsqltie3 lib version, not sqlite_orm
-   */
-  std::string libversion() {
-    return sqlite3_libversion();
-  }
-
-  bool transaction(const std::function<bool()> &f) {
-    this->begin_transaction();
-    auto shouldCommit = f();
-    if (shouldCommit) {
-      this->commit();
-    } else {
-      this->rollback();
-    }
-    return shouldCommit;
-  }
-
-  std::string current_timestamp() {
-    auto con = this->get_connection();
-    return this->current_timestamp(con.get());
-  }
-
-#if SQLITE_VERSION_NUMBER >= 3007010
-  /**
-   * \fn db_release_memory
-   * \brief Releases freeable memory of database. It is function can/should be
-   * called periodically by application, if application has less memory usage
-   * constraint. \note sqlite3_db_release_memory added in 3.7.10
-   * https://sqlite.org/changes.html
-   */
-  int db_release_memory() {
-    auto con = this->get_connection();
-    return sqlite3_db_release_memory(con.get());
-  }
-#endif
-
-  /**
-   *  Returns existing permanent table names in database. Doesn't check storage
-   * itself - works only with actual database.
-   *  @return Returns list of tables in database.
-   */
-  std::vector<std::string> table_names() {
-    auto con = this->get_connection();
-    std::vector<std::string> tableNames;
-    std::string sql = "SELECT name FROM sqlite_master WHERE type='table'";
-    using data_t = std::vector<std::string>;
-    auto db = con.get();
-    int res = sqlite3_exec(
-        db,
-        sql.c_str(),
-        [](void *data, int argc, char **argv, char ** /*columnName*/) -> int {
-          auto &tableNames_ = *(data_t *)data;
-          for (int i = 0; i < argc; i++) {
-            if (argv[i]) {
-              tableNames_.push_back(argv[i]);
-            }
-          }
-          return 0;
-        },
-        &tableNames,
-        nullptr);
-
-    if (res != SQLITE_OK) {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-    return tableNames;
-  }
-
-  void open_forever() {
-    this->isOpenedForever = true;
-    this->connection->retain();
-    if (1 == this->connection->retain_count()) {
-      this->on_open_internal(this->connection->get());
-    }
-  }
-
-  void create_collation(const std::string &name, collating_function f) {
-    collating_function *functionPointer = nullptr;
-    if (f) {
-      functionPointer = &(collatingFunctions[name] = std::move(f));
-    } else {
-      collatingFunctions.erase(name);
-    }
-
-    //  create collations if db is open
-    if (this->connection->retain_count() > 0) {
-      auto db = this->connection->get();
-      if (sqlite3_create_collation(
-              db,
-              name.c_str(),
-              SQLITE_UTF8,
-              functionPointer,
-              f ? collate_callback : nullptr) != SQLITE_OK) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    }
-  }
-
-  void begin_transaction() {
-    this->connection->retain();
-    if (1 == this->connection->retain_count()) {
-      this->on_open_internal(this->connection->get());
-    }
-    auto db = this->connection->get();
-    this->begin_transaction(db);
-  }
-
-  void commit() {
-    auto db = this->connection->get();
-    this->commit(db);
-    this->connection->release();
-    if (this->connection->retain_count() < 0) {
-      throw std::system_error(
-          std::make_error_code(orm_error_code::no_active_transaction));
-    }
-  }
-
-  void rollback() {
-    auto db = this->connection->get();
-    this->rollback(db);
-    this->connection->release();
-    if (this->connection->retain_count() < 0) {
-      throw std::system_error(
-          std::make_error_code(orm_error_code::no_active_transaction));
-    }
-  }
-
-  void backup_to(const std::string &filename) {
-    auto backup = this->make_backup_to(filename);
-    backup.step(-1);
-  }
-
-  void backup_to(storage_base &other) {
-    auto backup = this->make_backup_to(other);
-    backup.step(-1);
-  }
-
-  void backup_from(const std::string &filename) {
-    auto backup = this->make_backup_from(filename);
-    backup.step(-1);
-  }
-
-  void backup_from(storage_base &other) {
-    auto backup = this->make_backup_from(other);
-    backup.step(-1);
-  }
-
-  backup_t make_backup_to(const std::string &filename) {
-    auto holder = std::make_unique<connection_holder>(filename);
-    connection_ref conRef{*holder};
-    return {conRef, "main", this->get_connection(), "main", move(holder)};
-  }
-
-  backup_t make_backup_to(storage_base &other) {
-    return {other.get_connection(), "main", this->get_connection(), "main", {}};
-  }
-
-  backup_t make_backup_from(const std::string &filename) {
-    auto holder = std::make_unique<connection_holder>(filename);
-    connection_ref conRef{*holder};
-    return {this->get_connection(), "main", conRef, "main", move(holder)};
-  }
-
-  backup_t make_backup_from(storage_base &other) {
-    return {this->get_connection(), "main", other.get_connection(), "main", {}};
-  }
-
-  const std::string &filename() const {
-    return this->connection->filename;
-  }
-
-  /**
-   * Checks whether connection to database is opened right now.
-   * Returns always `true` for in memory databases.
-   */
-  bool is_opened() const {
-    return this->connection->retain_count() > 0;
-  }
-
-  int busy_handler(std::function<int(int)> handler) {
-    _busy_handler = move(handler);
-    if (this->is_opened()) {
-      if (_busy_handler) {
-        return sqlite3_busy_handler(
-            this->connection->get(), busy_handler_callback, this);
-      } else {
-        return sqlite3_busy_handler(this->connection->get(), nullptr, nullptr);
-      }
-    } else {
-      return SQLITE_OK;
-    }
-  }
-
-protected:
-  storage_base(const std::string &filename_, int foreignKeysCount)
-      : pragma(std::bind(&storage_base::get_connection, this)),
-        limit(std::bind(&storage_base::get_connection, this)),
-        inMemory(filename_.empty() || filename_ == ":memory:"),
-        connection(std::make_unique<connection_holder>(filename_)),
-        cachedForeignKeysCount(foreignKeysCount) {
-    if (this->inMemory) {
-      this->connection->retain();
-      this->on_open_internal(this->connection->get());
-    }
-  }
-
-  storage_base(const storage_base &other)
-      : on_open(other.on_open),
-        pragma(std::bind(&storage_base::get_connection, this)),
-        limit(std::bind(&storage_base::get_connection, this)),
-        inMemory(other.inMemory),
-        connection(
-            std::make_unique<connection_holder>(other.connection->filename)),
-        cachedForeignKeysCount(other.cachedForeignKeysCount) {
-    if (this->inMemory) {
-      this->connection->retain();
-      this->on_open_internal(this->connection->get());
-    }
-  }
-
-  ~storage_base() {
-    if (this->isOpenedForever) {
-      this->connection->release();
-    }
-    if (this->inMemory) {
-      this->connection->release();
-    }
-  }
-
-  const bool inMemory;
-  bool isOpenedForever = false;
-  std::unique_ptr<connection_holder> connection;
-  std::map<std::string, collating_function> collatingFunctions;
-  const int cachedForeignKeysCount;
-  std::function<int(int)> _busy_handler;
-
-  connection_ref get_connection() {
-    connection_ref res{*this->connection};
-    if (1 == this->connection->retain_count()) {
-      this->on_open_internal(this->connection->get());
-    }
-    return res;
-  }
-
-#if SQLITE_VERSION_NUMBER >= 3006019
-
-  void foreign_keys(sqlite3 *db, bool value) {
-    std::stringstream ss;
-    ss << "PRAGMA foreign_keys = " << value;
-    auto query = ss.str();
-    auto rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr);
-    if (rc != SQLITE_OK) {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  bool foreign_keys(sqlite3 *db) {
-    std::string query = "PRAGMA foreign_keys";
-    auto result = false;
-    auto rc = sqlite3_exec(
-        db,
-        query.c_str(),
-        [](void *data, int argc, char **argv, char **) -> int {
-          auto &res = *(bool *)data;
-          if (argc) {
-            res = row_extractor<bool>().extract(argv[0]);
-          }
-          return 0;
-        },
-        &result,
-        nullptr);
-    if (rc != SQLITE_OK) {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-    return result;
-  }
-
-#endif
-  void on_open_internal(sqlite3 *db) {
-
-#if SQLITE_VERSION_NUMBER >= 3006019
-    if (this->cachedForeignKeysCount) {
-      this->foreign_keys(db, true);
-    }
-#endif
-    if (this->pragma._synchronous != -1) {
-      this->pragma.synchronous(this->pragma._synchronous);
-    }
-
-    if (this->pragma._journal_mode != -1) {
-      this->pragma.set_pragma(
-          "journal_mode",
-          static_cast<journal_mode>(this->pragma._journal_mode),
-          db);
-    }
-
-    for (auto &p : this->collatingFunctions) {
-      if (sqlite3_create_collation(
-              db, p.first.c_str(), SQLITE_UTF8, &p.second, collate_callback) !=
-          SQLITE_OK) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    }
-
-    for (auto &p : this->limit.limits) {
-      sqlite3_limit(db, p.first, p.second);
-    }
-
-    if (_busy_handler) {
-      sqlite3_busy_handler(
-          this->connection->get(), busy_handler_callback, this);
-    }
-
-    if (this->on_open) {
-      this->on_open(db);
-    }
-  }
-
-  void begin_transaction(sqlite3 *db) {
-    std::stringstream ss;
-    ss << "BEGIN TRANSACTION";
-    auto query = ss.str();
-    sqlite3_stmt *stmt;
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      statement_finalizer finalizer{stmt};
-      if (sqlite3_step(stmt) == SQLITE_DONE) {
-        //  done..
-      } else {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  void commit(sqlite3 *db) {
-    std::stringstream ss;
-    ss << "COMMIT";
-    auto query = ss.str();
-    sqlite3_stmt *stmt;
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      statement_finalizer finalizer{stmt};
-      if (sqlite3_step(stmt) == SQLITE_DONE) {
-        //  done..
-      } else {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  void rollback(sqlite3 *db) {
-    std::stringstream ss;
-    ss << "ROLLBACK";
-    auto query = ss.str();
-    sqlite3_stmt *stmt;
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      statement_finalizer finalizer{stmt};
-      if (sqlite3_step(stmt) == SQLITE_DONE) {
-        //  done..
-      } else {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  std::string current_timestamp(sqlite3 *db) {
-    std::string result;
-    std::stringstream ss;
-    ss << "SELECT CURRENT_TIMESTAMP";
-    auto query = ss.str();
-    auto rc = sqlite3_exec(
-        db,
-        query.c_str(),
-        [](void *data, int argc, char **argv, char **) -> int {
-          auto &res = *(std::string *)data;
-          if (argc) {
-            if (argv[0]) {
-              res = row_extractor<std::string>().extract(argv[0]);
-            }
-          }
-          return 0;
-        },
-        &result,
-        nullptr);
-    if (rc != SQLITE_OK) {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-    return result;
-  }
-
-  void drop_table_internal(const std::string &tableName, sqlite3 *db) {
-    std::stringstream ss;
-    ss << "DROP TABLE '" << tableName + "'";
-    this->perform_query_without_result(ss.str(), db);
-  }
-
-  void perform_query_without_result(const std::string &query, sqlite3 *db) {
-    sqlite3_stmt *stmt;
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      statement_finalizer finalizer{stmt};
-      if (sqlite3_step(stmt) == SQLITE_DONE) {
-        //  done..
-      } else {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  static int collate_callback(
-      void *arg,
-      int leftLen,
-      const void *lhs,
-      int rightLen,
-      const void *rhs) {
-    auto &f = *(collating_function *)arg;
-    return f(leftLen, lhs, rightLen, rhs);
-  }
-
-  static int busy_handler_callback(void *selfPointer, int triesCount) {
-    auto &storage = *static_cast<storage_base *>(selfPointer);
-    if (storage._busy_handler) {
-      return storage._busy_handler(triesCount);
-    } else {
-      return 0;
-    }
-  }
-
-  //  returns foreign keys count in storage definition
-  template <class T> static int foreign_keys_count(T &storageImpl) {
-    auto res = 0;
-    storageImpl.for_each(
-        [&res](auto &impl) { res += impl.foreign_keys_count(); });
-    return res;
-  }
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "prepared_statement.h"
-
-// #include "expression_object_type.h"
-
-#include <functional>  //  std::reference_wrapper
-#include <type_traits> //  std::decay
-
-// #include "prepared_statement.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class T, class SFINAE = void> struct expression_object_type;
-
-template <class T> struct expression_object_type<update_t<T>> {
-  using type = typename std::decay<T>::type;
-};
-
-template <class T>
-struct expression_object_type<update_t<std::reference_wrapper<T>>> {
-  using type = typename std::decay<T>::type;
-};
-
-template <class T> struct expression_object_type<replace_t<T>> {
-  using type = typename std::decay<T>::type;
-};
-
-template <class T>
-struct expression_object_type<replace_t<std::reference_wrapper<T>>> {
-  using type = typename std::decay<T>::type;
-};
-
-template <class T> struct expression_object_type<insert_t<T>> {
-  using type = typename std::decay<T>::type;
-};
-
-template <class T>
-struct expression_object_type<insert_t<std::reference_wrapper<T>>> {
-  using type = typename std::decay<T>::type;
-};
-
-template <class T, class... Cols>
-struct expression_object_type<insert_explicit<T, Cols...>> {
-  using type = typename std::decay<T>::type;
-};
-
-template <class T, class... Cols>
-struct expression_object_type<
-    insert_explicit<std::reference_wrapper<T>, Cols...>> {
-  using type = typename std::decay<T>::type;
-};
-
-template <class T> struct get_ref_t {
-
-  template <class O> auto &operator()(O &t) const {
-    return t;
-  }
-};
-
-template <class T> struct get_ref_t<std::reference_wrapper<T>> {
-
-  template <class O> auto &operator()(O &t) const {
-    return t.get();
-  }
-};
-
-template <class T> auto &get_ref(T &t) {
-  using arg_type = typename std::decay<T>::type;
-  get_ref_t<arg_type> g;
-  return g(t);
-}
-
-template <class T> struct get_object_t;
-
-template <class T> struct get_object_t<const T> : get_object_t<T> {};
-
-template <class T> auto &get_object(T &t) {
-  using expression_type = typename std::decay<T>::type;
-  get_object_t<expression_type> obj;
-  return obj(t);
-}
-
-template <class T> struct get_object_t<replace_t<T>> {
-  using expression_type = replace_t<T>;
-
-  template <class O> auto &operator()(O &e) const {
-    return get_ref(e.obj);
-  }
-};
-
-template <class T> struct get_object_t<insert_t<T>> {
-  using expression_type = insert_t<T>;
-
-  template <class O> auto &operator()(O &e) const {
-    return get_ref(e.obj);
-  }
-};
-
-template <class T> struct get_object_t<update_t<T>> {
-  using expression_type = update_t<T>;
-
-  template <class O> auto &operator()(O &e) const {
-    return get_ref(e.obj);
-  }
-};
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "statement_serializator.h"
-
-#include <algorithm>   //  std::iter_swap
-#include <sstream>     //  std::stringstream
-#include <string>      //  std::string
-#include <type_traits> //  std::enable_if
-#include <vector>      //  std::vector
-
-// #include "core_functions.h"
-
-// #include "constraints.h"
-
-// #include "conditions.h"
-
-// #include "column.h"
-
-// #include "rowid.h"
-
-// #include "type_printer.h"
-
-// #include "table_name_collector.h"
-
-#include <functional> //  std::function
-#include <set>        //  std::set
-#include <string>     //  std::string
-#include <typeindex>  //  std::type_index
-
-// #include "select_constraints.h"
-
-// #include "alias.h"
-
-// #include "core_functions.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-struct table_name_collector {
-  using table_name_set = std::set<std::pair<std::string, std::string>>;
-  using find_table_name_t = std::function<std::string(std::type_index)>;
-
-  find_table_name_t find_table_name;
-  mutable table_name_set table_names;
-
-  template <class T> table_name_set operator()(const T &) const {
-    return {};
-  }
-
-  template <class F, class O>
-  void operator()(F O::*, std::string alias = {}) const {
-    if (this->find_table_name) {
-      table_names.insert(
-          std::make_pair(this->find_table_name(typeid(O)), move(alias)));
-    }
-  }
-
-  template <class T, class F>
-  void operator()(const column_pointer<T, F> &) const {
-    if (this->find_table_name) {
-      table_names.insert({this->find_table_name(typeid(T)), ""});
-    }
-  }
-
-  template <class T, class C>
-  void operator()(const alias_column_t<T, C> &a) const {
-    (*this)(a.column, alias_extractor<T>::get());
-  }
-
-  template <class T> void operator()(const count_asterisk_t<T> &) const {
-    if (this->find_table_name) {
-      auto tableName = this->find_table_name(typeid(T));
-      if (!tableName.empty()) {
-        table_names.insert(std::make_pair(move(tableName), ""));
-      }
-    }
-  }
-
-  template <class T> void operator()(const asterisk_t<T> &) const {
-    if (this->find_table_name) {
-      auto tableName = this->find_table_name(typeid(T));
-      table_names.insert(std::make_pair(move(tableName), ""));
-    }
-  }
-
-  template <class T> void operator()(const object_t<T> &) const {
-    if (this->find_table_name) {
-      auto tableName = this->find_table_name(typeid(T));
-      table_names.insert(std::make_pair(move(tableName), ""));
-    }
-  }
-};
-
-} // namespace internal
-
-} // namespace sqlite_orm
-
-// #include "column_names_getter.h"
-
-#include <functional> //  std::reference_wrapper
-#include <string>     //  std::string
-#include <vector>     //  std::vector
-
-// #include "error_code.h"
-
-// #include "select_constraints.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class T, class C> std::string serialize(const T &t, const C &context);
-
-template <class T, class SFINAE = void> struct column_names_getter {
-  using expression_type = T;
-
-  template <class C>
-  std::vector<std::string>
-  operator()(const expression_type &t, const C &context) {
-    auto newContext = context;
-    newContext.skip_table_name = false;
-    auto columnName = serialize(t, newContext);
-    if (columnName.length()) {
-      return {move(columnName)};
-    } else {
-      throw std::system_error(
-          std::make_error_code(orm_error_code::column_not_found));
-    }
-  }
-};
-
-template <class T, class C>
-std::vector<std::string> get_column_names(const T &t, const C &context) {
-  column_names_getter<T> serializator;
-  return serializator(t, context);
-}
-
-template <class T> struct column_names_getter<std::reference_wrapper<T>, void> {
-  using expression_type = std::reference_wrapper<T>;
-
-  template <class C>
-  std::vector<std::string>
-  operator()(const expression_type &expression, const C &context) {
-    return get_column_names(expression.get(), context);
-  }
-};
-
-template <class T> struct column_names_getter<asterisk_t<T>, void> {
-  using expression_type = asterisk_t<T>;
-
-  template <class C>
-  std::vector<std::string> operator()(const expression_type &, const C &) {
-    std::vector<std::string> res;
-    res.push_back("*");
-    return res;
-  }
-};
-
-template <class T> struct column_names_getter<object_t<T>, void> {
-  using expression_type = object_t<T>;
-
-  template <class C>
-  std::vector<std::string> operator()(const expression_type &, const C &) {
-    std::vector<std::string> res;
-    res.push_back("*");
-    return res;
-  }
-};
-
-template <class... Args> struct column_names_getter<columns_t<Args...>, void> {
-  using expression_type = columns_t<Args...>;
-
-  template <class C>
-  std::vector<std::string>
-  operator()(const expression_type &cols, const C &context) {
-    std::vector<std::string> columnNames;
-    columnNames.reserve(static_cast<size_t>(cols.count));
-    auto newContext = context;
-    newContext.skip_table_name = false;
-    iterate_tuple(cols.columns, [&columnNames, &newContext](auto &m) {
-      auto columnName = serialize(m, newContext);
-      if (columnName.length()) {
-        columnNames.push_back(columnName);
-      } else {
-        throw std::system_error(
-            std::make_error_code(orm_error_code::column_not_found));
-      }
-    });
-    return columnNames;
-  }
-};
-
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "order_by_serializator.h"
-
-#include <sstream> //  std::stringstream
-#include <string>  //  std::string
-#include <vector>  //  std::vector
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class T, class SFINAE = void> struct order_by_serializator;
-
-template <class T, class C>
-std::string serialize_order_by(const T &t, const C &context) {
-  order_by_serializator<T> serializator;
-  return serializator(t, context);
-}
-
-template <class O> struct order_by_serializator<order_by_t<O>, void> {
-  using statement_type = order_by_t<O>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &orderBy, const C &context) const {
-    std::stringstream ss;
-    auto newContext = context;
-    newContext.skip_table_name = false;
-    auto columnName = serialize(orderBy.o, newContext);
-    ss << columnName << " ";
-    if (orderBy._collate_argument.length()) {
-      ss << "COLLATE " << orderBy._collate_argument << " ";
-    }
-    switch (orderBy.asc_desc) {
-    case 1:
-      ss << "ASC";
-      break;
-    case -1:
-      ss << "DESC";
-      break;
-    }
-    return ss.str();
-  }
-};
-
-template <class S> struct order_by_serializator<dynamic_order_by_t<S>, void> {
-  using statement_type = dynamic_order_by_t<S>;
-
-  template <class C>
-  std::string operator()(const statement_type &orderBy, const C &) const {
-    std::vector<std::string> expressions;
-    for (auto &entry : orderBy) {
-      std::string entryString;
-      {
-        std::stringstream ss;
-        ss << entry.name << " ";
-        if (!entry._collate_argument.empty()) {
-          ss << "COLLATE " << entry._collate_argument << " ";
-        }
-        switch (entry.asc_desc) {
-        case 1:
-          ss << "ASC";
-          break;
-        case -1:
-          ss << "DESC";
-          break;
-        }
-        entryString = ss.str();
-      }
-      expressions.push_back(move(entryString));
-    };
-    std::stringstream ss;
-    ss << static_cast<std::string>(orderBy) << " ";
-    for (size_t i = 0; i < expressions.size(); ++i) {
-      ss << expressions[i];
-      if (i < expressions.size() - 1) {
-        ss << ", ";
-      }
-    }
-    ss << " ";
-    return ss.str();
-  }
-};
-
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "values.h"
-
-// #include "table_type.h"
-
-// #include "indexed_column.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-template <class T, class SFINAE = void> struct statement_serializator;
-
-template <class T, class C>
-std::string serialize(const T &t, const C &context) {
-  statement_serializator<T> serializator;
-  return serializator(t, context);
-}
-
-template <class T>
-struct statement_serializator<
-    T,
-    typename std::enable_if<is_bindable<T>::value>::type> {
-  using statement_type = T;
-
-  template <class C>
-  std::string operator()(const statement_type &statement, const C &context) {
-    if (context.replace_bindable_with_question) {
-      return "?";
-    } else {
-      return field_printer<T>{}(statement);
-    }
-  }
-};
-
-template <class T>
-struct statement_serializator<std::reference_wrapper<T>, void> {
-  using statement_type = std::reference_wrapper<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &s, const C &context) {
-    return serialize(s.get(), context);
-  }
-};
-
-template <> struct statement_serializator<std::nullptr_t, void> {
-  using statement_type = std::nullptr_t;
-
-  template <class C> std::string operator()(const statement_type &, const C &) {
-    return "?";
-  }
-};
-
-template <class T> struct statement_serializator<alias_holder<T>, void> {
-  using statement_type = alias_holder<T>;
-
-  template <class C> std::string operator()(const statement_type &, const C &) {
-    return T::get();
-  }
-};
-
-template <class R, class S, class... Args>
-struct statement_serializator<core_function_t<R, S, Args...>, void> {
-  using statement_type = core_function_t<R, S, Args...>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(c) << "(";
-    std::vector<std::string> args;
-    using args_type = typename std::decay<decltype(c)>::type::args_type;
-    args.reserve(std::tuple_size<args_type>::value);
-    iterate_tuple(c.args, [&args, &context](auto &v) {
-      args.push_back(serialize(v, context));
-    });
-    for (size_t i = 0; i < args.size(); ++i) {
-      ss << args[i];
-      if (i < args.size() - 1) {
-        ss << ", ";
-      }
-    }
-    ss << ")";
-    return ss.str();
-  }
-};
-
-template <class T, class E> struct statement_serializator<as_t<T, E>, void> {
-  using statement_type = as_t<T, E>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    auto tableAliasString = alias_extractor<T>::get();
-    return serialize(c.expression, context) + " AS " + tableAliasString;
-  }
-};
-
-template <class T, class P>
-struct statement_serializator<alias_column_t<T, P>, void> {
-  using statement_type = alias_column_t<T, P>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    if (!context.skip_table_name) {
-      ss << "'" << T::get() << "'.";
-    }
-    auto newContext = context;
-    newContext.skip_table_name = true;
-    ss << serialize(c.column, newContext);
-    return ss.str();
-  }
-};
-
-template <> struct statement_serializator<std::string, void> {
-  using statement_type = std::string;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    if (context.replace_bindable_with_question) {
-      return "?";
-    } else {
-      return "\"" + c + "\"";
-    }
-  }
-};
-
-template <> struct statement_serializator<const char *, void> {
-  using statement_type = const char *;
-
-  template <class C>
-  std::string operator()(const char *c, const C &context) const {
-    if (context.replace_bindable_with_question) {
-      return "?";
-    } else {
-      return std::string("'") + c + "'";
-    }
-  }
-};
-
-template <class O, class F> struct statement_serializator<F O::*, void> {
-  using statement_type = F O::*;
-
-  template <class C>
-  std::string operator()(const statement_type &m, const C &context) const {
-    std::stringstream ss;
-    if (!context.skip_table_name) {
-      ss << "\"" << context.impl.find_table_name(typeid(O)) << "\".";
-    }
-    ss << "\"" << context.column_name(m) << "\"";
-    return ss.str();
-  }
-};
-
-template <> struct statement_serializator<rowid_t, void> {
-  using statement_type = rowid_t;
-
-  template <class C>
-  std::string operator()(const statement_type &s, const C &) {
-    return static_cast<std::string>(s);
-  }
-};
-
-template <> struct statement_serializator<oid_t, void> {
-  using statement_type = oid_t;
-
-  template <class C>
-  std::string operator()(const statement_type &s, const C &) {
-    return static_cast<std::string>(s);
-  }
-};
-
-template <> struct statement_serializator<_rowid_t, void> {
-  using statement_type = _rowid_t;
-
-  template <class C>
-  std::string operator()(const statement_type &s, const C &) {
-    return static_cast<std::string>(s);
-  }
-};
-
-template <class O> struct statement_serializator<table_rowid_t<O>, void> {
-  using statement_type = table_rowid_t<O>;
-
-  template <class C>
-  std::string operator()(const statement_type &s, const C &context) {
-    std::stringstream ss;
-    if (!context.skip_table_name) {
-      ss << "'" << context.impl.find_table_name(typeid(O)) << "'.";
-    }
-    ss << static_cast<std::string>(s);
-    return ss.str();
-  }
-};
-
-template <class O> struct statement_serializator<table_oid_t<O>, void> {
-  using statement_type = table_oid_t<O>;
-
-  template <class C>
-  std::string operator()(const statement_type &s, const C &context) {
-    std::stringstream ss;
-    if (!context.skip_table_name) {
-      ss << "'" << context.impl.find_table_name(typeid(O)) << "'.";
-    }
-    ss << static_cast<std::string>(s);
-    return ss.str();
-  }
-};
-
-template <class O> struct statement_serializator<table__rowid_t<O>, void> {
-  using statement_type = table__rowid_t<O>;
-
-  template <class C>
-  std::string operator()(const statement_type &s, const C &context) {
-    std::stringstream ss;
-    if (!context.skip_table_name) {
-      ss << "'" << context.impl.find_table_name(typeid(O)) << "'.";
-    }
-    ss << static_cast<std::string>(s);
-    return ss.str();
-  }
-};
-
-template <class L, class R, class... Ds>
-struct statement_serializator<binary_operator<L, R, Ds...>, void> {
-  using statement_type = binary_operator<L, R, Ds...>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    auto lhs = serialize(c.lhs, context);
-    auto rhs = serialize(c.rhs, context);
-    std::stringstream ss;
-    ss << "(" << lhs << " " << static_cast<std::string>(c) << " " << rhs << ")";
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<count_asterisk_t<T>, void> {
-  using statement_type = count_asterisk_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &, const C &context) const {
-    return serialize(count_asterisk_without_type{}, context);
-  }
-};
-
-template <> struct statement_serializator<count_asterisk_without_type, void> {
-  using statement_type = count_asterisk_without_type;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(c) << "(*)";
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<distinct_t<T>, void> {
-  using statement_type = distinct_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    auto expr = serialize(c.t, context);
-    ss << static_cast<std::string>(c) << "(" << expr << ")";
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<all_t<T>, void> {
-  using statement_type = all_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    auto expr = serialize(c.t, context);
-    ss << static_cast<std::string>(c) << "(" << expr << ")";
-    return ss.str();
-  }
-};
-
-template <class T, class F>
-struct statement_serializator<column_pointer<T, F>, void> {
-  using statement_type = column_pointer<T, F>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    if (!context.skip_table_name) {
-      ss << "'" << context.impl.find_table_name(typeid(T)) << "'.";
-    }
-    ss << "\"" << context.impl.column_name_simple(c.field) << "\"";
-    return ss.str();
-  }
-};
-
-template <class T, class E> struct statement_serializator<cast_t<T, E>, void> {
-  using statement_type = cast_t<T, E>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(c) << " (";
-    ss << serialize(c.expression, context) << " AS "
-       << type_printer<T>().print() << ")";
-    return ss.str();
-  }
-};
-
-template <class T>
-struct statement_serializator<
-    T,
-    typename std::enable_if<
-        is_base_of_template<T, compound_operator>::value>::type> {
-  using statement_type = T;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << serialize(c.left, context) << " ";
-    ss << static_cast<std::string>(c) << " ";
-    ss << serialize(c.right, context);
-    return ss.str();
-  }
-};
-
-template <class R, class T, class E, class... Args>
-struct statement_serializator<simple_case_t<R, T, E, Args...>, void> {
-  using statement_type = simple_case_t<R, T, E, Args...>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << "CASE ";
-    c.case_expression.apply(
-        [&ss, context](auto &c_) { ss << serialize(c_, context) << " "; });
-    iterate_tuple(c.args, [&ss, context](auto &pair) {
-      ss << "WHEN " << serialize(pair.first, context) << " ";
-      ss << "THEN " << serialize(pair.second, context) << " ";
-    });
-    c.else_expression.apply([&ss, context](auto &el) {
-      ss << "ELSE " << serialize(el, context) << " ";
-    });
-    ss << "END";
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<is_null_t<T>, void> {
-  using statement_type = is_null_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << serialize(c.t, context) << " " << static_cast<std::string>(c);
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<is_not_null_t<T>, void> {
-  using statement_type = is_not_null_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << serialize(c.t, context) << " " << static_cast<std::string>(c);
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<bitwise_not_t<T>, void> {
-  using statement_type = bitwise_not_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(c) << " ";
-    auto cString = serialize(c.argument, context);
-    ss << " (" << cString << " )";
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<negated_condition_t<T>, void> {
-  using statement_type = negated_condition_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(c) << " ";
-    auto cString = serialize(c.c, context);
-    ss << " (" << cString << " )";
-    return ss.str();
-  }
-};
-
-template <class T>
-struct statement_serializator<
-    T,
-    typename std::enable_if<
-        is_base_of_template<T, binary_condition>::value>::type> {
-  using statement_type = T;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    auto leftString = serialize(c.l, context);
-    auto rightString = serialize(c.r, context);
-    std::stringstream ss;
-    if (context.use_parentheses) {
-      ss << "(";
-    }
-    ss << leftString << " " << static_cast<std::string>(c) << " "
-       << rightString;
-    if (context.use_parentheses) {
-      ss << ")";
-    }
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<named_collate<T>, void> {
-  using statement_type = named_collate<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    auto newContext = context;
-    newContext.use_parentheses = false;
-    auto res = serialize(c.expr, newContext);
-    return res + " " + static_cast<std::string>(c);
-  }
-};
-
-template <class T> struct statement_serializator<collate_t<T>, void> {
-  using statement_type = collate_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    auto newContext = context;
-    newContext.use_parentheses = false;
-    auto res = serialize(c.expr, newContext);
-    return res + " " + static_cast<std::string>(c);
-  }
-};
-
-template <class L, class A> struct statement_serializator<in_t<L, A>, void> {
-  using statement_type = in_t<L, A>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    auto leftString = serialize(c.l, context);
-    ss << leftString << " " << static_cast<std::string>(c) << " ";
-    auto newContext = context;
-    newContext.use_parentheses = true;
-    ss << serialize(c.arg, newContext);
-    return ss.str();
-  }
-};
-
-template <class L, class E>
-struct statement_serializator<in_t<L, std::vector<E>>, void> {
-  using statement_type = in_t<L, std::vector<E>>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    auto leftString = serialize(c.l, context);
-    if (context.use_parentheses) {
-      ss << '(';
-    }
-    ss << leftString << " " << static_cast<std::string>(c) << " ( ";
-    for (size_t index = 0; index < c.arg.size(); ++index) {
-      auto &value = c.arg[index];
-      ss << " " << serialize(value, context);
-      if (index < c.arg.size() - 1) {
-        ss << ", ";
-      }
-    }
-    ss << " )";
-    if (context.use_parentheses) {
-      ss << ')';
-    }
-    return ss.str();
-  }
-};
-
-template <class A, class T, class E>
-struct statement_serializator<like_t<A, T, E>, void> {
-  using statement_type = like_t<A, T, E>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << serialize(c.arg, context) << " ";
-    ss << static_cast<std::string>(c) << " ";
-    ss << serialize(c.pattern, context);
-    c.arg3.apply([&ss, &context](auto &value) {
-      ss << " ESCAPE " << serialize(value, context);
-    });
-    return ss.str();
-  }
-};
-
-template <class A, class T> struct statement_serializator<glob_t<A, T>, void> {
-  using statement_type = glob_t<A, T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << serialize(c.arg, context) << " ";
-    ss << static_cast<std::string>(c) << " ";
-    ss << serialize(c.pattern, context);
-    return ss.str();
-  }
-};
-
-template <class A, class T>
-struct statement_serializator<between_t<A, T>, void> {
-  using statement_type = between_t<A, T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    auto expr = serialize(c.expr, context);
-    ss << expr << " " << static_cast<std::string>(c) << " ";
-    ss << serialize(c.b1, context);
-    ss << " AND ";
-    ss << serialize(c.b2, context);
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<exists_t<T>, void> {
-  using statement_type = exists_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(c) << " ";
-    ss << serialize(c.t, context);
-    return ss.str();
-  }
-};
-
-template <> struct statement_serializator<constraints::autoincrement_t, void> {
-  using statement_type = constraints::autoincrement_t;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &) const {
-    return static_cast<std::string>(c);
-  }
-};
-
-template <class... Cs>
-struct statement_serializator<constraints::primary_key_t<Cs...>, void> {
-  using statement_type = constraints::primary_key_t<Cs...>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    auto res = static_cast<std::string>(c);
-    using columns_tuple = typename statement_type::columns_tuple;
-    auto columnsCount = std::tuple_size<columns_tuple>::value;
-    if (columnsCount) {
-      res += "(";
-      decltype(columnsCount) columnIndex = 0;
-      iterate_tuple(
-          c.columns,
-          [&context, &res, &columnIndex, columnsCount](auto &column) {
-            res += context.column_name(column);
-            if (columnIndex < columnsCount - 1) {
-              res += ", ";
-            }
-            ++columnIndex;
-          });
-      res += ")";
-    }
-    return res;
-  }
-};
-
-template <class... Args>
-struct statement_serializator<constraints::unique_t<Args...>, void> {
-  using statement_type = constraints::unique_t<Args...>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    auto res = static_cast<std::string>(c);
-    using columns_tuple = typename statement_type::columns_tuple;
-    auto columnsCount = std::tuple_size<columns_tuple>::value;
-    if (columnsCount) {
-      res += "(";
-      decltype(columnsCount) columnIndex = 0;
-      iterate_tuple(
-          c.columns,
-          [&context, &res, &columnIndex, columnsCount](auto &column) {
-            res += context.column_name(column);
-            if (columnIndex < columnsCount - 1) {
-              res += ", ";
-            }
-            ++columnIndex;
-          });
-      res += ")";
-    }
-    return res;
-  }
-};
-
-template <> struct statement_serializator<constraints::collate_t, void> {
-  using statement_type = constraints::collate_t;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &) const {
-    return static_cast<std::string>(c);
-  }
-};
-
-template <class T>
-struct statement_serializator<constraints::default_t<T>, void> {
-  using statement_type = constraints::default_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    return static_cast<std::string>(c) + " (" + serialize(c.value, context) +
-           ")";
-  }
-};
-
-template <class... Cs, class... Rs>
-struct statement_serializator<
-    constraints::foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>>,
-    void> {
-  using statement_type =
-      constraints::foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>>;
-
-  template <class C>
-  std::string operator()(const statement_type &fk, const C &context) const {
-    std::stringstream ss;
-    std::vector<std::string> columnNames;
-    using columns_type_t =
-        typename std::decay<decltype(fk)>::type::columns_type;
-    constexpr const size_t columnsCount =
-        std::tuple_size<columns_type_t>::value;
-    columnNames.reserve(columnsCount);
-    iterate_tuple(fk.columns, [&columnNames, &context](auto &v) {
-      columnNames.push_back(context.impl.column_name(v));
-    });
-    ss << "FOREIGN KEY(";
-    for (size_t i = 0; i < columnNames.size(); ++i) {
-      ss << "'" << columnNames[i] << "'";
-      if (i < columnNames.size() - 1) {
-        ss << ", ";
-      }
-    }
-    ss << ") REFERENCES ";
-    std::vector<std::string> referencesNames;
-    using references_type_t =
-        typename std::decay<decltype(fk)>::type::references_type;
-    constexpr const size_t referencesCount =
-        std::tuple_size<references_type_t>::value;
-    referencesNames.reserve(referencesCount);
-    {
-      using first_reference_t =
-          typename std::tuple_element<0, references_type_t>::type;
-      using first_reference_mapped_type =
-          typename internal::table_type<first_reference_t>::type;
-      auto refTableName =
-          context.impl.find_table_name(typeid(first_reference_mapped_type));
-      ss << '\'' << refTableName << '\'';
-    }
-    iterate_tuple(fk.references, [&referencesNames, &context](auto &v) {
-      referencesNames.push_back(context.impl.column_name(v));
-    });
-    ss << "(";
-    for (size_t i = 0; i < referencesNames.size(); ++i) {
-      ss << "'" << referencesNames[i] << "'";
-      if (i < referencesNames.size() - 1) {
-        ss << ", ";
-      }
-    }
-    ss << ")";
-    if (fk.on_update) {
-      ss << ' ' << static_cast<std::string>(fk.on_update) << " "
-         << fk.on_update._action;
-    }
-    if (fk.on_delete) {
-      ss << ' ' << static_cast<std::string>(fk.on_delete) << " "
-         << fk.on_delete._action;
-    }
-    return ss.str();
-  }
-};
-
-template <class T>
-struct statement_serializator<constraints::check_t<T>, void> {
-  using statement_type = constraints::check_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    return static_cast<std::string>(c) + " " + serialize(c.expression, context);
-  }
-};
-
-template <class O, class T, class G, class S, class... Op>
-struct statement_serializator<column_t<O, T, G, S, Op...>, void> {
-  using statement_type = column_t<O, T, G, S, Op...>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << "'" << c.name << "' ";
-    using column_type = typename std::decay<decltype(c)>::type;
-    using field_type = typename column_type::field_type;
-    using constraints_type = typename column_type::constraints_type;
-    ss << type_printer<field_type>().print() << " ";
-    {
-      std::vector<std::string> constraintsStrings;
-      constexpr const size_t constraintsCount =
-          std::tuple_size<constraints_type>::value;
-      constraintsStrings.reserve(constraintsCount);
-      int primaryKeyIndex = -1;
-      int autoincrementIndex = -1;
-      int tupleIndex = 0;
-      iterate_tuple(
-          c.constraints,
-          [&constraintsStrings,
-           &primaryKeyIndex,
-           &autoincrementIndex,
-           &tupleIndex,
-           &context](auto &v) {
-            using constraint_type = typename std::decay<decltype(v)>::type;
-            constraintsStrings.push_back(serialize(v, context));
-            if (is_primary_key<constraint_type>::value) {
-              primaryKeyIndex = tupleIndex;
-            } else if (std::is_same<
-                           constraints::autoincrement_t,
-                           constraint_type>::value) {
-              autoincrementIndex = tupleIndex;
-            }
-            ++tupleIndex;
-          });
-      if (primaryKeyIndex != -1 && autoincrementIndex != -1 &&
-          autoincrementIndex < primaryKeyIndex) {
-        iter_swap(
-            constraintsStrings.begin() + primaryKeyIndex,
-            constraintsStrings.begin() + autoincrementIndex);
-      }
-      for (auto &str : constraintsStrings) {
-        ss << str << ' ';
-      }
-    }
-    if (c.not_null()) {
-      ss << "NOT NULL ";
-    }
-    return ss.str();
-  }
-};
-
-template <class T, class... Args>
-struct statement_serializator<remove_all_t<T, Args...>, void> {
-  using statement_type = remove_all_t<T, Args...>;
-
-  template <class C>
-  std::string operator()(const statement_type &rem, const C &context) const {
-    auto &tImpl = context.impl.template get_impl<T>();
-    std::stringstream ss;
-    ss << "DELETE FROM '" << tImpl.table.name << "' ";
-    iterate_tuple(rem.conditions, [&context, &ss](auto &v) {
-      ss << serialize(v, context);
-    });
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<replace_t<T>, void> {
-  using statement_type = replace_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &rep, const C &context) const {
-    using expression_type = typename std::decay<decltype(rep)>::type;
-    using object_type = typename expression_object_type<expression_type>::type;
-    auto &tImpl = context.impl.template get_impl<object_type>();
-    std::stringstream ss;
-    ss << "REPLACE INTO '" << tImpl.table.name << "' (";
-    auto columnNames = tImpl.table.column_names();
-    auto columnNamesCount = columnNames.size();
-    for (size_t i = 0; i < columnNamesCount; ++i) {
-      ss << "\"" << columnNames[i] << "\"";
-      if (i < columnNamesCount - 1) {
-        ss << ",";
-      } else {
-        ss << ")";
-      }
-      ss << " ";
-    }
-    ss << "VALUES(";
-    for (size_t i = 0; i < columnNamesCount; ++i) {
-      ss << "?";
-      if (i < columnNamesCount - 1) {
-        ss << ", ";
-      } else {
-        ss << ")";
-      }
-    }
-    return ss.str();
-  }
-};
-
-template <class T, class... Cols>
-struct statement_serializator<insert_explicit<T, Cols...>, void> {
-  using statement_type = insert_explicit<T, Cols...>;
-
-  template <class C>
-  std::string operator()(const statement_type &ins, const C &context) const {
-    constexpr const size_t colsCount =
-        std::tuple_size<std::tuple<Cols...>>::value;
-    static_assert(
-        colsCount > 0, "Use insert or replace with 1 argument instead");
-    using expression_type = typename std::decay<decltype(ins)>::type;
-    using object_type = typename expression_object_type<expression_type>::type;
-    auto &tImpl = context.impl.template get_impl<object_type>();
-    std::stringstream ss;
-    ss << "INSERT INTO '" << tImpl.table.name << "' ";
-    std::vector<std::string> columnNames;
-    columnNames.reserve(colsCount);
-    {
-      auto columnsContext = context;
-      columnsContext.skip_table_name = true;
-      iterate_tuple(
-          ins.columns.columns, [&columnNames, &columnsContext](auto &m) {
-            auto columnName = serialize(m, columnsContext);
-            if (!columnName.empty()) {
-              columnNames.push_back(columnName);
-            } else {
-              throw std::system_error(
-                  std::make_error_code(orm_error_code::column_not_found));
-            }
-          });
-    }
-    ss << "(";
-    for (size_t i = 0; i < columnNames.size(); ++i) {
-      ss << columnNames[i];
-      if (i < columnNames.size() - 1) {
-        ss << ",";
-      } else {
-        ss << ")";
-      }
-      ss << " ";
-    }
-    ss << "VALUES (";
-    for (size_t i = 0; i < columnNames.size(); ++i) {
-      ss << "?";
-      if (i < columnNames.size() - 1) {
-        ss << ",";
-      } else {
-        ss << ")";
-      }
-      ss << " ";
-    }
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<update_t<T>, void> {
-  using statement_type = update_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &upd, const C &context) const {
-    using expression_type = typename std::decay<decltype(upd)>::type;
-    using object_type = typename expression_object_type<expression_type>::type;
-    auto &tImpl = context.impl.template get_impl<object_type>();
-
-    std::stringstream ss;
-    ss << "UPDATE '" << tImpl.table.name << "' SET ";
-    std::vector<std::string> setColumnNames;
-    tImpl.table.for_each_column([&setColumnNames](auto &c) {
-      if (!c.template has<constraints::primary_key_t<>>()) {
-        setColumnNames.emplace_back(c.name);
-      }
-    });
-    for (size_t i = 0; i < setColumnNames.size(); ++i) {
-      ss << "\"" << setColumnNames[i] << "\""
-         << " = ?";
-      if (i < setColumnNames.size() - 1) {
-        ss << ",";
-      }
-      ss << " ";
-    }
-    ss << "WHERE ";
-    auto primaryKeyColumnNames = tImpl.table.primary_key_column_names();
-    for (size_t i = 0; i < primaryKeyColumnNames.size(); ++i) {
-      ss << "\"" << primaryKeyColumnNames[i] << "\""
-         << " = ?";
-      if (i < primaryKeyColumnNames.size() - 1) {
-        ss << " AND";
-      }
-      ss << " ";
-    }
-    return ss.str();
-  }
-};
-
-template <class... Args, class... Wargs>
-struct statement_serializator<update_all_t<set_t<Args...>, Wargs...>, void> {
-  using statement_type = update_all_t<set_t<Args...>, Wargs...>;
-
-  template <class C>
-  std::string operator()(const statement_type &upd, const C &context) const {
-    std::stringstream ss;
-    ss << "UPDATE ";
-    table_name_collector collector{[&context](std::type_index ti) {
-      return context.impl.find_table_name(ti);
-    }};
-    iterate_ast(upd.set.assigns, collector);
-    if (!collector.table_names.empty()) {
-      if (collector.table_names.size() == 1) {
-        ss << " '" << collector.table_names.begin()->first << "' ";
-        ss << static_cast<std::string>(upd.set) << " ";
-        std::vector<std::string> setPairs;
-        auto leftContext = context;
-        leftContext.skip_table_name = true;
-        iterate_tuple(
-            upd.set.assigns, [&context, &leftContext, &setPairs](auto &asgn) {
-              std::stringstream sss;
-              sss << serialize(asgn.lhs, leftContext);
-              sss << " " << static_cast<std::string>(asgn) << " ";
-              sss << serialize(asgn.rhs, context) << " ";
-              setPairs.push_back(sss.str());
-            });
-        auto setPairsCount = setPairs.size();
-        for (size_t i = 0; i < setPairsCount; ++i) {
-          ss << setPairs[i] << " ";
-          if (i < setPairsCount - 1) {
-            ss << ", ";
-          }
-        }
-        iterate_tuple(upd.conditions, [&context, &ss](auto &v) {
-          ss << serialize(v, context);
-        });
-        return ss.str();
-      } else {
-        throw std::system_error(
-            std::make_error_code(orm_error_code::too_many_tables_specified));
-      }
-    } else {
-      throw std::system_error(
-          std::make_error_code(orm_error_code::incorrect_set_fields_specified));
-    }
-  }
-};
-
-template <class T> struct statement_serializator<insert_t<T>, void> {
-  using statement_type = insert_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &, const C &context) const {
-    using object_type = typename expression_object_type<statement_type>::type;
-    auto &tImpl = context.impl.template get_impl<object_type>();
-    std::stringstream ss;
-    ss << "INSERT INTO '" << tImpl.table.name << "' ";
-    std::vector<std::string> columnNames;
-    auto compositeKeyColumnNames = tImpl.table.composite_key_columns_names();
-
-    tImpl.table.for_each_column(
-        [&tImpl, &columnNames, &compositeKeyColumnNames](auto &c) {
-          if (tImpl.table._without_rowid ||
-              !c.template has<constraints::primary_key_t<>>()) {
-            auto it = find(
-                compositeKeyColumnNames.begin(),
-                compositeKeyColumnNames.end(),
-                c.name);
-            if (it == compositeKeyColumnNames.end()) {
-              columnNames.emplace_back(c.name);
-            }
-          }
-        });
-
-    auto columnNamesCount = columnNames.size();
-    if (columnNamesCount) {
-      ss << "(";
-      for (size_t i = 0; i < columnNamesCount; ++i) {
-        ss << "\"" << columnNames[i] << "\"";
-        if (i < columnNamesCount - 1) {
-          ss << ",";
-        } else {
-          ss << ")";
-        }
-        ss << " ";
-      }
-    } else {
-      ss << "DEFAULT ";
-    }
-    ss << "VALUES ";
-    if (columnNamesCount) {
-      ss << "(";
-      for (size_t i = 0; i < columnNamesCount; ++i) {
-        ss << "?";
-        if (i < columnNamesCount - 1) {
-          ss << ", ";
-        } else {
-          ss << ")";
-        }
-      }
-    }
-    return ss.str();
-  }
-};
-
-template <class T, class... Ids>
-struct statement_serializator<remove_t<T, Ids...>, void> {
-  using statement_type = remove_t<T, Ids...>;
-
-  template <class C>
-  std::string operator()(const statement_type &, const C &context) const {
-    auto &tImpl = context.impl.template get_impl<T>();
-    std::stringstream ss;
-    ss << "DELETE FROM '" << tImpl.table.name << "' ";
-    ss << "WHERE ";
-    auto primaryKeyColumnNames = tImpl.table.primary_key_column_names();
-    for (size_t i = 0; i < primaryKeyColumnNames.size(); ++i) {
-      ss << "\"" << primaryKeyColumnNames[i] << "\""
-         << " = ? ";
-      if (i < primaryKeyColumnNames.size() - 1) {
-        ss << "AND ";
-      }
-    }
-    return ss.str();
-  }
-};
-
-template <class It> struct statement_serializator<replace_range_t<It>, void> {
-  using statement_type = replace_range_t<It>;
-
-  template <class C>
-  std::string operator()(const statement_type &rep, const C &context) const {
-    using expression_type = typename std::decay<decltype(rep)>::type;
-    using object_type = typename expression_type::object_type;
-    auto &tImpl = context.impl.template get_impl<object_type>();
-    std::stringstream ss;
-    ss << "REPLACE INTO '" << tImpl.table.name << "' (";
-    auto columnNames = tImpl.table.column_names();
-    auto columnNamesCount = columnNames.size();
-    for (size_t i = 0; i < columnNamesCount; ++i) {
-      ss << "\"" << columnNames[i] << "\"";
-      if (i < columnNamesCount - 1) {
-        ss << ", ";
-      } else {
-        ss << ") ";
-      }
-    }
-    ss << "VALUES ";
-    auto valuesString = [columnNamesCount] {
-      std::stringstream ss_;
-      ss_ << "(";
-      for (size_t i = 0; i < columnNamesCount; ++i) {
-        ss_ << "?";
-        if (i < columnNamesCount - 1) {
-          ss_ << ", ";
-        } else {
-          ss_ << ")";
-        }
-      }
-      return ss_.str();
-    }();
-    auto valuesCount =
-        static_cast<int>(std::distance(rep.range.first, rep.range.second));
-    for (auto i = 0; i < valuesCount; ++i) {
-      ss << valuesString;
-      if (i < valuesCount - 1) {
-        ss << ",";
-      }
-      ss << " ";
-    }
-    return ss.str();
-  }
-};
-
-template <class It> struct statement_serializator<insert_range_t<It>, void> {
-  using statement_type = insert_range_t<It>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &statement, const C &context) const {
-    using expression_type = typename std::decay<decltype(statement)>::type;
-    using object_type = typename expression_type::object_type;
-    auto &tImpl = context.impl.template get_impl<object_type>();
-
-    std::stringstream ss;
-    ss << "INSERT INTO '" << tImpl.table.name << "' (";
-    std::vector<std::string> columnNames;
-    tImpl.table.for_each_column([&columnNames](auto &c) {
-      if (!c.template has<constraints::primary_key_t<>>()) {
-        columnNames.emplace_back(c.name);
-      }
-    });
-
-    auto columnNamesCount = columnNames.size();
-    for (size_t i = 0; i < columnNamesCount; ++i) {
-      ss << "\"" << columnNames[i] << "\"";
-      if (i < columnNamesCount - 1) {
-        ss << ",";
-      } else {
-        ss << ")";
-      }
-      ss << " ";
-    }
-    ss << "VALUES ";
-    auto valuesString = [columnNamesCount] {
-      std::stringstream ss_;
-      ss_ << "(";
-      for (size_t i = 0; i < columnNamesCount; ++i) {
-        ss_ << "?";
-        if (i < columnNamesCount - 1) {
-          ss_ << ", ";
-        } else {
-          ss_ << ")";
-        }
-      }
-      return ss_.str();
-    }();
-    auto valuesCount = static_cast<int>(
-        std::distance(statement.range.first, statement.range.second));
-    for (auto i = 0; i < valuesCount; ++i) {
-      ss << valuesString;
-      if (i < valuesCount - 1) {
-        ss << ",";
-      }
-      ss << " ";
-    }
-    return ss.str();
-  }
-};
-
-template <class T, class C>
-std::string serialize_get_all_impl(const T &get, const C &context) {
-  using primary_type = typename T::type;
-
-  table_name_collector collector;
-  collector.table_names.insert(std::make_pair(
-      context.impl.find_table_name(typeid(primary_type)), std::string{}));
-  iterate_ast(get.conditions, collector);
-  std::stringstream ss;
-  ss << "SELECT ";
-  auto &tImpl = context.impl.template get_impl<primary_type>();
-  auto columnNames = tImpl.table.column_names();
-  for (size_t i = 0; i < columnNames.size(); ++i) {
-    ss << "\"" << tImpl.table.name << "\"."
-       << "\"" << columnNames[i] << "\"";
-    if (i < columnNames.size() - 1) {
-      ss << ", ";
-    } else {
-      ss << " ";
-    }
-  }
-  ss << "FROM ";
-  std::vector<std::pair<std::string, std::string>> tableNames(
-      collector.table_names.begin(), collector.table_names.end());
-  for (size_t i = 0; i < tableNames.size(); ++i) {
-    auto &tableNamePair = tableNames[i];
-    ss << "'" << tableNamePair.first << "' ";
-    if (!tableNamePair.second.empty()) {
-      ss << tableNamePair.second << " ";
-    }
-    if (int(i) < int(tableNames.size()) - 1) {
-      ss << ",";
-    }
-    ss << " ";
-  }
-  iterate_tuple(get.conditions, [&context, &ss](auto &v) {
-    ss << serialize(v, context);
-  });
-  return ss.str();
-}
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <class T, class R, class... Args>
-struct statement_serializator<get_all_optional_t<T, R, Args...>, void> {
-  using statement_type = get_all_optional_t<T, R, Args...>;
-
-  template <class C>
-  std::string operator()(const statement_type &get, const C &context) const {
-    return serialize_get_all_impl(get, context);
-  }
-};
-#endif //  SQLITE_ORM_OPTIONAL_SUPPORTED
-
-template <class T, class R, class... Args>
-struct statement_serializator<get_all_pointer_t<T, R, Args...>, void> {
-  using statement_type = get_all_pointer_t<T, R, Args...>;
-
-  template <class C>
-  std::string operator()(const statement_type &get, const C &context) const {
-    return serialize_get_all_impl(get, context);
-  }
-};
-
-template <class T, class R, class... Args>
-struct statement_serializator<get_all_t<T, R, Args...>, void> {
-  using statement_type = get_all_t<T, R, Args...>;
-
-  template <class C>
-  std::string operator()(const statement_type &get, const C &context) const {
-    return serialize_get_all_impl(get, context);
-  }
-};
-
-template <class T, class C>
-std::string serialize_get_impl(const T &, const C &context) {
-  using primary_type = typename T::type;
-  auto &tImpl = context.impl.template get_impl<primary_type>();
-  std::stringstream ss;
-  ss << "SELECT ";
-  auto columnNames = tImpl.table.column_names();
-  for (size_t i = 0; i < columnNames.size(); ++i) {
-    ss << "\"" << columnNames[i] << "\"";
-    if (i < columnNames.size() - 1) {
-      ss << ",";
-    }
-    ss << " ";
-  }
-  ss << "FROM '" << tImpl.table.name << "' WHERE ";
-  auto primaryKeyColumnNames = tImpl.table.primary_key_column_names();
-  if (!primaryKeyColumnNames.empty()) {
-    for (size_t i = 0; i < primaryKeyColumnNames.size(); ++i) {
-      ss << "\"" << primaryKeyColumnNames[i] << "\""
-         << " = ? ";
-      if (i < primaryKeyColumnNames.size() - 1) {
-        ss << "AND";
-      }
-      ss << ' ';
-    }
-    return ss.str();
-  } else {
-    throw std::system_error(
-        std::make_error_code(orm_error_code::table_has_no_primary_key_column));
-  }
-}
-
-template <class T, class... Ids>
-struct statement_serializator<get_t<T, Ids...>, void> {
-  using statement_type = get_t<T, Ids...>;
-
-  template <class C>
-  std::string operator()(const statement_type &get, const C &context) const {
-    return serialize_get_impl(get, context);
-  }
-};
-
-template <class T, class... Ids>
-struct statement_serializator<get_pointer_t<T, Ids...>, void> {
-  using statement_type = get_pointer_t<T, Ids...>;
-
-  template <class C>
-  std::string operator()(const statement_type &get, const C &context) const {
-    return serialize_get_impl(get, context);
-  }
-};
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <class T, class... Ids>
-struct statement_serializator<get_optional_t<T, Ids...>, void> {
-  using statement_type = get_optional_t<T, Ids...>;
-
-  template <class C>
-  std::string operator()(const statement_type &get, const C &context) const {
-    return serialize_get_impl(get, context);
-  }
-};
-#endif //  SQLITE_ORM_OPTIONAL_SUPPORTED
-template <class T, class... Args>
-struct statement_serializator<select_t<T, Args...>, void> {
-  using statement_type = select_t<T, Args...>;
-
-  template <class C>
-  std::string operator()(const statement_type &sel, const C &context) const {
-    std::stringstream ss;
-    if (!is_base_of_template<T, compound_operator>::value) {
-      if (!sel.highest_level) {
-        ss << "( ";
-      }
-      ss << "SELECT ";
-    }
-    if (get_distinct(sel.col)) {
-      ss << static_cast<std::string>(distinct(0)) << " ";
-    }
-    auto columnNames = get_column_names(sel.col, context);
-    for (size_t i = 0; i < columnNames.size(); ++i) {
-      ss << columnNames[i];
-      if (i < columnNames.size() - 1) {
-        ss << ",";
-      }
-      ss << " ";
-    }
-    table_name_collector collector{[&context](std::type_index ti) {
-      return context.impl.find_table_name(ti);
-    }};
-    iterate_ast(sel.col, collector);
-    iterate_ast(sel.conditions, collector);
-    internal::join_iterator<Args...>()([&collector, &context](const auto &c) {
-      using original_join_type =
-          typename std::decay<decltype(c)>::type::join_type::type;
-      using cross_join_type =
-          typename internal::mapped_type_proxy<original_join_type>::type;
-      auto crossJoinedTableName =
-          context.impl.find_table_name(typeid(cross_join_type));
-      auto tableAliasString = alias_extractor<original_join_type>::get();
-      std::pair<std::string, std::string> tableNameWithAlias(
-          std::move(crossJoinedTableName), std::move(tableAliasString));
-      collector.table_names.erase(tableNameWithAlias);
-    });
-    if (!collector.table_names.empty()) {
-      ss << "FROM ";
-      std::vector<std::pair<std::string, std::string>> tableNames(
-          collector.table_names.begin(), collector.table_names.end());
-      for (size_t i = 0; i < tableNames.size(); ++i) {
-        auto &tableNamePair = tableNames[i];
-        ss << "'" << tableNamePair.first << "' ";
-        if (!tableNamePair.second.empty()) {
-          ss << tableNamePair.second << " ";
-        }
-        if (int(i) < int(tableNames.size()) - 1) {
-          ss << ",";
-        }
-        ss << " ";
-      }
-    }
-    iterate_tuple(sel.conditions, [&context, &ss](auto &v) {
-      ss << serialize(v, context);
-    });
-    if (!is_base_of_template<T, compound_operator>::value) {
-      if (!sel.highest_level) {
-        ss << ") ";
-      }
-    }
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<indexed_column_t<T>, void> {
-  using statement_type = indexed_column_t<T>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &statement, const C &context) const {
-    std::stringstream ss;
-    ss << serialize(statement.column_or_expression, context);
-    if (!statement._collation_name.empty()) {
-      ss << " COLLATE " << statement._collation_name;
-    }
-    if (statement._order) {
-      switch (statement._order) {
-      case -1:
-        ss << " DESC";
-        break;
-      case 1:
-        ss << " ASC";
-        break;
-      default:
-        throw std::system_error(
-            std::make_error_code(orm_error_code::incorrect_order));
-      }
-    }
-    return ss.str();
-  }
-};
-
-template <class... Cols> struct statement_serializator<index_t<Cols...>, void> {
-  using statement_type = index_t<Cols...>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &statement, const C &context) const {
-    std::stringstream ss;
-    ss << "CREATE ";
-    if (statement.unique) {
-      ss << "UNIQUE ";
-    }
-    using columns_type =
-        typename std::decay<decltype(statement)>::type::columns_type;
-    using head_t =
-        typename std::tuple_element<0, columns_type>::type::column_type;
-    using indexed_type = typename table_type<head_t>::type;
-    ss << "INDEX IF NOT EXISTS '" << statement.name << "' ON '"
-       << context.impl.find_table_name(typeid(indexed_type)) << "' (";
-    std::vector<std::string> columnNames;
-    iterate_tuple(statement.columns, [&columnNames, &context](auto &v) {
-      columnNames.push_back(context.column_name(v.column_or_expression));
-    });
-    for (size_t i = 0; i < columnNames.size(); ++i) {
-      ss << "'" << columnNames[i] << "'";
-      if (i < columnNames.size() - 1) {
-        ss << ", ";
-      }
-    }
-    ss << ")";
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<where_t<T>, void> {
-  using statement_type = where_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &w, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(w) << " ";
-    auto whereString = serialize(w.c, context);
-    ss << "( " << whereString << ") ";
-    return ss.str();
-  }
-};
-
-template <class O> struct statement_serializator<order_by_t<O>, void> {
-  using statement_type = order_by_t<O>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &orderBy, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(orderBy) << " ";
-    auto orderByString = serialize_order_by(orderBy, context);
-    ss << orderByString << " ";
-    return ss.str();
-  }
-};
-
-template <class C> struct statement_serializator<dynamic_order_by_t<C>, void> {
-  using statement_type = dynamic_order_by_t<C>;
-
-  template <class CC>
-  std::string
-  operator()(const statement_type &orderBy, const CC &context) const {
-    return serialize_order_by(orderBy, context);
-  }
-};
-
-template <class... Args>
-struct statement_serializator<multi_order_by_t<Args...>, void> {
-  using statement_type = multi_order_by_t<Args...>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &orderBy, const C &context) const {
-    std::stringstream ss;
-    std::vector<std::string> expressions;
-    iterate_tuple(orderBy.args, [&expressions, &context](auto &v) {
-      auto expression = serialize_order_by(v, context);
-      expressions.push_back(move(expression));
-    });
-    ss << static_cast<std::string>(orderBy) << " ";
-    for (size_t i = 0; i < expressions.size(); ++i) {
-      ss << expressions[i];
-      if (i < expressions.size() - 1) {
-        ss << ", ";
-      }
-    }
-    ss << " ";
-    return ss.str();
-  }
-};
-
-template <class O> struct statement_serializator<cross_join_t<O>, void> {
-  using statement_type = cross_join_t<O>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(c) << " ";
-    ss << " '" << context.impl.find_table_name(typeid(O)) << "'";
-    return ss.str();
-  }
-};
-
-template <class T, class O>
-struct statement_serializator<inner_join_t<T, O>, void> {
-  using statement_type = inner_join_t<T, O>;
-
-  template <class C>
-  std::string operator()(const statement_type &l, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(l) << " ";
-    auto aliasString = alias_extractor<T>::get();
-    ss << " '"
-       << context.impl.find_table_name(
-              typeid(typename mapped_type_proxy<T>::type))
-       << "' ";
-    if (aliasString.length()) {
-      ss << "'" << aliasString << "' ";
-    }
-    ss << serialize(l.constraint, context);
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<on_t<T>, void> {
-  using statement_type = on_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &t, const C &context) const {
-    std::stringstream ss;
-    auto newContext = context;
-    newContext.skip_table_name = false;
-    ss << static_cast<std::string>(t) << " " << serialize(t.arg, newContext)
-       << " ";
-    return ss.str();
-  }
-};
-
-template <class T, class O> struct statement_serializator<join_t<T, O>, void> {
-  using statement_type = join_t<T, O>;
-
-  template <class C>
-  std::string operator()(const statement_type &l, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(l) << " ";
-    ss << " '" << context.impl.find_table_name(typeid(T)) << "' ";
-    ss << serialize(l.constraint, context);
-    return ss.str();
-  }
-};
-
-template <class T, class O>
-struct statement_serializator<left_join_t<T, O>, void> {
-  using statement_type = left_join_t<T, O>;
-
-  template <class C>
-  std::string operator()(const statement_type &l, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(l) << " ";
-    ss << " '" << context.impl.find_table_name(typeid(T)) << "' ";
-    ss << serialize(l.constraint, context);
-    return ss.str();
-  }
-};
-
-template <class T, class O>
-struct statement_serializator<left_outer_join_t<T, O>, void> {
-  using statement_type = left_outer_join_t<T, O>;
-
-  template <class C>
-  std::string operator()(const statement_type &l, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(l) << " ";
-    ss << " '" << context.impl.find_table_name(typeid(T)) << "' ";
-    ss << serialize(l.constraint, context);
-    return ss.str();
-  }
-};
-
-template <class O> struct statement_serializator<natural_join_t<O>, void> {
-  using statement_type = natural_join_t<O>;
-
-  template <class C>
-  std::string operator()(const statement_type &c, const C &context) const {
-    std::stringstream ss;
-    ss << static_cast<std::string>(c) << " ";
-    ss << " '" << context.impl.find_table_name(typeid(O)) << "'";
-    return ss.str();
-  }
-};
-
-template <class... Args>
-struct statement_serializator<group_by_t<Args...>, void> {
-  using statement_type = group_by_t<Args...>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &groupBy, const C &context) const {
-    std::stringstream ss;
-    std::vector<std::string> expressions;
-    auto newContext = context;
-    newContext.skip_table_name = false;
-    iterate_tuple(groupBy.args, [&expressions, &newContext](auto &v) {
-      auto expression = serialize(v, newContext);
-      expressions.push_back(expression);
-    });
-    ss << static_cast<std::string>(groupBy) << " ";
-    for (size_t i = 0; i < expressions.size(); ++i) {
-      ss << expressions[i];
-      if (i < expressions.size() - 1) {
-        ss << ", ";
-      }
-    }
-    ss << " ";
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<having_t<T>, void> {
-  using statement_type = having_t<T>;
-
-  template <class C>
-  std::string operator()(const statement_type &hav, const C &context) const {
-    std::stringstream ss;
-    auto newContext = context;
-    newContext.skip_table_name = false;
-    ss << static_cast<std::string>(hav) << " ";
-    ss << serialize(hav.t, newContext) << " ";
-    return ss.str();
-  }
-};
-
-/**
- *  HO - has offset
- *  OI - offset is implicit
- */
-template <class T, bool HO, bool OI, class O>
-struct statement_serializator<limit_t<T, HO, OI, O>, void> {
-  using statement_type = limit_t<T, HO, OI, O>;
-
-  template <class C>
-  std::string operator()(const statement_type &limt, const C &context) const {
-    auto newContext = context;
-    newContext.skip_table_name = false;
-    std::stringstream ss;
-    ss << static_cast<std::string>(limt) << " ";
-    if (HO) {
-      if (OI) {
-        limt.off.apply([&newContext, &ss](auto &value) {
-          ss << serialize(value, newContext);
-        });
-        ss << ", ";
-        ss << serialize(limt.lim, newContext);
-      } else {
-        ss << serialize(limt.lim, newContext) << " OFFSET ";
-        limt.off.apply([&newContext, &ss](auto &value) {
-          ss << serialize(value, newContext);
-        });
-      }
-    } else {
-      ss << serialize(limt.lim, newContext);
-    }
-    return ss.str();
-  }
-};
-
-template <class F, class O> struct statement_serializator<using_t<F, O>, void> {
-  using statement_type = using_t<F, O>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &statement, const C &context) const {
-    auto newContext = context;
-    newContext.skip_table_name = true;
-    return static_cast<std::string>(statement) + " (" +
-           serialize(statement.column, newContext) + " )";
-  }
-};
-
-template <class... Args>
-struct statement_serializator<std::tuple<Args...>, void> {
-  using statement_type = std::tuple<Args...>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &statement, const C &context) const {
-    std::stringstream ss;
-    ss << '(';
-    auto index = 0;
-    using TupleSize = std::tuple_size<statement_type>;
-    iterate_tuple(statement, [&context, &index, &ss](auto &value) {
-      ss << serialize(value, context);
-      if (index < TupleSize::value - 1) {
-        ss << ", ";
-      }
-      ++index;
-    });
-    ss << ')';
-    return ss.str();
-  }
-};
-
-template <class... Args>
-struct statement_serializator<values_t<Args...>, void> {
-  using statement_type = values_t<Args...>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &statement, const C &context) const {
-    std::stringstream ss;
-    if (context.use_parentheses) {
-      ss << '(';
-    }
-    ss << "VALUES ";
-    {
-      auto index = 0;
-      auto &tuple = statement.tuple;
-      using tuple_type = typename std::decay<decltype(tuple)>::type;
-      using TupleSize = std::tuple_size<tuple_type>;
-      iterate_tuple(tuple, [&context, &index, &ss](auto &value) {
-        ss << serialize(value, context);
-        if (index < TupleSize::value - 1) {
-          ss << ", ";
-        }
-        ++index;
-      });
-    }
-    if (context.use_parentheses) {
-      ss << ')';
-    }
-    return ss.str();
-  }
-};
-
-template <class T> struct statement_serializator<dynamic_values_t<T>, void> {
-  using statement_type = dynamic_values_t<T>;
-
-  template <class C>
-  std::string
-  operator()(const statement_type &statement, const C &context) const {
-    std::stringstream ss;
-    if (context.use_parentheses) {
-      ss << '(';
-    }
-    ss << "VALUES ";
-    {
-      auto vectorSize = statement.vector.size();
-      for (decltype(vectorSize) index = 0; index < vectorSize; ++index) {
-        auto &value = statement.vector[index];
-        ss << serialize(value, context);
-        if (index < vectorSize - 1) {
-          ss << ", ";
-        }
-      }
-    }
-    if (context.use_parentheses) {
-      ss << ')';
-    }
-    return ss.str();
-  }
-};
-
-} // namespace internal
-} // namespace sqlite_orm
-
-// #include "table_name_collector.h"
-
-// #include "object_from_column_builder.h"
-
-namespace sqlite_orm {
-
-namespace internal {
-
-/**
- *  Storage class itself. Create an instanse to use it as an interfacto to
- * sqlite db by calling `make_storage` function.
- */
-template <class... Ts> struct storage_t : storage_base {
-  using self = storage_t<Ts...>;
-  using impl_type = storage_impl<Ts...>;
-
-  /**
-   *  @param filename database filename.
-   *  @param impl_ storage_impl head
-   */
-  storage_t(const std::string &filename, impl_type impl_)
-      : storage_base{filename, foreign_keys_count(impl_)},
-        impl(std::move(impl_)) {
-  }
-
-  storage_t(const storage_t &other) : storage_base(other), impl(other.impl) {
-  }
-
-protected:
-  impl_type impl;
-
-  template <class T, class S, class... Args> friend struct view_t;
-
-  template <class S> friend struct dynamic_order_by_t;
-
-  template <class V> friend struct iterator_t;
-
-  template <class S> friend struct serializator_context_builder;
-
-  template <class I>
-  void
-  create_table(sqlite3 *db, const std::string &tableName, const I &tableImpl) {
-    std::stringstream ss;
-    ss << "CREATE TABLE '" << tableName << "' ( ";
-    auto columnsCount = tableImpl.table.columns_count;
-    auto index = 0;
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    iterate_tuple(
-        tableImpl.table.columns,
-        [columnsCount, &index, &ss, &context](auto &c) {
-          ss << serialize(c, context);
-          if (index < columnsCount - 1) {
-            ss << ", ";
-          }
-          index++;
-        });
-    ss << ") ";
-    if (tableImpl.table._without_rowid) {
-      ss << "WITHOUT ROWID ";
-    }
-    auto query = ss.str();
-    sqlite3_stmt *stmt;
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      statement_finalizer finalizer{stmt};
-      if (sqlite3_step(stmt) == SQLITE_DONE) {
-        //  done..
-      } else {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class I>
-  void backup_table(
-      sqlite3 *db,
-      const I &tableImpl,
-      const std::vector<table_info *> &columnsToIgnore) {
-
-    //  here we copy source table to another with a name with '_backup' suffix,
-    //  but in case table with such a name already exists we append suffix 1,
-    //  then 2, etc until we find a free name..
-    auto backupTableName = tableImpl.table.name + "_backup";
-    if (tableImpl.table_exists(backupTableName, db)) {
-      int suffix = 1;
-      do {
-        std::stringstream stream;
-        stream << suffix;
-        auto anotherBackupTableName = backupTableName + stream.str();
-        if (!tableImpl.table_exists(anotherBackupTableName, db)) {
-          backupTableName = anotherBackupTableName;
-          break;
-        }
-        ++suffix;
-      } while (true);
-    }
-
-    this->create_table(db, backupTableName, tableImpl);
-
-    tableImpl.copy_table(db, backupTableName, columnsToIgnore);
-
-    this->drop_table_internal(tableImpl.table.name, db);
-
-    tableImpl.rename_table(db, backupTableName, tableImpl.table.name);
-  }
-
-  template <class O> void assert_mapped_type() const {
-    using mapped_types_tuples = std::tuple<typename Ts::object_type...>;
-    static_assert(
-        tuple_helper::has_type<O, mapped_types_tuples>::value,
-        "type is not mapped to a storage");
-  }
-
-  template <class O> auto &get_impl() const {
-    return this->impl.template get_impl<O>();
-  }
-
-  template <class O> auto &get_impl() {
-    return this->impl.template get_impl<O>();
-  }
-
-public:
-  template <class T, class... Args>
-  view_t<T, self, Args...> iterate(Args &&... args) {
-    this->assert_mapped_type<T>();
-
-    auto con = this->get_connection();
-    return {*this, std::move(con), std::forward<Args>(args)...};
-  }
-
-  /**
-   * Delete from routine.
-   * O is an object's type. Must be specified explicitly.
-   * @param args optional conditions: `where`, `join` etc
-   * @example: storage.remove_all<User>(); - DELETE FROM users
-   * @example: storage.remove_all<User>(where(in(&User::id, {5, 6, 7}))); -
-   * DELETE FROM users WHERE id IN (5, 6, 7)
-   */
-  template <class O, class... Args> void remove_all(Args &&... args) {
-    this->assert_mapped_type<O>();
-    auto statement =
-        this->prepare(sqlite_orm::remove_all<O>(std::forward<Args>(args)...));
-    this->execute(statement);
-  }
-
-  /**
-   *  Delete routine.
-   *  O is an object's type. Must be specified explicitly.
-   *  @param ids ids of object to be removed.
-   */
-  template <class O, class... Ids> void remove(Ids... ids) {
-    this->assert_mapped_type<O>();
-    auto statement =
-        this->prepare(sqlite_orm::remove<O>(std::forward<Ids>(ids)...));
-    this->execute(statement);
-  }
-
-  /**
-   *  Update routine. Sets all non primary key fields where primary key is
-   * equal. O is an object type. May be not specified explicitly cause it can be
-   * deduced by compiler from first parameter.
-   *  @param o object to be updated.
-   */
-  template <class O> void update(const O &o) {
-    this->assert_mapped_type<O>();
-    auto statement = this->prepare(sqlite_orm::update(std::ref(o)));
-    this->execute(statement);
-  }
-
-  template <class... Args, class... Wargs>
-  void update_all(internal::set_t<Args...> set, Wargs... wh) {
-    auto statement = this->prepare(
-        sqlite_orm::update_all(std::move(set), std::forward<Wargs>(wh)...));
-    this->execute(statement);
-  }
-
-protected:
-  template <class F, class O, class... Args>
-  std::string group_concat_internal(
-      F O::*m,
-      std::unique_ptr<std::string> y,
-      Args &&... args) {
-    this->assert_mapped_type<O>();
-    std::vector<std::string> rows;
-    if (y) {
-      rows = this->select(
-          sqlite_orm::group_concat(m, move(*y)), std::forward<Args>(args)...);
-    } else {
-      rows = this->select(
-          sqlite_orm::group_concat(m), std::forward<Args>(args)...);
-    }
-    if (!rows.empty()) {
-      return move(rows.front());
-    } else {
-      return {};
-    }
-  }
-
-public:
-  /**
-   *  SELECT * routine.
-   *  O is an object type to be extracted. Must be specified explicitly.
-   *  @return All objects of type O stored in database at the moment in
-   * `std::vector`.
-   *  @note If you need to return the result in a different container type then
-   * use a different `get_all` function overload `get_all<User,
-   * std::list<User>>`
-   *  @example: storage.get_all<User>() - SELECT * FROM users
-   *  @example: storage.get_all<User>(where(like(&User::name, "N%")),
-   * order_by(&User::id)); - SELECT * FROM users WHERE name LIKE 'N%' ORDER BY
-   * id
-   */
-  template <class O, class... Args> auto get_all(Args &&... args) {
-    this->assert_mapped_type<O>();
-    auto statement =
-        this->prepare(sqlite_orm::get_all<O>(std::forward<Args>(args)...));
-    return this->execute(statement);
-  }
-
-  /**
-   *  SELECT * routine.
-   *  O is an object type to be extracted. Must be specified explicitly.
-   *  R is an explicit return type. This type must have `push_back(O &&)`
-   * function.
-   *  @return All objects of type O stored in database at the moment in `R`.
-   *  @example: storage.get_all<User, std::list<User>>(); - SELECT * FROM users
-   *  @example: storage.get_all<User, std::list<User>>(where(like(&User::name,
-   * "N%")), order_by(&User::id)); - SELECT * FROM users WHERE name LIKE 'N%'
-   * ORDER BY id
-   */
-  template <class O, class R, class... Args> auto get_all(Args &&... args) {
-    this->assert_mapped_type<O>();
-    auto statement =
-        this->prepare(sqlite_orm::get_all<O, R>(std::forward<Args>(args)...));
-    return this->execute(statement);
-  }
-
-  /**
-   *  SELECT * routine.
-   *  O is an object type to be extracted. Must be specified explicitly.
-   *  @return All objects of type O as `std::unique_ptr<O>` inside a
-   * `std::vector` stored in database at the moment.
-   *  @note If you need to return the result in a different container type then
-   * use a different `get_all_pointer` function overload `get_all_pointer<User,
-   * std::list<User>>`
-   *  @example: storage.get_all_pointer<User>(); - SELECT * FROM users
-   *  @example: storage.get_all_pointer<User>(where(length(&User::name) > 6)); -
-   * SELECT * FROM users WHERE LENGTH(name)  > 6
-   */
-  template <class O, class... Args> auto get_all_pointer(Args &&... args) {
-    this->assert_mapped_type<O>();
-    auto statement = this->prepare(
-        sqlite_orm::get_all_pointer<O>(std::forward<Args>(args)...));
-    return this->execute(statement);
-  }
-
-  /**
-   *  SELECT * routine.
-   *  O is an object type to be extracted. Must be specified explicitly.
-   *  R is a container type. std::vector<std::unique_ptr<O>> is default
-   *  @return All objects of type O as std::unique_ptr<O> stored in database at
-   * the moment.
-   *  @example: storage.get_all_pointer<User, std::list<User>>(); - SELECT *
-   * FROM users
-   *  @example: storage.get_all_pointer<User,
-   * std::list<User>>(where(length(&User::name) > 6)); - SELECT * FROM users
-   * WHERE LENGTH(name)  > 6
-   */
-  template <class O, class R, class... Args>
-  auto get_all_pointer(Args &&... args) {
-    this->assert_mapped_type<O>();
-    auto statement = this->prepare(
-        sqlite_orm::get_all_pointer<O, R>(std::forward<Args>(args)...));
-    return this->execute(statement);
-  }
-
-  /**
-   *  Select * by id routine.
-   *  throws std::system_error(orm_error_code::not_found, orm_error_category) if
-   * object not found with given id. throws std::system_error with
-   * orm_error_category in case of db error. O is an object type to be
-   * extracted. Must be specified explicitly.
-   *  @return Object of type O where id is equal parameter passed or throws
-   * `std::system_error(orm_error_code::not_found, orm_error_category)` if there
-   * is no object with such id.
-   */
-  template <class O, class... Ids> O get(Ids... ids) {
-    this->assert_mapped_type<O>();
-    auto statement =
-        this->prepare(sqlite_orm::get<O>(std::forward<Ids>(ids)...));
-    return this->execute(statement);
-  }
-
-  /**
-   *  The same as `get` function but doesn't throw an exception if noting found
-   * but returns std::unique_ptr with null value. throws std::system_error in
-   * case of db error.
-   */
-  template <class O, class... Ids> std::unique_ptr<O> get_pointer(Ids... ids) {
-    this->assert_mapped_type<O>();
-    auto statement =
-        this->prepare(sqlite_orm::get_pointer<O>(std::forward<Ids>(ids)...));
-    return this->execute(statement);
-  }
-
-  /**
-   * A previous version of get_pointer() that returns a shared_ptr
-   * instead of a unique_ptr. New code should prefer get_pointer()
-   * unless the data needs to be shared.
-   *
-   * @note
-   * Most scenarios don't need shared ownership of data, so we should prefer
-   * unique_ptr when possible. It's more efficient, doesn't require atomic
-   * ops for a reference count (which can cause major slowdowns on
-   * weakly-ordered platforms like ARM), and can be easily promoted to a
-   * shared_ptr, exactly like we're doing here.
-   * (Conversely, you _can't_ go from shared back to unique.)
-   */
-  template <class O, class... Ids> std::shared_ptr<O> get_no_throw(Ids... ids) {
-    return std::shared_ptr<O>(get_pointer<O>(std::forward<Ids>(ids)...));
-  }
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-  /**
-   *  The same as `get` function but doesn't throw an exception if noting found
-   * but returns an empty std::optional. throws std::system_error in case of db
-   * error.
-   */
-  template <class O, class... Ids> std::optional<O> get_optional(Ids... ids) {
-    this->assert_mapped_type<O>();
-    auto statement =
-        this->prepare(sqlite_orm::get_optional<O>(std::forward<Ids>(ids)...));
-    return this->execute(statement);
-  }
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-  /**
-   *  SELECT COUNT(*) https://www.sqlite.org/lang_aggfunc.html#count
-   *  @return Number of O object in table.
-   */
-  template <
-      class O,
-      class... Args,
-      class R = typename mapped_type_proxy<O>::type>
-  int count(Args &&... args) {
-    this->assert_mapped_type<R>();
-    auto rows =
-        this->select(sqlite_orm::count<R>(), std::forward<Args>(args)...);
-    if (!rows.empty()) {
-      return rows.front();
-    } else {
-      return 0;
-    }
-  }
-
-  /**
-   *  SELECT COUNT(X) https://www.sqlite.org/lang_aggfunc.html#count
-   *  @param m member pointer to class mapped to the storage.
-   */
-  template <class F, class O, class... Args>
-  int count(F O::*m, Args &&... args) {
-    this->assert_mapped_type<O>();
-    auto rows = this->select(sqlite_orm::count(m), std::forward<Args>(args)...);
-    if (!rows.empty()) {
-      return rows.front();
-    } else {
-      return 0;
-    }
-  }
-
-  /**
-   *  AVG(X) query.   https://www.sqlite.org/lang_aggfunc.html#avg
-   *  @param m is a class member pointer (the same you passed into make_column).
-   *  @return average value from db.
-   */
-  template <class F, class O, class... Args>
-  double avg(F O::*m, Args &&... args) {
-    this->assert_mapped_type<O>();
-    auto rows = this->select(sqlite_orm::avg(m), std::forward<Args>(args)...);
-    if (!rows.empty()) {
-      return rows.front();
-    } else {
-      return 0;
-    }
-  }
-
-  template <class F, class O> std::string group_concat(F O::*m) {
-    return this->group_concat_internal(m, {});
-  }
-
-  /**
-   *  GROUP_CONCAT(X) query.
-   * https://www.sqlite.org/lang_aggfunc.html#groupconcat
-   *  @param m is a class member pointer (the same you passed into make_column).
-   *  @return group_concat query result.
-   */
-  template <
-      class F,
-      class O,
-      class... Args,
-      class Tuple = std::tuple<Args...>,
-      typename sfinae =
-          typename std::enable_if<std::tuple_size<Tuple>::value >= 1>::type>
-  std::string group_concat(F O::*m, Args &&... args) {
-    return this->group_concat_internal(m, {}, std::forward<Args>(args)...);
-  }
-
-  /**
-   *  GROUP_CONCAT(X, Y) query.
-   * https://www.sqlite.org/lang_aggfunc.html#groupconcat
-   *  @param m is a class member pointer (the same you passed into make_column).
-   *  @return group_concat query result.
-   */
-  template <class F, class O, class... Args>
-  std::string group_concat(F O::*m, std::string y, Args &&... args) {
-    return this->group_concat_internal(
-        m, std::make_unique<std::string>(move(y)), std::forward<Args>(args)...);
-  }
-
-  template <class F, class O, class... Args>
-  std::string group_concat(F O::*m, const char *y, Args &&... args) {
-    std::unique_ptr<std::string> str;
-    if (y) {
-      str = std::make_unique<std::string>(y);
-    } else {
-      str = std::make_unique<std::string>();
-    }
-    return this->group_concat_internal(
-        m, move(str), std::forward<Args>(args)...);
-  }
-
-  /**
-   *  MAX(x) query.
-   *  @param m is a class member pointer (the same you passed into make_column).
-   *  @return std::unique_ptr with max value or null if sqlite engine returned
-   * null.
-   */
-  template <
-      class F,
-      class O,
-      class... Args,
-      class Ret = typename column_result_t<self, F O::*>::type>
-  std::unique_ptr<Ret> max(F O::*m, Args &&... args) {
-    this->assert_mapped_type<O>();
-    auto rows = this->select(sqlite_orm::max(m), std::forward<Args>(args)...);
-    if (!rows.empty()) {
-      return std::move(rows.front());
-    } else {
-      return {};
-    }
-  }
-
-  /**
-   *  MIN(x) query.
-   *  @param m is a class member pointer (the same you passed into make_column).
-   *  @return std::unique_ptr with min value or null if sqlite engine returned
-   * null.
-   */
-  template <
-      class F,
-      class O,
-      class... Args,
-      class Ret = typename column_result_t<self, F O::*>::type>
-  std::unique_ptr<Ret> min(F O::*m, Args &&... args) {
-    this->assert_mapped_type<O>();
-    auto rows = this->select(sqlite_orm::min(m), std::forward<Args>(args)...);
-    if (!rows.empty()) {
-      return std::move(rows.front());
-    } else {
-      return {};
-    }
-  }
-
-  /**
-   *  SUM(x) query.
-   *  @param m is a class member pointer (the same you passed into make_column).
-   *  @return std::unique_ptr with sum value or null if sqlite engine returned
-   * null.
-   */
-  template <
-      class F,
-      class O,
-      class... Args,
-      class Ret = typename column_result_t<self, F O::*>::type>
-  std::unique_ptr<Ret> sum(F O::*m, Args &&... args) {
-    this->assert_mapped_type<O>();
-    std::vector<std::unique_ptr<double>> rows =
-        this->select(sqlite_orm::sum(m), std::forward<Args>(args)...);
-    if (!rows.empty()) {
-      if (rows.front()) {
-        return std::make_unique<Ret>(std::move(*rows.front()));
-      } else {
-        return {};
-      }
-    } else {
-      return {};
-    }
-  }
-
-  /**
-   *  TOTAL(x) query.
-   *  @param m is a class member pointer (the same you passed into make_column).
-   *  @return total value (the same as SUM but not nullable. More details here
-   * https://www.sqlite.org/lang_aggfunc.html)
-   */
-  template <class F, class O, class... Args>
-  double total(F O::*m, Args &&... args) {
-    this->assert_mapped_type<O>();
-    auto rows = this->select(sqlite_orm::total(m), std::forward<Args>(args)...);
-    if (!rows.empty()) {
-      return std::move(rows.front());
-    } else {
-      return {};
-    }
-  }
-
-  /**
-   *  Select a single column into std::vector<T> or multiple columns into
-   * std::vector<std::tuple<...>>. For a single column use `auto rows =
-   * storage.select(&User::id, where(...)); For multicolumns use `auto rows =
-   * storage.select(columns(&User::id, &User::name), where(...));
-   */
-  template <
-      class T,
-      class... Args,
-      class R = typename column_result_t<self, T>::type>
-  std::vector<R> select(T m, Args... args) {
-    static_assert(
-        !is_base_of_template<T, compound_operator>::value ||
-            std::tuple_size<std::tuple<Args...>>::value == 0,
-        "Cannot use args with a compound operator");
-    auto statement = this->prepare(
-        sqlite_orm::select(std::move(m), std::forward<Args>(args)...));
-    return this->execute(statement);
-  }
-
-  template <class T>
-  typename std::enable_if<is_prepared_statement<T>::value, std::string>::type
-  dump(const T &preparedStatement) const {
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    return serialize(preparedStatement.t, context);
-  }
-
-  /**
-   *  Returns a string representation of object of a class mapped to the
-   * storage. Type of string has json-like style.
-   */
-  template <class O>
-  typename std::enable_if<
-      storage_traits::type_is_mapped<self, O>::value,
-      std::string>::type
-  dump(const O &o) {
-    auto &tImpl = this->get_impl<O>();
-    std::stringstream ss;
-    ss << "{ ";
-    using pair = std::pair<std::string, std::string>;
-    std::vector<pair> pairs;
-    tImpl.table.for_each_column([&pairs, &o](auto &c) {
-      using column_type = typename std::decay<decltype(c)>::type;
-      using field_type = typename column_type::field_type;
-      pair p{c.name, std::string()};
-      if (c.member_pointer) {
-        p.second = field_printer<field_type>()(o.*c.member_pointer);
-      } else {
-        using getter_type = typename column_type::getter_type;
-        field_value_holder<getter_type> valueHolder{((o).*(c.getter))()};
-        p.second = field_printer<field_type>()(valueHolder.value);
-      }
-      pairs.push_back(move(p));
-    });
-    for (size_t i = 0; i < pairs.size(); ++i) {
-      auto &p = pairs[i];
-      ss << p.first << " : '" << p.second << "'";
-      if (i < pairs.size() - 1) {
-        ss << ", ";
-      } else {
-        ss << " }";
-      }
-    }
-    return ss.str();
-  }
-
-  /**
-   *  This is REPLACE (INSERT OR REPLACE) function.
-   *  Also if you need to insert value with knows id you should
-   *  also you this function instead of insert cause inserts ignores
-   *  id and creates own one.
-   */
-  template <class O> void replace(const O &o) {
-    this->assert_mapped_type<O>();
-    auto statement = this->prepare(sqlite_orm::replace(std::ref(o)));
-    this->execute(statement);
-  }
-
-  template <class It> void replace_range(It from, It to) {
-    using O = typename std::iterator_traits<It>::value_type;
-    this->assert_mapped_type<O>();
-    if (from == to) {
-      return;
-    }
-
-    auto statement = this->prepare(sqlite_orm::replace_range(from, to));
-    this->execute(statement);
-  }
-
-  template <class O, class... Cols>
-  int insert(const O &o, columns_t<Cols...> cols) {
-    constexpr const size_t colsCount =
-        std::tuple_size<std::tuple<Cols...>>::value;
-    static_assert(
-        colsCount > 0, "Use insert or replace with 1 argument instead");
-    this->assert_mapped_type<O>();
-    auto statement =
-        this->prepare(sqlite_orm::insert(std::ref(o), std::move(cols)));
-    return int(this->execute(statement));
-  }
-
-  /**
-   *  Insert routine. Inserts object with all non primary key fields in passed
-   * object. Id of passed object doesn't matter.
-   *  @return id of just created object.
-   */
-  template <class O> int insert(const O &o) {
-    this->assert_mapped_type<O>();
-    auto statement = this->prepare(sqlite_orm::insert(std::ref(o)));
-    return int(this->execute(statement));
-  }
-
-  template <class It> void insert_range(It from, It to) {
-    using O = typename std::iterator_traits<It>::value_type;
-    this->assert_mapped_type<O>();
-    if (from == to) {
-      return;
-    }
-
-    auto statement = this->prepare(sqlite_orm::insert_range(from, to));
-    this->execute(statement);
-  }
-
-  /**
-   * Change table name inside storage's schema info. This function does not
-   * affect database
-   */
-  template <class O> void rename_table(std::string name) {
-    this->assert_mapped_type<O>();
-    auto &tImpl = this->get_impl<O>();
-    tImpl.table.name = move(name);
-  }
-
-  using storage_base::rename_table;
-
-  /**
-   * Get table's name stored in storage's schema info. This function does not
-   * call any SQLite queries
-   */
-  template <class O> const std::string &tablename() const {
-    this->assert_mapped_type<O>();
-    auto &tImpl = this->get_impl<O>();
-    return tImpl.table.name;
-  }
-
-protected:
-  template <class... Tss, class... Cols>
-  sync_schema_result sync_table(
-      const storage_impl<index_t<Cols...>, Tss...> &tableImpl,
-      sqlite3 *db,
-      bool) {
-    auto res = sync_schema_result::already_in_sync;
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    auto query = serialize(tableImpl.table, context);
-    auto rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr);
-    if (rc != SQLITE_OK) {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-    return res;
-  }
-
-  template <class... Tss, class... Cs>
-  sync_schema_result sync_table(
-      const storage_impl<table_t<Cs...>, Tss...> &tImpl,
-      sqlite3 *db,
-      bool preserve) {
-    auto res = sync_schema_result::already_in_sync;
-
-    auto schema_stat = tImpl.schema_status(db, preserve);
-    if (schema_stat != decltype(schema_stat)::already_in_sync) {
-      if (schema_stat == decltype(schema_stat)::new_table_created) {
-        this->create_table(db, tImpl.table.name, tImpl);
-        res = decltype(res)::new_table_created;
-      } else {
-        if (schema_stat == sync_schema_result::old_columns_removed ||
-            schema_stat == sync_schema_result::new_columns_added ||
-            schema_stat ==
-                sync_schema_result::new_columns_added_and_old_columns_removed) {
-
-          //  get table info provided in `make_table` call..
-          auto storageTableInfo = tImpl.table.get_table_info();
-
-          //  now get current table info from db using `PRAGMA table_info`
-          //  query..
-          auto dbTableInfo = tImpl.get_table_info(tImpl.table.name, db);
-
-          //  this vector will contain pointers to columns that gotta be added..
-          std::vector<table_info *> columnsToAdd;
-
-          tImpl.get_remove_add_columns(
-              columnsToAdd, storageTableInfo, dbTableInfo);
-
-          if (schema_stat == sync_schema_result::old_columns_removed) {
-
-            //  extra table columns than storage columns
-            this->backup_table(db, tImpl, {});
-            res = decltype(res)::old_columns_removed;
-          }
-
-          if (schema_stat == sync_schema_result::new_columns_added) {
-            for (auto columnPointer : columnsToAdd) {
-              tImpl.add_column(*columnPointer, db);
-            }
-            res = decltype(res)::new_columns_added;
-          }
-
-          if (schema_stat ==
-              sync_schema_result::new_columns_added_and_old_columns_removed) {
-
-            // remove extra columns
-            this->backup_table(db, tImpl, columnsToAdd);
-            res = decltype(res)::new_columns_added_and_old_columns_removed;
-          }
-        } else if (schema_stat == sync_schema_result::dropped_and_recreated) {
-          this->drop_table_internal(tImpl.table.name, db);
-          this->create_table(db, tImpl.table.name, tImpl);
-          res = decltype(res)::dropped_and_recreated;
-        }
-      }
-    }
-    return res;
-  }
-
-public:
-  /**
-   *  This is a cute function used to replace migration up/down functionality.
-   *  It performs check storage schema with actual db schema and:
-   *  * if there are excess tables exist in db they are ignored (not dropped)
-   *  * every table from storage is compared with it's db analog and
-   *      * if table doesn't exist it is being created
-   *      * if table exists its colums are being compared with table_info from
-   * db and
-   *          * if there are columns in db that do not exist in storage (excess)
-   * table will be dropped and recreated
-   *          * if there are columns in storage that do not exist in db they
-   * will be added using `ALTER TABLE
-   * ... ADD COLUMN ...' command
-   *          * if there is any column existing in both db and storage but
-   * differs by any of properties/constraints (type, pk, notnull, dflt_value)
-   * table will be dropped and recreated Be aware that `sync_schema` doesn't
-   * guarantee that data will not be dropped. It guarantees only that it will
-   * make db schema the same as you specified in `make_storage` function call. A
-   * good point is that if you have no db file at all it will be created and all
-   * tables also will be created with exact tables and columns you specified in
-   * `make_storage`, `make_table` and `make_column` call. The best practice is
-   * to call this function right after storage creation.
-   *  @param preserve affects on function behaviour in case it is needed to
-   * remove a column. If it is `false` so table will be dropped if there is
-   * column to remove, if `true` -  table is being copied into another table,
-   * dropped and copied table is renamed with source table name. Warning:
-   * sync_schema doesn't check foreign keys cause it is unable to do so in
-   * sqlite3. If you know how to get foreign key info please submit an issue
-   * https://github.com/fnc12/sqlite_orm/issues
-   *  @return std::map with std::string key equal table name and
-   * `sync_schema_result` as value. `sync_schema_result` is a enum value that
-   * stores table state after syncing a schema. `sync_schema_result` can be
-   * printed out on std::ostream with `operator<<`.
-   */
-  std::map<std::string, sync_schema_result> sync_schema(bool preserve = false) {
-    auto con = this->get_connection();
-    std::map<std::string, sync_schema_result> result;
-    auto db = con.get();
-    this->impl.for_each([&result, db, preserve, this](auto &tableImpl) {
-      auto res = this->sync_table(tableImpl, db, preserve);
-      result.insert({tableImpl.table.name, res});
-    });
-    return result;
-  }
-
-  /**
-   *  This function returns the same map that `sync_schema` returns but it
-   *  doesn't perform `sync_schema` actually - just simulates it in case you
-   * want to know what will happen if you sync your schema.
-   */
-  std::map<std::string, sync_schema_result>
-  sync_schema_simulate(bool preserve = false) {
-    auto con = this->get_connection();
-    std::map<std::string, sync_schema_result> result;
-    auto db = con.get();
-    this->impl.for_each([&result, db, preserve](auto tableImpl) {
-      result.insert(
-          {tableImpl.table.name, tableImpl.schema_status(db, preserve)});
-    });
-    return result;
-  }
-
-  /**
-   *  Checks whether table exists in db. Doesn't check storage itself - works
-   * only with actual database. Note: table can be not mapped to a storage
-   *  @return true if table with a given name exists in db, false otherwise.
-   */
-  bool table_exists(const std::string &tableName) {
-    auto con = this->get_connection();
-    return this->impl.table_exists(tableName, con.get());
-  }
-
-  template <class T, class... Args>
-  prepared_statement_t<select_t<T, Args...>> prepare(select_t<T, Args...> sel) {
-    sel.highest_level = true;
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(sel, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(sel), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T, class... Args>
-  prepared_statement_t<get_all_t<T, Args...>>
-  prepare(get_all_t<T, Args...> get_) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(get_, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(get_), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T, class... Args>
-  prepared_statement_t<get_all_pointer_t<T, Args...>>
-  prepare(get_all_pointer_t<T, Args...> get_) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(get_, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(get_), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-  template <class T, class R, class... Args>
-  prepared_statement_t<get_all_optional_t<T, R, Args...>>
-  prepare(get_all_optional_t<T, R, Args...> get_) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(get_, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(get_), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-  template <class... Args, class... Wargs>
-  prepared_statement_t<update_all_t<set_t<Args...>, Wargs...>>
-  prepare(update_all_t<set_t<Args...>, Wargs...> upd) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(upd, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(upd), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T, class... Args>
-  prepared_statement_t<remove_all_t<T, Args...>>
-  prepare(remove_all_t<T, Args...> rem) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(rem, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(rem), stmt, std::move(con)};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T, class... Ids>
-  prepared_statement_t<get_t<T, Ids...>> prepare(get_t<T, Ids...> get_) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(get_, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(get_), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T, class... Ids>
-  prepared_statement_t<get_pointer_t<T, Ids...>>
-  prepare(get_pointer_t<T, Ids...> get_) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(get_, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(get_), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-  template <class T, class... Ids>
-  prepared_statement_t<get_optional_t<T, Ids...>>
-  prepare(get_optional_t<T, Ids...> get_) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(get_, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(get_), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-  template <class T>
-  prepared_statement_t<update_t<T>> prepare(update_t<T> upd) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(upd, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(upd), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T, class... Ids>
-  prepared_statement_t<remove_t<T, Ids...>> prepare(remove_t<T, Ids...> rem) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(rem, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(rem), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T>
-  prepared_statement_t<insert_t<T>> prepare(insert_t<T> ins) {
-    using object_type = typename expression_object_type<decltype(ins)>::type;
-    this->assert_mapped_type<object_type>();
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(ins, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(ins), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T>
-  prepared_statement_t<replace_t<T>> prepare(replace_t<T> rep) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    using object_type = typename expression_object_type<decltype(rep)>::type;
-    this->assert_mapped_type<object_type>();
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(rep, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(rep), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class It>
-  prepared_statement_t<insert_range_t<It>>
-  prepare(insert_range_t<It> statement) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(statement, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(statement), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class It>
-  prepared_statement_t<replace_range_t<It>> prepare(replace_range_t<It> rep) {
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(rep, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(rep), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T, class... Cols>
-  prepared_statement_t<insert_explicit<T, Cols...>>
-  prepare(insert_explicit<T, Cols...> ins) {
-    using object_type = typename expression_object_type<decltype(ins)>::type;
-    this->assert_mapped_type<object_type>();
-    auto con = this->get_connection();
-    sqlite3_stmt *stmt;
-    auto db = con.get();
-    using context_t = serializator_context<impl_type>;
-    context_t context{this->impl};
-    context.skip_table_name = false;
-    context.replace_bindable_with_question = true;
-    auto query = serialize(ins, context);
-    if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) ==
-        SQLITE_OK) {
-      return {std::move(ins), stmt, con};
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T, class... Cols>
-  int64
-  execute(const prepared_statement_t<insert_explicit<T, Cols...>> &statement) {
-    using statement_type = typename std::decay<decltype(statement)>::type;
-    using expression_type = typename statement_type::expression_type;
-    using object_type = typename expression_object_type<expression_type>::type;
-    auto index = 1;
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto &tImpl = this->get_impl<object_type>();
-    auto &o = statement.t.obj;
-    sqlite3_reset(stmt);
-    iterate_tuple(
-        statement.t.columns.columns, [&o, &index, &stmt, &tImpl, db](auto &m) {
-          using column_type = typename std::decay<decltype(m)>::type;
-          using field_type = typename column_result_t<self, column_type>::type;
-          const field_type *value =
-              tImpl.table.template get_object_field_pointer<field_type>(o, m);
-          if (SQLITE_OK !=
-              statement_binder<field_type>().bind(stmt, index++, *value)) {
-            throw std::system_error(
-                std::error_code(
-                    sqlite3_errcode(db), get_sqlite_error_category()),
-                sqlite3_errmsg(db));
-          }
-        });
-    if (sqlite3_step(stmt) == SQLITE_DONE) {
-      return sqlite3_last_insert_rowid(db);
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class It>
-  void execute(const prepared_statement_t<replace_range_t<It>> &statement) {
-    using statement_type = typename std::decay<decltype(statement)>::type;
-    using expression_type = typename statement_type::expression_type;
-    using object_type = typename expression_type::object_type;
-    auto &tImpl = this->get_impl<object_type>();
-    auto index = 1;
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    sqlite3_reset(stmt);
-    for (auto it = statement.t.range.first; it != statement.t.range.second;
-         ++it) {
-      auto &o = *it;
-      tImpl.table.for_each_column([&o, &index, &stmt, db](auto &c) {
-        using column_type = typename std::decay<decltype(c)>::type;
-        using field_type = typename column_type::field_type;
-        if (c.member_pointer) {
-          if (SQLITE_OK != statement_binder<field_type>().bind(
-                               stmt, index++, o.*c.member_pointer)) {
-            throw std::system_error(
-                std::error_code(
-                    sqlite3_errcode(db), get_sqlite_error_category()),
-                sqlite3_errmsg(db));
-          }
-        } else {
-          using getter_type = typename column_type::getter_type;
-          field_value_holder<getter_type> valueHolder{((o).*(c.getter))()};
-          if (SQLITE_OK != statement_binder<field_type>().bind(
-                               stmt, index++, valueHolder.value)) {
-            throw std::system_error(
-                std::error_code(
-                    sqlite3_errcode(db), get_sqlite_error_category()),
-                sqlite3_errmsg(db));
-          }
-        }
-      });
-    }
-    if (sqlite3_step(stmt) == SQLITE_DONE) {
-      //..
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class It>
-  void execute(const prepared_statement_t<insert_range_t<It>> &statement) {
-    using statement_type = typename std::decay<decltype(statement)>::type;
-    using expression_type = typename statement_type::expression_type;
-    using object_type = typename expression_type::object_type;
-    auto index = 1;
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto &tImpl = this->get_impl<object_type>();
-    sqlite3_reset(stmt);
-    for (auto it = statement.t.range.first; it != statement.t.range.second;
-         ++it) {
-      auto &o = *it;
-      tImpl.table.for_each_column([&o, &index, &stmt, db](auto &c) {
-        if (!c.template has<constraints::primary_key_t<>>()) {
-          using column_type = typename std::decay<decltype(c)>::type;
-          using field_type = typename column_type::field_type;
-          if (c.member_pointer) {
-            if (SQLITE_OK != statement_binder<field_type>().bind(
-                                 stmt, index++, o.*c.member_pointer)) {
-              throw std::system_error(
-                  std::error_code(
-                      sqlite3_errcode(db), get_sqlite_error_category()),
-                  sqlite3_errmsg(db));
-            }
-          } else {
-            using getter_type = typename column_type::getter_type;
-            field_value_holder<getter_type> valueHolder{((o).*(c.getter))()};
-            if (SQLITE_OK != statement_binder<field_type>().bind(
-                                 stmt, index++, valueHolder.value)) {
-              throw std::system_error(
-                  std::error_code(
-                      sqlite3_errcode(db), get_sqlite_error_category()),
-                  sqlite3_errmsg(db));
-            }
-          }
-        }
-      });
-    }
-    if (sqlite3_step(stmt) == SQLITE_DONE) {
-      //..
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T>
-  void execute(const prepared_statement_t<replace_t<T>> &statement) {
-    using statement_type = typename std::decay<decltype(statement)>::type;
-    using expression_type = typename statement_type::expression_type;
-    using object_type = typename expression_object_type<expression_type>::type;
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    auto &o = get_object(statement.t);
-    auto &tImpl = this->get_impl<object_type>();
-    sqlite3_reset(stmt);
-    tImpl.table.for_each_column([&o, &index, &stmt, db](auto &c) {
-      using column_type = typename std::decay<decltype(c)>::type;
-      using field_type = typename column_type::field_type;
-      if (c.member_pointer) {
-        if (SQLITE_OK != statement_binder<field_type>().bind(
-                             stmt, index++, o.*c.member_pointer)) {
-          throw std::system_error(
-              std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-              sqlite3_errmsg(db));
-        }
-      } else {
-        using getter_type = typename column_type::getter_type;
-        field_value_holder<getter_type> valueHolder{((o).*(c.getter))()};
-        if (SQLITE_OK != statement_binder<field_type>().bind(
-                             stmt, index++, valueHolder.value)) {
-          throw std::system_error(
-              std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-              sqlite3_errmsg(db));
-        }
-      }
-    });
-    if (sqlite3_step(stmt) == SQLITE_DONE) {
-      //..
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T>
-  int64 execute(const prepared_statement_t<insert_t<T>> &statement) {
-    using statement_type = typename std::decay<decltype(statement)>::type;
-    using expression_type = typename statement_type::expression_type;
-    using object_type = typename expression_object_type<expression_type>::type;
-    int64 res = 0;
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    auto &tImpl = this->get_impl<object_type>();
-    auto &o = get_object(statement.t);
-    auto compositeKeyColumnNames = tImpl.table.composite_key_columns_names();
-    sqlite3_reset(stmt);
-    tImpl.table.for_each_column(
-        [&o, &index, &stmt, &tImpl, &compositeKeyColumnNames, db](auto &c) {
-          if (tImpl.table._without_rowid ||
-              !c.template has<constraints::primary_key_t<>>()) {
-            auto it = std::find(
-                compositeKeyColumnNames.begin(),
-                compositeKeyColumnNames.end(),
-                c.name);
-            if (it == compositeKeyColumnNames.end()) {
-              using column_type = typename std::decay<decltype(c)>::type;
-              using field_type = typename column_type::field_type;
-              if (c.member_pointer) {
-                if (SQLITE_OK != statement_binder<field_type>().bind(
-                                     stmt, index++, o.*c.member_pointer)) {
-                  throw std::system_error(
-                      std::error_code(
-                          sqlite3_errcode(db), get_sqlite_error_category()),
-                      sqlite3_errmsg(db));
-                }
-              } else {
-                using getter_type = typename column_type::getter_type;
-                field_value_holder<getter_type> valueHolder{
-                    ((o).*(c.getter))()};
-                if (SQLITE_OK != statement_binder<field_type>().bind(
-                                     stmt, index++, valueHolder.value)) {
-                  throw std::system_error(
-                      std::error_code(
-                          sqlite3_errcode(db), get_sqlite_error_category()),
-                      sqlite3_errmsg(db));
-                }
-              }
-            }
-          }
-        });
-    if (sqlite3_step(stmt) == SQLITE_DONE) {
-      res = sqlite3_last_insert_rowid(db);
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-    return res;
-  }
-
-  template <class T, class... Ids>
-  void execute(const prepared_statement_t<remove_t<T, Ids...>> &statement) {
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    sqlite3_reset(stmt);
-    iterate_ast(statement.t.ids, [stmt, &index, db](auto &v) {
-      using field_type = typename std::decay<decltype(v)>::type;
-      if (SQLITE_OK != statement_binder<field_type>().bind(stmt, index++, v)) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    });
-    if (sqlite3_step(stmt) == SQLITE_DONE) {
-      //  done..
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T>
-  void execute(const prepared_statement_t<update_t<T>> &statement) {
-    using statement_type = typename std::decay<decltype(statement)>::type;
-    using expression_type = typename statement_type::expression_type;
-    using object_type = typename expression_object_type<expression_type>::type;
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto &tImpl = this->get_impl<object_type>();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    auto &o = get_object(statement.t);
-    sqlite3_reset(stmt);
-    tImpl.table.for_each_column([&o, stmt, &index, db](auto &c) {
-      if (!c.template has<constraints::primary_key_t<>>()) {
-        using column_type = typename std::decay<decltype(c)>::type;
-        using field_type = typename column_type::field_type;
-        if (c.member_pointer) {
-          auto bind_res = statement_binder<field_type>().bind(
-              stmt, index++, o.*c.member_pointer);
-          if (SQLITE_OK != bind_res) {
-            throw std::system_error(
-                std::error_code(
-                    sqlite3_errcode(db), get_sqlite_error_category()),
-                sqlite3_errmsg(db));
-          }
-        } else {
-          using getter_type = typename column_type::getter_type;
-          field_value_holder<getter_type> valueHolder{((o).*(c.getter))()};
-          if (SQLITE_OK != statement_binder<field_type>().bind(
-                               stmt, index++, valueHolder.value)) {
-            throw std::system_error(
-                std::error_code(
-                    sqlite3_errcode(db), get_sqlite_error_category()),
-                sqlite3_errmsg(db));
-          }
-        }
-      }
-    });
-    tImpl.table.for_each_column([&o, stmt, &index, db](auto &c) {
-      if (c.template has<constraints::primary_key_t<>>()) {
-        using column_type = typename std::decay<decltype(c)>::type;
-        using field_type = typename column_type::field_type;
-        if (c.member_pointer) {
-          if (SQLITE_OK != statement_binder<field_type>().bind(
-                               stmt, index++, o.*c.member_pointer)) {
-            throw std::system_error(
-                std::error_code(
-                    sqlite3_errcode(db), get_sqlite_error_category()),
-                sqlite3_errmsg(db));
-          }
-        } else {
-          using getter_type = typename column_type::getter_type;
-          field_value_holder<getter_type> valueHolder{((o).*(c.getter))()};
-          if (SQLITE_OK != statement_binder<field_type>().bind(
-                               stmt, index++, valueHolder.value)) {
-            throw std::system_error(
-                std::error_code(
-                    sqlite3_errcode(db), get_sqlite_error_category()),
-                sqlite3_errmsg(db));
-          }
-        }
-      }
-    });
-    if (sqlite3_step(stmt) == SQLITE_DONE) {
-      //  done..
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class T, class... Ids>
-  std::unique_ptr<T>
-  execute(const prepared_statement_t<get_pointer_t<T, Ids...>> &statement) {
-    auto &tImpl = this->get_impl<T>();
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    sqlite3_reset(stmt);
-    iterate_ast(statement.t.ids, [stmt, &index, db](auto &v) {
-      using field_type = typename std::decay<decltype(v)>::type;
-      if (SQLITE_OK != statement_binder<field_type>().bind(stmt, index++, v)) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    });
-    auto stepRes = sqlite3_step(stmt);
-    switch (stepRes) {
-    case SQLITE_ROW: {
-      auto res = std::make_unique<T>();
-      object_from_column_builder<T> builder{*res, stmt};
-      tImpl.table.for_each_column(builder);
-      return res;
-    } break;
-    case SQLITE_DONE: {
-      return {};
-    } break;
-    default: {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-    }
-  }
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-  template <class T, class... Ids>
-  std::optional<T>
-  execute(const prepared_statement_t<get_optional_t<T, Ids...>> &statement) {
-    auto &tImpl = this->get_impl<T>();
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    sqlite3_reset(stmt);
-    iterate_ast(statement.t.ids, [stmt, &index, db](auto &v) {
-      using field_type = typename std::decay<decltype(v)>::type;
-      if (SQLITE_OK != statement_binder<field_type>().bind(stmt, index++, v)) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    });
-    auto stepRes = sqlite3_step(stmt);
-    switch (stepRes) {
-    case SQLITE_ROW: {
-      auto res = std::make_optional<T>();
-      object_from_column_builder<T> builder{res.value(), stmt};
-      tImpl.table.for_each_column(builder);
-      return res;
-    } break;
-    case SQLITE_DONE: {
-      return {};
-    } break;
-    default: {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-    }
-  }
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-  template <class T, class... Ids>
-  T execute(const prepared_statement_t<get_t<T, Ids...>> &statement) {
-    auto &tImpl = this->get_impl<T>();
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    sqlite3_reset(stmt);
-    iterate_ast(statement.t.ids, [stmt, &index, db](auto &v) {
-      using field_type = typename std::decay<decltype(v)>::type;
-      if (SQLITE_OK != statement_binder<field_type>().bind(stmt, index++, v)) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    });
-    auto stepRes = sqlite3_step(stmt);
-    switch (stepRes) {
-    case SQLITE_ROW: {
-      T res;
-      object_from_column_builder<T> builder{res, stmt};
-      tImpl.table.for_each_column(builder);
-      return res;
-    } break;
-    case SQLITE_DONE: {
-      throw std::system_error(
-          std::make_error_code(sqlite_orm::orm_error_code::not_found));
-    } break;
-    default: {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-    }
-  }
-
-  template <class T, class... Args>
-  void
-  execute(const prepared_statement_t<remove_all_t<T, Args...>> &statement) {
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    sqlite3_reset(stmt);
-    iterate_ast(statement.t.conditions, [stmt, &index, db](auto &node) {
-      using node_type = typename std::decay<decltype(node)>::type;
-      conditional_binder<node_type, is_bindable<node_type>> binder{stmt, index};
-      if (SQLITE_OK != binder(node)) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    });
-    if (sqlite3_step(stmt) == SQLITE_DONE) {
-      //  done..
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <class... Args, class... Wargs>
-  void
-  execute(const prepared_statement_t<update_all_t<set_t<Args...>, Wargs...>>
-              &statement) {
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    sqlite3_reset(stmt);
-    iterate_tuple(statement.t.set.assigns, [&index, stmt, db](auto &setArg) {
-      iterate_ast(setArg, [&index, stmt, db](auto &node) {
-        using node_type = typename std::decay<decltype(node)>::type;
-        conditional_binder<node_type, is_bindable<node_type>> binder{
-            stmt, index};
-        if (SQLITE_OK != binder(node)) {
-          throw std::system_error(
-              std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-              sqlite3_errmsg(db));
-        }
-      });
-    });
-    iterate_ast(statement.t.conditions, [stmt, &index, db](auto &node) {
-      using node_type = typename std::decay<decltype(node)>::type;
-      conditional_binder<node_type, is_bindable<node_type>> binder{stmt, index};
-      if (SQLITE_OK != binder(node)) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    });
-    if (sqlite3_step(stmt) == SQLITE_DONE) {
-      //  done..
-    } else {
-      throw std::system_error(
-          std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-          sqlite3_errmsg(db));
-    }
-  }
-
-  template <
-      class T,
-      class... Args,
-      class R = typename column_result_t<self, T>::type>
-  std::vector<R>
-  execute(const prepared_statement_t<select_t<T, Args...>> &statement) {
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    sqlite3_reset(stmt);
-    iterate_ast(statement.t, [stmt, &index, db](auto &node) {
-      using node_type = typename std::decay<decltype(node)>::type;
-      conditional_binder<node_type, is_bindable<node_type>> binder{stmt, index};
-      if (SQLITE_OK != binder(node)) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    });
-    std::vector<R> res;
-    auto tableInfoPointer = this->impl.template find_table<R>();
-    int stepRes;
-    do {
-      stepRes = sqlite3_step(stmt);
-      switch (stepRes) {
-      case SQLITE_ROW: {
-        using table_info_pointer_t =
-            typename std::remove_pointer<decltype(tableInfoPointer)>::type;
-        using table_info_t = typename std::decay<table_info_pointer_t>::type;
-        row_extractor_builder<
-            R,
-            storage_traits::type_is_mapped<self, R>::value,
-            table_info_t>
-            builder;
-        auto rowExtractor = builder(tableInfoPointer);
-        res.push_back(rowExtractor.extract(stmt, 0));
-      } break;
-      case SQLITE_DONE:
-        break;
-      default: {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-      }
-    } while (stepRes != SQLITE_DONE);
-    return res;
-  }
-
-  template <class T, class R, class... Args>
-  R execute(const prepared_statement_t<get_all_t<T, R, Args...>> &statement) {
-    auto &tImpl = this->get_impl<T>();
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    sqlite3_reset(stmt);
-    iterate_ast(statement.t, [stmt, &index, db](auto &node) {
-      using node_type = typename std::decay<decltype(node)>::type;
-      conditional_binder<node_type, is_bindable<node_type>> binder{stmt, index};
-      if (SQLITE_OK != binder(node)) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    });
-    R res;
-    int stepRes;
-    do {
-      stepRes = sqlite3_step(stmt);
-      switch (stepRes) {
-      case SQLITE_ROW: {
-        T obj;
-        object_from_column_builder<T> builder{obj, stmt};
-        tImpl.table.for_each_column(builder);
-        res.push_back(std::move(obj));
-      } break;
-      case SQLITE_DONE:
-        break;
-      default: {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-      }
-    } while (stepRes != SQLITE_DONE);
-    return res;
-  }
-
-  template <class T, class R, class... Args>
-  R execute(
-      const prepared_statement_t<get_all_pointer_t<T, R, Args...>> &statement) {
-    auto &tImpl = this->get_impl<T>();
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    sqlite3_reset(stmt);
-    iterate_ast(statement.t, [stmt, &index, db](auto &node) {
-      using node_type = typename std::decay<decltype(node)>::type;
-      conditional_binder<node_type, is_bindable<node_type>> binder{stmt, index};
-      if (SQLITE_OK != binder(node)) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    });
-    R res;
-    int stepRes;
-    do {
-      stepRes = sqlite3_step(stmt);
-      switch (stepRes) {
-      case SQLITE_ROW: {
-        auto obj = std::make_unique<T>();
-        object_from_column_builder<T> builder{*obj, stmt};
-        tImpl.table.for_each_column(builder);
-        res.push_back(move(obj));
-      } break;
-      case SQLITE_DONE:
-        break;
-      default: {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-      }
-    } while (stepRes != SQLITE_DONE);
-    return res;
-  }
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-  template <class T, class R, class... Args>
-  R execute(const prepared_statement_t<get_all_optional_t<T, R, Args...>>
-                &statement) {
-    auto &tImpl = this->get_impl<T>();
-    auto con = this->get_connection();
-    auto db = con.get();
-    auto stmt = statement.stmt;
-    auto index = 1;
-    sqlite3_reset(stmt);
-    iterate_ast(statement.t, [stmt, &index, db](auto &node) {
-      using node_type = typename std::decay<decltype(node)>::type;
-      conditional_binder<node_type, is_bindable<node_type>> binder{stmt, index};
-      if (SQLITE_OK != binder(node)) {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-    });
-    R res;
-    int stepRes;
-    do {
-      stepRes = sqlite3_step(stmt);
-      switch (stepRes) {
-      case SQLITE_ROW: {
-        auto obj = std::make_optional<T>();
-        object_from_column_builder<T> builder{*obj, stmt};
-        tImpl.table.for_each_column(builder);
-        res.push_back(move(obj));
-      } break;
-      case SQLITE_DONE:
-        break;
-      default: {
-        throw std::system_error(
-            std::error_code(sqlite3_errcode(db), get_sqlite_error_category()),
-            sqlite3_errmsg(db));
-      }
-      }
-    } while (stepRes != SQLITE_DONE);
-    return res;
-  }
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-};     // struct storage_t
-
-template <class T> struct is_storage : std::false_type {};
-
-template <class... Ts> struct is_storage<storage_t<Ts...>> : std::true_type {};
-} // namespace internal
-
-template <class... Ts>
-internal::storage_t<Ts...>
-make_storage(const std::string &filename, Ts... tables) {
-  return {filename, internal::storage_impl<Ts...>(tables...)};
-}
-
-/**
- *  sqlite3_threadsafe() interface.
- */
-inline int threadsafe() {
-  return sqlite3_threadsafe();
-}
-} // namespace sqlite_orm
-#pragma once
-
-#if defined(_MSC_VER)
-#if defined(__RESTORE_MIN__)
-__pragma(pop_macro("min"))
-#undef __RESTORE_MIN__
-#endif
-#if defined(__RESTORE_MAX__)
-    __pragma(pop_macro("max"))
-#undef __RESTORE_MAX__
-#endif
-#endif // defined(_MSC_VER)
-#pragma once
-
-#include <functional> //  std::reference_wrapper
-#include <tuple>      //  std::tuple
-#include <utility>    //  std::pair
-
-    // #include "conditions.h"
-
-    // #include "operators.h"
-
-    // #include "select_constraints.h"
-
-    // #include "prepared_statement.h"
-
-    // #include "optional_container.h"
-
-    // #include "core_functions.h"
-
-    namespace sqlite_orm {
-
-  namespace internal {
-
-  template <class T, class SFINAE = void> struct node_tuple {
-    using type = std::tuple<T>;
-  };
-
-  template <> struct node_tuple<void, void> { using type = std::tuple<>; };
-
-  template <class T> struct node_tuple<std::reference_wrapper<T>, void> {
-    using type = typename node_tuple<T>::type;
-  };
-
-  template <class C> struct node_tuple<where_t<C>, void> {
-    using node_type = where_t<C>;
-    using type = typename node_tuple<C>::type;
-  };
-
-  template <class T>
-  struct node_tuple<
-      T,
-      typename std::enable_if<
-          is_base_of_template<T, binary_condition>::value>::type> {
-    using node_type = T;
-    using left_type = typename node_type::left_type;
-    using right_type = typename node_type::right_type;
-    using left_node_tuple = typename node_tuple<left_type>::type;
-    using right_node_tuple = typename node_tuple<right_type>::type;
-    using type = typename conc_tuple<left_node_tuple, right_node_tuple>::type;
-  };
-
-  template <class L, class R, class... Ds>
-  struct node_tuple<binary_operator<L, R, Ds...>, void> {
-    using node_type = binary_operator<L, R, Ds...>;
-    using left_type = typename node_type::left_type;
-    using right_type = typename node_type::right_type;
-    using left_node_tuple = typename node_tuple<left_type>::type;
-    using right_node_tuple = typename node_tuple<right_type>::type;
-    using type = typename conc_tuple<left_node_tuple, right_node_tuple>::type;
-  };
-
-  template <class... Args> struct node_tuple<columns_t<Args...>, void> {
-    using node_type = columns_t<Args...>;
-    using type = typename conc_tuple<typename node_tuple<Args>::type...>::type;
-  };
-
-  template <class L, class A> struct node_tuple<in_t<L, A>, void> {
-    using node_type = in_t<L, A>;
-    using left_tuple = typename node_tuple<L>::type;
-    using right_tuple = typename node_tuple<A>::type;
-    using type = typename conc_tuple<left_tuple, right_tuple>::type;
-  };
-
-  template <class T>
-  struct node_tuple<
-      T,
-      typename std::enable_if<
-          is_base_of_template<T, compound_operator>::value>::type> {
-    using node_type = T;
-    using left_type = typename node_type::left_type;
-    using right_type = typename node_type::right_type;
-    using left_tuple = typename node_tuple<left_type>::type;
-    using right_tuple = typename node_tuple<right_type>::type;
-    using type = typename conc_tuple<left_tuple, right_tuple>::type;
-  };
-
-  template <class T, class... Args>
-  struct node_tuple<select_t<T, Args...>, void> {
-    using node_type = select_t<T, Args...>;
-    using columns_tuple = typename node_tuple<T>::type;
-    using args_tuple =
-        typename conc_tuple<typename node_tuple<Args>::type...>::type;
-    using type = typename conc_tuple<columns_tuple, args_tuple>::type;
-  };
-
-  template <class T, class R, class... Args>
-  struct node_tuple<get_all_t<T, R, Args...>, void> {
-    using node_type = get_all_t<T, R, Args...>;
-    using type = typename conc_tuple<typename node_tuple<Args>::type...>::type;
-  };
-
-  template <class T, class... Args>
-  struct node_tuple<get_all_pointer_t<T, Args...>, void> {
-    using node_type = get_all_pointer_t<T, Args...>;
-    using type = typename conc_tuple<typename node_tuple<Args>::type...>::type;
-  };
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-  template <class T, class... Args>
-  struct node_tuple<get_all_optional_t<T, Args...>, void> {
-    using node_type = get_all_optional_t<T, Args...>;
-    using type = typename conc_tuple<typename node_tuple<Args>::type...>::type;
-  };
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-  template <class... Args, class... Wargs>
-  struct node_tuple<update_all_t<set_t<Args...>, Wargs...>, void> {
-    using node_type = update_all_t<set_t<Args...>, Wargs...>;
-    using set_tuple =
-        typename conc_tuple<typename node_tuple<Args>::type...>::type;
-    using conditions_tuple =
-        typename conc_tuple<typename node_tuple<Wargs>::type...>::type;
-    using type = typename conc_tuple<set_tuple, conditions_tuple>::type;
-  };
-
-  template <class T, class... Args>
-  struct node_tuple<remove_all_t<T, Args...>, void> {
-    using node_type = remove_all_t<T, Args...>;
-    using type = typename conc_tuple<typename node_tuple<Args>::type...>::type;
-  };
-
-  template <class T> struct node_tuple<having_t<T>, void> {
-    using node_type = having_t<T>;
-    using type = typename node_tuple<T>::type;
-  };
-
-  template <class T, class E> struct node_tuple<cast_t<T, E>, void> {
-    using node_type = cast_t<T, E>;
-    using type = typename node_tuple<E>::type;
-  };
-
-  template <class T> struct node_tuple<exists_t<T>, void> {
-    using node_type = exists_t<T>;
-    using type = typename node_tuple<T>::type;
-  };
-
-  template <class T> struct node_tuple<optional_container<T>, void> {
-    using node_type = optional_container<T>;
-    using type = typename node_tuple<T>::type;
-  };
-
-  template <> struct node_tuple<optional_container<void>, void> {
-    using node_type = optional_container<void>;
-    using type = std::tuple<>;
-  };
-
-  template <class A, class T, class E>
-  struct node_tuple<like_t<A, T, E>, void> {
-    using node_type = like_t<A, T, E>;
-    using arg_tuple = typename node_tuple<A>::type;
-    using pattern_tuple = typename node_tuple<T>::type;
-    using escape_tuple = typename node_tuple<E>::type;
-    using type =
-        typename conc_tuple<arg_tuple, pattern_tuple, escape_tuple>::type;
-  };
-
-  template <class A, class T> struct node_tuple<glob_t<A, T>, void> {
-    using node_type = glob_t<A, T>;
-    using arg_tuple = typename node_tuple<A>::type;
-    using pattern_tuple = typename node_tuple<T>::type;
-    using type = typename conc_tuple<arg_tuple, pattern_tuple>::type;
-  };
-
-  template <class A, class T> struct node_tuple<between_t<A, T>, void> {
-    using node_type = between_t<A, T>;
-    using expression_tuple = typename node_tuple<A>::type;
-    using lower_tuple = typename node_tuple<T>::type;
-    using upper_tuple = typename node_tuple<T>::type;
-    using type =
-        typename conc_tuple<expression_tuple, lower_tuple, upper_tuple>::type;
-  };
-
-  template <class T> struct node_tuple<named_collate<T>, void> {
-    using node_type = named_collate<T>;
-    using type = typename node_tuple<T>::type;
-  };
-
-  template <class T> struct node_tuple<is_null_t<T>, void> {
-    using node_type = is_null_t<T>;
-    using type = typename node_tuple<T>::type;
-  };
-
-  template <class T> struct node_tuple<is_not_null_t<T>, void> {
-    using node_type = is_not_null_t<T>;
-    using type = typename node_tuple<T>::type;
-  };
-
-  template <class C> struct node_tuple<negated_condition_t<C>, void> {
-    using node_type = negated_condition_t<C>;
-    using type = typename node_tuple<C>::type;
-  };
-
-  template <class R, class S, class... Args>
-  struct node_tuple<core_function_t<R, S, Args...>, void> {
-    using node_type = core_function_t<R, S, Args...>;
-    using type = typename conc_tuple<typename node_tuple<Args>::type...>::type;
-  };
-
-  template <class T, class O> struct node_tuple<left_join_t<T, O>, void> {
-    using node_type = left_join_t<T, O>;
-    using type = typename node_tuple<O>::type;
-  };
-
-  template <class T> struct node_tuple<on_t<T>, void> {
-    using node_type = on_t<T>;
-    using type = typename node_tuple<T>::type;
-  };
-
-  template <class T, class O> struct node_tuple<join_t<T, O>, void> {
-    using node_type = join_t<T, O>;
-    using type = typename node_tuple<O>::type;
-  };
-
-  template <class T, class O> struct node_tuple<left_outer_join_t<T, O>, void> {
-    using node_type = left_outer_join_t<T, O>;
-    using type = typename node_tuple<O>::type;
-  };
-
-  template <class T, class O> struct node_tuple<inner_join_t<T, O>, void> {
-    using node_type = inner_join_t<T, O>;
-    using type = typename node_tuple<O>::type;
-  };
-
-  template <class R, class T, class E, class... Args>
-  struct node_tuple<simple_case_t<R, T, E, Args...>, void> {
-    using node_type = simple_case_t<R, T, E, Args...>;
-    using case_tuple = typename node_tuple<T>::type;
-    using args_tuple =
-        typename conc_tuple<typename node_tuple<Args>::type...>::type;
-    using else_tuple = typename node_tuple<E>::type;
-    using type = typename conc_tuple<case_tuple, args_tuple, else_tuple>::type;
-  };
-
-  template <class L, class R> struct node_tuple<std::pair<L, R>, void> {
-    using node_type = std::pair<L, R>;
-    using left_tuple = typename node_tuple<L>::type;
-    using right_tuple = typename node_tuple<R>::type;
-    using type = typename conc_tuple<left_tuple, right_tuple>::type;
-  };
-
-  template <class T, class E> struct node_tuple<as_t<T, E>, void> {
-    using node_type = as_t<T, E>;
-    using type = typename node_tuple<E>::type;
-  };
-
-  template <class T> struct node_tuple<limit_t<T, false, false, void>, void> {
-    using node_type = limit_t<T, false, false, void>;
-    using type = typename node_tuple<T>::type;
-  };
-
-  template <class T, class O>
-  struct node_tuple<limit_t<T, true, false, O>, void> {
-    using node_type = limit_t<T, true, false, O>;
-    using type = typename conc_tuple<
-        typename node_tuple<T>::type,
-        typename node_tuple<O>::type>::type;
-  };
-
-  template <class T, class O>
-  struct node_tuple<limit_t<T, true, true, O>, void> {
-    using node_type = limit_t<T, true, true, O>;
-    using type = typename conc_tuple<
-        typename node_tuple<O>::type,
-        typename node_tuple<T>::type>::type;
-  };
-  } // namespace internal
-} // namespace sqlite_orm
-#pragma once
-
-#include <type_traits> //  std::is_same, std::decay, std::remove_reference
-
-// #include "prepared_statement.h"
-
-// #include "ast_iterator.h"
-
-// #include "static_magic.h"
-
-// #include "expression_object_type.h"
-
-namespace sqlite_orm {
-
-template <int N, class It>
-auto &
-get(internal::prepared_statement_t<internal::insert_range_t<It>> &statement) {
-  return std::get<N>(statement.t.range);
-}
-
-template <int N, class It>
-const auto &
-get(const internal::prepared_statement_t<internal::insert_range_t<It>>
-        &statement) {
-  return std::get<N>(statement.t.range);
-}
-
-template <int N, class It>
-auto &
-get(internal::prepared_statement_t<internal::replace_range_t<It>> &statement) {
-  return std::get<N>(statement.t.range);
-}
-
-template <int N, class It>
-const auto &
-get(const internal::prepared_statement_t<internal::replace_range_t<It>>
-        &statement) {
-  return std::get<N>(statement.t.range);
-}
-
-template <int N, class T, class... Ids>
-auto &
-get(internal::prepared_statement_t<internal::get_t<T, Ids...>> &statement) {
-  return internal::get_ref(std::get<N>(statement.t.ids));
-}
-
-template <int N, class T, class... Ids>
-const auto &get(const internal::prepared_statement_t<internal::get_t<T, Ids...>>
-                    &statement) {
-  return internal::get_ref(std::get<N>(statement.t.ids));
-}
-
-template <int N, class T, class... Ids>
-auto &get(internal::prepared_statement_t<internal::get_pointer_t<T, Ids...>>
-              &statement) {
-  return internal::get_ref(std::get<N>(statement.t.ids));
-}
-
-template <int N, class T, class... Ids>
-const auto &
-get(const internal::prepared_statement_t<internal::get_pointer_t<T, Ids...>>
-        &statement) {
-  return internal::get_ref(std::get<N>(statement.t.ids));
-}
-
-#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
-template <int N, class T, class... Ids>
-auto &get(internal::prepared_statement_t<internal::get_optional_t<T, Ids...>>
-              &statement) {
-  return internal::get_ref(std::get<N>(statement.t.ids));
-}
-
-template <int N, class T, class... Ids>
-const auto &
-get(const internal::prepared_statement_t<internal::get_optional_t<T, Ids...>>
-        &statement) {
-  return internal::get_ref(std::get<N>(statement.t.ids));
-}
-#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
-
-template <int N, class T, class... Ids>
-auto &
-get(internal::prepared_statement_t<internal::remove_t<T, Ids...>> &statement) {
-  return internal::get_ref(std::get<N>(statement.t.ids));
-}
-
-template <int N, class T, class... Ids>
-const auto &
-get(const internal::prepared_statement_t<internal::remove_t<T, Ids...>>
-        &statement) {
-  return internal::get_ref(std::get<N>(statement.t.ids));
-}
-
-template <int N, class T>
-auto &get(internal::prepared_statement_t<internal::update_t<T>> &statement) {
-  static_assert(
-      N == 0, "get<> works only with 0 argument for update statement");
-  return internal::get_ref(statement.t.obj);
-}
-
-template <int N, class T>
-const auto &
-get(const internal::prepared_statement_t<internal::update_t<T>> &statement) {
-  static_assert(
-      N == 0, "get<> works only with 0 argument for update statement");
-  return internal::get_ref(statement.t.obj);
-}
-
-template <int N, class T, class... Cols>
-auto &get(internal::prepared_statement_t<internal::insert_explicit<T, Cols...>>
-              &statement) {
-  static_assert(
-      N == 0, "get<> works only with 0 argument for insert statement");
-  return internal::get_ref(statement.t.obj);
-}
-
-template <int N, class T, class... Cols>
-const auto &
-get(const internal::prepared_statement_t<internal::insert_explicit<T, Cols...>>
-        &statement) {
-  static_assert(
-      N == 0, "get<> works only with 0 argument for insert statement");
-  return internal::get_ref(statement.t.obj);
-}
-
-template <int N, class T>
-auto &get(internal::prepared_statement_t<internal::replace_t<T>> &statement) {
-  static_assert(
-      N == 0, "get<> works only with 0 argument for replace statement");
-  return internal::get_ref(statement.t.obj);
-}
-
-template <int N, class T>
-const auto &
-get(const internal::prepared_statement_t<internal::replace_t<T>> &statement) {
-  static_assert(
-      N == 0, "get<> works only with 0 argument for replace statement");
-  return internal::get_ref(statement.t.obj);
-}
-
-template <int N, class T>
-auto &get(internal::prepared_statement_t<internal::insert_t<T>> &statement) {
-  static_assert(
-      N == 0, "get<> works only with 0 argument for insert statement");
-  return internal::get_ref(statement.t.obj);
-}
-
-template <int N, class T>
-const auto &
-get(const internal::prepared_statement_t<internal::insert_t<T>> &statement) {
-  static_assert(
-      N == 0, "get<> works only with 0 argument for insert statement");
-  return internal::get_ref(statement.t.obj);
-}
-
-template <int N, class T>
-const auto &get(const internal::prepared_statement_t<T> &statement) {
-  using statement_type = typename std::decay<decltype(statement)>::type;
-  using expression_type = typename statement_type::expression_type;
-  using node_tuple = typename internal::node_tuple<expression_type>::type;
-  using bind_tuple = typename internal::bindable_filter<node_tuple>::type;
-  using result_tupe = typename std::tuple_element<N, bind_tuple>::type;
-  const result_tupe *result = nullptr;
-  auto index = -1;
-  internal::iterate_ast(statement.t, [&result, &index](auto &node) {
-    using node_type = typename std::decay<decltype(node)>::type;
-    if (internal::is_bindable<node_type>::value) {
-      ++index;
-    }
-    if (index == N) {
-      internal::static_if<std::is_same<result_tupe, node_type>{}>([](auto &r,
-                                                                     auto &n) {
-        r = const_cast<typename std::remove_reference<decltype(r)>::type>(&n);
-      })(result, node);
-    }
-  });
-  return internal::get_ref(*result);
-}
-
-template <int N, class T>
-auto &get(internal::prepared_statement_t<T> &statement) {
-  using statement_type = typename std::decay<decltype(statement)>::type;
-  using expression_type = typename statement_type::expression_type;
-  using node_tuple = typename internal::node_tuple<expression_type>::type;
-  using bind_tuple = typename internal::bindable_filter<node_tuple>::type;
-  using result_tupe = typename std::tuple_element<N, bind_tuple>::type;
-  result_tupe *result = nullptr;
-  auto index = -1;
-  internal::iterate_ast(statement.t, [&result, &index](auto &node) {
-    using node_type = typename std::decay<decltype(node)>::type;
-    if (internal::is_bindable<node_type>::value) {
-      ++index;
-    }
-    if (index == N) {
-      internal::static_if<std::is_same<result_tupe, node_type>{}>([](auto &r,
-                                                                     auto &n) {
-        r = const_cast<typename std::remove_reference<decltype(r)>::type>(&n);
-      })(result, node);
-    }
-  });
-  return internal::get_ref(*result);
-}
-} // namespace sqlite_orm
diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj
--- a/native/ios/Comm.xcodeproj/project.pbxproj
+++ b/native/ios/Comm.xcodeproj/project.pbxproj
@@ -152,7 +152,6 @@
 		71BE84422636A944002849D2 /* SQLiteQueryExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLiteQueryExecutor.h; sourceTree = "<group>"; };
 		71BE84432636A944002849D2 /* DatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseManager.h; sourceTree = "<group>"; };
 		71BE84452636A944002849D2 /* Draft.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Draft.h; sourceTree = "<group>"; };
-		71BE84482636A944002849D2 /* sqlite_orm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqlite_orm.h; sourceTree = "<group>"; };
 		71BF5B6F26B3FF0900EDE27D /* Session.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Session.cpp; sourceTree = "<group>"; };
 		71BF5B7026B3FF0900EDE27D /* Session.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Session.h; sourceTree = "<group>"; };
 		71BF5B7226B3FFBC00EDE27D /* Persist.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Persist.h; sourceTree = "<group>"; };
@@ -410,7 +409,6 @@
 			isa = PBXGroup;
 			children = (
 				71BE84372636A944002849D2 /* CommonCpp */,
-				71BE84462636A944002849D2 /* third-party */,
 			);
 			name = cpp;
 			path = ../cpp;
@@ -505,22 +503,6 @@
 			path = entities;
 			sourceTree = "<group>";
 		};
-		71BE84462636A944002849D2 /* third-party */ = {
-			isa = PBXGroup;
-			children = (
-				71BE84472636A944002849D2 /* sqlite_orm */,
-			);
-			path = "third-party";
-			sourceTree = "<group>";
-		};
-		71BE84472636A944002849D2 /* sqlite_orm */ = {
-			isa = PBXGroup;
-			children = (
-				71BE84482636A944002849D2 /* sqlite_orm.h */,
-			);
-			path = sqlite_orm;
-			sourceTree = "<group>";
-		};
 		71BF5B6A26B3FCFF00EDE27D /* CryptoTools */ = {
 			isa = PBXGroup;
 			children = (
diff --git a/nix/dev-shell.nix b/nix/dev-shell.nix
--- a/nix/dev-shell.nix
+++ b/nix/dev-shell.nix
@@ -105,7 +105,7 @@
     fmt # needed for folly
     boost # needed for folly
     olm # needed for CryptoTools
-    sqlite # needed for sqlite_orm
+    sqlite # needed for sqlite database
     openssl # needed for grpc
   ] ++ lib.optionals stdenv.isDarwin (with darwin.apple_sdk.frameworks; [
     CoreFoundation
diff --git a/web/scripts/run_emscripten.sh b/web/scripts/run_emscripten.sh
--- a/web/scripts/run_emscripten.sh
+++ b/web/scripts/run_emscripten.sh
@@ -140,7 +140,6 @@
 CFLAGS=(
   -I "$INPUT_DIR"
   -I "$SQLITE_DIR"
-  -I "${NATIVE_CPP_DIR}third-party/sqlite_orm/"
   -I "${NATIVE_CPP_DIR}CommonCpp/Tools/"
 )