Search in sources :

Example 1 with QueryResult

use of io.micronaut.data.model.query.builder.QueryResult in project micronaut-data by micronaut-projects.

the class AbstractSqlRepositoryOperations method resolveEntityUpdate.

/**
 * Resolves a stored update for the given entity.
 *
 * @param annotationMetadata The repository annotation metadata
 * @param repositoryType     The repository type
 * @param rootEntity         The root entity
 * @param persistentEntity   The persistent entity
 * @return The insert
 */
@NonNull
protected DBOperation resolveEntityUpdate(AnnotationMetadata annotationMetadata, Class<?> repositoryType, @NonNull Class<?> rootEntity, @NonNull RuntimePersistentEntity<?> persistentEntity) {
    final QueryKey key = new QueryKey(repositoryType, rootEntity);
    // noinspection unchecked
    return entityUpdates.computeIfAbsent(key, (queryKey) -> {
        final SqlQueryBuilder queryBuilder = queryBuilders.getOrDefault(repositoryType, DEFAULT_SQL_BUILDER);
        final String idName;
        final PersistentProperty identity = persistentEntity.getIdentity();
        if (identity != null) {
            idName = identity.getName();
        } else {
            idName = TypeRole.ID;
        }
        final QueryModel queryModel = QueryModel.from(persistentEntity).idEq(new QueryParameter(idName));
        List<String> updateProperties = persistentEntity.getPersistentProperties().stream().filter(p -> !((p instanceof Association) && ((Association) p).isForeignKey()) && p.getAnnotationMetadata().booleanValue(AutoPopulated.class, "updateable").orElse(true)).map(PersistentProperty::getName).collect(Collectors.toList());
        final QueryResult queryResult = queryBuilder.buildUpdate(annotationMetadata, queryModel, updateProperties);
        return new QueryResultSqlOperation(queryBuilder, queryResult);
    });
}
Also used : QueryParameter(io.micronaut.data.model.query.QueryParameter) QueryResult(io.micronaut.data.model.query.builder.QueryResult) RuntimeAssociation(io.micronaut.data.model.runtime.RuntimeAssociation) Association(io.micronaut.data.model.Association) SqlQueryBuilder(io.micronaut.data.model.query.builder.sql.SqlQueryBuilder) PersistentProperty(io.micronaut.data.model.PersistentProperty) RuntimePersistentProperty(io.micronaut.data.model.runtime.RuntimePersistentProperty) QueryModel(io.micronaut.data.model.query.QueryModel) AutoPopulated(io.micronaut.data.annotation.AutoPopulated) NonNull(io.micronaut.core.annotation.NonNull)

Example 2 with QueryResult

use of io.micronaut.data.model.query.builder.QueryResult in project micronaut-data by micronaut-projects.

the class AbstractSpecificationInterceptor method preparedQueryForCriteria.

protected final <E, QR> PreparedQuery<E, QR> preparedQueryForCriteria(RepositoryMethodKey methodKey, MethodInvocationContext<T, R> context, Type type) {
    Class<Object> rootEntity = getRequiredRootEntity(context);
    Pageable pageable = Pageable.UNPAGED;
    for (Object param : context.getParameterValues()) {
        if (param instanceof Pageable) {
            pageable = (Pageable) param;
            break;
        }
    }
    QueryBuilder sqlQueryBuilder = sqlQueryBuilderForRepositories.computeIfAbsent(methodKey, repositoryMethodKey -> {
        Class<QueryBuilder> builder = context.getAnnotationMetadata().classValue(RepositoryConfiguration.class, "queryBuilder").orElseThrow(() -> new IllegalStateException("Cannot determine QueryBuilder"));
        BeanIntrospection<QueryBuilder> introspection = BeanIntrospection.getIntrospection(builder);
        if (introspection.getConstructorArguments().length == 1 && introspection.getConstructorArguments()[0].getType() == AnnotationMetadata.class) {
            return introspection.instantiate(context.getAnnotationMetadata());
        }
        return introspection.instantiate();
    });
    QueryResult queryResult;
    if (type == Type.COUNT || type == Type.FIND_ALL || type == Type.FIND_ONE || type == Type.FIND_PAGE) {
        QuerySpecification<Object> specification = getQuerySpecification(context);
        PersistentEntityCriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery();
        Root<Object> root = criteriaQuery.from(rootEntity);
        if (specification != null) {
            Predicate predicate = specification.toPredicate(root, criteriaQuery, criteriaBuilder);
            if (predicate != null) {
                criteriaQuery.where(predicate);
            }
        }
        if (type == Type.FIND_ALL) {
            for (Object param : context.getParameterValues()) {
                if (param instanceof Sort && param != pageable) {
                    Sort sort = (Sort) param;
                    if (sort.isSorted()) {
                        criteriaQuery.orderBy(getOrders(sort, root, criteriaBuilder));
                        break;
                    }
                }
            }
        } else if (type == Type.COUNT) {
            criteriaQuery.select(criteriaBuilder.count(root));
        }
        queryResult = ((QueryResultPersistentEntityCriteriaQuery) criteriaQuery).buildQuery(sqlQueryBuilder);
    } else if (type == Type.DELETE_ALL) {
        DeleteSpecification<Object> specification = getDeleteSpecification(context);
        PersistentEntityCriteriaDelete<Object> criteriaDelete = criteriaBuilder.createCriteriaDelete(rootEntity);
        Root<Object> root = criteriaDelete.from(rootEntity);
        if (specification != null) {
            Predicate predicate = specification.toPredicate(root, criteriaDelete, criteriaBuilder);
            if (predicate != null) {
                criteriaDelete.where(predicate);
            }
        }
        queryResult = ((QueryResultPersistentEntityCriteriaQuery) criteriaDelete).buildQuery(sqlQueryBuilder);
    } else if (type == Type.UPDATE_ALL) {
        UpdateSpecification<Object> specification = getUpdateSpecification(context);
        PersistentEntityCriteriaUpdate<Object> criteriaUpdate = criteriaBuilder.createCriteriaUpdate(rootEntity);
        Root<Object> root = criteriaUpdate.from(rootEntity);
        if (specification != null) {
            Predicate predicate = specification.toPredicate(root, criteriaUpdate, criteriaBuilder);
            if (predicate != null) {
                criteriaUpdate.where(predicate);
            }
        }
        queryResult = ((QueryResultPersistentEntityCriteriaQuery) criteriaUpdate).buildQuery(sqlQueryBuilder);
    } else {
        throw new IllegalStateException("Unknown criteria type: " + type);
    }
    String query = queryResult.getQuery();
    String update = queryResult.getUpdate();
    List<io.micronaut.data.model.query.builder.QueryParameterBinding> parameterBindings = queryResult.getParameterBindings();
    List<QueryParameterBinding> queryParameters = new ArrayList<>(parameterBindings.size());
    for (io.micronaut.data.model.query.builder.QueryParameterBinding p : parameterBindings) {
        queryParameters.add(new QueryResultParameterBinding(p, queryParameters));
    }
    String[] queryParts = queryParameters.stream().anyMatch(QueryParameterBinding::isExpandable) ? queryResult.getQueryParts().toArray(new String[0]) : null;
    StoredQuery<E, QR> storedQuery;
    if (type == Type.COUNT) {
        storedQuery = (StoredQuery<E, QR>) storedQueryResolver.createCountStoredQuery(context.getExecutableMethod(), DataMethod.OperationType.COUNT, context.getName(), context.getAnnotationMetadata(), rootEntity, query, queryParts, queryParameters);
    } else if (type == Type.FIND_ALL) {
        storedQuery = storedQueryResolver.createStoredQuery(context.getExecutableMethod(), DataMethod.OperationType.QUERY, context.getName(), context.getAnnotationMetadata(), rootEntity, query, null, queryParts, queryParameters, !pageable.isUnpaged(), false);
    } else {
        DataMethod.OperationType operationType;
        switch(type) {
            case COUNT:
                operationType = DataMethod.OperationType.COUNT;
                break;
            case DELETE_ALL:
                operationType = DataMethod.OperationType.DELETE;
                break;
            case UPDATE_ALL:
                operationType = DataMethod.OperationType.UPDATE;
                break;
            case FIND_ALL:
            case FIND_ONE:
            case FIND_PAGE:
                operationType = DataMethod.OperationType.QUERY;
                break;
            default:
                throw new IllegalStateException("Unknown value: " + type);
        }
        storedQuery = storedQueryResolver.createStoredQuery(context.getExecutableMethod(), operationType, context.getName(), context.getAnnotationMetadata(), rootEntity, query, update, queryParts, queryParameters, false, true);
    }
    return preparedQueryResolver.resolveQuery(context, storedQuery, pageable);
}
Also used : QueryParameterBinding(io.micronaut.data.model.runtime.QueryParameterBinding) DeleteSpecification(io.micronaut.data.repository.jpa.criteria.DeleteSpecification) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) ArrayList(java.util.ArrayList) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Predicate(jakarta.persistence.criteria.Predicate) QueryResult(io.micronaut.data.model.query.builder.QueryResult) Pageable(io.micronaut.data.model.Pageable) Sort(io.micronaut.data.model.Sort) RepositoryConfiguration(io.micronaut.data.annotation.RepositoryConfiguration) Root(jakarta.persistence.criteria.Root) QueryResultPersistentEntityCriteriaQuery(io.micronaut.data.model.jpa.criteria.impl.QueryResultPersistentEntityCriteriaQuery) PersistentEntityCriteriaDelete(io.micronaut.data.model.jpa.criteria.PersistentEntityCriteriaDelete)

Example 3 with QueryResult

use of io.micronaut.data.model.query.builder.QueryResult in project micronaut-data by micronaut-projects.

the class MongoRawQueryMethodMatcher method buildRawQuery.

private void buildRawQuery(@NonNull MethodMatchContext matchContext, MethodMatchInfo methodMatchInfo, ParameterElement entityParameter, ParameterElement entitiesParameter, DataMethod.OperationType operationType) {
    MethodElement methodElement = matchContext.getMethodElement();
    List<ParameterElement> parameters = Arrays.asList(matchContext.getParameters());
    ParameterElement entityParam = null;
    SourcePersistentEntity persistentEntity = null;
    if (entityParameter != null) {
        entityParam = entityParameter;
        persistentEntity = matchContext.getEntity(entityParameter.getGenericType());
    } else if (entitiesParameter != null) {
        entityParam = entitiesParameter;
        persistentEntity = matchContext.getEntity(entitiesParameter.getGenericType().getFirstTypeArgument().orElseThrow(IllegalStateException::new));
    }
    QueryResult queryResult;
    if (operationType == DataMethod.OperationType.UPDATE) {
        queryResult = getUpdateQueryResult(matchContext, parameters, entityParam, persistentEntity);
    } else {
        queryResult = getQueryResult(matchContext, parameters, entityParam, persistentEntity);
    }
    boolean encodeEntityParameters = persistentEntity != null || operationType == DataMethod.OperationType.INSERT;
    methodElement.annotate(Query.class, builder -> {
        if (queryResult.getUpdate() != null) {
            builder.member("update", queryResult.getUpdate());
        }
        builder.value(queryResult.getQuery());
    });
    methodMatchInfo.encodeEntityParameters(encodeEntityParameters).queryResult(queryResult).countQueryResult(null);
}
Also used : QueryResult(io.micronaut.data.model.query.builder.QueryResult) SourcePersistentEntity(io.micronaut.data.processor.model.SourcePersistentEntity) MethodElement(io.micronaut.inject.ast.MethodElement) ParameterElement(io.micronaut.inject.ast.ParameterElement)

Example 4 with QueryResult

use of io.micronaut.data.model.query.builder.QueryResult in project micronaut-data by micronaut-projects.

the class MongoRawQueryMethodMatcher method getQueryResult.

private QueryResult getQueryResult(MethodMatchContext matchContext, List<ParameterElement> parameters, ParameterElement entityParam, SourcePersistentEntity persistentEntity) {
    String filterQueryString;
    if (matchContext.getMethodElement().hasAnnotation(MongoAnnotations.AGGREGATION_QUERY)) {
        filterQueryString = matchContext.getMethodElement().stringValue(MongoAnnotations.AGGREGATION_QUERY).orElseThrow(() -> new MatchFailedException("The pipeline value is missing!"));
        // Mapped to query
        removeAnnotation(matchContext.getAnnotationMetadata(), MongoAnnotations.AGGREGATION_QUERY);
    } else if (matchContext.getMethodElement().hasAnnotation(MongoAnnotations.FIND_QUERY)) {
        filterQueryString = matchContext.getMethodElement().stringValue(MongoAnnotations.FILTER).orElseThrow(() -> new MatchFailedException("The filter value is missing!"));
        // Mapped to query
        removeAnnotation(matchContext.getAnnotationMetadata(), MongoAnnotations.FILTER);
        // Mapped to query
        removeAnnotation(matchContext.getAnnotationMetadata(), MongoAnnotations.FIND_QUERY);
    } else if (matchContext.getMethodElement().hasAnnotation(MongoAnnotations.DELETE_QUERY)) {
        filterQueryString = matchContext.getMethodElement().stringValue(MongoAnnotations.FILTER).orElseThrow(() -> new MatchFailedException("The filter value is missing!"));
        // Mapped to query
        removeAnnotation(matchContext.getAnnotationMetadata(), MongoAnnotations.FILTER);
        // Mapped to query
        removeAnnotation(matchContext.getAnnotationMetadata(), MongoAnnotations.DELETE_QUERY);
    } else {
        throw new MatchFailedException("Unknown custom query annotation!");
    }
    List<QueryParameterBinding> parameterBindings = new ArrayList<>(parameters.size());
    String filterQuery = processCustomQuery(matchContext, filterQueryString, parameters, entityParam, persistentEntity, parameterBindings);
    return new QueryResult() {

        @Override
        public String getQuery() {
            return filterQuery;
        }

        @Override
        public List<String> getQueryParts() {
            return Collections.emptyList();
        }

        @Override
        public List<QueryParameterBinding> getParameterBindings() {
            return parameterBindings;
        }

        @Override
        public Map<String, String> getAdditionalRequiredParameters() {
            return Collections.emptyMap();
        }
    };
}
Also used : QueryResult(io.micronaut.data.model.query.builder.QueryResult) MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) QueryParameterBinding(io.micronaut.data.model.query.builder.QueryParameterBinding) ArrayList(java.util.ArrayList)

Example 5 with QueryResult

use of io.micronaut.data.model.query.builder.QueryResult in project micronaut-data by micronaut-projects.

the class SqlQueryBuilder method buildInsert.

@NonNull
@Override
public QueryResult buildInsert(AnnotationMetadata repositoryMetadata, PersistentEntity entity) {
    boolean escape = shouldEscape(entity);
    final String unescapedTableName = getUnescapedTableName(entity);
    NamingStrategy namingStrategy = entity.getNamingStrategy();
    Collection<? extends PersistentProperty> persistentProperties = entity.getPersistentProperties();
    List<QueryParameterBinding> parameterBindings = new ArrayList<>();
    List<String> columns = new ArrayList<>();
    List<String> values = new ArrayList<>();
    for (PersistentProperty prop : persistentProperties) {
        if (!prop.isGenerated()) {
            traversePersistentProperties(prop, (associations, property) -> {
                addWriteExpression(values, prop);
                String key = String.valueOf(values.size());
                String[] path = asStringPath(associations, property);
                parameterBindings.add(new QueryParameterBinding() {

                    @Override
                    public String getKey() {
                        return key;
                    }

                    @Override
                    public DataType getDataType() {
                        return property.getDataType();
                    }

                    @Override
                    public String[] getPropertyPath() {
                        return path;
                    }
                });
                String columnName = namingStrategy.mappedName(associations, property);
                if (escape) {
                    columnName = quote(columnName);
                }
                columns.add(columnName);
            });
        }
    }
    PersistentProperty version = entity.getVersion();
    if (version != null) {
        addWriteExpression(values, version);
        String key = String.valueOf(values.size());
        parameterBindings.add(new QueryParameterBinding() {

            @Override
            public String getKey() {
                return key;
            }

            @Override
            public DataType getDataType() {
                return version.getDataType();
            }

            @Override
            public String[] getPropertyPath() {
                return new String[] { version.getName() };
            }
        });
        String columnName = namingStrategy.mappedName(Collections.emptyList(), version);
        if (escape) {
            columnName = quote(columnName);
        }
        columns.add(columnName);
    }
    PersistentProperty identity = entity.getIdentity();
    if (identity != null) {
        traversePersistentProperties(identity, (associations, property) -> {
            boolean isSequence = false;
            if (isNotForeign(associations)) {
                Optional<AnnotationValue<GeneratedValue>> generated = property.findAnnotation(GeneratedValue.class);
                if (generated.isPresent()) {
                    GeneratedValue.Type idGeneratorType = generated.flatMap(av -> av.enumValue(GeneratedValue.Type.class)).orElseGet(() -> selectAutoStrategy(property));
                    if (idGeneratorType == GeneratedValue.Type.SEQUENCE) {
                        isSequence = true;
                    } else if (dialect != Dialect.MYSQL || property.getDataType() != DataType.UUID) {
                        // Property skipped
                        return;
                    }
                }
            }
            if (isSequence) {
                values.add(getSequenceStatement(unescapedTableName, property));
            } else {
                addWriteExpression(values, property);
                String key = String.valueOf(values.size());
                String[] path = asStringPath(associations, property);
                parameterBindings.add(new QueryParameterBinding() {

                    @Override
                    public String getKey() {
                        return key;
                    }

                    @Override
                    public DataType getDataType() {
                        return property.getDataType();
                    }

                    @Override
                    public String[] getPropertyPath() {
                        return path;
                    }
                });
            }
            String columnName = namingStrategy.mappedName(associations, property);
            if (escape) {
                columnName = quote(columnName);
            }
            columns.add(columnName);
        });
    }
    String builder = INSERT_INTO + getTableName(entity) + " (" + String.join(",", columns) + CLOSE_BRACKET + " " + "VALUES (" + String.join(String.valueOf(COMMA), values) + CLOSE_BRACKET;
    return QueryResult.of(builder, Collections.emptyList(), parameterBindings, Collections.emptyMap());
}
Also used : DataType(io.micronaut.data.model.DataType) SqlMembers(io.micronaut.data.annotation.sql.SqlMembers) Arrays(java.util.Arrays) IDENTITY(io.micronaut.data.annotation.GeneratedValue.Type.IDENTITY) ListIterator(java.util.ListIterator) ArrayUtils(io.micronaut.core.util.ArrayUtils) SEQUENCE(io.micronaut.data.annotation.GeneratedValue.Type.SEQUENCE) MappedProperty(io.micronaut.data.annotation.MappedProperty) GeneratedValue(io.micronaut.data.annotation.GeneratedValue) Locale(java.util.Locale) Map(java.util.Map) QueryResult(io.micronaut.data.model.query.builder.QueryResult) ArgumentUtils(io.micronaut.core.util.ArgumentUtils) PersistentPropertyPath(io.micronaut.data.model.PersistentPropertyPath) PersistentProperty(io.micronaut.data.model.PersistentProperty) Index(io.micronaut.data.annotation.Index) MappingException(io.micronaut.data.exceptions.MappingException) Collection(java.util.Collection) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) AUTO(io.micronaut.data.annotation.GeneratedValue.Type.AUTO) StringUtils(io.micronaut.core.util.StringUtils) AbstractSqlLikeQueryBuilder(io.micronaut.data.model.query.builder.AbstractSqlLikeQueryBuilder) List(java.util.List) Stream(java.util.stream.Stream) UUID(io.micronaut.data.annotation.GeneratedValue.Type.UUID) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) Annotation(java.lang.annotation.Annotation) Optional(java.util.Optional) Experimental(io.micronaut.core.annotation.Experimental) Pattern(java.util.regex.Pattern) Relation(io.micronaut.data.annotation.Relation) IntStream(java.util.stream.IntStream) QueryParameterBinding(io.micronaut.data.model.query.builder.QueryParameterBinding) Join(io.micronaut.data.annotation.Join) Creator(io.micronaut.core.annotation.Creator) QueryModel(io.micronaut.data.model.query.QueryModel) MappedEntity(io.micronaut.data.annotation.MappedEntity) HashMap(java.util.HashMap) OptionalInt(java.util.OptionalInt) Function(java.util.function.Function) ArrayList(java.util.ArrayList) Embedded(io.micronaut.data.model.Embedded) Pageable(io.micronaut.data.model.Pageable) BiConsumer(java.util.function.BiConsumer) Clob(java.sql.Clob) NamingStrategy(io.micronaut.data.model.naming.NamingStrategy) Indexes(io.micronaut.data.annotation.Indexes) NonNull(io.micronaut.core.annotation.NonNull) JoinPath(io.micronaut.data.model.query.JoinPath) Association(io.micronaut.data.model.Association) PersistentEntity(io.micronaut.data.model.PersistentEntity) CollectionUtils(io.micronaut.core.util.CollectionUtils) StringJoiner(java.util.StringJoiner) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) Repository(io.micronaut.data.annotation.Repository) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Blob(java.sql.Blob) Collections(java.util.Collections) QueryParameterBinding(io.micronaut.data.model.query.builder.QueryParameterBinding) ArrayList(java.util.ArrayList) PersistentProperty(io.micronaut.data.model.PersistentProperty) GeneratedValue(io.micronaut.data.annotation.GeneratedValue) NamingStrategy(io.micronaut.data.model.naming.NamingStrategy) DataType(io.micronaut.data.model.DataType) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) NonNull(io.micronaut.core.annotation.NonNull)

Aggregations

QueryResult (io.micronaut.data.model.query.builder.QueryResult)15 Map (java.util.Map)8 QueryModel (io.micronaut.data.model.query.QueryModel)7 QueryParameterBinding (io.micronaut.data.model.query.builder.QueryParameterBinding)7 QueryBuilder (io.micronaut.data.model.query.builder.QueryBuilder)6 ArrayList (java.util.ArrayList)6 NonNull (io.micronaut.core.annotation.NonNull)5 ClassElement (io.micronaut.inject.ast.ClassElement)5 RepositoryConfiguration (io.micronaut.data.annotation.RepositoryConfiguration)4 DataInterceptor (io.micronaut.data.intercept.DataInterceptor)4 PersistentPropertyPath (io.micronaut.data.model.PersistentPropertyPath)4 SourcePersistentEntity (io.micronaut.data.processor.model.SourcePersistentEntity)4 MatchFailedException (io.micronaut.data.processor.visitors.MatchFailedException)4 MethodMatchInfo (io.micronaut.data.processor.visitors.finders.MethodMatchInfo)4 MethodElement (io.micronaut.inject.ast.MethodElement)4 ParameterElement (io.micronaut.inject.ast.ParameterElement)4 HashMap (java.util.HashMap)4 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)3 Query (io.micronaut.data.annotation.Query)3 Pageable (io.micronaut.data.model.Pageable)3