From 7c80289e3506adb86f9767d5e298d547fdf9d7d2 Mon Sep 17 00:00:00 2001 From: lukaseder Date: Thu, 22 Feb 2018 11:03:06 +0100 Subject: [PATCH] [#7171] Add support for parsing Oracle-style hints --- .../main/java/org/jooq/impl/ParserImpl.java | 54 +++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 7cd6b06a8b..433c68d3a3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -888,6 +888,7 @@ final class ParserImpl implements Parser { } parseKeyword(ctx, "SELECT"); + String hints = parseHints(ctx); boolean distinct = parseKeywordIf(ctx, "DISTINCT") || parseKeywordIf(ctx, "UNIQUE"); List> distinctOn = null; @@ -1019,6 +1020,9 @@ final class ParserImpl implements Parser { // TODO support WINDOW SelectQueryImpl result = new SelectQueryImpl(ctx.dsl.configuration(), with); + if (hints != null) + result.addHint(hints); + if (distinct) result.setDistinct(distinct); @@ -3410,6 +3414,41 @@ final class ParserImpl implements Parser { return toField(ctx, parseConcat(ctx, type)); } + private static final String parseHints(ParserContext ctx) { + ctx.ignoreHints = false; + StringBuilder sb = new StringBuilder(); + + while (parseWhitespaceIf(ctx)) { + int position = ctx.position; + if (parseIf(ctx, '/')) { + parse(ctx, '*'); + + int i = ctx.position; + + loop: + while (i < ctx.sql.length) { + switch (ctx.sql[i]) { + case '*': + if (i + 1 < ctx.sql.length && ctx.sql[i + 1] == '/') + break loop; + } + + i++; + } + + ctx.position = i + 2; + + if (sb.length() > 0) + sb.append(' '); + + sb.append(new String(ctx.sql, position, ctx.position - position)); + } + } + + ctx.ignoreHints = true; + return sb.length() > 0 ? sb.toString() : null; + } + private static final Condition toCondition(ParserContext ctx, QueryPart part) { if (part == null) return null; @@ -7046,16 +7085,22 @@ final class ParserImpl implements Parser { while (i < ctx.sql.length) { switch (ctx.sql[i]) { + case '+': + if (!ctx.ignoreHints && i + 1 < ctx.sql.length && Character.isAlphabetic(ctx.sql[i + 1])) + break loop; + + break; + case '*': if (i + 1 < ctx.sql.length && ctx.sql[i + 1] == '/') { position = i = i + 1; continue loop; } - // No break - default: - i++; + break; } + + i++; } } @@ -7104,7 +7149,8 @@ final class ParserImpl implements Parser { final ParseWithMetaLookups metaLookups; final String sqlString; final char[] sql; - int position = 0; + int position = 0; + boolean ignoreHints = true; final Object[] bindings; int bindIndex = 0; String delimiter = ";";