feat: 解决所有问题,支持函数扩展

feat: 嵌套问题待解决
This commit is contained in:
wangyu 2024-07-04 00:26:35 +08:00
parent 95e5b1800a
commit b9028c3aa5
11 changed files with 63 additions and 123 deletions

View File

@ -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);
}; };

View File

@ -15,6 +15,14 @@ import java.util.List;
*/ */
public interface CriteriaAdaptor<C> { public interface CriteriaAdaptor<C> {
/**
* 判断某个查询是否为空
*
* @param criteria 查询
* @return 结果
*/
boolean isEmpty(C criteria);
/** /**
* 一个空的查询用于起手 * 一个空的查询用于起手
* *

View File

@ -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();

View File

@ -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();
} }
} }

View File

@ -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();

View File

@ -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;
} }
} }

View File

@ -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;

View File

@ -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();
} }
} }

View File

@ -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;
}
}

View File

@ -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

View File

@ -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();
} }