From d60388b23d9994c3b6dfb42612a423fb3e0edcc5 Mon Sep 17 00:00:00 2001 From: Kirill Kurdyukov Date: Mon, 19 Aug 2024 19:37:04 +0300 Subject: [PATCH 1/5] feat: view index on select from --- .../tech/ydb/hibernate/dialect/YdbDialect.java | 16 ++++++++++++++++ .../student/StudentsRepositoryTest.java | 15 ++++++++++++++- .../tech/ydb/hibernate/student/entity/Group.java | 3 +-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java b/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java index b3f549a..30f494b 100644 --- a/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java +++ b/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java @@ -1,6 +1,8 @@ package tech.ydb.hibernate.dialect; import java.time.LocalDateTime; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.hibernate.boot.model.FunctionContributions; import org.hibernate.boot.model.TypeContributions; import org.hibernate.dialect.Dialect; @@ -62,6 +64,7 @@ public class YdbDialect extends Dialect { private static final Exporter FOREIGN_KEY_EMPTY_EXPORTER = new EmptyExporter<>(); private static final Exporter UNIQUE_KEY_EMPTY_EXPORTER = new EmptyExporter<>(); + private static final Pattern QUERY_PATTERN = Pattern.compile("^\\s*(select.+?from\\s+\\w+)(.+where.+)$", Pattern.CASE_INSENSITIVE); public YdbDialect(DialectResolutionInfo dialectResolutionInfo) { super(dialectResolutionInfo); @@ -118,6 +121,19 @@ public void initializeFunctionRegistry(FunctionContributions functionContributio ); } + @Override + public String getQueryHintString(String query, String hints) { + Matcher matcher = QUERY_PATTERN.matcher(query); + if (matcher.matches() && matcher.groupCount() > 1) { + String startToken = matcher.group(1); + String endToken = matcher.group(2); + + return startToken + " view " + hints + " " + endToken; + } else { + return query; + } + } + @Override public LimitHandler getLimitHandler() { return LimitOffsetLimitHandler.INSTANCE; diff --git a/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/StudentsRepositoryTest.java b/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/StudentsRepositoryTest.java index de17063..ddc4591 100644 --- a/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/StudentsRepositoryTest.java +++ b/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/StudentsRepositoryTest.java @@ -143,7 +143,6 @@ void studentsAndCourses_Lazy_ManyToManyTest() { ); } - @Test void studentsByGroupName_Lazy_OneToManyTest() { inTransaction( @@ -160,6 +159,20 @@ void studentsByGroupName_Lazy_OneToManyTest() { ); } + @Test + void groupByGroupName_ViewIndex() { + inTransaction( + session -> { + Group group = session + .createQuery("FROM Group g WHERE g.name = 'M3439'", Group.class) + .addQueryHint("group_name_index") + .getSingleResult(); + + assertEquals("M3439", group.getName()); + } + ); + } + @Test void studentsByGroupName_Eager_OneToManyTest() { inTransaction( diff --git a/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/entity/Group.java b/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/entity/Group.java index cda1dd8..95b7fce 100644 --- a/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/entity/Group.java +++ b/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/entity/Group.java @@ -7,11 +7,10 @@ import jakarta.persistence.NamedQuery; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; +import java.util.List; import lombok.Getter; import lombok.Setter; -import java.util.List; - /** * @author Kirill Kurdyukov */ From 49178e11b7a0f0b70cddf816c563fd43593601e3 Mon Sep 17 00:00:00 2001 From: Kirill Kurdyukov Date: Mon, 19 Aug 2024 19:42:42 +0300 Subject: [PATCH 2/5] feat: view index on select from --- hibernate-dialect/CHANGELOG.md | 4 ++++ .../src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/hibernate-dialect/CHANGELOG.md b/hibernate-dialect/CHANGELOG.md index c0ed08d..420dd90 100644 --- a/hibernate-dialect/CHANGELOG.md +++ b/hibernate-dialect/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.5 ## + +- Added query hint for view index for "select * from ... where" queries + ## 0.9.4 ## - Fixed the generated bool value diff --git a/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java b/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java index 30f494b..6044002 100644 --- a/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java +++ b/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java @@ -64,7 +64,8 @@ public class YdbDialect extends Dialect { private static final Exporter FOREIGN_KEY_EMPTY_EXPORTER = new EmptyExporter<>(); private static final Exporter UNIQUE_KEY_EMPTY_EXPORTER = new EmptyExporter<>(); - private static final Pattern QUERY_PATTERN = Pattern.compile("^\\s*(select.+?from\\s+\\w+)(.+where.+)$", Pattern.CASE_INSENSITIVE); + private static final Pattern SELECT_FROM_WHERE_QUERY_PATTERN = Pattern + .compile("^\\s*(select.+?from\\s+\\w+)(.+where.+)$", Pattern.CASE_INSENSITIVE); public YdbDialect(DialectResolutionInfo dialectResolutionInfo) { super(dialectResolutionInfo); @@ -123,7 +124,7 @@ public void initializeFunctionRegistry(FunctionContributions functionContributio @Override public String getQueryHintString(String query, String hints) { - Matcher matcher = QUERY_PATTERN.matcher(query); + Matcher matcher = SELECT_FROM_WHERE_QUERY_PATTERN.matcher(query); if (matcher.matches() && matcher.groupCount() > 1) { String startToken = matcher.group(1); String endToken = matcher.group(2); From 9a27eca59ea4184c92e71cb431e1dc253c758579 Mon Sep 17 00:00:00 2001 From: Kirill Kurdyukov Date: Tue, 20 Aug 2024 11:04:36 +0300 Subject: [PATCH 3/5] feat: use_index hint --- .../ydb/hibernate/dialect/YdbDialect.java | 18 ++------ .../dialect/hint/IndexQueryHintHandler.java | 43 +++++++++++++++++++ .../student/StudentsRepositoryTest.java | 2 +- 3 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/hint/IndexQueryHintHandler.java diff --git a/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java b/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java index 6044002..41614b7 100644 --- a/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java +++ b/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/YdbDialect.java @@ -1,8 +1,7 @@ package tech.ydb.hibernate.dialect; import java.time.LocalDateTime; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.List; import org.hibernate.boot.model.FunctionContributions; import org.hibernate.boot.model.TypeContributions; import org.hibernate.dialect.Dialect; @@ -53,6 +52,7 @@ import org.hibernate.type.StandardBasicTypes; import tech.ydb.hibernate.dialect.exporter.EmptyExporter; import tech.ydb.hibernate.dialect.exporter.YdbIndexExporter; +import tech.ydb.hibernate.dialect.hint.IndexQueryHintHandler; import tech.ydb.hibernate.dialect.translator.YdbSqlAstTranslatorFactory; import tech.ydb.hibernate.dialect.types.LocalDateTimeJavaType; import tech.ydb.hibernate.dialect.types.LocalDateTimeJdbcType; @@ -64,8 +64,6 @@ public class YdbDialect extends Dialect { private static final Exporter FOREIGN_KEY_EMPTY_EXPORTER = new EmptyExporter<>(); private static final Exporter UNIQUE_KEY_EMPTY_EXPORTER = new EmptyExporter<>(); - private static final Pattern SELECT_FROM_WHERE_QUERY_PATTERN = Pattern - .compile("^\\s*(select.+?from\\s+\\w+)(.+where.+)$", Pattern.CASE_INSENSITIVE); public YdbDialect(DialectResolutionInfo dialectResolutionInfo) { super(dialectResolutionInfo); @@ -123,16 +121,8 @@ public void initializeFunctionRegistry(FunctionContributions functionContributio } @Override - public String getQueryHintString(String query, String hints) { - Matcher matcher = SELECT_FROM_WHERE_QUERY_PATTERN.matcher(query); - if (matcher.matches() && matcher.groupCount() > 1) { - String startToken = matcher.group(1); - String endToken = matcher.group(2); - - return startToken + " view " + hints + " " + endToken; - } else { - return query; - } + public String getQueryHintString(String query, List hintList) { + return IndexQueryHintHandler.INSTANCE.addQueryHints(query, hintList); } @Override diff --git a/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/hint/IndexQueryHintHandler.java b/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/hint/IndexQueryHintHandler.java new file mode 100644 index 0000000..b0418e7 --- /dev/null +++ b/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/hint/IndexQueryHintHandler.java @@ -0,0 +1,43 @@ +package tech.ydb.hibernate.dialect.hint; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Kirill Kurdyukov + */ +public class IndexQueryHintHandler { + private static final Pattern SELECT_FROM_WHERE_QUERY_PATTERN = Pattern + .compile("^\\s*(select.+?from\\s+\\w+)(.+where.+)$", Pattern.CASE_INSENSITIVE); + + public static final String HINT_USE_INDEX = "use_index"; + public static final IndexQueryHintHandler INSTANCE = new IndexQueryHintHandler(); + + public String addQueryHints(String query, List hints) { + if (hints.isEmpty()) { + return query; + } + + var useIndexes = new ArrayList(); + hints.forEach(hint -> { + var hintSplit = hint.split(":"); + if (hintSplit.length == 2 && hintSplit[0].equals(HINT_USE_INDEX)) { + useIndexes.add(hintSplit[1]); + } + }); + + if (!useIndexes.isEmpty()) { + Matcher matcher = SELECT_FROM_WHERE_QUERY_PATTERN.matcher(query); + if (matcher.matches() && matcher.groupCount() > 1) { + String startToken = matcher.group(1); + String endToken = matcher.group(2); + + return startToken + " view " + String.join(", ", useIndexes) + endToken; + } + } + + return query; + } +} diff --git a/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/StudentsRepositoryTest.java b/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/StudentsRepositoryTest.java index ddc4591..1ef2a9e 100644 --- a/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/StudentsRepositoryTest.java +++ b/hibernate-dialect/src/test/java/tech/ydb/hibernate/student/StudentsRepositoryTest.java @@ -165,7 +165,7 @@ void groupByGroupName_ViewIndex() { session -> { Group group = session .createQuery("FROM Group g WHERE g.name = 'M3439'", Group.class) - .addQueryHint("group_name_index") + .addQueryHint("use_index:group_name_index") .getSingleResult(); assertEquals("M3439", group.getName()); From ea0adf58517268c0540c3cf62a20dbeac5fb4871 Mon Sep 17 00:00:00 2001 From: Kirill Kurdyukov Date: Tue, 20 Aug 2024 11:06:16 +0300 Subject: [PATCH 4/5] feat: hibernate 6 add java 21 --- .github/workflows/ci-hibernate-dialect.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-hibernate-dialect.yaml b/.github/workflows/ci-hibernate-dialect.yaml index 6c20a52..620050f 100644 --- a/.github/workflows/ci-hibernate-dialect.yaml +++ b/.github/workflows/ci-hibernate-dialect.yaml @@ -20,7 +20,7 @@ jobs: strategy: matrix: - java: [ '17' ] + java: [ '17', '21' ] steps: - uses: actions/checkout@v4 From 7c3b15043b35dd140a7fdd8dd19789f9ec2d75db Mon Sep 17 00:00:00 2001 From: Kirill Kurdyukov Date: Tue, 20 Aug 2024 11:25:39 +0300 Subject: [PATCH 5/5] feat: fix issue --- .../ydb/hibernate/dialect/hint/IndexQueryHintHandler.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/hint/IndexQueryHintHandler.java b/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/hint/IndexQueryHintHandler.java index b0418e7..f397aab 100644 --- a/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/hint/IndexQueryHintHandler.java +++ b/hibernate-dialect/src/main/java/tech/ydb/hibernate/dialect/hint/IndexQueryHintHandler.java @@ -12,7 +12,7 @@ public class IndexQueryHintHandler { private static final Pattern SELECT_FROM_WHERE_QUERY_PATTERN = Pattern .compile("^\\s*(select.+?from\\s+\\w+)(.+where.+)$", Pattern.CASE_INSENSITIVE); - public static final String HINT_USE_INDEX = "use_index"; + public static final String HINT_USE_INDEX = "use_index:"; public static final IndexQueryHintHandler INSTANCE = new IndexQueryHintHandler(); public String addQueryHints(String query, List hints) { @@ -22,9 +22,8 @@ public String addQueryHints(String query, List hints) { var useIndexes = new ArrayList(); hints.forEach(hint -> { - var hintSplit = hint.split(":"); - if (hintSplit.length == 2 && hintSplit[0].equals(HINT_USE_INDEX)) { - useIndexes.add(hintSplit[1]); + if (hint.startsWith(HINT_USE_INDEX)) { + useIndexes.add(hint.substring(HINT_USE_INDEX.length())); } });