feat: 解决所有问题,支持函数扩展
feat: 嵌套问题待解决
This commit is contained in:
parent
95e5b1800a
commit
b9028c3aa5
@ -47,10 +47,14 @@ class DefaultQueryChainHolder<C> implements QueryChainHolder<C> {
|
||||
Function<CriteriaAdaptor<C>, BinaryOperator<C>> finalOperator = operator;
|
||||
this.operator = null;
|
||||
BiFunction<C, CriteriaAdaptor<C>, C> builder = (previous, adaptor) -> {
|
||||
// 连接逻辑
|
||||
BinaryOperator<C> linker = finalOperator.apply(adaptor);
|
||||
// 具体条件
|
||||
C next = criteria.apply(adaptor);
|
||||
// 如果之前的为空,不计入
|
||||
if (adaptor.isEmpty(previous)) {
|
||||
return next;
|
||||
}
|
||||
// 连接逻辑
|
||||
BinaryOperator<C> linker = finalOperator.apply(adaptor);
|
||||
// 之前的条件
|
||||
return linker.apply(previous, next);
|
||||
};
|
||||
|
@ -15,6 +15,14 @@ import java.util.List;
|
||||
*/
|
||||
public interface CriteriaAdaptor<C> {
|
||||
|
||||
/**
|
||||
* 判断某个查询是否为空
|
||||
*
|
||||
* @param criteria 查询
|
||||
* @return 结果
|
||||
*/
|
||||
boolean isEmpty(C criteria);
|
||||
|
||||
/**
|
||||
* 一个空的查询,用于起手
|
||||
*
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.flyfish.framework.mongodb.query.adaptor;
|
||||
|
||||
import com.flyfish.framework.mongodb.utils.CriteriaUtils;
|
||||
import com.flyfish.framework.query.Queries;
|
||||
import com.flyfish.framework.query.spi.adaptor.CriteriaAdaptor;
|
||||
import org.bson.types.ObjectId;
|
||||
@ -10,6 +11,11 @@ import java.util.List;
|
||||
|
||||
public class MongoCriteriaAdaptor implements CriteriaAdaptor<Criteria> {
|
||||
|
||||
@Override
|
||||
public boolean isEmpty(Criteria criteria) {
|
||||
return CriteriaUtils.isEmpty(criteria);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Criteria empty() {
|
||||
return new Criteria();
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.flyfish.framework.mongodb.utils;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
|
||||
/**
|
||||
@ -26,6 +27,7 @@ public final class CriteriaUtils {
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean isEmpty(Criteria criteria) {
|
||||
return null == criteria.getCriteriaObject() || criteria.getCriteriaObject().size() == 0;
|
||||
Document document = criteria.getCriteriaObject();
|
||||
return null == document || document.isEmpty();
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,11 @@ import java.util.List;
|
||||
*/
|
||||
public class R2dbcCriteriaAdaptor implements CriteriaAdaptor<Criteria> {
|
||||
|
||||
@Override
|
||||
public boolean isEmpty(Criteria criteria) {
|
||||
return criteria.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Criteria empty() {
|
||||
return Criteria.empty();
|
||||
|
@ -14,8 +14,15 @@ import org.springframework.data.relational.core.sql.render.RenderContext;
|
||||
*/
|
||||
public class PredefinedStatementMapper extends DefaultStatementMapper {
|
||||
|
||||
private static RenderContext RENDER_CONTEXT;
|
||||
|
||||
public PredefinedStatementMapper(R2dbcDialect dialect, RenderContext renderContext, UpdateMapper updateMapper,
|
||||
MappingContext<RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext) {
|
||||
MappingContext<RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext) {
|
||||
super(dialect, renderContext, updateMapper, mappingContext);
|
||||
RENDER_CONTEXT = renderContext;
|
||||
}
|
||||
|
||||
public static RenderContext sharedRenderContext() {
|
||||
return RENDER_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ public class FullUpdateMapper extends UpdateMapper {
|
||||
private final R2dbcDialect dialect;
|
||||
private final MappingContext<? extends RelationalPersistentEntity<?>, RelationalPersistentProperty> mappingContext;
|
||||
|
||||
|
||||
public FullUpdateMapper(R2dbcDialect dialect, R2dbcConverter converter) {
|
||||
super(dialect, converter);
|
||||
this.dialect = dialect;
|
||||
|
@ -1,6 +1,8 @@
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.data.relational.core.sql.render.FunctionVisitor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -12,8 +14,11 @@ import java.util.List;
|
||||
*/
|
||||
public class FunctionCondition extends ConstantCondition implements Condition {
|
||||
|
||||
@Getter
|
||||
private final SimpleFunction function;
|
||||
|
||||
private final StringBuilder builder = new StringBuilder();
|
||||
|
||||
private FunctionCondition(SimpleFunction function) {
|
||||
super("");
|
||||
this.function = function;
|
||||
@ -27,9 +32,19 @@ public class FunctionCondition extends ConstantCondition implements Condition {
|
||||
return of(functionName, Arrays.asList(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Visitor visitor) {
|
||||
Assert.notNull(visitor, "Visitor must not be null");
|
||||
|
||||
visitor.enter(this);
|
||||
function.visit(visitor);
|
||||
visitor.leave(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
FunctionVisitor visitor = new FunctionVisitor();
|
||||
return function.toString();
|
||||
FunctionVisitor visitor = new FunctionVisitor(this, builder::append);
|
||||
this.visit(visitor);
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.relational.core.sql.*;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.data.relational.core.sql.Visitor} delegating {@link Condition} rendering to condition
|
||||
* {@link org.springframework.data.relational.core.sql.Visitor}s.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Jens Schauder
|
||||
* @author Daniele Canteri
|
||||
* @see AndCondition
|
||||
* @see OrCondition
|
||||
* @see IsNull
|
||||
* @see Comparison
|
||||
* @see Like
|
||||
* @see In
|
||||
* @since 1.1
|
||||
*/
|
||||
class ConditionVisitor extends TypedSubtreeVisitor<Condition> implements PartRenderer {
|
||||
|
||||
private final RenderContext context;
|
||||
private final StringBuilder builder = new StringBuilder();
|
||||
|
||||
ConditionVisitor(RenderContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
Delegation enterMatched(Condition segment) {
|
||||
|
||||
DelegatingVisitor visitor = getDelegation(segment);
|
||||
|
||||
return visitor != null ? Delegation.delegateTo(visitor) : Delegation.retain();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private DelegatingVisitor getDelegation(Condition segment) {
|
||||
|
||||
if (segment instanceof AndCondition) {
|
||||
return new MultiConcatConditionVisitor(context, (AndCondition) segment, builder::append);
|
||||
}
|
||||
|
||||
if (segment instanceof OrCondition) {
|
||||
return new MultiConcatConditionVisitor(context, (OrCondition) segment, builder::append);
|
||||
}
|
||||
|
||||
if (segment instanceof IsNull) {
|
||||
return new IsNullVisitor(context, builder::append);
|
||||
}
|
||||
|
||||
if (segment instanceof Between) {
|
||||
return new BetweenVisitor((Between) segment, context, builder::append);
|
||||
}
|
||||
|
||||
if (segment instanceof Comparison) {
|
||||
return new ComparisonVisitor(context, (Comparison) segment, builder::append);
|
||||
}
|
||||
|
||||
if (segment instanceof Like) {
|
||||
return new LikeVisitor((Like) segment, context, builder::append);
|
||||
}
|
||||
|
||||
if (segment instanceof In) {
|
||||
|
||||
if (((In) segment).hasExpressions()) {
|
||||
return new InVisitor(context, builder::append);
|
||||
} else {
|
||||
return new EmptyInVisitor(context, builder::append);
|
||||
}
|
||||
}
|
||||
|
||||
if (segment instanceof NestedCondition) {
|
||||
return new NestedConditionVisitor(context, builder::append);
|
||||
}
|
||||
|
||||
if (segment instanceof ConstantCondition) {
|
||||
return new ConstantConditionVisitor(context, builder::append);
|
||||
}
|
||||
|
||||
if (segment instanceof Not) {
|
||||
return new NotConditionVisitor(context, builder::append);
|
||||
}
|
||||
|
||||
if (segment instanceof FunctionCondition functionCondition) {
|
||||
return new FunctionVisitor(functionCondition, context, builder::append);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getRenderedPart() {
|
||||
return builder;
|
||||
}
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.r2dbc.core.PredefinedStatementMapper;
|
||||
import org.springframework.data.relational.core.sql.FunctionCondition;
|
||||
import org.springframework.data.relational.core.sql.SimpleFunction;
|
||||
import org.springframework.data.relational.core.sql.Visitable;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class FunctionVisitor extends FilteredSubtreeVisitor {
|
||||
|
||||
private final RenderContext context;
|
||||
@ -12,10 +15,10 @@ public class FunctionVisitor extends FilteredSubtreeVisitor {
|
||||
private @Nullable PartRenderer current;
|
||||
private final StringBuilder part = new StringBuilder();
|
||||
|
||||
public FunctionVisitor(FunctionCondition condition, RenderContext context, RenderTarget target) {
|
||||
public FunctionVisitor(FunctionCondition condition, Consumer<CharSequence> target) {
|
||||
super(it -> it == condition);
|
||||
this.context = context;
|
||||
this.target = target;
|
||||
this.context = PredefinedStatementMapper.sharedRenderContext();
|
||||
this.target = target::accept;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -68,7 +68,10 @@ public class FlyfishUserTest {
|
||||
|
||||
@Test
|
||||
public void testFunc() {
|
||||
userRepository.findAll(Queries.where(User::getOpenId).has("1").wrap())
|
||||
userRepository.findAll(Queries
|
||||
.where(User::getOpenId).has("1")
|
||||
.or(User::getApp).eq(true)
|
||||
.wrap())
|
||||
.doOnNext(this::log)
|
||||
.blockFirst();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user