refactor: 优化原生sql查询解析逻辑

This commit is contained in:
zhouhao
2024-06-27 18:04:18 +08:00
parent c6dca0a672
commit 6054867d82
5 changed files with 137 additions and 90 deletions

View File

@@ -4,6 +4,8 @@ import lombok.Getter;
import lombok.Setter;
import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository;
import org.hswebframework.ezorm.rdb.mapping.defaults.DefaultReactiveRepository;
import org.hswebframework.ezorm.rdb.metadata.RDBSchemaMetadata;
import org.hswebframework.ezorm.rdb.metadata.RDBTableMetadata;
import org.hswebframework.ezorm.rdb.operator.DatabaseOperator;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
@@ -11,7 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
@Getter
@Setter
public class ReactiveRepositoryFactoryBean<E, PK>
implements FactoryBean<ReactiveRepository<E, PK>> {
implements FactoryBean<ReactiveRepository<E, PK>> {
@Autowired
private DatabaseOperator operator;
@@ -26,11 +28,13 @@ public class ReactiveRepositoryFactoryBean<E, PK>
@Override
public ReactiveRepository<E, PK> getObject() {
return new DefaultReactiveRepository<>(operator,
resolver.resolve(entityType),
entityType,
wrapperFactory.getWrapper(entityType));
RDBTableMetadata table = resolver.resolve(entityType);
String tableName = table.getName();
return new DefaultReactiveRepository<>(
operator,
tableName,
entityType,
wrapperFactory.getWrapper(entityType));
}
@Override

View File

@@ -256,7 +256,7 @@ class QueryAnalyzerImpl implements FromItemVisitor, SelectItemVisitor, SelectVis
} else {
schemaMetadata = database.getMetadata().getCurrentSchema();
if (!virtualTable.containsKey(name)) {
tableName.setSchemaName(schemaMetadata.getName());
tableName.setSchemaName(schemaMetadata.getQuoteName());
}
}
@@ -269,7 +269,7 @@ class QueryAnalyzerImpl implements FromItemVisitor, SelectItemVisitor, SelectVis
if (tableMetadata == null) {
throw new IllegalStateException("table or view " + tableName.getName() + " not found in " + schemaMetadata.getName());
}
tableName.setName(tableMetadata.getRealName());
QueryAnalyzer.Table table = new QueryAnalyzer.Table(
parsePlainName(alias),
tableMetadata
@@ -339,6 +339,7 @@ class QueryAnalyzerImpl implements FromItemVisitor, SelectItemVisitor, SelectVis
}
view.setName(name);
view.setRealName(name);
view.setSchema(database.getMetadata().getCurrentSchema());
view.setAlias(name);
@@ -403,7 +404,7 @@ class QueryAnalyzerImpl implements FromItemVisitor, SelectItemVisitor, SelectVis
String alias = table == select.table ? column.getAlias() : table.alias + "." + column.getAlias();
container.add(new QueryAnalyzer.Column(
column.getName(),
column.getRealName(),
alias,
table.alias,
column
@@ -519,7 +520,7 @@ class QueryAnalyzerImpl implements FromItemVisitor, SelectItemVisitor, SelectVis
throw new IllegalStateException("column [" + column.getColumnName() + "] not found in " + table.metadata.getName());
}
select.columnList.add(new QueryAnalyzer.Column(metadata.getName(), aliasName, table.alias, metadata));
select.columnList.add(new QueryAnalyzer.Column(metadata.getRealName(), aliasName, table.alias, metadata));
}
@@ -670,13 +671,15 @@ class QueryAnalyzerImpl implements FromItemVisitor, SelectItemVisitor, SelectVis
metadata = table.metadata;
}
String colName = col.metadata != null ? col.metadata.getName() : col.name;
Column _col = col;
Table _table = table;
String colName = col.metadata != null ? col.metadata.getRealName() : col.name;
String fullName = col.metadata != null
? col.getMetadata().getFullName(table.alias)
: table.alias + "." + dialect.quote(colName, false);
return metadata
.findFeature(createFeatureId(term.getTermType()))
.map(feature -> feature.createFragments(
_table.alias + "." + dialect.quote(colName, _col.metadata != null), _col.metadata, term))
fullName, col.metadata, term))
.orElse(EmptySqlFragments.INSTANCE);
}
}
@@ -727,7 +730,9 @@ class QueryAnalyzerImpl implements FromItemVisitor, SelectItemVisitor, SelectVis
continue;
}
columns.append(column.owner).append('.').append(dialect.quote(column.name, column.metadata != null))
columns.append(column.owner)
.append('.')
.append(dialect.quote(column.name, column.metadata != null && !column.metadata.realNameDetected()))
.append(" as ")
.append(dialect.quote(column.alias, false));
}
@@ -839,7 +844,8 @@ class QueryAnalyzerImpl implements FromItemVisitor, SelectItemVisitor, SelectVis
@Override
public void visit(ValuesStatement aThis) {
PrepareStatementVisitor visitor = new PrepareStatementVisitor();
aThis.accept(visitor);
}
public Object[] getPrefixParameters(Object... args) {

View File

@@ -6,6 +6,8 @@ import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hswebframework.ezorm.core.param.Sort;
import org.hswebframework.ezorm.rdb.executor.SqlRequest;
import org.hswebframework.ezorm.rdb.executor.SqlRequests;
import org.hswebframework.ezorm.rdb.operator.DatabaseOperator;
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.hswebframework.web.crud.entity.EventTestEntity;
@@ -34,6 +36,39 @@ class DefaultQueryHelperTest {
private DatabaseOperator database;
@Test
public void testLoadTable() {
database
.sql()
.reactive()
.execute(SqlRequests.of("create table \"NATIVE_TEST\"( " +
"\"id\" varchar(32) primary key" +
",name varchar(32)" +
",\"testName\" varchar(32)" +
")"))
.as(StepVerifier::create)
.expectComplete()
.verify();
DefaultQueryHelper helper = new DefaultQueryHelper(database);
database
.dml()
.insert("native_test")
.value("id", "test")
.value("NAME", "test")
.value("testName", "test")
.execute()
.sync();
helper.select("select id,name,testName from native_test")
.fetch()
.doOnNext(System.out::println)
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
@Test
public void testPage() {
DefaultQueryHelper helper = new DefaultQueryHelper(database);
@@ -97,15 +132,16 @@ class DefaultQueryHelperTest {
.execute()
.sync();
helper.select("select name as \"name\",count(1) totalResult from s_test group by name having count(1) > ? ", GroupResult::new, 0)
.where(dsl -> dsl
.is("age", "31")
.orderByAsc(GroupResult::getTotalResult))
.fetch()
.doOnNext(v -> System.out.println(JSON.toJSONString(v, SerializerFeature.PrettyFormat)))
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
helper
.select("select name as \"name\",count(1) totalResult from s_test group by name having count(1) > ? ", GroupResult::new, 0)
.where(dsl -> dsl
.is("age", "31")
.orderByAsc(GroupResult::getTotalResult))
.fetch()
.doOnNext(v -> System.out.println(JSON.toJSONString(v, SerializerFeature.PrettyFormat)))
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
@Test
@@ -146,10 +182,10 @@ class DefaultQueryHelperTest {
helper.select("select age,count(1) c from ( select *,'1' as x from s_test ) a group by age ", 0)
.where(dsl -> dsl
.is("x", "1")
.is("name", "inner")
.is("a.testName", "inner")
.is("age", 31))
.is("x", "1")
.is("name", "inner")
.is("a.testName", "inner")
.is("age", 31))
.fetchPaged(0, 10)
.doOnNext(v -> System.out.println(JSON.toJSONString(v, SerializerFeature.PrettyFormat)))
.as(StepVerifier::create)
@@ -170,12 +206,13 @@ class DefaultQueryHelperTest {
.execute()
.sync();
helper.select("select * from s_test t1 join (select * from s_test s where name = ? ) t2 on t2.id = t1.id ", "join_sub")
.fetch()
.doOnNext(v -> System.out.println(JSON.toJSONString(v, SerializerFeature.PrettyFormat)))
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
helper
.select("select * from s_test t1 join (select * from s_test s where name = ? ) t2 on t2.id = t1.id ", "join_sub")
.fetch()
.doOnNext(v -> System.out.println(JSON.toJSONString(v, SerializerFeature.PrettyFormat)))
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
@Getter
@@ -204,11 +241,11 @@ class DefaultQueryHelperTest {
DefaultQueryHelper helper = new DefaultQueryHelper(database);
QueryParamEntity param = QueryParamEntity
.newQuery()
.is("e.id", "helper_testNative")
.is("t.age", "20")
.orderByAsc("t.age")
.getParam();
.newQuery()
.is("e.id", "helper_testNative")
.is("t.age", "20")
.orderByAsc("t.age")
.getParam();
{
Sort sortByValue = new Sort();
@@ -225,8 +262,8 @@ class DefaultQueryHelperTest {
helper.select("select t.*,e.*,e.name ename,e.id `x.id` from s_test t " +
"left join s_test_event e on e.id = t.id " +
"where t.age = ?", 20)
"left join s_test_event e on e.id = t.id " +
"where t.age = ?", 20)
.logger(LoggerFactory.getLogger("org.hswebframework.test.native"))
.where(param)
.fetchPaged()
@@ -236,10 +273,10 @@ class DefaultQueryHelperTest {
.verifyComplete();
helper.select("select id,name from s_test t " +
"union all select id,name from s_test_event")
"union all select id,name from s_test_event")
.where(dsl -> dsl
.is("id", "helper_testNative")
.orderByAsc("name"))
.is("id", "helper_testNative")
.orderByAsc("name"))
.fetchPaged()
.doOnNext(v -> System.out.println(JSON.toJSONString(v, SerializerFeature.PrettyFormat)))
.as(StepVerifier::create)
@@ -308,10 +345,10 @@ class DefaultQueryHelperTest {
.from(TestEntity.class)
.leftJoin(EventTestEntity.class,
join -> join
.alias("e1")
.is(EventTestEntity::getId, TestEntity::getId)
.alias("e1")
.is(EventTestEntity::getId, TestEntity::getId)
// .is(EventTestEntity::getName, TestEntity::getId)
.notNull(EventTestEntity::getAge))
.notNull(EventTestEntity::getAge))
// .leftJoin(EventTestEntity.class,
// join -> join
// .alias("e2")

View File

@@ -173,7 +173,7 @@ class QueryAnalyzerImplTest {
void testValues(){
QueryAnalyzerImpl analyzer = new QueryAnalyzerImpl(
database,
"select * from (values (1,2),(3,4)) t(a,b)");
"select * from (values (1,2),(3,4)) t(\"a\",b)");
SqlRequest request = analyzer
.refactor(QueryParamEntity.of().and("a","eq",1),1);

View File

@@ -114,11 +114,11 @@ public interface EnumDict<V> extends JSONSerializable, Serializable {
}
}
return this == v
|| getValue() == v
|| Objects.equals(getValue(), v)
|| Objects.equals(ordinal(), v)
|| String.valueOf(getValue()).equalsIgnoreCase(String.valueOf(v))
|| getText().equalsIgnoreCase(String.valueOf(v)
|| getValue() == v
|| Objects.equals(getValue(), v)
|| Objects.equals(ordinal(), v)
|| String.valueOf(getValue()).equalsIgnoreCase(String.valueOf(v))
|| getText().equalsIgnoreCase(String.valueOf(v)
);
}
@@ -183,8 +183,8 @@ public interface EnumDict<V> extends JSONSerializable, Serializable {
return Optional.empty();
}
return find(type, e -> e.getValue() == value || e.getValue().equals(value) || String
.valueOf(e.getValue())
.equalsIgnoreCase(String.valueOf(value)));
.valueOf(e.getValue())
.equalsIgnoreCase(String.valueOf(value)));
}
/**
@@ -358,9 +358,9 @@ public interface EnumDict<V> extends JSONSerializable, Serializable {
if (value instanceof Map) {
return (T) EnumDict.find(((Class) type), ((Map) value).get("value"))
.orElseGet(() ->
EnumDict
.find(((Class) type), ((Map) value).get("text"))
.orElse(null));
EnumDict
.find(((Class) type), ((Map) value).get("text"))
.orElse(null));
}
}
@@ -400,14 +400,14 @@ public interface EnumDict<V> extends JSONSerializable, Serializable {
}
Supplier<ValidationException> exceptionSupplier = () -> {
List<Object> values = Stream
.of(findPropertyType.getEnumConstants())
.map(Enum.class::cast)
.map(e -> {
if (e instanceof EnumDict) {
return ((EnumDict) e).getValue();
}
return e.name();
}).collect(Collectors.toList());
.of(findPropertyType.getEnumConstants())
.map(Enum.class::cast)
.map(e -> {
if (e instanceof EnumDict) {
return ((EnumDict) e).getValue();
}
return e.name();
}).collect(Collectors.toList());
return new ValidationException(currentName, "validation.parameter_does_not_exist_in_enums", currentName);
};
@@ -423,38 +423,38 @@ public interface EnumDict<V> extends JSONSerializable, Serializable {
}
}
return (EnumDict) EnumDict
.findByValue(findPropertyType, value)
.orElseThrow(exceptionSupplier);
.findByValue(findPropertyType, value)
.orElseThrow(exceptionSupplier);
}
if (node.isNumber()) {
return (EnumDict) EnumDict
.find(findPropertyType, node.numberValue())
.orElseThrow(exceptionSupplier);
.find(findPropertyType, node.numberValue())
.orElseThrow(exceptionSupplier);
}
if (node.isTextual()) {
return (EnumDict) EnumDict
.find(findPropertyType, node.textValue())
.orElseThrow(exceptionSupplier);
.find(findPropertyType, node.textValue())
.orElseThrow(exceptionSupplier);
}
return exceptionSupplier.get();
}
if (findPropertyType.isEnum()) {
return Stream
.of(findPropertyType.getEnumConstants())
.filter(o -> {
if (node.isTextual()) {
return node.textValue().equalsIgnoreCase(((Enum) o).name());
}
if (node.isNumber()) {
return node.intValue() == ((Enum) o).ordinal();
}
return false;
})
.findAny()
.orElseThrow(exceptionSupplier);
.of(findPropertyType.getEnumConstants())
.filter(o -> {
if (node.isTextual()) {
return node.textValue().equalsIgnoreCase(((Enum) o).name());
}
if (node.isNumber()) {
return node.intValue() == ((Enum) o).ordinal();
}
return false;
})
.findAny()
.orElseThrow(exceptionSupplier);
}
log.warn("unsupported deserialize enum json : {}", node);
log.warn("unsupported deserialize enum json : {} for: {}@{}", node, currentName, currentValue);
return null;
}
}
@@ -478,9 +478,9 @@ public interface EnumDict<V> extends JSONSerializable, Serializable {
*/
static EnumDict<String> create(String value, String text) {
return DefaultItemDefine
.builder()
.value(value)
.text(text)
.build();
.builder()
.value(value)
.text(text)
.build();
}
}