diff --git a/DataStorage/Database/Connection/ConnectionAbstract.h b/DataStorage/Database/Connection/ConnectionAbstract.h index 366ef13..cac4e23 100755 --- a/DataStorage/Database/Connection/ConnectionAbstract.h +++ b/DataStorage/Database/Connection/ConnectionAbstract.h @@ -21,6 +21,12 @@ namespace DataStorage { namespace Database { + typedef struct { + size_t rows = 0; + size_t columns = 0; + char **results = NULL; + } QueryResult; + struct ConnectionAbstract { void *con = NULL; @@ -44,6 +50,11 @@ namespace DataStorage this->con = NULL; this->status = DatabaseStatus::CLOSED; } + + virtual QueryResult query_execute(char *stmt, char *paramValues = NULL) + { + return QueryResult(); + } }; } } diff --git a/DataStorage/Database/Connection/MysqlConnection.h b/DataStorage/Database/Connection/MysqlConnection.h index ab29eff..95c92bc 100755 --- a/DataStorage/Database/Connection/MysqlConnection.h +++ b/DataStorage/Database/Connection/MysqlConnection.h @@ -85,6 +85,64 @@ namespace DataStorage this->con = NULL; this->status = DatabaseStatus::CLOSED; } + + QueryResult query_execute(char *stmt, char *paramValues = NULL) + { + QueryResult result; + + MYSQL_RES *res; + int status = 0; + + if (paramValues != NULL) { + return result; + } else { + status = mysql_query((::MYSQL *) this->con, stmt); + res = mysql_store_result((::MYSQL *) this->con); + } + + if (res == NULL) { + return result; + } + + result.rows = mysql_num_rows(res); + result.columns = mysql_num_fields(res); + + if (result.rows == 0 || result.columns == 0) { + return result; + } + + result.results = (char **) malloc(result.rows * result.columns * sizeof(char*)); + + char *temp = NULL; + size_t valLen = 0; + size_t *lengths; + + ::MYSQL_ROW row; + size_t i = 0; + + while ((row = mysql_fetch_row(res)) != NULL) { + lengths = mysql_fetch_lengths(res); + for (int j = 0; j < result.columns; ++j) { + temp = row[j]; + + if (temp == NULL) { + result.results[i * result.columns + j] = NULL; + + continue; + } + + valLen = lengths[j]; + + result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char)); + memcpy(result.results[i * result.columns + j], temp, valLen); + result.results[i * result.columns + j][valLen] = '\0'; + } + + ++i; + } + + return result; + } }; } } diff --git a/DataStorage/Database/Connection/PostgresqlConnection.h b/DataStorage/Database/Connection/PostgresqlConnection.h index 27eb542..83cbd1e 100755 --- a/DataStorage/Database/Connection/PostgresqlConnection.h +++ b/DataStorage/Database/Connection/PostgresqlConnection.h @@ -89,6 +89,54 @@ namespace DataStorage this->con = NULL; this->status = DatabaseStatus::CLOSED; } + + QueryResult query_execute(char *stmt, char *paramValues = NULL) + { + QueryResult result; + + PGresult *res; + if (paramValues != NULL) { + res = PQexecParams((PGconn *) this->con, stmt, 1, NULL, (const char* const*) paramValues, NULL, NULL, 0); + } else { + res = PQexec((PGconn *) this->con, stmt); + } + + if (PQresultStatus(res) != PGRES_TUPLES_OK) { + PQclear(res); + + return result; + } + + result.rows = PQntuples(res); + result.columns = PQnfields(res); + + result.results = (char **) malloc(result.rows * result.columns * sizeof(char*)); + + char *temp = NULL; + size_t valLen = 0; + + for (size_t i = 0; i < result.rows; ++i) { + for (size_t j = 0; j < result.columns; ++j) { + temp = PQgetvalue(res, i, j); + + if (temp == NULL) { + result.results[i * result.columns + j] = NULL; + + continue; + } + + valLen = strlen(temp); + + result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char)); + memcpy(result.results[i * result.columns + j], temp, valLen); + result.results[i * result.columns + j][valLen] = '\0'; + } + } + + PQclear(res); + + return result; + } }; } } diff --git a/DataStorage/Database/Connection/SQLiteConnection.h b/DataStorage/Database/Connection/SQLiteConnection.h index edc9f76..a549800 100755 --- a/DataStorage/Database/Connection/SQLiteConnection.h +++ b/DataStorage/Database/Connection/SQLiteConnection.h @@ -71,6 +71,89 @@ namespace DataStorage this->con = NULL; this->status = DatabaseStatus::CLOSED; } + + QueryResult query_execute(char *stmt, char *paramValues = NULL) + { + QueryResult result; + + sqlite3_stmt *res; + int status = 0; + + if (paramValues != NULL) { + status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0); + + // @todo: sqlite3_bind_int(res, 1, 3); + } else { + status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0); + } + + if (res == NULL) { + return result; + } + + status = sqlite3_step(res); + + result.rows = 100; + result.columns = sqlite3_column_count(res); + + if (result.rows == 0 || result.columns == 0) { + return result; + } + + result.results = (char **) malloc(result.rows * result.columns * sizeof(char*)); + + char *temp = NULL; + size_t valLen = 0; + char ** tempStorage = NULL; + + size_t i = 0; + while (status == SQLITE_ROW) { + if (i == result.rows) { + tempStorage = (char **) malloc((result.rows + 100) * result.columns * sizeof(char*)); + memcpy(tempStorage, result.results, result.rows * result.columns * sizeof(char*)); + + free(result.results); + result.results = tempStorage; + + result.rows += 100; + } + + for (int j = 0; j < result.columns; ++j) { + temp = (char *) sqlite3_column_text(res, j); + + if (temp == NULL) { + result.results[i * result.columns + j] = NULL; + + continue; + } + + valLen = strlen(temp); + + result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char)); + memcpy(result.results[i * result.columns + j], temp, valLen); + result.results[i * result.columns + j][valLen] = '\0'; + } + + status = sqlite3_step(res); + + ++i; + } + + --i; + if (i != result.rows) { + tempStorage = (char **) malloc(i * result.columns * sizeof(char*)); + memcpy(tempStorage, result.results, i * result.columns * sizeof(char*)); + + free(result.results); + result.results = tempStorage; + + result.rows = i; + } + + sqlite3_finalize(res); + + return result; + } }; } } diff --git a/DataStorage/Database/Mapper/DataMapperFactory.h b/DataStorage/Database/Mapper/DataMapperFactory.h index c701ecc..de7adb1 100644 --- a/DataStorage/Database/Mapper/DataMapperFactory.h +++ b/DataStorage/Database/Mapper/DataMapperFactory.h @@ -23,10 +23,10 @@ namespace DataStorage namespace Database { static DataStorage::Database::ConnectionAbstract *db; - static char *dateTimeFormat = (char *) "Y-m-d H:i:s"; + static const char *dateTimeFormat = "Y-m-d H:i:s"; struct DataMapperFactory { - static ReadMapper *reader(const DataStorage::Database::MapperData *mapper, ConnectionAbstract *db = NULL) + static ReadMapper *reader(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL) { ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper)); readMapper->mapper = mapper; @@ -35,7 +35,7 @@ namespace DataStorage return readMapper; } - static ReadMapper *get(const DataStorage::Database::MapperData *mapper, ConnectionAbstract *db = NULL) + static ReadMapper *get(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL) { ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper)); readMapper->mapper = mapper; @@ -44,7 +44,7 @@ namespace DataStorage return readMapper->get(); } - static ReadMapper *getAll(const DataStorage::Database::MapperData *mapper, ConnectionAbstract *db = NULL) + static ReadMapper *getAll(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL) { ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper)); readMapper->mapper = mapper; diff --git a/DataStorage/Database/Mapper/DataMapperTypes.h b/DataStorage/Database/Mapper/DataMapperTypes.h index 2e6cf99..1643112 100644 --- a/DataStorage/Database/Mapper/DataMapperTypes.h +++ b/DataStorage/Database/Mapper/DataMapperTypes.h @@ -17,6 +17,19 @@ namespace DataStorage { namespace Database { + typedef enum { + MAPPER_DEFAULT = 0, + MAPPER_GET = 1, + MAPPER_GET_ALL = 4, + MAPPER_FIND = 7, + MAPPER_GET_RAW = 8, + MAPPER_GET_RANDOM = 11, + MAPPER_COUNT_MODELS = 12, + MAPPER_CREATE = 1001, + MAPPER_UPDATE = 2001, + MAPPER_DELETE = 3001 + } MapperType; + typedef enum { FIELD_TYPE_INT = 1, FIELD_TYPE_FLOAT = 2, @@ -31,9 +44,11 @@ namespace DataStorage void free_ModelStructure(ModelStructure *data) { + /* Not necessary if (data->name != NULL) { free((void *) data->name); } + */ } typedef struct { @@ -56,49 +71,51 @@ namespace DataStorage } typedef struct { - char *member = NULL; - char *mapper = NULL; - char *external = NULL; - char *table = NULL; - char *self = NULL; - char *column = NULL; + const char *member = NULL; + const char *mapper = NULL; + const char *external = NULL; + const char *table = NULL; + const char *self = NULL; + const char *column = NULL; bool conditional = false; - char *by = NULL; + const char *by = NULL; } TableRelation; void free_TableRelation(TableRelation *data) { + /* Not necessary if (data->member != NULL) { - free(data->member); + free((void *) data->member); } if (data->mapper != NULL) { - free(data->mapper); + free((void *) data->mapper); } if (data->external != NULL) { - free(data->external); + free((void *) data->external); } if (data->table != NULL) { - free(data->table); + free((void *) data->table); } if (data->self != NULL) { - free(data->self); + free((void *) data->self); } if (data->column != NULL) { - free(data->column); + free((void *) data->column); } if (data->self != NULL) { - free(data->self); + free((void *) data->self); } if (data->by != NULL) { - free(data->by); + free((void *) data->by); } + */ } typedef struct { @@ -126,6 +143,7 @@ namespace DataStorage void free_MapperData(DataStorage::Database::MapperData *data) { + /* Not necessary if (data->TABLE != NULL) { free((void *) data->TABLE); } @@ -145,44 +163,55 @@ namespace DataStorage if (data->MODEL != NULL) { free(data->MODEL); } + */ int i = 0; if (data->MODEL_STRUCTURE != NULL) { + /* not neccessary for (i = 0; i < data->MEMBER_COUNT; ++i) { free_ModelStructure(&data->MODEL_STRUCTURE[i]); } + */ free(data->MODEL_STRUCTURE); } if (data->COLUMNS != NULL) { - for (i = 0; data->COLUMN_COUNT; ++i) { + /* not neccessary + for (i = 0; i < data->COLUMN_COUNT; ++i) { free_DataMapperColumn(&data->COLUMNS[i]); } + */ free(data->COLUMNS); } if (data->OWNS_ONE != NULL) { - for (i = 0; data->OWNS_ONE_COUNT; ++i) { + /* not neccessary + for (i = 0; i < data->OWNS_ONE_COUNT; ++i) { free_TableRelation(&data->OWNS_ONE[i]); } + */ free(data->OWNS_ONE); } if (data->HAS_MANY != NULL) { - for (i = 0; data->HAS_MANY_COUNT; ++i) { + /* not neccessary + for (i = 0; i < data->HAS_MANY_COUNT; ++i) { free_TableRelation(&data->HAS_MANY[i]); } + */ free(data->HAS_MANY); } if (data->BELONGS_TO != NULL) { - for (i = 0; data->BELONGS_TO_COUNT; ++i) { + /* not neccessary + for (i = 0; i < data->BELONGS_TO_COUNT; ++i) { free_TableRelation(&data->BELONGS_TO[i]); } + */ free(data->BELONGS_TO); } diff --git a/DataStorage/Database/Mapper/MapperAbstract.h b/DataStorage/Database/Mapper/MapperAbstract.h index b49e3cb..443995c 100644 --- a/DataStorage/Database/Mapper/MapperAbstract.h +++ b/DataStorage/Database/Mapper/MapperAbstract.h @@ -25,6 +25,8 @@ namespace DataStorage const DataStorage::Database::ConnectionAbstract *db = NULL; + DataStorage::Database::MapperType type = DataStorage::Database::MapperType::MAPPER_DEFAULT; + int MEMBERS = 0; int COLUMN_COUNT = 0; @@ -86,6 +88,18 @@ namespace DataStorage return NULL; } + + MapperAbstract *where( + char *member, + void *value, + int valueType, + const char *logic = "=", + const char *connector = "AND" + ) { + return this; + } + + virtual void *execute(void *options = NULL); }; } } diff --git a/DataStorage/Database/Mapper/ReadMapper.h b/DataStorage/Database/Mapper/ReadMapper.h index daaa69a..cf68a09 100644 --- a/DataStorage/Database/Mapper/ReadMapper.h +++ b/DataStorage/Database/Mapper/ReadMapper.h @@ -32,12 +32,34 @@ namespace DataStorage return this; } - ReadMapper *where(char *where, void *data) + void *execute(void *options = NULL) { - return this; + switch(this->type) { + case DataStorage::Database::MapperType::MAPPER_GET: + return this->executeGet(options); + case DataStorage::Database::MapperType::MAPPER_GET_RAW: + return this->executeGetRaw(options); + case DataStorage::Database::MapperType::MAPPER_GET_ALL: + return this->executeGetAll(options); + default: + return NULL; + }; } - void *execute() + void *executeGet(void *options) + { + int *primaryKeys = NULL; + const char *memberOfPrimaryField = findByColumnName((char *) this->mapper->PRIMARYFIELD)->internal; + + return NULL; + } + + void *executeGetRaw(void *options) + { + return NULL; + } + + void *executeGetAll(void *options) { return NULL; }