Skip to content

Commit

Permalink
Merge pull request #3994 from Anjali-NEC/issue1492
Browse files Browse the repository at this point in the history
Fix using limit=0 and details=on to get only the count of elements #1492
  • Loading branch information
fgalan authored Apr 27, 2022
2 parents 2c54398 + e779cb2 commit c20bd31
Show file tree
Hide file tree
Showing 12 changed files with 707 additions and 62 deletions.
1 change: 1 addition & 0 deletions CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
- Fix: allow limit=0 in all paginated operations in the NGSIv2 API (entities, entity types, subscriptions and registrations) (#1492)
- Add: conditions.alterationTypes subscription fuctionality (#1494)
- Reference distribution changed RHEL/CentOS 8 to Debian 11
66 changes: 34 additions & 32 deletions src/lib/mongoBackend/MongoGlobal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1560,51 +1560,53 @@ bool entitiesQuery
int errType;
std::string nextErr;

while (cursor.next(&r, &errType, &nextErr))
if (limit != 0)
{
alarmMgr.dbErrorReset();

// Build CER from BSON retrieved from DB
docs++;
LM_T(LmtMongo, ("retrieved document [%d]: '%s'", docs, r.toString().c_str()));
ContextElementResponse* cer = new ContextElementResponse(r, attrL, includeEmpty, apiVersion);

// Add builtin attributes and metadata (only in NGSIv2)
if (apiVersion == V2)
while (cursor.next(&r, &errType, &nextErr))
{
addBuiltins(cer);
}
alarmMgr.dbErrorReset();

/* All the attributes existing in the request but not found in the response are added with 'found' set to false */
for (unsigned int ix = 0; ix < attrL.size(); ++ix)
{
bool found = false;
std::string attrName = attrL[ix];
// Build CER from BSON retrieved from DB
docs++;
LM_T(LmtMongo, ("retrieved document [%d]: '%s'", docs, r.toString().c_str()));
ContextElementResponse* cer = new ContextElementResponse(r, attrL, includeEmpty, apiVersion);

/* The special case "*" is not taken into account*/
if (attrName == ALL_ATTRS)
// Add builtin attributes and metadata (only in NGSIv2)
if (apiVersion == V2)
{
continue;
addBuiltins(cer);
}

for (unsigned int jx = 0; jx < cer->entity.attributeVector.size(); ++jx)
/* All the attributes existing in the request but not found in the response are added with 'found' set to false */
for (unsigned int ix = 0; ix < attrL.size(); ++ix)
{
if (attrName == cer->entity.attributeVector[jx]->name)
bool found = false;
std::string attrName = attrL[ix];

/* The special case "*" is not taken into account*/
if (attrName == ALL_ATTRS)
{
continue;
}

for (unsigned int jx = 0; jx < cer->entity.attributeVector.size(); ++jx)
{
found = true;
break;
if (attrName == cer->entity.attributeVector[jx]->name)
{
found = true;
break;
}
}
}

if (!found)
{
ContextAttribute* caP = new ContextAttribute(attrName, "", "", false);
cer->entity.attributeVector.push_back(caP);
if (!found)
{
ContextAttribute* caP = new ContextAttribute(attrName, "", "", false);
cer->entity.attributeVector.push_back(caP);
}
}
cer->statusCode.fill(SccOk);
cerV->push_back(cer);
}

cer->statusCode.fill(SccOk);
cerV->push_back(cer);
}

orion::releaseMongoConnection(connection);
Expand Down
26 changes: 14 additions & 12 deletions src/lib/mongoBackend/mongoGetSubscriptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,23 +338,25 @@ void mongoListSubscriptions
/* Process query result */
unsigned int docs = 0;

orion::BSONObj r;
while (cursor.next(&r))
if (limit != 0)
{
docs++;
LM_T(LmtMongo, ("retrieved document [%d]: '%s'", docs, r.toString().c_str()));
orion::BSONObj r;
while (cursor.next(&r))
{
docs++;
LM_T(LmtMongo, ("retrieved document [%d]: '%s'", docs, r.toString().c_str()));

Subscription s;
Subscription s;

setNewSubscriptionId(&s, r);
setDescription(&s, r);
setSubject(&s, r);
setStatus(&s, r, tenant);
setNotification(&s, r, tenant);
setNewSubscriptionId(&s, r);
setDescription(&s, r);
setSubject(&s, r);
setStatus(&s, r, tenant);
setNotification(&s, r, tenant);

subs->push_back(s);
subs->push_back(s);
}
}

orion::releaseMongoConnection(connection);
reqSemGive(__FUNCTION__, "Mongo List Subscriptions", reqSemTaken);

Expand Down
1 change: 0 additions & 1 deletion src/lib/mongoBackend/mongoQueryContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,6 @@ HttpStatusCode mongoQueryContext
countP,
sortOrderList,
apiVersion);

if (!ok)
{
responseP->errorCode.fill(SccReceiverInternalError, err);
Expand Down
7 changes: 5 additions & 2 deletions src/lib/mongoBackend/mongoQueryTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,9 +627,12 @@ HttpStatusCode mongoEntityTypes
entityType->contextAttributeVector.push_back(caP);
}
}

responseP->entityTypeVector.push_back(entityType);
if (limit != 0)
{
responseP->entityTypeVector.push_back(entityType);
}
}

orion::releaseMongoConnection(connection);

// Get count if user requested (i.e. if totalTypesP is not NULL)
Expand Down
5 changes: 4 additions & 1 deletion src/lib/mongoBackend/mongoRegistrationGet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,10 @@ void mongoRegistrationsGet
setExpires(&reg, r);
setStatus(&reg, r);

regV->push_back(reg);
if (limit != 0)
{
regV->push_back(reg);
}
}

orion::releaseMongoConnection(connection);
Expand Down
9 changes: 1 addition & 8 deletions src/lib/rest/rest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ static int uriArgumentGet(void* cbDataP, MHD_ValueKind kind, const char* ckey, c
{
if ((*cP < '0') || (*cP > '9'))
{
OrionError error(SccBadRequest, std::string("Bad pagination limit: /") + value + "/ [must be a decimal number]");
OrionError error(SccBadRequest, std::string("Bad pagination limit: /") + value + "/ [must be a positive integer number]");
ciP->httpStatusCode = error.code;
ciP->answer = error.smartRender(ciP->apiVersion);
return MHD_YES;
Expand All @@ -175,13 +175,6 @@ static int uriArgumentGet(void* cbDataP, MHD_ValueKind kind, const char* ckey, c
ciP->answer = error.smartRender(ciP->apiVersion);
return MHD_YES;
}
else if (limit == 0)
{
OrionError error(SccBadRequest, std::string("Bad pagination limit: /") + value + "/ [a value of ZERO is unacceptable]");
ciP->httpStatusCode = error.code;
ciP->answer = error.smartRender(ciP->apiVersion);
return MHD_YES;
}
}
else if (key == URI_PARAM_PAGINATION_DETAILS)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ echo
--REGEXPECT--
+++++ 1. bad characters in URI param 'limit'
HTTP/1.1 400 Bad Request
Content-Length: 125
Content-Length: 134
Content-Type: application/json
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Date: REGEX(.*)

{
"orionError": {
"code": "400",
"details": "Bad pagination limit: /abc/ [must be a decimal number]",
"details": "Bad pagination limit: /abc/ [must be a positive integer number]",
"reasonPhrase": "Bad Request"
}
}
Expand All @@ -93,16 +93,16 @@ Date: REGEX(.*)


+++++ 3. URI param 'limit' == 0
HTTP/1.1 400 Bad Request
Content-Length: 135
HTTP/1.1 200 OK
Content-Length: 86
Content-Type: application/json
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Date: REGEX(.*)

{
"orionError": {
"errorCode": {
"code": "400",
"details": "Bad pagination limit: /000000/ [a value of ZERO is unacceptable]",
"details": "JSON Parse Error",
"reasonPhrase": "Bad Request"
}
}
Expand Down
142 changes: 142 additions & 0 deletions test/functionalTest/cases/1492_limit_zero/limit_zero_entities.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Copyright 2021 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--
limit_zero_entities

--SHELL-INIT--
dbInit CB
brokerStart CB

--SHELL--

#
# 01. GET /v2/entities with 'limit' == 0 and options=count and see no entities and fiware-total-count: 0
# 02. POST /v2/entities to create E1 entity
# 03. POST /v2/entities to create E2 entity
# 04. GET /v2/entities with 'limit' == 0 and options=count and see no entities and fiware-total-count: 2
# 05. GET /v2/entities with 'limit' == 0 and see no entities
#

echo "01. GET /v2/entities with 'limit' == 0 and options=count and see no entities and fiware-total-count: 0"
echo "======================================================================================================"
orionCurl --url "/v2/entities?limit=0&options=count"
echo
echo


echo "02. POST /v2/entities to create E1 entity"
echo "========================================="
payload='{
"id": "E1",
"type": "T"
}'
orionCurl --url /v2/entities -X POST --payload "$payload"
echo
echo


echo "03. POST /v2/entities to create E2 entity"
echo "========================================="
payload='{
"id": "E2",
"type": "T"
}'
orionCurl --url /v2/entities -X POST --payload "$payload"
echo
echo


echo "04. GET /v2/entities with 'limit' == 0 and options=count and see no entities and fiware-total-count: 2"
echo "======================================================================================================"
orionCurl --url "/v2/entities?limit=0&options=count"
echo
echo


echo "05. GET /v2/entities with 'limit' == 0 and see no entities"
echo "=========================================================="
orionCurl --url "/v2/entities?limit=0"
echo
echo



--REGEXPECT--
01. GET /v2/entities with 'limit' == 0 and options=count and see no entities and fiware-total-count: 0
======================================================================================================
HTTP/1.1 200 OK
Content-Length: 2
Content-Type: application/json
Fiware-Total-Count: 0
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Date: REGEX(.*)

[]


02. POST /v2/entities to create E1 entity
=========================================
HTTP/1.1 201 Created
Content-Length: 0
Location: /v2/entities/E1?type=T
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Date: REGEX(.*)



03. POST /v2/entities to create E2 entity
=========================================
HTTP/1.1 201 Created
Content-Length: 0
Location: /v2/entities/E2?type=T
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Date: REGEX(.*)



04. GET /v2/entities with 'limit' == 0 and options=count and see no entities and fiware-total-count: 2
======================================================================================================
HTTP/1.1 200 OK
Content-Length: 2
Content-Type: application/json
Fiware-Total-Count: 2
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Date: REGEX(.*)

[]


05. GET /v2/entities with 'limit' == 0 and see no entities
==========================================================
HTTP/1.1 200 OK
Content-Length: 2
Content-Type: application/json
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Date: REGEX(.*)

[]


--TEARDOWN--
brokerStop CB
dbDrop CB
Loading

0 comments on commit c20bd31

Please sign in to comment.