This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch STABLE-4.2
in repository https://gitbox.apache.org/repos/asf/cayenne.git


The following commit(s) were added to refs/heads/STABLE-4.2 by this push:
     new 2a9debc1c CAY-2813 Regression: Constants.CI_PROPERTY flag is no longer 
working for MySQL
2a9debc1c is described below

commit 2a9debc1c84d4f82bc688114f7f993f1d0193e6f
Author: Nikita Timofeev <[email protected]>
AuthorDate: Wed Aug 23 22:32:01 2023 +0300

    CAY-2813 Regression: Constants.CI_PROPERTY flag is no longer working for 
MySQL
    
    (cherry picked from commit 983c51cd1f322ccbaa0468afe693adf938c3c1fe)
---
 RELEASE-NOTES.txt                                  |  1 +
 .../select/TypeAwareSQLTreeProcessor.java          |  3 +-
 .../org/apache/cayenne/dba/mysql/MySQLAdapter.java |  2 +-
 .../cayenne/dba/mysql/MySQLTreeProcessor.java      | 14 +++++---
 .../cayenne/dba/mysql/sqltree/MysqlLikeNode.java   |  2 +-
 .../access/sqlbuilder/BaseSqlBuilderTest.java      | 10 +++---
 .../cayenne/dba/mysql/MySQLTreeProcessorTest.java  | 42 ++++++++++++++++++++++
 7 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 1954a0dc8..10b3227e4 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -18,6 +18,7 @@ Bug Fixes:
 CAY-2806 Incorrect processing of unicode escape syntax in JSON
 CAY-2809 Cayenne Expression grammar doesn't allow custom function as an 
argument for string functions
 CAY-2810 Can't use custom operator expression with aggregate functions
+CAY-2813 Regression: Constants.CI_PROPERTY flag is no longer working for MySQL
 
 ----------------------------------
 Release: 4.2
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TypeAwareSQLTreeProcessor.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TypeAwareSQLTreeProcessor.java
index 7e48aed3f..b1f36b312 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TypeAwareSQLTreeProcessor.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TypeAwareSQLTreeProcessor.java
@@ -92,7 +92,8 @@ public class TypeAwareSQLTreeProcessor extends 
SimpleNodeTreeVisitor implements
 
     protected DbAttribute getColumnAttribute(ColumnNode node) {
         DbAttribute attribute = node.getAttribute();
-        if(attribute.getType() == Types.OTHER
+        if(attribute != null
+                && attribute.getType() == Types.OTHER
                 && node.getParent() != null
                 && node.getParent().getType() == NodeType.RESULT) {
             return attribute;
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java 
b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
index 1573379ff..9a2acfef5 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
@@ -112,7 +112,7 @@ public class MySQLAdapter extends JdbcAdapter {
      */
        @Override
        public SQLTreeProcessor getSqlTreeProcessor() {
-               return MySQLTreeProcessor.getInstance();
+               return 
MySQLTreeProcessor.getInstance(caseInsensitiveCollations);
        }
 
        /**
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLTreeProcessor.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLTreeProcessor.java
index f8243f5e8..e5ab32556 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLTreeProcessor.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLTreeProcessor.java
@@ -38,14 +38,18 @@ import org.apache.cayenne.value.Wkt;
  */
 public class MySQLTreeProcessor extends TypeAwareSQLTreeProcessor {
 
-    private static final MySQLTreeProcessor INSTANCE = new 
MySQLTreeProcessor();
+    private static final MySQLTreeProcessor INSTANCE_CI = new 
MySQLTreeProcessor(true);
+    private static final MySQLTreeProcessor INSTANCE_CS = new 
MySQLTreeProcessor(false);
 
-    public static MySQLTreeProcessor getInstance() {
-        return INSTANCE;
+    public static MySQLTreeProcessor getInstance(boolean 
caseInsensitiveCollations) {
+        return caseInsensitiveCollations ? INSTANCE_CI : INSTANCE_CS;
     }
 
-    protected MySQLTreeProcessor() {
-        registerProcessor(NodeType.LIKE, (ChildProcessor<LikeNode>) 
this::onLikeNode);
+    protected MySQLTreeProcessor(boolean ciCollations) {
+        if(ciCollations) {
+            // For case insensitive collations we need to use `LIKE BINARY` 
operator to keep strict `LIKE` semantics
+            registerProcessor(NodeType.LIKE, (ChildProcessor<LikeNode>) 
this::onLikeNode);
+        }
         registerProcessor(NodeType.LIMIT_OFFSET, 
(ChildProcessor<LimitOffsetNode>) this::onLimitOffsetNode);
         registerProcessor(NodeType.FUNCTION, (ChildProcessor<FunctionNode>) 
this::onFunctionNode);
 
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/sqltree/MysqlLikeNode.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/sqltree/MysqlLikeNode.java
index 0a0ec454d..35d1470ae 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/sqltree/MysqlLikeNode.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/sqltree/MysqlLikeNode.java
@@ -36,7 +36,7 @@ public class MysqlLikeNode extends LikeNode {
         if (not) {
             buffer.append(" NOT");
         }
-        buffer.append(" LIKE BINARY ");
+        buffer.append(" LIKE BINARY");
     }
 
     @Override
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/access/sqlbuilder/BaseSqlBuilderTest.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/access/sqlbuilder/BaseSqlBuilderTest.java
index 0df1e5066..f07862199 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/access/sqlbuilder/BaseSqlBuilderTest.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/access/sqlbuilder/BaseSqlBuilderTest.java
@@ -22,23 +22,23 @@ import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
 
 import static org.junit.Assert.assertEquals;
 
-class BaseSqlBuilderTest {
+public class BaseSqlBuilderTest {
 
-    void assertSQL(String expected, Node node) {
+    protected void assertSQL(String expected, Node node) {
         assertSQL(expected, node, new StringBuilderAppendable());
     }
 
-    void assertQuotedSQL(String expected, Node node) {
+    protected void assertQuotedSQL(String expected, Node node) {
         assertSQL(expected, node, new MockQuotedStringBuilderAppendable());
     }
 
-    void assertSQL(String expected, Node node, QuotingAppendable appendable) {
+    protected void assertSQL(String expected, Node node, QuotingAppendable 
appendable) {
         SQLGenerationVisitor visitor = new SQLGenerationVisitor(appendable);
         node.visit(visitor);
         assertEquals(expected, visitor.getSQLString());
     }
 
-    static class MockQuotedStringBuilderAppendable extends 
StringBuilderAppendable {
+    protected static class MockQuotedStringBuilderAppendable extends 
StringBuilderAppendable {
         @Override
         public QuotingAppendable appendQuoted(CharSequence csq) {
             builder.append('`').append(csq).append('`');
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/dba/mysql/MySQLTreeProcessorTest.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/dba/mysql/MySQLTreeProcessorTest.java
new file mode 100644
index 000000000..4a35c1247
--- /dev/null
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/dba/mysql/MySQLTreeProcessorTest.java
@@ -0,0 +1,42 @@
+package org.apache.cayenne.dba.mysql;
+
+import org.apache.cayenne.access.sqlbuilder.BaseSqlBuilderTest;
+import org.apache.cayenne.access.sqlbuilder.sqltree.LikeNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.cayenne.access.sqlbuilder.SQLBuilder.*;
+
+public class MySQLTreeProcessorTest extends BaseSqlBuilderTest {
+
+    private Node sqlNode;
+
+    @Before
+    public void generateSql() {
+        sqlNode = select(column("*"))
+                .from(table("test"))
+                .where(() -> {
+                    Node node = new LikeNode(false, false, (char) 0);
+                    node.addChild(column("column").build());
+                    node.addChild(value("abc").build());
+                    return node;
+                })
+                .build();
+        assertSQL("SELECT * FROM test WHERE column LIKE 'abc'", sqlNode);
+    }
+
+    @Test
+    public void testLikeCI() {
+        MySQLTreeProcessor instance = MySQLTreeProcessor.getInstance(true);
+        Node processed = instance.process(sqlNode);
+        assertSQL("SELECT * FROM test WHERE column LIKE BINARY 'abc'", 
processed);
+    }
+
+    @Test
+    public void testLikeCS() {
+        MySQLTreeProcessor instance = MySQLTreeProcessor.getInstance(false);
+        Node processed = instance.process(sqlNode);
+        assertSQL("SELECT * FROM test WHERE column LIKE 'abc'", processed);
+    }
+}
\ No newline at end of file

Reply via email to