1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sql.parser.sql.common.util;
19
20 import com.google.common.base.CharMatcher;
21 import com.google.common.base.Strings;
22 import lombok.AccessLevel;
23 import lombok.NoArgsConstructor;
24 import org.apache.shardingsphere.sql.parser.api.ASTNode;
25 import org.apache.shardingsphere.sql.parser.sql.common.enums.Paren;
26 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
27 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
28 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
29 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
30 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
31 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
32 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.BooleanLiteralValue;
33 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.NullLiteralValue;
34 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.NumberLiteralValue;
35 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.OtherLiteralValue;
36 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue;
37
38 import java.math.BigDecimal;
39 import java.math.BigInteger;
40 import java.util.LinkedList;
41 import java.util.List;
42
43
44
45
46 @NoArgsConstructor(access = AccessLevel.PRIVATE)
47 public final class SQLUtils {
48
49 private static final String BACKTICK = "`";
50
51 private static final String SQL_END = ";";
52
53 private static final String COMMENT_PREFIX = "/*";
54
55 private static final String COMMENT_SUFFIX = "*/";
56
57 private static final String EXCLUDED_CHARACTERS = "[]'\"";
58
59
60
61
62
63
64
65
66 public static Number getExactlyNumber(final String value, final int radix) {
67 try {
68 return getBigInteger(value, radix);
69 } catch (final NumberFormatException ex) {
70 return new BigDecimal(value);
71 }
72 }
73
74 private static Number getBigInteger(final String value, final int radix) {
75 BigInteger result = new BigInteger(value, radix);
76 if (result.compareTo(new BigInteger(String.valueOf(Integer.MIN_VALUE))) >= 0 && result.compareTo(new BigInteger(String.valueOf(Integer.MAX_VALUE))) <= 0) {
77 return result.intValue();
78 }
79 if (result.compareTo(new BigInteger(String.valueOf(Long.MIN_VALUE))) >= 0 && result.compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) <= 0) {
80 return result.longValue();
81 }
82 return result;
83 }
84
85
86
87
88
89
90
91
92
93 public static String getExactlyValue(final String value) {
94 return null == value ? null : tryGetRealContentInBackticks(CharMatcher.anyOf(EXCLUDED_CHARACTERS).removeFrom(value));
95 }
96
97
98
99
100
101
102
103
104
105
106 public static String getExactlyValue(final String value, final String reservedCharacters) {
107 if (null == value) {
108 return null;
109 }
110 String toBeExcludedCharacters = CharMatcher.anyOf(reservedCharacters).removeFrom(EXCLUDED_CHARACTERS);
111 return CharMatcher.anyOf(toBeExcludedCharacters).removeFrom(value);
112 }
113
114
115
116
117
118
119
120
121
122 public static String tryGetRealContentInBackticks(final String value) {
123 if (null == value) {
124 return null;
125 }
126 if (value.startsWith(BACKTICK) && value.endsWith(BACKTICK)) {
127 int startIndex = 1;
128 int stopIndex = value.length() - 1;
129 StringBuilder exactlyTableName = new StringBuilder();
130 while (startIndex < stopIndex) {
131 if (value.charAt(startIndex) == '`' && (startIndex + 1 >= stopIndex || value.charAt(startIndex + 1) != '`')) {
132 return value;
133 } else if (value.charAt(startIndex) == '`' && value.charAt(startIndex + 1) == '`') {
134 startIndex++;
135 }
136 exactlyTableName.append(value.charAt(startIndex));
137 startIndex++;
138 }
139 return 0 == exactlyTableName.length() ? value : exactlyTableName.toString();
140 }
141 return value;
142 }
143
144
145
146
147
148
149
150
151
152 public static String getExactlyExpression(final String value) {
153 return Strings.isNullOrEmpty(value) ? value : CharMatcher.anyOf(" ").removeFrom(value);
154 }
155
156
157
158
159
160
161
162 public static String getExpressionWithoutOutsideParentheses(final String value) {
163 int parenthesesOffset = getParenthesesOffset(value);
164 return 0 == parenthesesOffset ? value : value.substring(parenthesesOffset, value.length() - parenthesesOffset);
165 }
166
167 private static int getParenthesesOffset(final String value) {
168 int result = 0;
169 if (Strings.isNullOrEmpty(value)) {
170 return result;
171 }
172 while (Paren.PARENTHESES.getLeftParen() == value.charAt(result)) {
173 result++;
174 }
175 return result;
176 }
177
178
179
180
181
182
183
184 public static List<SubqueryTableSegment> getSubqueryTableSegmentFromTableSegment(final TableSegment tableSegment) {
185 List<SubqueryTableSegment> result = new LinkedList<>();
186 if (tableSegment instanceof SubqueryTableSegment) {
187 result.add((SubqueryTableSegment) tableSegment);
188 }
189 if (tableSegment instanceof JoinTableSegment) {
190 result.addAll(getSubqueryTableSegmentFromJoinTableSegment((JoinTableSegment) tableSegment));
191 }
192 return result;
193 }
194
195 private static List<SubqueryTableSegment> getSubqueryTableSegmentFromJoinTableSegment(final JoinTableSegment joinTableSegment) {
196 List<SubqueryTableSegment> result = new LinkedList<>();
197 if (joinTableSegment.getLeft() instanceof SubqueryTableSegment) {
198 result.add((SubqueryTableSegment) joinTableSegment.getLeft());
199 } else if (joinTableSegment.getLeft() instanceof JoinTableSegment) {
200 result.addAll(getSubqueryTableSegmentFromJoinTableSegment((JoinTableSegment) joinTableSegment.getLeft()));
201 }
202 if (joinTableSegment.getRight() instanceof SubqueryTableSegment) {
203 result.add((SubqueryTableSegment) joinTableSegment.getRight());
204 } else if (joinTableSegment.getRight() instanceof JoinTableSegment) {
205 result.addAll(getSubqueryTableSegmentFromJoinTableSegment((JoinTableSegment) joinTableSegment.getRight()));
206 }
207 return result;
208 }
209
210
211
212
213
214
215
216
217
218
219 public static ExpressionSegment createLiteralExpression(final ASTNode astNode, final int startIndex, final int stopIndex, final String text) {
220 if (astNode instanceof StringLiteralValue) {
221 return new LiteralExpressionSegment(startIndex, stopIndex, ((StringLiteralValue) astNode).getValue());
222 }
223 if (astNode instanceof NumberLiteralValue) {
224 return new LiteralExpressionSegment(startIndex, stopIndex, ((NumberLiteralValue) astNode).getValue());
225 }
226 if (astNode instanceof BooleanLiteralValue) {
227 return new LiteralExpressionSegment(startIndex, stopIndex, ((BooleanLiteralValue) astNode).getValue());
228 }
229 if (astNode instanceof NullLiteralValue) {
230 return new LiteralExpressionSegment(startIndex, stopIndex, null);
231 }
232 if (astNode instanceof OtherLiteralValue) {
233 return new CommonExpressionSegment(startIndex, stopIndex, ((OtherLiteralValue) astNode).getValue());
234 }
235 return new CommonExpressionSegment(startIndex, stopIndex, text);
236 }
237
238
239
240
241
242
243
244 public static String trimSemicolon(final String sql) {
245 return sql.endsWith(SQL_END) ? sql.substring(0, sql.length() - 1) : sql;
246 }
247
248
249
250
251
252
253
254 public static String trimComment(final String sql) {
255 String result = sql;
256 if (sql.startsWith(COMMENT_PREFIX)) {
257 result = result.substring(sql.indexOf(COMMENT_SUFFIX) + 2);
258 }
259 if (sql.endsWith(SQL_END)) {
260 result = result.substring(0, result.length() - 1);
261 }
262 return result.trim();
263 }
264 }