Skip to content

Commit

Permalink
FIX DateTime with min and max operators
Browse files Browse the repository at this point in the history
  • Loading branch information
fgalan committed Aug 1, 2024
1 parent a37740a commit 37c7649
Show file tree
Hide file tree
Showing 6 changed files with 594 additions and 9 deletions.
3 changes: 2 additions & 1 deletion CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
- Fix: custom notification ngsi patching evaluation priority based in evalPriority builtin metadata (#4556)
- Add: custom notification ngsi patching evaluation priority based in evalPriority builtin metadata (#4556)
- Fix: $max and $min operators were not supported with DateTime attributes (#4585)
- Fix: wrong date values should not allowed in subscription's expires field (#4541)
- Fix: do not raise DB alarm in case of wrong GeoJSON in client request
- Upgrade cjexl version from 0.3.0 to 0.4.0 (new transformations: now, getTime and toIsoString)
Expand Down
3 changes: 2 additions & 1 deletion doc/manuals/orion-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1618,7 +1618,8 @@ The only exception to "use only one operator" rule is the case of `$set` and
Update operators can be used in entity creation or replace operations. In particular:

* Numeric operators takes 0 as reference. For instance, `{"$inc": 4}` results in 4,
`{$mul: 1000}` results in 0, etc.
`{"$mul": 1000}` results in 0, etc.
* Epoch time (`"1970-01-01T00:00:00Z"`) is used as reference for `DateTime` when `$min` or `$max` are used.
* `$set` takes the empty object (`{}`) as reference. For instance, `"$set": {"X": 1}` results in just `{"X": 1}`
* `$push` and `$addToSet` take the empty array (`[]`) as reference. For instance, `{"$push": 4}`
results in `[ 4 ]`.
Expand Down
40 changes: 33 additions & 7 deletions src/lib/jsonParseV2/parseContextAttribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,42 @@ static std::string parseContextAttributeObject
// Is it a (not null) date?
if (checkAttrSpecialTypes && ((caP->type == DATE_TYPE) || (caP->type == DATE_TYPE_ALT)) && (caP->valueType != orion::ValueTypeNull))
{
caP->numberValue = parse8601Time(caP->stringValue);

if (caP->numberValue == -1)
if (caP->valueType == orion::ValueTypeObject)
{
return "date has invalid format";
// check if $max or $min operators are being used. Other usages of object values result in parsing error
if ((caP->compoundValueP != NULL) && (caP->compoundValueP->valueType == orion::ValueTypeObject)
&& (caP->compoundValueP->childV.size() == 1) && ((caP->compoundValueP->childV[0]->name == "$max") || (caP->compoundValueP->childV[0]->name == "$min")))
{
orion::CompoundValueNode* upOp = caP->compoundValueP->childV[0];
upOp->numberValue = parse8601Time(upOp->stringValue);

if (upOp->numberValue == -1)
{
return "date has invalid format";
}

// Probably reseting stringValue is not needed, but let's do it for cleanliness
upOp->stringValue = "";
upOp->valueType = orion::ValueTypeNumber;
}
else
{
return "date has invalid format";
}
}
else
{
caP->numberValue = parse8601Time(caP->stringValue);

if (caP->numberValue == -1)
{
return "date has invalid format";
}

// Probably reseting stringValue is not needed, but let's do it for cleanliness
caP->stringValue = "";
caP->valueType = orion::ValueTypeNumber;
// Probably reseting stringValue is not needed, but let's do it for cleanliness
caP->stringValue = "";
caP->valueType = orion::ValueTypeNumber;
}
}

// It is a safe GeoJSON?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
# Copyright 2024 Telefonica Investigacion y Desarrollo, S.A.U
#
# This file is part of Orion Context Broker.
#
# Orion Context Broker is free software: you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# Orion Context Broker is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
# General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/.
#
# For those usages not covered by this license please contact with
# iot_support at tid dot es

# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh

--NAME--
DateTime with min and max operators

--SHELL-INIT--
dbInit CB
brokerStart CB

--SHELL--

#
# 01. Create entity E1 with DateTime T=2024-04-15T10:59:59.000Z
# 02. Update entity with {$min: 2025-04-15T10:59:59.000Z}
# 03. Get entity see T=2024-04-15T10:59:59.000Z
# 04. Update entity with {$min: 2023-04-15T10:59:59.000Z}
# 05. Get entity see T=2023-04-15T10:59:59.000Z
# 06. Update entity with {$max: 2022-04-15T10:59:59.000Z}
# 07. Get entity see T=2023-04-15T10:59:59.000Z
# 08. Update entity with {$max: 2026-04-15T10:59:59.000Z}
# 09. Get entity see T=2026-04-15T10:59:59.000Z
#


echo '01. Create entity E1 with DateTime T=2024-04-15T10:59:59.000Z'
echo '============================================================='
payload='{
"id": "E1",
"type": "T",
"T": {
"value": "2024-04-15T10:59:59.000Z",
"type": "DateTime"
}
}'
orionCurl --url /v2/entities --payload "$payload"
echo
echo


echo '02. Update entity with {$min: 2025-04-15T10:59:59.000Z}'
echo "======================================================="
payload='{
"T": {
"value": {"$min": "2025-04-15T10:59:59.000Z"},
"type": "DateTime"
}
}'
orionCurl --url /v2/entities/E1/attrs --payload "$payload" -X PATCH
echo
echo


echo "03. Get entity see T=2024-04-15T10:59:59.000Z"
echo "============================================="
orionCurl --url /v2/entities/E1/attrs
echo
echo


echo '04. Update entity with {$min: 2023-04-15T10:59:59.000Z}'
echo "======================================================="
payload='{
"T": {
"value": {"$min": "2023-04-15T10:59:59.000Z"},
"type": "DateTime"
}
}'
orionCurl --url /v2/entities/E1/attrs --payload "$payload" -X PATCH
echo
echo


echo "05. Get entity see T=2023-04-15T10:59:59.000Z"
echo "============================================="
orionCurl --url /v2/entities/E1/attrs
echo
echo


echo '06. Update entity with {$max: 2022-04-15T10:59:59.000Z}'
echo "======================================================="
payload='{
"T": {
"value": {"$max": "2022-04-15T10:59:59.000Z"},
"type": "DateTime"
}
}'
orionCurl --url /v2/entities/E1/attrs --payload "$payload" -X PATCH
echo
echo


echo "07. Get entity see T=2023-04-15T10:59:59.000Z"
echo "============================================="
orionCurl --url /v2/entities/E1/attrs
echo
echo


echo '08. Update entity with {$max: 2026-04-15T10:59:59.000Z}'
echo "======================================================="
payload='{
"T": {
"value": {"$max": "2026-04-15T10:59:59.000Z"},
"type": "DateTime"
}
}'
orionCurl --url /v2/entities/E1/attrs --payload "$payload" -X PATCH
echo
echo


echo "09. Get entity see T=2026-04-15T10:59:59.000Z"
echo "============================================="
orionCurl --url /v2/entities/E1/attrs
echo
echo


--REGEXPECT--
01. Create entity E1 with DateTime T=2024-04-15T10:59:59.000Z
=============================================================
HTTP/1.1 201 Created
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Location: /v2/entities/E1?type=T
Content-Length: 0



02. Update entity with {$min: 2025-04-15T10:59:59.000Z}
=======================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})



03. Get entity see T=2024-04-15T10:59:59.000Z
=============================================
HTTP/1.1 200 OK
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Content-Type: application/json
Content-Length: 74

{
"T": {
"metadata": {},
"type": "DateTime",
"value": "2024-04-15T10:59:59.000Z"
}
}


04. Update entity with {$min: 2023-04-15T10:59:59.000Z}
=======================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})



05. Get entity see T=2023-04-15T10:59:59.000Z
=============================================
HTTP/1.1 200 OK
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Content-Type: application/json
Content-Length: 74

{
"T": {
"metadata": {},
"type": "DateTime",
"value": "2023-04-15T10:59:59.000Z"
}
}


06. Update entity with {$max: 2022-04-15T10:59:59.000Z}
=======================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})



07. Get entity see T=2023-04-15T10:59:59.000Z
=============================================
HTTP/1.1 200 OK
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Content-Type: application/json
Content-Length: 74

{
"T": {
"metadata": {},
"type": "DateTime",
"value": "2023-04-15T10:59:59.000Z"
}
}


08. Update entity with {$max: 2026-04-15T10:59:59.000Z}
=======================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})



09. Get entity see T=2026-04-15T10:59:59.000Z
=============================================
HTTP/1.1 200 OK
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Content-Type: application/json
Content-Length: 74

{
"T": {
"metadata": {},
"type": "DateTime",
"value": "2026-04-15T10:59:59.000Z"
}
}


--TEARDOWN--
brokerStop CB
dbDrop CB
Loading

0 comments on commit 37c7649

Please sign in to comment.