use of com.yahoo.elide.core.request.Pagination in project elide by yahoo.
the class CollectionTerminalState method handleGet.
@Override
public Supplier<Pair<Integer, JsonNode>> handleGet(StateContext state) {
JsonApiDocument jsonApiDocument = new JsonApiDocument();
RequestScope requestScope = state.getRequestScope();
MultivaluedMap<String, String> queryParams = requestScope.getQueryParams();
Set<PersistentResource> collection = getResourceCollection(requestScope).toList(LinkedHashSet::new).blockingGet();
// Set data
jsonApiDocument.setData(getData(collection, requestScope.getDictionary()));
// Run include processor
DocumentProcessor includedProcessor = new IncludedProcessor();
includedProcessor.execute(jsonApiDocument, collection, queryParams);
Pagination pagination = parentProjection.getPagination();
if (parent.isPresent()) {
pagination = parentProjection.getRelationship(relationName.orElseThrow(IllegalStateException::new)).get().getProjection().getPagination();
}
// Add pagination meta data
if (!pagination.isDefaultInstance()) {
Map<String, Number> pageMetaData = new HashMap<>();
pageMetaData.put("number", (pagination.getOffset() / pagination.getLimit()) + 1);
pageMetaData.put("limit", pagination.getLimit());
// Get total records if it has been requested and add to the page meta data
if (pagination.returnPageTotals()) {
Long totalRecords = pagination.getPageTotals();
pageMetaData.put("totalPages", totalRecords / pagination.getLimit() + ((totalRecords % pagination.getLimit()) > 0 ? 1 : 0));
pageMetaData.put("totalRecords", totalRecords);
}
Map<String, Object> allMetaData = new HashMap<>();
allMetaData.put("page", pageMetaData);
Meta meta = new Meta(allMetaData);
jsonApiDocument.setMeta(meta);
}
JsonNode responseBody = requestScope.getMapper().toJsonObject(jsonApiDocument);
return () -> Pair.of(HttpStatus.SC_OK, responseBody);
}
use of com.yahoo.elide.core.request.Pagination in project elide by yahoo.
the class SQLQueryEngine method executeQuery.
@Override
public QueryResult executeQuery(Query query, Transaction transaction) {
SqlTransaction sqlTransaction = (SqlTransaction) transaction;
ConnectionDetails details = query.getConnectionDetails();
DataSource dataSource = details.getDataSource();
SQLDialect dialect = details.getDialect();
Query expandedQuery = expandMetricQueryPlans(query);
// Translate the query into SQL.
NativeQuery sql = toSQL(expandedQuery, dialect);
String queryString = sql.toString();
QueryResult.QueryResultBuilder resultBuilder = QueryResult.builder();
NamedParamPreparedStatement stmt;
Pagination pagination = query.getPagination();
if (returnPageTotals(pagination)) {
resultBuilder.pageTotals(getPageTotal(expandedQuery, sql, query, sqlTransaction));
}
log.debug("SQL Query: " + queryString);
stmt = sqlTransaction.initializeStatement(queryString, dataSource);
// Supply the query parameters to the query
supplyFilterQueryParameters(query, stmt, dialect);
// Run the primary query and log the time spent.
ResultSet resultSet = runQuery(stmt, queryString, Function.identity());
resultBuilder.data(new EntityHydrator(resultSet, query, metadataDictionary));
return resultBuilder.build();
}
use of com.yahoo.elide.core.request.Pagination in project elide by yahoo.
the class SQLQueryEngine method explain.
/**
* Returns the actual query string(s) that would be executed for the input {@link Query}.
*
* @param query The query customized for a particular persistent storage or storage client.
* @param dialect SQL dialect to use for this storage.
* @return List of SQL string(s) corresponding to the given query.
*/
public List<String> explain(Query query, SQLDialect dialect) {
List<String> queries = new ArrayList<>();
Query expandedQuery = expandMetricQueryPlans(query);
NativeQuery sql = toSQL(expandedQuery, dialect);
Pagination pagination = query.getPagination();
if (returnPageTotals(pagination)) {
NativeQuery paginationSql = toPageTotalSQL(expandedQuery, sql, dialect);
if (paginationSql != null) {
queries.add(paginationSql.toString());
}
}
queries.add(sql.toString());
return queries;
}
use of com.yahoo.elide.core.request.Pagination in project elide by yahoo.
the class SubCollectionFetchQueryBuilderTest method testFetchJoinExcludesParent.
@Test
public void testFetchJoinExcludesParent() {
Publisher publisher = new Publisher();
publisher.setId(1);
Book book = new Book();
book.setId(2);
Pagination pagination = new PaginationImpl(Book.class, 0, 10, 10, 10, false, false);
EntityProjection entityProjection = EntityProjection.builder().type(Book.class).pagination(pagination).build();
Relationship relationshipProjection = Relationship.builder().name(BOOKS).projection(entityProjection).build();
RelationshipImpl relationship = new RelationshipImpl(ClassType.of(Publisher.class), publisher, relationshipProjection);
SubCollectionFetchQueryBuilder builder = new SubCollectionFetchQueryBuilder(relationship, dictionary, new TestSessionWrapper());
TestQueryWrapper query = (TestQueryWrapper) builder.build();
String expected = "SELECT example_Book FROM example.Publisher example_Publisher__fetch " + "JOIN example_Publisher__fetch.books example_Book " + "WHERE example_Publisher__fetch=:example_Publisher__fetch";
String actual = query.getQueryText();
actual = actual.replaceFirst(":publisher_name_\\w+", ":publisher_name_XXX");
assertEquals(expected, actual);
}
use of com.yahoo.elide.core.request.Pagination in project elide by yahoo.
the class PersistentResource method loadRecords.
/**
* Load a collection from the datastore.
*
* @param projection the projection to load
* @param requestScope the request scope
* @param ids a list of object identifiers to optionally load. Can be empty.
* @return a filtered collection of resources loaded from the datastore.
*/
public static Observable<PersistentResource> loadRecords(EntityProjection projection, List<String> ids, RequestScope requestScope) {
Type<?> loadClass = projection.getType();
Pagination pagination = projection.getPagination();
Sorting sorting = projection.getSorting();
FilterExpression filterExpression = projection.getFilterExpression();
EntityDictionary dictionary = requestScope.getDictionary();
DataStoreTransaction tx = requestScope.getTransaction();
if (shouldSkipCollection(loadClass, ReadPermission.class, requestScope, projection.getRequestedFields())) {
if (ids.isEmpty()) {
return Observable.empty();
}
throw new InvalidObjectIdentifierException(ids.toString(), dictionary.getJsonAliasFor(loadClass));
}
Set<String> requestedFields = projection.getRequestedFields();
if (pagination != null && !pagination.isDefaultInstance() && !CanPaginateVisitor.canPaginate(loadClass, dictionary, requestScope, requestedFields)) {
throw new BadRequestException(String.format("Cannot paginate %s", dictionary.getJsonAliasFor(loadClass)));
}
Set<PersistentResource> newResources = new LinkedHashSet<>();
if (!ids.isEmpty()) {
String typeAlias = dictionary.getJsonAliasFor(loadClass);
newResources = requestScope.getNewPersistentResources().stream().filter(resource -> typeAlias.equals(resource.getTypeName()) && ids.contains(resource.getUUID().orElse(""))).collect(Collectors.toSet());
FilterExpression idExpression = buildIdFilterExpression(ids, loadClass, dictionary, requestScope);
// Combine filters if necessary
filterExpression = Optional.ofNullable(filterExpression).map(fe -> (FilterExpression) new AndFilterExpression(idExpression, fe)).orElse(idExpression);
}
Optional<FilterExpression> permissionFilter = getPermissionFilterExpression(loadClass, requestScope, requestedFields);
if (permissionFilter.isPresent()) {
if (filterExpression != null) {
filterExpression = new AndFilterExpression(filterExpression, permissionFilter.get());
} else {
filterExpression = permissionFilter.get();
}
}
EntityProjection modifiedProjection = projection.copyOf().filterExpression(filterExpression).sorting(sorting).pagination(pagination).build();
Observable<PersistentResource> existingResources = filter(ReadPermission.class, Optional.ofNullable(modifiedProjection.getFilterExpression()), projection.getRequestedFields(), Observable.fromIterable(new PersistentResourceSet(tx.loadObjects(modifiedProjection, requestScope), requestScope)));
// TODO: Sort again in memory now that two sets are glommed together?
Observable<PersistentResource> allResources = Observable.fromIterable(newResources).mergeWith(existingResources);
Set<String> foundIds = new HashSet<>();
allResources = allResources.doOnNext((resource) -> {
String id = (String) resource.getUUID().orElseGet(resource::getId);
if (ids.contains(id)) {
foundIds.add(id);
}
});
allResources = allResources.doOnComplete(() -> {
Set<String> missedIds = Sets.difference(new HashSet<>(ids), foundIds);
if (!missedIds.isEmpty()) {
throw new InvalidObjectIdentifierException(missedIds.toString(), dictionary.getJsonAliasFor(loadClass));
}
});
return allResources;
}
Aggregations