|
@@ -16,6 +16,7 @@ import java.util.StringTokenizer;
|
|
|
* Performs formatting of basic SQL statements (DML + query).
|
|
|
* <p>
|
|
|
* Copy Hibernate BasicFormatterImpl
|
|
|
+ * last commit on 2018-03-15
|
|
|
* </P>
|
|
|
*
|
|
|
* @author Gavin King
|
|
@@ -23,7 +24,7 @@ import java.util.StringTokenizer;
|
|
|
*/
|
|
|
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<>();
|
|
@@ -31,7 +32,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");
|
|
@@ -44,7 +45,6 @@ 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");
|
|
@@ -86,18 +86,17 @@ public class SqlFormatter {
|
|
|
boolean afterInsert;
|
|
|
int inFunction;
|
|
|
int parensSinceSelect;
|
|
|
- private LinkedList<Integer> parenCounts = new LinkedList<>();
|
|
|
- private LinkedList<Boolean> afterByOrFromOrSelects = new LinkedList<>();
|
|
|
-
|
|
|
- int indent = 1;
|
|
|
-
|
|
|
StringBuilder result = new StringBuilder();
|
|
|
StringTokenizer tokens;
|
|
|
+
|
|
|
+ int indent = 1;
|
|
|
+ private LinkedList<Integer> parenCounts = new LinkedList<>();
|
|
|
+ private LinkedList<Boolean> afterByOrFromOrSelects = new LinkedList<>();
|
|
|
String lastToken;
|
|
|
String token;
|
|
|
String lcToken;
|
|
|
|
|
|
- public FormatProcess(String sql) {
|
|
|
+ FormatProcess(String sql) {
|
|
|
tokens = new StringTokenizer(
|
|
|
sql,
|
|
|
"()+*/-=<>'`\"[]," + WHITESPACE,
|
|
@@ -105,7 +104,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);
|
|
|
|
|
@@ -114,12 +174,9 @@ 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
|
|
@@ -130,7 +187,17 @@ public class SqlFormatter {
|
|
|
t = tokens.nextToken();
|
|
|
token += t;
|
|
|
}
|
|
|
- while (!"\"".equals(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 (!"]".equals(t) && tokens.hasMoreTokens());
|
|
|
}
|
|
|
|
|
|
if (afterByOrSetOrFromOrSelect && ",".equals(token)) {
|
|
@@ -172,58 +239,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(" ");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private void updateOrInsertOrDelete() {
|
|
|
out();
|
|
|
indent++;
|
|
@@ -331,15 +346,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) {
|
|
@@ -347,12 +357,11 @@ public class SqlFormatter {
|
|
|
}
|
|
|
|
|
|
private void newline() {
|
|
|
- result.append("\n");
|
|
|
+ result.append(System.lineSeparator());
|
|
|
for (int i = 0; i < indent; i++) {
|
|
|
result.append(INDENT_STRING);
|
|
|
}
|
|
|
beginLine = true;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
}
|