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;
|
Function<CriteriaAdaptor<C>, BinaryOperator<C>> finalOperator = operator;
|
||||||
this.operator = null;
|
this.operator = null;
|
||||||
BiFunction<C, CriteriaAdaptor<C>, C> builder = (previous, adaptor) -> {
|
BiFunction<C, CriteriaAdaptor<C>, C> builder = (previous, adaptor) -> {
|
||||||
// 连接逻辑
|
|
||||||
BinaryOperator<C> linker = finalOperator.apply(adaptor);
|
|
||||||
// 具体条件
|
// 具体条件
|
||||||
C next = criteria.apply(adaptor);
|
C next = criteria.apply(adaptor);
|
||||||
|
// 如果之前的为空,不计入
|
||||||
|
if (adaptor.isEmpty(previous)) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
// 连接逻辑
|
||||||
|
BinaryOperator<C> linker = finalOperator.apply(adaptor);
|
||||||
// 之前的条件
|
// 之前的条件
|
||||||
return linker.apply(previous, next);
|
return linker.apply(previous, next);
|
||||||
};
|
};
|
||||||
|
@ -15,6 +15,14 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface CriteriaAdaptor<C> {
|
public interface CriteriaAdaptor<C> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断某个查询是否为空
|
||||||
|
*
|
||||||
|
* @param criteria 查询
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
boolean isEmpty(C criteria);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一个空的查询,用于起手
|
* 一个空的查询,用于起手
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.flyfish.framework.mongodb.query.adaptor;
|
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.Queries;
|
||||||
import com.flyfish.framework.query.spi.adaptor.CriteriaAdaptor;
|
import com.flyfish.framework.query.spi.adaptor.CriteriaAdaptor;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
@ -10,6 +11,11 @@ import java.util.List;
|
|||||||
|
|
||||||
public class MongoCriteriaAdaptor implements CriteriaAdaptor<Criteria> {
|
public class MongoCriteriaAdaptor implements CriteriaAdaptor<Criteria> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty(Criteria criteria) {
|
||||||
|
return CriteriaUtils.isEmpty(criteria);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Criteria empty() {
|
public Criteria empty() {
|
||||||
return new Criteria();
|
return new Criteria();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.flyfish.framework.mongodb.utils;
|
package com.flyfish.framework.mongodb.utils;
|
||||||
|
|
||||||
|
import org.bson.Document;
|
||||||
import org.springframework.data.mongodb.core.query.Criteria;
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,6 +27,7 @@ public final class CriteriaUtils {
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public static boolean isEmpty(Criteria criteria) {
|
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> {
|
public class R2dbcCriteriaAdaptor implements CriteriaAdaptor<Criteria> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty(Criteria criteria) {
|
||||||
|
return criteria.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Criteria empty() {
|
public Criteria empty() {
|
||||||
return Criteria.empty();
|
return Criteria.empty();
|
||||||
|
@ -14,8 +14,15 @@ import org.springframework.data.relational.core.sql.render.RenderContext;
|
|||||||
*/
|
*/
|
||||||
public class PredefinedStatementMapper extends DefaultStatementMapper {
|
public class PredefinedStatementMapper extends DefaultStatementMapper {
|
||||||
|
|
||||||
|
private static RenderContext RENDER_CONTEXT;
|
||||||
|
|
||||||
public PredefinedStatementMapper(R2dbcDialect dialect, RenderContext renderContext, UpdateMapper updateMapper,
|
public PredefinedStatementMapper(R2dbcDialect dialect, RenderContext renderContext, UpdateMapper updateMapper,
|
||||||
MappingContext<RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext) {
|
MappingContext<RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext) {
|
||||||
super(dialect, renderContext, updateMapper, 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 R2dbcDialect dialect;
|
||||||
private final MappingContext<? extends RelationalPersistentEntity<?>, RelationalPersistentProperty> mappingContext;
|
private final MappingContext<? extends RelationalPersistentEntity<?>, RelationalPersistentProperty> mappingContext;
|
||||||
|
|
||||||
|
|
||||||
public FullUpdateMapper(R2dbcDialect dialect, R2dbcConverter converter) {
|
public FullUpdateMapper(R2dbcDialect dialect, R2dbcConverter converter) {
|
||||||
super(dialect, converter);
|
super(dialect, converter);
|
||||||
this.dialect = dialect;
|
this.dialect = dialect;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package org.springframework.data.relational.core.sql;
|
package org.springframework.data.relational.core.sql;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import org.springframework.data.relational.core.sql.render.FunctionVisitor;
|
import org.springframework.data.relational.core.sql.render.FunctionVisitor;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -12,8 +14,11 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class FunctionCondition extends ConstantCondition implements Condition {
|
public class FunctionCondition extends ConstantCondition implements Condition {
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final SimpleFunction function;
|
private final SimpleFunction function;
|
||||||
|
|
||||||
|
private final StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
private FunctionCondition(SimpleFunction function) {
|
private FunctionCondition(SimpleFunction function) {
|
||||||
super("");
|
super("");
|
||||||
this.function = function;
|
this.function = function;
|
||||||
@ -27,9 +32,19 @@ public class FunctionCondition extends ConstantCondition implements Condition {
|
|||||||
return of(functionName, Arrays.asList(args));
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
FunctionVisitor visitor = new FunctionVisitor();
|
FunctionVisitor visitor = new FunctionVisitor(this, builder::append);
|
||||||
return function.toString();
|
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;
|
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.FunctionCondition;
|
||||||
import org.springframework.data.relational.core.sql.SimpleFunction;
|
import org.springframework.data.relational.core.sql.SimpleFunction;
|
||||||
import org.springframework.data.relational.core.sql.Visitable;
|
import org.springframework.data.relational.core.sql.Visitable;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class FunctionVisitor extends FilteredSubtreeVisitor {
|
public class FunctionVisitor extends FilteredSubtreeVisitor {
|
||||||
|
|
||||||
private final RenderContext context;
|
private final RenderContext context;
|
||||||
@ -12,10 +15,10 @@ public class FunctionVisitor extends FilteredSubtreeVisitor {
|
|||||||
private @Nullable PartRenderer current;
|
private @Nullable PartRenderer current;
|
||||||
private final StringBuilder part = new StringBuilder();
|
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);
|
super(it -> it == condition);
|
||||||
this.context = context;
|
this.context = PredefinedStatementMapper.sharedRenderContext();
|
||||||
this.target = target;
|
this.target = target::accept;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -68,7 +68,10 @@ public class FlyfishUserTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFunc() {
|
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)
|
.doOnNext(this::log)
|
||||||
.blockFirst();
|
.blockFirst();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user