diff --git a/jOOQ/src/main/java/org/jooq/JSONFormat.java b/jOOQ/src/main/java/org/jooq/JSONFormat.java
index 03d53d4d7e..a5e01a4dd7 100644
--- a/jOOQ/src/main/java/org/jooq/JSONFormat.java
+++ b/jOOQ/src/main/java/org/jooq/JSONFormat.java
@@ -73,6 +73,7 @@ public final class JSONFormat {
final boolean format;
final String newline;
+ final int globalIndent;
final int indent;
final String[] indented;
final boolean header;
@@ -84,6 +85,7 @@ public final class JSONFormat {
this(
false,
"\n",
+ 0,
2,
null,
true,
@@ -96,6 +98,7 @@ public final class JSONFormat {
private JSONFormat(
boolean format,
String newline,
+ int globalIndent,
int indent,
String[] indented,
boolean header,
@@ -105,6 +108,7 @@ public final class JSONFormat {
) {
this.format = format;
this.newline = newline;
+ this.globalIndent = globalIndent;
this.indent = indent;
this.indented = indented != null ? indented : new String[] {
"",
@@ -125,6 +129,7 @@ public final class JSONFormat {
return new JSONFormat(
newFormat,
newline,
+ globalIndent,
indent,
null,
header,
@@ -148,6 +153,7 @@ public final class JSONFormat {
return new JSONFormat(
format,
newNewline,
+ globalIndent,
indent,
indented,
header,
@@ -165,12 +171,37 @@ public final class JSONFormat {
}
/**
- * The new indentation value, defaulting to 2.
+ * The new global indentation size applied on all levels, defaulting to 0.
+ */
+ public final JSONFormat globalIndent(int newGlobalIndent) {
+ return new JSONFormat(
+ format,
+ newline,
+ newGlobalIndent,
+ indent,
+ null,
+ header,
+ recordFormat,
+ wrapSingleColumnRecords,
+ quoteNested
+ );
+ }
+
+ /**
+ * The global indentation applied on all levels.
+ */
+ public final int globalIndent() {
+ return globalIndent;
+ }
+
+ /**
+ * The new indentation size per level value, defaulting to 2.
*/
public final JSONFormat indent(int newIndent) {
return new JSONFormat(
format,
newline,
+ globalIndent,
newIndent,
null,
header,
@@ -181,7 +212,7 @@ public final class JSONFormat {
}
/**
- * The indentation.
+ * The indentation size per level.
*/
public final int indent() {
return indent;
@@ -191,10 +222,12 @@ public final class JSONFormat {
* Convenience method to get an indentation string at a given level.
*/
public final String indentString(int level) {
- if (level < indented.length)
- return indented[level];
+ int i = level + globalIndent / indent;
+
+ if (i < indented.length)
+ return indented[i];
else if (format)
- return rightPad("", indent * level);
+ return rightPad("", globalIndent + indent * level);
else
return "";
}
@@ -207,6 +240,7 @@ public final class JSONFormat {
return new JSONFormat(
format,
newline,
+ globalIndent,
indent,
indented,
newHeader,
@@ -232,6 +266,7 @@ public final class JSONFormat {
return new JSONFormat(
format,
newline,
+ globalIndent,
indent,
indented,
header,
@@ -256,6 +291,7 @@ public final class JSONFormat {
return new JSONFormat(
format,
newline,
+ globalIndent,
indent,
indented,
header,
@@ -280,6 +316,7 @@ public final class JSONFormat {
return new JSONFormat(
format,
newline,
+ globalIndent,
indent,
indented,
header,
diff --git a/jOOQ/src/main/java/org/jooq/SelectForXMLCommonDirectivesStep.java b/jOOQ/src/main/java/org/jooq/SelectForXMLCommonDirectivesStep.java
index 149ea20014..58756d4b95 100644
--- a/jOOQ/src/main/java/org/jooq/SelectForXMLCommonDirectivesStep.java
+++ b/jOOQ/src/main/java/org/jooq/SelectForXMLCommonDirectivesStep.java
@@ -121,6 +121,14 @@ import static org.jooq.SQLDialect.POSTGRES;
+
+
+
+
+
+
+
+
diff --git a/jOOQ/src/main/java/org/jooq/SelectForXMLPathDirectivesStep.java b/jOOQ/src/main/java/org/jooq/SelectForXMLPathDirectivesStep.java
index c3de861fa0..69e79212dd 100644
--- a/jOOQ/src/main/java/org/jooq/SelectForXMLPathDirectivesStep.java
+++ b/jOOQ/src/main/java/org/jooq/SelectForXMLPathDirectivesStep.java
@@ -101,6 +101,22 @@ import org.jetbrains.annotations.*;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jOOQ/src/main/java/org/jooq/SelectForXMLRawDirectivesStep.java b/jOOQ/src/main/java/org/jooq/SelectForXMLRawDirectivesStep.java
index c1ab312cef..dd86c6e7ac 100644
--- a/jOOQ/src/main/java/org/jooq/SelectForXMLRawDirectivesStep.java
+++ b/jOOQ/src/main/java/org/jooq/SelectForXMLRawDirectivesStep.java
@@ -106,6 +106,22 @@ import static org.jooq.SQLDialect.POSTGRES;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jOOQ/src/main/java/org/jooq/SelectQuery.java b/jOOQ/src/main/java/org/jooq/SelectQuery.java
index 43d79ccbfe..d1156534d0 100644
--- a/jOOQ/src/main/java/org/jooq/SelectQuery.java
+++ b/jOOQ/src/main/java/org/jooq/SelectQuery.java
@@ -1305,6 +1305,27 @@ public interface SelectQuery extends Select, ConditionProvi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java b/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java
index 833346f834..a943914cb0 100644
--- a/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java
+++ b/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java
@@ -461,6 +461,7 @@ abstract class AbstractResult extends AbstractFormattable impl
try {
String separator;
int recordLevel = format.header() ? 2 : 1;
+ boolean hasRecords = false;
if (format.header()) {
if (format.format())
@@ -552,6 +553,7 @@ abstract class AbstractResult extends AbstractFormattable impl
switch (format.recordFormat()) {
case ARRAY:
for (Record record : this) {
+ hasRecords = true;
writer.append(separator);
if (format.format())
@@ -564,6 +566,7 @@ abstract class AbstractResult extends AbstractFormattable impl
break;
case OBJECT:
for (Record record : this) {
+ hasRecords = true;
writer.append(separator);
if (format.format())
@@ -578,17 +581,23 @@ abstract class AbstractResult extends AbstractFormattable impl
throw new IllegalArgumentException("Format not supported: " + format);
}
- if (format.format()) {
+ if (format.format() && hasRecords) {
writer.append(format.newline());
if (format.header())
writer.append(format.indentString(1));
+ else
+ writer.append(format.indentString(0));
}
writer.append(']');
- if (format.header())
- writer.append(format.newline()).append('}');
+ if (format.header()) {
+ if (format.format())
+ writer.append(format.newline()).append(format.indentString(0));
+
+ writer.append('}');
+ }
writer.flush();
}
@@ -647,17 +656,20 @@ abstract class AbstractResult extends AbstractFormattable impl
int size = fields.size();
boolean wrapRecords = format.wrapSingleColumnRecords() || size > 1;
+ if (format.format())
+ writer.append(format.indentString(recordLevel));
+
if (wrapRecords)
- if (format.format())
- writer.append(format.indentString(recordLevel)).append('{');
- else
- writer.append('{');
+ writer.append('{');
for (int index = 0; index < size; index++) {
writer.append(separator);
if (format.format())
- writer.append(format.newline()).append(format.indentString(recordLevel + 1));
+ if (size > 1)
+ writer.append(format.newline()).append(format.indentString(recordLevel + 1));
+ else if (format.wrapSingleColumnRecords())
+ writer.append(' ');
if (wrapRecords) {
JSONValue.writeJSONString(record.field(index).getName(), writer);
@@ -667,12 +679,16 @@ abstract class AbstractResult extends AbstractFormattable impl
writer.append(' ');
}
- formatJSON0(record.get(index), writer, format);
+ formatJSON0(record.get(index), writer, format.globalIndent(format.globalIndent() + format.indent() * (recordLevel + 1)));
+
+ if (format.format() && format.wrapSingleColumnRecords() && size == 1)
+ writer.append(' ');
+
separator = ",";
}
if (wrapRecords)
- if (format.format())
+ if (format.format() && size > 1)
writer.append(format.newline()).append(format.indentString(recordLevel)).append('}');
else
writer.append('}');
@@ -686,26 +702,34 @@ abstract class AbstractResult extends AbstractFormattable impl
Writer writer
) throws java.io.IOException {
String separator = "";
-
int size = fields.size();
- if (format.wrapSingleColumnRecords() || size > 1)
- if (format.format())
- writer.append(format.indentString(recordLevel)).append('[');
- else
- writer.append('[');
+ boolean wrapRecords = format.wrapSingleColumnRecords() || size > 1;
+
+ if (format.format())
+ writer.append(format.indentString(recordLevel));
+
+ if (wrapRecords)
+ writer.append('[');
for (int index = 0; index < size; index++) {
writer.append(separator);
if (format.format())
- writer.append(format.newline()).append(format.indentString(recordLevel + 1));
+ if (size > 1)
+ writer.append(format.newline()).append(format.indentString(recordLevel + 1));
+ else if (format.wrapSingleColumnRecords())
+ writer.append(' ');
+
+ formatJSON0(record.get(index), writer, format.globalIndent(format.globalIndent() + format.indent() * (recordLevel + 1)));
+
+ if (format.format() && format.wrapSingleColumnRecords() && size == 1)
+ writer.append(' ');
- formatJSON0(record.get(index), writer, format);
separator = ",";
}
- if (format.wrapSingleColumnRecords() || size > 1)
- if (format.format())
+ if (wrapRecords)
+ if (format.format() && size > 1)
writer.append(format.newline()).append(format.indentString(recordLevel)).append(']');
else
writer.append(']');
@@ -771,7 +795,7 @@ abstract class AbstractResult extends AbstractFormattable impl
if (format.header())
writer.append(newline).append(format.indentString(1)).append("");
- writer.append(newline).append("");
+ writer.append(newline).append(format.indentString(0)).append("");
writer.flush();
}
catch (java.io.IOException e) {
@@ -818,7 +842,7 @@ abstract class AbstractResult extends AbstractFormattable impl
if (value instanceof Formattable) {
writer.append(newline).append(format.indentString(recordLevel + 2));
- ((Formattable) value).formatXML(writer, format.globalIndent(format.indent() * (recordLevel + 2)));
+ ((Formattable) value).formatXML(writer, format.globalIndent(format.globalIndent() + format.indent() * (recordLevel + 2)));
writer.append(newline).append(format.indentString(recordLevel + 1));
}
else if (value instanceof XML && !format.quoteNested())
diff --git a/jOOQ/src/main/java/org/jooq/impl/ForXML.java b/jOOQ/src/main/java/org/jooq/impl/ForXML.java
index 7b0dded612..d856dc4531 100644
--- a/jOOQ/src/main/java/org/jooq/impl/ForXML.java
+++ b/jOOQ/src/main/java/org/jooq/impl/ForXML.java
@@ -93,6 +93,19 @@ package org.jooq.impl;
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jOOQ/src/main/java/org/jooq/impl/Keywords.java b/jOOQ/src/main/java/org/jooq/impl/Keywords.java
index c083618d61..36358d4abc 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Keywords.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Keywords.java
@@ -452,6 +452,7 @@ final class Keywords {
static final Keyword K_XML = keyword("xml");
static final Keyword K_XMLEXISTS = keyword("xmlexists");
static final Keyword K_XMLTABLE = keyword("xmltable");
+ static final Keyword K_XSINIL = keyword("xsinil");
static final Keyword K_YEAR = keyword("year");
static final Keyword K_YEAR_MONTH = keyword("year_month");
static final Keyword K_YEAR_TO_DAY = keyword("year to day");
diff --git a/jOOQ/src/main/java/org/jooq/impl/Multiset.java b/jOOQ/src/main/java/org/jooq/impl/Multiset.java
index 07445d5884..616e05fda5 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Multiset.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Multiset.java
@@ -77,7 +77,6 @@ final class Multiset extends AbstractField> {
this.select = select;
}
- @SuppressWarnings("unchecked")
@Override
public final void accept(Context> ctx) {
switch (emulateMultiset(ctx.configuration())) {
diff --git a/jOOQ/src/main/java/org/jooq/impl/MultisetDataType.java b/jOOQ/src/main/java/org/jooq/impl/MultisetDataType.java
new file mode 100644
index 0000000000..a8fec74240
--- /dev/null
+++ b/jOOQ/src/main/java/org/jooq/impl/MultisetDataType.java
@@ -0,0 +1,158 @@
+/*
+ * 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.Tools.CTX;
+import static org.jooq.impl.Tools.newRecord;
+import static org.jooq.impl.Tools.recordType;
+import static org.jooq.impl.Tools.row0;
+
+import java.util.List;
+
+import org.jooq.CharacterSet;
+import org.jooq.Collation;
+import org.jooq.Field;
+import org.jooq.Nullability;
+import org.jooq.Record;
+import org.jooq.Result;
+import org.jooq.Row;
+import org.jooq.Select;
+import org.jooq.impl.AbstractRecord.TransferRecordState;
+
+/**
+ * A wrapper for anonymous multiset data types.
+ *
+ * @author Lukas Eder
+ */
+final class MultisetDataType extends DefaultDataType> {
+
+ final AbstractRow row;
+ final Class extends R> recordType;
+
+ @SuppressWarnings("unchecked")
+ public MultisetDataType(AbstractRow row, Class extends R> recordType) {
+ // [#11829] TODO: Implement this correctly for ArrayRecord
+ super(null, (Class) Result.class, "multiset", "multiset");
+
+ this.row = row;
+ this.recordType = recordType;
+ }
+
+ /**
+ * [#3225] Performant constructor for creating derived types.
+ */
+ MultisetDataType(
+ DefaultDataType> t,
+ AbstractRow row,
+ Class extends R> recordType,
+ Integer precision,
+ Integer scale,
+ Integer length,
+ Nullability nullability,
+ Collation collation,
+ CharacterSet characterSet,
+ boolean identity,
+ Field> defaultValue
+ ) {
+ super(t, precision, scale, length, nullability, collation, characterSet, identity, defaultValue);
+
+ this.row = row;
+ this.recordType = recordType;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ DefaultDataType> construct(
+ Integer newPrecision,
+ Integer newScale,
+ Integer newLength,
+ Nullability
+ newNullability,
+ Collation newCollation,
+ CharacterSet newCharacterSet,
+ boolean newIdentity,
+ Field> newDefaultValue
+ ) {
+ return new MultisetDataType<>(
+ this,
+ row,
+ recordType,
+ newPrecision,
+ newScale,
+ newLength,
+ newNullability,
+ newCollation,
+ newCharacterSet,
+ newIdentity,
+ (Field) newDefaultValue
+ );
+ }
+
+ @Override
+ public final Row getRow() {
+ return row;
+ }
+
+ @Override
+ public Result convert(Object object) {
+
+ // [#3884] TODO: Move this logic into JSONReader to make it more generally useful
+ if (object instanceof List) {
+ ResultImpl result = new ResultImpl<>(CTX.configuration(), row);
+
+ for (Object record : (List) object)
+ result.add(newRecord(true, recordType, row, CTX.configuration())
+ .operate(r -> {
+
+ // [#12014] TODO: Fix this and remove workaround
+ if (record instanceof Record)
+ ((AbstractRecord) r).from((Record) record);
+ else
+ r.from(record);
+
+ return r;
+ }));
+
+ return result;
+ }
+ else if (object == null)
+ return new ResultImpl<>(CTX.configuration(), row);
+ else
+ return super.convert(object);
+ }
+}
diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java
index 55d57b8bf1..7fa4b8c5ee 100644
--- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java
@@ -1017,6 +1017,13 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
+
+
+
+
+
+
+
diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java
index 51500d8efa..3add0f700d 100644
--- a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java
@@ -1947,6 +1947,36 @@ implements
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java
index 800687d9ff..616517db1a 100644
--- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java
@@ -1524,6 +1524,13 @@ final class SelectQueryImpl extends AbstractResultQuery imp
+
+
+
+
+
+
+
@@ -3575,6 +3582,21 @@ final class SelectQueryImpl extends AbstractResultQuery imp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+