diff --git a/RESTAPI_GWobjects.cpp b/RESTAPI_GWobjects.cpp deleted file mode 100644 index c626f5f..0000000 --- a/RESTAPI_GWobjects.cpp +++ /dev/null @@ -1,276 +0,0 @@ -// -// License type: BSD 3-Clause License -// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE -// -// Created by Stephane Bourque on 2021-03-04. -// Arilia Wireless Inc. -// - -#include "Poco/JSON/Parser.h" -#include "Poco/JSON/Stringifier.h" - -#include "Daemon.h" -#ifdef TIP_GATEWAY_SERVICE -#include "DeviceRegistry.h" -#include "CapabilitiesCache.h" -#endif - -#include "RESTAPI_GWobjects.h" -#include "framework/MicroService.h" - -using OpenWifi::RESTAPI_utils::field_to_json; -using OpenWifi::RESTAPI_utils::field_from_json; -using OpenWifi::RESTAPI_utils::EmbedDocument; - -namespace OpenWifi::GWObjects { - - void Device::to_json(Poco::JSON::Object &Obj) const { - field_to_json(Obj,"serialNumber", SerialNumber); -#ifdef TIP_GATEWAY_SERVICE - field_to_json(Obj,"deviceType", CapabilitiesCache::instance()->GetPlatform(Compatible)); -#endif - field_to_json(Obj,"macAddress", MACAddress); - field_to_json(Obj,"manufacturer", Manufacturer); - field_to_json(Obj,"UUID", UUID); - EmbedDocument("configuration", Obj, Configuration); - field_to_json(Obj,"notes", Notes); - field_to_json(Obj,"createdTimestamp", CreationTimestamp); - field_to_json(Obj,"lastConfigurationChange", LastConfigurationChange); - field_to_json(Obj,"lastConfigurationDownload", LastConfigurationDownload); - field_to_json(Obj,"lastFWUpdate", LastFWUpdate); - field_to_json(Obj,"owner", Owner); - field_to_json(Obj,"location", Location); - field_to_json(Obj,"venue", Venue); - field_to_json(Obj,"firmware", Firmware); - field_to_json(Obj,"compatible", Compatible); - field_to_json(Obj,"fwUpdatePolicy", FWUpdatePolicy); - field_to_json(Obj,"devicePassword", DevicePassword); - field_to_json(Obj,"subscriber", subscriber); - field_to_json(Obj,"entity", entity); - field_to_json(Obj,"modified", modified); - field_to_json(Obj,"locale", locale); - } - - void Device::to_json_with_status(Poco::JSON::Object &Obj) const { - to_json(Obj); - -#ifdef TIP_GATEWAY_SERVICE - ConnectionState ConState; - - if (DeviceRegistry()->GetState(SerialNumber, ConState)) { - ConState.to_json(Obj); - } else { - field_to_json(Obj,"ipAddress", ""); - field_to_json(Obj,"txBytes", (uint64_t) 0); - field_to_json(Obj,"rxBytes", (uint64_t )0); - field_to_json(Obj,"messageCount", (uint64_t )0); - field_to_json(Obj,"connected", false); - field_to_json(Obj,"lastContact", ""); - field_to_json(Obj,"verifiedCertificate", "NO_CERTIFICATE"); - field_to_json(Obj,"associations_2G", (uint64_t) 0); - field_to_json(Obj,"associations_5G", (uint64_t) 0); - } -#endif - } - - bool Device::from_json(const Poco::JSON::Object::Ptr &Obj) { - try { - field_from_json(Obj,"serialNumber",SerialNumber); - field_from_json(Obj,"deviceType",DeviceType); - field_from_json(Obj,"macAddress",MACAddress); - field_from_json(Obj,"configuration",Configuration); - field_from_json(Obj,"notes",Notes); - field_from_json(Obj,"manufacturer",Manufacturer); - field_from_json(Obj,"owner",Owner); - field_from_json(Obj,"location",Location); - field_from_json(Obj,"venue",Venue); - field_from_json(Obj,"compatible",Compatible); - field_from_json(Obj,"subscriber", subscriber); - field_from_json(Obj,"entity", entity); - field_from_json(Obj,"locale", locale); - return true; - } catch (const Poco::Exception &E) { - } - return false; - } - - void Device::Print() const { - std::cout << "Device: " << SerialNumber << " DeviceType:" << DeviceType << " MACAddress:" << MACAddress << " Manufacturer:" - << Manufacturer << " " << Configuration << std::endl; - } - - void Statistics::to_json(Poco::JSON::Object &Obj) const { - EmbedDocument("data", Obj, Data); - field_to_json(Obj,"UUID", UUID); - field_to_json(Obj,"recorded", Recorded); - } - - void Capabilities::to_json(Poco::JSON::Object &Obj) const { - EmbedDocument("capabilities", Obj, Capabilities); - field_to_json(Obj,"firstUpdate", FirstUpdate); - field_to_json(Obj,"lastUpdate", LastUpdate); - } - - void DeviceLog::to_json(Poco::JSON::Object &Obj) const { - EmbedDocument("data", Obj, Data); - field_to_json(Obj,"log", Log); - field_to_json(Obj,"severity", Severity); - field_to_json(Obj,"recorded", Recorded); - field_to_json(Obj,"logType", LogType); - field_to_json(Obj,"UUID", UUID); - } - - void HealthCheck::to_json(Poco::JSON::Object &Obj) const { - EmbedDocument("values", Obj, Data); - field_to_json(Obj,"UUID", UUID); - field_to_json(Obj,"sanity", Sanity); - field_to_json(Obj,"recorded", Recorded); - } - - void DefaultConfiguration::to_json(Poco::JSON::Object &Obj) const { - EmbedDocument("configuration", Obj, Configuration); - field_to_json(Obj,"name", Name); - field_to_json(Obj,"modelIds", Models); - field_to_json(Obj,"description", Description); - field_to_json(Obj,"created", Created); - field_to_json(Obj,"lastModified", LastModified); - } - - void CommandDetails::to_json(Poco::JSON::Object &Obj) const { - EmbedDocument("details", Obj, Details); - EmbedDocument("results", Obj, Results); - field_to_json(Obj,"UUID", UUID); - field_to_json(Obj,"serialNumber", SerialNumber); - field_to_json(Obj,"command", Command); - field_to_json(Obj,"errorText", ErrorText); - field_to_json(Obj,"submittedBy", SubmittedBy); - field_to_json(Obj,"status", Status); - field_to_json(Obj,"submitted", Submitted); - field_to_json(Obj,"executed", Executed); - field_to_json(Obj,"completed", Completed); - field_to_json(Obj,"when", RunAt); - field_to_json(Obj,"errorCode", ErrorCode); - field_to_json(Obj,"custom", Custom); - field_to_json(Obj,"waitingForFile", WaitingForFile); - field_to_json(Obj,"attachFile", AttachDate); - field_to_json(Obj,"executionTime", executionTime); - } - - bool DefaultConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) { - try { - field_from_json(Obj,"name",Name); - field_from_json(Obj,"configuration",Configuration); - field_from_json(Obj,"modelIds",Models); - field_from_json(Obj,"description",Description); - return true; - } catch (const Poco::Exception &E) { - } - return false; - } - - void BlackListedDevice::to_json(Poco::JSON::Object &Obj) const { - field_to_json(Obj,"serialNumber", serialNumber); - field_to_json(Obj,"author", author); - field_to_json(Obj,"reason", reason); - field_to_json(Obj,"created", created); - } - - bool BlackListedDevice::from_json(const Poco::JSON::Object::Ptr &Obj) { - try { - field_from_json(Obj,"serialNumber",serialNumber); - field_from_json(Obj,"author",author); - field_from_json(Obj,"reason",reason); - field_from_json(Obj,"created",created); - return true; - } catch (const Poco::Exception &E) { - } - return false; - } - - void ConnectionState::to_json(Poco::JSON::Object &Obj) const { - field_to_json(Obj,"ipAddress", Address); - field_to_json(Obj,"txBytes", TX); - field_to_json(Obj,"rxBytes", RX); - field_to_json(Obj,"messageCount", MessageCount); - field_to_json(Obj,"UUID", UUID); - field_to_json(Obj,"connected", Connected); - field_to_json(Obj,"firmware", Firmware); - field_to_json(Obj,"lastContact", LastContact); - field_to_json(Obj,"associations_2G", Associations_2G); - field_to_json(Obj,"associations_5G", Associations_5G); - field_to_json(Obj,"webSocketClients", webSocketClients); - field_to_json(Obj,"websocketPackets", websocketPackets); - field_to_json(Obj,"kafkaClients", kafkaClients); - field_to_json(Obj,"kafkaPackets", kafkaPackets); - field_to_json(Obj,"locale", locale); - - switch(VerifiedCertificate) { - case NO_CERTIFICATE: - field_to_json(Obj,"verifiedCertificate", "NO_CERTIFICATE"); break; - case VALID_CERTIFICATE: - field_to_json(Obj,"verifiedCertificate", "VALID_CERTIFICATE"); break; - case MISMATCH_SERIAL: - field_to_json(Obj,"verifiedCertificate", "MISMATCH_SERIAL"); break; - case VERIFIED: - field_to_json(Obj,"verifiedCertificate", "VERIFIED"); break; - default: - field_to_json(Obj,"verifiedCertificate", "NO_CERTIFICATE"); break; - } - } - - void RttySessionDetails::to_json(Poco::JSON::Object &Obj) const { - field_to_json(Obj,"serialNumber", SerialNumber); - field_to_json(Obj,"server", Server); - field_to_json(Obj,"port", Port); - field_to_json(Obj,"token",Token); - field_to_json(Obj,"timeout", TimeOut); - field_to_json(Obj,"connectionId",ConnectionId); - field_to_json(Obj,"commandUUID",CommandUUID); - field_to_json(Obj,"started", Started); - field_to_json(Obj,"viewport",ViewPort); - field_to_json(Obj,"password",DevicePassword); - } - - void Dashboard::to_json(Poco::JSON::Object &Obj) const { - field_to_json(Obj,"commands",commands); - field_to_json(Obj,"upTimes",upTimes); - field_to_json(Obj,"memoryUsed",memoryUsed); - field_to_json(Obj,"load1",load1); - field_to_json(Obj,"load5",load5); - field_to_json(Obj,"load15",load15); - field_to_json(Obj,"vendors",vendors); - field_to_json(Obj,"status",status); - field_to_json(Obj,"deviceType",deviceType); - field_to_json(Obj,"healths",healths); - field_to_json(Obj,"certificates",certificates); - field_to_json(Obj,"lastContact",lastContact); - field_to_json(Obj,"associations",associations); - field_to_json(Obj,"snapshot",snapshot); - field_to_json(Obj,"numberOfDevices",numberOfDevices); - } - - void Dashboard::reset() { - commands.clear(); - upTimes.clear(); - memoryUsed.clear(); - load1.clear(); - load5.clear(); - load15.clear(); - vendors.clear(); - status.clear(); - deviceType.clear(); - healths.clear(); - certificates.clear(); - lastContact.clear(); - associations.clear(); - numberOfDevices = 0 ; - snapshot = std::time(nullptr); - } - - void CapabilitiesModel::to_json(Poco::JSON::Object &Obj) const{ - field_to_json(Obj,"deviceType", deviceType); - field_to_json(Obj,"capabilities", capabilities); - }; - -} - diff --git a/RESTAPI_GWobjects.h b/RESTAPI_GWobjects.h deleted file mode 100644 index 187f7ec..0000000 --- a/RESTAPI_GWobjects.h +++ /dev/null @@ -1,202 +0,0 @@ -// -// License type: BSD 3-Clause License -// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE -// -// Created by Stephane Bourque on 2021-03-04. -// Arilia Wireless Inc. -// - -#pragma once - -#include "Poco/JSON/Object.h" -#include "RESTAPI_SecurityObjects.h" - -namespace OpenWifi::GWObjects { - - enum CertificateValidation { - NO_CERTIFICATE, - VALID_CERTIFICATE, - MISMATCH_SERIAL, - VERIFIED - }; - - struct ConnectionState { - uint64_t MessageCount = 0 ; - std::string Address; - uint64_t UUID = 0 ; - uint64_t PendingUUID = 0 ; - uint64_t TX = 0, RX = 0; - uint64_t Associations_2G=0; - uint64_t Associations_5G=0; - bool Connected = false; - uint64_t LastContact=0; - std::string Firmware; - CertificateValidation VerifiedCertificate = NO_CERTIFICATE; - std::string Compatible; - uint64_t kafkaClients=0; - uint64_t webSocketClients=0; - uint64_t kafkaPackets=0; - uint64_t websocketPackets=0; - std::string locale; - void to_json(Poco::JSON::Object &Obj) const; - }; - - struct Device { - std::string SerialNumber; - std::string DeviceType; - std::string MACAddress; - std::string Manufacturer; - std::string Configuration; - SecurityObjects::NoteInfoVec Notes; - std::string Owner; - std::string Location; - std::string Firmware; - std::string Compatible; - std::string FWUpdatePolicy; - uint64_t UUID = 0 ; - uint64_t CreationTimestamp = 0 ; - uint64_t LastConfigurationChange = 0 ; - uint64_t LastConfigurationDownload = 0 ; - uint64_t LastFWUpdate = 0 ; - std::string Venue; - std::string DevicePassword; - std::string subscriber; - std::string entity; - uint64_t modified=0; - std::string locale; - - void to_json(Poco::JSON::Object &Obj) const; - void to_json_with_status(Poco::JSON::Object &Obj) const; - bool from_json(const Poco::JSON::Object::Ptr &Obj); - void Print() const; - }; - - struct Statistics { - std::string SerialNumber; - uint64_t UUID = 0 ; - std::string Data; - uint64_t Recorded = 0; - void to_json(Poco::JSON::Object &Obj) const; - }; - - struct HealthCheck { - std::string SerialNumber; - uint64_t UUID = 0 ; - std::string Data; - uint64_t Recorded = 0 ; - uint64_t Sanity = 0 ; - void to_json(Poco::JSON::Object &Obj) const; - }; - - struct Capabilities { - std::string Capabilities; - uint64_t FirstUpdate = 0 ; - uint64_t LastUpdate = 0 ; - void to_json(Poco::JSON::Object &Obj) const; - }; - - struct DeviceLog { - enum Level { - LOG_EMERG = 0, /* system is unusable */ - LOG_ALERT = 1, /* action must be taken immediately */ - LOG_CRIT = 2, /* critical conditions */ - LOG_ERR = 3, /* error conditions */ - LOG_WARNING = 4, /* warning conditions */ - LOG_NOTICE = 5, /* normal but significant condition */ - LOG_INFO = 6, /* informational */ - LOG_DEBUG = 7 /* debug-level messages */ - }; - std::string SerialNumber; - std::string Log; - std::string Data; - uint64_t Severity = 0 ; - uint64_t Recorded = 0 ; - uint64_t LogType = 0 ; - uint64_t UUID = 0 ; - void to_json(Poco::JSON::Object &Obj) const; - }; - - struct DefaultConfiguration { - std::string Name; - std::string Configuration; - Types::StringVec Models; - std::string Description; - uint64_t Created; - uint64_t LastModified; - void to_json(Poco::JSON::Object &Obj) const; - bool from_json(const Poco::JSON::Object::Ptr &Obj); - }; - - struct CommandDetails { - std::string UUID; - std::string SerialNumber; - std::string Command; - std::string Status; - std::string SubmittedBy; - std::string Results; - std::string Details; - std::string ErrorText; - uint64_t Submitted = time(nullptr); - uint64_t Executed = 0; - uint64_t Completed = 0 ; - uint64_t RunAt = 0 ; - uint64_t ErrorCode = 0 ; - uint64_t Custom = 0 ; - uint64_t WaitingForFile = 0 ; - uint64_t AttachDate = 0 ; - uint64_t AttachSize = 0 ; - std::string AttachType; - double executionTime = 0.0; - void to_json(Poco::JSON::Object &Obj) const; - }; - - struct BlackListedDevice { - std::string serialNumber; - std::string reason; - std::string author; - uint64_t created; - void to_json(Poco::JSON::Object &Obj) const; - bool from_json(const Poco::JSON::Object::Ptr &Obj); - }; - - struct RttySessionDetails { - std::string SerialNumber; - std::string Server; - uint64_t Port = 0 ; - std::string Token; - uint64_t TimeOut = 0 ; - std::string ConnectionId; - uint64_t Started = 0 ; - std::string CommandUUID; - uint64_t ViewPort = 0 ; - std::string DevicePassword; - void to_json(Poco::JSON::Object &Obj) const; - }; - - struct Dashboard { - uint64_t snapshot = 0 ; - uint64_t numberOfDevices = 0 ; - Types::CountedMap commands; - Types::CountedMap upTimes; - Types::CountedMap memoryUsed; - Types::CountedMap load1; - Types::CountedMap load5; - Types::CountedMap load15; - Types::CountedMap vendors; - Types::CountedMap status; - Types::CountedMap deviceType; - Types::CountedMap healths; - Types::CountedMap certificates; - Types::CountedMap lastContact; - Types::CountedMap associations; - void to_json(Poco::JSON::Object &Obj) const; - void reset(); - }; - - struct CapabilitiesModel { - std::string deviceType; - std::string capabilities; - - void to_json(Poco::JSON::Object &Obj) const; - }; -} diff --git a/src/RESTAPI/RESTAPI_wificlienthistory_handler.cpp b/src/RESTAPI/RESTAPI_wificlienthistory_handler.cpp index 7d007e4..22df501 100644 --- a/src/RESTAPI/RESTAPI_wificlienthistory_handler.cpp +++ b/src/RESTAPI/RESTAPI_wificlienthistory_handler.cpp @@ -32,6 +32,21 @@ namespace OpenWifi { return BadRequest(RESTAPI::Errors::InvalidSerialNumber); } + auto orderBy = GetParameter("orderBy"); + if(orderBy.empty()) { + orderBy = " timestamp DESC"; + } else { + auto tokens = Poco::StringTokenizer(orderBy,":",Poco::StringTokenizer::TOK_TRIM); + if(tokens.count()!=2 || (tokens[1]!="a" && tokens[1]!="d")) { + return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); + } + if(!StorageService()->WifiClientHistoryDB().ValidFieldName(tokens[0])) { + return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); + } + orderBy = fmt::format(" {} {}",tokens[0] , tokens[1]=="a" ? "asc" : "desc"); + } + + auto fromDate = GetParameter("fromDate",0); auto endDate = GetParameter("endDate",0); @@ -51,7 +66,7 @@ namespace OpenWifi { return ReturnCountOnly(Count); } - if(StorageService()->WifiClientHistoryDB().GetRecords(QB_.Offset,QB_.Limit, Results, Where)) { + if(StorageService()->WifiClientHistoryDB().GetRecords(QB_.Offset,QB_.Limit, Results, Where, orderBy)) { return ReturnObject("entries",Results); } diff --git a/src/framework/orm.h b/src/framework/orm.h index 8559bdf..3b78430 100644 --- a/src/framework/orm.h +++ b/src/framework/orm.h @@ -208,7 +208,8 @@ namespace ORM { int Place=0; for(const auto &i:Fields) { - FieldNames_[i.Name] = Place; + std::string FieldName = Poco::toLower(i.Name); + FieldNames_[FieldName] = Place; if(!first) { CreateFields_ += ", "; SelectFields_ += ", "; @@ -218,9 +219,9 @@ namespace ORM { SelectList_ += "("; } - CreateFields_ += i.Name + " " + FieldTypeToChar(Type_, i.Type,i.Size) + (i.Index ? " unique primary key" : ""); - SelectFields_ += i.Name ; - UpdateFields_ += i.Name + "=?"; + CreateFields_ += FieldName + " " + FieldTypeToChar(Type_, i.Type,i.Size) + (i.Index ? " unique primary key" : ""); + SelectFields_ += FieldName ; + UpdateFields_ += FieldName + "=?"; SelectList_ += "?"; first = false; Place++; @@ -235,12 +236,13 @@ namespace ORM { IndexLine = std::string("CREATE INDEX IF NOT EXISTS ") + j.Name + std::string(" ON ") + TableName_+ " ("; bool first_entry=true; for(const auto &k:j.Entries) { - assert(FieldNames_.find(k.FieldName) != FieldNames_.end()); + auto IndexFieldName = Poco::toLower(k.FieldName); + assert(ValidFieldName(IndexFieldName)); if(!first_entry) { IndexLine += " , "; } first_entry = false; - IndexLine += k.FieldName + std::string(" ") + std::string(k.Type == Indextype::ASC ? "ASC" : "DESC") ; + IndexLine += IndexFieldName + std::string(" ") + std::string(k.Type == Indextype::ASC ? "ASC" : "DESC") ; } IndexLine += " )"; IndexCreation_.template emplace_back(IndexLine); @@ -255,12 +257,13 @@ namespace ORM { IndexLine += " INDEX " + j.Name + " ( " ; bool first_entry=true; for(const auto &k:j.Entries) { - assert(FieldNames_.find(k.FieldName) != FieldNames_.end()); + auto IndexFieldName = Poco::toLower(k.FieldName); + assert(FieldNames_.find(IndexFieldName) != FieldNames_.end()); if(!first_entry) { IndexLine += " ,"; } first_entry = false; - IndexLine += k.FieldName + std::string(k.Type == Indextype::ASC ? " ASC" : " DESC"); + IndexLine += IndexFieldName + std::string(k.Type == Indextype::ASC ? " ASC" : " DESC"); } IndexLine += " ) "; } @@ -275,27 +278,27 @@ namespace ORM { [[nodiscard]] const std::string & UpdateFields() const { return UpdateFields_; }; inline std::string OP(field_name_t F, SqlComparison O , bool V) { - assert( FieldNames_.find(F) != FieldNames_.end() ); + assert(ValidFieldName(F)); return std::string{"("} + F + SQLCOMPS[O] + (V ? "true" : "false") + ")" ; } inline std::string OP(field_name_t F, SqlComparison O , int V) { - assert( FieldNames_.find(F) != FieldNames_.end() ); + assert(ValidFieldName(F)); return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ; } inline std::string OP(field_name_t F, SqlComparison O , uint64_t V) { - assert( FieldNames_.find(F) != FieldNames_.end() ); + assert(ValidFieldName(F)); return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ; } std::string OP(field_name_t F, SqlComparison O , const std::string & V) { - assert( FieldNames_.find(F) != FieldNames_.end() ); + assert(ValidFieldName(F)); return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ; } std::string OP(field_name_t F, SqlComparison O , const char * V) { - assert( FieldNames_.find(F) != FieldNames_.end() ); + assert(ValidFieldName(F)); return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ; } @@ -417,7 +420,7 @@ namespace ORM { template bool GetRecord(field_name_t FieldName, const T & Value, RecordType & R) { try { - assert( FieldNames_.find(FieldName) != FieldNames_.end() ); + assert(ValidFieldName(FieldName)); if(Cache_) { if(Cache_->GetFromCache(FieldName, Value, R)) @@ -455,7 +458,7 @@ namespace ORM { typename T0, typename T1> bool GR(field_name_t FieldName, T & R,T0 &V0, T1 &V1) { try { - assert( FieldNames_.find(FieldName) != FieldNames_.end() ); + assert( ValidFieldName(FieldName) ); Poco::Data::Session Session = Pool_.get(); Poco::Data::Statement Select(Session); @@ -513,7 +516,7 @@ namespace ORM { template bool UpdateRecord(field_name_t FieldName, const T & Value, const RecordType & R) { try { - assert( FieldNames_.find(FieldName) != FieldNames_.end() ); + assert( ValidFieldName(FieldName) ); Poco::Data::Session Session = Pool_.get(); Poco::Data::Statement Update(Session); @@ -567,7 +570,7 @@ namespace ORM { template bool GetNameAndDescription(field_name_t FieldName, const T & Value, std::string & Name, std::string & Description ) { try { - assert( FieldNames_.find(FieldName) != FieldNames_.end() ); + assert( ValidFieldName(FieldName) ); Poco::Data::Session Session = Pool_.get(); Poco::Data::Statement Select(Session); RecordTuple RT; @@ -594,7 +597,7 @@ namespace ORM { template bool DeleteRecord(field_name_t FieldName, const T & Value) { try { - assert( FieldNames_.find(FieldName) != FieldNames_.end() ); + assert( ValidFieldName(FieldName) ); Poco::Data::Session Session = Pool_.get(); Poco::Data::Statement Delete(Session); @@ -632,7 +635,7 @@ namespace ORM { bool Exists(field_name_t FieldName, const std::string & Value) { try { - assert( FieldNames_.find(FieldName) != FieldNames_.end() ); + assert( ValidFieldName(FieldName) ); RecordType R; if(GetRecord(FieldName,Value,R)) @@ -721,7 +724,7 @@ namespace ORM { template bool ManipulateVectorMember( X T, field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID, bool Add) { try { - assert( FieldNames_.find(FieldName) != FieldNames_.end() ); + assert( ValidFieldName(FieldName) ); RecordType R; if(GetRecord(FieldName, ParentUUID, R)) { @@ -870,6 +873,15 @@ namespace ORM { return false; } + inline bool ValidFieldName(const std::string &FieldName) { + return FieldNames_.find(Poco::toLower(FieldName)) != FieldNames_.end(); + } + + inline bool ValidFieldName(const char *FieldName) { + std::string Field{FieldName}; + return ValidFieldName(Field); + } + [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { if(From<1) From=0; switch(Type_) {