From 05cdf8cbeefc5a6df07c1896779fbf51dff1145e Mon Sep 17 00:00:00 2001 From: Sergey Korotaev Date: Wed, 2 Jul 2025 10:50:19 +0300 Subject: [PATCH] Allow Table and Column name expressions to return SqlIdentifier Signed-off-by: Sergey Korotaev --- .../BasicRelationalPersistentEntity.java | 13 +++++++------ .../BasicRelationalPersistentProperty.java | 15 +++++++++------ .../core/mapping/RelationalMappingContext.java | 11 ++++++----- ...va => SqlIdentifierExpressionEvaluator.java} | 17 ++++++++++++----- 4 files changed, 34 insertions(+), 22 deletions(-) rename spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/{ExpressionEvaluator.java => SqlIdentifierExpressionEvaluator.java} (67%) diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentEntity.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentEntity.java index e216ee4865..a2a53ef702 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentEntity.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentEntity.java @@ -37,6 +37,7 @@ * @author Bastian Wilhelm * @author Mikhail Polivakha * @author Kurt Niemi + * @author Sergey Korotaev */ class BasicRelationalPersistentEntity extends BasicPersistentEntity implements RelationalPersistentEntity { @@ -47,7 +48,7 @@ class BasicRelationalPersistentEntity extends BasicPersistentEntity> schemaName; private final @Nullable Expression schemaNameExpression; - private final ExpressionEvaluator expressionEvaluator; + private final SqlIdentifierExpressionEvaluator sqlIdentifierExpressionEvaluator; private boolean forceQuote = true; /** @@ -56,11 +57,11 @@ class BasicRelationalPersistentEntity extends BasicPersistentEntity information, NamingStrategy namingStrategy, - ExpressionEvaluator expressionEvaluator) { + SqlIdentifierExpressionEvaluator sqlIdentifierExpressionEvaluator) { super(information); - this.expressionEvaluator = expressionEvaluator; + this.sqlIdentifierExpressionEvaluator = sqlIdentifierExpressionEvaluator; Lazy> defaultSchema = Lazy.of(() -> StringUtils.hasText(namingStrategy.getSchema()) ? Optional.of(createDerivedSqlIdentifier(namingStrategy.getSchema())) @@ -129,7 +130,7 @@ public SqlIdentifier getTableName() { return tableName.get(); } - return createSqlIdentifier(expressionEvaluator.evaluate(tableNameExpression)); + return sqlIdentifierExpressionEvaluator.evaluate(tableNameExpression, isForceQuote()); } @Override @@ -137,7 +138,7 @@ public SqlIdentifier getQualifiedTableName() { SqlIdentifier schema; if (schemaNameExpression != null) { - schema = createSqlIdentifier(expressionEvaluator.evaluate(schemaNameExpression)); + schema = sqlIdentifierExpressionEvaluator.evaluate(schemaNameExpression, isForceQuote()); } else { schema = schemaName.get().orElse(null); } @@ -147,7 +148,7 @@ public SqlIdentifier getQualifiedTableName() { } if (schemaNameExpression != null) { - schema = createSqlIdentifier(expressionEvaluator.evaluate(schemaNameExpression)); + schema = sqlIdentifierExpressionEvaluator.evaluate(schemaNameExpression, isForceQuote()); } return SqlIdentifier.from(schema, getTableName()); diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java index 395174a645..267857ea6c 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java @@ -43,6 +43,7 @@ * @author Florian Lüdiger * @author Bastian Wilhelm * @author Kurt Niemi + * @author Sergey Korotaev */ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistentProperty implements RelationalPersistentProperty { @@ -61,7 +62,9 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent private final NamingStrategy namingStrategy; private boolean forceQuote = true; - private ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator(EvaluationContextProvider.DEFAULT); + + private SqlIdentifierExpressionEvaluator sqlIdentifierExpressionEvaluator = + new SqlIdentifierExpressionEvaluator(EvaluationContextProvider.DEFAULT); /** * Creates a new {@link BasicRelationalPersistentProperty}. @@ -73,7 +76,7 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent * @since 2.0 */ public BasicRelationalPersistentProperty(Property property, PersistentEntity owner, - SimpleTypeHolder simpleTypeHolder, NamingStrategy namingStrategy) { + SimpleTypeHolder simpleTypeHolder, NamingStrategy namingStrategy) { super(property, owner, simpleTypeHolder); this.namingStrategy = namingStrategy; @@ -136,8 +139,8 @@ public BasicRelationalPersistentProperty(Property property, PersistentEntity getPersistentEntity(RelationalPersistentPro protected RelationalPersistentEntity createPersistentEntity(TypeInformation typeInformation) { BasicRelationalPersistentEntity entity = new BasicRelationalPersistentEntity<>(typeInformation, - this.namingStrategy, this.expressionEvaluator); + this.namingStrategy, this.sqlIdentifierExpressionEvaluator); entity.setForceQuote(isForceQuote()); return entity; @@ -171,7 +172,7 @@ public void setSingleQueryLoadingEnabled(boolean singleQueryLoadingEnabled) { protected void applyDefaults(BasicRelationalPersistentProperty persistentProperty) { persistentProperty.setForceQuote(isForceQuote()); - persistentProperty.setExpressionEvaluator(this.expressionEvaluator); + persistentProperty.setSqlIdentifierExpressionEvaluator(this.sqlIdentifierExpressionEvaluator); } /** diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/ExpressionEvaluator.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/SqlIdentifierExpressionEvaluator.java similarity index 67% rename from spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/ExpressionEvaluator.java rename to spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/SqlIdentifierExpressionEvaluator.java index 28933ddfb3..f6b2891cbf 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/ExpressionEvaluator.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/SqlIdentifierExpressionEvaluator.java @@ -1,5 +1,6 @@ package org.springframework.data.relational.core.mapping; +import org.springframework.data.relational.core.sql.SqlIdentifier; import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.expression.EvaluationException; import org.springframework.expression.Expression; @@ -13,25 +14,31 @@ * {@link #setSanitizer(SqlIdentifierSanitizer)} method. * * @author Kurt Niemi + * @author Sergey Korotaev * @see SqlIdentifierSanitizer * @since 3.2 */ -class ExpressionEvaluator { +class SqlIdentifierExpressionEvaluator { private EvaluationContextProvider provider; private SqlIdentifierSanitizer sanitizer = SqlIdentifierSanitizer.words(); - public ExpressionEvaluator(EvaluationContextProvider provider) { + public SqlIdentifierExpressionEvaluator(EvaluationContextProvider provider) { this.provider = provider; } - public String evaluate(Expression expression) throws EvaluationException { + public SqlIdentifier evaluate(Expression expression, boolean isForceQuote) throws EvaluationException { Assert.notNull(expression, "Expression must not be null."); - String result = expression.getValue(provider.getEvaluationContext(null), String.class); - return sanitizer.sanitize(result); + Object value = expression.getValue(provider.getEvaluationContext(null), Object.class); + if (value instanceof SqlIdentifier sqlIdentifier) { + return sqlIdentifier; + } + + String sanitizedResult = sanitizer.sanitize((String) value); + return isForceQuote ? SqlIdentifier.quoted(sanitizedResult) : SqlIdentifier.unquoted(sanitizedResult); } public void setSanitizer(SqlIdentifierSanitizer sanitizer) {