Skip to content

[Kotlin] Improve Insert DSL #452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ This log will detail notable changes to MyBatis Dynamic SQL. Full details are av

## Release 1.4.0 - Unreleased

The release includes new function in the Where Clause DSL to support arbitrary grouping of conditions, and also use
of a "not" condition. It should now be possible to write any type of where clause.

Additionally, there were significant updates to the Kotlin DSL - both to support the new functionality in the
where clause, and significant updates to insert statements. There were also many minor updates in Kotlin
to make more use of Kotlin language features like infix functions and operator overloads.

GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/issues?q=milestone%3A1.4.0+](https://github.com/mybatis/mybatis-dynamic-sql/issues?q=milestone%3A1.4.0+)

1. Added support for arbitrary placement of nested criteria. For example, it is now
Expand Down Expand Up @@ -33,6 +40,10 @@ GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/issues?q=miles
([#446](https://github.com/mybatis/mybatis-dynamic-sql/pull/446))
6. Minor update the Kotlin join DSL to make it closer to natural SQL. The existing join methods are deprecated and
will be removed in version 1.5.0. ([#447](https://github.com/mybatis/mybatis-dynamic-sql/pull/447))
7. Updated most of the Kotlin insert DSL functions to be more like natural SQL. The main difference is that for insert,
insertBatch, and insertMultiple, the "into" function is moved inside the completer lambda. The old methods are now
deprecated and will be removed in version 1.5.0 of the library. This also allowed us to make some insert DSL
methods into infix functions. ([#452](https://github.com/mybatis/mybatis-dynamic-sql/pull/452))

## Release 1.3.1 - December 18, 2021

Expand Down
48 changes: 42 additions & 6 deletions src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 the original author or authors.
* Copyright 2016-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,6 +19,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import org.jetbrains.annotations.NotNull;
import org.mybatis.dynamic.sql.SqlColumn;
Expand All @@ -34,11 +35,12 @@ public class BatchInsertDSL<T> implements Buildable<BatchInsertModel<T>> {

private final Collection<T> records;
private final SqlTable table;
private final List<AbstractColumnMapping> columnMappings = new ArrayList<>();
private final List<AbstractColumnMapping> columnMappings;

private BatchInsertDSL(Collection<T> records, SqlTable table) {
this.records = records;
this.table = table;
private BatchInsertDSL(AbstractBuilder<T, ?> builder) {
this.records = builder.records;
this.table = Objects.requireNonNull(builder.table);
this.columnMappings = builder.columnMappings;
}

public <F> ColumnMappingFinisher<F> map(SqlColumn<F> column) {
Expand Down Expand Up @@ -71,7 +73,7 @@ private IntoGatherer(Collection<T> records) {
}

public BatchInsertDSL<T> into(SqlTable table) {
return new BatchInsertDSL<>(records, table);
return new Builder<T>().withRecords(records).withTable(table).build();
}
}

Expand Down Expand Up @@ -102,4 +104,38 @@ public BatchInsertDSL<T> toStringConstant(String constant) {
return BatchInsertDSL.this;
}
}

public abstract static class AbstractBuilder<T, B extends AbstractBuilder<T, B>> {
final Collection<T> records = new ArrayList<>();
SqlTable table;
final List<AbstractColumnMapping> columnMappings = new ArrayList<>();

public B withRecords(Collection<T> records) {
this.records.addAll(records);
return getThis();
}

public B withTable(SqlTable table) {
this.table = table;
return getThis();
}

public B withColumnMappings(Collection<AbstractColumnMapping> columnMappings) {
this.columnMappings.addAll(columnMappings);
return getThis();
}

protected abstract B getThis();
}

public static class Builder<T> extends AbstractBuilder<T, Builder<T>> {
@Override
protected Builder<T> getThis() {
return this;
}

public BatchInsertDSL<T> build() {
return new BatchInsertDSL<>(this);
}
}
}
45 changes: 33 additions & 12 deletions src/main/java/org/mybatis/dynamic/sql/insert/GeneralInsertDSL.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2021 the original author or authors.
* Copyright 2016-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@
package org.mybatis.dynamic.sql.insert;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
Expand All @@ -33,11 +34,12 @@
import org.mybatis.dynamic.sql.util.ValueWhenPresentMapping;

public class GeneralInsertDSL implements Buildable<GeneralInsertModel> {
private final List<AbstractColumnMapping> insertMappings = new ArrayList<>();
private final List<AbstractColumnMapping> columnMappings;
private final SqlTable table;

private GeneralInsertDSL(SqlTable table) {
this.table = Objects.requireNonNull(table);
private GeneralInsertDSL(Builder builder) {
table = Objects.requireNonNull(builder.table);
columnMappings = builder.columnMappings;
}

public <T> SetClauseFinisher<T> set(SqlColumn<T> column) {
Expand All @@ -49,12 +51,12 @@ public <T> SetClauseFinisher<T> set(SqlColumn<T> column) {
public GeneralInsertModel build() {
return new GeneralInsertModel.Builder()
.withTable(table)
.withInsertMappings(insertMappings)
.withInsertMappings(columnMappings)
.build();
}

public static GeneralInsertDSL insertInto(SqlTable table) {
return new GeneralInsertDSL(table);
return new GeneralInsertDSL.Builder().withTable(table).build();
}

public class SetClauseFinisher<T> {
Expand All @@ -66,17 +68,17 @@ public SetClauseFinisher(SqlColumn<T> column) {
}

public GeneralInsertDSL toNull() {
insertMappings.add(NullMapping.of(column));
columnMappings.add(NullMapping.of(column));
return GeneralInsertDSL.this;
}

public GeneralInsertDSL toConstant(String constant) {
insertMappings.add(ConstantMapping.of(column, constant));
columnMappings.add(ConstantMapping.of(column, constant));
return GeneralInsertDSL.this;
}

public GeneralInsertDSL toStringConstant(String constant) {
insertMappings.add(StringConstantMapping.of(column, constant));
columnMappings.add(StringConstantMapping.of(column, constant));
return GeneralInsertDSL.this;
}

Expand All @@ -85,7 +87,7 @@ public GeneralInsertDSL toValue(T value) {
}

public GeneralInsertDSL toValue(Supplier<T> valueSupplier) {
insertMappings.add(ValueMapping.of(column, valueSupplier));
columnMappings.add(ValueMapping.of(column, valueSupplier));
return GeneralInsertDSL.this;
}

Expand All @@ -94,7 +96,7 @@ public GeneralInsertDSL toValueOrNull(T value) {
}

public GeneralInsertDSL toValueOrNull(Supplier<T> valueSupplier) {
insertMappings.add(ValueOrNullMapping.of(column, valueSupplier));
columnMappings.add(ValueOrNullMapping.of(column, valueSupplier));
return GeneralInsertDSL.this;
}

Expand All @@ -103,8 +105,27 @@ public GeneralInsertDSL toValueWhenPresent(T value) {
}

public GeneralInsertDSL toValueWhenPresent(Supplier<T> valueSupplier) {
insertMappings.add(ValueWhenPresentMapping.of(column, valueSupplier));
columnMappings.add(ValueWhenPresentMapping.of(column, valueSupplier));
return GeneralInsertDSL.this;
}
}

public static class Builder {
private final List<AbstractColumnMapping> columnMappings = new ArrayList<>();
private SqlTable table;

public Builder withTable(SqlTable table) {
this.table = table;
return this;
}

public Builder withColumnMappings(Collection<AbstractColumnMapping> columnMappings) {
this.columnMappings.addAll(columnMappings);
return this;
}

public GeneralInsertDSL build() {
return new GeneralInsertDSL(this);
}
}
}
40 changes: 34 additions & 6 deletions src/main/java/org/mybatis/dynamic/sql/insert/InsertDSL.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2021 the original author or authors.
* Copyright 2016-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,9 @@
package org.mybatis.dynamic.sql.insert;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

import org.jetbrains.annotations.NotNull;
Expand All @@ -34,11 +36,12 @@ public class InsertDSL<T> implements Buildable<InsertModel<T>> {

private final T row;
private final SqlTable table;
private final List<AbstractColumnMapping> columnMappings = new ArrayList<>();
private final List<AbstractColumnMapping> columnMappings;

private InsertDSL(T row, SqlTable table) {
this.row = row;
this.table = table;
private InsertDSL(Builder<T> builder) {
this.row = Objects.requireNonNull(builder.row);
this.table = Objects.requireNonNull(builder.table);
columnMappings = builder.columnMappings;
}

public <F> ColumnMappingFinisher<F> map(SqlColumn<F> column) {
Expand Down Expand Up @@ -66,7 +69,7 @@ private IntoGatherer(T row) {
}

public InsertDSL<T> into(SqlTable table) {
return new InsertDSL<>(row, table);
return new InsertDSL.Builder<T>().withRow(row).withTable(table).build();
}
}

Expand Down Expand Up @@ -102,4 +105,29 @@ public InsertDSL<T> toStringConstant(String constant) {
return InsertDSL.this;
}
}

public static class Builder<T> {
private T row;
private SqlTable table;
private final List<AbstractColumnMapping> columnMappings = new ArrayList<>();

public Builder<T> withRow(T row) {
this.row = row;
return this;
}

public Builder<T> withTable(SqlTable table) {
this.table = table;
return this;
}

public Builder<T> withColumnMappings(Collection<AbstractColumnMapping> columnMappings) {
this.columnMappings.addAll(columnMappings);
return this;
}

public InsertDSL<T> build() {
return new InsertDSL<>(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 the original author or authors.
* Copyright 2016-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,10 +15,10 @@
*/
package org.mybatis.dynamic.sql.insert;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import org.jetbrains.annotations.NotNull;
import org.mybatis.dynamic.sql.SqlColumn;
Expand All @@ -34,11 +34,12 @@ public class MultiRowInsertDSL<T> implements Buildable<MultiRowInsertModel<T>> {

private final Collection<T> records;
private final SqlTable table;
private final List<AbstractColumnMapping> columnMappings = new ArrayList<>();
private final List<AbstractColumnMapping> columnMappings;

private MultiRowInsertDSL(Collection<T> records, SqlTable table) {
this.records = records;
this.table = table;
private MultiRowInsertDSL(BatchInsertDSL.AbstractBuilder<T, ?> builder) {
this.records = builder.records;
this.table = Objects.requireNonNull(builder.table);
this.columnMappings = builder.columnMappings;
}

public <F> ColumnMappingFinisher<F> map(SqlColumn<F> column) {
Expand Down Expand Up @@ -71,7 +72,7 @@ private IntoGatherer(Collection<T> records) {
}

public MultiRowInsertDSL<T> into(SqlTable table) {
return new MultiRowInsertDSL<>(records, table);
return new Builder<T>().withRecords(records).withTable(table).build();
}
}

Expand Down Expand Up @@ -102,4 +103,16 @@ public MultiRowInsertDSL<T> toStringConstant(String constant) {
return MultiRowInsertDSL.this;
}
}

public static class Builder<T> extends BatchInsertDSL.AbstractBuilder<T, Builder<T>> {

@Override
protected Builder<T> getThis() {
return this;
}

public MultiRowInsertDSL<T> build() {
return new MultiRowInsertDSL<>(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class GroupingCriteriaCollector {
internal var initialCriterion: SqlCriterion? = null
private set(value) {
if (field != null) {
throw DuplicateInitialCriterionException()
throw KInvalidSQLException("Setting more than one initial criterion is not allowed. " +
"Additional criteria should be added with \"and\" or \"or\" expression")
}
field = value
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ typealias JoinReceiver = JoinCollector.() -> Unit

@MyBatisDslMarker
class JoinCollector {
val onJoinCriterion: JoinCriterion by lazy { internalOnCriterion }
val andJoinCriteria = mutableListOf<JoinCriterion>()
private lateinit var internalOnCriterion: JoinCriterion
private var onJoinCriterion: JoinCriterion? = null
internal val andJoinCriteria = mutableListOf<JoinCriterion>()

internal fun onJoinCriterion() : JoinCriterion =
onJoinCriterion?: throw KInvalidSQLException("You must specify an \"on\" condition in a join")

fun on(leftColumn: BasicColumn): RightColumnCollector = RightColumnCollector {
internalOnCriterion = JoinCriterion.Builder()
onJoinCriterion = JoinCriterion.Builder()
.withConnector("on")
.withJoinColumn(leftColumn)
.withJoinCondition(it)
Expand All @@ -48,7 +50,7 @@ class JoinCollector {

@Deprecated("Please use: on(leftColumn) equalTo rightColumn")
fun on(column: BasicColumn, condition: JoinCondition) {
internalOnCriterion = JoinCriterion.Builder()
onJoinCriterion = JoinCriterion.Builder()
.withConnector("on")
.withJoinColumn(column)
.withJoinCondition(condition)
Expand Down
Loading