[jOOQ/jOOQ#13408] Can't generate xsi:nil attribute, just generate nil

This commit is contained in:
Lukas Eder 2022-04-04 11:54:30 +02:00
parent 3582e1a8cc
commit 5ceedce7e7
9 changed files with 51 additions and 19 deletions

View File

@ -39,7 +39,7 @@ package org.jooq.impl;
import static org.jooq.SQLDialect.DERBY;
import static org.jooq.impl.DSL.selectFrom;
import static org.jooq.impl.Names.N_SELECT;
import static org.jooq.impl.Names.NQ_SELECT;
import static org.jooq.impl.Tools.selectQueryImpl;
import static org.jooq.impl.Tools.visitSubquery;
import static org.jooq.impl.Tools.DataKey.DATA_SELECT_ALIASES;
@ -72,7 +72,7 @@ final class AliasedSelect<R extends Record> extends AbstractTable<R> implements
}
AliasedSelect(Select<R> query, boolean subquery, boolean ignoreOrderBy, Name... aliases) {
super(TableOptions.expression(), N_SELECT);
super(TableOptions.expression(), NQ_SELECT);
this.query = query;
this.subquery = subquery;

View File

@ -49,7 +49,7 @@ import static org.jooq.impl.Keywords.K_SWITCH;
import static org.jooq.impl.Keywords.K_THEN;
import static org.jooq.impl.Keywords.K_TRUE;
import static org.jooq.impl.Keywords.K_WHEN;
import static org.jooq.impl.Names.N_CASE;
import static org.jooq.impl.Names.NQ_CASE;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_FORCE_CASE_ELSE_NULL;
import java.util.ArrayList;
@ -75,7 +75,7 @@ final class CaseConditionStepImpl<T> extends AbstractField<T> implements CaseCon
private Field<T> else_;
CaseConditionStepImpl(Condition condition, Field<T> result) {
super(N_CASE, result.getDataType());
super(NQ_CASE, result.getDataType());
this.conditions = new ArrayList<>();
this.results = new ArrayList<>();

View File

@ -46,7 +46,7 @@ import static org.jooq.impl.Keywords.K_SWITCH;
import static org.jooq.impl.Keywords.K_THEN;
import static org.jooq.impl.Keywords.K_TRUE;
import static org.jooq.impl.Keywords.K_WHEN;
import static org.jooq.impl.Names.N_CASE;
import static org.jooq.impl.Names.NQ_CASE;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_FORCE_CASE_ELSE_NULL;
import java.util.ArrayList;
@ -82,7 +82,7 @@ final class CaseWhenStepImpl<V, T> extends AbstractField<T> implements CaseWhenS
}
private CaseWhenStepImpl(Field<V> value, DataType<T> type) {
super(N_CASE, type);
super(NQ_CASE, type);
this.value = value;
this.compareValues = new ArrayList<>();

View File

@ -42,12 +42,14 @@ import static java.lang.Boolean.TRUE;
// ...
// ...
import static org.jooq.SQLDialect.POSTGRES;
// ...
import static org.jooq.SQLDialect.YUGABYTEDB;
import static org.jooq.impl.DSL.function;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.jsonArray;
import static org.jooq.impl.DSL.jsonEntry;
import static org.jooq.impl.DSL.jsonbArray;
import static org.jooq.impl.DSL.quotedName;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.selectFrom;
import static org.jooq.impl.DSL.when;
@ -57,6 +59,7 @@ import static org.jooq.impl.DSL.xmlelement;
import static org.jooq.impl.DSL.xmlserializeContent;
import static org.jooq.impl.JSONArrayAgg.patchOracleArrayAggBug;
import static org.jooq.impl.Keywords.K_MULTISET;
import static org.jooq.impl.Names.NQ_RESULT;
import static org.jooq.impl.Names.N_JSON_QUERY;
import static org.jooq.impl.Names.N_MULTISET;
import static org.jooq.impl.Names.N_RECORD;
@ -284,13 +287,13 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
XMLAggOrderByStep<XML> order;
AggregateFilterStep<XML> filter;
filter = order = xmlaggEmulation(t, false);
filter = order = xmlaggEmulation(ctx, t, false);
// TODO: Re-apply derived table's ORDER BY clause as aggregate ORDER BY
if (multisetCondition)
filter = order.orderBy(t.fields());
Select<Record1<XML>> s = select(xmlelement(N_RESULT, filter)).from(t);
Select<Record1<XML>> s = select(xmlelement(nResult(ctx), filter)).from(t);
if (multisetCondition && NO_SUPPORT_XML_COMPARE.contains(ctx.dialect()))
ctx.visit(xmlserializeContent(DSL.field(s), VARCHAR));
@ -310,6 +313,28 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
}
}
static final Name nResult(Scope ctx) {
switch (ctx.family()) {
default:
return N_RESULT;
}
}
static final Name xsiNil(Context<?> ctx) {
switch (ctx.family()) {
default:
return DSL.name("xsi:nil");
}
}
static final <J> Field<J> returningClob(Scope ctx, JSONObjectReturningStep<J> j) {
switch (ctx.family()) {
@ -401,7 +426,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
}
}
static final XMLAggOrderByStep<XML> xmlaggEmulation(Fields fields, boolean agg) {
static final XMLAggOrderByStep<XML> xmlaggEmulation(Context<?> ctx, Fields fields, boolean agg) {
return xmlagg(
xmlelement(N_RECORD,
map(fields.fields(), (f, i) -> {
@ -410,7 +435,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
// [#13181] We must make the '' vs NULL distinction explicit in XML
if (v.getDataType().isString())
return xmlelement(n, xmlattributes(when(v.isNull(), inline("true")).as("xsi:nil")), v);
return xmlelement(n, xmlattributes(when(v.isNull(), inline("true")).as(xsiNil(ctx))), v);
else
return xmlelement(n, v);
})

View File

@ -46,6 +46,7 @@ import static org.jooq.impl.Multiset.NO_SUPPORT_JSON_COMPARE;
import static org.jooq.impl.Multiset.NO_SUPPORT_XML_COMPARE;
import static org.jooq.impl.Multiset.jsonArrayaggEmulation;
import static org.jooq.impl.Multiset.jsonbArrayaggEmulation;
import static org.jooq.impl.Multiset.nResult;
import static org.jooq.impl.Multiset.returningClob;
import static org.jooq.impl.Multiset.xmlaggEmulation;
import static org.jooq.impl.Names.N_MULTISET_AGG;
@ -145,9 +146,9 @@ final class MultisetAgg<R extends Record> extends AbstractAggregateFunction<Resu
}
case XML: {
XMLAggOrderByStep<XML> order = xmlaggEmulation(row, true);
XMLAggOrderByStep<XML> order = xmlaggEmulation(ctx, row, true);
Field<XML> f = xmlelement(N_RESULT,
Field<XML> f = xmlelement(nResult(ctx),
multisetCondition
? fo((AbstractAggregateFunction<?>) order.orderBy(row.fields()))
: ofo((AbstractAggregateFunction<?>) order)

View File

@ -52,8 +52,9 @@ import org.jooq.Name;
final class Names {
// [#13383] These names must never be unquoted to prevent conflicts with keywords
static final Name N_CASE = quotedName("case");
static final Name N_SELECT = quotedName("select");
static final Name NQ_CASE = quotedName("case");
static final Name NQ_RESULT = quotedName("result");
static final Name NQ_SELECT = quotedName("select");
static final Name N_ARRAY_TABLE = name("array_table");
static final Name N_COLUMN_VALUE = name("COLUMN_VALUE");

View File

@ -41,7 +41,7 @@ package org.jooq.impl;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.table;
import static org.jooq.impl.Names.N_SELECT;
import static org.jooq.impl.Names.NQ_SELECT;
import java.util.Arrays;
@ -64,7 +64,7 @@ final class ProjectSingleScalarSubquery<T> extends AbstractField<T> implements Q
final int index;
ProjectSingleScalarSubquery(Select<?> query, int index) {
super(N_SELECT, (DataType<T>) query.getSelect().get(index).getDataType());
super(NQ_SELECT, (DataType<T>) query.getSelect().get(index).getDataType());
this.query = query;
this.index = index;

View File

@ -43,7 +43,7 @@ import static org.jooq.SQLDialect.HSQLDB;
// ...
import static org.jooq.impl.DSL.asterisk;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.Names.N_SELECT;
import static org.jooq.impl.Names.NQ_SELECT;
import static org.jooq.impl.Tools.visitSubquery;
import java.util.Set;
@ -67,7 +67,7 @@ final class ScalarSubquery<T> extends AbstractField<T> implements QOM.ScalarSubq
final boolean predicandSubquery;
ScalarSubquery(Select<?> query, DataType<T> type, boolean predicandSubquery) {
super(N_SELECT, type);
super(NQ_SELECT, type);
this.query = query;
this.predicandSubquery = predicandSubquery;

View File

@ -243,7 +243,12 @@ final class XMLHandler<R extends Record> extends DefaultHandler {
DataType<?> t = s.fields.get(s.column).getDataType();
// [#13181] String NULL and '' values cannot be distinguished without xsi:nil
if (t.isString() && !("true".equals(attributes.getValue("xsi:nil"))))
if (t.isString()
&& !("true".equals(attributes.getValue("xsi:nil")))
)
s.values.add("");
else if (!t.isMultiset() && !t.isRecord())
s.values.add(null);