You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2022/07/26 12:19:10 UTC

[cayenne] branch master updated: Fix H2 support

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 1af5ad353 Fix H2 support
1af5ad353 is described below

commit 1af5ad353725c1a9d761d833517c1487d2afd536
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Tue Jul 26 15:19:02 2022 +0300

    Fix H2 support
---
 .../java/org/apache/cayenne/dba/h2/H2Adapter.java  | 14 ++++-
 .../cayenne/dba/h2/H2EJBQLConditionTranslator.java | 66 ++++++++++++++++++++++
 ...rocessor.java => H2EJBQLTranslatorFactory.java} | 16 +++---
 .../apache/cayenne/dba/h2/H2SQLTreeProcessor.java  |  6 ++
 ...reeProcessor.java => H2TrimmingColumnNode.java} | 28 ++++++---
 .../ServerCaseDataSourceDescriptorProvider.java    |  2 +-
 6 files changed, 112 insertions(+), 20 deletions(-)

diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
index 6799ef5de..76714ffe1 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
@@ -21,6 +21,8 @@ package org.apache.cayenne.dba.h2;
 
 import org.apache.cayenne.access.DataNode;
 import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
 import org.apache.cayenne.access.types.ExtendedType;
 import org.apache.cayenne.access.types.ExtendedTypeFactory;
 import org.apache.cayenne.access.types.ExtendedTypeMap;
@@ -28,7 +30,6 @@ import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
 import org.apache.cayenne.configuration.Constants;
 import org.apache.cayenne.configuration.RuntimeProperties;
 import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.query.Query;
@@ -79,6 +80,17 @@ public class H2Adapter extends JdbcAdapter {
         return new H2SQLTreeProcessor();
     }
 
+    /**
+     * @return translator factory for EJBQL queries
+     * @since 4.3
+     */
+    @Override
+    protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
+        JdbcEJBQLTranslatorFactory translatorFactory = new H2EJBQLTranslatorFactory();
+        translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
+        return translatorFactory;
+    }
+
     @Override
     public SQLAction getAction(Query query, DataNode node) {
         return query.createSQLAction(new H2ActionBuilder(node));
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLConditionTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLConditionTranslator.java
new file mode 100644
index 000000000..b8f9d3a44
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLConditionTranslator.java
@@ -0,0 +1,66 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.cayenne.dba.h2;
+
+import java.sql.Types;
+
+import org.apache.cayenne.access.translator.ejbql.EJBQLConditionTranslator;
+import org.apache.cayenne.access.translator.ejbql.EJBQLMultiColumnOperand;
+import org.apache.cayenne.access.translator.ejbql.EJBQLPathTranslator;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
+import org.apache.cayenne.dba.hsqldb.HSQLDBAdapter;
+import org.apache.cayenne.ejbql.EJBQLExpression;
+import org.apache.cayenne.map.ObjAttribute;
+
+/**
+ * @since 4.3
+ */
+public class H2EJBQLConditionTranslator extends EJBQLConditionTranslator {
+
+    H2EJBQLConditionTranslator(EJBQLTranslationContext context) {
+        super(context);
+    }
+
+    @Override
+    public boolean visitPath(EJBQLExpression expression, int finishedChildIndex) {
+
+        expression.visit(new EJBQLPathTranslator(context) {
+
+            @Override
+            protected void appendMultiColumnPath(EJBQLMultiColumnOperand operand) {
+                H2EJBQLConditionTranslator.this.addMultiColumnOperand(operand);
+            }
+
+            @Override
+            protected void processTerminatingAttribute(ObjAttribute attribute) {
+                if (attribute.getDbAttribute().getType() == Types.CHAR) {
+                    context.append(' ').append(HSQLDBAdapter.TRIM_FUNCTION).append("(");
+                    super.processTerminatingAttribute(attribute);
+                    context.append(')');
+                }
+                else {
+                    super.processTerminatingAttribute(attribute);
+                }
+            }
+        });
+
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SQLTreeProcessor.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLTranslatorFactory.java
similarity index 66%
copy from cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SQLTreeProcessor.java
copy to cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLTranslatorFactory.java
index e33fc0712..3706146ec 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SQLTreeProcessor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLTranslatorFactory.java
@@ -19,19 +19,17 @@
 
 package org.apache.cayenne.dba.h2;
 
-import org.apache.cayenne.access.sqlbuilder.sqltree.LimitOffsetNode;
-import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
-import org.apache.cayenne.access.sqlbuilder.sqltree.OffsetFetchNextNode;
-import org.apache.cayenne.access.translator.select.BaseSQLTreeProcessor;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
 
 /**
- * @since 4.2
+ * @since 4.3
  */
-public class H2SQLTreeProcessor extends BaseSQLTreeProcessor {
+public class H2EJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
 
     @Override
-    protected void onLimitOffsetNode(Node parent, LimitOffsetNode child, int index) {
-        replaceChild(parent, index, new OffsetFetchNextNode(child), false);
+    public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
+        return new H2EJBQLConditionTranslator(context);
     }
-
 }
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SQLTreeProcessor.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SQLTreeProcessor.java
index e33fc0712..7ca7f8d75 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SQLTreeProcessor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SQLTreeProcessor.java
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne.dba.h2;
 
+import org.apache.cayenne.access.sqlbuilder.sqltree.ColumnNode;
 import org.apache.cayenne.access.sqlbuilder.sqltree.LimitOffsetNode;
 import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
 import org.apache.cayenne.access.sqlbuilder.sqltree.OffsetFetchNextNode;
@@ -29,6 +30,11 @@ import org.apache.cayenne.access.translator.select.BaseSQLTreeProcessor;
  */
 public class H2SQLTreeProcessor extends BaseSQLTreeProcessor {
 
+    @Override
+    protected void onColumnNode(Node parent, ColumnNode child, int index) {
+        replaceChild(parent, index, new H2TrimmingColumnNode(child));
+    }
+
     @Override
     protected void onLimitOffsetNode(Node parent, LimitOffsetNode child, int index) {
         replaceChild(parent, index, new OffsetFetchNextNode(child), false);
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SQLTreeProcessor.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2TrimmingColumnNode.java
similarity index 57%
copy from cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SQLTreeProcessor.java
copy to cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2TrimmingColumnNode.java
index e33fc0712..10991c8fc 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SQLTreeProcessor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2TrimmingColumnNode.java
@@ -19,19 +19,29 @@
 
 package org.apache.cayenne.dba.h2;
 
-import org.apache.cayenne.access.sqlbuilder.sqltree.LimitOffsetNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.ColumnNode;
 import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
-import org.apache.cayenne.access.sqlbuilder.sqltree.OffsetFetchNextNode;
-import org.apache.cayenne.access.translator.select.BaseSQLTreeProcessor;
+import org.apache.cayenne.access.sqlbuilder.sqltree.NodeType;
+import org.apache.cayenne.access.sqlbuilder.sqltree.TrimmingColumnNode;
 
 /**
- * @since 4.2
+ * @since 4.3
  */
-public class H2SQLTreeProcessor extends BaseSQLTreeProcessor {
-
-    @Override
-    protected void onLimitOffsetNode(Node parent, LimitOffsetNode child, int index) {
-        replaceChild(parent, index, new OffsetFetchNextNode(child), false);
+public class H2TrimmingColumnNode extends TrimmingColumnNode {
+    public H2TrimmingColumnNode(ColumnNode columnNode) {
+        super(columnNode);
     }
 
+    protected boolean isAllowedForTrimming() {
+        Node parent = getParent();
+        while(parent != null) {
+            if(parent.getType() == NodeType.JOIN
+                    || parent.getType() == NodeType.UPDATE_SET
+                    || parent.getType() == NodeType.INSERT_COLUMNS) {
+                return false;
+            }
+            parent = parent.getParent();
+        }
+        return true;
+    }
 }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceDescriptorProvider.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceDescriptorProvider.java
index d887703de..b59a3d754 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceDescriptorProvider.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceDescriptorProvider.java
@@ -90,7 +90,7 @@ public class ServerCaseDataSourceDescriptorProvider implements Provider<UnitData
         h2.setAdapterClassName(H2Adapter.class.getName());
         h2.setUserName("sa");
         h2.setPassword("");
-        h2.setDataSourceUrl("jdbc:h2:mem:aname;DB_CLOSE_DELAY=-1");
+        h2.setDataSourceUrl("jdbc:h2:mem:aname;DB_CLOSE_DELAY=-1;");
         h2.setJdbcDriver("org.h2.Driver");
         h2.setMinConnections(ConnectionProperties.MIN_CONNECTIONS);
         h2.setMaxConnections(ConnectionProperties.MAX_CONNECTIONS);