Page Not Found
We could not find what you were looking for.
Please contact the owner of the site that linked you to the original URL and let them know their link is broken.
diff --git a/404.html b/404.html index 348b1e13f..4c1c96e28 100644 --- a/404.html +++ b/404.html @@ -13,9 +13,9 @@ - - - + + +
We could not find what you were looking for.
Please contact the owner of the site that linked you to the original URL and let them know their link is broken.
vcpkg
environment",id:"set-up-vcpkg-environment",level:4},{value:"C preprocessor macros",id:"c-preprocessor-macros",level:2},{value:"Building with CMake",id:"building-with-cmake",level:2},{value:"Configure & Build (cmake)",id:"configure-and-build-cmake",level:3},{value:"CMake STRICT_MODE
option",id:"cmake-strict_mode-option",level:5},{value:"Build TinyORM",id:"build-tinyorm",level:4},{value:"CMake build options",id:"cmake-build-options",level:3},{value:"CMake build environment variables",id:"cmake-build-environment-variables",level:3},{value:"Consume TinyOrm library (cmake)",id:"consume-tinyorm-library-cmake",level:3},{value:"Building with qmake",id:"building-with-qmake",level:2},{value:"Install dependencies",id:"install-dependencies",level:3},{value:"Configure & Build (qmake)",id:"configure-and-build-qmake",level:3},{value:"Open QtCreator IDE",id:"open-qtcreator-ide",level:4},{value:"Configure TinyORM",id:"configure-tinyorm",level:4},{value:"Auto-configuration and tiny_dotenv",id:"auto-configuration-and-tiny_dotenv",level:5},{value:"Manual configuration (conf.pri)",id:"manual-configuration-confpri",level:5},{value:"Opening TinyORM.pro (main project file)",id:"opening-tinyormpro-main-project-file",level:5},{value:"Build TinyORM",id:"build-tinyorm-1",level:4},{value:"qmake build options",id:"qmake-build-options",level:3},{value:"Consume TinyOrm library (qmake)",id:"consume-tinyorm-library-qmake",level:3},{value:"Requirements",id:"requirements",level:4},{value:"QMAKEFEATURES
",id:"qmakefeatures",level:5},{value:"Variables affecting TinyOrm.pri
",id:"variables-affecting-tinyormpri",level:5},{value:"Manual configuration examples",id:"manual-configuration-examples",level:5},{value:"Auto-configuration internals",id:"auto-configuration-internals",level:3},{value:"Environment files",id:"environment-files",level:4},{value:"Partial guessing of the TINYORM_BUILD_TREE
",id:"partial-guessing-of-the-tinyorm_build_tree",level:4},{value:"Manual configuration internals",id:"manual-configuration-internals",level:3},{value:"Ccache support",id:"ccache-support",level:2}];function I(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,d.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"building-tinyorm",children:"Building: TinyORM"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#introduction",children:"Introduction"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#common-prerequisites",children:"Common Prerequisites"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#windows-prerequisites",children:"Windows Prerequisites"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#folders-structure",children:"Folders structure"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#getting-started",children:"Getting started"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#vcpkg",children:"vcpkg"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#c-preprocessor-macros",children:"C preprocessor macros"})}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#building-with-cmake",children:"Building with CMake"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#configure-and-build-cmake",children:"Configure & Build"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#cmake-build-options",children:"CMake build options"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#cmake-build-environment-variables",children:"CMake build environment variables"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#consume-tinyorm-library-cmake",children:"Consume TinyOrm library"})}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#building-with-qmake",children:"Building with qmake"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#install-dependencies",children:"Install dependencies"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#configure-and-build-qmake",children:"Configure & Build"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#qmake-build-options",children:"qmake build options"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#consume-tinyorm-library-qmake",children:"Consume TinyOrm library"})}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#auto-configuration-internals",children:"Auto-configuration internals"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#environment-files",children:"Environment files"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#manual-configuration-internals",children:"Manual configuration internals"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#ccache-support",children:"Ccache support"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsx)("div",{className:"api-stability alert alert--success",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)(r.A,{to:"/stability#stability-indexes",children:(0,s.jsx)(n.strong,{children:"Stability: 2"})})," - Stable"]})}),"\n",(0,s.jsxs)(n.p,{children:["The build systems supported out of the box are ",(0,s.jsx)(n.code,{children:"CMake"})," and ",(0,s.jsx)(n.code,{children:"qmake"}),"."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["All examples below assume that ",(0,s.jsx)(n.code,{children:"pwsh"})," runs on ",(0,s.jsx)(n.code,{children:"Windows"})," and ",(0,s.jsx)(n.code,{children:"bash"})," runs on ",(0,s.jsx)(n.code,{children:"Linux"}),"."]})}),"\n",(0,s.jsx)(n.h4,{id:"common-prerequisites",children:"Common Prerequisites"}),"\n",(0,s.jsxs)(n.p,{children:["Install the required ",(0,s.jsx)(n.a,{href:"/dependencies",children:"dependencies"})," before starting."]}),"\n",(0,s.jsx)(n.admonition,{type:"warning",children:(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"QSqlDatabase"})," depends on ",(0,s.jsx)(n.code,{children:"QCoreApplication"})," from ",(0,s.jsx)(n.code,{children:"Qt v6.5.3"})," so you must create the ",(0,s.jsx)(n.code,{children:"QCoreApplication"})," instance before you will call anything from the ",(0,s.jsx)(n.code,{children:"TinyORM"})," library. \ud83e\udee4 The change was made ",(0,s.jsx)(n.a,{href:"https://github.com/qt/qtbase/commit/8d2bdc9cd5482eace12ba7e45304857bd24db0e6#diff-1d355c25c0b0eddec2be48253407780c4dc510d986739aec61e1ec892ccaf86e",children:"here"}),"."]})}),"\n",(0,s.jsx)(n.h4,{id:"windows-prerequisites",children:"Windows Prerequisites"}),"\n",(0,s.jsx)(n.h5,{id:"build-environment-scripts",children:"Build environment scripts"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"Visual Studio"})," does not provide ",(0,s.jsx)(n.code,{children:"vcvars"})," scripts for ",(0,s.jsx)(n.code,{children:"pwsh"}),", you can use ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/tree/main/tools/vcvars64.ps1",children:(0,s.jsx)(n.code,{children:"vcvars64.ps1"})})," provided by ",(0,s.jsx)(n.code,{children:"TinyORM"})," in the ",(0,s.jsx)(n.code,{children:"tools/"})," folder. Place them on the ",(0,s.jsx)(n.code,{children:"$env:Path"})," user/system path and they will be available system-wide."]}),"\n",(0,s.jsxs)(n.p,{children:["The same is true for the ",(0,s.jsx)(n.code,{children:"Qt Framework"}),", it doesn't provide ",(0,s.jsx)(n.code,{children:"qtenv"})," scripts for ",(0,s.jsx)(n.code,{children:"pwsh"})," too. You can create your own script, place it on the ",(0,s.jsx)(n.code,{children:"$env:Path"})," user/system path and it will be available system-wide."]}),"\n",(0,s.jsxs)(n.p,{children:["Here is one simple example for ",(0,s.jsx)(n.code,{children:"pwsh"})," and ",(0,s.jsx)(n.code,{children:"bash"})," on ",(0,s.jsx)(n.code,{children:"Linux"}),"."]}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-powershell",metastring:"title='qtenv6.ps1'",children:"#!/usr/bin/env pwsh\n\nSet-StrictMode -Version 3.0\n\nWrite-Host 'Setting up environment for Qt 6.7.2 usage...' -ForegroundColor Magenta\nWrite-Host\n\n$Script:QtRoot = $env:TINY_QT_ROOT ?? 'C:\\Qt'\n\n$env:Path = \"$Script:QtRoot\\6.7.2\\msvc2019_64\\bin;\" + $env:Path\n\n. vcvars64.ps1\n"})})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:"title='qtenv6'",children:'#!/usr/bin/env sh\n\necho \'Setting up environment for Qt 6.7.2 usage...\'\n\nQtRoot="${TINY_QT_ROOT:-/opt/Qt}"\n\nexport PATH="$QtRoot/6.7.2/gcc_64/bin"${PATH:+:}$PATH\nexport LD_LIBRARY_PATH="$QtRoot/6.7.2/gcc_64/lib"${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH\n'})})})]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["These scripts consider the ",(0,s.jsx)(n.code,{children:"TINY_QT_ROOT"})," environment variable that should point to the ",(0,s.jsx)(n.code,{children:"Qt"})," installation folder, you can define this environment variable globally in your OS."]})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["You can't execute these ",(0,s.jsx)(n.code,{children:"qtenvX"})," scripts, they have to be sourced like ",(0,s.jsx)(n.code,{children:"source qtenvX"})," or ",(0,s.jsx)(n.code,{children:". qtenvX"}),"."]})}),"\n",(0,s.jsx)(n.h5,{id:"allow-symbolic-links-unprivileged",children:"Allow symbolic links unprivileged"}),"\n",(0,s.jsxs)(n.p,{children:["Open ",(0,s.jsx)(n.code,{children:"Local Security Policy"}),", go to ",(0,s.jsx)(n.code,{children:"Local Policies - User Rights Assignment"}),", open ",(0,s.jsx)(n.code,{children:"Create symbolic links"})," and add your user account or user group, restart when it doesn't apply immediately."]}),"\n",(0,s.jsx)(n.h2,{id:"folders-structure",children:"Folders structure"}),"\n",(0,s.jsxs)(n.p,{children:["All ",(0,s.jsx)(n.code,{children:"tinyorm.org"})," examples are based on the following folders structure. The ",(0,s.jsx)(n.code,{children:"tom"})," folder will contain a ",(0,s.jsx)(n.a,{href:"/building/migrations",children:"migrations console application"}),"."]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["You can set the root and application folder paths in the form below and they will be used across the whole ",(0,s.jsx)(n.a,{href:"http://www.tinyorm.org",children:"www.tinyorm.org"})," website. \ud83e\udd73 The pwsh shell is supposed to use on Windows and the bash shell on Linux, but it is not a requirement."]})}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsxs)(t.A,{value:y.b,label:y.ux,className:"tiny-tree",children:[(0,s.jsx)("div",{className:"tiny-root-folder-info-wrapper",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)("span",{className:"tiny-root-folder-info-prefix",children:"Current pwsh path"}),"\xa0",(0,s.jsx)(u,{groupId:y.b})]})}),(0,s.jsx)(g,{groupId:y.b,label:y.ux}),(0,s.jsx)(g,{groupId:y.pW,label:y.kl}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-text",children:"\n\n\n\u251c\u2500\u2500\n\u2502 \u251c\u2500\u2500 HelloWorld/\n\u2502 | \u251c\u2500\u2500 HelloWorld/\n\u2502 | \u251c\u2500\u2500 HelloWorld-builds-cmake/\n\u2502 | | \u2514\u2500\u2500 build-debug/\n\u2502 | \u2514\u2500\u2500 HelloWorld-builds-qmake/\n\u2502 | \u2514\u2500\u2500 build-debug/\n\u2502 \u251c\u2500\u2500 TinyORM/\n\u2502 | \u251c\u2500\u2500 TinyORM/\n\u2502 | \u251c\u2500\u2500 TinyORM-builds-cmake/\n\u2502 | \u2502 \u251c\u2500\u2500 build-gcc-debug/\n\u2502 | \u2502 \u251c\u2500\u2500 build-gcc-release/\n\u2502 | \u2502 \u2514\u2500\u2500 build-clang-debug/\n\u2502 | \u2514\u2500\u2500 TinyORM-builds-qmake/\n\u2502 | \u251c\u2500\u2500 build-debug/\n\u2502 | \u251c\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_MSVC2019_64bit-Debug/\n\u2502 | \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_MSYS2_UCRT64_64bit-Release/\n\u2502 \u2514\u2500\u2500 tom/\n\u2502 \u251c\u2500\u2500 tom/\n\u2502 \u2502 \u2514\u2500\u2500 database/\n\u2502 \u2502 \u251c\u2500\u2500 migrations/\n\u2502 \u2502 \u251c\u2500\u2500 seeders/\n\u2502 \u2502 \u251c\u2500\u2500 migrations.pri\n\u2502 \u2502 \u2514\u2500\u2500 seeders.pri\n\u2502 \u251c\u2500\u2500 tom-builds-cmake/\n\u2502 \u2502 \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_MSVC2019_64bit-Debug/\n\u2502 \u2514\u2500\u2500 tom-builds-qmake/\n\u2502 \u251c\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_MSYS2_UCRT64_64bit-Release/\n\u2502 \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_MSVC2019_64bit-Debug/\n\u251c\u2500\u2500 tmp/\n\u2514\u2500\u2500 vcpkg/\n"})})]}),(0,s.jsxs)(t.A,{value:y.xj,label:y.gg,className:"tiny-tree",children:[(0,s.jsx)("div",{className:"tiny-root-folder-info-wrapper",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)("span",{className:"tiny-root-folder-info-prefix",children:"Current bash path"}),"\xa0",(0,s.jsx)(u,{groupId:y.xj})]})}),(0,s.jsx)(g,{groupId:y.xj,label:y.gg}),(0,s.jsx)(g,{groupId:y.pW,label:y.pW}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-text",children:"\n\n\n\u251c\u2500\u2500\n\u2502 \u251c\u2500\u2500 HelloWorld/\n\u2502 | \u251c\u2500\u2500 HelloWorld/\n\u2502 | \u251c\u2500\u2500 HelloWorld-builds-cmake/\n\u2502 | | \u2514\u2500\u2500 build-debug/\n\u2502 | \u2514\u2500\u2500 HelloWorld-builds-qmake/\n\u2502 | \u2514\u2500\u2500 build-debug/\n\u2502 \u251c\u2500\u2500 TinyORM/\n\u2502 | \u251c\u2500\u2500 TinyORM/\n\u2502 | \u251c\u2500\u2500 TinyORM-builds-cmake/\n\u2502 | \u2502 \u251c\u2500\u2500 build-gcc-debug/\n\u2502 | \u2502 \u251c\u2500\u2500 build-gcc-release/\n\u2502 | \u2502 \u2514\u2500\u2500 build-clang-debug/\n\u2502 | \u2514\u2500\u2500 TinyORM-builds-qmake/\n\u2502 | \u251c\u2500\u2500 build-debug/\n\u2502 | \u251c\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_GCC_64bit-Debug/\n\u2502 | \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_clang18_64bit_ccache-Release/\n\u2502 \u2514\u2500\u2500 tom/\n\u2502 \u251c\u2500\u2500 tom/\n\u2502 \u2502 \u2514\u2500\u2500 database/\n\u2502 \u2502 \u251c\u2500\u2500 migrations/\n\u2502 \u2502 \u251c\u2500\u2500 seeders/\n\u2502 \u2502 \u251c\u2500\u2500 migrations.pri\n\u2502 \u2502 \u2514\u2500\u2500 seeders.pri\n\u2502 \u251c\u2500\u2500 tom-builds-cmake/\n\u2502 \u2502 \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_clang18_64bit_ccache-Debug/\n\u2502 \u2514\u2500\u2500 tom-builds-qmake/\n\u2502 \u251c\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_GCC_64bit-Debug/\n\u2502 \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_clang18_64bit_ccache-Release/\n\u251c\u2500\u2500 tmp/\n\u2514\u2500\u2500 vcpkg/\n"})})]})]}),"\n",(0,s.jsx)(n.admonition,{type:"danger",children:(0,s.jsxs)(n.p,{children:["Avoid paths with spaces with the ",(0,s.jsx)(n.code,{children:"qmake"})," build system, it will not compile."]})}),"\n",(0,s.jsx)(r.A,{id:"qtcreator-default-build-directory"}),"\n",(0,s.jsxs)(n.admonition,{type:"tip",children:[(0,s.jsxs)(n.p,{children:["You can force the ",(0,s.jsx)(n.code,{children:"QtCreator"})," to generate a build folders structure as is described above."]}),(0,s.jsxs)(n.p,{children:["To generate the required folders structure set the ",(0,s.jsx)(n.code,{children:"Settings"})," - ",(0,s.jsx)(n.code,{children:"Build & Run"})," - ",(0,s.jsx)(n.code,{children:"Default Build Properties"})," - ",(0,s.jsx)(n.code,{children:"Default build directory"})," to:",(0,s.jsx)("br",{}),"\n",(0,s.jsx)(n.code,{children:'../%{Project:Name}-builds-%{BuildSystem:Name}/%{JS: Util.asciify("build-%{Project:Name}-%{Kit:FileSystemName}-%{BuildConfig:Name}")}'})]})]}),"\n",(0,s.jsx)(n.h2,{id:"getting-started",children:"Getting started"}),"\n",(0,s.jsxs)(n.p,{children:["Prepare compilation environment, we need to put the Qt Framework and Visual Studio MSVC compiler on the path on Windows. The compiler is already on the path on Linux and you can export ",(0,s.jsx)(n.code,{children:"PATH"})," and ",(0,s.jsx)(n.code,{children:"LD_LIBRARY_PATH"})," for Qt Framework, or use our ",(0,s.jsx)(n.code,{children:"qtenvX"})," scripts described above."]}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(c.A,{className:"language-powershell",children:`mkdir ${(0,x.Sn)(y.b)}\ncd ${(0,x.Sn)(y.b)}\n$env:Path = 'C:\\Qt\\6.7.2\\msvc2019_64\\bin;' + $env:Path\nvcvars64.ps1`})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(c.A,{className:"language-bash",children:`mkdir -p ${(0,x.Sn)(y.xj)}\ncd ${(0,x.Sn)(y.xj)}\nexport PATH=/opt/Qt/6.7.2/gcc_64/bin\${PATH:+:}$PATH\nexport LD_LIBRARY_PATH=/opt/Qt/6.7.2/gcc_64/lib\${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH`})})]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["You can also use the ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/tools/Add-FolderOnPath.ps1",children:(0,s.jsx)(n.code,{children:"tools/Add-FolderOnPath.ps1"})})," pwsh script to fastly prepend a path or ",(0,s.jsx)("abbr",{title:"Current working directory",children:"pwd"})," on the system ",(0,s.jsx)(n.code,{children:"PATH"}),"."]})}),"\n",(0,s.jsx)(n.h2,{id:"vcpkg",children:"vcpkg"}),"\n",(0,s.jsxs)(n.p,{children:["Installing the ",(0,s.jsx)(n.code,{children:"vcpkg"})," is highly recommended, it simplifies installation of the ",(0,s.jsx)(n.code,{children:"range-v3"})," and ",(0,s.jsx)(n.code,{children:"tabulate"})," dependencies."]}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-powershell",children:"git clone git@github.com:microsoft/vcpkg.git\ncd vcpkg\n.\\bootstrap-vcpkg.bat\n"})})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"git clone git@github.com:microsoft/vcpkg.git\ncd vcpkg\n./bootstrap-vcpkg.sh\n"})})})]}),"\n",(0,s.jsxs)(n.p,{children:["Add ",(0,s.jsx)(n.code,{children:"vcpkg"})," on the system path, add the following to the ",(0,s.jsx)(n.code,{children:".bashrc"})," or ",(0,s.jsx)(n.code,{children:".zshrc"})," on Linux."]}),"\n",(0,s.jsx)(c.A,{className:"language-bash",children:`export PATH=${(0,x.Sn)(y.xj)}/vcpkg\${PATH:+:}$PATH`}),"\n",(0,s.jsxs)(n.p,{children:["On Windows, open the ",(0,s.jsx)(n.code,{children:"Environment variables"})," dialog and add ",(0,s.jsx)(n.code,{children:"vcpkg"})," on the user ",(0,s.jsx)(n.code,{children:"PATH"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Or you can export it for the current session only."}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(c.A,{className:"language-powershell",children:`$env:Path = "${(0,x.Sn)(y.b,!1)}\\vcpkg;" + $env:Path`})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(c.A,{className:"language-bash",children:`export PATH=${(0,x.Sn)(y.xj)}/vcpkg\${PATH:+:}$PATH`})})]}),"\n",(0,s.jsxs)(n.h4,{id:"set-up-vcpkg-environment",children:["Set up ",(0,s.jsx)(n.code,{children:"vcpkg"})," environment"]}),"\n",(0,s.jsxs)(n.p,{children:["To export ",(0,s.jsx)(n.code,{children:"vcpkg"})," environment variables globally, add it to the ",(0,s.jsx)(n.code,{children:".bashrc"})," or ",(0,s.jsx)(n.code,{children:".zshrc"})," on Linux, and you can use the ",(0,s.jsx)(n.code,{children:"Environment variables"})," dialog on Windows."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:"title='Linux'",children:'export VCPKG_DEFAULT_TRIPLET=x64-linux\n#export VCPKG_DEFAULT_HOST_TRIPLET=x64-linux\nexport VCPKG_MAX_CONCURRENCY=11\nexport VCPKG_OVERLAY_PORTS="$HOME/.local/share/vcpkg/ports"\nexport VCPKG_OVERLAY_TRIPLETS="$HOME/.local/share/vcpkg/triplets"\nexport VCPKG_ROOT="$HOME/Code/c/vcpkg"\n'})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["It is recommended to define these variables globally because the ",(0,s.jsx)(n.code,{children:"CMake"})," and ",(0,s.jsx)(n.code,{children:"qmake"})," build system are able to detect the ",(0,s.jsx)(n.code,{children:"vcpkg"})," installation from them so you don't have to configure them manually to detect the ",(0,s.jsx)(n.code,{children:"vcpkg"})," installation."]})}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["On Windows, it's always better to create these types of variables as user variables instead of system variables in the ",(0,s.jsx)(n.code,{children:"Environment variables"})," dialog."]})}),"\n",(0,s.jsx)(n.h2,{id:"c-preprocessor-macros",children:"C preprocessor macros"}),"\n",(0,s.jsxs)(n.p,{children:["The following table summarizes all the C preprocessor macros defined in the ",(0,s.jsx)(n.code,{children:"TinyORM"})," library. These C macros are configured by ",(0,s.jsx)(n.code,{children:"CMake"})," or ",(0,s.jsx)(n.code,{children:"qmake"})," build systems. They are not sorted alphabetically, but they are sorted by how significant they are."]}),"\n",(0,s.jsxs)(n.p,{children:["In the ",(0,s.jsx)(n.code,{children:"CMake"})," build system, all the C macros are auto-detected / auto-configured or controlled by ",(0,s.jsx)(n.a,{href:"#cmake-build-options",children:(0,s.jsx)(n.code,{children:"CMake build options"})}),", so you don't have to care too much about them."]}),"\n",(0,s.jsxs)(n.p,{children:["In the ",(0,s.jsx)(n.code,{children:"qmake"})," build is important whether you are building ",(0,s.jsx)(n.code,{children:"TinyORM"})," library or you are building your application and linking against ",(0,s.jsx)(n.code,{children:"TinyORM"})," library. When you are building the ",(0,s.jsx)(n.code,{children:"TinyORM"})," library, all the C macros are auto-detected / auto-configured or controlled by ",(0,s.jsx)(n.a,{href:"#qmake-build-options",children:(0,s.jsx)(n.code,{children:"qmake build options"})}),", so you don't have to care too much about them."]}),"\n",(0,s.jsxs)(n.p,{children:["But a special situation is when you are building your application / library and you are linking against ",(0,s.jsx)(n.code,{children:"TinyORM"})," library. In this particular case, you must configure all these C macros manually! For this reason, the ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/qmake/TinyOrm.pri",children:(0,s.jsx)(n.code,{children:"TinyOrm.pri"})})," has been created, so that's not a big deal either. Little more info ",(0,s.jsx)(n.a,{href:"#consume-tinyorm-library-qmake",children:"here"}),"."]}),"\n",(0,s.jsx)("div",{id:"apitable-c-macros",children:(0,s.jsx)(l.A,{children:(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"C Macro Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_LINKING_SHARED"})}),(0,s.jsxs)(n.td,{children:[(0,s.jsx)("u",{children:(0,s.jsx)(n.strong,{children:"Must"})})," be defined when you are linking against ",(0,s.jsx)(n.code,{children:"TinyORM"})," shared build (",(0,s.jsx)(n.code,{children:"dll"})," library), exported classes and functions will be tagged with ",(0,s.jsx)(n.code,{children:"__declspec(dllimport)"})," on ",(0,s.jsx)(n.code,{children:"msvc"})," and ",(0,s.jsx)(n.code,{children:'visibility("default")'})," on ",(0,s.jsx)(n.code,{children:"GCC >= 4"}),"."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_BUILDING_SHARED"})}),(0,s.jsxs)(n.td,{children:["Defined when ",(0,s.jsx)(n.code,{children:"TinyORM"})," is built as a ",(0,s.jsx)(n.code,{children:"dll"})," library (shared build)."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_DEBUG"})}),(0,s.jsx)(n.td,{children:"Defined in the debug build."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_NO_DEBUG"})}),(0,s.jsx)(n.td,{children:"Defined in the release build."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_DEBUG_SQL"})}),(0,s.jsx)(n.td,{children:"Defined in the debug build."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_NO_DEBUG_SQL"})}),(0,s.jsx)(n.td,{children:"Defined in the release build."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_MYSQL_PING"})}),(0,s.jsxs)(n.td,{children:["Enable ",(0,s.jsx)(n.code,{children:"Orm::MySqlConnection::pingDatabase()"})," method.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined when ",(0,s.jsx)(n.a,{href:"#mysql_ping",children:(0,s.jsx)(n.code,{children:"mysql_ping"})})," ",(0,s.jsx)("small",{children:"(qmake)"})," / ",(0,s.jsx)(n.a,{href:"#MYSQL_PING",children:(0,s.jsx)(n.code,{children:"MYSQL_PING"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration ",(0,s.jsx)(n.code,{children:"build option"})," is enabled."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_DISABLE_ORM"})}),(0,s.jsxs)(n.td,{children:["Controls the compilation of all ",(0,s.jsx)(n.code,{children:"ORM-related"})," source code, when this macro is ",(0,s.jsx)(n.code,{children:"defined"}),", then only the ",(0,s.jsx)(n.code,{children:"query builder"})," without ",(0,s.jsx)(n.code,{children:"ORM"})," is compiled. Also excludes ",(0,s.jsx)(n.code,{children:"ORM-related"})," unit tests.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined when ",(0,s.jsx)(n.a,{href:"#disable_orm",children:(0,s.jsx)(n.code,{children:"disable_orm"})})," ",(0,s.jsx)("small",{children:"(qmake)"})," / ",(0,s.jsx)(n.a,{href:"#ORM",children:(0,s.jsx)(n.code,{children:"ORM"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration ",(0,s.jsx)(n.code,{children:"build option"})," is enabled ",(0,s.jsx)("small",{children:"(qmake)"})," / disabled ",(0,s.jsx)("small",{children:"(cmake)"}),"."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_EXTERN_CONSTANTS"})}),(0,s.jsxs)(n.td,{children:["Defined when extern constants are used. Extern constants are enabled by default for shared builds and disabled for static builds.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Described at ",(0,s.jsx)(n.a,{href:"#extern_constants",children:(0,s.jsx)(n.code,{children:"qmake"})})," / ",(0,s.jsx)(n.a,{href:"#INLINE_CONSTANTS",children:(0,s.jsx)(n.code,{children:"CMake"})})," how it works."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_INLINE_CONSTANTS"})}),(0,s.jsxs)(n.td,{children:["Defined when global inline constants are used.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined when ",(0,s.jsx)(n.a,{href:"#inline_constants",children:(0,s.jsx)(n.code,{children:"inline_constants"})})," ",(0,s.jsx)("small",{children:"(qmake)"})," / ",(0,s.jsx)(n.a,{href:"#INLINE_CONSTANTS",children:(0,s.jsx)(n.code,{children:"INLINE_CONSTANTS"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration ",(0,s.jsx)(n.code,{children:"build option"})," is enabled."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_TESTS_CODE"})}),(0,s.jsxs)(n.td,{children:["Enable code needed by unit tests, eg. connection overriding in the ",(0,s.jsx)(n.code,{children:"Orm::Tiny::Model"}),".",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined when ",(0,s.jsx)(n.a,{href:"#build_tests",children:(0,s.jsx)(n.code,{children:"build_tests"})})," ",(0,s.jsx)("small",{children:"(qmake)"})," / ",(0,s.jsx)(n.a,{href:"#BUILD_TESTS",children:(0,s.jsx)(n.code,{children:"BUILD_TESTS"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration ",(0,s.jsx)(n.code,{children:"build option"})," is enabled."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_DISABLE_THREAD_LOCAL"})}),(0,s.jsxs)(n.td,{children:["Remove all ",(0,s.jsx)(n.a,{href:"https://en.cppreference.com/w/c/language/storage_duration",children:(0,s.jsx)(n.code,{children:"thread_local"})})," storage duration specifiers, it disables multi-threading support.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined when ",(0,s.jsx)(n.a,{href:"#disable_thread_local",children:(0,s.jsx)(n.code,{children:"disable_thread_local"})})," ",(0,s.jsx)("small",{children:"(qmake)"})," / ",(0,s.jsx)(n.a,{href:"#DISABLE_THREAD_LOCAL",children:(0,s.jsx)(n.code,{children:"DISABLE_THREAD_LOCAL"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration ",(0,s.jsx)(n.code,{children:"build option"})," is enabled."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYTOM_MIGRATIONS_DIR"})}),(0,s.jsxs)(n.td,{children:["Default migrations path for the ",(0,s.jsx)(n.code,{children:"make:migration"})," command, can be an absolute or relative path (to the ",(0,s.jsx)("abbr",{title:"Current working directory",children:"pwd"}),").",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Default value: ",(0,s.jsx)(n.code,{children:"database/migrations"})," ",(0,s.jsx)("small",{children:"(relative to the pwd)"})]}),(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined by ",(0,s.jsx)(n.a,{href:"#TOM_MIGRATIONS_DIR",children:(0,s.jsx)(n.code,{children:"TOM_MIGRATIONS_DIR"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration build option.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["(qmake note) You can use ",(0,s.jsx)(n.code,{children:'DEFINES += TINYTOM_MIGRATIONS_DIR="\\"database/migrations\\""'})," on the command-line or set it in the ",(0,s.jsx)(n.strong,{children:"main"})," ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/conf.pri.example#L65-L70",children:(0,s.jsx)(n.code,{children:"conf.pri"})})," file."]})]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYTOM_MODELS_DIR"})}),(0,s.jsxs)(n.td,{children:["Default models path for the ",(0,s.jsx)(n.code,{children:"make:model"})," command, can be an absolute or relative path (to the ",(0,s.jsx)("abbr",{title:"Current working directory",children:"pwd"}),").",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Default value: ",(0,s.jsx)(n.code,{children:"database/models"})," ",(0,s.jsx)("small",{children:"(relative to the pwd)"})]}),(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined by ",(0,s.jsx)(n.a,{href:"#TOM_MODELS_DIR",children:(0,s.jsx)(n.code,{children:"TOM_MODELS_DIR"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration build option.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["(qmake note) You can use ",(0,s.jsx)(n.code,{children:'DEFINES += TINYTOM_MODELS_DIR="\\"database/models\\""'})," on the command-line or set it in the ",(0,s.jsx)(n.strong,{children:"main"})," ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/conf.pri.example#L72-L73",children:(0,s.jsx)(n.code,{children:"conf.pri"})})," file."]})]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYTOM_SEEDERS_DIR"})}),(0,s.jsxs)(n.td,{children:["Default seeders path for the ",(0,s.jsx)(n.code,{children:"make:seeder"})," command, can be an absolute or relative path (to the ",(0,s.jsx)("abbr",{title:"Current working directory",children:"pwd"}),").",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Default value: ",(0,s.jsx)(n.code,{children:"database/seeders"})," ",(0,s.jsx)("small",{children:"(relative to the pwd)"})]}),(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined by ",(0,s.jsx)(n.a,{href:"#TOM_SEEDERS_DIR",children:(0,s.jsx)(n.code,{children:"TOM_SEEDERS_DIR"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration build option.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["(qmake note) You can use ",(0,s.jsx)(n.code,{children:'DEFINES += TINYTOM_SEEDERS_DIR="\\"database/seeders\\""'})," on the command-line or set it in the ",(0,s.jsx)(n.strong,{children:"main"})," ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/conf.pri.example#L75-L76",children:(0,s.jsx)(n.code,{children:"conf.pri"})})," file."]})]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_USING_PCH"})}),(0,s.jsxs)(n.td,{children:["Defined if building with precompiled headers.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Controlled by ",(0,s.jsx)(n.a,{href:"#qmake-precompile_header",children:(0,s.jsx)(n.code,{children:"qmake"})})," / ",(0,s.jsx)(n.a,{href:"#CMAKE_DISABLE_PRECOMPILE_HEADERS",children:(0,s.jsx)(n.code,{children:"CMake"})}),"."]})]})]})]})]})})}),"\n",(0,s.jsx)(n.h2,{id:"building-with-cmake",children:"Building with CMake"}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["If something is not clear, you can still look at GitHub Action ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/tree/main/.github/workflows",children:(0,s.jsx)(n.code,{children:"workflows"})})," how the build is done."]})}),"\n",(0,s.jsxs)(n.p,{children:["First, create a basic folder structure and then clone the ",(0,s.jsx)(n.code,{children:"TinyORM"})," project."]}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(c.A,{className:"language-powershell",children:`cd ${(0,x.Sn)(y.b)}\nmkdir ${(0,x.np)()}/TinyORM/TinyORM-builds-cmake/build-debug\n\ncd ${(0,x.np)()}/TinyORM\ngit clone git@github.com:silverqx/TinyORM.git`})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(c.A,{className:"language-bash",children:`cd ${(0,x.Sn)(y.xj)}\nmkdir -p ${(0,x.np)()}/TinyORM/TinyORM-builds-cmake/build-debug\n\ncd ${(0,x.np)()}/TinyORM\ngit clone git@github.com:silverqx/TinyORM.git`})})]}),"\n",(0,s.jsxs)(n.h3,{id:"configure-and-build-cmake",children:["Configure & Build ",(0,s.jsx)("small",{children:"(cmake)"})]}),"\n",(0,s.jsxs)(n.p,{children:["Now you are ready to configure the ",(0,s.jsx)(n.code,{children:"TinyORM"})," library."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cd TinyORM-builds-cmake/build-debug\n"})}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(c.A,{className:"language-powershell",children:`cmake.exe \`\n-S "${(0,x.OZ)(y.b)}/TinyORM/TinyORM" \`\n-B "${(0,x.OZ)(y.b)}/TinyORM/TinyORM-builds-cmake/build-debug" \`\n-G 'Ninja' \`\n-D CMAKE_BUILD_TYPE:STRING='Debug' \`\n-D CMAKE_TOOLCHAIN_FILE:FILEPATH="${(0,x.Sn)(y.b)}/vcpkg/scripts/buildsystems/vcpkg.cmake" \`\n-D CMAKE_CXX_SCAN_FOR_MODULES:BOOL=OFF \`\n-D CMAKE_INSTALL_PREFIX:PATH="${(0,x.Sn)(y.b)}/tmp/TinyORM" \`\n-D BUILD_TESTS:BOOL=OFF \`\n-D MATCH_EQUAL_EXPORTED_BUILDTREE:BOOL=ON \`\n-D MYSQL_PING:BOOL=OFF \`\n-D TOM:BOOL=ON \`\n-D TOM_EXAMPLE:BOOL=OFF \`\n-D VERBOSE_CONFIGURE:BOOL=ON`})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(c.A,{className:"language-bash",children:`cmake \\\n-S "${(0,x.OZ)(y.xj)}/TinyORM/TinyORM" \\\n-B "${(0,x.OZ)(y.xj)}/TinyORM/TinyORM-builds-cmake/build-debug" \\\n-G 'Ninja' \\\n-D CMAKE_BUILD_TYPE:STRING='Debug' \\\n-D CMAKE_TOOLCHAIN_FILE:FILEPATH="${(0,x.Sn)(y.xj)}/vcpkg/scripts/buildsystems/vcpkg.cmake" \\\n-D CMAKE_CXX_SCAN_FOR_MODULES:BOOL=OFF \\\n-D CMAKE_INSTALL_PREFIX:PATH="${(0,x.Sn)(y.xj)}/tmp/TinyORM" \\\n-D VERBOSE_CONFIGURE:BOOL=ON \\\n-D BUILD_TESTS:BOOL=OFF \\\n-D MYSQL_PING:BOOL=OFF \\\n-D TOM:BOOL=ON \\\n-D TOM_EXAMPLE:BOOL=OFF \\\n-D MATCH_EQUAL_EXPORTED_BUILDTREE:BOOL=ON`})})]}),"\n",(0,s.jsxs)(n.h5,{id:"cmake-strict_mode-option",children:["CMake ",(0,s.jsx)(n.code,{children:"STRICT_MODE"})," option"]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"STRICT_MODE"})," ",(0,s.jsx)(n.code,{children:"CMake"})," configuration option was added in ",(0,s.jsx)(n.code,{children:"TinyORM"})," ",(0,s.jsx)(n.code,{children:"v0.38.0"}),". This option was added to avoid the propagation of aggressive strict warning compiler/linker options and Qt definitions from the ",(0,s.jsx)(n.code,{children:"TinyORM"})," library to user code through the ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/cmake/CommonModules/TinyCommon.cmake",children:(0,s.jsx)(n.code,{children:"TinyOrm::CommonConfig"})})," interface library."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"TinyORM"})," uses the strictest warning level options, virtually anything that can be enabled is enabled to produce a better code. I highly recommend enabling this option to produce better code and to follow good practices. It also helps to follow the ",(0,s.jsx)(n.code,{children:"ISOCPP"})," ",(0,s.jsx)(n.a,{href:"https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines",children:"C++ Core Guidelines"})," standards."]}),"\n",(0,s.jsxs)(n.p,{children:["If you want to enable these strict warning options in your code, you can enable the ",(0,s.jsx)(n.code,{children:"STRICT_MODE"})," ",(0,s.jsx)(n.code,{children:"CMake"})," configuration option and they will be propagated to your code. You can also enabled it globally using the ",(0,s.jsx)(n.code,{children:"TINYORM_STRICT_MODE"})," environment variable, and the value of this environment variable will be picked up during initial CMake configuration as the default value for the ",(0,s.jsx)(n.code,{children:"STRICT_MODE"})," ",(0,s.jsx)(n.code,{children:"CMake"})," configuration option."]}),"\n",(0,s.jsxs)(n.p,{children:["You can achieve the same result by manually linking against the ",(0,s.jsx)(n.code,{children:"TinyOrm::CommonConfig"})," interface library when the ",(0,s.jsx)(n.code,{children:"STRICT_MODE"})," is set to ",(0,s.jsx)(n.code,{children:"OFF"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-cmake",children:"target_link_libraries(vcpkg
environment",id:"set-up-vcpkg-environment",level:4},{value:"C preprocessor macros",id:"c-preprocessor-macros",level:2},{value:"Building with CMake",id:"building-with-cmake",level:2},{value:"Configure & Build (cmake)",id:"configure-and-build-cmake",level:3},{value:"CMake STRICT_MODE
option",id:"cmake-strict_mode-option",level:5},{value:"Build TinyORM",id:"build-tinyorm",level:4},{value:"CMake build options",id:"cmake-build-options",level:3},{value:"CMake build environment variables",id:"cmake-build-environment-variables",level:3},{value:"Consume TinyOrm library (cmake)",id:"consume-tinyorm-library-cmake",level:3},{value:"Building with qmake",id:"building-with-qmake",level:2},{value:"Install dependencies",id:"install-dependencies",level:3},{value:"Configure & Build (qmake)",id:"configure-and-build-qmake",level:3},{value:"Open QtCreator IDE",id:"open-qtcreator-ide",level:4},{value:"Configure TinyORM",id:"configure-tinyorm",level:4},{value:"Auto-configuration and tiny_dotenv",id:"auto-configuration-and-tiny_dotenv",level:5},{value:"Manual configuration (conf.pri)",id:"manual-configuration-confpri",level:5},{value:"Opening TinyORM.pro (main project file)",id:"opening-tinyormpro-main-project-file",level:5},{value:"Build TinyORM",id:"build-tinyorm-1",level:4},{value:"qmake build options",id:"qmake-build-options",level:3},{value:"Consume TinyOrm library (qmake)",id:"consume-tinyorm-library-qmake",level:3},{value:"Requirements",id:"requirements",level:4},{value:"QMAKEFEATURES
",id:"qmakefeatures",level:5},{value:"Variables affecting TinyOrm.pri
",id:"variables-affecting-tinyormpri",level:5},{value:"Manual configuration examples",id:"manual-configuration-examples",level:5},{value:"Auto-configuration internals",id:"auto-configuration-internals",level:3},{value:"Environment files",id:"environment-files",level:4},{value:"Partial guessing of the TINYORM_BUILD_TREE
",id:"partial-guessing-of-the-tinyorm_build_tree",level:4},{value:"Manual configuration internals",id:"manual-configuration-internals",level:3},{value:"Ccache support",id:"ccache-support",level:2}];function I(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,d.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"building-tinyorm",children:"Building: TinyORM"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#introduction",children:"Introduction"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#common-prerequisites",children:"Common Prerequisites"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#windows-prerequisites",children:"Windows Prerequisites"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#folders-structure",children:"Folders structure"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#getting-started",children:"Getting started"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#vcpkg",children:"vcpkg"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#c-preprocessor-macros",children:"C preprocessor macros"})}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#building-with-cmake",children:"Building with CMake"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#configure-and-build-cmake",children:"Configure & Build"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#cmake-build-options",children:"CMake build options"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#cmake-build-environment-variables",children:"CMake build environment variables"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#consume-tinyorm-library-cmake",children:"Consume TinyOrm library"})}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#building-with-qmake",children:"Building with qmake"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#install-dependencies",children:"Install dependencies"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#configure-and-build-qmake",children:"Configure & Build"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#qmake-build-options",children:"qmake build options"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#consume-tinyorm-library-qmake",children:"Consume TinyOrm library"})}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#auto-configuration-internals",children:"Auto-configuration internals"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#environment-files",children:"Environment files"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#manual-configuration-internals",children:"Manual configuration internals"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#ccache-support",children:"Ccache support"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsx)("div",{className:"api-stability alert alert--success",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)(r.A,{to:"/stability#stability-indexes",children:(0,s.jsx)(n.strong,{children:"Stability: 2"})})," - Stable"]})}),"\n",(0,s.jsxs)(n.p,{children:["The build systems supported out of the box are ",(0,s.jsx)(n.code,{children:"CMake"})," and ",(0,s.jsx)(n.code,{children:"qmake"}),"."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["All examples below assume that ",(0,s.jsx)(n.code,{children:"pwsh"})," runs on ",(0,s.jsx)(n.code,{children:"Windows"})," and ",(0,s.jsx)(n.code,{children:"bash"})," runs on ",(0,s.jsx)(n.code,{children:"Linux"}),"."]})}),"\n",(0,s.jsx)(n.h4,{id:"common-prerequisites",children:"Common Prerequisites"}),"\n",(0,s.jsxs)(n.p,{children:["Install the required ",(0,s.jsx)(n.a,{href:"/dependencies",children:"dependencies"})," before starting."]}),"\n",(0,s.jsx)(n.admonition,{type:"warning",children:(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"QSqlDatabase"})," depends on ",(0,s.jsx)(n.code,{children:"QCoreApplication"})," from ",(0,s.jsx)(n.code,{children:"Qt v6.5.3"})," so you must create the ",(0,s.jsx)(n.code,{children:"QCoreApplication"})," instance before you will call anything from the ",(0,s.jsx)(n.code,{children:"TinyORM"})," library. \ud83e\udee4 The change was made ",(0,s.jsx)(n.a,{href:"https://github.com/qt/qtbase/commit/8d2bdc9cd5482eace12ba7e45304857bd24db0e6#diff-1d355c25c0b0eddec2be48253407780c4dc510d986739aec61e1ec892ccaf86e",children:"here"}),"."]})}),"\n",(0,s.jsx)(n.h4,{id:"windows-prerequisites",children:"Windows Prerequisites"}),"\n",(0,s.jsx)(n.h5,{id:"build-environment-scripts",children:"Build environment scripts"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"Visual Studio"})," does not provide ",(0,s.jsx)(n.code,{children:"vcvars"})," scripts for ",(0,s.jsx)(n.code,{children:"pwsh"}),", you can use ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/tree/main/tools/vcvars64.ps1",children:(0,s.jsx)(n.code,{children:"vcvars64.ps1"})})," provided by ",(0,s.jsx)(n.code,{children:"TinyORM"})," in the ",(0,s.jsx)(n.code,{children:"tools/"})," folder. Place them on the ",(0,s.jsx)(n.code,{children:"$env:Path"})," user/system path and they will be available system-wide."]}),"\n",(0,s.jsxs)(n.p,{children:["The same is true for the ",(0,s.jsx)(n.code,{children:"Qt Framework"}),", it doesn't provide ",(0,s.jsx)(n.code,{children:"qtenv"})," scripts for ",(0,s.jsx)(n.code,{children:"pwsh"})," too. You can create your own script, place it on the ",(0,s.jsx)(n.code,{children:"$env:Path"})," user/system path and it will be available system-wide."]}),"\n",(0,s.jsxs)(n.p,{children:["Here is one simple example for ",(0,s.jsx)(n.code,{children:"pwsh"})," and ",(0,s.jsx)(n.code,{children:"bash"})," on ",(0,s.jsx)(n.code,{children:"Linux"}),"."]}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-powershell",metastring:"title='qtenv6.ps1'",children:"#!/usr/bin/env pwsh\n\nSet-StrictMode -Version 3.0\n\nWrite-Host 'Setting up environment for Qt 6.7.2 usage...' -ForegroundColor Magenta\nWrite-Host\n\n$Script:QtRoot = $env:TINY_QT_ROOT ?? 'C:\\Qt'\n\n$env:Path = \"$Script:QtRoot\\6.7.2\\msvc2019_64\\bin;\" + $env:Path\n\n. vcvars64.ps1\n"})})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:"title='qtenv6'",children:'#!/usr/bin/env sh\n\necho \'Setting up environment for Qt 6.7.2 usage...\'\n\nQtRoot="${TINY_QT_ROOT:-/opt/Qt}"\n\nexport PATH="$QtRoot/6.7.2/gcc_64/bin"${PATH:+:}$PATH\nexport LD_LIBRARY_PATH="$QtRoot/6.7.2/gcc_64/lib"${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH\n'})})})]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["These scripts consider the ",(0,s.jsx)(n.code,{children:"TINY_QT_ROOT"})," environment variable that should point to the ",(0,s.jsx)(n.code,{children:"Qt"})," installation folder, you can define this environment variable globally in your OS."]})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["You can't execute these ",(0,s.jsx)(n.code,{children:"qtenvX"})," scripts, they have to be sourced like ",(0,s.jsx)(n.code,{children:"source qtenvX"})," or ",(0,s.jsx)(n.code,{children:". qtenvX"}),"."]})}),"\n",(0,s.jsx)(n.h5,{id:"allow-symbolic-links-unprivileged",children:"Allow symbolic links unprivileged"}),"\n",(0,s.jsxs)(n.p,{children:["Open ",(0,s.jsx)(n.code,{children:"Local Security Policy"}),", go to ",(0,s.jsx)(n.code,{children:"Local Policies - User Rights Assignment"}),", open ",(0,s.jsx)(n.code,{children:"Create symbolic links"})," and add your user account or user group, restart when it doesn't apply immediately."]}),"\n",(0,s.jsx)(n.h2,{id:"folders-structure",children:"Folders structure"}),"\n",(0,s.jsxs)(n.p,{children:["All ",(0,s.jsx)(n.code,{children:"tinyorm.org"})," examples are based on the following folders structure. The ",(0,s.jsx)(n.code,{children:"tom"})," folder will contain a ",(0,s.jsx)(n.a,{href:"/building/migrations",children:"migrations console application"}),"."]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["You can set the root and application folder paths in the form below and they will be used across the whole ",(0,s.jsx)(n.a,{href:"http://www.tinyorm.org",children:"www.tinyorm.org"})," website. \ud83e\udd73 The pwsh shell is supposed to use on Windows and the bash shell on Linux, but it is not a requirement."]})}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsxs)(t.A,{value:y.b,label:y.ux,className:"tiny-tree",children:[(0,s.jsx)("div",{className:"tiny-root-folder-info-wrapper",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)("span",{className:"tiny-root-folder-info-prefix",children:"Current pwsh path"}),"\xa0",(0,s.jsx)(u,{groupId:y.b})]})}),(0,s.jsx)(g,{groupId:y.b,label:y.ux}),(0,s.jsx)(g,{groupId:y.pW,label:y.kl}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-text",children:"\n\n\n\u251c\u2500\u2500\n\u2502 \u251c\u2500\u2500 HelloWorld/\n\u2502 | \u251c\u2500\u2500 HelloWorld/\n\u2502 | \u251c\u2500\u2500 HelloWorld-builds-cmake/\n\u2502 | | \u2514\u2500\u2500 build-debug/\n\u2502 | \u2514\u2500\u2500 HelloWorld-builds-qmake/\n\u2502 | \u2514\u2500\u2500 build-debug/\n\u2502 \u251c\u2500\u2500 TinyORM/\n\u2502 | \u251c\u2500\u2500 TinyORM/\n\u2502 | \u251c\u2500\u2500 TinyORM-builds-cmake/\n\u2502 | \u2502 \u251c\u2500\u2500 build-gcc-debug/\n\u2502 | \u2502 \u251c\u2500\u2500 build-gcc-release/\n\u2502 | \u2502 \u2514\u2500\u2500 build-clang-debug/\n\u2502 | \u2514\u2500\u2500 TinyORM-builds-qmake/\n\u2502 | \u251c\u2500\u2500 build-debug/\n\u2502 | \u251c\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_MSVC2019_64bit-Debug/\n\u2502 | \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_MSYS2_UCRT64_64bit-Release/\n\u2502 \u2514\u2500\u2500 tom/\n\u2502 \u251c\u2500\u2500 tom/\n\u2502 \u2502 \u2514\u2500\u2500 database/\n\u2502 \u2502 \u251c\u2500\u2500 migrations/\n\u2502 \u2502 \u251c\u2500\u2500 seeders/\n\u2502 \u2502 \u251c\u2500\u2500 migrations.pri\n\u2502 \u2502 \u2514\u2500\u2500 seeders.pri\n\u2502 \u251c\u2500\u2500 tom-builds-cmake/\n\u2502 \u2502 \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_MSVC2019_64bit-Debug/\n\u2502 \u2514\u2500\u2500 tom-builds-qmake/\n\u2502 \u251c\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_MSYS2_UCRT64_64bit-Release/\n\u2502 \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_MSVC2019_64bit-Debug/\n\u251c\u2500\u2500 tmp/\n\u2514\u2500\u2500 vcpkg/\n"})})]}),(0,s.jsxs)(t.A,{value:y.xj,label:y.gg,className:"tiny-tree",children:[(0,s.jsx)("div",{className:"tiny-root-folder-info-wrapper",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)("span",{className:"tiny-root-folder-info-prefix",children:"Current bash path"}),"\xa0",(0,s.jsx)(u,{groupId:y.xj})]})}),(0,s.jsx)(g,{groupId:y.xj,label:y.gg}),(0,s.jsx)(g,{groupId:y.pW,label:y.pW}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-text",children:"\n\n\n\u251c\u2500\u2500\n\u2502 \u251c\u2500\u2500 HelloWorld/\n\u2502 | \u251c\u2500\u2500 HelloWorld/\n\u2502 | \u251c\u2500\u2500 HelloWorld-builds-cmake/\n\u2502 | | \u2514\u2500\u2500 build-debug/\n\u2502 | \u2514\u2500\u2500 HelloWorld-builds-qmake/\n\u2502 | \u2514\u2500\u2500 build-debug/\n\u2502 \u251c\u2500\u2500 TinyORM/\n\u2502 | \u251c\u2500\u2500 TinyORM/\n\u2502 | \u251c\u2500\u2500 TinyORM-builds-cmake/\n\u2502 | \u2502 \u251c\u2500\u2500 build-gcc-debug/\n\u2502 | \u2502 \u251c\u2500\u2500 build-gcc-release/\n\u2502 | \u2502 \u2514\u2500\u2500 build-clang-debug/\n\u2502 | \u2514\u2500\u2500 TinyORM-builds-qmake/\n\u2502 | \u251c\u2500\u2500 build-debug/\n\u2502 | \u251c\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_GCC_64bit-Debug/\n\u2502 | \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_clang18_64bit_ccache-Release/\n\u2502 \u2514\u2500\u2500 tom/\n\u2502 \u251c\u2500\u2500 tom/\n\u2502 \u2502 \u2514\u2500\u2500 database/\n\u2502 \u2502 \u251c\u2500\u2500 migrations/\n\u2502 \u2502 \u251c\u2500\u2500 seeders/\n\u2502 \u2502 \u251c\u2500\u2500 migrations.pri\n\u2502 \u2502 \u2514\u2500\u2500 seeders.pri\n\u2502 \u251c\u2500\u2500 tom-builds-cmake/\n\u2502 \u2502 \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_clang18_64bit_ccache-Debug/\n\u2502 \u2514\u2500\u2500 tom-builds-qmake/\n\u2502 \u251c\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_GCC_64bit-Debug/\n\u2502 \u2514\u2500\u2500 build-TinyORM-Desktop_Qt_6_7_2_clang18_64bit_ccache-Release/\n\u251c\u2500\u2500 tmp/\n\u2514\u2500\u2500 vcpkg/\n"})})]})]}),"\n",(0,s.jsx)(n.admonition,{type:"danger",children:(0,s.jsxs)(n.p,{children:["Avoid paths with spaces with the ",(0,s.jsx)(n.code,{children:"qmake"})," build system, it will not compile."]})}),"\n",(0,s.jsx)(r.A,{id:"qtcreator-default-build-directory"}),"\n",(0,s.jsxs)(n.admonition,{type:"tip",children:[(0,s.jsxs)(n.p,{children:["You can force the ",(0,s.jsx)(n.code,{children:"QtCreator"})," to generate a build folders structure as is described above."]}),(0,s.jsxs)(n.p,{children:["To generate the required folders structure set the ",(0,s.jsx)(n.code,{children:"Settings"})," - ",(0,s.jsx)(n.code,{children:"Build & Run"})," - ",(0,s.jsx)(n.code,{children:"Default Build Properties"})," - ",(0,s.jsx)(n.code,{children:"Default build directory"})," to:",(0,s.jsx)("br",{}),"\n",(0,s.jsx)(n.code,{children:'../%{Project:Name}-builds-%{BuildSystem:Name}/%{JS: Util.asciify("build-%{Project:Name}-%{Kit:FileSystemName}-%{BuildConfig:Name}")}'})]})]}),"\n",(0,s.jsx)(n.h2,{id:"getting-started",children:"Getting started"}),"\n",(0,s.jsxs)(n.p,{children:["Prepare compilation environment, we need to put the Qt Framework and Visual Studio MSVC compiler on the path on Windows. The compiler is already on the path on Linux and you can export ",(0,s.jsx)(n.code,{children:"PATH"})," and ",(0,s.jsx)(n.code,{children:"LD_LIBRARY_PATH"})," for Qt Framework, or use our ",(0,s.jsx)(n.code,{children:"qtenvX"})," scripts described above."]}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(c.A,{className:"language-powershell",children:`mkdir ${(0,x.Sn)(y.b)}\ncd ${(0,x.Sn)(y.b)}\n$env:Path = 'C:\\Qt\\6.7.2\\msvc2019_64\\bin;' + $env:Path\nvcvars64.ps1`})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(c.A,{className:"language-bash",children:`mkdir -p ${(0,x.Sn)(y.xj)}\ncd ${(0,x.Sn)(y.xj)}\nexport PATH=/opt/Qt/6.7.2/gcc_64/bin\${PATH:+:}$PATH\nexport LD_LIBRARY_PATH=/opt/Qt/6.7.2/gcc_64/lib\${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH`})})]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["You can also use the ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/tools/Add-FolderOnPath.ps1",children:(0,s.jsx)(n.code,{children:"tools/Add-FolderOnPath.ps1"})})," pwsh script to quickly prepend a path or ",(0,s.jsx)("abbr",{title:"Current working directory",children:"pwd"})," on the system ",(0,s.jsx)(n.code,{children:"PATH"}),"."]})}),"\n",(0,s.jsx)(n.h2,{id:"vcpkg",children:"vcpkg"}),"\n",(0,s.jsxs)(n.p,{children:["Installing the ",(0,s.jsx)(n.code,{children:"vcpkg"})," is highly recommended, it simplifies installation of the ",(0,s.jsx)(n.code,{children:"range-v3"})," and ",(0,s.jsx)(n.code,{children:"tabulate"})," dependencies."]}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-powershell",children:"git clone git@github.com:microsoft/vcpkg.git\ncd vcpkg\n.\\bootstrap-vcpkg.bat\n"})})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"git clone git@github.com:microsoft/vcpkg.git\ncd vcpkg\n./bootstrap-vcpkg.sh\n"})})})]}),"\n",(0,s.jsxs)(n.p,{children:["Add ",(0,s.jsx)(n.code,{children:"vcpkg"})," on the system path, add the following to the ",(0,s.jsx)(n.code,{children:".bashrc"})," or ",(0,s.jsx)(n.code,{children:".zshrc"})," on Linux."]}),"\n",(0,s.jsx)(c.A,{className:"language-bash",children:`export PATH=${(0,x.Sn)(y.xj)}/vcpkg\${PATH:+:}$PATH`}),"\n",(0,s.jsxs)(n.p,{children:["On Windows, open the ",(0,s.jsx)(n.code,{children:"Environment variables"})," dialog and add ",(0,s.jsx)(n.code,{children:"vcpkg"})," on the user ",(0,s.jsx)(n.code,{children:"PATH"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Or you can export it for the current session only."}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(c.A,{className:"language-powershell",children:`$env:Path = "${(0,x.Sn)(y.b,!1)}\\vcpkg;" + $env:Path`})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(c.A,{className:"language-bash",children:`export PATH=${(0,x.Sn)(y.xj)}/vcpkg\${PATH:+:}$PATH`})})]}),"\n",(0,s.jsxs)(n.h4,{id:"set-up-vcpkg-environment",children:["Set up ",(0,s.jsx)(n.code,{children:"vcpkg"})," environment"]}),"\n",(0,s.jsxs)(n.p,{children:["To export ",(0,s.jsx)(n.code,{children:"vcpkg"})," environment variables globally, add it to the ",(0,s.jsx)(n.code,{children:".bashrc"})," or ",(0,s.jsx)(n.code,{children:".zshrc"})," on Linux, and you can use the ",(0,s.jsx)(n.code,{children:"Environment variables"})," dialog on Windows."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:"title='Linux'",children:'export VCPKG_DEFAULT_TRIPLET=x64-linux\n#export VCPKG_DEFAULT_HOST_TRIPLET=x64-linux\nexport VCPKG_MAX_CONCURRENCY=11\nexport VCPKG_OVERLAY_PORTS="$HOME/.local/share/vcpkg/ports"\nexport VCPKG_OVERLAY_TRIPLETS="$HOME/.local/share/vcpkg/triplets"\nexport VCPKG_ROOT="$HOME/Code/c/vcpkg"\n'})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["It is recommended to define these variables globally because the ",(0,s.jsx)(n.code,{children:"CMake"})," and ",(0,s.jsx)(n.code,{children:"qmake"})," build system are able to detect the ",(0,s.jsx)(n.code,{children:"vcpkg"})," installation from them so you don't have to configure them manually to detect the ",(0,s.jsx)(n.code,{children:"vcpkg"})," installation."]})}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["On Windows, it's always better to create these types of variables as user variables instead of system variables in the ",(0,s.jsx)(n.code,{children:"Environment variables"})," dialog."]})}),"\n",(0,s.jsx)(n.h2,{id:"c-preprocessor-macros",children:"C preprocessor macros"}),"\n",(0,s.jsxs)(n.p,{children:["The following table summarizes all the C preprocessor macros defined in the ",(0,s.jsx)(n.code,{children:"TinyORM"})," library. These C macros are configured by ",(0,s.jsx)(n.code,{children:"CMake"})," or ",(0,s.jsx)(n.code,{children:"qmake"})," build systems. They are not sorted alphabetically, but they are sorted by how significant they are."]}),"\n",(0,s.jsxs)(n.p,{children:["In the ",(0,s.jsx)(n.code,{children:"CMake"})," build system, all the C macros are auto-detected / auto-configured or controlled by ",(0,s.jsx)(n.a,{href:"#cmake-build-options",children:(0,s.jsx)(n.code,{children:"CMake build options"})}),", so you don't have to care too much about them."]}),"\n",(0,s.jsxs)(n.p,{children:["In the ",(0,s.jsx)(n.code,{children:"qmake"})," build is important whether you are building ",(0,s.jsx)(n.code,{children:"TinyORM"})," library or you are building your application and linking against ",(0,s.jsx)(n.code,{children:"TinyORM"})," library. When you are building the ",(0,s.jsx)(n.code,{children:"TinyORM"})," library, all the C macros are auto-detected / auto-configured or controlled by ",(0,s.jsx)(n.a,{href:"#qmake-build-options",children:(0,s.jsx)(n.code,{children:"qmake build options"})}),", so you don't have to care too much about them."]}),"\n",(0,s.jsxs)(n.p,{children:["But a special situation is when you are building your application / library and you are linking against ",(0,s.jsx)(n.code,{children:"TinyORM"})," library. In this particular case, you must configure all these C macros manually! For this reason, the ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/qmake/TinyOrm.pri",children:(0,s.jsx)(n.code,{children:"TinyOrm.pri"})})," has been created, so that's not a big deal either. Little more info ",(0,s.jsx)(n.a,{href:"#consume-tinyorm-library-qmake",children:"here"}),"."]}),"\n",(0,s.jsx)("div",{id:"apitable-c-macros",children:(0,s.jsx)(l.A,{children:(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"C Macro Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_LINKING_SHARED"})}),(0,s.jsxs)(n.td,{children:[(0,s.jsx)("u",{children:(0,s.jsx)(n.strong,{children:"Must"})})," be defined when you are linking against ",(0,s.jsx)(n.code,{children:"TinyORM"})," shared build (",(0,s.jsx)(n.code,{children:"dll"})," library), exported classes and functions will be tagged with ",(0,s.jsx)(n.code,{children:"__declspec(dllimport)"})," on ",(0,s.jsx)(n.code,{children:"msvc"})," and ",(0,s.jsx)(n.code,{children:'visibility("default")'})," on ",(0,s.jsx)(n.code,{children:"GCC >= 4"}),"."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_BUILDING_SHARED"})}),(0,s.jsxs)(n.td,{children:["Defined when ",(0,s.jsx)(n.code,{children:"TinyORM"})," is built as a ",(0,s.jsx)(n.code,{children:"dll"})," library (shared build)."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_DEBUG"})}),(0,s.jsx)(n.td,{children:"Defined in the debug build."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_NO_DEBUG"})}),(0,s.jsx)(n.td,{children:"Defined in the release build."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_DEBUG_SQL"})}),(0,s.jsx)(n.td,{children:"Defined in the debug build."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_NO_DEBUG_SQL"})}),(0,s.jsx)(n.td,{children:"Defined in the release build."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_MYSQL_PING"})}),(0,s.jsxs)(n.td,{children:["Enable ",(0,s.jsx)(n.code,{children:"Orm::MySqlConnection::pingDatabase()"})," method.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined when ",(0,s.jsx)(n.a,{href:"#mysql_ping",children:(0,s.jsx)(n.code,{children:"mysql_ping"})})," ",(0,s.jsx)("small",{children:"(qmake)"})," / ",(0,s.jsx)(n.a,{href:"#MYSQL_PING",children:(0,s.jsx)(n.code,{children:"MYSQL_PING"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration ",(0,s.jsx)(n.code,{children:"build option"})," is enabled."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_DISABLE_ORM"})}),(0,s.jsxs)(n.td,{children:["Controls the compilation of all ",(0,s.jsx)(n.code,{children:"ORM-related"})," source code, when this macro is ",(0,s.jsx)(n.code,{children:"defined"}),", then only the ",(0,s.jsx)(n.code,{children:"query builder"})," without ",(0,s.jsx)(n.code,{children:"ORM"})," is compiled. Also excludes ",(0,s.jsx)(n.code,{children:"ORM-related"})," unit tests.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined when ",(0,s.jsx)(n.a,{href:"#disable_orm",children:(0,s.jsx)(n.code,{children:"disable_orm"})})," ",(0,s.jsx)("small",{children:"(qmake)"})," / ",(0,s.jsx)(n.a,{href:"#ORM",children:(0,s.jsx)(n.code,{children:"ORM"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration ",(0,s.jsx)(n.code,{children:"build option"})," is enabled ",(0,s.jsx)("small",{children:"(qmake)"})," / disabled ",(0,s.jsx)("small",{children:"(cmake)"}),"."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_EXTERN_CONSTANTS"})}),(0,s.jsxs)(n.td,{children:["Defined when extern constants are used. Extern constants are enabled by default for shared builds and disabled for static builds.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Described at ",(0,s.jsx)(n.a,{href:"#extern_constants",children:(0,s.jsx)(n.code,{children:"qmake"})})," / ",(0,s.jsx)(n.a,{href:"#INLINE_CONSTANTS",children:(0,s.jsx)(n.code,{children:"CMake"})})," how it works."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_INLINE_CONSTANTS"})}),(0,s.jsxs)(n.td,{children:["Defined when global inline constants are used.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined when ",(0,s.jsx)(n.a,{href:"#inline_constants",children:(0,s.jsx)(n.code,{children:"inline_constants"})})," ",(0,s.jsx)("small",{children:"(qmake)"})," / ",(0,s.jsx)(n.a,{href:"#INLINE_CONSTANTS",children:(0,s.jsx)(n.code,{children:"INLINE_CONSTANTS"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration ",(0,s.jsx)(n.code,{children:"build option"})," is enabled."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_TESTS_CODE"})}),(0,s.jsxs)(n.td,{children:["Enable code needed by unit tests, eg. connection overriding in the ",(0,s.jsx)(n.code,{children:"Orm::Tiny::Model"}),".",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined when ",(0,s.jsx)(n.a,{href:"#build_tests",children:(0,s.jsx)(n.code,{children:"build_tests"})})," ",(0,s.jsx)("small",{children:"(qmake)"})," / ",(0,s.jsx)(n.a,{href:"#BUILD_TESTS",children:(0,s.jsx)(n.code,{children:"BUILD_TESTS"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration ",(0,s.jsx)(n.code,{children:"build option"})," is enabled."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_DISABLE_THREAD_LOCAL"})}),(0,s.jsxs)(n.td,{children:["Remove all ",(0,s.jsx)(n.a,{href:"https://en.cppreference.com/w/c/language/storage_duration",children:(0,s.jsx)(n.code,{children:"thread_local"})})," storage duration specifiers, it disables multi-threading support.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined when ",(0,s.jsx)(n.a,{href:"#disable_thread_local",children:(0,s.jsx)(n.code,{children:"disable_thread_local"})})," ",(0,s.jsx)("small",{children:"(qmake)"})," / ",(0,s.jsx)(n.a,{href:"#DISABLE_THREAD_LOCAL",children:(0,s.jsx)(n.code,{children:"DISABLE_THREAD_LOCAL"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration ",(0,s.jsx)(n.code,{children:"build option"})," is enabled."]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYTOM_MIGRATIONS_DIR"})}),(0,s.jsxs)(n.td,{children:["Default migrations path for the ",(0,s.jsx)(n.code,{children:"make:migration"})," command, can be an absolute or relative path (to the ",(0,s.jsx)("abbr",{title:"Current working directory",children:"pwd"}),").",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Default value: ",(0,s.jsx)(n.code,{children:"database/migrations"})," ",(0,s.jsx)("small",{children:"(relative to the pwd)"})]}),(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined by ",(0,s.jsx)(n.a,{href:"#TOM_MIGRATIONS_DIR",children:(0,s.jsx)(n.code,{children:"TOM_MIGRATIONS_DIR"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration build option.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["(qmake note) You can use ",(0,s.jsx)(n.code,{children:'DEFINES += TINYTOM_MIGRATIONS_DIR="\\"database/migrations\\""'})," on the command-line or set it in the ",(0,s.jsx)(n.strong,{children:"main"})," ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/conf.pri.example#L65-L70",children:(0,s.jsx)(n.code,{children:"conf.pri"})})," file."]})]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYTOM_MODELS_DIR"})}),(0,s.jsxs)(n.td,{children:["Default models path for the ",(0,s.jsx)(n.code,{children:"make:model"})," command, can be an absolute or relative path (to the ",(0,s.jsx)("abbr",{title:"Current working directory",children:"pwd"}),").",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Default value: ",(0,s.jsx)(n.code,{children:"database/models"})," ",(0,s.jsx)("small",{children:"(relative to the pwd)"})]}),(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined by ",(0,s.jsx)(n.a,{href:"#TOM_MODELS_DIR",children:(0,s.jsx)(n.code,{children:"TOM_MODELS_DIR"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration build option.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["(qmake note) You can use ",(0,s.jsx)(n.code,{children:'DEFINES += TINYTOM_MODELS_DIR="\\"database/models\\""'})," on the command-line or set it in the ",(0,s.jsx)(n.strong,{children:"main"})," ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/conf.pri.example#L72-L73",children:(0,s.jsx)(n.code,{children:"conf.pri"})})," file."]})]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYTOM_SEEDERS_DIR"})}),(0,s.jsxs)(n.td,{children:["Default seeders path for the ",(0,s.jsx)(n.code,{children:"make:seeder"})," command, can be an absolute or relative path (to the ",(0,s.jsx)("abbr",{title:"Current working directory",children:"pwd"}),").",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Default value: ",(0,s.jsx)(n.code,{children:"database/seeders"})," ",(0,s.jsx)("small",{children:"(relative to the pwd)"})]}),(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Defined by ",(0,s.jsx)(n.a,{href:"#TOM_SEEDERS_DIR",children:(0,s.jsx)(n.code,{children:"TOM_SEEDERS_DIR"})})," ",(0,s.jsx)("small",{children:"(cmake)"})," configuration build option.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["(qmake note) You can use ",(0,s.jsx)(n.code,{children:'DEFINES += TINYTOM_SEEDERS_DIR="\\"database/seeders\\""'})," on the command-line or set it in the ",(0,s.jsx)(n.strong,{children:"main"})," ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/conf.pri.example#L75-L76",children:(0,s.jsx)(n.code,{children:"conf.pri"})})," file."]})]})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"TINYORM_USING_PCH"})}),(0,s.jsxs)(n.td,{children:["Defined if building with precompiled headers.",(0,s.jsx)("br",{}),(0,s.jsxs)("small",{children:["Controlled by ",(0,s.jsx)(n.a,{href:"#qmake-precompile_header",children:(0,s.jsx)(n.code,{children:"qmake"})})," / ",(0,s.jsx)(n.a,{href:"#CMAKE_DISABLE_PRECOMPILE_HEADERS",children:(0,s.jsx)(n.code,{children:"CMake"})}),"."]})]})]})]})]})})}),"\n",(0,s.jsx)(n.h2,{id:"building-with-cmake",children:"Building with CMake"}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["If something is not clear, you can still look at GitHub Action ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/tree/main/.github/workflows",children:(0,s.jsx)(n.code,{children:"workflows"})})," how the build is done."]})}),"\n",(0,s.jsxs)(n.p,{children:["First, create a basic folder structure and then clone the ",(0,s.jsx)(n.code,{children:"TinyORM"})," project."]}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(c.A,{className:"language-powershell",children:`cd ${(0,x.Sn)(y.b)}\nmkdir ${(0,x.np)()}/TinyORM/TinyORM-builds-cmake/build-debug\n\ncd ${(0,x.np)()}/TinyORM\ngit clone git@github.com:silverqx/TinyORM.git`})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(c.A,{className:"language-bash",children:`cd ${(0,x.Sn)(y.xj)}\nmkdir -p ${(0,x.np)()}/TinyORM/TinyORM-builds-cmake/build-debug\n\ncd ${(0,x.np)()}/TinyORM\ngit clone git@github.com:silverqx/TinyORM.git`})})]}),"\n",(0,s.jsxs)(n.h3,{id:"configure-and-build-cmake",children:["Configure & Build ",(0,s.jsx)("small",{children:"(cmake)"})]}),"\n",(0,s.jsxs)(n.p,{children:["Now you are ready to configure the ",(0,s.jsx)(n.code,{children:"TinyORM"})," library."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cd TinyORM-builds-cmake/build-debug\n"})}),"\n",(0,s.jsxs)(o.A,{groupId:y.vf,children:[(0,s.jsx)(t.A,{value:y.b,label:y.ux,children:(0,s.jsx)(c.A,{className:"language-powershell",children:`cmake.exe \`\n-S "${(0,x.OZ)(y.b)}/TinyORM/TinyORM" \`\n-B "${(0,x.OZ)(y.b)}/TinyORM/TinyORM-builds-cmake/build-debug" \`\n-G 'Ninja' \`\n-D CMAKE_BUILD_TYPE:STRING='Debug' \`\n-D CMAKE_TOOLCHAIN_FILE:FILEPATH="${(0,x.Sn)(y.b)}/vcpkg/scripts/buildsystems/vcpkg.cmake" \`\n-D CMAKE_CXX_SCAN_FOR_MODULES:BOOL=OFF \`\n-D CMAKE_INSTALL_PREFIX:PATH="${(0,x.Sn)(y.b)}/tmp/TinyORM" \`\n-D BUILD_TESTS:BOOL=OFF \`\n-D MATCH_EQUAL_EXPORTED_BUILDTREE:BOOL=ON \`\n-D MYSQL_PING:BOOL=OFF \`\n-D TOM:BOOL=ON \`\n-D TOM_EXAMPLE:BOOL=OFF \`\n-D VERBOSE_CONFIGURE:BOOL=ON`})}),(0,s.jsx)(t.A,{value:y.xj,label:y.gg,children:(0,s.jsx)(c.A,{className:"language-bash",children:`cmake \\\n-S "${(0,x.OZ)(y.xj)}/TinyORM/TinyORM" \\\n-B "${(0,x.OZ)(y.xj)}/TinyORM/TinyORM-builds-cmake/build-debug" \\\n-G 'Ninja' \\\n-D CMAKE_BUILD_TYPE:STRING='Debug' \\\n-D CMAKE_TOOLCHAIN_FILE:FILEPATH="${(0,x.Sn)(y.xj)}/vcpkg/scripts/buildsystems/vcpkg.cmake" \\\n-D CMAKE_CXX_SCAN_FOR_MODULES:BOOL=OFF \\\n-D CMAKE_INSTALL_PREFIX:PATH="${(0,x.Sn)(y.xj)}/tmp/TinyORM" \\\n-D VERBOSE_CONFIGURE:BOOL=ON \\\n-D BUILD_TESTS:BOOL=OFF \\\n-D MYSQL_PING:BOOL=OFF \\\n-D TOM:BOOL=ON \\\n-D TOM_EXAMPLE:BOOL=OFF \\\n-D MATCH_EQUAL_EXPORTED_BUILDTREE:BOOL=ON`})})]}),"\n",(0,s.jsxs)(n.h5,{id:"cmake-strict_mode-option",children:["CMake ",(0,s.jsx)(n.code,{children:"STRICT_MODE"})," option"]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"STRICT_MODE"})," ",(0,s.jsx)(n.code,{children:"CMake"})," configuration option was added in ",(0,s.jsx)(n.code,{children:"TinyORM"})," ",(0,s.jsx)(n.code,{children:"v0.38.0"}),". This option was added to avoid the propagation of aggressive strict warning compiler/linker options and Qt definitions from the ",(0,s.jsx)(n.code,{children:"TinyORM"})," library to user code through the ",(0,s.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/blob/main/cmake/CommonModules/TinyCommon.cmake",children:(0,s.jsx)(n.code,{children:"TinyOrm::CommonConfig"})})," interface library."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"TinyORM"})," uses the strictest warning level options, virtually anything that can be enabled is enabled to produce a better code. I highly recommend enabling this option to produce better code and to follow good practices. It also helps to follow the ",(0,s.jsx)(n.code,{children:"ISOCPP"})," ",(0,s.jsx)(n.a,{href:"https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines",children:"C++ Core Guidelines"})," standards."]}),"\n",(0,s.jsxs)(n.p,{children:["If you want to enable these strict warning options in your code, you can enable the ",(0,s.jsx)(n.code,{children:"STRICT_MODE"})," ",(0,s.jsx)(n.code,{children:"CMake"})," configuration option and they will be propagated to your code. You can also enabled it globally using the ",(0,s.jsx)(n.code,{children:"TINYORM_STRICT_MODE"})," environment variable, and the value of this environment variable will be picked up during initial CMake configuration as the default value for the ",(0,s.jsx)(n.code,{children:"STRICT_MODE"})," ",(0,s.jsx)(n.code,{children:"CMake"})," configuration option."]}),"\n",(0,s.jsxs)(n.p,{children:["You can achieve the same result by manually linking against the ",(0,s.jsx)(n.code,{children:"TinyOrm::CommonConfig"})," interface library when the ",(0,s.jsx)(n.code,{children:"STRICT_MODE"})," is set to ",(0,s.jsx)(n.code,{children:"OFF"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-cmake",children:"target_link_libraries(Shared
library build",id:"the-shared-library-build",level:5},{value:"The Static
build",id:"the-static-build",level:5},{value:"The Loadable
SQL drivers build",id:"the-loadable-sql-drivers-build",level:5},{value:"CMake
/qmake
build options",id:"cmakeqmake-build-options",level:4},{value:"For CMake
",id:"for-cmake",level:5},{value:"For qmake
",id:"for-qmake",level:5},{value:"Performance",id:"performance",level:3},{value:"Internals",id:"internals",level:2},{value:"SqlDatabase",id:"sqldatabase",level:5},{value:"Namespaces",id:"namespaces",level:5},{value:"Documentation",id:"documentation",level:5}];function h(e){const i={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.header,{children:(0,r.jsx)(i.h1,{id:"tinydrivers-getting-started",children:"TinyDrivers: Getting Started"})}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.a,{href:"#introduction",children:"Introduction"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"#features-summary",children:"Features summary"})}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.a,{href:"#differences-from-qtsql",children:"Differences from QtSql"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"#build-system",children:"Build system"})}),"\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"#performance",children:"Performance"})}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"#internals",children:"Internals"})}),"\n"]}),"\n",(0,r.jsx)(i.h2,{id:"introduction",children:"Introduction"}),"\n",(0,r.jsx)("div",{className:"api-stability alert alert--success",children:(0,r.jsxs)(i.p,{children:[(0,r.jsx)(d.A,{to:"/stability#stability-indexes",children:(0,r.jsx)(i.strong,{children:"Stability: 2"})})," - Stable"]})}),"\n",(0,r.jsxs)(i.p,{children:["The ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," library is an underlying SQL database layer for ",(0,r.jsx)(i.code,{children:"TinyORM"}),". It can be used instead of the ",(0,r.jsx)(i.code,{children:"QtSql"})," module, can be ",(0,r.jsx)("u",{children:(0,r.jsx)(i.strong,{children:"swapped"})})," at compile time, and has ",(0,r.jsx)(i.strong,{children:"1:1"})," API as the ",(0,r.jsx)(i.code,{children:"QtSql"})," module. \ud83d\ude2e Swapping is controlled by the ",(0,r.jsx)(i.code,{children:"qmake"})," and ",(0,r.jsx)(i.code,{children:"CMake"})," build system options."]}),"\n",(0,r.jsxs)(i.p,{children:["It was designed to drop the ",(0,r.jsx)(i.code,{children:"QtSql"})," dependency while maintaining backward compatibility and without the need for any code changes after the swap."]}),"\n",(0,r.jsx)(i.h4,{id:"features-summary",children:"Features summary"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"both, normal and prepared statements are supported"}),"\n",(0,r.jsxs)(i.li,{children:["TLS/SSL connections using ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/mysql-options.html",children:(0,r.jsx)(i.code,{children:"MYSQL_OPT_SSL_MODE"})})," (verify_ca, verify_identity) \ud83d\udd25"]}),"\n",(0,r.jsxs)(i.li,{children:["setting many other MySQL connection options (see ",(0,r.jsx)(i.a,{href:"https://github.com/silverqx/TinyORM/blob/main/drivers/mysql/src/orm/drivers/mysql/mysqldriver_p.cpp",children:(0,r.jsx)(i.code,{children:"mysqldriver_p.cpp"})}),")"]}),"\n",(0,r.jsxs)(i.li,{children:["building and linking against the ",(0,r.jsx)(i.a,{href:"https://mariadb.com/kb/en/mariadb-connector-c/",children:(0,r.jsx)(i.code,{children:"MariaDB Connector/C"})})," \ud83d\udd7a"]}),"\n",(0,r.jsx)(i.li,{children:"transactions"}),"\n",(0,r.jsxs)(i.li,{children:["re-using the current ",(0,r.jsx)(i.code,{children:"SqlQuery"})," instance to re-execute the same or another SQL query"]}),"\n",(0,r.jsx)(i.li,{children:"detaching from the result set (related to freeing/releasing memory)"}),"\n",(0,r.jsxs)(i.li,{children:["query size, number of affected rows, last inserted ID, testing ",(0,r.jsx)(i.code,{children:"isNull()"}),", ..."]}),"\n",(0,r.jsxs)(i.li,{children:["all ",(0,r.jsx)(i.strong,{children:"3378 unit tests"})," passed \ud83d\ude2e"]}),"\n",(0,r.jsxs)(i.li,{children:["strictly using ",(0,r.jsx)(i.strong,{children:"smart pointers"})," (no ",(0,r.jsx)(i.code,{children:"new"})," keyword in the whole ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," code base \ud83d\ude0e)"]}),"\n",(0,r.jsx)(i.li,{children:"clear code \ud83e\udd14"}),"\n"]}),"\n",(0,r.jsx)(i.admonition,{type:"info",children:(0,r.jsxs)(i.p,{children:["Currently, only the ",(0,r.jsx)(i.code,{children:"MySQL"})," database driver is supported and finished. \ud83d\ude1e"]})}),"\n",(0,r.jsx)(i.admonition,{type:"note",children:(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TinyDrivers"})," library supports both build systems ",(0,r.jsx)(i.code,{children:"qmake"})," and also ",(0,r.jsx)(i.code,{children:"CMake"}),"."]})}),"\n",(0,r.jsx)(i.h2,{id:"differences-from-qtsql",children:"Differences from QtSql"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TinyDrivers"})," doesn't return errors the the same way as the ",(0,r.jsx)(i.code,{children:"QtSql"})," module, which means return a ",(0,r.jsx)(i.code,{children:"bool"})," and if it's the result ",(0,r.jsx)(i.code,{children:"false"})," then obtain the ",(0,r.jsx)(i.code,{children:"SqlError"})," instance using the ",(0,r.jsx)(i.code,{children:"lastError()"})," method from ",(0,r.jsx)(i.code,{children:"SqlDatabase"})," or ",(0,r.jsx)(i.code,{children:"SqlQuery"})," instances. Instead, it throws exceptions, and methods returning a ",(0,r.jsx)(i.code,{children:"bool"})," type to report an error state always return ",(0,r.jsx)(i.code,{children:"true"}),"."]}),"\n",(0,r.jsx)(i.h5,{id:"naming-conventions",children:"Naming conventions"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"QtSql"})," ",(0,r.jsx)("small",{children:"module"})," -> ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," ",(0,r.jsx)("small",{children:"library"})]}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"QMYSQL"})," ",(0,r.jsx)("small",{children:"driver"})," -> ",(0,r.jsx)(i.code,{children:"TinyMySql"})," ",(0,r.jsx)("small",{children:"driver"})]}),"\n"]}),"\n",(0,r.jsx)(i.h5,{id:"mysql-driver",children:"MySQL driver"}),"\n",(0,r.jsxs)(i.p,{children:["The following describes the differences between ",(0,r.jsx)(i.code,{children:"QMYSQL"})," and ",(0,r.jsx)(i.code,{children:"TinyMySql"})," drivers."]}),"\n",(0,r.jsxs)(i.p,{children:["The ",(0,r.jsx)(i.code,{children:"QMYSQL"})," driver doesn't support setting ",(0,r.jsx)(i.code,{children:"MySQL"})," non-flag ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/mysql-options.html",children:"connection options"})," like ",(0,r.jsx)(i.code,{children:"MYSQL_OPT_RECONNECT"})," without the value, it needs to be defined with value like ",(0,r.jsx)(i.code,{children:"=1"})," or ",(0,r.jsx)(i.code,{children:"=TRUE"})," (case-sensitive), only real flag options like ",(0,r.jsx)(i.code,{children:"CLIENT_INTERACTIVE"})," can be set without the value and ",(0,r.jsx)(i.code,{children:"="})," character."]}),"\n",(0,r.jsxs)(i.p,{children:["On the other hand, the ",(0,r.jsx)(i.code,{children:"TinyMySql"})," driver allows setting non-flag ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/mysql-options.html",children:"connection options"})," options without the value and ",(0,r.jsx)(i.code,{children:"="})," character, which are considered enabled (ON or TRUE)."]}),"\n",(0,r.jsx)(i.h5,{id:"removed-features",children:"Removed features"}),"\n",(0,r.jsxs)(i.p,{children:["Simulation of prepared statements while calling ",(0,r.jsx)(i.code,{children:"SqlQuery::exec(QString)"}),", this functionality is useless because you can call regular prepared statements using ",(0,r.jsx)(i.code,{children:"SqlQuery::prepare(QString)"})," and then ",(0,r.jsx)(i.code,{children:"SqlQuery::exec()"}),"."]}),"\n",(0,r.jsx)(i.h5,{id:"missing-features",children:"Missing features"}),"\n",(0,r.jsxs)(i.p,{children:["Fetching multiple result sets using ",(0,r.jsx)(i.code,{children:"SqlQuery::nextResult()"}),". Multiple statement queries are supported they will be executed correctly (they can return multiple result sets), but only the first result set can be fetched currently. However, destroying multiple result sets is handled correctly."]}),"\n",(0,r.jsx)(i.h3,{id:"build-system",children:"Build system"}),"\n",(0,r.jsxs)(i.p,{children:["Another difference is that you can build the ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," and its SQL drivers (",(0,r.jsx)(i.code,{children:"TinyMySql"}),") in 3 different ways; ",(0,r.jsx)(i.code,{children:"Shared"}),", ",(0,r.jsx)(i.code,{children:"Static"}),", and as a ",(0,r.jsx)(i.code,{children:"Loadable"})," library at runtime using ",(0,r.jsx)(i.code,{children:"LoadLibrary()"})," on Windows or ",(0,r.jsx)(i.code,{children:"dlopen()"})," on Linux."]}),"\n",(0,r.jsxs)(i.h5,{id:"the-shared-library-build",children:["The ",(0,r.jsx)(i.code,{children:"Shared"})," library build"]}),"\n",(0,r.jsxs)(i.p,{children:["It builds two shared libraries, the ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," shared library that contains the core/common code and the ",(0,r.jsx)(i.code,{children:"TinyMySql"})," shared library that contains ",(0,r.jsx)(i.code,{children:"MySQL"})," implementation. The ",(0,r.jsx)(i.code,{children:"TinyOrm"})," links only against the ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," shared library and ",(0,r.jsx)(i.code,{children:"TinyMySql"})," is a private implementation."]}),"\n",(0,r.jsxs)(i.h5,{id:"the-static-build",children:["The ",(0,r.jsx)(i.code,{children:"Static"})," build"]}),"\n",(0,r.jsxs)(i.p,{children:["It builds one ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," static archive that contains the core/common code and SQL drivers (",(0,r.jsx)(i.code,{children:"TinyMySql"}),"). This static library is linked or merged into the ",(0,r.jsx)(i.code,{children:"TinyOrm"})," shared or static library (both variants are supported)."]}),"\n",(0,r.jsxs)(i.h5,{id:"the-loadable-sql-drivers-build",children:["The ",(0,r.jsx)(i.code,{children:"Loadable"})," SQL drivers build"]}),"\n",(0,r.jsxs)(i.p,{children:["It builds two shared libraries, the ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," shared library that contains the core/common code and ",(0,r.jsx)(i.code,{children:"TinyMySql"})," shared library (module) that contains ",(0,r.jsx)(i.code,{children:"MySQL"})," implementation that is loaded at runtime using ",(0,r.jsx)(i.code,{children:"LoadLibrary()"})," on Windows or ",(0,r.jsx)(i.code,{children:"dlopen()"})," on Linux. The SQL driver library loader throws an exception if it cannot find this library at runtime."]}),"\n",(0,r.jsx)(i.admonition,{type:"info",children:(0,r.jsxs)(i.p,{children:["The ",(0,r.jsx)(i.code,{children:"TinyMySql"})," links directly against the ",(0,r.jsx)(i.code,{children:"MySQL C connector"})," (",(0,r.jsx)(i.code,{children:"libmysql"})," or ",(0,r.jsx)(i.code,{children:"mysqlclient"})," library)."]})}),"\n",(0,r.jsxs)(i.h4,{id:"cmakeqmake-build-options",children:[(0,r.jsx)(i.code,{children:"CMake"}),"/",(0,r.jsx)(i.code,{children:"qmake"})," build options"]}),"\n",(0,r.jsxs)(i.h5,{id:"for-cmake",children:["For ",(0,r.jsx)(i.code,{children:"CMake"})]}),"\n",(0,r.jsxs)(i.p,{children:["See ",(0,r.jsx)(i.a,{href:"/building/tinyorm#cmake-build-options",children:"CMake build options"}),", related ",(0,r.jsx)(i.code,{children:"CMake"})," build options are:",(0,r.jsx)("br",{}),(0,r.jsx)(i.a,{href:"/building/tinyorm#BUILD_DRIVERS",children:(0,r.jsx)(i.code,{children:"BUILD_DRIVERS"})}),", ",(0,r.jsx)(i.a,{href:"/building/tinyorm#BUILD_MYSQL_DRIVER",children:(0,r.jsx)(i.code,{children:"BUILD_MYSQL_DRIVER"})}),", and ",(0,r.jsx)(i.a,{href:"/building/tinyorm#DRIVERS_TYPE",children:(0,r.jsx)(i.code,{children:"DRIVERS_TYPE"})})]}),"\n",(0,r.jsxs)(i.p,{children:["To control shared and static build use ",(0,r.jsx)(i.a,{href:"https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html",children:(0,r.jsx)(i.code,{children:"BUILD_SHARED_LIBS"})})," ",(0,r.jsx)(i.code,{children:"CMake"})," configuration option."]}),"\n",(0,r.jsxs)(i.h5,{id:"for-qmake",children:["For ",(0,r.jsx)(i.code,{children:"qmake"})]}),"\n",(0,r.jsxs)(i.p,{children:["See ",(0,r.jsx)(i.a,{href:"/building/tinyorm#qmake-build-options",children:"qmake build options"}),", related ",(0,r.jsx)(i.code,{children:"qmake"})," configuration options are:",(0,r.jsx)("br",{}),(0,r.jsx)(i.a,{href:"/building/tinyorm#build_loadable_drivers",children:(0,r.jsx)(i.code,{children:"build_loadable_drivers"})}),", ",(0,r.jsx)(i.a,{href:"/building/tinyorm#build_mysql_driver",children:(0,r.jsx)(i.code,{children:"build_mysql_driver"})}),", ",(0,r.jsx)(i.a,{href:"/building/tinyorm#build_shared_drivers",children:(0,r.jsx)(i.code,{children:"build_shared_drivers"})}),", and ",(0,r.jsx)(i.a,{href:"/building/tinyorm#build_static_drivers",children:(0,r.jsx)(i.code,{children:"build_static_drivers"})})]}),"\n",(0,r.jsxs)(i.p,{children:["To control shared and static build use ",(0,r.jsx)(i.a,{href:"/building/tinyorm#qmake-static",children:(0,r.jsx)(i.code,{children:"static"})})," ",(0,r.jsx)(i.code,{children:"qmake"})," ",(0,r.jsx)(i.a,{href:"https://doc.qt.io/qt/qmake-variable-reference.html#config",children:"configuration option"}),"."]}),"\n",(0,r.jsx)(i.h3,{id:"performance",children:"Performance"}),"\n",(0,r.jsxs)(i.p,{children:["Performance is several milliseconds faster compared to ",(0,r.jsx)(i.code,{children:"QtSql"})," with the ",(0,r.jsx)(i.code,{children:"QMYSQL"})," driver. It was tuned using the ",(0,r.jsx)(i.code,{children:"KCacheGrind"})," to be so. It's ~40ms faster on ",(0,r.jsx)(i.a,{href:"https://github.com/silverqx/TinyOrmPlayground",children:(0,r.jsx)(i.code,{children:"TinyOrmPlayground"})})," project with ",(0,r.jsx)(i.strong,{children:"620"})," database queries compiled using ",(0,r.jsx)(i.code,{children:"GCC v13.2.1"})," Debug build on Linux. Similar results can be expected on other platforms but it's not guaranteed."]}),"\n",(0,r.jsxs)(i.p,{children:["This means performance is very similar to ",(0,r.jsx)(i.code,{children:"QtSql"}),". There is not much to speed up because ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," code is swift and 90% of the time is spent inside the ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/",children:(0,r.jsx)(i.code,{children:"MySQL C API"})})," because we always have to wait for the database server, especially when creating database connections using eg. ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/mysql-real-connect.html",children:(0,r.jsx)(i.code,{children:"mysql_real_connect()"})})," (this function is king among the slowest functions \ud83d\ude0e, which is understandable of course)."]}),"\n",(0,r.jsx)(i.h2,{id:"internals",children:"Internals"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TinyDrivers"})," internal design can be divided into 3 different layers:"]}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Driver layer"}),"\n",(0,r.jsx)(i.li,{children:"SQL API layer"}),"\n",(0,r.jsx)(i.li,{children:"Public API layer"}),"\n"]}),"\n",(0,r.jsxs)(i.p,{children:["The Driver layer is eg. ",(0,r.jsx)(i.code,{children:"TinyMySql"})," library which is responsible for communicating with the underlying database driver (eg. ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/",children:(0,r.jsx)(i.code,{children:"MySQL C API"})}),")."]}),"\n",(0,r.jsx)(i.p,{children:"The SQL API layer is a semi-layer that glues everything up and sits between the Public interface API and the Driver layer."}),"\n",(0,r.jsxs)(i.p,{children:["The Public interface API layer are the end classes like ",(0,r.jsx)(i.code,{children:"SqlDatabase"})," and ",(0,r.jsx)(i.code,{children:"SqlQuery"})," which are exposed to the end user."]}),"\n",(0,r.jsx)(i.h5,{id:"sqldatabase",children:"SqlDatabase"}),"\n",(0,r.jsxs)(i.p,{children:["One more thing worth mentioning is the ",(0,r.jsx)(i.code,{children:"SqlDatabase"})," API. It's one class that has two responsibilities! All static methods act as the database connection manager and an instance of the ",(0,r.jsx)(i.code,{children:"SqlDatabase"})," represents a physical database connection. It's not a good design because it breaks the ",(0,r.jsx)(i.a,{href:"https://en.wikipedia.org/wiki/Single_responsibility_principle",children:"Single Responsibility principle"}),", but it's what it is."]}),"\n",(0,r.jsx)(i.h5,{id:"namespaces",children:"Namespaces"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TinyDrivers"})," classes are defined in the ",(0,r.jsx)(i.code,{children:"Orm::Drivers"})," namespace and ",(0,r.jsx)(i.code,{children:"TinyMySql"})," classes in the ",(0,r.jsx)(i.code,{children:"Orm::Drivers::MySql"})," namespace."]}),"\n",(0,r.jsx)(i.h5,{id:"documentation",children:"Documentation"}),"\n",(0,r.jsxs)(i.p,{children:["For all other APIs you can follow the ",(0,r.jsx)(i.a,{href:"https://doc.qt.io/qt/qtsql-index.html",children:"QtSql documentation"})," as the API is 1:1. The exception is of course the build system, ",(0,r.jsx)(i.code,{children:"TinyOrm"})," has its own build system that doesn't follow the ",(0,r.jsx)(i.code,{children:"QtSql"})," module."]})]})}function u(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>t,x:()=>l});var r=n(6540);const s={},d=r.createContext(s);function t(e){const i=r.useContext(d);return r.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:t(e.components),r.createElement(d.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/cb1e72f9.c32b3e2f.js b/assets/js/cb1e72f9.c32b3e2f.js
deleted file mode 100644
index e40e1de59..000000000
--- a/assets/js/cb1e72f9.c32b3e2f.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunktinyorm_org=self.webpackChunktinyorm_org||[]).push([[258],{6349:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>c,contentTitle:()=>l,default:()=>u,frontMatter:()=>t,metadata:()=>a,toc:()=>o});var r=n(4848),s=n(8453),d=n(8774);const t={sidebar_position:0,sidebar_label:"Getting Started",description:"The TinyDrivers library is an underlying SQL database layer for TinyORM. It can be used instead of the QtSql module, can be swapped at compile time, and has 1:1 API as the QtSql module. Swapping is controlled by the qmake and CMake build system options. It was designed to drop the QtSql dependency while maintaining backward compatibility and without the need for any code changes after the swap.",keywords:["c++ orm","database","getting started","tinydrivers","sql drivers"]},l="TinyDrivers: Getting Started",a={id:"tinydrivers/getting-started",title:"TinyDrivers: Getting Started",description:"The TinyDrivers library is an underlying SQL database layer for TinyORM. It can be used instead of the QtSql module, can be swapped at compile time, and has 1:1 API as the QtSql module. Swapping is controlled by the qmake and CMake build system options. It was designed to drop the QtSql dependency while maintaining backward compatibility and without the need for any code changes after the swap.",source:"@site/docs/tinydrivers/getting-started.mdx",sourceDirName:"tinydrivers",slug:"/tinydrivers/getting-started",permalink:"/tinydrivers/getting-started",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:0,frontMatter:{sidebar_position:0,sidebar_label:"Getting Started",description:"The TinyDrivers library is an underlying SQL database layer for TinyORM. It can be used instead of the QtSql module, can be swapped at compile time, and has 1:1 API as the QtSql module. Swapping is controlled by the qmake and CMake build system options. It was designed to drop the QtSql dependency while maintaining backward compatibility and without the need for any code changes after the swap.",keywords:["c++ orm","database","getting started","tinydrivers","sql drivers"]},sidebar:"tinyormSidebar",previous:{title:"Serialization",permalink:"/tinyorm/serialization"},next:{title:"TinyORM",permalink:"/building/tinyorm"}},c={},o=[{value:"Introduction",id:"introduction",level:2},{value:"Features summary",id:"features-summary",level:5},{value:"Differences from QtSql",id:"differences-from-qtsql",level:2},{value:"Naming conventions",id:"naming-conventions",level:5},{value:"MySQL driver",id:"mysql-driver",level:5},{value:"Removed features",id:"removed-features",level:5},{value:"Missing features",id:"missing-features",level:5},{value:"Build system",id:"build-system",level:3},{value:"The Shared
library build",id:"the-shared-library-build",level:5},{value:"The Static
build",id:"the-static-build",level:5},{value:"The Loadable
SQL drivers build",id:"the-loadable-sql-drivers-build",level:5},{value:"CMake
/qmake
build options",id:"cmakeqmake-build-options",level:4},{value:"For CMake
",id:"for-cmake",level:5},{value:"For qmake
",id:"for-qmake",level:5},{value:"Performance",id:"performance",level:3},{value:"Internals",id:"internals",level:2},{value:"SqlDatabase",id:"sqldatabase",level:5},{value:"Namespaces",id:"namespaces",level:5},{value:"Documentation",id:"documentation",level:5}];function h(e){const i={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.header,{children:(0,r.jsx)(i.h1,{id:"tinydrivers-getting-started",children:"TinyDrivers: Getting Started"})}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"#introduction",children:"Introduction"})}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.a,{href:"#differences-from-qtsql",children:"Differences from QtSql"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"#build-system",children:"Build system"})}),"\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"#performance",children:"Performance"})}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"#internals",children:"Internals"})}),"\n"]}),"\n",(0,r.jsx)(i.h2,{id:"introduction",children:"Introduction"}),"\n",(0,r.jsx)("div",{className:"api-stability alert alert--success",children:(0,r.jsxs)(i.p,{children:[(0,r.jsx)(d.A,{to:"/stability#stability-indexes",children:(0,r.jsx)(i.strong,{children:"Stability: 2"})})," - Stable"]})}),"\n",(0,r.jsxs)(i.p,{children:["The ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," library is an underlying SQL database layer for ",(0,r.jsx)(i.code,{children:"TinyORM"}),". It can be used instead of the ",(0,r.jsx)(i.code,{children:"QtSql"})," module, can be ",(0,r.jsx)("u",{children:(0,r.jsx)(i.strong,{children:"swapped"})})," at compile time, and has ",(0,r.jsx)(i.strong,{children:"1:1"})," API as the ",(0,r.jsx)(i.code,{children:"QtSql"})," module. \ud83d\ude2e Swapping is controlled by the ",(0,r.jsx)(i.code,{children:"qmake"})," and ",(0,r.jsx)(i.code,{children:"CMake"})," build system options."]}),"\n",(0,r.jsxs)(i.p,{children:["It was designed to drop the ",(0,r.jsx)(i.code,{children:"QtSql"})," dependency while maintaining backward compatibility and without the need for any code changes after the swap."]}),"\n",(0,r.jsx)(i.h5,{id:"features-summary",children:"Features summary"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"both, normal and prepared statements are supported"}),"\n",(0,r.jsxs)(i.li,{children:["TLS/SSL connections using ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/mysql-options.html",children:(0,r.jsx)(i.code,{children:"MYSQL_OPT_SSL_MODE"})})," (verify_ca, verify_identity) \ud83d\udd25"]}),"\n",(0,r.jsxs)(i.li,{children:["setting many other connection options (see ",(0,r.jsx)(i.a,{href:"https://github.com/silverqx/TinyORM/blob/main/drivers/mysql/src/orm/drivers/mysql/mysqldriver_p.cpp",children:(0,r.jsx)(i.code,{children:"mysqldriver_p.cpp"})}),")"]}),"\n",(0,r.jsxs)(i.li,{children:["building and linking against the ",(0,r.jsx)(i.a,{href:"https://mariadb.com/kb/en/mariadb-connector-c/",children:(0,r.jsx)(i.code,{children:"MariaDB Connector/C"})})]}),"\n",(0,r.jsx)(i.li,{children:"transactions"}),"\n",(0,r.jsxs)(i.li,{children:["re-using the current ",(0,r.jsx)(i.code,{children:"SqlQuery"})," instance to re-execute the same or another query"]}),"\n",(0,r.jsx)(i.li,{children:"detaching from the result set (associated to release memory)"}),"\n",(0,r.jsxs)(i.li,{children:["query size, number of affected rows, last inserted ID, testing ",(0,r.jsx)(i.code,{children:"isNull()"}),", ..."]}),"\n",(0,r.jsxs)(i.li,{children:["all ",(0,r.jsx)(i.strong,{children:"3378 unit tests"})," passed \ud83d\ude2e"]}),"\n"]}),"\n",(0,r.jsx)(i.admonition,{type:"info",children:(0,r.jsxs)(i.p,{children:["Currently, only the ",(0,r.jsx)(i.code,{children:"MySQL"})," database driver is supported and finished."]})}),"\n",(0,r.jsx)(i.admonition,{type:"note",children:(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TinyDrivers"})," library supports both build systems ",(0,r.jsx)(i.code,{children:"qmake"})," and also ",(0,r.jsx)(i.code,{children:"CMake"}),"."]})}),"\n",(0,r.jsx)(i.h2,{id:"differences-from-qtsql",children:"Differences from QtSql"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TinyDrivers"})," doesn't return errors the the same way as the ",(0,r.jsx)(i.code,{children:"QtSql"})," module, which means return a ",(0,r.jsx)(i.code,{children:"bool"})," and if it's the result ",(0,r.jsx)(i.code,{children:"false"})," then obtain the ",(0,r.jsx)(i.code,{children:"SqlError"})," instance using the ",(0,r.jsx)(i.code,{children:"lastError()"})," method from ",(0,r.jsx)(i.code,{children:"SqlDatabase"})," or ",(0,r.jsx)(i.code,{children:"SqlQuery"})," instances. Instead, it throws exceptions, and methods returning a ",(0,r.jsx)(i.code,{children:"bool"})," type to report an error state always return ",(0,r.jsx)(i.code,{children:"true"}),"."]}),"\n",(0,r.jsx)(i.h5,{id:"naming-conventions",children:"Naming conventions"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"QtSql"})," ",(0,r.jsx)("small",{children:"module"})," -> ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," ",(0,r.jsx)("small",{children:"library"})]}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"QMYSQL"})," ",(0,r.jsx)("small",{children:"driver"})," -> ",(0,r.jsx)(i.code,{children:"TinyMySql"})," ",(0,r.jsx)("small",{children:"driver"})]}),"\n"]}),"\n",(0,r.jsx)(i.h5,{id:"mysql-driver",children:"MySQL driver"}),"\n",(0,r.jsxs)(i.p,{children:["The following describes the differences between ",(0,r.jsx)(i.code,{children:"QMYSQL"})," and ",(0,r.jsx)(i.code,{children:"TinyMySql"})," drivers."]}),"\n",(0,r.jsxs)(i.p,{children:["The ",(0,r.jsx)(i.code,{children:"QMYSQL"})," driver doesn't support setting ",(0,r.jsx)(i.code,{children:"MySQL"})," non-flag ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/mysql-options.html",children:"connection options"})," like ",(0,r.jsx)(i.code,{children:"MYSQL_OPT_RECONNECT"})," without the value, it needs to be defined with value like ",(0,r.jsx)(i.code,{children:"=1"})," or ",(0,r.jsx)(i.code,{children:"=TRUE"})," (case-sensitive), only real flag options like ",(0,r.jsx)(i.code,{children:"CLIENT_INTERACTIVE"})," can be set without the value and ",(0,r.jsx)(i.code,{children:"="})," character."]}),"\n",(0,r.jsxs)(i.p,{children:["On the other hand, the ",(0,r.jsx)(i.code,{children:"TinyMySql"})," driver allows setting non-flag ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/mysql-options.html",children:"connection options"})," options without the value and ",(0,r.jsx)(i.code,{children:"="})," character, which are considered enabled (ON or TRUE)."]}),"\n",(0,r.jsx)(i.h5,{id:"removed-features",children:"Removed features"}),"\n",(0,r.jsxs)(i.p,{children:["Simulation of prepared statements while calling ",(0,r.jsx)(i.code,{children:"SqlQuery::exec(QString)"}),", this functionality is useless because you can call regular prepared statements using ",(0,r.jsx)(i.code,{children:"SqlQuery::prepare(QString)"})," and then ",(0,r.jsx)(i.code,{children:"SqlQuery::exec()"}),"."]}),"\n",(0,r.jsx)(i.h5,{id:"missing-features",children:"Missing features"}),"\n",(0,r.jsxs)(i.p,{children:["Fetching multiple result sets using ",(0,r.jsx)(i.code,{children:"SqlQuery::nextResult()"}),". Multiple statement queries are supported they will be executed correctly (they can return multiple result sets), but only the first result set can be fetched currently. However, destroying multiple result sets is handled correctly."]}),"\n",(0,r.jsx)(i.h3,{id:"build-system",children:"Build system"}),"\n",(0,r.jsxs)(i.p,{children:["Another difference is that you can build the ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," and its SQL drivers (",(0,r.jsx)(i.code,{children:"TinyMySql"}),") in 3 different ways; ",(0,r.jsx)(i.code,{children:"Shared"}),", ",(0,r.jsx)(i.code,{children:"Static"}),", and as a ",(0,r.jsx)(i.code,{children:"Loadable"})," library at runtime using ",(0,r.jsx)(i.code,{children:"LoadLibrary()"})," on Windows or ",(0,r.jsx)(i.code,{children:"dlopen()"})," on Linux."]}),"\n",(0,r.jsxs)(i.h5,{id:"the-shared-library-build",children:["The ",(0,r.jsx)(i.code,{children:"Shared"})," library build"]}),"\n",(0,r.jsxs)(i.p,{children:["It builds two shared libraries, the ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," shared library that contains the core/common code and the ",(0,r.jsx)(i.code,{children:"TinyMySql"})," shared library that contains ",(0,r.jsx)(i.code,{children:"MySQL"})," implementation. The ",(0,r.jsx)(i.code,{children:"TinyOrm"})," links only against the ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," shared library and ",(0,r.jsx)(i.code,{children:"TinyMySql"})," is a private implementation."]}),"\n",(0,r.jsxs)(i.h5,{id:"the-static-build",children:["The ",(0,r.jsx)(i.code,{children:"Static"})," build"]}),"\n",(0,r.jsxs)(i.p,{children:["It builds one ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," static archive that contains the core/common code and SQL drivers (",(0,r.jsx)(i.code,{children:"TinyMySql"}),"). This static library is linked or merged into the ",(0,r.jsx)(i.code,{children:"TinyOrm"})," shared or static library (both variants are supported)."]}),"\n",(0,r.jsxs)(i.h5,{id:"the-loadable-sql-drivers-build",children:["The ",(0,r.jsx)(i.code,{children:"Loadable"})," SQL drivers build"]}),"\n",(0,r.jsxs)(i.p,{children:["It builds two shared libraries, the ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," shared library that contains the core/common code and ",(0,r.jsx)(i.code,{children:"TinyMySql"})," shared library (module) that contains ",(0,r.jsx)(i.code,{children:"MySQL"})," implementation that is loaded at runtime using ",(0,r.jsx)(i.code,{children:"LoadLibrary()"})," on Windows or ",(0,r.jsx)(i.code,{children:"dlopen()"})," on Linux. The SQL driver library loader throws an exception if it cannot find this library at runtime."]}),"\n",(0,r.jsx)(i.admonition,{type:"info",children:(0,r.jsxs)(i.p,{children:["The ",(0,r.jsx)(i.code,{children:"TinyMySql"})," links directly against the ",(0,r.jsx)(i.code,{children:"MySQL C connector"})," (",(0,r.jsx)(i.code,{children:"libmysql"})," or ",(0,r.jsx)(i.code,{children:"mysqlclient"})," library)."]})}),"\n",(0,r.jsxs)(i.h4,{id:"cmakeqmake-build-options",children:[(0,r.jsx)(i.code,{children:"CMake"}),"/",(0,r.jsx)(i.code,{children:"qmake"})," build options"]}),"\n",(0,r.jsxs)(i.h5,{id:"for-cmake",children:["For ",(0,r.jsx)(i.code,{children:"CMake"})]}),"\n",(0,r.jsxs)(i.p,{children:["See ",(0,r.jsx)(i.a,{href:"/building/tinyorm#cmake-build-options",children:"CMake build options"}),", related ",(0,r.jsx)(i.code,{children:"CMake"})," build options are:",(0,r.jsx)("br",{}),(0,r.jsx)(i.a,{href:"/building/tinyorm#BUILD_DRIVERS",children:(0,r.jsx)(i.code,{children:"BUILD_DRIVERS"})}),", ",(0,r.jsx)(i.a,{href:"/building/tinyorm#BUILD_MYSQL_DRIVER",children:(0,r.jsx)(i.code,{children:"BUILD_MYSQL_DRIVER"})}),", and ",(0,r.jsx)(i.a,{href:"/building/tinyorm#DRIVERS_TYPE",children:(0,r.jsx)(i.code,{children:"DRIVERS_TYPE"})})]}),"\n",(0,r.jsxs)(i.p,{children:["To control shared and static build use ",(0,r.jsx)(i.a,{href:"https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html",children:(0,r.jsx)(i.code,{children:"BUILD_SHARED_LIBS"})})," ",(0,r.jsx)(i.code,{children:"CMake"})," configuration option."]}),"\n",(0,r.jsxs)(i.h5,{id:"for-qmake",children:["For ",(0,r.jsx)(i.code,{children:"qmake"})]}),"\n",(0,r.jsxs)(i.p,{children:["See ",(0,r.jsx)(i.a,{href:"/building/tinyorm#qmake-build-options",children:"qmake build options"}),", related ",(0,r.jsx)(i.code,{children:"qmake"})," configuration options are:",(0,r.jsx)("br",{}),(0,r.jsx)(i.a,{href:"/building/tinyorm#build_loadable_drivers",children:(0,r.jsx)(i.code,{children:"build_loadable_drivers"})}),", ",(0,r.jsx)(i.a,{href:"/building/tinyorm#build_mysql_driver",children:(0,r.jsx)(i.code,{children:"build_mysql_driver"})}),", ",(0,r.jsx)(i.a,{href:"/building/tinyorm#build_shared_drivers",children:(0,r.jsx)(i.code,{children:"build_shared_drivers"})}),", and ",(0,r.jsx)(i.a,{href:"/building/tinyorm#build_static_drivers",children:(0,r.jsx)(i.code,{children:"build_static_drivers"})})]}),"\n",(0,r.jsxs)(i.p,{children:["To control shared and static build use ",(0,r.jsx)(i.a,{href:"/building/tinyorm#qmake-static",children:(0,r.jsx)(i.code,{children:"static"})})," ",(0,r.jsx)(i.code,{children:"qmake"})," ",(0,r.jsx)(i.a,{href:"https://doc.qt.io/qt/qmake-variable-reference.html#config",children:"configuration option"}),"."]}),"\n",(0,r.jsx)(i.h3,{id:"performance",children:"Performance"}),"\n",(0,r.jsxs)(i.p,{children:["Performance is several milliseconds faster compared to ",(0,r.jsx)(i.code,{children:"QtSql"})," with the ",(0,r.jsx)(i.code,{children:"QMYSQL"})," driver. It was tuned using the ",(0,r.jsx)(i.code,{children:"KCacheGrind"})," to be so. It's ~40ms faster on ",(0,r.jsx)(i.a,{href:"https://github.com/silverqx/TinyOrmPlayground",children:(0,r.jsx)(i.code,{children:"TinyOrmPlayground"})})," project with ",(0,r.jsx)(i.strong,{children:"620"})," database queries compiled using ",(0,r.jsx)(i.code,{children:"GCC v13.2.1"})," Debug build on Linux. Similar results can be expected on other platforms but it's not guaranteed."]}),"\n",(0,r.jsxs)(i.p,{children:["This means performance is very similar to ",(0,r.jsx)(i.code,{children:"QtSql"}),". There is not much to speed up because ",(0,r.jsx)(i.code,{children:"TinyDrivers"})," code is swift and 90% of the time is spent inside the ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/",children:(0,r.jsx)(i.code,{children:"MySQL C API"})})," because we always have to wait for the database server, especially when creating database connections using eg. ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/mysql-real-connect.html",children:(0,r.jsx)(i.code,{children:"mysql_real_connect()"})})," (this function is king among the slowest functions \ud83d\ude0e, which is understandable of course)."]}),"\n",(0,r.jsx)(i.h2,{id:"internals",children:"Internals"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TinyDrivers"})," internal design can be divided into 3 different layers:"]}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Driver layer"}),"\n",(0,r.jsx)(i.li,{children:"SQL API layer"}),"\n",(0,r.jsx)(i.li,{children:"Public API layer"}),"\n"]}),"\n",(0,r.jsxs)(i.p,{children:["The Driver layer is eg. ",(0,r.jsx)(i.code,{children:"TinyMySql"})," library which is responsible for communicating with the underlying database driver (eg. ",(0,r.jsx)(i.a,{href:"https://dev.mysql.com/doc/c-api/9.0/en/",children:(0,r.jsx)(i.code,{children:"MySQL C API"})}),")."]}),"\n",(0,r.jsx)(i.p,{children:"The SQL API layer is a semi-layer that glues everything up and sits between the Public interface API and the Driver layer."}),"\n",(0,r.jsxs)(i.p,{children:["The Public interface API layer are the end classes like ",(0,r.jsx)(i.code,{children:"SqlDatabase"})," and ",(0,r.jsx)(i.code,{children:"SqlQuery"})," which are exposed to the end user."]}),"\n",(0,r.jsx)(i.h5,{id:"sqldatabase",children:"SqlDatabase"}),"\n",(0,r.jsxs)(i.p,{children:["One more thing worth mentioning is the ",(0,r.jsx)(i.code,{children:"SqlDatabase"})," API. It's one class that has two responsibilities! All static methods act as the database connection manager and an instance of the ",(0,r.jsx)(i.code,{children:"SqlDatabase"})," represents a physical database connection. It's not a good design because it breaks the ",(0,r.jsx)(i.a,{href:"https://en.wikipedia.org/wiki/Single_responsibility_principle",children:"Single Responsibility principle"}),", but it's what it is."]}),"\n",(0,r.jsx)(i.h5,{id:"namespaces",children:"Namespaces"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TinyDrivers"})," classes are defined in the ",(0,r.jsx)(i.code,{children:"Orm::Drivers"})," namespace and ",(0,r.jsx)(i.code,{children:"TinyMySql"})," classes in the ",(0,r.jsx)(i.code,{children:"Orm::Drivers::MySql"})," namespace."]}),"\n",(0,r.jsx)(i.h5,{id:"documentation",children:"Documentation"}),"\n",(0,r.jsxs)(i.p,{children:["For all other APIs you can follow the ",(0,r.jsx)(i.a,{href:"https://doc.qt.io/qt/qtsql-index.html",children:"QtSql documentation"})," as the API is 1:1. The exception is of course the build system, ",(0,r.jsx)(i.code,{children:"TinyOrm"})," has its own build system that doesn't follow the ",(0,r.jsx)(i.code,{children:"QtSql"})," module."]})]})}function u(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>t,x:()=>l});var r=n(6540);const s={},d=r.createContext(s);function t(e){const i=r.useContext(d);return r.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:t(e.components),r.createElement(d.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/e19c288b.a42b5d93.js b/assets/js/e19c288b.a42b5d93.js
deleted file mode 100644
index 8b6086c9c..000000000
--- a/assets/js/e19c288b.a42b5d93.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunktinyorm_org=self.webpackChunktinyorm_org||[]).push([[69],{9158:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>a,metadata:()=>d,toc:()=>l});var t=r(4848),o=r(8453),s=r(6684);const a={sidebar_position:9,sidebar_label:"\u2764\ufe0f Sponsors",hide_table_of_contents:!0,description:"How to sponsor and support the TinyORM project.",keywords:["c++ orm","tinyorm","support","fund","funding","sponsors","donations","sponsors"]},i="Sponsors",d={id:"sponsors",title:"Sponsors",description:"How to sponsor and support the TinyORM project.",source:"@site/docs/sponsors.mdx",sourceDirName:".",slug:"/sponsors",permalink:"/sponsors",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:9,frontMatter:{sidebar_position:9,sidebar_label:"\u2764\ufe0f Sponsors",hide_table_of_contents:!0,description:"How to sponsor and support the TinyORM project.",keywords:["c++ orm","tinyorm","support","fund","funding","sponsors","donations","sponsors"]},sidebar:"tinyormSidebar",previous:{title:"\ud83d\udcc4 Features Summary",permalink:"/features-summary"}},c={},l=[];function p(e){const n={a:"a",h1:"h1",header:"header",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"sponsors",children:"Sponsors"})}),"\n",(0,t.jsx)(n.p,{children:"I have spent ~2 years every day 10 hours of coding (excluding weekends and sick days) to make this project real. Everything was funded from my personal resources, I had no problem with it to be honest, it was really fun \ud83c\udf89, but I had to move to the new apartment a few months ago and I'm out of money now. \u2639\ufe0f"}),"\n",(0,t.jsx)(n.p,{children:"I would like to continue developing and enhancing this project and I will as long as I can. But the future is unclear now."}),"\n",(0,t.jsx)("div",{id:"apitable-sponsors",children:(0,t.jsx)(s.A,{children:(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Service"}),(0,t.jsx)(n.th,{children:"Address"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Bitcoin address"}),(0,t.jsx)(n.td,{children:"1NiF2cTvYxUj8FTZJnGn1ycN4yisWfo1vJ"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"PayPal"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://paypal.me/silverzachara",children:"https://paypal.me/silverzachara"})})]})]})]})})})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},6684:(e,n,r)=>{r.d(n,{A:()=>l});var t=r(6540),o=r(3427),s=r(6347);const a={apiTable:"apiTable_flxF"};var i=r(4848);function d(e,n){let{name:r,children:a}=e;const d=function(e){let n=e;for(;(0,t.isValidElement)(n);)[n]=t.Children.toArray(n.props.children);if("string"!=typeof n)throw new Error(`Could not extract APITable row name from JSX tree:\n${JSON.stringify(e,null,2)}`);return n}(a),c=r?`${r}-${d}`:d,l=`#${c}`,p=(0,s.W6)();return(0,o.A)().collectAnchor(c),(0,i.jsx)("tr",{id:c,tabIndex:0,ref:p.location.hash===l?n:void 0,onClick:e=>{const n=e.target;[n,n.parentElement].some((e=>"A"===e?.tagName.toUpperCase()))||p.push(l)},onKeyDown:e=>{"Enter"===e.key&&p.push(l)},children:a.props.children})}const c=t.forwardRef(d);function l(e){let{children:n,name:r}=e;if("table"!==n.type)throw new Error("Bad usage of APITable component.\nIt is probably that your Markdown table is malformed.\nMake sure to double-check you have the appropriate number of columns for each table row.");const[o,s]=t.Children.toArray(n.props.children),d=(0,t.useRef)(null);(0,t.useEffect)((()=>{d.current?.focus()}),[d]);const l=t.Children.map(s.props.children,(e=>(0,i.jsx)(c,{name:r,ref:d,children:e})));return(0,i.jsxs)("table",{className:a.apiTable,children:[o,(0,i.jsx)("tbody",{children:l})]})}},8453:(e,n,r)=>{r.d(n,{R:()=>a,x:()=>i});var t=r(6540);const o={},s=t.createContext(o);function a(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/fb313d4e.afd496da.js b/assets/js/fb313d4e.afd496da.js
new file mode 100644
index 000000000..c1294034c
--- /dev/null
+++ b/assets/js/fb313d4e.afd496da.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunktinyorm_org=self.webpackChunktinyorm_org||[]).push([[871],{8489:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var i=s(4848),t=s(8453);const r={sidebar_position:8,sidebar_label:"\ud83d\udcc4 Features Summary",hide_table_of_contents:!0,description:"List that quickly summarizes all TinyORM features.",keywords:["c++ orm","tinyorm","features","summary","features summary"]},a="Features Summary",l={id:"features-summary",title:"Features Summary",description:"List that quickly summarizes all TinyORM features.",source:"@site/docs/features-summary.mdx",sourceDirName:".",slug:"/features-summary",permalink:"/features-summary",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:8,frontMatter:{sidebar_position:8,sidebar_label:"\ud83d\udcc4 Features Summary",hide_table_of_contents:!0,description:"List that quickly summarizes all TinyORM features.",keywords:["c++ orm","tinyorm","features","summary","features summary"]},sidebar:"tinyormSidebar",previous:{title:"\ud83d\udea9 Stability",permalink:"/stability"},next:{title:"\ud83e\ude99 Donations",permalink:"/donations"}},o={},d=[{value:"Summary List",id:"summary-list",level:2},{value:"Showcase Images",id:"showcase-images",level:2},{value:"Tom console application",id:"tom-console-application",level:6},{value:"Passed all unit tests \ud83e\udd73",id:"passed-all-unit-tests-",level:6},{value:"TinyOrmPlayground",id:"tinyormplayground",level:4},{value:"TinyOrmPlayground single-threaded",id:"tinyormplayground-single-threaded",level:6},{value:"TinyOrmPlayground multi-threaded",id:"tinyormplayground-multi-threaded",level:6}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h4:"h4",h6:"h6",header:"header",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"features-summary",children:"Features Summary"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"#summary-list",children:"Summary List"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"#showcase-images",children:"Showcase Images"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"summary-list",children:"Summary List"}),"\n",(0,i.jsxs)(n.p,{children:["The following list quickly summarizes all the ",(0,i.jsx)(n.code,{children:"TinyORM"})," features."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"simple database connections management"})," \ud83e\uddec","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"database manager that helps with the database connections management"}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Orm::DB"})," facade class for nicer and shorter syntax"]}),"\n",(0,i.jsxs)(n.li,{children:["MySQL, MariaDB, SQLite, and PostgreSQL support for ",(0,i.jsx)(n.strong,{children:"all"})," features \ud83d\udc8e"]}),"\n",(0,i.jsx)(n.li,{children:"multi-threading support \ud83d\udc40"}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"SSL"})," connections support \ud83d\udd12"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"impressive query builder"})," \ud83d\udd27","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"allows passing sub-queries and raw expressions practically everywhere, to column names, values, and to every SQL clause as select, where, joins, group by, having, order by \ud83d\udd25"}),"\n",(0,i.jsx)(n.li,{children:"a logical grouping that offers to wrap logical groups in parenthesis"}),"\n",(0,i.jsx)(n.li,{children:"chunked results for lower memory footprint \u2728"}),"\n",(0,i.jsx)(n.li,{children:"raw methods for all SQL clauses"}),"\n",(0,i.jsx)(n.li,{children:"all join types (left, right, cross, inner) and also join where clause support \ud83e\udee4"}),"\n",(0,i.jsx)(n.li,{children:"aggregate methods min, max, sum, increment, decrement, ..."}),"\n",(0,i.jsx)(n.li,{children:"whereExists and exists methods for an existence queries"}),"\n",(0,i.jsx)(n.li,{children:"transactions and pessimistic locking \ud83d\udd12"}),"\n",(0,i.jsx)(n.li,{children:"of course, insert, update, and delete SQL clauses support"}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"correct QDateTime time zone"})," using the ",(0,i.jsx)(n.code,{children:"qt_timezone"})," connection configuration option \ud83d\udcc5 (returned QDateTime instances will have the correct time zone, and also works for an ORM)","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"this feature allows you to set up the database server time zone to the UTC and all returned QDateTime instances will have the correct UTC time zone"}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"clever ORM with all relation types support"})," \ud83c\udf89","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"one-to-one, one-to-many, and many-to-many relation types (also inverse relationships) \ud83e\udde8"}),"\n",(0,i.jsx)(n.li,{children:"eager and lazy loading with custom select and constraints \ud83d\ude80"}),"\n",(0,i.jsxs)(n.li,{children:["fluent ",(0,i.jsx)(n.code,{children:"ModelsCollection"})," that expose a variety of map / reduce operations that may be chained using an intuitive interface \u2728"]}),"\n",(0,i.jsx)(n.li,{children:"all query builder methods are proxied from the model instances and also from the relation instances back to the query builder \ud83e\udd2f (everything that can be called on the query builder can also be called on the model and relation instances)"}),"\n",(0,i.jsx)(n.li,{children:"clean active record pattern"}),"\n",(0,i.jsxs)(n.li,{children:["advanced features like timestamps, touching parent timestamps, ",(0,i.jsx)(n.strong,{children:"soft deleting"}),", default models, default model attributes, and attributes casting \ud83e\udd13"]}),"\n",(0,i.jsxs)(n.li,{children:["querying relationships existence/absence using the has, whereHas, and hasNested methods (using dot notation for selecting nested relationships ",(0,i.jsx)(n.em,{children:"users.posts.comments"}),")"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"serializing"})," models and collection of models including all nested relations to ",(0,i.jsx)(n.strong,{children:"JSON"})," and converting to vectors and maps \ud83e\udea1","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"supports controlling a custom date format during serialization"}),"\n",(0,i.jsx)(n.li,{children:"supports hiding and appending attributes"}),"\n",(0,i.jsxs)(n.li,{children:["supports defining ",(0,i.jsx)(n.strong,{children:"Accessors"})," (transform attribute value when it is accessed; eg. building value from multiple attributes)"]}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"compiled database migrations and seeders"})," \ud83d\udd7a","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"create, update, drop, and rename database tables"}),"\n",(0,i.jsxs)(n.li,{children:["create, ",(0,i.jsx)(n.strong,{children:"update"}),", drop, and rename table columns"]}),"\n",(0,i.jsx)(n.li,{children:"extensive schema builder that allows creating of all possible column types"}),"\n",(0,i.jsx)(n.li,{children:"terser syntax for creating foreign keys and foreign key constraints"}),"\n",(0,i.jsx)(n.li,{children:"supports creating and dropping column indexes (primary, unique, fulltext, spatial)"}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsxs)(n.strong,{children:["the ",(0,i.jsx)(n.code,{children:"tom"})," console application with tab completion for all shells (pwsh, bash, zsh)"]})," \ud83e\udd73","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["tab completion is as accurate as possible","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"completes commands, long and short parameters, argument values"}),"\n",(0,i.jsx)(n.li,{children:"even connection names can be completed"}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"migrate, fresh, refresh, rollback, and reset migrate operations"}),"\n",(0,i.jsx)(n.li,{children:"install and uninstall migration repository (table that tracks migrations and batches; table name can be customized)"}),"\n",(0,i.jsx)(n.li,{children:"seed and wipe database operations"}),"\n",(0,i.jsx)(n.li,{children:"scaffolding of models, migrations, and seeders"}),"\n",(0,i.jsxs)(n.li,{children:["impressive models scaffolding, every feature that is supported by models can be generated using the ",(0,i.jsx)(n.code,{children:"tom make:model"})," cli command"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"others"})," \ud83d\udedd","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["a huge amount of code is unit tested, currently ",(0,i.jsx)(n.strong,{children:"3378 unit tests"})," \ud83e\udd2f"]}),"\n",(0,i.jsxs)(n.li,{children:["C++20 only, with all the latest features used like concepts/constraints, ranges, ",(0,i.jsx)(n.strong,{children:"smart pointers"})," (no ",(0,i.jsx)(n.code,{children:"new"})," keyword in the whole code base \ud83d\ude0e), folding expressions"]}),"\n",(0,i.jsxs)(n.li,{children:["qmake and CMake build systems support","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["CMake ",(0,i.jsx)(n.strong,{children:"FetchContent"})," module support \ud83e\udd19"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"LTO"})," support (backed up by CI)"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["vcpkg support (official ",(0,i.jsx)(n.a,{href:"https://github.com/microsoft/vcpkg/tree/master/ports/tinyorm",children:"tinyorm"})," vcpkg port)","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["official port doesn't allow to have alternative implementations so it doesn't contain ",(0,i.jsx)(n.strong,{children:"TinyDrivers"})]}),"\n",(0,i.jsxs)(n.li,{children:["unofficial ",(0,i.jsx)(n.a,{href:"https://github.com/silverqx/TinyORM/tree/main/cmake/vcpkg/ports/tinyorm",children:"tinyorm"})," vcpkg port with ",(0,i.jsx)(n.strong,{children:"TinyDrivers"})," support (currently MySQL only)"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"it's really fast, you can run 1000 complex queries in 500ms (heavily DB dependent, the PostgreSQL is by far the fastest) \u231a"}),"\n",(0,i.jsx)(n.li,{children:"extensive documentation \ud83d\udcc3"}),"\n",(0,i.jsx)(n.li,{children:"..."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["See the ",(0,i.jsx)(n.code,{children:"TinyDrivers"})," ",(0,i.jsx)(n.a,{href:"tinydrivers/getting-started#features-summary",children:"Features summary"}),"."]})}),"\n",(0,i.jsx)(n.h2,{id:"showcase-images",children:"Showcase Images"}),"\n",(0,i.jsx)(n.h6,{id:"tom-console-application",children:"Tom console application"}),"\n",(0,i.jsx)("img",{src:s(5848).A,alt:"TinyORM - Tom console application - Showcase",title:"Tom console application"}),"\n",(0,i.jsx)(n.h6,{id:"passed-all-unit-tests-",children:"Passed all unit tests \ud83e\udd73"}),"\n",(0,i.jsx)("img",{src:s(8994).A,alt:"TinyORM - Passed all unit tests - Showcase",title:"Passed all unit tests",width:"700",className:"no-blurry"}),"\n",(0,i.jsx)(n.h4,{id:"tinyormplayground",children:"TinyOrmPlayground"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.a,{href:"https://github.com/silverqx/TinyOrmPlayground",children:"TinyOrmPlayground"})," project is my personal project where I have tested all the TinyORM database queries in the early development phases, currently, it executes ~1600 database queries across the whole TinyORM framework. Every query has a nice title header, is logged to the console, and is counted and measured (elapsed time). Every query also runs on all ",(0,i.jsx)(n.a,{href:"/database/getting-started#introduction",children:"Supported Databases"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The TinyOrmPlayground project can be compiled in a single-threaded or multi-threaded mode. In the multi-threaded mode, every database connection runs in its own thread. The connection summary is logged at the end of every database connection and the application summary is logged before an exit. Whole TinyOrmPlayground application is configurable through the ",(0,i.jsx)(n.a,{href:"https://github.com/silverqx/TinyOrmPlayground/blob/main/src/configuration.hpp",children:"src/configuration.hpp"})," class."]}),"\n",(0,i.jsx)(n.h6,{id:"tinyormplayground-single-threaded",children:"TinyOrmPlayground single-threaded"}),"\n",(0,i.jsx)("img",{src:s(3672).A,alt:"TinyORM - Invoked TinyOrmPlayground single-threaded - Showcase",title:"Invoked TinyOrmPlayground single-threaded"}),"\n",(0,i.jsx)(n.h6,{id:"tinyormplayground-multi-threaded",children:"TinyOrmPlayground multi-threaded"}),"\n",(0,i.jsx)("img",{src:s(2599).A,alt:"TinyORM - Invoked TinyOrmPlayground multi-threaded - Showcase",title:"Invoked TinyOrmPlayground multi-threaded"})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8994:(e,n,s)=>{s.d(n,{A:()=>i});const i=s.p+"assets/images/tinyorm-passed_all_unit_tests-d730d995b6b490fb42c3671738e3b81e.png"},2599:(e,n,s)=>{s.d(n,{A:()=>i});const i=s.p+"assets/images/tinyormplayground-multi-threaded-edb67030c75e2845e1fa7013e510174c.png"},3672:(e,n,s)=>{s.d(n,{A:()=>i});const i=s.p+"assets/images/tinyormplayground-single-threaded-4e7a5769ad5a768a4d04c6dc856c4391.png"},5848:(e,n,s)=>{s.d(n,{A:()=>i});const i=s.p+"assets/images/tom_cli-402f7dd4dfe7dbd0b20dfe5fb61838a2.png"},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>l});var i=s(6540);const t={},r=i.createContext(t);function a(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/fb313d4e.d61d160a.js b/assets/js/fb313d4e.d61d160a.js
deleted file mode 100644
index c7940ca5e..000000000
--- a/assets/js/fb313d4e.d61d160a.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunktinyorm_org=self.webpackChunktinyorm_org||[]).push([[871],{8489:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var t=s(4848),i=s(8453);const r={sidebar_position:8,sidebar_label:"\ud83d\udcc4 Features Summary",hide_table_of_contents:!0,description:"List that fastly summarizes all TinyORM features.",keywords:["c++ orm","tinyorm","features","summary","features summary"]},a="Features Summary",l={id:"features-summary",title:"Features Summary",description:"List that fastly summarizes all TinyORM features.",source:"@site/docs/features-summary.mdx",sourceDirName:".",slug:"/features-summary",permalink:"/features-summary",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:8,frontMatter:{sidebar_position:8,sidebar_label:"\ud83d\udcc4 Features Summary",hide_table_of_contents:!0,description:"List that fastly summarizes all TinyORM features.",keywords:["c++ orm","tinyorm","features","summary","features summary"]},sidebar:"tinyormSidebar",previous:{title:"\ud83d\udea9 Stability",permalink:"/stability"},next:{title:"\u2764\ufe0f Sponsors",permalink:"/sponsors"}},o={},d=[{value:"Summary List",id:"summary-list",level:2},{value:"Showcase Images",id:"showcase-images",level:2},{value:"Tom console application",id:"tom-console-application",level:6},{value:"Passed all unit tests \ud83e\udd73",id:"passed-all-unit-tests-",level:6},{value:"TinyOrmPlayground",id:"tinyormplayground",level:4},{value:"TinyOrmPlayground single-threaded",id:"tinyormplayground-single-threaded",level:6},{value:"TinyOrmPlayground multi-threaded",id:"tinyormplayground-multi-threaded",level:6}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h4:"h4",h6:"h6",header:"header",li:"li",p:"p",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"features-summary",children:"Features Summary"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"#summary-list",children:"Summary List"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"#showcase-images",children:"Showcase Images"})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"summary-list",children:"Summary List"}),"\n",(0,t.jsxs)(n.p,{children:["The following list fastly summarizes all the ",(0,t.jsx)(n.code,{children:"TinyORM"})," features."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"simple database connections management"})," \ud83e\uddec","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"database manager that helps with the database connections management"}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Orm::DB"})," facade class for nicer and shorter syntax"]}),"\n",(0,t.jsxs)(n.li,{children:["MySQL, MariaDB, SQLite, and PostgreSQL support for ",(0,t.jsx)(n.strong,{children:"all"})," features \ud83d\udc8e"]}),"\n",(0,t.jsx)(n.li,{children:"multi-threading support \ud83d\udc40"}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"SSL"})," connections support \ud83d\udd12"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"impressive query builder"})," \ud83d\udd27","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"allows passing sub-queries and raw expressions practically everywhere, to column names, values, and to every SQL clause as select, where, joins, group by, having, order by \ud83d\udd25"}),"\n",(0,t.jsx)(n.li,{children:"a logical grouping that offers to wrap logical groups in parenthesis"}),"\n",(0,t.jsx)(n.li,{children:"chunked results for lower memory footprint \u2728"}),"\n",(0,t.jsx)(n.li,{children:"raw methods for all SQL clauses"}),"\n",(0,t.jsx)(n.li,{children:"all join types (left, right, cross, inner) and also join where clause support \ud83e\udee4"}),"\n",(0,t.jsx)(n.li,{children:"aggregate methods min, max, sum, increment, decrement, ..."}),"\n",(0,t.jsx)(n.li,{children:"whereExists and exists methods for an existence queries"}),"\n",(0,t.jsx)(n.li,{children:"transactions and pessimistic locking \ud83d\udd12"}),"\n",(0,t.jsx)(n.li,{children:"of course, insert, update, and delete SQL clauses support"}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"correct QDateTime time zone"})," using the ",(0,t.jsx)(n.code,{children:"qt_timezone"})," connection configuration option \ud83d\udcc5 (returned QDateTime instances will have the correct time zone, and also works for an ORM)","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"this feature allows you to set up the database server time zone to the UTC and all returned QDateTime instances will have the correct UTC time zone"}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"clever ORM with all relation types support"})," \ud83c\udf89","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"one-to-one, one-to-many, and many-to-many relation types (also inverse relationships) \ud83e\udde8"}),"\n",(0,t.jsx)(n.li,{children:"eager and lazy loading with custom select and constraints \ud83d\ude80"}),"\n",(0,t.jsxs)(n.li,{children:["fluent ",(0,t.jsx)(n.code,{children:"ModelsCollection"})," that expose a variety of map / reduce operations that may be chained using an intuitive interface \u2728"]}),"\n",(0,t.jsx)(n.li,{children:"all query builder methods are proxied from the model instances and also from the relation instances back to the query builder \ud83e\udd2f (everything that can be called on the query builder can also be called on the model and relation instances)"}),"\n",(0,t.jsx)(n.li,{children:"clean active record pattern"}),"\n",(0,t.jsxs)(n.li,{children:["advanced features like timestamps, touching parent timestamps, ",(0,t.jsx)(n.strong,{children:"soft deleting"}),", default models, default model attributes, and attribute casting \ud83e\udd13"]}),"\n",(0,t.jsxs)(n.li,{children:["querying relationships existence/absence using the has, whereHas, and hasNested methods (using dot notation for selecting nested relationships ",(0,t.jsx)(n.em,{children:"users.posts.comments"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"serializing"})," models and collection of models including all nested relations to ",(0,t.jsx)(n.strong,{children:"JSON"})," and converting to vectors and maps \ud83e\udea1","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"supports controlling a custom date format during serialization"}),"\n",(0,t.jsx)(n.li,{children:"supports hiding and appending attributes"}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"compiled database migrations and seeders"})," \ud83d\udd7a","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"create, update, drop, and rename database tables"}),"\n",(0,t.jsx)(n.li,{children:"create, drop, and rename table columns"}),"\n",(0,t.jsx)(n.li,{children:"extensive schema builder that allows creating of all possible column types"}),"\n",(0,t.jsx)(n.li,{children:"terser syntax for creating foreign keys and foreign key constraints"}),"\n",(0,t.jsx)(n.li,{children:"supports creating, and dropping column indexes (primary, unique, fulltext, spatial)"}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsxs)(n.strong,{children:["the ",(0,t.jsx)(n.code,{children:"tom"})," console application with tab completion for all shells (pwsh, bash, zsh)"]})," \ud83e\udd73","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"scaffolding of models, migrations, and seeders"}),"\n",(0,t.jsxs)(n.li,{children:["impressive models scaffolding, every feature that is supported by models can be generated using the ",(0,t.jsx)(n.code,{children:"tom make:model"})," cli command"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["a huge amount of code is unit tested, currently ",(0,t.jsx)(n.strong,{children:"3378 unit tests"})," \ud83e\udd2f"]}),"\n",(0,t.jsxs)(n.li,{children:["C++20 only, with all the latest features used like concepts/constraints, ranges, smart pointers (no ",(0,t.jsx)(n.code,{children:"new"})," keyword in the whole code \ud83d\ude0e), folding expressions"]}),"\n",(0,t.jsxs)(n.li,{children:["qmake and CMake build systems support","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"CMake FetchContent module support \ud83e\udd19"}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.li,{children:"vcpkg support (also the vcpkg port, currently not committed to the vcpkg repository \u2639\ufe0f)"}),"\n",(0,t.jsx)(n.li,{children:"it's really fast, you can run 1000 complex queries in 500ms (heavily DB dependant, the PostgreSQL is by far the fastest) \u231a"}),"\n",(0,t.jsx)(n.li,{children:"extensive documentation \ud83d\udcc3"}),"\n",(0,t.jsx)(n.li,{children:"..."}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["See the ",(0,t.jsx)(n.code,{children:"TinyDrivers"})," ",(0,t.jsx)(n.a,{href:"tinydrivers/getting-started#features-summary",children:"Features summary"}),"."]})}),"\n",(0,t.jsx)(n.h2,{id:"showcase-images",children:"Showcase Images"}),"\n",(0,t.jsx)(n.h6,{id:"tom-console-application",children:"Tom console application"}),"\n",(0,t.jsx)("img",{src:s(5848).A,alt:"TinyORM - Tom console application - Showcase",title:"Tom console application"}),"\n",(0,t.jsx)(n.h6,{id:"passed-all-unit-tests-",children:"Passed all unit tests \ud83e\udd73"}),"\n",(0,t.jsx)("img",{src:s(8994).A,alt:"TinyORM - Passed all unit tests - Showcase",title:"Passed all unit tests",width:"700",className:"no-blurry"}),"\n",(0,t.jsx)(n.h4,{id:"tinyormplayground",children:"TinyOrmPlayground"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.a,{href:"https://github.com/silverqx/TinyOrmPlayground",children:"TinyOrmPlayground"})," project is my personal project where I have tested all the TinyORM database queries in the early development phases, currently, it executes ~1600 database queries across the whole TinyORM framework. Every query has a nice title header, is logged to the console, and is counted and measured (elapsed time). Every query also runs on all ",(0,t.jsx)(n.a,{href:"/database/getting-started#introduction",children:"supported databases"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["The TinyOrmPlayground project can be compiled in a single-threaded or multi-threaded mode. In the multi-threaded mode, every database connection runs in its own thread. At the end of every database connection is logged a connection summary and before an exit is logged the application summary. Whole TinyOrmPlayground application is configurable through the ",(0,t.jsx)(n.a,{href:"https://github.com/silverqx/TinyOrmPlayground/blob/main/src/configuration.hpp",children:"src/configuration.hpp"})," class."]}),"\n",(0,t.jsx)(n.h6,{id:"tinyormplayground-single-threaded",children:"TinyOrmPlayground single-threaded"}),"\n",(0,t.jsx)("img",{src:s(3672).A,alt:"TinyORM - Invoked TinyOrmPlayground single-threaded - Showcase",title:"Invoked TinyOrmPlayground single-threaded"}),"\n",(0,t.jsx)(n.h6,{id:"tinyormplayground-multi-threaded",children:"TinyOrmPlayground multi-threaded"}),"\n",(0,t.jsx)("img",{src:s(2599).A,alt:"TinyORM - Invoked TinyOrmPlayground multi-threaded - Showcase",title:"Invoked TinyOrmPlayground multi-threaded"})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8994:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/tinyorm-passed_all_unit_tests-d730d995b6b490fb42c3671738e3b81e.png"},2599:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/tinyormplayground-multi-threaded-edb67030c75e2845e1fa7013e510174c.png"},3672:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/tinyormplayground-single-threaded-4e7a5769ad5a768a4d04c6dc856c4391.png"},5848:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/tom_cli-402f7dd4dfe7dbd0b20dfe5fb61838a2.png"},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>l});var t=s(6540);const i={},r=t.createContext(i);function a(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/main.625349cf.js b/assets/js/main.625349cf.js
new file mode 100644
index 000000000..e21748287
--- /dev/null
+++ b/assets/js/main.625349cf.js
@@ -0,0 +1,2 @@
+/*! For license information please see main.625349cf.js.LICENSE.txt */
+(self.webpackChunktinyorm_org=self.webpackChunktinyorm_org||[]).push([[792],{3219:(e,t,n)=>{"use strict";n.d(t,{Bc:()=>g,E8:()=>Hn,a1:()=>$n});var r=n(6540);n(961);function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;tYour Docusaurus site did not load properly.
\nA very common reason is a wrong site baseUrl configuration.
\nCurrent configured baseUrl = ${e} ${"/"===e?" (default value)":""}
\nWe suggest trying baseUrl =
\n