From bd53d19855866b6845494748b8143f82ddb87b8d Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 20 Mar 2020 12:24:56 +0100 Subject: [PATCH] [jOOQ/jOOQ#9925] Add support for XMLPARSE() --- jOOQ/src/main/java/org/jooq/impl/DSL.java | 33 +++++++++ .../src/main/java/org/jooq/impl/Keywords.java | 2 + jOOQ/src/main/java/org/jooq/impl/Names.java | 1 + .../main/java/org/jooq/impl/ParserImpl.java | 28 +++++++ .../src/main/java/org/jooq/impl/XMLParse.java | 74 +++++++++++++++++++ 5 files changed, 138 insertions(+) create mode 100644 jOOQ/src/main/java/org/jooq/impl/XMLParse.java diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index ad3e5f62fd..0a45819fe4 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -394,6 +394,7 @@ import org.jooq.XMLAttributes; import org.jooq.XMLExistsPassingStep; import org.jooq.conf.Settings; import org.jooq.exception.SQLDialectNotSupportedException; +import org.jooq.impl.XMLParse.DocumentOrContent; import org.jooq.tools.Convert; import org.jooq.tools.StringUtils; import org.jooq.tools.jdbc.JDBCUtils; @@ -18094,6 +18095,38 @@ public class DSL { // XXX XML functions // ------------------------------------------------------------------------- + /** + * The XML parse function. + */ + @Support({ POSTGRES }) + public static Field xmlparseDocument(String content) { + return xmlparseDocument(Tools.field(content)); + } + + /** + * The XML parse function. + */ + @Support({ POSTGRES }) + public static Field xmlparseDocument(Field content) { + return new XMLParse(content, DocumentOrContent.DOCUMENT); + } + + /** + * The XML parse function. + */ + @Support({ POSTGRES }) + public static Field xmlparseContent(String content) { + return xmlparseContent(Tools.field(content)); + } + + /** + * The XML parse function. + */ + @Support({ POSTGRES }) + public static Field xmlparseContent(Field content) { + return new XMLParse(content, DocumentOrContent.CONTENT); + } + /** * The XML comment constructor. */ diff --git a/jOOQ/src/main/java/org/jooq/impl/Keywords.java b/jOOQ/src/main/java/org/jooq/impl/Keywords.java index e2c25f5f74..4332a8e612 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Keywords.java +++ b/jOOQ/src/main/java/org/jooq/impl/Keywords.java @@ -98,6 +98,7 @@ final class Keywords { static final Keyword K_CONSTRAINT = keyword("constraint"); static final Keyword K_CONSTRAINTS = keyword("constraints"); static final Keyword K_CONTAINED = keyword("contained"); + static final Keyword K_CONTENT = keyword("content"); static final Keyword K_CONTINUE = keyword("continue"); static final Keyword K_CONTINUE_IDENTITY = keyword("continue identity"); static final Keyword K_CREATE = keyword("create"); @@ -129,6 +130,7 @@ final class Keywords { static final Keyword K_DO = keyword("do"); static final Keyword K_DO_NOTHING = keyword("do nothing"); static final Keyword K_DO_UPDATE = keyword("do update"); + static final Keyword K_DOCUMENT = keyword("document"); static final Keyword K_DROP = keyword("drop"); static final Keyword K_DROP_COLUMN = keyword("drop column"); static final Keyword K_DROP_CONSTRAINT = keyword("drop constraint"); diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index d730885eb5..ba59ddb3f6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -160,6 +160,7 @@ final class Names { static final Name N_XMLCONCAT = DSL.unquotedName("xmlconcat"); static final Name N_XMLELEMENT = DSL.unquotedName("xmlelement"); static final Name N_XMLFOREST = DSL.unquotedName("xmlforest"); + static final Name N_XMLPARSE = DSL.unquotedName("xmlparse"); static final Name N_XMLPI = DSL.unquotedName("xmlpi"); static final Name N_XMLROOT = DSL.unquotedName("xmlroot"); static final Name N_XPATH = DSL.unquotedName("xpath"); diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 2ae4be3f10..5cfc0f29df 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -298,6 +298,8 @@ import static org.jooq.impl.DSL.xmlconcat; import static org.jooq.impl.DSL.xmlelement; import static org.jooq.impl.DSL.xmlexists; import static org.jooq.impl.DSL.xmlforest; +import static org.jooq.impl.DSL.xmlparseContent; +import static org.jooq.impl.DSL.xmlparseDocument; import static org.jooq.impl.DSL.xmlpi; import static org.jooq.impl.DSL.year; import static org.jooq.impl.DSL.zero; @@ -522,6 +524,7 @@ import org.jooq.conf.RenderQuotedNames; import org.jooq.conf.Settings; import org.jooq.conf.SettingsTools; import org.jooq.impl.XMLExists.PassingMechanism; +import org.jooq.impl.XMLParse.DocumentOrContent; import org.jooq.tools.StringUtils; import org.jooq.tools.reflect.Reflect; import org.jooq.types.DayToSecond; @@ -6439,6 +6442,8 @@ final class ParserImpl implements Parser { return field; else if ((field = parseFieldXMLForestIf(ctx)) != null) return field; + else if ((field = parseFieldXMLParseIf(ctx)) != null) + return field; break; @@ -6809,6 +6814,29 @@ final class ParserImpl implements Parser { return null; } + private static final Field parseFieldXMLParseIf(ParserContext ctx) { + if (parseFunctionNameIf(ctx, "XMLPARSE")) { + parse(ctx, '('); + DocumentOrContent documentOrContent; + + if (parseKeywordIf(ctx, "DOCUMENT")) + documentOrContent = DocumentOrContent.DOCUMENT; + else if (parseKeywordIf(ctx, "CONTENT")) + documentOrContent = DocumentOrContent.CONTENT; + else + throw ctx.expected("CONTENT", "DOCUMENT"); + + Field xml = (Field) parseField(ctx); + parse(ctx, ')'); + + return documentOrContent == DocumentOrContent.DOCUMENT + ? xmlparseDocument(xml) + : xmlparseContent(xml); + } + + return null; + } + private static final List> parseAliasedXMLContent(ParserContext ctx) { List> result = new ArrayList<>(); diff --git a/jOOQ/src/main/java/org/jooq/impl/XMLParse.java b/jOOQ/src/main/java/org/jooq/impl/XMLParse.java new file mode 100644 index 0000000000..c02d07707b --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/XMLParse.java @@ -0,0 +1,74 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import static org.jooq.impl.Keywords.K_CONTENT; +import static org.jooq.impl.Keywords.K_DOCUMENT; +import static org.jooq.impl.Names.N_XMLPARSE; +import static org.jooq.impl.XMLParse.DocumentOrContent.DOCUMENT; + +import org.jooq.Context; +import org.jooq.Field; +import org.jooq.XML; + +/** + * @author Lukas Eder + */ +final class XMLParse extends AbstractField { + + /** + * Generated UID + */ + private static final long serialVersionUID = 4505809303211506197L; + private final Field content; + private final DocumentOrContent documentOrContent; + + XMLParse(Field content, DocumentOrContent documentOrContent) { + super(N_XMLPARSE, SQLDataType.XML); + + this.content = content; + this.documentOrContent = documentOrContent; + } + + @Override + public final void accept(Context ctx) { + ctx.visit(N_XMLPARSE).sql('(').visit(documentOrContent == DOCUMENT ? K_DOCUMENT : K_CONTENT).sql(' ').visit(content).sql(')'); + } + + enum DocumentOrContent { DOCUMENT, CONTENT } +}