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

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

commit 8c12c10f59c92d0892520d236ecb029275b32a9c
Author: Andrus Adamchik <[email protected]>
AuthorDate: Fri Jul 3 16:27:38 2026 -0400

    Exploring FormattedSlf4jJdbcEventLogger behavior
---
 .../cayenne/log/FormattedSlf4jJdbcEventLogger.java |  12 +-
 .../log/FormattedSlf4jJdbcEventLoggerTest.java     | 167 +++++++++++++++++++++
 2 files changed, 173 insertions(+), 6 deletions(-)

diff --git 
a/cayenne/src/main/java/org/apache/cayenne/log/FormattedSlf4jJdbcEventLogger.java
 
b/cayenne/src/main/java/org/apache/cayenne/log/FormattedSlf4jJdbcEventLogger.java
index 38f8b6561..6bef94dbf 100644
--- 
a/cayenne/src/main/java/org/apache/cayenne/log/FormattedSlf4jJdbcEventLogger.java
+++ 
b/cayenne/src/main/java/org/apache/cayenne/log/FormattedSlf4jJdbcEventLogger.java
@@ -18,15 +18,15 @@
  ****************************************************************/
 package org.apache.cayenne.log;
 
+import org.apache.cayenne.access.jdbc.PSParameter;
+import org.apache.cayenne.configuration.RuntimeProperties;
+import org.apache.cayenne.di.Inject;
+
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.TreeMap;
 
-import org.apache.cayenne.access.jdbc.PSParameter;
-import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.di.Inject;
-
 /**
  * A {@link Slf4jJdbcEventLogger} extension that provides pretty formatting of 
the logged SQL messages.
  * 
@@ -57,7 +57,7 @@ public class FormattedSlf4jJdbcEventLogger extends 
Slf4jJdbcEventLogger {
        super(runtimeProperties);
     }
     
-    private String formatQuery(String sql) {
+    static String formatQuery(String sql) {
         Map<Integer, String> scanResult = scanQuery(sql);
         Iterator<Integer> iter = scanResult.keySet().iterator();
         int nextKeyIdx = (iter.hasNext()) ? iter.next() : -1;
@@ -101,7 +101,7 @@ public class FormattedSlf4jJdbcEventLogger extends 
Slf4jJdbcEventLogger {
         return result;
     }
 
-    private Map<Integer, String> scanQuery(String sql) {
+    private static Map<Integer, String> scanQuery(String sql) {
         Map<Integer, String> result = new TreeMap<>();
         String sql2Lower = sql.toLowerCase();
         for (String keyWrd : KEYWORDS.keySet()) {
diff --git 
a/cayenne/src/test/java/org/apache/cayenne/log/FormattedSlf4jJdbcEventLoggerTest.java
 
b/cayenne/src/test/java/org/apache/cayenne/log/FormattedSlf4jJdbcEventLoggerTest.java
new file mode 100644
index 000000000..a21623ffb
--- /dev/null
+++ 
b/cayenne/src/test/java/org/apache/cayenne/log/FormattedSlf4jJdbcEventLoggerTest.java
@@ -0,0 +1,167 @@
+/*****************************************************************
+ *   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.log;
+
+import org.junit.jupiter.api.Test;
+
+import static org.apache.cayenne.log.FormattedSlf4jJdbcEventLogger.formatQuery;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Assertions use text blocks so the resulting SQL layout is visible. The 
formatter emits trailing spaces on many
+ * lines and indents continuations with a tab; since text blocks strip 
trailing whitespace, those are spelled out
+ * explicitly as {@code \s} (space) and {@code \t} (tab).
+ */
+public class FormattedSlf4jJdbcEventLoggerTest {
+
+    @Test
+    public void formatQuery_breaksBeforeKeywords() {
+        assertEquals("""
+                SELECT *\s
+                FROM ARTIST
+                """,
+                formatQuery("SELECT * FROM ARTIST"));
+    }
+
+    @Test
+    public void formatQuery_fullSelect() {
+        assertEquals("""
+                SELECT t0.ID,
+                \t t0.NAME\s
+                FROM ARTIST t0\s
+                WHERE t0.NAME = ?\s
+                ORDER BY t0.NAME
+                """,
+                formatQuery("SELECT t0.ID, t0.NAME FROM ARTIST t0 WHERE 
t0.NAME = ? ORDER BY t0.NAME"));
+    }
+
+    @Test
+    public void formatQuery_update() {
+        assertEquals("""
+                UPDATE ARTIST\s
+                SET NAME = ?\s
+                WHERE ID = ?
+                """,
+                formatQuery("UPDATE ARTIST SET NAME = ? WHERE ID = ?"));
+    }
+
+    @Test
+    public void formatQuery_delete() {
+        assertEquals("""
+                DELETE\s
+                FROM ARTIST\s
+                WHERE ID = ?
+                """,
+                formatQuery("DELETE FROM ARTIST WHERE ID = ?"));
+    }
+
+    @Test
+    public void formatQuery_insertBreaksOnParensAndCommas() {
+        assertEquals("""
+                INSERT INTO ARTIST (
+                \tID,
+                \t NAME)
+                \t\s
+                VALUES (
+                \t?,
+                \t ?)
+                \t
+                """,
+                formatQuery("INSERT INTO ARTIST (ID, NAME) VALUES (?, ?)"));
+    }
+
+    @Test
+    public void formatQuery_groupBy() {
+        assertEquals("""
+                SELECT COUNT(
+                \t*)
+                \t\s
+                FROM ARTIST\s
+                GROUP BY NAME
+                """,
+                formatQuery("SELECT COUNT(*) FROM ARTIST GROUP BY NAME"));
+    }
+
+    /**
+     * The leading keyword of a statement has no preceding space, so it is not 
matched and not broken onto its own line.
+     */
+    @Test
+    public void formatQuery_leadingKeywordNotBroken() {
+        assertEquals("""
+                SELECT *\s
+                FROM ARTIST
+                """,
+                formatQuery("SELECT * FROM ARTIST"));
+    }
+
+    /**
+     * Keywords, commas and parentheses that appear inside a quoted string 
literal must be left untouched.
+     */
+    @Test
+    public void formatQuery_ignoresContentInsideStringLiterals() {
+        assertEquals("""
+                SELECT *\s
+                FROM T\s
+                WHERE NAME = 'a, b, (c)'
+                """,
+                formatQuery("SELECT * FROM T WHERE NAME = 'a, b, (c)'"));
+        assertEquals("""
+                SELECT *\s
+                FROM T\s
+                WHERE NAME = 'from the where group'
+                """,
+                formatQuery("SELECT * FROM T WHERE NAME = 'from the where 
group'"));
+    }
+
+    /**
+     * A doubled single quote is an escaped apostrophe within a literal and 
must not toggle the "inside literal" state.
+     */
+    @Test
+    public void formatQuery_handlesEscapedQuotesInsideLiterals() {
+        assertEquals("""
+                SELECT *\s
+                FROM T\s
+                WHERE NAME = 'O''Brien from x'
+                """,
+                formatQuery("SELECT * FROM T WHERE NAME = 'O''Brien from x'"));
+    }
+
+    @Test
+    public void formatQuery_collapsesRepeatedSpaces() {
+        assertEquals("""
+                SELECT *\s
+                FROM T
+                """,
+                formatQuery("SELECT   *   FROM   T"));
+    }
+
+    @Test
+    public void formatQuery_noKeywords() {
+        assertEquals("""
+                no keywords here just text
+                """,
+                formatQuery("no keywords here just text"));
+    }
+
+    @Test
+    public void formatQuery_empty() {
+        // a bare newline is clearer as a plain literal than as a text block
+        assertEquals("\n", formatQuery(""));
+    }
+}

Reply via email to