Page MenuHomePhorge

D10710.1765068318.diff
No OneTemporary

Size
430 KB
Referenced Files
None
Subscribers
None

D10710.1765068318.diff

This file is larger than 256 KB, so syntax highlighting was skipped.
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/"
)

File Metadata

Mime Type
text/plain
Expires
Sun, Dec 7, 12:45 AM (23 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5841716
Default Alt Text
D10710.1765068318.diff (430 KB)

Event Timeline