1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
#pragma once
#include "Driver.h"
#include "Host.h"
#include "Value.h"
#include "SequentialConnection.h"
namespace sql {
/**
* Base class for MySQL-derivatives.
*
* Use the MySQL or MariaDB classes to connect.
*/
class MariaDBBase : public SequentialConnection {
STORM_CLASS;
public:
class Stmt;
// Destructor of an Mariadb database connection. Calls MariaDB:close().
virtual ~MariaDBBase();
// Prepares a statement for execution.
using DBConnection::prepare;
Statement *STORM_FN prepare(Str *query) override;
// Closes the connection.
void STORM_FN close() override;
// Returns all names of tables in MariaDB connection in an Array of Str.
Array<Str*> *STORM_FN tables() override;
// Returns a Schema for MariaDB connection.
MAYBE(Schema *) STORM_FN schema(Str *table) override;
// Migrate database.
void STORM_FN migrate(Migration *migration) override;
// Get database features.
virtual features::DBFeatures STORM_FN features() const override;
protected:
// Create the connection, called from derived classes.
STORM_CTOR MariaDBBase(Host c, MAYBE(Str *) user, MAYBE(Str *) password, Str *database);
// Create a visitor.
QueryStr::Visitor *STORM_FN visitor() const override;
// Transaction management.
void STORM_FN beginTransaction() override;
void STORM_FN endTransaction(Transaction::End end) override;
// Throw an error if one is present.
void throwError();
/**
* Interface from SequentialConnection.
*/
// Finalize a statement.
virtual void STORM_FN finalizeStmt(SequentialStatement *stmt) override;
private:
// Handle to the database.
UNKNOWN(PTR_NOGC) MYSQL *handle;
// Pointer to the API block of the handle for easy access.
UNKNOWN(PTR_NOGC) st_mariadb_api *api;
// Cached query for last row id.
Stmt *lastRowIdQuery;
// Find the last row id.
Int queryLastRowId();
// Helper to migrate a single table.
void migrateTable(Migration::Table *m);
// Helper to perform one-off queries.
void query(const char *query);
void query(Str *query);
void query(QueryStr *query);
public:
/**
* Prepared statement.
*/
class Stmt : public SequentialStatement {
STORM_CLASS;
public:
// Bind parameters.
void STORM_FN bind(Nat pos, Str *str) override;
void STORM_FN bind(Nat pos, Bool b) override;
void STORM_FN bind(Nat pos, Int i) override;
void STORM_FN bind(Nat pos, Long l) override;
void STORM_FN bind(Nat pos, Float f) override;
void STORM_FN bind(Nat pos, Double d) override;
void STORM_FN bindNull(Nat pos) override;
protected:
// Get last row id and changes.
Int STORM_FN lastRowId() override { return lastId; }
Nat STORM_FN changes() override { return lastChanges; }
// Execute the query.
Bool STORM_FN executeSeq() override;
// Get next row.
Maybe<Row> STORM_FN nextRowSeq() override;
// Dispose result.
void STORM_FN disposeResultSeq() override;
private:
friend class MariaDBBase;
// Create.
Stmt(MariaDBBase *owner, Str *query);
// The prepared statement itself.
UNKNOWN(PTR_NOGC) MYSQL_STMT *stmt;
// Saved row id.
Int lastId;
// Saved number of changes.
Nat lastChanges;
/**
* Bound buffers for the parameters:
*
* Arrays are allocated with malloc since the library has pointers into them (at least
* "values", but maybe also to "resultBind").
*/
Nat paramCount;
UNKNOWN(PTR_NOGC) MYSQL_BIND *paramBinds;
UNKNOWN(PTR_NOGC) Value *paramValues;
/**
* Bound buffers for the result:
*
* Arrays are allocated with malloc since the library has pointers into them (at least
* "values", but maybe also to "resultBind").
*/
Nat resultCount;
UNKNOWN(PTR_NOGC) MYSQL_BIND *resultBinds;
UNKNOWN(PTR_NOGC) Value *resultValues;
// Get the owner.
MariaDBBase *owner() const {
return reinterpret_cast<MariaDBBase *>(connection());
}
// Throw error.
void throwError();
};
/**
* Visitor to transform query strings.
*/
class Visitor : public QueryStr::Visitor {
STORM_CLASS;
public:
STORM_CTOR Visitor();
void STORM_FN name(StrBuf *to, Str *name) override;
void STORM_FN type(StrBuf *to, QueryType type) override;
void STORM_FN autoIncrement(StrBuf *to) override;
};
};
/**
* Connection to MySQL databases.
*
* Note: The distinction between MySQL and MariaDB is mostly for future-proofing any differences
* that might arise eventually. They are currently compatible enough for this difference to be
* irrelevant.
*/
class MySQL : public MariaDBBase {
STORM_CLASS;
public:
// Connect.
STORM_CTOR MySQL(Host c, MAYBE(Str *) user, MAYBE(Str *) password, Str *database);
};
/**
* Connection to MariaDB databases.
*
* Note: The distinction between MySQL and MariaDB is mostly for future-proofing any differences
* that might arise eventually. They are currently compatible enough for this difference to be
* irrelevant.
*/
class MariaDB : public MariaDBBase {
STORM_CLASS;
public:
// Connect.
STORM_CTOR MariaDB(Host c, MAYBE(Str *) user, MAYBE(Str *) password, Str *database);
// Get database features.
virtual features::DBFeatures STORM_FN features() const override;
};
}
|