|
13 | 13 | import java.io.InputStream; |
14 | 14 | import java.io.Reader; |
15 | 15 | import java.util.Stack; |
| 16 | +import java.util.ArrayList; |
| 17 | +import java.util.List; |
16 | 18 | import java.util.concurrent.Callable; |
17 | 19 | import java.util.concurrent.ExecutorService; |
18 | 20 | import java.util.concurrent.Executors; |
|
31 | 33 | import net.sf.jsqlparser.statement.Statement; |
32 | 34 | import net.sf.jsqlparser.statement.Statements; |
33 | 35 | import net.sf.jsqlparser.statement.create.table.ColDataType; |
| 36 | +import net.sf.jsqlparser.statement.select.OrderByElement; |
34 | 37 |
|
35 | 38 | /** |
36 | 39 | * Toolfunctions to start and use JSqlParser. |
@@ -242,34 +245,68 @@ public static ColDataType parseColDataType(String columnDataType) throws JSQLPar |
242 | 245 | */ |
243 | 246 | public static ColDataType parseColDataType(String columnDataType, |
244 | 247 | Consumer<CCJSqlParser> consumer) throws JSQLParserException { |
245 | | - if (columnDataType == null || columnDataType.isEmpty()) { |
| 248 | + return parseFragment(columnDataType, "column data type", consumer, |
| 249 | + CCJSqlParser::ColDataType); |
| 250 | + } |
| 251 | + |
| 252 | + /** |
| 253 | + * Parses comma-separated ORDER BY elements without the ORDER BY keywords. Trailing tokens are |
| 254 | + * rejected. Returns an empty list for null or empty input. |
| 255 | + */ |
| 256 | + public static List<OrderByElement> parseOrderByElements(String elements) |
| 257 | + throws JSQLParserException { |
| 258 | + return parseOrderByElements(elements, null); |
| 259 | + } |
| 260 | + |
| 261 | + /** |
| 262 | + * Parses ORDER BY elements with optional parser configuration. The input contains only the |
| 263 | + * elements (for example, {@code name DESC, id ASC}), and must be consumed completely. |
| 264 | + * |
| 265 | + * @return the parsed elements, or an empty list for null or empty input |
| 266 | + * @throws JSQLParserException when the input cannot be parsed completely |
| 267 | + */ |
| 268 | + public static List<OrderByElement> parseOrderByElements(String elements, |
| 269 | + Consumer<CCJSqlParser> consumer) throws JSQLParserException { |
| 270 | + return elements == null || elements.isEmpty() ? new ArrayList<>() |
| 271 | + : parseFragment(elements, "ORDER BY elements", consumer, |
| 272 | + CCJSqlParser::OrderByElementList); |
| 273 | + } |
| 274 | + |
| 275 | + @FunctionalInterface |
| 276 | + private interface FragmentParser<T> { |
| 277 | + T parse(CCJSqlParser parser) throws ParseException; |
| 278 | + } |
| 279 | + |
| 280 | + private static <T> T parseFragment(String input, String description, |
| 281 | + Consumer<CCJSqlParser> consumer, FragmentParser<T> fragment) |
| 282 | + throws JSQLParserException { |
| 283 | + if (input == null || input.isEmpty()) { |
246 | 284 | return null; |
247 | 285 | } |
248 | | - |
249 | 286 | try { |
250 | | - return parseColDataType(columnDataType, false, consumer); |
| 287 | + return parseFragment(input, description, false, consumer, fragment); |
251 | 288 | } catch (JSQLParserException ex) { |
252 | | - return parseColDataType(columnDataType, true, consumer); |
| 289 | + return parseFragment(input, description, true, consumer, fragment); |
253 | 290 | } |
254 | 291 | } |
255 | 292 |
|
256 | | - private static ColDataType parseColDataType(String columnDataType, boolean allowComplexParsing, |
257 | | - Consumer<CCJSqlParser> consumer) throws JSQLParserException { |
258 | | - CCJSqlParser parser = newParser(columnDataType) |
259 | | - .withAllowComplexParsing(allowComplexParsing); |
| 293 | + private static <T> T parseFragment(String input, String description, |
| 294 | + boolean allowComplexParsing, |
| 295 | + Consumer<CCJSqlParser> consumer, FragmentParser<T> fragment) |
| 296 | + throws JSQLParserException { |
| 297 | + CCJSqlParser parser = newParser(input).withAllowComplexParsing(allowComplexParsing); |
260 | 298 | if (consumer != null) { |
261 | 299 | consumer.accept(parser); |
262 | 300 | } |
263 | | - |
264 | 301 | try { |
265 | | - ColDataType result = parser.ColDataType(); |
| 302 | + T result = fragment.parse(parser); |
266 | 303 | if (parser.getNextToken().kind != CCJSqlParserTokenManager.EOF) { |
267 | 304 | throw new JSQLParserException( |
268 | | - "could only parse partial column data type " + result); |
| 305 | + "could only parse partial " + description + " " + result); |
269 | 306 | } |
270 | 307 | return result; |
271 | 308 | } catch (ParseException ex) { |
272 | | - throw new JSQLParserException(columnDataType, ex); |
| 309 | + throw new JSQLParserException(input, ex); |
273 | 310 | } |
274 | 311 | } |
275 | 312 |
|
|
0 commit comments