in src/Core/Resolvers/SqlPaginationUtil.cs [84:168]
private static JsonObject CreatePaginationConnection(JsonElement root, PaginationMetadata paginationMetadata, GroupByMetadata? groupByMetadata = null)
{
// Maintains the connection JSON object *Connection
JsonObject connection = new();
// in dw we wrap array with "" and hence jsonValueKind is string instead of array.
if (root.ValueKind is JsonValueKind.String)
{
using JsonDocument document = JsonDocument.Parse(root.GetString()!);
root = document.RootElement.Clone();
}
// If the request includes either hasNextPage or endCursor then to correctly return those
// values we need to determine the correct pagination logic
bool isPaginationRequested = paginationMetadata.RequestedHasNextPage || paginationMetadata.RequestedEndCursor;
IEnumerable<JsonElement> rootEnumerated = root.EnumerateArray();
int returnedElementCount = rootEnumerated.Count();
bool hasExtraElement = false;
if (isPaginationRequested)
{
// structure.Limit() is first + 1 for paginated queries where hasNextPage or endCursor is requested
hasExtraElement = returnedElementCount == paginationMetadata.Structure!.Limit();
if (hasExtraElement)
{
// In a pagination scenario where we have an extra element, this element
// must be removed since it was only used to determine if there are additional
// records after those requested.
rootEnumerated = rootEnumerated.Take(rootEnumerated.Count() - 1);
--returnedElementCount;
}
}
if (paginationMetadata.RequestedHasNextPage)
{
// add hasNextPage to connection elements
connection.Add(QueryBuilder.HAS_NEXT_PAGE_FIELD_NAME, hasExtraElement);
}
if (paginationMetadata.RequestedItems)
{
if (hasExtraElement)
{
// use rootEnumerated to make the *Connection.items since the last element of rootEnumerated
// is removed if the result has an extra element
connection.Add(QueryBuilder.PAGINATION_FIELD_NAME, JsonSerializer.Serialize(rootEnumerated.ToArray()));
}
else
{
// if the result doesn't have an extra element, just return the dbResult for *Connection.items
connection.Add(QueryBuilder.PAGINATION_FIELD_NAME, root.ToString()!);
}
}
if (groupByMetadata is not null && paginationMetadata.RequestedGroupBy == true)
{
connection.Add(QueryBuilder.GROUP_BY_FIELD_NAME, GenerateGroupByObjectFromResult(groupByMetadata, rootEnumerated));
}
if (paginationMetadata.RequestedEndCursor)
{
// Note: if we do not add endCursor to the connection but it was in the request, its value will
// automatically be populated as null.
// Need to validate we have an extra element, because otherwise there is no next page
// and endCursor should be left as null.
if (returnedElementCount > 0 && hasExtraElement)
{
JsonElement lastElemInRoot = rootEnumerated.ElementAtOrDefault(returnedElementCount - 1);
connection.Add(QueryBuilder.PAGINATION_TOKEN_FIELD_NAME,
MakeCursorFromJsonElement(
lastElemInRoot,
paginationMetadata.Structure!.PrimaryKey(),
paginationMetadata.Structure!.OrderByColumns,
paginationMetadata.Structure!.EntityName,
paginationMetadata.Structure!.DatabaseObject.SchemaName,
paginationMetadata.Structure!.DatabaseObject.Name,
paginationMetadata.Structure!.MetadataProvider,
paginationMetadata.RequestedGroupBy));
}
}
return connection;
}