use of io.micronaut.data.model.query.builder.QueryParameterBinding 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();
}
};
}
use of io.micronaut.data.model.query.builder.QueryParameterBinding 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());
}
use of io.micronaut.data.model.query.builder.QueryParameterBinding in project micronaut-data by micronaut-projects.
the class RepositoryTypeElementVisitor method bindAdditionalParameters.
private void bindAdditionalParameters(MatchContext matchContext, SourcePersistentEntity entity, List<QueryParameterBinding> parameterBinding, ParameterElement[] parameters, Map<String, String> params) {
if (CollectionUtils.isNotEmpty(params)) {
Map<String, DataType> configuredDataTypes = Utils.getConfiguredDataTypes(matchContext.getRepositoryClass());
for (Map.Entry<String, String> param : params.entrySet()) {
ParameterElement parameter = Arrays.stream(parameters).filter(p -> p.stringValue(Parameter.class).orElse(p.getName()).equals(param.getValue())).findFirst().orElse(null);
if (parameter == null) {
throw new MatchFailedException("A @Where(..) definition requires a parameter called [" + param.getValue() + "] which is not present in the method signature.");
}
PersistentPropertyPath propertyPath = entity.getPropertyPath(parameter.getName());
BindingParameter.BindingContext bindingContext = BindingParameter.BindingContext.create().name(param.getKey()).incomingMethodParameterProperty(propertyPath).outgoingQueryParameterProperty(propertyPath);
QueryParameterBinding binding = new SourceParameterExpressionImpl(configuredDataTypes, matchContext.parameters, parameter, false).bind(bindingContext);
parameterBinding.add(binding);
}
}
}
use of io.micronaut.data.model.query.builder.QueryParameterBinding in project micronaut-data by micronaut-projects.
the class RepositoryTypeElementVisitor method processMethodInfo.
private void processMethodInfo(MethodMatchContext methodMatchContext, MethodMatchInfo methodInfo) {
QueryBuilder queryEncoder = methodMatchContext.getQueryBuilder();
MethodElement element = methodMatchContext.getMethodElement();
SourcePersistentEntity entity = methodMatchContext.getRootEntity();
ParameterElement[] parameters = methodMatchContext.getParameters();
// populate parameter roles
for (Map.Entry<String, Element> entry : methodMatchContext.getParametersInRole().entrySet()) {
methodInfo.addParameterRole(entry.getKey(), entry.getValue().getName());
}
List<QueryParameterBinding> parameterBinding = null;
boolean encodeEntityParameters = false;
boolean supportsImplicitQueries = methodMatchContext.supportsImplicitQueries();
QueryResult queryResult = methodInfo.getQueryResult();
if (queryResult != null) {
if (methodInfo.isRawQuery()) {
// no need to annotation since already annotated, just replace the
// the computed parameter names
parameterBinding = queryResult.getParameterBindings();
element.annotate(Query.class, (builder) -> builder.member(DataMethod.META_MEMBER_RAW_QUERY, element.stringValue(Query.class).map(q -> addRawQueryParameterPlaceholders(queryEncoder, queryResult.getQuery(), queryResult.getQueryParts())).orElse(null)));
ClassElement genericReturnType = methodMatchContext.getReturnType();
if (methodMatchContext.isTypeInRole(genericReturnType, TypeRole.PAGE) || element.isPresent(Query.class, "countQuery")) {
QueryResult countQueryResult = methodInfo.getCountQueryResult();
if (countQueryResult == null) {
throw new MatchFailedException("Query returns a Page and does not specify a 'countQuery' member.", element);
} else {
element.annotate(Query.class, (builder) -> builder.member(DataMethod.META_MEMBER_RAW_COUNT_QUERY, addRawQueryParameterPlaceholders(queryEncoder, countQueryResult.getQuery(), countQueryResult.getQueryParts())));
}
}
encodeEntityParameters = methodInfo.isEncodeEntityParameters();
} else {
encodeEntityParameters = methodInfo.isEncodeEntityParameters();
parameterBinding = queryResult.getParameterBindings();
bindAdditionalParameters(methodMatchContext, entity, parameterBinding, parameters, queryResult.getAdditionalRequiredParameters());
QueryResult preparedCount = methodInfo.getCountQueryResult();
if (preparedCount != null) {
element.annotate(Query.class, annotationBuilder -> {
annotationBuilder.value(queryResult.getQuery());
annotationBuilder.member(DataMethod.META_MEMBER_COUNT_QUERY, preparedCount.getQuery());
});
} else {
element.annotate(Query.class, annotationBuilder -> {
annotationBuilder.value(queryResult.getQuery());
String update = queryResult.getUpdate();
if (StringUtils.isNotEmpty(update)) {
annotationBuilder.member("update", update);
}
});
}
}
}
ClassElement runtimeInterceptor = methodInfo.getRuntimeInterceptor();
if (runtimeInterceptor == null) {
throw new MatchFailedException("Unable to implement Repository method: " + currentRepository.getSimpleName() + "." + element.getName() + "(..). No possible runtime implementations found.", element);
}
boolean finalEncodeEntityParameters = encodeEntityParameters;
List<QueryParameterBinding> finalParameterBinding = parameterBinding;
element.annotate(DataMethod.class, annotationBuilder -> {
annotationBuilder.member(DataMethod.META_MEMBER_OPERATION_TYPE, methodInfo.getOperationType());
annotationBuilder.member(DataMethod.META_MEMBER_ROOT_ENTITY, new AnnotationClassValue<>(entity.getName()));
// include the roles
methodInfo.getParameterRoles().forEach(annotationBuilder::member);
if (methodInfo.isDto()) {
annotationBuilder.member(DataMethod.META_MEMBER_DTO, true);
}
if (methodInfo.isOptimisticLock()) {
annotationBuilder.member(DataMethod.META_MEMBER_OPTIMISTIC_LOCK, true);
}
TypedElement resultType = methodInfo.getResultType();
if (resultType != null) {
annotationBuilder.member(DataMethod.META_MEMBER_RESULT_TYPE, new AnnotationClassValue<>(resultType.getName()));
ClassElement type = resultType.getType();
if (!TypeUtils.isVoid(type)) {
annotationBuilder.member(DataMethod.META_MEMBER_RESULT_DATA_TYPE, TypeUtils.resolveDataType(type, dataTypes));
}
}
String idType = resolveIdType(entity);
if (idType != null) {
annotationBuilder.member(DataMethod.META_MEMBER_ID_TYPE, idType);
}
annotationBuilder.member(DataMethod.META_MEMBER_INTERCEPTOR, new AnnotationClassValue<>(runtimeInterceptor.getName()));
if (queryResult != null) {
if (finalParameterBinding.stream().anyMatch(QueryParameterBinding::isExpandable)) {
annotationBuilder.member(DataMethod.META_MEMBER_EXPANDABLE_QUERY, queryResult.getQueryParts().toArray(new String[0]));
QueryResult preparedCount = methodInfo.getCountQueryResult();
if (preparedCount != null) {
annotationBuilder.member(DataMethod.META_MEMBER_EXPANDABLE_COUNT_QUERY, preparedCount.getQueryParts().toArray(new String[0]));
}
}
int max = queryResult.getMax();
if (max > -1) {
annotationBuilder.member(DataMethod.META_MEMBER_PAGE_SIZE, max);
}
long offset = queryResult.getOffset();
if (offset > 0) {
annotationBuilder.member(DataMethod.META_MEMBER_PAGE_INDEX, offset);
}
}
Arrays.stream(parameters).filter(p -> p.getGenericType().isAssignable(entity.getName())).findFirst().ifPresent(parameterElement -> annotationBuilder.member(DataMethod.META_MEMBER_ENTITY, parameterElement.getName()));
if (CollectionUtils.isNotEmpty(finalParameterBinding)) {
bindParameters(supportsImplicitQueries, finalParameterBinding, finalEncodeEntityParameters, annotationBuilder);
}
});
}
use of io.micronaut.data.model.query.builder.QueryParameterBinding in project micronaut-data by micronaut-projects.
the class RawQueryMethodMatcher method getQueryResult.
private QueryResult getQueryResult(MethodMatchContext matchContext, String queryString, List<ParameterElement> parameters, boolean namedParameters, ParameterElement entityParam, SourcePersistentEntity persistentEntity) {
java.util.regex.Matcher matcher = VARIABLE_PATTERN.matcher(queryString.replace("\\:", ""));
List<QueryParameterBinding> parameterBindings = new ArrayList<>(parameters.size());
List<String> queryParts = new ArrayList<>();
int index = 1;
int lastOffset = 0;
while (matcher.find()) {
String prefix = queryString.substring(lastOffset, matcher.start(3) - 1);
if (!prefix.isEmpty()) {
queryParts.add(prefix);
}
lastOffset = matcher.end(3);
String name = matcher.group(3);
if (namedParameters) {
Optional<ParameterElement> element = parameters.stream().filter(p -> p.stringValue(Parameter.class).orElse(p.getName()).equals(name)).findFirst();
if (element.isPresent()) {
PersistentPropertyPath propertyPath = matchContext.getRootEntity().getPropertyPath(name);
BindingContext bindingContext = BindingContext.create().name(name).incomingMethodParameterProperty(propertyPath).outgoingQueryParameterProperty(propertyPath);
parameterBindings.add(bindingParameter(matchContext, element.get()).bind(bindingContext));
} else if (persistentEntity != null) {
PersistentPropertyPath propertyPath = persistentEntity.getPropertyPath(name);
if (propertyPath == null) {
throw new MatchFailedException("Cannot update non-existent property: " + name);
} else {
BindingContext bindingContext = BindingContext.create().name(name).incomingMethodParameterProperty(propertyPath).outgoingQueryParameterProperty(propertyPath);
parameterBindings.add(bindingParameter(matchContext, entityParam, true).bind(bindingContext));
}
} else {
throw new MatchFailedException("No method parameter found for named Query parameter: " + name);
}
} else {
Optional<ParameterElement> element = parameters.stream().filter(p -> p.stringValue(Parameter.class).orElse(p.getName()).equals(name)).findFirst();
if (element.isPresent()) {
PersistentPropertyPath propertyPath = matchContext.getRootEntity().getPropertyPath(name);
BindingContext bindingContext = BindingContext.create().index(index++).incomingMethodParameterProperty(propertyPath).outgoingQueryParameterProperty(propertyPath);
parameterBindings.add(bindingParameter(matchContext, element.get()).bind(bindingContext));
} else if (persistentEntity != null) {
PersistentPropertyPath propertyPath = persistentEntity.getPropertyPath(name);
if (propertyPath == null) {
matchContext.fail("Cannot update non-existent property: " + name);
} else {
BindingContext bindingContext = BindingContext.create().index(index++).incomingMethodParameterProperty(propertyPath).outgoingQueryParameterProperty(propertyPath);
parameterBindings.add(bindingParameter(matchContext, entityParam, true).bind(bindingContext));
}
} else {
throw new MatchFailedException("No method parameter found for named Query parameter: " + name);
}
}
}
queryString = queryString.replace("\\:", ":");
if (queryParts.isEmpty()) {
queryParts.add(queryString);
} else if (lastOffset > 0) {
queryParts.add(queryString.substring(lastOffset));
}
String finalQueryString = queryString;
return new QueryResult() {
@Override
public String getQuery() {
return finalQueryString;
}
@Override
public List<String> getQueryParts() {
return queryParts;
}
@Override
public List<QueryParameterBinding> getParameterBindings() {
return parameterBindings;
}
@Override
public Map<String, String> getAdditionalRequiredParameters() {
return Collections.emptyMap();
}
};
}
Aggregations