added support for table prefixes

- also added tests
This commit is contained in:
silverqx
2021-05-28 18:23:05 +02:00
parent 0236cc47bb
commit 84e456060b
12 changed files with 217 additions and 41 deletions
+10 -5
View File
@@ -59,6 +59,11 @@ namespace Query
/*! Get the value of a raw expression. */
QVariant getValue(const Expression &expression) const;
/*! Get the grammar's table prefix. */
QString getTablePrefix() const;
/*! Set the grammar's table prefix. */
BaseGrammar &setTablePrefix(const QString &prefix);
protected:
/*! Convert the vector of column names into a delimited string. */
QString columnize(const QStringList &columns) const;
@@ -68,11 +73,6 @@ namespace Query
/*! Get the appropriate query parameter place-holder for a value. */
QString parameter(const QVariant &value) const;
/*! Get the grammar's table prefix. */
QString getTablePrefix() const;
/*! Set the grammar's table prefix. */
BaseGrammar &setTablePrefix(const QString &prefix);
/*! Wrap a value that has an alias. */
QString wrapAliasedValue(const QString &value, bool prefixAlias = false) const;
/*! Wrap a single string in keyword identifiers. */
@@ -94,6 +94,11 @@ namespace Query
QString m_tablePrefix = "";
};
inline QString BaseGrammar::getTablePrefix() const
{
return m_tablePrefix;
}
template<QStringContainer T>
T BaseGrammar::wrapArray(T values) const
{
+8
View File
@@ -16,6 +16,7 @@ namespace TINYORM_COMMON_NAMESPACE
namespace Orm
{
class BaseGrammar;
class DatabaseConnection;
namespace Query
@@ -228,6 +229,13 @@ namespace Grammars
virtual void recordsHaveBeenModified(bool value = true) = 0;
/*! Reset the record modification state. */
virtual void forgetRecordModificationState() = 0;
/*! Get the table prefix for the connection. */
virtual QString getTablePrefix() const = 0;
/*! Set the table prefix in use by the connection. */
virtual DatabaseConnection &setTablePrefix(const QString &prefix) = 0;
/*! Set the table prefix and return the query grammar. */
virtual BaseGrammar &withTablePrefix(BaseGrammar &grammar) const = 0;
};
} // namespace Orm
+44 -11
View File
@@ -23,6 +23,7 @@ namespace TINYORM_COMMON_NAMESPACE
namespace Orm
{
// CUR return DatabaseConnection vs ConnectionInterface silverqx
class SHAREDLIB_EXPORT DatabaseConnection :
public ConnectionInterface,
public Concerns::DetectsLostConnections
@@ -43,13 +44,19 @@ namespace Orm
QSharedPointer<QueryBuilder>
table(const QString &table, const QString &as = "") override;
/*! Get the table prefix for the connection. */
QString getTablePrefix() const override;
/*! Set the table prefix in use by the connection. */
DatabaseConnection &setTablePrefix(const QString &prefix) override;
/*! Set the table prefix and return the query grammar. */
BaseGrammar &withTablePrefix(BaseGrammar &grammar) const override;
/*! Get a new query builder instance. */
QSharedPointer<QueryBuilder> query() override;
// FEATURE dilemma Raw Expressions fuckup🤔 silverqx
/*! Get a new raw query expression. */
inline Query::Expression raw(const QVariant &value) const override
{ return value; }
Query::Expression raw(const QVariant &value) const override;
// TODO next transaction method with callback silverqx
/*! Start a new database transaction. */
@@ -67,8 +74,7 @@ namespace Orm
/*! Rollback to a named transaction savepoint. */
bool rollbackToSavepoint(size_t id) override;
/*! Get the number of active transactions. */
inline uint transactionLevel() const override
{ return m_savepoints; }
uint transactionLevel() const override;
/*! Run a select statement against the database. */
QSqlQuery
@@ -109,9 +115,8 @@ namespace Orm
/*! Get underlying database connection without executing any reconnect logic. */
QSqlDatabase getRawQtConnection() const;
/*! Get the connection resolver for an underlying database connection. */
inline const std::function<Connectors::ConnectionName()> &
getQtConnectionResolver() const
{ return m_qtConnectionResolver; }
const std::function<Connectors::ConnectionName()> &
getQtConnectionResolver() const;
/*! Set the connection resolver for an underlying database connection. */
DatabaseConnection &setQtConnectionResolver(
const std::function<Connectors::ConnectionName()> &resolver);
@@ -137,8 +142,7 @@ namespace Orm
/*! Get the database connection name. */
const QString &getName() const override;
/*! Get the name of the connected database. */
inline const QString &getDatabaseName() const override
{ return m_database; }
const QString &getDatabaseName() const override;
/*! Set the query grammar to the default implementation. */
void useDefaultQueryGrammar() override;
@@ -293,9 +297,8 @@ namespace Orm
std::function<Connectors::ConnectionName()> m_qtConnectionResolver;
/*! The name of the connected database. */
const QString m_database;
// FEATURE table prefix silverqx
/*! The table prefix for the connection. */
const QString m_tablePrefix {""};
QString m_tablePrefix;
/*! The database connection configuration options. */
const QVariantHash m_config;
/*! The reconnector instance for the connection. */
@@ -359,6 +362,9 @@ namespace Orm
QVariantMap
convertPositionalToNamedBindings(const QVector<QVariant> &bindings) const;
/*! Get the query grammar used by the connection. */
QueryGrammar &getQueryGrammar();
/*! The flag for the database was disconnected. */
bool m_disconnectedLogged = false;
/*! The flag for the database was connected. */
@@ -387,11 +393,38 @@ namespace Orm
};
// TODO inline functions, do it like below silverqx
inline QString DatabaseConnection::getTablePrefix() const
{
return m_tablePrefix;
}
inline Query::Expression
DatabaseConnection::raw(const QVariant &value) const
{
return value;
}
inline uint DatabaseConnection::transactionLevel() const
{
return m_savepoints;
}
inline const std::function<Connectors::ConnectionName()> &
DatabaseConnection::getQtConnectionResolver() const
{
return m_qtConnectionResolver;
}
inline const QString &DatabaseConnection::getName() const
{
return m_connectionName;
}
inline const QString &DatabaseConnection::getDatabaseName() const
{
return m_database;
}
inline std::shared_ptr<QVector<Log>>
DatabaseConnection::getQueryLog() const
{
-1
View File
@@ -372,7 +372,6 @@ namespace Relations
: m_query(query)
, m_model(model)
{
// FEATURE table prefix, check for 'as'? silverqx
m_query->from(m_model.getTable());
}
+7 -12
View File
@@ -65,6 +65,13 @@ QVariant BaseGrammar::getValue(const Expression &expression) const
return expression.getValue();
}
BaseGrammar &BaseGrammar::setTablePrefix(const QString &prefix)
{
m_tablePrefix = prefix;
return *this;
}
QString BaseGrammar::columnize(const QStringList &columns) const
{
return wrapArray(columns).join(", ");
@@ -78,18 +85,6 @@ QString BaseGrammar::parameter(const QVariant &value) const
: QStringLiteral("?");
}
QString BaseGrammar::getTablePrefix() const
{
return m_tablePrefix;
}
BaseGrammar &BaseGrammar::setTablePrefix(const QString &prefix)
{
m_tablePrefix = prefix;
return *this;
}
QString BaseGrammar::wrapAliasedValue(const QString &value, const bool prefixAlias) const
{
auto segments = getSegmentsFromFrom(value);
+21
View File
@@ -60,6 +60,22 @@ DatabaseConnection::table(const QString &table, const QString &as)
return builder;
}
DatabaseConnection &DatabaseConnection::setTablePrefix(const QString &prefix)
{
m_tablePrefix = prefix;
getQueryGrammar().setTablePrefix(prefix);
return *this;
}
BaseGrammar &DatabaseConnection::withTablePrefix(BaseGrammar &grammar) const
{
grammar.setTablePrefix(m_tablePrefix);
return grammar;
}
QSharedPointer<QueryBuilder> DatabaseConnection::query()
{
return QSharedPointer<QueryBuilder>::create(*this, *m_queryGrammar);
@@ -979,6 +995,11 @@ DatabaseConnection::convertPositionalToNamedBindings(
return result;
}
QueryGrammar &DatabaseConnection::getQueryGrammar()
{
return *m_queryGrammar;
}
} // namespace Orm
#ifdef TINYORM_COMMON_NAMESPACE
} // namespace TINYORM_COMMON_NAMESPACE
+12 -4
View File
@@ -114,14 +114,22 @@ bool MySqlConnection::pingDatabase()
std::unique_ptr<QueryGrammar> MySqlConnection::getDefaultQueryGrammar() const
{
// FEATURE table prefix silverqx
return std::make_unique<Query::Grammars::MySqlGrammar>();
// Ownership of a unique_ptr()
auto grammar = std::make_unique<Query::Grammars::MySqlGrammar>();
withTablePrefix(*grammar);
return grammar;
}
std::unique_ptr<SchemaGrammar> MySqlConnection::getDefaultSchemaGrammar() const
{
// FEATURE table prefix silverqx
return std::make_unique<Schema::Grammars::MySqlSchemaGrammar>();
// Ownership of a unique_ptr()
auto grammar = std::make_unique<Schema::Grammars::MySqlSchemaGrammar>();
withTablePrefix(*grammar);
return grammar;
}
std::unique_ptr<QueryProcessor> MySqlConnection::getDefaultPostProcessor() const
+2 -3
View File
@@ -11,11 +11,10 @@ namespace Orm::Schema
QStringList MySqlSchemaBuilder::getColumnListing(const QString &table) const
{
// FEATURE table prefix silverqx
// const auto table_ = m_connection.getTablePrefix() + table;
const QString table_ = m_connection.getTablePrefix() + table;
auto query = m_connection.select(m_grammar.compileColumnListing(), {
m_connection.getDatabaseName(), table
m_connection.getDatabaseName(), table_
});
return m_connection.getPostProcessor().processColumnListing(query);
+1 -1
View File
@@ -16,8 +16,8 @@ SchemaBuilder::SchemaBuilder(DatabaseConnection &connection)
QStringList SchemaBuilder::getColumnListing(const QString &table) const
{
// FEATURE table prefix silverqx
auto query = m_connection.selectFromWriteConnection(
m_connection.getTablePrefix() +
m_grammar.compileColumnListing(table));
return m_connection.getPostProcessor().processColumnListing(query);
+12 -4
View File
@@ -37,14 +37,22 @@ std::unique_ptr<SchemaBuilder> SQLiteConnection::getSchemaBuilder()
std::unique_ptr<QueryGrammar> SQLiteConnection::getDefaultQueryGrammar() const
{
// FEATURE table prefix silverqx
return std::make_unique<Query::Grammars::SQLiteGrammar>();
// Ownership of a unique_ptr()
auto grammar = std::make_unique<Query::Grammars::SQLiteGrammar>();
withTablePrefix(*grammar);
return grammar;
}
std::unique_ptr<SchemaGrammar> SQLiteConnection::getDefaultSchemaGrammar() const
{
// FEATURE table prefix silverqx
return std::make_unique<Schema::Grammars::SQLiteSchemaGrammar>();
// Ownership of a unique_ptr()
auto grammar = std::make_unique<Schema::Grammars::SQLiteSchemaGrammar>();
withTablePrefix(*grammar);
return grammar;
}
std::unique_ptr<QueryProcessor> SQLiteConnection::getDefaultPostProcessor() const
@@ -18,6 +18,8 @@ private slots:
void from() const;
void from_TableWrappingQuotationMarks() const;
void from_WithPrefix() const;
void from_AliasWithPrefix() const;
void select() const;
void addSelect() const;
@@ -160,6 +162,54 @@ void tst_MySql_QueryBuilder::from_TableWrappingQuotationMarks() const
}
}
void tst_MySql_QueryBuilder::from_WithPrefix() const
{
auto builder = createQuery(m_connection);
const auto prefix = QStringLiteral("xyz_");
const auto table = QStringLiteral("table");
builder->from(table);
builder->getConnection().setTablePrefix(prefix);
QCOMPARE(builder->getFrom(), table);
QCOMPARE(builder->toSql(),
"select * from `xyz_table`");
// Restore
builder->getConnection().setTablePrefix("");
}
void tst_MySql_QueryBuilder::from_AliasWithPrefix() const
{
auto builder = createQuery(m_connection);
const auto prefix = QStringLiteral("xyz_");
builder->getConnection().setTablePrefix(prefix);
{
const auto table = QStringLiteral("table");
const auto alias = QStringLiteral("alias");
builder->from(table, alias);
QCOMPARE(builder->getFrom(), QStringLiteral("%1 as %2").arg(table, alias));
QCOMPARE(builder->toSql(),
"select * from `xyz_table` as `xyz_alias`");
}
{
const auto table = QStringLiteral("table as alias");
builder->from(table);
QCOMPARE(builder->getFrom(), table);
QCOMPARE(builder->toSql(),
"select * from `xyz_table` as `xyz_alias`");
}
// Restore
builder->getConnection().setTablePrefix("");
}
void tst_MySql_QueryBuilder::select() const
{
auto builder = createQuery(m_connection);
@@ -18,6 +18,8 @@ private slots:
void from() const;
void from_TableWrappingQuotationMarks() const;
void from_WithPrefix() const;
void from_AliasWithPrefix() const;
void select() const;
void addSelect() const;
@@ -141,6 +143,54 @@ void tst_SQLite_QueryBuilder::from_TableWrappingQuotationMarks() const
}
}
void tst_SQLite_QueryBuilder::from_WithPrefix() const
{
auto builder = createQuery(m_connection);
const auto prefix = QStringLiteral("xyz_");
const auto table = QStringLiteral("table");
builder->from(table);
builder->getConnection().setTablePrefix(prefix);
QCOMPARE(builder->getFrom(), table);
QCOMPARE(builder->toSql(),
"select * from \"xyz_table\"");
// Restore
builder->getConnection().setTablePrefix("");
}
void tst_SQLite_QueryBuilder::from_AliasWithPrefix() const
{
auto builder = createQuery(m_connection);
const auto prefix = QStringLiteral("xyz_");
builder->getConnection().setTablePrefix(prefix);
{
const auto table = QStringLiteral("table");
const auto alias = QStringLiteral("alias");
builder->from(table, alias);
QCOMPARE(builder->getFrom(), QStringLiteral("%1 as %2").arg(table, alias));
QCOMPARE(builder->toSql(),
"select * from \"xyz_table\" as \"xyz_alias\"");
}
{
const auto table = QStringLiteral("table as alias");
builder->from(table);
QCOMPARE(builder->getFrom(), table);
QCOMPARE(builder->toSql(),
"select * from \"xyz_table\" as \"xyz_alias\"");
}
// Restore
builder->getConnection().setTablePrefix("");
}
void tst_SQLite_QueryBuilder::select() const
{
auto builder = createQuery(m_connection);