Skip to content

Instantly share code, notes, and snippets.

@ianmac45
Created October 6, 2014 23:08
Show Gist options
  • Save ianmac45/9fae0872b92e6da76cce to your computer and use it in GitHub Desktop.
Save ianmac45/9fae0872b92e6da76cce to your computer and use it in GitHub Desktop.
the "sugar coating" for working with "raw" sql in c++, using qt
#pragma once
#include <QDebug>
#include <QString>
#include <QVariant>
#include <QSqlField>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlDriver>
#include <QSqlRecord>
#include <QSqlDatabase>
#ifndef VAL_EXIT
#define VAL_EXIT(RETURN_VALUE) { qWarning() << (RETURN_VALUE); return 0; }
#endif
namespace sql
{
static QSqlQuery generateSql(QSqlDatabase db, QSqlDriver::StatementType type, const QString &tableName, const QSqlRecord &values, const QSqlRecord &wheres = QSqlRecord())
{
QSqlQuery q(db);
QString sql = q.driver()->sqlStatement(type, tableName, values, false);
if(!wheres.isEmpty())
sql += " " + q.driver()->sqlStatement(QSqlDriver::WhereStatement, tableName, wheres, false);
q.prepare(sql);
return q;
}
//facilitates intuitive execution of sql commands
// => bool execOk = sql::insert(table) << [[field1]] << sql::where() << field("id", 1);
class field_dest
{
public:
const bool IsWhere;
field_dest(bool _isWhere) :
IsWhere(_isWhere)
{
}
};
//helpful ctor for QSqlField
class field : QSqlField
{
public:
explicit field(const QString &name, const QVariant &value = QVariant()) :
QSqlField(name, value.type())
{
setValue(value);
}
field(const QSqlField &other) :
QSqlField(other)
{
}
};
//generalized structure (& support classes) for executing normal CRUD operations
class command_data
{
public:
QSqlRecord values, wheres;
QString table;
QSqlDatabase database;
QSqlDriver::StatementType type;
bool isWheres;
unsigned status; //0 = not exec'ed, 1 = bad, 2 = good
command_data(const QString &tableName, QSqlDatabase db, QSqlDriver::StatementType _type) :
table(tableName),
database(db),
type(_type),
status(0),
isWheres(false)
{
}
virtual ~command_data()
{
doExec();
}
bool exec() const
{
if(type == QSqlDriver::InsertStatement || type == QSqlDriver::UpdateStatement)
if(values.isEmpty())
return true;
QSqlQuery q = generateSql(database, type, table, values, wheres);
if(!q.exec())
VAL_EXIT(q.lastError().text() + "\n" + q.executedQuery());
return true;
}
void doExec()
{
if(!status)
status = exec() + 1;
}
};
class command
{
std::auto_ptr<command_data> d;
public:
command(command_data *data = 0) :
d(data)
{
}
operator bool()
{
if(!d.get()) return false;
d->doExec();
return d->status == 2;
}
command& operator<< (const field &f)
{
if(d.get()) (d->isWheres ? d->wheres : d->values).append(f);
return *this;
}
command& operator<< (const field_dest &dest)
{
if(d.get()) d->isWheres = dest.IsWhere;
return *this;
}
};
inline command insert(const QString &table, QSqlDatabase db = QSqlDatabase::database()) { return command(new command_data(table, db, QSqlDriver::InsertStatement)); }
inline command update(const QString &table, QSqlDatabase db = QSqlDatabase::database()) { return command(new command_data(table, db, QSqlDriver::UpdateStatement)); }
inline command delete_(const QString &table, QSqlDatabase db = QSqlDatabase::database()) { return command(new command_data(table, db, QSqlDriver::DeleteStatement)) << field_dest(true); }
}
inline sql::command& where (sql::command &c) { return c << sql::field_dest (true); }
inline sql::command& values(sql::command &c) { return c << sql::field_dest(false); }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment