Skip to content

Commit

Permalink
Fixed another bson array index problem
Browse files Browse the repository at this point in the history
  • Loading branch information
kzangeli committed Sep 5, 2023
1 parent 23be467 commit 51d27f3
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 1 deletion.
11 changes: 11 additions & 0 deletions src/lib/orionld/mongoc/mongocEntityUpdate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ extern "C"

#include "orionld/common/orionldState.h" // orionldState
#include "orionld/common/dotForEq.h" // dotForEq
#include "orionld/mongoc/mongocWriteLog.h" // MONGOC_WLOG
#include "orionld/mongoc/mongocConnectionGet.h" // mongocConnectionGet
#include "orionld/mongoc/mongocKjTreeToBson.h" // mongocKjTreeToBson
#include "orionld/mongoc/mongocIndexString.h" // mongocIndexString
Expand Down Expand Up @@ -100,6 +101,7 @@ static void mongocKjTreeToUpdateBson
if (isValue)
{
bson_t compound;
LM_T(LmtMongoc, ("Member '%s' has a value that is a compound object - calling mongocKjTreeToBson", subAttrP->name));
mongocKjTreeToBson(subAttrP, &compound);
bson_append_document(setP, path, pathLen, &compound);
}
Expand All @@ -108,6 +110,7 @@ static void mongocKjTreeToUpdateBson
int bsonPathLen = strlen(bsonPath) + 1 + strlen(attrP->name) + 1;
char* bsonPath2 = kaAlloc(&orionldState.kalloc, bsonPathLen);

LM_T(LmtMongoc, ("Member '%s' has a value that is a simple value - calling mongocKjTreeToUpdateBson", subAttrP->name));
snprintf(bsonPath2, bsonPathLen, "%s.%s", bsonPath, attrP->name);
mongocKjTreeToUpdateBson(subAttrP, setP, unsetP, bsonPath2, NULL, NULL, NULL, level + 1); // Perhaps another function for sub-attributes ...?
}
Expand All @@ -118,9 +121,12 @@ static void mongocKjTreeToUpdateBson
{
bson_t compound;

LM_T(LmtMongoc, ("Array member '%s' is a compound object - calling mongocKjTreeToBson", subAttrP->name));
mongocKjTreeToBson(subAttrP, &compound);
bson_append_array(setP, path, pathLen, &compound);
}
else
LM_T(LmtMongoc, ("Wait, what???"));
}

++jx;
Expand Down Expand Up @@ -210,6 +216,7 @@ static bool patchApply
char buf[16];
int bufLen = mongocIndexString(ix, buf);

LM_T(LmtMongoc, ("Array Index: '%s'", buf));
bson_append_utf8(&commaArrayBson, buf, bufLen, itemNameP->value.s, -1);
++ix;
}
Expand All @@ -235,12 +242,15 @@ static bool patchApply
else if (tree->type == KjBoolean) bson_append_bool(setP, path, -1, tree->value.b);
else if (tree->type == KjArray)
{
LM_T(LmtMongoc, ("'%s' is an Array - calling mongocKjTreeToBson", tree->name));
kjTreeLog(tree, "TREE", LmtMongoc);
mongocKjTreeToBson(tree, &compound);
bson_append_array(setP, path, -1, &compound);
bson_destroy(&compound);
}
else if (tree->type == KjObject)
{
LM_T(LmtMongoc, ("'%s' is an Object - calling mongocKjTreeToBson", tree->name));
mongocKjTreeToBson(tree, &compound);
bson_append_document(setP, path, -1, &compound);
bson_destroy(&compound);
Expand Down Expand Up @@ -294,6 +304,7 @@ bool mongocEntityUpdate(const char* entityId, KjNode* patchTree)
if (pulls > 0) bson_append_document(&request, "$pull", 5, &pull);
if (pushes > 0) bson_append_document(&request, "$push", 5, &push);

MONGOC_WLOG("PATCH Entity", orionldState.tenantP->mongoDbName, "entities", &selector, &request, LmtMongoc);
bool b = mongoc_collection_update_one(orionldState.mongoc.entitiesP, &selector, &request, NULL, &reply, &orionldState.mongoc.error);
if (b == false)
{
Expand Down
9 changes: 8 additions & 1 deletion src/lib/orionld/mongoc/mongocKjTreeToBson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ static void kjTreeToBson(KjNode* nodeP, bson_t* parentP, bool inArray, int array
{
slen = snprintf(nameBuf, sizeof(nameBuf), "%d", arrayIndex);
name = nameBuf;
LM_T(LmtMongoc, ("Array Index: '%s'", name));
}
else
{
name = nodeP->name;
slen = strlen(name);
LM_T(LmtMongoc, ("Name: '%s'", name));
}

if (nodeP->type == KjString) bson_append_utf8(parentP, name, slen, nodeP->value.s, -1);
Expand All @@ -75,6 +77,7 @@ static void kjTreeToBson(KjNode* nodeP, bson_t* parentP, bool inArray, int array

for (KjNode* itemP = nodeP->value.firstChildP; itemP != NULL; itemP = itemP->next)
{
LM_T(LmtMongoc, ("Calling kjTreeToBson for item '%s' of container '%s'", itemP->name, nodeP->name));
kjTreeToBson(itemP, &bObject, false);
}
bson_append_document_end(parentP, &bObject);
Expand All @@ -88,6 +91,7 @@ static void kjTreeToBson(KjNode* nodeP, bson_t* parentP, bool inArray, int array
bson_append_array_begin(parentP, name, slen, &bArray);
for (KjNode* itemP = nodeP->value.firstChildP; itemP != NULL; itemP = itemP->next)
{
LM_T(LmtMongoc, ("Calling kjTreeToBson for array item %d of '%s'", arrayIndex, nodeP->name));
kjTreeToBson(itemP, &bArray, true, arrayIndex);
arrayIndex += 1;
}
Expand All @@ -108,8 +112,11 @@ void mongocKjTreeToBson(KjNode* treeP, bson_t* bsonP)

bson_init(bsonP);

int arrayIx = 0;
for (KjNode* itemP = treeP->value.firstChildP; itemP != NULL; itemP = itemP->next)
{
kjTreeToBson(itemP, bsonP, inArray);
LM_T(LmtMongoc, ("Calling kjTreeToBson for '%s' of '%s'", itemP->name, treeP->name));
kjTreeToBson(itemP, bsonP, inArray, arrayIx);
++arrayIx;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Copyright 2023 FIWARE Foundation e.V.
#
# This file is part of Orion-LD Context Broker.
#
# Orion-LD 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-LD 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-LD Context Broker. If not, see http://www.gnu.org/licenses/.
#
# For those usages not covered by this license please contact with
# orionld at fiware dot org

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

--NAME--
Entity Patch using Smart Input Format

--SHELL-INIT--
dbInit CB
orionldStart CB -experimental

--SHELL--

#
# 01. Create an entity 'urn:E1' with a Relationship 'occupier' whose object is an array of one item
# 02. GET 'urn:E1'
# 03. PATCH entity 'urn:E1', making 'occupier' have an array of two
# 04. GET the entity and see that occupier::object is an array of two items
#


echo "01. Create an entity 'urn:E1' with a Relationship 'occupier' whose object is an array of one item"
echo "================================================================================================="
payload='{
"id": "urn:E1",
"type": "T",
"occupier": {
"object": [
"urn:ngsi-ld:Person:You"
]
}
}'
orionCurl --url /ngsi-ld/v1/entities --payload "$payload"
echo
echo


echo "02. GET 'urn:E1'"
echo "================"
orionCurl --url /ngsi-ld/v1/entities/urn:E1
echo
echo


echo "03. PATCH entity 'urn:E1', making 'occupier' have an array of two"
echo "================================================================="
payload='{
"occupier": {
"object": [
"urn:ngsi-ld:Person:He",
"urn:ngsi-ld:Person:She"
]
}
}'
orionCurl --url /ngsi-ld/v1/entities/urn:E1 -X PATCH --payload "$payload"
echo
echo


echo "04. GET the entity and see that occupier::object is an array of two items"
echo "========================================================================="
orionCurl --url /ngsi-ld/v1/entities/urn:E1
echo
echo


--REGEXPECT--
01. Create an entity 'urn:E1' with a Relationship 'occupier' whose object is an array of one item
=================================================================================================
HTTP/1.1 201 Created
Content-Length: 0
Date: REGEX(.*)
Location: /ngsi-ld/v1/entities/urn:E1



02. GET 'urn:E1'
================
HTTP/1.1 200 OK
Content-Length: 97
Content-Type: application/json
Date: REGEX(.*)
Link: <https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-contextREGEX(.*)

{
"id": "urn:E1",
"occupier": {
"object": [
"urn:ngsi-ld:Person:You"
],
"type": "Relationship"
},
"type": "T"
}


03. PATCH entity 'urn:E1', making 'occupier' have an array of two
=================================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)



04. GET the entity and see that occupier::object is an array of two items
=========================================================================
HTTP/1.1 200 OK
Content-Length: 121
Content-Type: application/json
Date: REGEX(.*)
Link: <https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-contextREGEX(.*)

{
"id": "urn:E1",
"occupier": {
"object": [
"urn:ngsi-ld:Person:He",
"urn:ngsi-ld:Person:She"
],
"type": "Relationship"
},
"type": "T"
}


--TEARDOWN--
brokerStop CB
dbDrop CB

0 comments on commit 51d27f3

Please sign in to comment.