166 lines
3.9 KiB
C++
166 lines
3.9 KiB
C++
/**
|
|
* @file
|
|
*/
|
|
|
|
#include "Model.h"
|
|
#include "ConstraintType.h"
|
|
#include "core/Log.h"
|
|
#include "core/StringUtil.h"
|
|
#include "core/Singleton.h"
|
|
#include "core/Assert.h"
|
|
|
|
namespace persistence {
|
|
|
|
core::String toLower(const char *in) {
|
|
const core::String s(in);
|
|
return s.toLower();
|
|
}
|
|
|
|
core::String toLower(const core::String& in) {
|
|
return in.toLower();
|
|
}
|
|
|
|
Model::Model(const Meta* s) :
|
|
_s(s) {
|
|
_membersPointer = (uint8_t*)this;
|
|
}
|
|
|
|
Model::~Model() {
|
|
}
|
|
|
|
const Field& Model::getField(const char* name) const {
|
|
if (name != nullptr && name[0] != '\0') {
|
|
for (auto i = _s->_fields.begin(); i != _s->_fields.end(); ++i) {
|
|
const Field& field = *i;
|
|
if (field.name == name) {
|
|
return field;
|
|
}
|
|
}
|
|
// might e.g. happen in table update steps
|
|
Log::debug("Failed to lookup field '%s' in table '%s'", name, _s->_tableName);
|
|
}
|
|
static const Field emptyField {};
|
|
return emptyField;
|
|
}
|
|
|
|
bool Model::fillModelValues(State& state) {
|
|
const int cols = state.cols;
|
|
Log::debug("Query has values for %i cols", cols);
|
|
for (int i = 0; i < cols; ++i) {
|
|
const char* name = state.columnName(i);
|
|
const Field& f = getField(name);
|
|
if (f.name != name) {
|
|
Log::error("Unknown field name for '%s'", name);
|
|
state.result = false;
|
|
return false;
|
|
}
|
|
const char *value;
|
|
int length;
|
|
bool isNull;
|
|
state.getResult(i, f.type, &value, &length, &isNull);
|
|
Log::debug("Try to set '%s' to '%s' (length: %i)", name, value, length);
|
|
switch (f.type) {
|
|
case FieldType::PASSWORD:
|
|
case FieldType::TEXT:
|
|
setValue(f, core::String(value, length));
|
|
break;
|
|
case FieldType::STRING: {
|
|
const core::String s(value, length);
|
|
if (f.isLower()) {
|
|
setValue(f, s.toLower());
|
|
} else {
|
|
setValue(f, s);
|
|
}
|
|
break;
|
|
}
|
|
case FieldType::BOOLEAN:
|
|
setValue(f, state.isBool(value));
|
|
break;
|
|
case FieldType::BLOB:
|
|
setValue(f, Blob((uint8_t*)value, length));
|
|
break;
|
|
case FieldType::INT:
|
|
setValue(f, (int32_t)core::string::toInt(value));
|
|
break;
|
|
case FieldType::SHORT:
|
|
setValue(f, (int16_t)core::string::toInt(value));
|
|
break;
|
|
case FieldType::BYTE:
|
|
setValue(f, (uint8_t)core::string::toInt(value));
|
|
break;
|
|
case FieldType::LONG:
|
|
setValue(f, core::string::toLong(value));
|
|
break;
|
|
case FieldType::DOUBLE:
|
|
setValue(f, core::string::toDouble(value));
|
|
break;
|
|
case FieldType::TIMESTAMP: {
|
|
setValue(f, Timestamp(core::string::toLong(value)));
|
|
break;
|
|
}
|
|
case FieldType::MAX:
|
|
break;
|
|
}
|
|
setIsNull(f, isNull);
|
|
}
|
|
++state.currentRow;
|
|
return true;
|
|
}
|
|
|
|
void Model::setValue(const Field& f, const core::String& value) {
|
|
core_assert(f.offset >= 0);
|
|
uint8_t* target = (uint8_t*)(_membersPointer + f.offset);
|
|
core::String* targetValue = (core::String*)target;
|
|
*targetValue = value;
|
|
setValid(f, true);
|
|
}
|
|
|
|
void Model::setValue(const Field& f, const Timestamp& value) {
|
|
core_assert(f.offset >= 0);
|
|
uint8_t* target = (uint8_t*)(_membersPointer + f.offset);
|
|
Timestamp* targetValue = (Timestamp*)target;
|
|
*targetValue = value;
|
|
setValid(f, true);
|
|
}
|
|
|
|
void Model::setValue(const Field& f, std::nullptr_t np) {
|
|
setIsNull(f, true);
|
|
}
|
|
|
|
void Model::setIsNull(const Field& f, bool isNull) {
|
|
if (f.nulloffset == -1) {
|
|
return;
|
|
}
|
|
uint8_t* target = (uint8_t*)(_membersPointer + f.nulloffset);
|
|
bool* targetValue = (bool*)target;
|
|
*targetValue = isNull;
|
|
setValid(f, true);
|
|
}
|
|
|
|
void Model::setValid(const Field& f, bool valid) {
|
|
uint8_t* target = (uint8_t*)(_membersPointer + f.validoffset);
|
|
bool* targetValue = (bool*)target;
|
|
*targetValue = valid;
|
|
}
|
|
|
|
void Model::reset(const Field& f) {
|
|
setValid(f, false);
|
|
}
|
|
|
|
bool Model::isValid(const Field& f) const {
|
|
const uint8_t* target = (const uint8_t*)(_membersPointer + f.validoffset);
|
|
const bool* targetValue = (const bool*)target;
|
|
return *targetValue;
|
|
}
|
|
|
|
bool Model::isNull(const Field& f) const {
|
|
if (f.nulloffset < 0) {
|
|
return false;
|
|
}
|
|
const uint8_t* target = (const uint8_t*)(_membersPointer + f.nulloffset);
|
|
const bool* targetValue = (const bool*)target;
|
|
return *targetValue;
|
|
}
|
|
|
|
}
|