drivers get rid of passing weak_ptr<SqlDriver> 🙌

Used the std::enable_shared_from_this<MySqlDriver> base class to avoid
passing the weak_ptr<SqlDriver> all around. It greatly simplified
the code and also the logic is more correct.

It also allowed to remove the SqlDatabase::driverWeak() non-const
version which was dedicated exactly for this, to be able to pass it
to methods that needed it, no more needed now.
This commit is contained in:
silverqx
2024-07-28 00:25:30 +02:00
parent 189e80465e
commit 3518d9f316
9 changed files with 28 additions and 73 deletions
@@ -37,9 +37,7 @@ namespace Concerns
/* Others */
/*! Select all columns in the given table with LIMIT 0 (used by record()). */
SqlQuery
selectAllColumnsWithLimit0(const QString &table,
const std::weak_ptr<SqlDriver> &driver) const;
SqlQuery selectAllColumnsWithLimit0(const QString &table) const;
private:
/* Others */
@@ -125,8 +125,6 @@ namespace Orm::Drivers
const SqlDriver *driver() const noexcept;
/*! Get the SQL database driver used to access the database connection (const). */
std::weak_ptr<const SqlDriver> driverWeak() const noexcept;
/*! Get the SQL database driver used to access the database connection. */
std::weak_ptr<SqlDriver> driverWeak() noexcept;
/*! Determine if the same thread check during the database() call is enabled. */
static bool isThreadCheckEnabled() noexcept;
@@ -175,16 +175,12 @@ namespace Orm::Drivers
IdentifierType type) const;
/*! Factory method to create an empty database result. */
virtual std::unique_ptr<SqlResult>
createResult(const std::weak_ptr<SqlDriver> &driver) const = 0;
virtual std::unique_ptr<SqlResult> createResult() const = 0;
/*! Get a SqlRecord containing the field information for the given table. */
virtual SqlRecord
record(const QString &table, const std::weak_ptr<SqlDriver> &driver) const = 0;
virtual SqlRecord record(const QString &table) const = 0;
/*! Get a SqlRecord containing the field information for the given table. */
virtual SqlRecord
recordWithDefaultValues(const QString &table,
const std::weak_ptr<SqlDriver> &driver) const = 0;
virtual SqlRecord recordWithDefaultValues(const QString &table) const = 0;
protected:
/* Setters */
@@ -19,12 +19,11 @@ namespace Orm::Drivers::Concerns
/* public */
SqlQuery
SelectsAllColumnsWithLimit0::selectAllColumnsWithLimit0(
const QString &table, const std::weak_ptr<SqlDriver> &driver) const
SelectsAllColumnsWithLimit0::selectAllColumnsWithLimit0(const QString &table) const
{
const auto &sqlDriver = this->sqlDriver();
SqlQuery query(sqlDriver.createResult(driver));
SqlQuery query(sqlDriver.createResult());
/* Don't check if a table exists in the currently selected database because
it doesn't make sense, leave the defaults on the database server.
+2 -14
View File
@@ -284,18 +284,6 @@ std::weak_ptr<const SqlDriver> SqlDatabase::driverWeak() const noexcept
return d->sqldriver;
}
/* The reason why the driverWeak() non-const method is exposed only here and isn't also
exposed in the Drivers::SqlQuery/SqlResult is to be able to instantiate the SqlQuery
manually like this:
const auto driver = SqlDatabase::database(Databases::MYSQL).driverWeak();
SqlQuery query(driver.lock()->createResult(driver));
*/
std::weak_ptr<SqlDriver> SqlDatabase::driverWeak() noexcept
{
return d->sqldriver;
}
bool SqlDatabase::isThreadCheckEnabled() noexcept
{
return SqlDatabasePrivate::checkSameThread();
@@ -358,9 +346,9 @@ SqlRecord SqlDatabase::record(const QString &table, const bool withDefaultValues
This method will contain field information for ALL columns for the given table,
but of course without the field values. */
if (withDefaultValues)
return d->driver().recordWithDefaultValues(table, d->sqldriver);
return d->driver().recordWithDefaultValues(table);
return d->driver().record(table, d->sqldriver);
return d->driver().record(table);
}
/* private */
@@ -15,9 +15,7 @@ namespace Orm::Drivers
SqlResultPrivate::SqlResultPrivate(const std::weak_ptr<SqlDriver> &driver) noexcept
: sqldriver(driver)
{
/* The sqldriver must always be valid during construction, I'm leaving this check
here even there is another check in the MySqlDriver::createResult() because
the MySqlResult can still be instantiated manually. */
// The sqldriver must always be valid/alive during instantiation
Q_ASSERT(!sqldriver.expired());
// Ownership of the shared_ptr()
@@ -15,7 +15,9 @@ namespace Orm::Drivers::MySql
class MySqlDriverPrivate;
/*! MySQL database driver. */
class TINYDRIVERS_EXPORT MySqlDriver final : public SqlDriver
class TINYDRIVERS_EXPORT MySqlDriver final :
public SqlDriver,
public std::enable_shared_from_this<MySqlDriver>
{
Q_DISABLE_COPY_MOVE(MySqlDriver)
Q_DECLARE_PRIVATE(MySqlDriver) // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
@@ -71,16 +73,12 @@ namespace Orm::Drivers::MySql
IdentifierType type) const final;
/*! Factory method to create an empty MySQL result. */
std::unique_ptr<SqlResult>
createResult(const std::weak_ptr<SqlDriver> &driver) const final;
std::unique_ptr<SqlResult> createResult() const final;
/*! Get a SqlRecord containing the field information for the given table. */
SqlRecord record(const QString &table,
const std::weak_ptr<SqlDriver> &driver) const final;
SqlRecord record(const QString &table) const final;
/*! Get a SqlRecord containing the field information for the given table. */
SqlRecord
recordWithDefaultValues(const QString &table,
const std::weak_ptr<SqlDriver> &driver) const final;
SqlRecord recordWithDefaultValues(const QString &table) const final;
};
/* public */
@@ -38,7 +38,7 @@ void PopulatesFieldDefaultValuesPrivate::populateFieldDefaultValuesInternal(
// Ownership of the shared_ptr()
const auto driver = sqldriver.lock();
SqlQuery sqlQuery(driver->createResult(sqldriver));
SqlQuery sqlQuery(driver->createResult());
// Prepare the query string and field names based on the allColumns
const auto [queryString, fieldNames] = prepareQueryStringAndFieldNames(
@@ -1,8 +1,6 @@
#include "orm/drivers/mysql/mysqldriver.hpp"
#include <orm/macros/likely.hpp>
#include "orm/drivers/exceptions/invalidargumenterror.hpp"
#include "orm/drivers/exceptions/logicerror.hpp"
#include "orm/drivers/exceptions/sqltransactionerror.hpp"
#include "orm/drivers/mysql/mysqlconstants_p.hpp"
#include "orm/drivers/mysql/mysqldriver_p.hpp"
@@ -223,42 +221,24 @@ bool MySqlDriver::isIdentifierEscaped(const QString &identifier,
identifier.endsWith(BACKTICK);
}
std::unique_ptr<SqlResult>
MySqlDriver::createResult(const std::weak_ptr<SqlDriver> &driver) const
std::unique_ptr<SqlResult> MySqlDriver::createResult() const
{
if (const auto driverShared = driver.lock(); driverShared) T_LIKELY
/* We need to upcast here, there is no other way, it also has to be
std::weak_ptr(), it can't be done better. This upcast is kind of check,
we can't pass down the SqlDriver to the MySqlResult.
Even if it would be the shared_ptr<SqlDriver> we had to upcast the same way.
Revisited, also, all driver data members like host, port, username, ..., and
also connectionName will be still the same, it only creates an empty result
set. I'm noting this because of SqlQuery::clear() as it was confusing that
all these data members stay unchanged, but it's correct. */
return std::make_unique<MySqlResult>(
std::dynamic_pointer_cast<MySqlDriver>(driverShared));
else T_UNLIKELY {
Q_D(const MySqlDriver);
throw Exceptions::InvalidArgumentError(
u"The 'driver' argument can't be nullptr, it can't be expired, "
"for '%1' MySQL database connection in %2()."_s
.arg(d->connectionName, __tiny_func__));
}
/* We must use the const_cast<> as the weak_from_this() return type is controlled
by the current method const-nes, what means it's only our implementation detail
as we can't control this. Also, it's better to have the same const-nes as
in the QtSql. */
return std::make_unique<MySqlResult>(
const_cast<MySqlDriver &>(*this).weak_from_this()); // NOLINT(cppcoreguidelines-pro-type-const-cast)
}
SqlRecord
MySqlDriver::record(const QString &table, const std::weak_ptr<SqlDriver> &driver) const
SqlRecord MySqlDriver::record(const QString &table) const
{
return selectAllColumnsWithLimit0(table, driver).record(false);
return selectAllColumnsWithLimit0(table).record(false);
}
SqlRecord
MySqlDriver::recordWithDefaultValues(const QString &table,
const std::weak_ptr<SqlDriver> &driver) const
SqlRecord MySqlDriver::recordWithDefaultValues(const QString &table) const
{
return selectAllColumnsWithLimit0(table, driver).recordAllColumns(true);
return selectAllColumnsWithLimit0(table).recordAllColumns(true);
}
} // namespace Orm::Drivers::MySql