Question

I want to create a class with static constants which are used whenever a part of an application want to access the database in any way. This way I want to remove all magic numbers and string inside my application code except at one place. So any time later any changes to the database model have to be done, all adjustments must be taken at one place or the compiler finds all others.

Anyway, this is what I have so far

#include <QObject>

class DatabaseModel : public QObject
{
    Q_OBJECT
public:
    static const QChar SCHEMA_SEPARATOR() { return '.'; }

    static const QString qualifiedTableName(const QString &schema, const QString &table) {
        return schema + SCHEMA_SEPARATOR() + table;
    }

    static const QString SCHEMA_VERSION() { return "0.2"; }

    static const QString DATA_SCHEMA() { return "core"; }
    static const QString DEFAULT_SCHEMA() { return "public"; }
    static const QString LOG_SCHEMA() { return "audit"; }

    static const QString UNIT_TABLE() { return "unit"; }
    static const QStringList UNIT_TABLE_COLS() {
        return QStringList() << "id"
                             << "name"
                             << "abbreviation";
    }
};

Sample usage

// get the fully qualified database table name
// result: core.unit
DatabaseModel::qualifiedTableName(DatabaseModel::DATA_SCHEMA(), DatabaseModel::UNIT_TABLE());

// get the database column name
// result: name
DatabaseModel::UNIT_TABLE_COLS().at(1);

Resulting problems from my points of view:

  • pretty long function invocation
  • separation between table and its columns

I tried some class constellation but way not happy either. So my question: Is there a simple, nice approach for accessing database names and qualifier for a complex database model?

I am using Qt (5.6), PostgreSQL with C++. It might be possible to describe a solution in pure C++ because there should be no advantages of using Qt's functionality.

Edit: Additionally I use Qt's MVC for accessing the database, namely its QSqlTableModel.

Was it helpful?

Solution

If it's only about the length of the expressions, you could:

  • create a local object DatabaseModel dbm;
  • or use a namespace and a using claus instead of a class.

Nevertheless, this would end up in a constantly growing class, without real separation of concern. And it will leave you the problems of table names and column names.

I'd therefore suggest you to use the table data gateway pattern:

  • you could group the table independent constants in a DataGateway parent class, together with some common table access/management functions.
  • You would derive a concrete TableXGateway for each table X. This would allow to keep not only table name and column names together, but also some additional table specific logic (queries).

Ideally, all your SQL code would be concentrated in these classes (and perhaps in some query objects) so that the rest of your code would become less database dependent.

Licensed under: CC-BY-SA with attribution
scroll top