Files
TinyORM/docs/tinydrivers/getting-started.mdx
2024-08-26 13:23:05 +02:00

145 lines
9.1 KiB
Plaintext

---
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]
---
import Link from '@docusaurus/Link'
# TinyDrivers: Getting Started
- [Introduction](#introduction)
- [Features summary](#features-summary)
- [Differences from QtSql](#differences-from-qtsql)
- [Build system](#build-system)
- [Performance](#performance)
- [Internals](#internals)
## Introduction
<div className="api-stability alert alert--success">
<Link to='/stability#stability-indexes'>__Stability: 2__</Link> - Stable
</div>
The `TinyDrivers` library is an underlying SQL database layer for `TinyORM`. It can be used instead of the `QtSql` module, can be <u>__swapped__</u> 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.
#### Features summary
- both, normal and prepared statements are supported
- TLS/SSL connections using [`MYSQL_OPT_SSL_MODE`](https://dev.mysql.com/doc/c-api/9.0/en/mysql-options.html) (verify_ca, verify_identity) 🔥
- setting many other MySQL connection options (see [`mysqldriver_p.cpp`](https://github.com/silverqx/TinyORM/blob/main/drivers/mysql/src/orm/drivers/mysql/mysqldriver_p.cpp))
- building and linking against the [`MariaDB Connector/C`](https://mariadb.com/kb/en/mariadb-connector-c/) 🕺
- transactions
- re-using the current `SqlQuery` instance to re-execute the same or another SQL query
- detaching from the result set (related to freeing/releasing memory)
- query size, number of affected rows, last inserted ID, testing `isNull()`, ...
- all __3378 unit tests__ passed 😮
- strictly using __smart pointers__ (no `new` keyword in the whole `TinyDrivers` code base 😎)
- clear code 🤔
:::info
Currently, only the `MySQL` database driver is supported and finished. 😞
:::
:::tip
All database drivers described in the [Database](database/getting-started.mdx#introduction) documentation are supported when linking against the [`QtSql`](https://doc.qt.io/qt/qtsql-index.html) module.
:::
:::note
`TinyDrivers` library supports both build systems `qmake` and also `CMake`.
:::
## Differences from QtSql
`TinyDrivers` doesn't return errors the the same way as the `QtSql` module, which means return a `bool` and if it's the result `false` then obtain the `SqlError` instance using the `lastError()` method from `SqlDatabase` or `SqlQuery` instances. Instead, it throws exceptions, and methods returning a `bool` type to report an error state always return `true`.
##### Naming conventions
- `QtSql` <small>module</small> -> `TinyDrivers` <small>library</small>
- `QMYSQL` <small>driver</small> -> `TinyMySql` <small>driver</small>
##### MySQL driver
The following describes the differences between `QMYSQL` and `TinyMySql` drivers.
The `QMYSQL` driver doesn't support setting `MySQL` non-flag [connection options](https://dev.mysql.com/doc/c-api/9.0/en/mysql-options.html) like `MYSQL_OPT_RECONNECT` without the value, it needs to be defined with value like `=1` or `=TRUE` (case-sensitive), only real flag options like `CLIENT_INTERACTIVE` can be set without the value and `=` character.
On the other hand, the `TinyMySql` driver allows setting non-flag [connection options](https://dev.mysql.com/doc/c-api/9.0/en/mysql-options.html) options without the value and `=` character, which are considered enabled (ON or TRUE).
##### Removed features
Simulation of prepared statements while calling `SqlQuery::exec(QString)`, this functionality is useless because you can call regular prepared statements using `SqlQuery::prepare(QString)` and then `SqlQuery::exec()`.
##### Missing features
Fetching multiple result sets using `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.
### Build system
Another difference is that you can build the `TinyDrivers` and its SQL drivers (`TinyMySql`) in 3 different ways; `Shared`, `Static`, and as a `Loadable` library at runtime using `LoadLibrary()` on Windows or `dlopen()` on Linux.
##### The `Shared` library build
It builds two shared libraries, the `TinyDrivers` shared library that contains the core/common code and the `TinyMySql` shared library that contains `MySQL` implementation. The `TinyOrm` links only against the `TinyDrivers` shared library and `TinyMySql` is a private implementation.
##### The `Static` build
It builds one `TinyDrivers` static archive that contains the core/common code and SQL drivers (`TinyMySql`). This static library is linked or merged into the `TinyOrm` shared or static library (both variants are supported).
##### The `Loadable` SQL drivers build
It builds two shared libraries, the `TinyDrivers` shared library that contains the core/common code and `TinyMySql` shared library (module) that contains `MySQL` implementation that is loaded at runtime using `LoadLibrary()` on Windows or `dlopen()` on Linux. The SQL driver library loader throws an exception if it cannot find this library at runtime.
:::info
The `TinyMySql` links directly against the `MySQL C connector` (`libmysql` or `mysqlclient` library).
:::
#### `CMake`/`qmake` build options
##### For `CMake`
See [CMake build options](building/tinyorm.mdx#cmake-build-options), related `CMake` build options are:<br/>[`BUILD_DRIVERS`](building/tinyorm.mdx#BUILD_DRIVERS), [`BUILD_MYSQL_DRIVER`](building/tinyorm.mdx#BUILD_MYSQL_DRIVER), and [`DRIVERS_TYPE`](building/tinyorm.mdx#DRIVERS_TYPE)
To control shared and static build use [`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html) `CMake` configuration option.
##### For `qmake`
See [qmake build options](building/tinyorm.mdx#qmake-build-options), related `qmake` configuration options are:<br/>[`build_loadable_drivers`](building/tinyorm.mdx#build_loadable_drivers), [`build_mysql_driver`](building/tinyorm.mdx#build_mysql_driver), [`build_shared_drivers`](building/tinyorm.mdx#build_shared_drivers), and [`build_static_drivers`](building/tinyorm.mdx#build_static_drivers)
To control shared and static build use [`static`](building/tinyorm.mdx#qmake-static) `qmake` [configuration option](https://doc.qt.io/qt/qmake-variable-reference.html#config).
### Performance
Performance is several milliseconds faster compared to `QtSql` with the `QMYSQL` driver. It was tuned using the `KCacheGrind` to be so. It's ~40ms faster on [`TinyOrmPlayground`](https://github.com/silverqx/TinyOrmPlayground) project with __620__ database queries compiled using `GCC v13.2.1` Debug build on Linux. Similar results can be expected on other platforms but it's not guaranteed.
This means performance is very similar to `QtSql`. There is not much to speed up because `TinyDrivers` code is swift and 90% of the time is spent inside the [`MySQL C API`](https://dev.mysql.com/doc/c-api/9.0/en/) because we always have to wait for the database server, especially when creating database connections using eg. [`mysql_real_connect()`](https://dev.mysql.com/doc/c-api/9.0/en/mysql-real-connect.html) (this function is king among the slowest functions 😎, which is understandable of course).
## Internals
`TinyDrivers` internal design can be divided into 3 different layers:
- Driver layer
- SQL API layer
- Public API layer
The Driver layer is eg. `TinyMySql` library which is responsible for communicating with the underlying database driver (eg. [`MySQL C API`](https://dev.mysql.com/doc/c-api/9.0/en/)).
The SQL API layer is a semi-layer that glues everything up and sits between the Public interface API and the Driver layer.
The Public interface API layer are the end classes like `SqlDatabase` and `SqlQuery` which are exposed to the end user.
##### SqlDatabase
One more thing worth mentioning is the `SqlDatabase` API. It's one class that has two responsibilities! All static methods act as the database connection manager and an instance of the `SqlDatabase` represents a physical database connection. It's not a good design because it breaks the [Single Responsibility principle](https://en.wikipedia.org/wiki/Single_responsibility_principle), but it's what it is.
##### Namespaces
`TinyDrivers` classes are defined in the `Orm::Drivers` namespace and `TinyMySql` classes in the `Orm::Drivers::MySql` namespace.
##### Documentation
For all other APIs you can follow the [QtSql documentation](https://doc.qt.io/qt/qtsql-index.html) as the API is 1:1. The exception is of course the build system, `TinyOrm` has its own build system that doesn't follow the `QtSql` module.