Browse Source

[优化] 从 hibernate copy最新代码到 SqlFormatter

miemie 6 years ago
parent
commit
9f082155ae

+ 96 - 94
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/sql/SqlFormatter.java

@@ -6,19 +6,13 @@
  */
 package com.baomidou.mybatisplus.core.toolkit.sql;
 
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Locale;
-import java.util.Set;
-import java.util.StringTokenizer;
-
-import com.baomidou.mybatisplus.core.toolkit.StringPool;
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import java.util.*;
 
 /**
  * Performs formatting of basic SQL statements (DML + query).
  * <p>
  * Copy Hibernate BasicFormatterImpl
+ * last commit on 2018-03-15
  * </P>
  *
  * @author Gavin King
@@ -26,7 +20,7 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
  */
 public class SqlFormatter {
 
-    public static final String WHITESPACE = " \n\r\f\t";
+    private static final String WHITESPACE = " \n\r\f\t";
     private static final Set<String> BEGIN_CLAUSES = new HashSet<>();
     private static final Set<String> END_CLAUSES = new HashSet<>();
     private static final Set<String> LOGICAL = new HashSet<>();
@@ -34,7 +28,7 @@ public class SqlFormatter {
     private static final Set<String> DML = new HashSet<>();
     private static final Set<String> MISC = new HashSet<>();
     private static final String INDENT_STRING = "    ";
-    private static final String INITIAL = "\n    ";
+    private static final String INITIAL = System.lineSeparator() + INDENT_STRING;
 
     static {
         BEGIN_CLAUSES.add("left");
@@ -47,9 +41,9 @@ public class SqlFormatter {
         END_CLAUSES.add("where");
         END_CLAUSES.add("set");
         END_CLAUSES.add("having");
-        END_CLAUSES.add("join");
         END_CLAUSES.add("from");
         END_CLAUSES.add("by");
+        END_CLAUSES.add("join");
         END_CLAUSES.add("into");
         END_CLAUSES.add("union");
 
@@ -78,7 +72,6 @@ public class SqlFormatter {
     }
 
     private static class FormatProcess {
-
         boolean beginLine = true;
         boolean afterBeginBeforeEnd;
         boolean afterByOrSetOrFromOrSelect;
@@ -88,18 +81,17 @@ public class SqlFormatter {
         boolean afterInsert;
         int inFunction;
         int parensSinceSelect;
-        private final LinkedList<Integer> parenCounts = new LinkedList<>();
-        private final LinkedList<Boolean> afterByOrFromOrSelects = new LinkedList<>();
+        StringBuilder result = new StringBuilder();
+        StringTokenizer tokens;
 
         int indent = 1;
-
-        final StringBuilder result = new StringBuilder();
-        final StringTokenizer tokens;
+        private LinkedList<Integer> parenCounts = new LinkedList<Integer>();
+        private LinkedList<Boolean> afterByOrFromOrSelects = new LinkedList<Boolean>();
         String lastToken;
         String token;
         String lcToken;
 
-        public FormatProcess(String sql) {
+        FormatProcess(String sql) {
             tokens = new StringTokenizer(
                 sql,
                 "()+*/-=<>'`\"[]," + WHITESPACE,
@@ -107,7 +99,68 @@ public class SqlFormatter {
             );
         }
 
-        public String perform() {
+        private static boolean isFunctionName(String tok) {
+            if (tok == null || tok.length() == 0) {
+                return false;
+            }
+
+            final char begin = tok.charAt(0);
+            final boolean isIdentifier = Character.isJavaIdentifierStart(begin) || '"' == begin;
+            return isIdentifier &&
+                !LOGICAL.contains(tok) &&
+                !END_CLAUSES.contains(tok) &&
+                !QUANTIFIERS.contains(tok) &&
+                !DML.contains(tok) &&
+                !MISC.contains(tok);
+        }
+
+        private void commaAfterOn() {
+            out();
+            indent--;
+            newline();
+            afterOn = false;
+            afterByOrSetOrFromOrSelect = true;
+        }
+
+        private void commaAfterByOrFromOrSelect() {
+            out();
+            newline();
+        }
+
+        private void logical() {
+            if ("end".equals(lcToken)) {
+                indent--;
+            }
+            newline();
+            out();
+            beginLine = false;
+        }
+
+        private void on() {
+            indent++;
+            afterOn = true;
+            newline();
+            out();
+            beginLine = false;
+        }
+
+        private void misc() {
+            out();
+            if ("between".equals(lcToken)) {
+                afterBetween = true;
+            }
+            if (afterInsert) {
+                newline();
+                afterInsert = false;
+            } else {
+                beginLine = false;
+                if ("case".equals(lcToken)) {
+                    indent++;
+                }
+            }
+        }
+
+        String perform() {
 
             result.append(INITIAL);
 
@@ -116,32 +169,39 @@ public class SqlFormatter {
                 lcToken = token.toLowerCase(Locale.ROOT);
 
                 if ("'".equals(token)) {
-                    String t = StringUtils.EMPTY;
+                    String t;
                     do {
-                        try {
-                            t = tokens.nextToken();
-                        } catch (Exception ignored) {
-                        }
+                        t = tokens.nextToken();
                         token += t;
                     }
                     // cannot handle single quotes
                     while (!"'".equals(t) && tokens.hasMoreTokens());
-                } else if (StringPool.QUOTE.equals(token)) {
+                } else if ("\"".equals(token)) {
+                    String t;
+                    do {
+                        t = tokens.nextToken();
+                        token += t;
+                    }
+                    while (!"\"".equals(t) && tokens.hasMoreTokens());
+                }
+                // SQL Server uses "[" and "]" to escape reserved words
+                // see SQLServerDialect.openQuote and SQLServerDialect.closeQuote
+                else if ("[".equals(token)) {
                     String t;
                     do {
                         t = tokens.nextToken();
                         token += t;
                     }
-                    while (!StringPool.QUOTE.equals(t));
+                    while (!"]".equals(t) && tokens.hasMoreTokens());
                 }
 
-                if (afterByOrSetOrFromOrSelect && StringPool.COMMA.equals(token)) {
+                if (afterByOrSetOrFromOrSelect && ",".equals(token)) {
                     commaAfterByOrFromOrSelect();
-                } else if (afterOn && StringPool.COMMA.equals(token)) {
+                } else if (afterOn && ",".equals(token)) {
                     commaAfterOn();
-                } else if (StringPool.LEFT_BRACKET.equals(token)) {
+                } else if ("(".equals(token)) {
                     openParen();
-                } else if (StringPool.RIGHT_BRACKET.equals(token)) {
+                } else if (")".equals(token)) {
                     closeParen();
                 } else if (BEGIN_CLAUSES.contains(lcToken)) {
                     beginNewClause();
@@ -155,7 +215,7 @@ public class SqlFormatter {
                     values();
                 } else if ("on".equals(lcToken)) {
                     on();
-                } else if (afterBetween && "and".equals(lcToken)) {
+                } else if (afterBetween && lcToken.equals("and")) {
                     misc();
                     afterBetween = false;
                 } else if (LOGICAL.contains(lcToken)) {
@@ -174,58 +234,6 @@ public class SqlFormatter {
             return result.toString();
         }
 
-        private void commaAfterOn() {
-            out();
-            indent--;
-            newline();
-            afterOn = false;
-            afterByOrSetOrFromOrSelect = true;
-        }
-
-        private void commaAfterByOrFromOrSelect() {
-            out();
-            newline();
-        }
-
-        private void logical() {
-            if ("end".equals(lcToken)) {
-                indent--;
-            }
-            newline();
-            out();
-            beginLine = false;
-        }
-
-        private void on() {
-            indent++;
-            afterOn = true;
-            newline();
-            out();
-            beginLine = false;
-        }
-
-        private void misc() {
-            out();
-            if ("between".equals(lcToken)) {
-                afterBetween = true;
-            }
-            if (afterInsert) {
-                newline();
-                afterInsert = false;
-            } else {
-                beginLine = false;
-                if ("case".equals(lcToken)) {
-                    indent++;
-                }
-            }
-        }
-
-        private void white() {
-            if (!beginLine) {
-                result.append(StringPool.SPACE);
-            }
-        }
-
         private void updateOrInsertOrDelete() {
             out();
             indent++;
@@ -333,15 +341,10 @@ public class SqlFormatter {
             parensSinceSelect++;
         }
 
-        private static boolean isFunctionName(String tok) {
-            final char begin = tok.charAt(0);
-            final boolean isIdentifier = Character.isJavaIdentifierStart(begin) || '"' == begin;
-            return isIdentifier &&
-                !LOGICAL.contains(tok) &&
-                !END_CLAUSES.contains(tok) &&
-                !QUANTIFIERS.contains(tok) &&
-                !DML.contains(tok) &&
-                !MISC.contains(tok);
+        private void white() {
+            if (!beginLine) {
+                result.append(" ");
+            }
         }
 
         private static boolean isWhitespace(String token) {
@@ -349,12 +352,11 @@ public class SqlFormatter {
         }
 
         private void newline() {
-            result.append(StringPool.NEWLINE);
+            result.append(System.lineSeparator());
             for (int i = 0; i < indent; i++) {
                 result.append(INDENT_STRING);
             }
             beginLine = true;
         }
     }
-
 }

+ 38 - 0
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/toolkit/sql/SqlFormatterTest.java

@@ -0,0 +1,38 @@
+package com.baomidou.mybatisplus.core.toolkit.sql;
+
+import org.junit.Test;
+
+/**
+ * @author miemie
+ * @since 2019-01-09
+ */
+public class SqlFormatterTest {
+
+    @Test
+    public void format() {
+        String format = new SqlFormatter().format(" INSERT INTO bianla_easemob_chat_record \n" +
+            " ( msg_id,\n" +
+            "\tmsg_send_time,\n" +
+            "\tdirection,\n" +
+            "\tsend_from,\n" +
+            "\tsend_to,\n" +
+            "\tchat_type,\n" +
+            "\tbodies,\n" +
+            "\tmsg,\n" +
+            "\text,\n" +
+            "\t`type`,\n" +
+            "\tcreated )  VALUES \n" +
+            " ( '555794876462008332',\n" +
+            "\t'2019-01-09 02:07:58.848',\n" +
+            "\t'outgoing',\n" +
+            "\t'bianla_67248',\n" +
+            "\t'bianla_5197773',\n" +
+            "\t'chat',\n" +
+            "\t'\\'dfsfsfsdf',\n" +
+            "\t'[):][):]',\n" +
+            "\t'{}',\n" +
+            "\t'txt',\n" +
+            "\t'2019-01-09 17:45:33.992' )");
+        System.out.println(format);
+    }
+}