From 6cfdf1449342dc70af59d52d23c0509832a6d532 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Fri, 9 Jun 2023 11:41:45 -0400 Subject: [PATCH 1/8] Checkstyle --- src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java index 08f62d1f1..817a63e16 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java @@ -79,7 +79,8 @@ public static QueryExpressionDSL.FromGatherer selectDistinct(BasicC return selectDistinct(Function.identity(), selectList); } - public static QueryExpressionDSL.FromGatherer selectDistinct(Collection selectList) { + public static QueryExpressionDSL.FromGatherer selectDistinct( + Collection selectList) { return selectDistinct(Function.identity(), selectList); } From 35c0dc564c2aac1f80434f1a7ba3a599df6f55b8 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Fri, 9 Jun 2023 11:44:13 -0400 Subject: [PATCH 2/8] Remove trailing spaces --- src/site/markdown/docs/complexQueries.md | 6 +-- src/site/markdown/docs/conditions.md | 10 ++--- src/site/markdown/docs/configuration.md | 4 +- src/site/markdown/docs/delete.md | 6 +-- src/site/markdown/docs/exceptions.md | 2 +- src/site/markdown/docs/extending.md | 6 +-- src/site/markdown/docs/howItWorks.md | 6 +-- src/site/markdown/docs/insert.md | 22 +++++----- src/site/markdown/docs/introduction.md | 4 +- src/site/markdown/docs/kotlinMyBatis3.md | 10 ++--- src/site/markdown/docs/kotlinOverview.md | 8 ++-- src/site/markdown/docs/kotlinSpring.md | 4 +- src/site/markdown/docs/kotlinWhereClauses.md | 2 +- src/site/markdown/docs/mybatis3.md | 18 ++++---- src/site/markdown/docs/quickStart.md | 2 +- src/site/markdown/docs/select.md | 8 ++-- src/site/markdown/docs/spring.md | 46 ++++++++++---------- src/site/markdown/docs/subQueries.md | 10 ++--- src/site/markdown/docs/update.md | 4 +- src/site/markdown/docs/whereClauses.md | 2 +- src/site/markdown/index.md | 2 +- 21 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/site/markdown/docs/complexQueries.md b/src/site/markdown/docs/complexQueries.md index 5171ed109..36614324b 100644 --- a/src/site/markdown/docs/complexQueries.md +++ b/src/site/markdown/docs/complexQueries.md @@ -19,7 +19,7 @@ public SelectStatementProvider search(Integer targetId, String fName, String lNa var builder = select(id, firstName, lastName) // (1) .from(person) .where(); // (2) - + if (targetId != null) { // (3) builder .and(id, isEqualTo(targetId)); @@ -32,10 +32,10 @@ public SelectStatementProvider search(Integer targetId, String fName, String lNa builder .orderBy(lastName, firstName) .fetchFirst(50).rowsOnly(); // (7) - + return builder.build().render(RenderingStrategies.MYBATIS3); // (8) } - + public String addWildcards(String s) { return "%" + s + "%"; } diff --git a/src/site/markdown/docs/conditions.md b/src/site/markdown/docs/conditions.md index 4947c39eb..4c52e6d3b 100644 --- a/src/site/markdown/docs/conditions.md +++ b/src/site/markdown/docs/conditions.md @@ -80,7 +80,7 @@ List search(String searchName) { .orderBy(id) .build() .render(RenderingStrategies.MYBATIS3); - + ... } ``` @@ -97,7 +97,7 @@ List search(String searchName){ .build() .render(RenderingStrategies.MYBATIS3); } - + String appendWildCards(String in) { return "%" + in + "%"; } @@ -144,7 +144,7 @@ If all three values are null, then no where clause will be generated. Each of the conditions accepts a lambda expression that can be used to determine if the condition should render or not. The lambdas will all be of standard JDK types (either `java.util.function.BooleanSupplier`, `java.util.function.Predicate`, or `java.util.function.BiPredicate` depending on the type of condition). The following -table lists the optional conditions and shows how to use them: +table lists the optional conditions and shows how to use them: | Condition | Example | Rendering Rules | |-----------|---------|-----------------| @@ -197,7 +197,7 @@ Optionality with the "in" and "not in" conditions is a bit more complex than the thing to know is that no "in" or "not in" condition will render if the list of values is empty. For example, there will never be rendered SQL like `where name in ()`. So optionality of the "in" conditions is more about optionality of the *values* of the condition. The library comes with functions that will filter out null values, and will upper -case String values to enable case insensitive queries. There are extension points to add additional filtering and +case String values to enable case insensitive queries. There are extension points to add additional filtering and mapping if you so desire. The following table shows the different supplied In conditions and how they will render for different sets of inputs. @@ -218,7 +218,7 @@ The table assumes the following types of input: | IsNotInCaseInsensitive | No | Yes | upper(name) not in ('FOO', null, 'BAR') | upper(name) not in (null) | | IsNotInCaseInsensitiveWhenPresent | Yes | Yes | upper(name) not in ('FOO', 'BAR') | No Render | -If none of these options meet your needs, the "In" conditions also support "map" and "filter" methods for the values. +If none of these options meet your needs, the "In" conditions also support "map" and "filter" methods for the values. This gives you great flexibility to alter or filter the value list before the condition is rendered. diff --git a/src/site/markdown/docs/configuration.md b/src/site/markdown/docs/configuration.md index 4796d387d..e98fba5f8 100644 --- a/src/site/markdown/docs/configuration.md +++ b/src/site/markdown/docs/configuration.md @@ -31,7 +31,7 @@ The configuration file is a standard Java properties file. The possible values a ## Statement Configuration If the global configuration is not acceptable for any individual statement, you can also configure the statement in the -DSL. Consider the following statement: +DSL. Consider the following statement: ```java DeleteStatementProvider deleteStatement = deleteFrom(animalData) @@ -52,7 +52,7 @@ The Kotlin DSL contains the same function: ```kotlin val deleteStatement = deleteFrom(person) { where { id isEqualToWhenPresent null } - configureStatement { isNonRenderingWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } ``` diff --git a/src/site/markdown/docs/delete.md b/src/site/markdown/docs/delete.md index b7dd9cec3..5de5bf42b 100644 --- a/src/site/markdown/docs/delete.md +++ b/src/site/markdown/docs/delete.md @@ -16,13 +16,13 @@ For example: DeleteStatementProvider deleteStatement = deleteFrom(foo) .build() .render(RenderingStrategies.MYBATIS3); -``` +``` ## Annotated Mapper for Delete Statements The DeleteStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you are using an annotated mapper, the delete method should look like this: - + ```java import org.apache.ibatis.annotations.DeleteProvider; import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; @@ -41,7 +41,7 @@ We do not recommend using an XML mapper for delete statements, but if you want t object can be used as a parameter to a MyBatis mapper method directly. If you are using an XML mapper, the delete method should look like this in the Java interface: - + ```java import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; diff --git a/src/site/markdown/docs/exceptions.md b/src/site/markdown/docs/exceptions.md index f2a98ff3b..c589ad345 100644 --- a/src/site/markdown/docs/exceptions.md +++ b/src/site/markdown/docs/exceptions.md @@ -30,7 +30,7 @@ All of these exceptions can be avoided through proper use of the DSL and validat Most conditions in a where clause provide optionality - they have `filter` methods that can cause the condition to be dropped from the where clause. If all the conditions in a where clause fail to render, then the where clause itself is dropped from the rendered SQL. This can be dangerous in that it can cause a statement to be generated that affects all -rows in a table. For example, all rows could be deleted. As of version 1.4.1, the library will throw a +rows in a table. For example, all rows could be deleted. As of version 1.4.1, the library will throw a `NonRenderingWhereClauseException` in this case out of an abundance of caution. This behavior can be overridden through either global configuration, or by configuring individual statements to allow for where clauses to be dropped. diff --git a/src/site/markdown/docs/extending.md b/src/site/markdown/docs/extending.md index 2f593f6d6..92b4f6795 100644 --- a/src/site/markdown/docs/extending.md +++ b/src/site/markdown/docs/extending.md @@ -20,7 +20,7 @@ A calculated column can be used anywhere in a SELECT statement. If you don't ne ```java public class CountAll implements BasicColumn { - + private String alias; public CountAll() { @@ -100,7 +100,7 @@ public class ToBase64 extends AbstractTypeConvertingFunction column) { return new ToBase64(column); } @@ -113,7 +113,7 @@ The following function implements the common database `UPPER()` function. ```java public class Upper extends AbstractUniTypeFunction { - + private Upper(BindableColumn column) { super(column); } diff --git a/src/site/markdown/docs/howItWorks.md b/src/site/markdown/docs/howItWorks.md index 40d3568e6..51eee6960 100644 --- a/src/site/markdown/docs/howItWorks.md +++ b/src/site/markdown/docs/howItWorks.md @@ -13,7 +13,7 @@ templating engine for generating dynamic SQL. For example, MyBatis can execute an SQL string formatted like this: ```sql - select id, description from table_codes where id = #{id,jdbcType=INTEGER} + select id, description from table_codes where id = #{id,jdbcType=INTEGER} ``` This is standard SQL with a MyBatis twist - the parameter notation `#{id,jdbcType=INTEGER}` @@ -36,11 +36,11 @@ public class Parameter { public Parameter(Integer id) { this.id = id; } - + public Integer getId() { return id; } - + public String getSql() { return sql; } diff --git a/src/site/markdown/docs/insert.md b/src/site/markdown/docs/insert.md index c289542c8..b7fe11a70 100644 --- a/src/site/markdown/docs/insert.md +++ b/src/site/markdown/docs/insert.md @@ -5,7 +5,7 @@ The library will generate a variety of INSERT statements: 1. An insert for multiple rows with a single statement 1. An insert for multiple rows with a JDBC batch 1. A general insert statement -1. An insert with a select statement +1. An insert with a select statement ## Single Row Insert A single record insert is a statement that inserts a single record into a table. This statement is configured differently than other statements in the library so that MyBatis' support for generated keys will work properly. To use the statement, you must first create an object that will map to the database row, then map object attributes to fields in the database. For example: @@ -42,7 +42,7 @@ Notice the `map` method. It is used to map a database column to an attribute of 3. `map(column).toStringConstant(constant_value)` will insert a constant into a column. The constant_value will be written into the generated insert statement surrounded by single quote marks (as an SQL String) 4. `map(column).toProperty(property)` will insert a value from the record into a column. The value of the property will be bound to the SQL statement as a prepared statement parameter 5. `map(column).toPropertyWhenPresent(property, Supplier valueSupplier)` will insert a value from the record into a column if the value is non-null. The value of the property will be bound to the SQL statement as a prepared statement parameter. This is used to generate a "selective" insert as defined in MyBatis Generator. -6. `map(column).toRow()` will insert the record itself into a column. This is appropriate when the "record" is a simple class like Integer or String. +6. `map(column).toRow()` will insert the record itself into a column. This is appropriate when the "record" is a simple class like Integer or String. ### Annotated Mapper for Single Row Insert Statements The InsertStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you @@ -64,7 +64,7 @@ import org.mybatis.dynamic.sql.util.SqlProviderAdapter; We do not recommend using an XML mapper for insert statements, but if you want to do so the InsertStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you are using an XML mapper, the insert method should look like this in the Java interface: - + ```java import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider; @@ -110,7 +110,7 @@ A multiple row insert statement looks like this: try (SqlSession session = sqlSessionFactory.openSession()) { GeneratedAlwaysAnnotatedMapper mapper = session.getMapper(GeneratedAlwaysAnnotatedMapper.class); List records = getRecordsToInsert(); // not shown - + MultiRowInsertStatementProvider multiRowInsert = insertMultiple(records) .into(generatedAlways) .map(id).toProperty("id") @@ -118,7 +118,7 @@ A multiple row insert statement looks like this: .map(lastName).toProperty("lastName") .build() .render(RenderingStrategies.MYBATIS3); - + int rows = mapper.insertMultiple(multiRowInsert); } ``` @@ -143,7 +143,7 @@ import org.mybatis.dynamic.sql.util.SqlProviderAdapter; We do not recommend using an XML mapper for insert statements, but if you want to do so the MultiRowInsertStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you are using an XML mapper, the insert method should look like this in the Java interface: - + ```java import org.mybatis.dynamic.sql.insert.render.MultiInsertStatementProvider; @@ -189,7 +189,7 @@ that we expect generated values. Further, note that the `keyProperty` is set to return the `insertStatement` as supplied in the method call. The adapter method requires that there be one, and only one, String parameter in the method call, and it assumes that this one String parameter is the SQL insert statement. The parameter can have any name and can be specified in any position in the method's parameter list. -The `@Param` annotation is not required for the insert statement. However, it may be specified if you so desire. +The `@Param` annotation is not required for the insert statement. However, it may be specified if you so desire. The second method above decomposes the `MultiRowInsertStatementProvider` and calls the first method. @@ -222,7 +222,7 @@ A batch insert is a collection of statements that can be used to execute a JDBC It is important to open a MyBatis session by setting the executor type to BATCH. The records are inserted on the commit. You can call commit multiple times if you want to do intermediate commits. -Notice that the same mapper method that is used to insert a single record is now executed multiple times. The `map` methods are the same with the exception that the `toPropertyWhenPresent` mapping is not supported for batch inserts. +Notice that the same mapper method that is used to insert a single record is now executed multiple times. The `map` methods are the same with the exception that the `toPropertyWhenPresent` mapping is not supported for batch inserts. ## General Insert Statement A general insert is used to build arbitrary insert statements. The general insert does not require a separate record object to hold values for the statement - any value can be passed into the statement. This version of the insert is not convenient for retrieving generated keys with MyBatis - for that use case we recommend the "single record insert". However the general insert is perfectly acceptable for Spring JDBC template or MyBatis inserts that do not return generated keys. For example @@ -265,7 +265,7 @@ import org.mybatis.dynamic.sql.util.SqlProviderAdapter; We do not recommend using an XML mapper for insert statements, but if you want to do so the GeneralInsertStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you are using an XML mapper, the insert method should look like this in the Java interface: - + ```java import org.mybatis.dynamic.sql.insert.render.GeneralInsertStatementProvider; @@ -299,7 +299,7 @@ An insert select is an SQL insert statement the inserts the results of a select int rows = mapper.insertSelect(insertSelectStatement); ``` -The column list is optional and can be removed if the selected columns match the layout of the table. +The column list is optional and can be removed if the selected columns match the layout of the table. ### Annotated Mapper for Insert Select Statements The InsertSelectStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you @@ -322,7 +322,7 @@ Note that MyBatis does not support overloaded mapper method names, so the name o We do not recommend using an XML mapper for insert statements, but if you want to do so the InsertSelectStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you are using an XML mapper, the insert method should look like this in the Java interface: - + ```java import org.mybatis.dynamic.sql.insert.render.InsertSelectStatementProvider; diff --git a/src/site/markdown/docs/introduction.md b/src/site/markdown/docs/introduction.md index e9b8b2c9e..32b2f9899 100644 --- a/src/site/markdown/docs/introduction.md +++ b/src/site/markdown/docs/introduction.md @@ -33,8 +33,8 @@ The primary goals of the library are: 3. Flexible - where clauses can be built using any combination of and, or, and nested conditions 4. Extensible - the library will render statements for MyBatis3, Spring JDBC templates or plain JDBC. It can be extended to generate clauses for other frameworks as well. Custom where conditions can - be added easily if none of the built in conditions are sufficient for your needs. + be added easily if none of the built in conditions are sufficient for your needs. 5. Small - the library is a small dependency to add. It has no transitive dependencies. - + This library grew out of a desire to create a utility that could be used to improve the code generated by MyBatis Generator, but the library can be used on its own with very little setup required. diff --git a/src/site/markdown/docs/kotlinMyBatis3.md b/src/site/markdown/docs/kotlinMyBatis3.md index 18a3a5c1e..5150f8215 100644 --- a/src/site/markdown/docs/kotlinMyBatis3.md +++ b/src/site/markdown/docs/kotlinMyBatis3.md @@ -115,7 +115,7 @@ The extension methods will reuse the abstract methods and add functionality to m execute the SQL statements in a one-step process. The extension methods shown below assume that you will create a set of CRUD methods for each table you are accessing (as is the case with code created by MyBatis Generator). -If you create a Kotlin mapper interface that includes both abstract and non-abstract methods, MyBatis will +If you create a Kotlin mapper interface that includes both abstract and non-abstract methods, MyBatis will throw errors. By default, Kotlin does not create Java default methods in an interface. For this reason, Kotlin mapper interfaces should only contain the actual MyBatis mapper abstract interface methods. What would normally be coded as default or static methods in a Java mapper interface should be coded as extension methods in Kotlin. For example, @@ -556,7 +556,7 @@ val rows = mapper.insertMultiple(record1, record2) ### Generated Key Support -Multi-row insert statements support returning a generated key using normal MyBatis generated key support. However, +Multi-row insert statements support returning a generated key using normal MyBatis generated key support. However, generated keys require some care for multi-row insert statements. In this section we will show how to use the library's built-in support. When generated keys are expected you must code the mapper method manually and supply the `@Options` annotation that configures generated key support. You cannot use the built-in base interface when there are @@ -606,7 +606,7 @@ import org.apache.ibatis.executor.BatchResult interface PersonMapper { @InsertProvider(type = SqlProviderAdapter::class, method = "insert") fun insert(insertStatement: InsertStatementProvider): Int - + @Flush fun flush(): List } @@ -838,7 +838,7 @@ distinct can be executed with the `selectMany` method. ### One-Step Method You can use built-in utility functions to create mapper extension functions that simplify execution of select statements. The extension functions will reuse the abstract methods and supply the table and column list for the statement. -We recommend three extension methods for select multiple records, select multiple records with the distinct keyword, +We recommend three extension methods for select multiple records, select multiple records with the distinct keyword, and selecting a single record: ```kotlin @@ -1024,7 +1024,7 @@ It is also possible to write utility methods that will set values. For example: fun KotlinUpdateBuilder.updateSelectiveColumns(record: PersonRecord) = apply { set(id) equalToWhenPresent record::id - set(firstName) equalToWhenPresent record::firstName + set(firstName) equalToWhenPresent record::firstName set(lastName) equalToWhenPresent record::lastName set(birthDate) equalToWhenPresent record::birthDate set(employed) equalToWhenPresent record::employed diff --git a/src/site/markdown/docs/kotlinOverview.md b/src/site/markdown/docs/kotlinOverview.md index 9346488d6..5b646a7b0 100644 --- a/src/site/markdown/docs/kotlinOverview.md +++ b/src/site/markdown/docs/kotlinOverview.md @@ -94,7 +94,7 @@ object PersonDynamicSqlSupport { val birthDate = person.birthDate val employed = person.employed val occupation = person.occupation - + class Person : AlisableSqlTable("Person", ::Person) { val id = column(name = "id", jdbcType = JDBCType.INTEGER) val firstName = column(name = "first_name", jdbcType = JDBCType.VARCHAR) @@ -118,7 +118,7 @@ Notes: instances for use in self-joins. 3. Note the use of the `column` extension function. This function accepts different parameters for the different attributes that can be assigned to a column (such as a MyBatis3 type handler, or a - custom rendering strategy). We recommend using this extension function rather than the corresponding `column` and + custom rendering strategy). We recommend using this extension function rather than the corresponding `column` and `withXXX` methods in the Java native DSL because the extension method will retain the non-nullable type information associated with the column. @@ -168,7 +168,7 @@ val countColumnStatement = count(lastName) { from(person) } -// count(distinct column) +// count(distinct column) val countDistinctColumnStatement = countDistinct(lastName) { from(person) } @@ -232,7 +232,7 @@ val row = PersonRecord(100, "Joe", "Jones", Date(), true, "Developer", 1) val insertRecordStatement = insert(row) { into(person) - map(id) toProperty "id" + map(id) toProperty "id" map(firstName) toProperty "firstName" map(lastName) toProperty "lastName" map(birthDate) toProperty "birthDate" diff --git a/src/site/markdown/docs/kotlinSpring.md b/src/site/markdown/docs/kotlinSpring.md index f30712fb9..ec008c2c1 100644 --- a/src/site/markdown/docs/kotlinSpring.md +++ b/src/site/markdown/docs/kotlinSpring.md @@ -24,7 +24,7 @@ For each operation, there are two different methods of executing SQL: 1. The first method is a two-step method. With this method you build SQL provider objects as shown on the Kotlin overview page and then execute the generated SQL by passing the provider to an extension method on `NamedParameterJdbcTemplate` -2. The second method is a one-step method that combines these operations into a single step +2. The second method is a one-step method that combines these operations into a single step We will illustrate both approaches below. @@ -586,7 +586,7 @@ Multi-select statements are a special case of select statement. All the above in equally to multi-select statements. The library does not provide a "one-step" shortcut for multi-select queries. You can execute a multi-select query -with the two-step method using either the "selectList" or "selectOne" extension methods as shown above. +with the two-step method using either the "selectList" or "selectOne" extension methods as shown above. ## Update Method Support diff --git a/src/site/markdown/docs/kotlinWhereClauses.md b/src/site/markdown/docs/kotlinWhereClauses.md index 887012488..23ab8801d 100644 --- a/src/site/markdown/docs/kotlinWhereClauses.md +++ b/src/site/markdown/docs/kotlinWhereClauses.md @@ -140,7 +140,7 @@ given context. Others must be enclosed in an `and` or an `or` block. The four ty } } ``` - + You can accomplish a "not exists" by nesting `exists` inside a `not` block: ```kotlin diff --git a/src/site/markdown/docs/mybatis3.md b/src/site/markdown/docs/mybatis3.md index 17eb9e5d2..5af522b7b 100644 --- a/src/site/markdown/docs/mybatis3.md +++ b/src/site/markdown/docs/mybatis3.md @@ -47,7 +47,7 @@ public interface FooMapper extends CommonCountMapper, CommonDeleteMapper, Common } ``` -This mapper can be extended with default methods as shown below. +This mapper can be extended with default methods as shown below. ### Common Select Mapper MyBatis is very good at mapping result sets to objects - this is one of its primary differentiators. MyBatis also requires @@ -58,7 +58,7 @@ The general mapper is `org.mybatis.dynamic.sql.util.mybatis3.CommonSelectMapper` MyBatis configuration as is, or it can be extended by an existing mapper. The mapper contains three types of methods: - + 1. The `selectOneMappedRow` and `selectManyMappedRows` methods allow you to use select statements with any number of columns. MyBatis will process the rows and return a Map of values, or a List of Maps for multiple rows. 1. The `selectOne` and `selectMany` methods also allow you to use select statements with any number of columns. These methods @@ -222,7 +222,7 @@ int delete(DeleteStatementProvider deleteStatement); ``` This is a standard method for MyBatis Dynamic SQL that executes a delete and returns an `int` - the number of rows deleted. -In lieu of writing this method, you could extend `org.mybatis.dynamic.sql.util.mybatis3.CommonDeleteMapper` instead. +In lieu of writing this method, you could extend `org.mybatis.dynamic.sql.util.mybatis3.CommonDeleteMapper` instead. The second method will reuse this method and supply everything needed to build the delete statement except the where clause: ```java @@ -265,7 +265,7 @@ int insertMultiple(MultiRowInsertStatementProvider insertStatement These methods are standard methods for MyBatis Dynamic SQL. They execute a single row insert, a general insert, and a multiple row insert. In lieu of writing these methods, you could extend -`org.mybatis.dynamic.sql.util.mybatis3.CommonInsertMapper` instead. +`org.mybatis.dynamic.sql.util.mybatis3.CommonInsertMapper` instead. These methods can be used to implement simplified insert methods: @@ -275,7 +275,7 @@ default int insert(UnaryOperator completer) { } default int insert(PersonRecord record) { - return MyBatis3Utils.insert(this::insert, record, person, c -> + return MyBatis3Utils.insert(this::insert, record, person, c -> c.map(id).toProperty("id") .map(firstName).toProperty("firstName") .map(lastName).toProperty("lastName") @@ -326,7 +326,7 @@ standard MyBatis Dynamic SQL method that will execute a select: @Result(column="occupation", property="occupation", jdbcType=JdbcType.VARCHAR) }) List selectMany(SelectStatementProvider selectStatement); - + @SelectProvider(type=SqlProviderAdapter.class, method="select") @ResultMap("PersonResult") Optional selectOne(SelectStatementProvider selectStatement); @@ -364,13 +364,13 @@ default Optional selectByPrimaryKey(Integer id_) { ``` The `selectMany` method can be used to implement generalized select methods where a user can specify a where clause -and/or an order by clause. Typically, we recommend two of these methods - for select, and select distinct: +and/or an order by clause. Typically, we recommend two of these methods - for select, and select distinct: ```java default List select(SelectDSLCompleter completer) { return MyBatis3Utils.selectList(this::selectMany, selectList, person, completer); } - + default List selectDistinct(SelectDSLCompleter completer) { return MyBatis3Utils.selectDistinct(this::selectMany, selectList, person, completer); } @@ -415,7 +415,7 @@ int update(UpdateStatementProvider updateStatement); ``` This is a standard method for MyBatis Dynamic SQL that executes a query and returns an `int` - the number of rows updated. -In lieu of writing this method, you could extend `org.mybatis.dynamic.sql.util.mybatis3.CommonUpdateMapper` instead. +In lieu of writing this method, you could extend `org.mybatis.dynamic.sql.util.mybatis3.CommonUpdateMapper` instead. The second method will reuse this method and supply everything needed to build the update statement except the values and the where clause: diff --git a/src/site/markdown/docs/quickStart.md b/src/site/markdown/docs/quickStart.md index 3b50e33a6..01e9bdb9c 100644 --- a/src/site/markdown/docs/quickStart.md +++ b/src/site/markdown/docs/quickStart.md @@ -36,7 +36,7 @@ public class PersonRecord { private Boolean employed; private String occupation; private Integer addressId; - + // getters and setters omitted } ``` diff --git a/src/site/markdown/docs/select.md b/src/site/markdown/docs/select.md index bb1e0f01d..923c30c42 100644 --- a/src/site/markdown/docs/select.md +++ b/src/site/markdown/docs/select.md @@ -11,7 +11,7 @@ In general, the following are supported: 3. Columns can be aliased per select statement 4. Some support for aggregates (avg, min, max, sum) 5. Equijoins of type INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER -6. Subqueries in where clauses. For example, `where foo in (select foo from foos where id < 36)` +6. Subqueries in where clauses. For example, `where foo in (select foo from foos where id < 36)` 7. Select from another select. For example `select count(*) from (select foo from foos where id < 36)` 8. Multi-Selects. For example `(select * from foo order by id limit 3) union (select * from foo order by id desc limit 3)` @@ -115,7 +115,7 @@ paging clauses can be applied to the merged queries. For example: The SelectStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you are using an annotated mapper, the select method should look like this (note that we recommend coding a "selectMany" and a "selectOne" method with a shared result mapping): - + ```java import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.ResultMap; @@ -174,7 +174,7 @@ Notice that the resultMap is the only element in the XML mapper. This is our rec We do not recommend using an XML mapper for select statements, but if you want to do so the SelectStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you are using an XML mapper, the select method should look like this in the Java interface: - + ```java import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; @@ -212,7 +212,7 @@ it is easist to use the "arbitrary string" method with the column alias as shown there is a join, and the ORDER BY column is in two or more tables, and the ORDER BY column is not in the select list. For example `orderBy(sortColumn("t1", foo))`. 1. If none of the above use cases meet your needs, then you can specify an arbitrary String to write into the rendered ORDER BY -phrase (see below for an example). +phrase (see below for an example). In our testing, this caused an issue in only one case. When there is an outer join and the select list contains both the left and right join column. In that case, the workaround is to supply a column alias for both columns. diff --git a/src/site/markdown/docs/spring.md b/src/site/markdown/docs/spring.md index d3c8710f2..d247365cd 100644 --- a/src/site/markdown/docs/spring.md +++ b/src/site/markdown/docs/spring.md @@ -60,7 +60,7 @@ The following code shows a complete example without the utility class: .orderBy(id.descending()) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); - + SqlParameterSource namedParameters = new MapSqlParameterSource(selectStatement.getParameters()); List records = template.query(selectStatement.getSelectStatement(), namedParameters, (rs, rowNum) -> { @@ -83,7 +83,7 @@ The following code shows a complete example with the utility class: .from(generatedAlways) .where(id, isGreaterThan(3)) .orderBy(id.descending()); - + List records = extensions.selectList(selectStatement, (rs, rowNum) -> { GeneratedAlwaysRecord record = new GeneratedAlwaysRecord(); @@ -104,7 +104,7 @@ The utility class also includes a `selectOne` method that returns an `Optional`. Buildable selectStatement = select(id, firstName, lastName, fullName) .from(generatedAlways) .where(id, isEqualTo(3)); - + Optional record = extensions.selectOne(selectStatement, (rs, rowNum) -> { GeneratedAlwaysRecord record = new GeneratedAlwaysRecord(); @@ -167,7 +167,7 @@ This can be simplified by using the utility class as follows: .set(id).toValue(100) .set(firstName).toValue("Bob") .set(lastName).toValue("Jones"); - + // no generated key retrieval int rows = extensions.generalInsert(insertStatement); @@ -186,7 +186,7 @@ Insert record statements are a bit different - MyBatis Dynamic SQL generates a p record.setId(100); record.setFirstName("Bob"); record.setLastName("Jones"); - + InsertStatementProvider insertStatement = insert(record) .into(generatedAlways) .map(id).toProperty("id") @@ -194,10 +194,10 @@ Insert record statements are a bit different - MyBatis Dynamic SQL generates a p .map(lastName).toProperty("lastName") .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); - + SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(insertStatement.getRecord()); KeyHolder keyHolder = new GeneratedKeyHolder(); - + int rows = template.update(insertStatement.getInsertStatement(), parameterSource, keyHolder); String generatedKey = (String) keyHolder.getKeys().get("FULL_NAME"); ``` @@ -212,13 +212,13 @@ This can be simplified by using the utility class as follows: record.setId(100); record.setFirstName("Bob"); record.setLastName("Jones"); - + Buildable> insertStatement = insert(record) .into(generatedAlways) .map(id).toProperty("id") .map(firstName).toProperty("firstName") .map(lastName).toProperty("lastName"); - + // no generated key retrieval int rows = extensions.insert(insertStatement); @@ -241,7 +241,7 @@ With multi-row insert statements MyBatis Dynamic SQL generates a properly format record.setFirstName("Bob"); record.setLastName("Jones"); records.add(record); - + record = new GeneratedAlwaysRecord(); record.setId(101); record.setFirstName("Jim"); @@ -257,7 +257,7 @@ With multi-row insert statements MyBatis Dynamic SQL generates a properly format SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(insertStatement); KeyHolder keyHolder = new GeneratedKeyHolder(); - + int rows = template.update(insertStatement.getInsertStatement(), parameterSource, keyHolder); String firstGeneratedKey = (String) keyHolder.getKeyList().get(0).get("FULL_NAME"); String secondGeneratedKey = (String) keyHolder.getKeyList().get(1).get("FULL_NAME"); @@ -275,7 +275,7 @@ This can be simplified by using the utility class as follows: record.setFirstName("Bob"); record.setLastName("Jones"); records.add(record); - + record = new GeneratedAlwaysRecord(); record.setId(101); record.setFirstName("Jim"); @@ -307,7 +307,7 @@ A JDBC batch insert is an efficient way to perform a bulk insert. It does not ha record.setFirstName("Bob"); record.setLastName("Jones"); records.add(record); - + record = new GeneratedAlwaysRecord(); record.setId(101); record.setFirstName("Jim"); @@ -315,7 +315,7 @@ A JDBC batch insert is an efficient way to perform a bulk insert. It does not ha records.add(record); SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(records.toArray()); - + BatchInsert batchInsert = insert(records) .into(generatedAlways) .map(id).toProperty("id") @@ -323,7 +323,7 @@ A JDBC batch insert is an efficient way to perform a bulk insert. It does not ha .map(lastName).toProperty("lastName") .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); - + int[] updateCounts = template.batchUpdate(batchInsert.getInsertStatementSQL(), batch); ``` @@ -339,7 +339,7 @@ This can be simplified by using the utility class as follows: record.setFirstName("Bob"); record.setLastName("Jones"); records.add(record); - + record = new GeneratedAlwaysRecord(); record.setId(101); record.setFirstName("Jim"); @@ -351,7 +351,7 @@ This can be simplified by using the utility class as follows: .map(id).toProperty("id") .map(firstName).toProperty("firstName") .map(lastName).toProperty("lastName"); - + int[] updateCounts = extensions.insertBatch(insertStatement); ``` @@ -365,9 +365,9 @@ Delete statements use the `MapSqlParameterSource` as with select statements, but .where(id, isLessThan(3)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); - + SqlParameterSource parameterSource = new MapSqlParameterSource(deleteStatement.getParameters()); - + int rows = template.update(deleteStatement.getDeleteStatement(), parameterSource); ``` @@ -379,7 +379,7 @@ This can be simplified by using the utility class as follows: Buildable deleteStatement = deleteFrom(generatedAlways) .where(id, isLessThan(3)); - + int rows = extensions.delete(deleteStatement); ``` @@ -394,9 +394,9 @@ Update statements use the `MapSqlParameterSource` as with select statements, but .where(id, isIn(1, 5, 22)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); - + SqlParameterSource parameterSource = new MapSqlParameterSource(updateStatement.getParameters()); - + int rows = template.update(updateStatement.getUpdateStatement(), parameterSource); ``` @@ -409,6 +409,6 @@ This can be simplified by using the utility class as follows: Buildable updateStatement = update(generatedAlways) .set(firstName).equalToStringConstant("Rob") .where(id, isIn(1, 5, 22)); - + int rows = extensions.update(updateStatement); ``` diff --git a/src/site/markdown/docs/subQueries.md b/src/site/markdown/docs/subQueries.md index ecd570c85..0f2913093 100644 --- a/src/site/markdown/docs/subQueries.md +++ b/src/site/markdown/docs/subQueries.md @@ -14,7 +14,7 @@ table qualifiers in select statements. We'll cover that first. The library attempts to automatically calculate table qualifiers. If a table qualifier is specified, the library will automatically render the table qualifier on all columns associated with the -table. For example with the following query: +table. For example with the following query: ```java SelectStatementProvider selectStatement = @@ -73,10 +73,10 @@ from (select a.id, a.animal_name where id < #{parameters.p1} order by animal_name desc) b where rownum() < #{parameters.p2} - and animal_name like #{parameters.p3} + and animal_name like #{parameters.p3} ``` -Notice that the qualifier `a` is automatically applied to columns in the subquery and that the +Notice that the qualifier `a` is automatically applied to columns in the subquery and that the qualifier `b` is not applied anywhere. If your query requires the subquery qualifier to be applied to columns in the outer select list, @@ -110,7 +110,7 @@ from (select a.id, a.animal_name where id < #{parameters.p1} order by animal_name desc) b where rownum() < #{parameters.p2} - and b.animal_name like #{parameters.p3} + and b.animal_name like #{parameters.p3} ``` ## Subqueries in Where Conditions @@ -164,7 +164,7 @@ SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, bra ### Kotlin Support The library includes Kotlin versions of the where conditions that allow use of the Kotlin subquery builder. The Kotlin where conditions are in the `org.mybatis.dynamic.sql.util.kotlin` package. - + An example of an exists subquery is as follows: ```kotlin val selectStatement = select(ItemMaster.allColumns()) { diff --git a/src/site/markdown/docs/update.md b/src/site/markdown/docs/update.md index eb1298515..c98388ef6 100644 --- a/src/site/markdown/docs/update.md +++ b/src/site/markdown/docs/update.md @@ -42,7 +42,7 @@ For example: The UpdateStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you are using an annotated mapper, the update method should look like this: - + ```java import org.apache.ibatis.annotations.UpdateProvider; import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider; @@ -59,7 +59,7 @@ import org.mybatis.dynamic.sql.util.SqlProviderAdapter; We do not recommend using an XML mapper for update statements, but if you want to do so the UpdateStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you are using an XML mapper, the update method should look like this in the Java interface: - + ```java import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider; diff --git a/src/site/markdown/docs/whereClauses.md b/src/site/markdown/docs/whereClauses.md index cd79c0c74..a7e5516e5 100644 --- a/src/site/markdown/docs/whereClauses.md +++ b/src/site/markdown/docs/whereClauses.md @@ -146,7 +146,7 @@ parameter name to use the for rendered where clause. That code looks like this: Optional whereClause = where(id, isLessThan(60)) .build() .render(RenderingStrategies.MYBATIS3, "whereClauseProvider"); - + List animals = whereClause.map(wc -> mapper.selectWithWhereClauseLimitAndOffset(wc, 5, 15)).orElse(Collections.emptyList()); ``` Notice that the string `whereClauseProvider` is used both as the parameter name in the mapper `@Param` annotation, diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md index 6cb33e241..9d1ca46b6 100644 --- a/src/site/markdown/index.md +++ b/src/site/markdown/index.md @@ -3,7 +3,7 @@ MyBatis Dynamic SQL is an SQL DSL (domain specific language). It allows develope includes many functions for creating very dynamic SQL statements based on current runtime parameter values. The DSL will render standard SQL DELETE, INSERT, SELECT, and UPDATE statements - and associated -parameters - that can be used directly by SQL execution engines like MyBatis or Spring JDBC template. +parameters - that can be used directly by SQL execution engines like MyBatis or Spring JDBC template. Please read the user's guide for detailed instructions on use. The user's guide is accessible through menu links to the left. From 678dbe84557d0689b5d0754a1d943d6d110215a5 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Fri, 9 Jun 2023 11:44:57 -0400 Subject: [PATCH 3/8] Remove trailing spaces --- src/site/markdown/docs/codingStandards.md | 4 +- .../kotlin/nullability/test/BetweenTest.kt | 12 ++--- .../test/BetweenWhenPresentTest.kt | 12 ++--- .../kotlin/nullability/test/ComparisonTest.kt | 48 +++++++++---------- .../nullability/test/EqualNotEqualTest.kt | 16 +++---- src/test/kotlin/nullability/test/InTest.kt | 8 ++-- .../nullability/test/InWhenPresentTest.kt | 16 +++---- .../nullability/test/LikeNotLikeTest.kt | 16 +++---- .../kotlin/nullability/test/NotBetweenTest.kt | 12 ++--- .../test/NotBetweenWhenPresentTest.kt | 12 ++--- src/test/kotlin/nullability/test/NotInTest.kt | 8 ++-- .../nullability/test/NotInWhenPresentTest.kt | 16 +++---- 12 files changed, 90 insertions(+), 90 deletions(-) diff --git a/src/site/markdown/docs/codingStandards.md b/src/site/markdown/docs/codingStandards.md index 052aa0c61..bfb0c5404 100644 --- a/src/site/markdown/docs/codingStandards.md +++ b/src/site/markdown/docs/codingStandards.md @@ -30,7 +30,7 @@ these general principles for functional style coding in Java: We are committed to clean code. This means: -- Small methods - less than 5 lines is good, 1 line is ideal +- Small methods - less than 5 lines is good, 1 line is ideal - Small classes - less than 100 lines is good, less than 50 lines is ideal - Use descriptive names - Comments are a last resort - don't comment bad code, refactor it @@ -43,7 +43,7 @@ We are committed to clean code. This means: Remember the three rules of TDD: 1. You may not write production code until you have written a failing unit test. -2. You may not write more of a unit test than is sufficient to fail, and not compiling is failing. +2. You may not write more of a unit test than is sufficient to fail, and not compiling is failing. 3. You may not write more production code than is sufficient to passing the currently failing test. diff --git a/src/test/kotlin/nullability/test/BetweenTest.kt b/src/test/kotlin/nullability/test/BetweenTest.kt index db7de0b1b..84bf2dfd7 100644 --- a/src/test/kotlin/nullability/test/BetweenTest.kt +++ b/src/test/kotlin/nullability/test/BetweenTest.kt @@ -23,7 +23,7 @@ class BetweenTest { fun `Test That First Null Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class BetweenTest { fun `Test That Second Null Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -63,7 +63,7 @@ class BetweenTest { fun `Test That Both Null Causes Two Compile Errors`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -86,7 +86,7 @@ class BetweenTest { fun `Test That First Null In Elements Method Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -107,7 +107,7 @@ class BetweenTest { fun `Test That Second Null In Elements Method Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -128,7 +128,7 @@ class BetweenTest { fun `Test That Both Null In Elements Method Causes Two Compile Errors`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom diff --git a/src/test/kotlin/nullability/test/BetweenWhenPresentTest.kt b/src/test/kotlin/nullability/test/BetweenWhenPresentTest.kt index f07c0d383..2c7b0316d 100644 --- a/src/test/kotlin/nullability/test/BetweenWhenPresentTest.kt +++ b/src/test/kotlin/nullability/test/BetweenWhenPresentTest.kt @@ -23,7 +23,7 @@ class BetweenWhenPresentTest { fun `Test That First Null Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class BetweenWhenPresentTest { fun `Test That Second Null Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -63,7 +63,7 @@ class BetweenWhenPresentTest { fun `Test That Both Null Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -83,7 +83,7 @@ class BetweenWhenPresentTest { fun `Test That First Null In Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -104,7 +104,7 @@ class BetweenWhenPresentTest { fun `Test That Second Null In Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -125,7 +125,7 @@ class BetweenWhenPresentTest { fun `Test That Both Null In Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom diff --git a/src/test/kotlin/nullability/test/ComparisonTest.kt b/src/test/kotlin/nullability/test/ComparisonTest.kt index d667db430..76c721ab5 100644 --- a/src/test/kotlin/nullability/test/ComparisonTest.kt +++ b/src/test/kotlin/nullability/test/ComparisonTest.kt @@ -23,7 +23,7 @@ class ComparisonTest { fun `Test That Null In EqualTo Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class ComparisonTest { fun `Test That Null In EqualToWhenPresent is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -63,7 +63,7 @@ class ComparisonTest { fun `Test That Null In EqualTo Elements Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -84,7 +84,7 @@ class ComparisonTest { fun `Test That Null In EqualToWhenPresent Elements is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -105,7 +105,7 @@ class ComparisonTest { fun `Test That Null In NotEqualTo Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -125,7 +125,7 @@ class ComparisonTest { fun `Test That Null In NotEqualToWhenPresent is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -145,7 +145,7 @@ class ComparisonTest { fun `Test That Null In NotEqualTo Elements Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -166,7 +166,7 @@ class ComparisonTest { fun `Test That Null In NotEqualToWhenPresent Elements is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -187,7 +187,7 @@ class ComparisonTest { fun `Test That Null In GreaterThan Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -207,7 +207,7 @@ class ComparisonTest { fun `Test That Null In GreaterThanWhenPresent is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -227,7 +227,7 @@ class ComparisonTest { fun `Test That Null In GreaterThan Elements Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -248,7 +248,7 @@ class ComparisonTest { fun `Test That Null In GreaterThanWhenPresent Elements is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -269,7 +269,7 @@ class ComparisonTest { fun `Test That Null In GreaterThanOrEqualTo Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -289,7 +289,7 @@ class ComparisonTest { fun `Test That Null In GreaterThanOrEqualToWhenPresent is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -309,7 +309,7 @@ class ComparisonTest { fun `Test That Null In GreaterThanOrEqualTo Elements Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -330,7 +330,7 @@ class ComparisonTest { fun `Test That Null In GreaterThanOrEqualToWhenPresent Elements is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -351,7 +351,7 @@ class ComparisonTest { fun `Test That Null In LessThan Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -371,7 +371,7 @@ class ComparisonTest { fun `Test That Null In LessThanWhenPresent is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -391,7 +391,7 @@ class ComparisonTest { fun `Test That Null In LessThan Elements Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -412,7 +412,7 @@ class ComparisonTest { fun `Test That Null In LessThanWhenPresent Elements is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -433,7 +433,7 @@ class ComparisonTest { fun `Test That Null In LessThanOrEqualTo Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -453,7 +453,7 @@ class ComparisonTest { fun `Test That Null In LessThanOrEqualToWhenPresent is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -473,7 +473,7 @@ class ComparisonTest { fun `Test That Null In LessThanOrEqualTo Elements Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -494,7 +494,7 @@ class ComparisonTest { fun `Test That Null In LessThanOrEqualToWhenPresent Elements is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom diff --git a/src/test/kotlin/nullability/test/EqualNotEqualTest.kt b/src/test/kotlin/nullability/test/EqualNotEqualTest.kt index b3b3aedec..dbc1590b8 100644 --- a/src/test/kotlin/nullability/test/EqualNotEqualTest.kt +++ b/src/test/kotlin/nullability/test/EqualNotEqualTest.kt @@ -23,7 +23,7 @@ class EqualNotEqualTest { fun `Test That Null Equal Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class EqualNotEqualTest { fun `Test That Null Equal When Present is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -63,7 +63,7 @@ class EqualNotEqualTest { fun `Test That Null Not Equal Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -84,7 +84,7 @@ class EqualNotEqualTest { fun `Test That Null Not Equal When Present is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -104,7 +104,7 @@ class EqualNotEqualTest { fun `Test That Null Elements Equal Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -125,7 +125,7 @@ class EqualNotEqualTest { fun `Test That Null Elements Equal When Present is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -146,7 +146,7 @@ class EqualNotEqualTest { fun `Test That Null Elements Not Equal Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -168,7 +168,7 @@ class EqualNotEqualTest { fun `Test That Null Elements Not Equal When Present is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom diff --git a/src/test/kotlin/nullability/test/InTest.kt b/src/test/kotlin/nullability/test/InTest.kt index cf8504c43..91ce704a7 100644 --- a/src/test/kotlin/nullability/test/InTest.kt +++ b/src/test/kotlin/nullability/test/InTest.kt @@ -23,7 +23,7 @@ class InTest { fun `Test That Null In VarAgs Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class InTest { fun `Test That Null in List Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -64,7 +64,7 @@ class InTest { fun `Test That Null In VarArgs Elements Method Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -85,7 +85,7 @@ class InTest { fun `Test That Null In List Elements Method Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom diff --git a/src/test/kotlin/nullability/test/InWhenPresentTest.kt b/src/test/kotlin/nullability/test/InWhenPresentTest.kt index 019a0f4f8..581b512fd 100644 --- a/src/test/kotlin/nullability/test/InWhenPresentTest.kt +++ b/src/test/kotlin/nullability/test/InWhenPresentTest.kt @@ -23,7 +23,7 @@ class InWhenPresentTest { fun `Test That Null In VarAgs Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class InWhenPresentTest { fun `Test That Null in List Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -64,7 +64,7 @@ class InWhenPresentTest { fun `Test That Empty VarAgs Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -84,7 +84,7 @@ class InWhenPresentTest { fun `Test That Null List Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -104,7 +104,7 @@ class InWhenPresentTest { fun `Test That Null In VarArgs Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -125,7 +125,7 @@ class InWhenPresentTest { fun `Test That Null In List Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -147,7 +147,7 @@ class InWhenPresentTest { fun `Test That Empty VarAgs In Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -168,7 +168,7 @@ class InWhenPresentTest { fun `Test That Null List In Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom diff --git a/src/test/kotlin/nullability/test/LikeNotLikeTest.kt b/src/test/kotlin/nullability/test/LikeNotLikeTest.kt index 03c70be36..b05964cc3 100644 --- a/src/test/kotlin/nullability/test/LikeNotLikeTest.kt +++ b/src/test/kotlin/nullability/test/LikeNotLikeTest.kt @@ -23,7 +23,7 @@ class LikeNotLikeTest { fun `Test That Null Like Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class LikeNotLikeTest { fun `Test That Null Like When Present is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -63,7 +63,7 @@ class LikeNotLikeTest { fun `Test That Null Not Like Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -84,7 +84,7 @@ class LikeNotLikeTest { fun `Test That Null Not Like When Present is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -104,7 +104,7 @@ class LikeNotLikeTest { fun `Test That Null Elements Like Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -125,7 +125,7 @@ class LikeNotLikeTest { fun `Test That Null Elements Like When Present is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -146,7 +146,7 @@ class LikeNotLikeTest { fun `Test That Null Elements Not Like Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -168,7 +168,7 @@ class LikeNotLikeTest { fun `Test That Null Elements Not Like When Present is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.firstName import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom diff --git a/src/test/kotlin/nullability/test/NotBetweenTest.kt b/src/test/kotlin/nullability/test/NotBetweenTest.kt index 18e2cbc83..c4c784382 100644 --- a/src/test/kotlin/nullability/test/NotBetweenTest.kt +++ b/src/test/kotlin/nullability/test/NotBetweenTest.kt @@ -23,7 +23,7 @@ class NotBetweenTest { fun `Test That First Null Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class NotBetweenTest { fun `Test That Second Null Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -63,7 +63,7 @@ class NotBetweenTest { fun `Test That Both Null Causes Compile Errors`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -86,7 +86,7 @@ class NotBetweenTest { fun `Test That First Null In Elements Method Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -107,7 +107,7 @@ class NotBetweenTest { fun `Test That Second Null In Elements Method Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -128,7 +128,7 @@ class NotBetweenTest { fun `Test That Both Null In Elements Method Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom diff --git a/src/test/kotlin/nullability/test/NotBetweenWhenPresentTest.kt b/src/test/kotlin/nullability/test/NotBetweenWhenPresentTest.kt index bc19da1b1..a98cc49ad 100644 --- a/src/test/kotlin/nullability/test/NotBetweenWhenPresentTest.kt +++ b/src/test/kotlin/nullability/test/NotBetweenWhenPresentTest.kt @@ -23,7 +23,7 @@ class NotBetweenWhenPresentTest { fun `Test That First Null Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class NotBetweenWhenPresentTest { fun `Test That Second Null Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -63,7 +63,7 @@ class NotBetweenWhenPresentTest { fun `Test That Both Null Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -83,7 +83,7 @@ class NotBetweenWhenPresentTest { fun `Test That First Null In Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -104,7 +104,7 @@ class NotBetweenWhenPresentTest { fun `Test That Second Null In Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -125,7 +125,7 @@ class NotBetweenWhenPresentTest { fun `Test That Both Null In Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom diff --git a/src/test/kotlin/nullability/test/NotInTest.kt b/src/test/kotlin/nullability/test/NotInTest.kt index 0d5a68847..dbb523e1e 100644 --- a/src/test/kotlin/nullability/test/NotInTest.kt +++ b/src/test/kotlin/nullability/test/NotInTest.kt @@ -23,7 +23,7 @@ class NotInTest { fun `Test That Null In VarAgs Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class NotInTest { fun `Test That Null in List Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -64,7 +64,7 @@ class NotInTest { fun `Test That Null In VarArgs Elements Method Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -85,7 +85,7 @@ class NotInTest { fun `Test That Null In List Elements Method Causes Compile Error`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom diff --git a/src/test/kotlin/nullability/test/NotInWhenPresentTest.kt b/src/test/kotlin/nullability/test/NotInWhenPresentTest.kt index ec6d6bf0b..3d22f8475 100644 --- a/src/test/kotlin/nullability/test/NotInWhenPresentTest.kt +++ b/src/test/kotlin/nullability/test/NotInWhenPresentTest.kt @@ -23,7 +23,7 @@ class NotInWhenPresentTest { fun `Test That Null In VarAgs Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -43,7 +43,7 @@ class NotInWhenPresentTest { fun `Test That Null in List Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -64,7 +64,7 @@ class NotInWhenPresentTest { fun `Test That Empty VarAgs Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -84,7 +84,7 @@ class NotInWhenPresentTest { fun `Test That Null List Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -104,7 +104,7 @@ class NotInWhenPresentTest { fun `Test That Null In VarArgs Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -125,7 +125,7 @@ class NotInWhenPresentTest { fun `Test That Null In List Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -147,7 +147,7 @@ class NotInWhenPresentTest { fun `Test That Empty VarAgs In Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom @@ -168,7 +168,7 @@ class NotInWhenPresentTest { fun `Test That Null List In Elements Method Is OK`() { val source = """ package temp.kotlin.test - + import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.person import org.mybatis.dynamic.sql.util.kotlin.mybatis3.countFrom From f35a4dec779ce4a192e2476c7f26dadca2a079d7 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Fri, 9 Jun 2023 12:54:10 -0400 Subject: [PATCH 4/8] Basic support for using parameter values in joins --- .../org/mybatis/dynamic/sql/SqlBuilder.java | 9 +- .../sql/select/QueryExpressionDSL.java | 11 ++- .../select/join/ColumnBasedJoinCondition.java | 37 +++++++ .../dynamic/sql/select/join/EqualTo.java | 2 +- .../dynamic/sql/select/join/EqualToValue.java | 27 +++++ .../sql/select/join/JoinCondition.java | 18 +--- .../sql/select/join/JoinConditionVisitor.java | 22 +++++ .../sql/select/join/JoinCriterion.java | 18 ++-- .../sql/select/join/TypedJoinCondition.java | 35 +++++++ .../select/render/JoinConditionRenderer.java | 98 +++++++++++++++++++ .../sql/select/render/JoinRenderer.java | 54 ++++++++-- .../render/QueryExpressionRenderer.java | 2 + .../dynamic/sql/util/kotlin/JoinCollector.kt | 7 +- .../java/examples/joins/JoinMapperTest.java | 34 +++++++ .../kotlin/mybatis3/joins/JoinMapperTest.kt | 35 +++++++ 15 files changed, 364 insertions(+), 45 deletions(-) create mode 100644 src/main/java/org/mybatis/dynamic/sql/select/join/ColumnBasedJoinCondition.java create mode 100644 src/main/java/org/mybatis/dynamic/sql/select/join/EqualToValue.java create mode 100644 src/main/java/org/mybatis/dynamic/sql/select/join/JoinConditionVisitor.java create mode 100644 src/main/java/org/mybatis/dynamic/sql/select/join/TypedJoinCondition.java create mode 100644 src/main/java/org/mybatis/dynamic/sql/select/render/JoinConditionRenderer.java diff --git a/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java b/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java index 4ed0de186..477676598 100644 --- a/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java +++ b/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java @@ -54,6 +54,7 @@ import org.mybatis.dynamic.sql.select.function.Subtract; import org.mybatis.dynamic.sql.select.function.Upper; import org.mybatis.dynamic.sql.select.join.EqualTo; +import org.mybatis.dynamic.sql.select.join.EqualToValue; import org.mybatis.dynamic.sql.select.join.JoinCondition; import org.mybatis.dynamic.sql.select.join.JoinCriterion; import org.mybatis.dynamic.sql.update.UpdateDSL; @@ -425,7 +426,7 @@ static AndOrCriteriaGroup and(List subCriteria) { } // join support - static JoinCriterion and(BasicColumn joinColumn, JoinCondition joinCondition) { + static JoinCriterion and(BindableColumn joinColumn, JoinCondition joinCondition) { return new JoinCriterion.Builder() .withConnector("and") //$NON-NLS-1$ .withJoinColumn(joinColumn) @@ -433,7 +434,7 @@ static JoinCriterion and(BasicColumn joinColumn, JoinCondition joinCondition) { .build(); } - static JoinCriterion on(BasicColumn joinColumn, JoinCondition joinCondition) { + static JoinCriterion on(BindableColumn joinColumn, JoinCondition joinCondition) { return new JoinCriterion.Builder() .withConnector("on") //$NON-NLS-1$ .withJoinColumn(joinColumn) @@ -445,6 +446,10 @@ static EqualTo equalTo(BasicColumn column) { return new EqualTo(column); } + static EqualToValue equalTo(T value) { + return new EqualToValue<>(value); + } + // aggregate support static CountAll count() { return new CountAll(); diff --git a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java index 422f915f2..b97601000 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java @@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.BindableColumn; import org.mybatis.dynamic.sql.CriteriaGroup; import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.SqlTable; @@ -349,11 +350,11 @@ public JoinSpecificationStarter(TableExpression joinTable, JoinType joinType) { this.joinType = joinType; } - public JoinSpecificationFinisher on(BasicColumn joinColumn, JoinCondition joinCondition) { + public JoinSpecificationFinisher on(BindableColumn joinColumn, JoinCondition joinCondition) { return new JoinSpecificationFinisher(joinTable, joinColumn, joinCondition, joinType); } - public JoinSpecificationFinisher on(BasicColumn joinColumn, JoinCondition onJoinCondition, + public JoinSpecificationFinisher on(BindableColumn joinColumn, JoinCondition onJoinCondition, JoinCriterion... andJoinCriteria) { return new JoinSpecificationFinisher(joinTable, joinColumn, onJoinCondition, joinType, andJoinCriteria); } @@ -364,7 +365,7 @@ public class JoinSpecificationFinisher implements Buildable { private final JoinSpecification.Builder joinSpecificationBuilder; - public JoinSpecificationFinisher(TableExpression table, BasicColumn joinColumn, + public JoinSpecificationFinisher(TableExpression table, BindableColumn joinColumn, JoinCondition joinCondition, JoinType joinType) { JoinCriterion joinCriterion = new JoinCriterion.Builder() .withConnector("on") //$NON-NLS-1$ @@ -379,7 +380,7 @@ public JoinSpecificationFinisher(TableExpression table, BasicColumn joinColumn, addJoinSpecificationBuilder(joinSpecificationBuilder); } - public JoinSpecificationFinisher(TableExpression table, BasicColumn joinColumn, + public JoinSpecificationFinisher(TableExpression table, BindableColumn joinColumn, JoinCondition joinCondition, JoinType joinType, JoinCriterion... andJoinCriteria) { JoinCriterion onJoinCriterion = new JoinCriterion.Builder() .withConnector("on") //$NON-NLS-1$ @@ -412,7 +413,7 @@ public QueryExpressionWhereBuilder where() { return QueryExpressionDSL.this.where(); } - public JoinSpecificationFinisher and(BasicColumn joinColumn, JoinCondition joinCondition) { + public JoinSpecificationFinisher and(BindableColumn joinColumn, JoinCondition joinCondition) { JoinCriterion joinCriterion = new JoinCriterion.Builder() .withConnector("and") //$NON-NLS-1$ .withJoinColumn(joinColumn) diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/ColumnBasedJoinCondition.java b/src/main/java/org/mybatis/dynamic/sql/select/join/ColumnBasedJoinCondition.java new file mode 100644 index 000000000..a9ca3bdd3 --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/ColumnBasedJoinCondition.java @@ -0,0 +1,37 @@ +/* + * Copyright 2016-2023 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. + * You may obtain a copy of the License at + * + * https://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. + */ +package org.mybatis.dynamic.sql.select.join; + +import java.util.Objects; + +import org.mybatis.dynamic.sql.BasicColumn; + +public abstract class ColumnBasedJoinCondition implements JoinCondition { + private final BasicColumn rightColumn; + + protected ColumnBasedJoinCondition(BasicColumn rightColumn) { + this.rightColumn = Objects.requireNonNull(rightColumn); + } + + public BasicColumn rightColumn() { + return rightColumn; + } + + @Override + public R accept(JoinConditionVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/EqualTo.java b/src/main/java/org/mybatis/dynamic/sql/select/join/EqualTo.java index d73cec215..d8fc448e5 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/join/EqualTo.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/EqualTo.java @@ -17,7 +17,7 @@ import org.mybatis.dynamic.sql.BasicColumn; -public class EqualTo extends JoinCondition { +public class EqualTo extends ColumnBasedJoinCondition { public EqualTo(BasicColumn rightColumn) { super(rightColumn); diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/EqualToValue.java b/src/main/java/org/mybatis/dynamic/sql/select/join/EqualToValue.java new file mode 100644 index 000000000..c7cb39c27 --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/EqualToValue.java @@ -0,0 +1,27 @@ +/* + * Copyright 2016-2023 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. + * You may obtain a copy of the License at + * + * https://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. + */ +package org.mybatis.dynamic.sql.select.join; + +public class EqualToValue extends TypedJoinCondition { + public EqualToValue(T value) { + super(value); + } + + @Override + public String operator() { + return "="; //$NON-NLS-1$ + } +} diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCondition.java b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCondition.java index 7db8327e2..eb091c957 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCondition.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCondition.java @@ -15,20 +15,8 @@ */ package org.mybatis.dynamic.sql.select.join; -import java.util.Objects; +public interface JoinCondition { + String operator(); -import org.mybatis.dynamic.sql.BasicColumn; - -public abstract class JoinCondition { - private final BasicColumn rightColumn; - - protected JoinCondition(BasicColumn rightColumn) { - this.rightColumn = Objects.requireNonNull(rightColumn); - } - - public BasicColumn rightColumn() { - return rightColumn; - } - - public abstract String operator(); + R accept(JoinConditionVisitor visitor); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinConditionVisitor.java b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinConditionVisitor.java new file mode 100644 index 000000000..cc3c0216b --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinConditionVisitor.java @@ -0,0 +1,22 @@ +/* + * Copyright 2016-2023 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. + * You may obtain a copy of the License at + * + * https://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. + */ +package org.mybatis.dynamic.sql.select.join; + +public interface JoinConditionVisitor { + R visit(TypedJoinCondition condition); + + R visit(ColumnBasedJoinCondition condition); +} diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCriterion.java b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCriterion.java index 269c77c28..1a96b30ad 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCriterion.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCriterion.java @@ -17,12 +17,12 @@ import java.util.Objects; -import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.BindableColumn; public class JoinCriterion { private final String connector; - private final BasicColumn leftColumn; + private final BindableColumn leftColumn; private final JoinCondition joinCondition; private JoinCriterion(Builder builder) { @@ -35,21 +35,17 @@ public String connector() { return connector; } - public BasicColumn leftColumn() { + public BindableColumn leftColumn() { return leftColumn; } - public BasicColumn rightColumn() { - return joinCondition.rightColumn(); - } - - public String operator() { - return joinCondition.operator(); + public JoinCondition joinCondition() { + return joinCondition; } public static class Builder { private String connector; - private BasicColumn joinColumn; + private BindableColumn joinColumn; private JoinCondition joinCondition; public Builder withConnector(String connector) { @@ -57,7 +53,7 @@ public Builder withConnector(String connector) { return this; } - public Builder withJoinColumn(BasicColumn joinColumn) { + public Builder withJoinColumn(BindableColumn joinColumn) { this.joinColumn = joinColumn; return this; } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/TypedJoinCondition.java b/src/main/java/org/mybatis/dynamic/sql/select/join/TypedJoinCondition.java new file mode 100644 index 000000000..17cd4e350 --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/TypedJoinCondition.java @@ -0,0 +1,35 @@ +/* + * Copyright 2016-2023 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. + * You may obtain a copy of the License at + * + * https://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. + */ +package org.mybatis.dynamic.sql.select.join; + +import java.util.Objects; + +public abstract class TypedJoinCondition implements JoinCondition { + private final T value; + + protected TypedJoinCondition(T value) { + this.value = Objects.requireNonNull(value); + } + + public T value() { + return value; + } + + @Override + public R accept(JoinConditionVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/JoinConditionRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/JoinConditionRenderer.java new file mode 100644 index 000000000..550bc406b --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/JoinConditionRenderer.java @@ -0,0 +1,98 @@ +/* + * Copyright 2016-2023 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. + * You may obtain a copy of the License at + * + * https://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. + */ +package org.mybatis.dynamic.sql.select.render; + +import static org.mybatis.dynamic.sql.util.StringUtilities.spaceBefore; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; + +import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.BindableColumn; +import org.mybatis.dynamic.sql.render.RenderingStrategy; +import org.mybatis.dynamic.sql.render.TableAliasCalculator; +import org.mybatis.dynamic.sql.select.join.ColumnBasedJoinCondition; +import org.mybatis.dynamic.sql.select.join.JoinConditionVisitor; +import org.mybatis.dynamic.sql.select.join.TypedJoinCondition; +import org.mybatis.dynamic.sql.util.FragmentAndParameters; + +public class JoinConditionRenderer implements JoinConditionVisitor { + private final RenderingStrategy renderingStrategy; + private final AtomicInteger sequence; + private final BindableColumn leftColumn; + private final TableAliasCalculator tableAliasCalculator; + + private JoinConditionRenderer(Builder builder) { + renderingStrategy = Objects.requireNonNull(builder.renderingStrategy); + sequence = Objects.requireNonNull(builder.sequence); + leftColumn = Objects.requireNonNull(builder.leftColumn); + tableAliasCalculator = Objects.requireNonNull(builder.tableAliasCalculator); + } + + @Override + public FragmentAndParameters visit(TypedJoinCondition condition) { + String mapKey = renderingStrategy.formatParameterMapKey(sequence); + + String placeHolder = leftColumn.renderingStrategy().orElse(renderingStrategy) + .getFormattedJdbcPlaceholder(leftColumn, RenderingStrategy.DEFAULT_PARAMETER_PREFIX, mapKey); + + return FragmentAndParameters.withFragment(condition.operator() + spaceBefore(placeHolder)) + .withParameter(mapKey, condition.value()) + .build(); + } + + @Override + public FragmentAndParameters visit(ColumnBasedJoinCondition condition) { + return FragmentAndParameters + .withFragment(condition.operator() + spaceBefore(applyTableAlias(condition.rightColumn()))) + .build(); + } + + private String applyTableAlias(BasicColumn column) { + return column.renderWithTableAlias(tableAliasCalculator); + } + + public static class Builder { + private RenderingStrategy renderingStrategy; + private AtomicInteger sequence; + private BindableColumn leftColumn; + private TableAliasCalculator tableAliasCalculator; + + public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) { + this.renderingStrategy = renderingStrategy; + return this; + } + + public Builder withSequence(AtomicInteger sequence) { + this.sequence = sequence; + return this; + } + + public Builder withLeftColumn(BindableColumn leftColumn) { + this.leftColumn = leftColumn; + return this; + } + + public Builder withTableAliasCalculator(TableAliasCalculator tableAliasCalculator) { + this.tableAliasCalculator = tableAliasCalculator; + return this; + } + + public JoinConditionRenderer build() { + return new JoinConditionRenderer(this); + } + } +} diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/JoinRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/JoinRenderer.java index 59efad3b7..179469090 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/JoinRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/JoinRenderer.java @@ -18,9 +18,11 @@ import static org.mybatis.dynamic.sql.util.StringUtilities.spaceBefore; import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.render.TableAliasCalculator; import org.mybatis.dynamic.sql.select.join.JoinCriterion; import org.mybatis.dynamic.sql.select.join.JoinModel; @@ -32,11 +34,15 @@ public class JoinRenderer { private final JoinModel joinModel; private final TableExpressionRenderer tableExpressionRenderer; private final TableAliasCalculator tableAliasCalculator; + private final RenderingStrategy renderingStrategy; + private final AtomicInteger sequence; private JoinRenderer(Builder builder) { joinModel = Objects.requireNonNull(builder.joinModel); tableExpressionRenderer = Objects.requireNonNull(builder.tableExpressionRenderer); tableAliasCalculator = Objects.requireNonNull(builder.tableAliasCalculator); + renderingStrategy = Objects.requireNonNull(builder.renderingStrategy); + sequence = Objects.requireNonNull(builder.sequence); } public FragmentAndParameters render() { @@ -50,26 +56,44 @@ public FragmentAndParameters render() { private FragmentAndParameters renderJoinSpecification(JoinSpecification joinSpecification) { FragmentAndParameters renderedTable = joinSpecification.table().accept(tableExpressionRenderer); + FragmentAndParameters renderedJoin = renderConditions(joinSpecification); String fragment = joinSpecification.joinType().type() + spaceBefore(renderedTable.fragment()) - + spaceBefore(renderConditions(joinSpecification)); + + spaceBefore(renderedJoin.fragment()); return FragmentAndParameters.withFragment(fragment) .withParameters(renderedTable.parameters()) + .withParameters(renderedJoin.parameters()) .build(); } - private String renderConditions(JoinSpecification joinSpecification) { - return joinSpecification.mapJoinCriteria(this::renderCriterion) - .collect(Collectors.joining(" ")); //$NON-NLS-1$ + private FragmentAndParameters renderConditions(JoinSpecification joinSpecification) { + FragmentCollector fragmentCollector = joinSpecification.mapJoinCriteria(this::renderCriterion) + .collect(FragmentCollector.collect()); + + return FragmentAndParameters + .withFragment(fragmentCollector.fragments().collect(Collectors.joining(" "))) //$NON-NLS-1$ + .withParameters(fragmentCollector.parameters()) + .build(); } - private String renderCriterion(JoinCriterion joinCriterion) { - return joinCriterion.connector() - + spaceBefore(applyTableAlias(joinCriterion.leftColumn())) - + spaceBefore(joinCriterion.operator()) - + spaceBefore(applyTableAlias(joinCriterion.rightColumn())); + private FragmentAndParameters renderCriterion(JoinCriterion joinCriterion) { + String prefix = joinCriterion.connector() + + spaceBefore(applyTableAlias(joinCriterion.leftColumn())); + + JoinConditionRenderer joinConditionRenderer = new JoinConditionRenderer.Builder() + .withRenderingStrategy(renderingStrategy) + .withSequence(sequence) + .withTableAliasCalculator(tableAliasCalculator) + .withLeftColumn(joinCriterion.leftColumn()) + .build(); + + FragmentAndParameters suffix = joinCriterion.joinCondition().accept(joinConditionRenderer); + + return FragmentAndParameters.withFragment(prefix + spaceBefore(suffix.fragment())) + .withParameters(suffix.parameters()) + .build(); } private String applyTableAlias(BasicColumn column) { @@ -84,6 +108,8 @@ public static class Builder { private JoinModel joinModel; private TableExpressionRenderer tableExpressionRenderer; private TableAliasCalculator tableAliasCalculator; + private RenderingStrategy renderingStrategy; + private AtomicInteger sequence; public Builder withJoinModel(JoinModel joinModel) { this.joinModel = joinModel; @@ -100,6 +126,16 @@ public Builder withTableAliasCalculator(TableAliasCalculator tableAliasCalculato return this; } + public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) { + this.renderingStrategy = renderingStrategy; + return this; + } + + public Builder withSequence(AtomicInteger sequence) { + this.sequence = sequence; + return this; + } + public JoinRenderer build() { return new JoinRenderer(this); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/QueryExpressionRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/QueryExpressionRenderer.java index 49bb09694..e69d576df 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/QueryExpressionRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/QueryExpressionRenderer.java @@ -171,6 +171,8 @@ private FragmentAndParameters renderJoin(JoinModel joinModel) { return JoinRenderer.withJoinModel(joinModel) .withTableExpressionRenderer(tableExpressionRenderer) .withTableAliasCalculator(tableAliasCalculator) + .withRenderingStrategy(renderingStrategy) + .withSequence(sequence) .build() .render(); } diff --git a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt index 84829f9d6..4c151e34a 100644 --- a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt +++ b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt @@ -16,6 +16,7 @@ package org.mybatis.dynamic.sql.util.kotlin import org.mybatis.dynamic.sql.BasicColumn +import org.mybatis.dynamic.sql.BindableColumn import org.mybatis.dynamic.sql.SqlBuilder import org.mybatis.dynamic.sql.select.join.JoinCondition import org.mybatis.dynamic.sql.select.join.JoinCriterion @@ -31,7 +32,7 @@ class JoinCollector { internal fun onJoinCriterion() : JoinCriterion = onJoinCriterion?: throw KInvalidSQLException(Messages.getString("ERROR.22")) //$NON-NLS-1$ - fun on(leftColumn: BasicColumn): RightColumnCollector = RightColumnCollector { + fun on(leftColumn: BindableColumn<*>): RightColumnCollector = RightColumnCollector { onJoinCriterion = JoinCriterion.Builder() .withConnector("on") //$NON-NLS-1$ .withJoinColumn(leftColumn) @@ -39,7 +40,7 @@ class JoinCollector { .build() } - fun and(leftColumn: BasicColumn): RightColumnCollector = RightColumnCollector { + fun and(leftColumn: BindableColumn<*>): RightColumnCollector = RightColumnCollector { andJoinCriteria.add( JoinCriterion.Builder() .withConnector("and") //$NON-NLS-1$ @@ -52,4 +53,6 @@ class JoinCollector { class RightColumnCollector(private val joinConditionConsumer: (JoinCondition) -> Unit) { infix fun equalTo(rightColumn: BasicColumn) = joinConditionConsumer.invoke(SqlBuilder.equalTo(rightColumn)) + + infix fun equalTo(value: T) = joinConditionConsumer.invoke(SqlBuilder.equalTo(value)) } diff --git a/src/test/java/examples/joins/JoinMapperTest.java b/src/test/java/examples/joins/JoinMapperTest.java index 1b90b06a5..de69082ed 100644 --- a/src/test/java/examples/joins/JoinMapperTest.java +++ b/src/test/java/examples/joins/JoinMapperTest.java @@ -1193,4 +1193,38 @@ void testFetchFirstOnlyAfterJoin() { assertThat(row).containsEntry("ITEM_ID", 22); } } + + @Test + void testJoinWithParameterValue() { + try (SqlSession session = sqlSessionFactory.openSession()) { + CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class); + + SelectStatementProvider selectStatement = select(orderLine.orderId, orderLine.quantity, itemMaster.itemId, itemMaster.description) + .from(itemMaster, "im") + .join(orderLine, "ol").on(orderLine.itemId, equalTo(itemMaster.itemId)) + .and(orderLine.orderId, equalTo(1)) + .build() + .render(RenderingStrategies.MYBATIS3); + + String expectedStatement = "select ol.order_id, ol.quantity, im.item_id, im.description" + + " from ItemMaster im join OrderLine ol on ol.item_id = im.item_id" + + " and ol.order_id = #{parameters.p1,jdbcType=INTEGER}"; + assertThat(selectStatement.getSelectStatement()).isEqualTo(expectedStatement); + + List> rows = mapper.selectManyMappedRows(selectStatement); + + assertThat(rows).hasSize(2); + Map row = rows.get(0); + assertThat(row).containsEntry("ORDER_ID", 1); + assertThat(row).containsEntry("QUANTITY", 1); + assertThat(row).containsEntry("DESCRIPTION", "Helmet"); + assertThat(row).containsEntry("ITEM_ID", 22); + + row = rows.get(1); + assertThat(row).containsEntry("ORDER_ID", 1); + assertThat(row).containsEntry("QUANTITY", 1); + assertThat(row).containsEntry("DESCRIPTION", "First Base Glove"); + assertThat(row).containsEntry("ITEM_ID", 33); + } + } } diff --git a/src/test/kotlin/examples/kotlin/mybatis3/joins/JoinMapperTest.kt b/src/test/kotlin/examples/kotlin/mybatis3/joins/JoinMapperTest.kt index 737917ae7..c0be0a86b 100644 --- a/src/test/kotlin/examples/kotlin/mybatis3/joins/JoinMapperTest.kt +++ b/src/test/kotlin/examples/kotlin/mybatis3/joins/JoinMapperTest.kt @@ -86,6 +86,41 @@ class JoinMapperTest { } } + @Test + fun testSingleTableJoinWithValue() { + sqlSessionFactory.openSession().use { session -> + val mapper = session.getMapper(JoinMapper::class.java) + + val selectStatement = select( + orderMaster.orderId, orderMaster.orderDate, + orderDetail.lineNumber, orderDetail.description, orderDetail.quantity + ) { + from(orderMaster, "om") + join(orderDetail, "od") { + on(orderMaster.orderId) equalTo orderDetail.orderId + and(orderMaster.orderId) equalTo 1 + } + } + + val expectedStatement = "select om.order_id, om.order_date, od.line_number, od.description, od.quantity" + + " from OrderMaster om join OrderDetail od on om.order_id = od.order_id" + + " and om.order_id = #{parameters.p1,jdbcType=INTEGER}" + + assertThat(selectStatement.selectStatement).isEqualTo(expectedStatement) + + val rows = mapper.selectMany(selectStatement) + + assertThat(rows).hasSize(1) + + with(rows[0]) { + assertThat(id).isEqualTo(1) + assertThat(details).hasSize(2) + assertThat(details?.get(0)?.lineNumber).isEqualTo(1) + assertThat(details?.get(1)?.lineNumber).isEqualTo(2) + } + } + } + @Test fun testCompoundJoin1() { // this is a nonsensical join, but it does test the "and" capability From 514c70258a82cb635ac34ac2311ae704115b56f4 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Fri, 9 Jun 2023 15:16:57 -0400 Subject: [PATCH 5/8] Update CLIRR Version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9113b386d..db2938b1b 100644 --- a/pom.xml +++ b/pom.xml @@ -57,7 +57,7 @@ checkstyle-override.xml - 1.2.0 + 1.5.0 org.mybatis.dynamic.sql From fc174c09d2012e6489e9dee3b0cc86f4a4c698fc Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Fri, 9 Jun 2023 15:18:28 -0400 Subject: [PATCH 6/8] Propagate generics properly --- .../org/mybatis/dynamic/sql/SqlBuilder.java | 12 +-- .../select/AbstractQueryExpressionDSL.java | 84 +++++++++---------- .../sql/select/QueryExpressionDSL.java | 22 ++--- .../select/join/ColumnBasedJoinCondition.java | 4 +- .../dynamic/sql/select/join/EqualTo.java | 2 +- .../sql/select/join/JoinCondition.java | 4 +- .../sql/select/join/JoinConditionVisitor.java | 6 +- .../sql/select/join/JoinCriterion.java | 28 +++---- .../sql/select/join/JoinSpecification.java | 10 +-- .../sql/select/join/TypedJoinCondition.java | 4 +- .../select/render/JoinConditionRenderer.java | 26 +++--- .../sql/select/render/JoinRenderer.java | 4 +- .../dynamic/sql/util/kotlin/JoinCollector.kt | 18 ++-- 13 files changed, 112 insertions(+), 112 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java b/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java index 477676598..3e822236d 100644 --- a/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java +++ b/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java @@ -426,24 +426,24 @@ static AndOrCriteriaGroup and(List subCriteria) { } // join support - static JoinCriterion and(BindableColumn joinColumn, JoinCondition joinCondition) { - return new JoinCriterion.Builder() + static JoinCriterion and(BindableColumn joinColumn, JoinCondition joinCondition) { + return new JoinCriterion.Builder() .withConnector("and") //$NON-NLS-1$ .withJoinColumn(joinColumn) .withJoinCondition(joinCondition) .build(); } - static JoinCriterion on(BindableColumn joinColumn, JoinCondition joinCondition) { - return new JoinCriterion.Builder() + static JoinCriterion on(BindableColumn joinColumn, JoinCondition joinCondition) { + return new JoinCriterion.Builder() .withConnector("on") //$NON-NLS-1$ .withJoinColumn(joinColumn) .withJoinCondition(joinCondition) .build(); } - static EqualTo equalTo(BasicColumn column) { - return new EqualTo(column); + static EqualTo equalTo(BasicColumn column) { + return new EqualTo<>(column); } static EqualToValue equalTo(T value) { diff --git a/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java index 6fdac9fd7..e6ec1d17b 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java @@ -52,132 +52,132 @@ public TableExpression table() { return table; } - public T join(SqlTable joinTable, JoinCriterion onJoinCriterion, - JoinCriterion... andJoinCriteria) { + public T join(SqlTable joinTable, JoinCriterion onJoinCriterion, + JoinCriterion... andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.INNER, Arrays.asList(andJoinCriteria)); return getThis(); } - public T join(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - JoinCriterion... andJoinCriteria) { + public T join(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, + JoinCriterion... andJoinCriteria) { addTableAlias(joinTable, tableAlias); return join(joinTable, onJoinCriterion, andJoinCriteria); } - public T join(SqlTable joinTable, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T join(SqlTable joinTable, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.INNER, andJoinCriteria); return getThis(); } - public T join(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T join(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addTableAlias(joinTable, tableAlias); return join(joinTable, onJoinCriterion, andJoinCriteria); } - public T join(Buildable subQuery, String tableAlias, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T join(Buildable subQuery, String tableAlias, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addJoinSpecificationBuilder(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.INNER, andJoinCriteria); return getThis(); } - public T leftJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, - JoinCriterion... andJoinCriteria) { + public T leftJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, + JoinCriterion... andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.LEFT, Arrays.asList(andJoinCriteria)); return getThis(); } - public T leftJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - JoinCriterion... andJoinCriteria) { + public T leftJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, + JoinCriterion... andJoinCriteria) { addTableAlias(joinTable, tableAlias); return leftJoin(joinTable, onJoinCriterion, andJoinCriteria); } - public T leftJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T leftJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.LEFT, andJoinCriteria); return getThis(); } - public T leftJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T leftJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addTableAlias(joinTable, tableAlias); return leftJoin(joinTable, onJoinCriterion, andJoinCriteria); } - public T leftJoin(Buildable subQuery, String tableAlias, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T leftJoin(Buildable subQuery, String tableAlias, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addJoinSpecificationBuilder(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.LEFT, andJoinCriteria); return getThis(); } - public T rightJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, - JoinCriterion... andJoinCriteria) { + public T rightJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, + JoinCriterion... andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.RIGHT, Arrays.asList(andJoinCriteria)); return getThis(); } - public T rightJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - JoinCriterion... andJoinCriteria) { + public T rightJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, + JoinCriterion... andJoinCriteria) { addTableAlias(joinTable, tableAlias); return rightJoin(joinTable, onJoinCriterion, andJoinCriteria); } - public T rightJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T rightJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.RIGHT, andJoinCriteria); return getThis(); } - public T rightJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T rightJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addTableAlias(joinTable, tableAlias); return rightJoin(joinTable, onJoinCriterion, andJoinCriteria); } - public T rightJoin(Buildable subQuery, String tableAlias, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T rightJoin(Buildable subQuery, String tableAlias, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addJoinSpecificationBuilder(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.RIGHT, andJoinCriteria); return getThis(); } - public T fullJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, - JoinCriterion... andJoinCriteria) { + public T fullJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, + JoinCriterion... andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.FULL, Arrays.asList(andJoinCriteria)); return getThis(); } - public T fullJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - JoinCriterion... andJoinCriteria) { + public T fullJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, + JoinCriterion... andJoinCriteria) { addTableAlias(joinTable, tableAlias); return fullJoin(joinTable, onJoinCriterion, andJoinCriteria); } - public T fullJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T fullJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.FULL, andJoinCriteria); return getThis(); } - public T fullJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T fullJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addTableAlias(joinTable, tableAlias); return fullJoin(joinTable, onJoinCriterion, andJoinCriteria); } - public T fullJoin(Buildable subQuery, String tableAlias, JoinCriterion onJoinCriterion, - List andJoinCriteria) { + public T fullJoin(Buildable subQuery, String tableAlias, JoinCriterion onJoinCriterion, + List> andJoinCriteria) { addJoinSpecificationBuilder(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.FULL, andJoinCriteria); return getThis(); } - private void addJoinSpecificationBuilder(TableExpression joinTable, JoinCriterion onJoinCriterion, - JoinType joinType, List andJoinCriteria) { + private void addJoinSpecificationBuilder(TableExpression joinTable, JoinCriterion onJoinCriterion, + JoinType joinType, List> andJoinCriteria) { joinSpecificationBuilders.add(new JoinSpecification.Builder() .withJoinTable(joinTable) .withJoinType(joinType) diff --git a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java index b97601000..22647f230 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java @@ -350,12 +350,12 @@ public JoinSpecificationStarter(TableExpression joinTable, JoinType joinType) { this.joinType = joinType; } - public JoinSpecificationFinisher on(BindableColumn joinColumn, JoinCondition joinCondition) { + public JoinSpecificationFinisher on(BindableColumn joinColumn, JoinCondition joinCondition) { return new JoinSpecificationFinisher(joinTable, joinColumn, joinCondition, joinType); } - public JoinSpecificationFinisher on(BindableColumn joinColumn, JoinCondition onJoinCondition, - JoinCriterion... andJoinCriteria) { + public JoinSpecificationFinisher on(BindableColumn joinColumn, JoinCondition onJoinCondition, + JoinCriterion... andJoinCriteria) { return new JoinSpecificationFinisher(joinTable, joinColumn, onJoinCondition, joinType, andJoinCriteria); } } @@ -365,9 +365,9 @@ public class JoinSpecificationFinisher implements Buildable { private final JoinSpecification.Builder joinSpecificationBuilder; - public JoinSpecificationFinisher(TableExpression table, BindableColumn joinColumn, - JoinCondition joinCondition, JoinType joinType) { - JoinCriterion joinCriterion = new JoinCriterion.Builder() + public JoinSpecificationFinisher(TableExpression table, BindableColumn joinColumn, + JoinCondition joinCondition, JoinType joinType) { + JoinCriterion joinCriterion = new JoinCriterion.Builder() .withConnector("on") //$NON-NLS-1$ .withJoinColumn(joinColumn) .withJoinCondition(joinCondition) @@ -380,9 +380,9 @@ public JoinSpecificationFinisher(TableExpression table, BindableColumn joinCo addJoinSpecificationBuilder(joinSpecificationBuilder); } - public JoinSpecificationFinisher(TableExpression table, BindableColumn joinColumn, - JoinCondition joinCondition, JoinType joinType, JoinCriterion... andJoinCriteria) { - JoinCriterion onJoinCriterion = new JoinCriterion.Builder() + public JoinSpecificationFinisher(TableExpression table, BindableColumn joinColumn, + JoinCondition joinCondition, JoinType joinType, JoinCriterion... andJoinCriteria) { + JoinCriterion onJoinCriterion = new JoinCriterion.Builder() .withConnector("on") //$NON-NLS-1$ .withJoinColumn(joinColumn) .withJoinCondition(joinCondition) @@ -413,8 +413,8 @@ public QueryExpressionWhereBuilder where() { return QueryExpressionDSL.this.where(); } - public JoinSpecificationFinisher and(BindableColumn joinColumn, JoinCondition joinCondition) { - JoinCriterion joinCriterion = new JoinCriterion.Builder() + public JoinSpecificationFinisher and(BindableColumn joinColumn, JoinCondition joinCondition) { + JoinCriterion joinCriterion = new JoinCriterion.Builder() .withConnector("and") //$NON-NLS-1$ .withJoinColumn(joinColumn) .withJoinCondition(joinCondition) diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/ColumnBasedJoinCondition.java b/src/main/java/org/mybatis/dynamic/sql/select/join/ColumnBasedJoinCondition.java index a9ca3bdd3..fda626dbb 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/join/ColumnBasedJoinCondition.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/ColumnBasedJoinCondition.java @@ -19,7 +19,7 @@ import org.mybatis.dynamic.sql.BasicColumn; -public abstract class ColumnBasedJoinCondition implements JoinCondition { +public abstract class ColumnBasedJoinCondition implements JoinCondition { private final BasicColumn rightColumn; protected ColumnBasedJoinCondition(BasicColumn rightColumn) { @@ -31,7 +31,7 @@ public BasicColumn rightColumn() { } @Override - public R accept(JoinConditionVisitor visitor) { + public R accept(JoinConditionVisitor visitor) { return visitor.visit(this); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/EqualTo.java b/src/main/java/org/mybatis/dynamic/sql/select/join/EqualTo.java index d8fc448e5..4f20ec920 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/join/EqualTo.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/EqualTo.java @@ -17,7 +17,7 @@ import org.mybatis.dynamic.sql.BasicColumn; -public class EqualTo extends ColumnBasedJoinCondition { +public class EqualTo extends ColumnBasedJoinCondition { public EqualTo(BasicColumn rightColumn) { super(rightColumn); diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCondition.java b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCondition.java index eb091c957..6965db5b9 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCondition.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCondition.java @@ -15,8 +15,8 @@ */ package org.mybatis.dynamic.sql.select.join; -public interface JoinCondition { +public interface JoinCondition { String operator(); - R accept(JoinConditionVisitor visitor); + R accept(JoinConditionVisitor visitor); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinConditionVisitor.java b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinConditionVisitor.java index cc3c0216b..7cee1a596 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinConditionVisitor.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinConditionVisitor.java @@ -15,8 +15,8 @@ */ package org.mybatis.dynamic.sql.select.join; -public interface JoinConditionVisitor { - R visit(TypedJoinCondition condition); +public interface JoinConditionVisitor { + R visit(TypedJoinCondition condition); - R visit(ColumnBasedJoinCondition condition); + R visit(ColumnBasedJoinCondition condition); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCriterion.java b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCriterion.java index 1a96b30ad..e40407b42 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCriterion.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinCriterion.java @@ -19,13 +19,13 @@ import org.mybatis.dynamic.sql.BindableColumn; -public class JoinCriterion { +public class JoinCriterion { private final String connector; - private final BindableColumn leftColumn; - private final JoinCondition joinCondition; + private final BindableColumn leftColumn; + private final JoinCondition joinCondition; - private JoinCriterion(Builder builder) { + private JoinCriterion(Builder builder) { connector = Objects.requireNonNull(builder.connector); leftColumn = Objects.requireNonNull(builder.joinColumn); joinCondition = Objects.requireNonNull(builder.joinCondition); @@ -35,36 +35,36 @@ public String connector() { return connector; } - public BindableColumn leftColumn() { + public BindableColumn leftColumn() { return leftColumn; } - public JoinCondition joinCondition() { + public JoinCondition joinCondition() { return joinCondition; } - public static class Builder { + public static class Builder { private String connector; - private BindableColumn joinColumn; - private JoinCondition joinCondition; + private BindableColumn joinColumn; + private JoinCondition joinCondition; - public Builder withConnector(String connector) { + public Builder withConnector(String connector) { this.connector = connector; return this; } - public Builder withJoinColumn(BindableColumn joinColumn) { + public Builder withJoinColumn(BindableColumn joinColumn) { this.joinColumn = joinColumn; return this; } - public Builder withJoinCondition(JoinCondition joinCondition) { + public Builder withJoinCondition(JoinCondition joinCondition) { this.joinCondition = joinCondition; return this; } - public JoinCriterion build() { - return new JoinCriterion(this); + public JoinCriterion build() { + return new JoinCriterion<>(this); } } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinSpecification.java b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinSpecification.java index c1024f441..7aba7473e 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/join/JoinSpecification.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/JoinSpecification.java @@ -28,7 +28,7 @@ public class JoinSpecification { private final TableExpression table; - private final List joinCriteria; + private final List> joinCriteria; private final JoinType joinType; private JoinSpecification(Builder builder) { @@ -45,7 +45,7 @@ public TableExpression table() { return table; } - public Stream mapJoinCriteria(Function mapper) { + public Stream mapJoinCriteria(Function, R> mapper) { return joinCriteria.stream().map(mapper); } @@ -59,7 +59,7 @@ public static Builder withJoinTable(TableExpression table) { public static class Builder { private TableExpression table; - private final List joinCriteria = new ArrayList<>(); + private final List> joinCriteria = new ArrayList<>(); private JoinType joinType; public Builder withJoinTable(TableExpression table) { @@ -67,12 +67,12 @@ public Builder withJoinTable(TableExpression table) { return this; } - public Builder withJoinCriterion(JoinCriterion joinCriterion) { + public Builder withJoinCriterion(JoinCriterion joinCriterion) { this.joinCriteria.add(joinCriterion); return this; } - public Builder withJoinCriteria(List joinCriteria) { + public Builder withJoinCriteria(List> joinCriteria) { this.joinCriteria.addAll(joinCriteria); return this; } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/join/TypedJoinCondition.java b/src/main/java/org/mybatis/dynamic/sql/select/join/TypedJoinCondition.java index 17cd4e350..0feb6c78c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/join/TypedJoinCondition.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/join/TypedJoinCondition.java @@ -17,7 +17,7 @@ import java.util.Objects; -public abstract class TypedJoinCondition implements JoinCondition { +public abstract class TypedJoinCondition implements JoinCondition { private final T value; protected TypedJoinCondition(T value) { @@ -29,7 +29,7 @@ public T value() { } @Override - public R accept(JoinConditionVisitor visitor) { + public R accept(JoinConditionVisitor visitor) { return visitor.visit(this); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/JoinConditionRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/JoinConditionRenderer.java index 550bc406b..75e8e382f 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/JoinConditionRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/JoinConditionRenderer.java @@ -29,13 +29,13 @@ import org.mybatis.dynamic.sql.select.join.TypedJoinCondition; import org.mybatis.dynamic.sql.util.FragmentAndParameters; -public class JoinConditionRenderer implements JoinConditionVisitor { +public class JoinConditionRenderer implements JoinConditionVisitor { private final RenderingStrategy renderingStrategy; private final AtomicInteger sequence; - private final BindableColumn leftColumn; + private final BindableColumn leftColumn; private final TableAliasCalculator tableAliasCalculator; - private JoinConditionRenderer(Builder builder) { + private JoinConditionRenderer(Builder builder) { renderingStrategy = Objects.requireNonNull(builder.renderingStrategy); sequence = Objects.requireNonNull(builder.sequence); leftColumn = Objects.requireNonNull(builder.leftColumn); @@ -43,7 +43,7 @@ private JoinConditionRenderer(Builder builder) { } @Override - public FragmentAndParameters visit(TypedJoinCondition condition) { + public FragmentAndParameters visit(TypedJoinCondition condition) { String mapKey = renderingStrategy.formatParameterMapKey(sequence); String placeHolder = leftColumn.renderingStrategy().orElse(renderingStrategy) @@ -55,7 +55,7 @@ public FragmentAndParameters visit(TypedJoinCondition condition) { } @Override - public FragmentAndParameters visit(ColumnBasedJoinCondition condition) { + public FragmentAndParameters visit(ColumnBasedJoinCondition condition) { return FragmentAndParameters .withFragment(condition.operator() + spaceBefore(applyTableAlias(condition.rightColumn()))) .build(); @@ -65,34 +65,34 @@ private String applyTableAlias(BasicColumn column) { return column.renderWithTableAlias(tableAliasCalculator); } - public static class Builder { + public static class Builder { private RenderingStrategy renderingStrategy; private AtomicInteger sequence; - private BindableColumn leftColumn; + private BindableColumn leftColumn; private TableAliasCalculator tableAliasCalculator; - public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) { + public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) { this.renderingStrategy = renderingStrategy; return this; } - public Builder withSequence(AtomicInteger sequence) { + public Builder withSequence(AtomicInteger sequence) { this.sequence = sequence; return this; } - public Builder withLeftColumn(BindableColumn leftColumn) { + public Builder withLeftColumn(BindableColumn leftColumn) { this.leftColumn = leftColumn; return this; } - public Builder withTableAliasCalculator(TableAliasCalculator tableAliasCalculator) { + public Builder withTableAliasCalculator(TableAliasCalculator tableAliasCalculator) { this.tableAliasCalculator = tableAliasCalculator; return this; } - public JoinConditionRenderer build() { - return new JoinConditionRenderer(this); + public JoinConditionRenderer build() { + return new JoinConditionRenderer<>(this); } } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/JoinRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/JoinRenderer.java index 179469090..8e9e7a04c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/JoinRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/JoinRenderer.java @@ -78,11 +78,11 @@ private FragmentAndParameters renderConditions(JoinSpecification joinSpecificati .build(); } - private FragmentAndParameters renderCriterion(JoinCriterion joinCriterion) { + private FragmentAndParameters renderCriterion(JoinCriterion joinCriterion) { String prefix = joinCriterion.connector() + spaceBefore(applyTableAlias(joinCriterion.leftColumn())); - JoinConditionRenderer joinConditionRenderer = new JoinConditionRenderer.Builder() + JoinConditionRenderer joinConditionRenderer = new JoinConditionRenderer.Builder() .withRenderingStrategy(renderingStrategy) .withSequence(sequence) .withTableAliasCalculator(tableAliasCalculator) diff --git a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt index 4c151e34a..e9c24d9aa 100644 --- a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt +++ b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt @@ -26,23 +26,23 @@ typealias JoinReceiver = JoinCollector.() -> Unit @MyBatisDslMarker class JoinCollector { - private var onJoinCriterion: JoinCriterion? = null - internal val andJoinCriteria = mutableListOf() + private var onJoinCriterion: JoinCriterion<*>? = null + internal val andJoinCriteria = mutableListOf>() - internal fun onJoinCriterion() : JoinCriterion = + internal fun onJoinCriterion() : JoinCriterion<*> = onJoinCriterion?: throw KInvalidSQLException(Messages.getString("ERROR.22")) //$NON-NLS-1$ - fun on(leftColumn: BindableColumn<*>): RightColumnCollector = RightColumnCollector { - onJoinCriterion = JoinCriterion.Builder() + fun on(leftColumn: BindableColumn): RightColumnCollector = RightColumnCollector { + onJoinCriterion = JoinCriterion.Builder() .withConnector("on") //$NON-NLS-1$ .withJoinColumn(leftColumn) .withJoinCondition(it) .build() } - fun and(leftColumn: BindableColumn<*>): RightColumnCollector = RightColumnCollector { + fun and(leftColumn: BindableColumn): RightColumnCollector = RightColumnCollector { andJoinCriteria.add( - JoinCriterion.Builder() + JoinCriterion.Builder() .withConnector("and") //$NON-NLS-1$ .withJoinColumn(leftColumn) .withJoinCondition(it) @@ -51,8 +51,8 @@ class JoinCollector { } } -class RightColumnCollector(private val joinConditionConsumer: (JoinCondition) -> Unit) { +class RightColumnCollector(private val joinConditionConsumer: (JoinCondition) -> Unit) { infix fun equalTo(rightColumn: BasicColumn) = joinConditionConsumer.invoke(SqlBuilder.equalTo(rightColumn)) - infix fun equalTo(value: T) = joinConditionConsumer.invoke(SqlBuilder.equalTo(value)) + infix fun equalTo(value: T) = joinConditionConsumer.invoke(SqlBuilder.equalTo(value)) } From 06bd9162f098b7c6aff9ae00924e53738a603e95 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Fri, 9 Jun 2023 15:47:15 -0400 Subject: [PATCH 7/8] Add proper types to joins --- .../org/mybatis/dynamic/sql/SqlBuilder.java | 2 +- .../dynamic/sql/util/kotlin/JoinCollector.kt | 3 +- .../java/examples/joins/JoinMapperTest.java | 34 ++++++++++++++++++ .../kotlin/mybatis3/joins/JoinMapperTest.kt | 36 +++++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java b/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java index 3e822236d..d77b0b026 100644 --- a/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java +++ b/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java @@ -442,7 +442,7 @@ static JoinCriterion on(BindableColumn joinColumn, JoinCondition jo .build(); } - static EqualTo equalTo(BasicColumn column) { + static EqualTo equalTo(BindableColumn column) { return new EqualTo<>(column); } diff --git a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt index e9c24d9aa..24473360f 100644 --- a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt +++ b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/JoinCollector.kt @@ -15,7 +15,6 @@ */ package org.mybatis.dynamic.sql.util.kotlin -import org.mybatis.dynamic.sql.BasicColumn import org.mybatis.dynamic.sql.BindableColumn import org.mybatis.dynamic.sql.SqlBuilder import org.mybatis.dynamic.sql.select.join.JoinCondition @@ -52,7 +51,7 @@ class JoinCollector { } class RightColumnCollector(private val joinConditionConsumer: (JoinCondition) -> Unit) { - infix fun equalTo(rightColumn: BasicColumn) = joinConditionConsumer.invoke(SqlBuilder.equalTo(rightColumn)) + infix fun equalTo(rightColumn: BindableColumn) = joinConditionConsumer.invoke(SqlBuilder.equalTo(rightColumn)) infix fun equalTo(value: T) = joinConditionConsumer.invoke(SqlBuilder.equalTo(value)) } diff --git a/src/test/java/examples/joins/JoinMapperTest.java b/src/test/java/examples/joins/JoinMapperTest.java index de69082ed..9417e467f 100644 --- a/src/test/java/examples/joins/JoinMapperTest.java +++ b/src/test/java/examples/joins/JoinMapperTest.java @@ -1227,4 +1227,38 @@ void testJoinWithParameterValue() { assertThat(row).containsEntry("ITEM_ID", 33); } } + + @Test + void testJoinWithConstant() { + try (SqlSession session = sqlSessionFactory.openSession()) { + CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class); + + SelectStatementProvider selectStatement = select(orderLine.orderId, orderLine.quantity, itemMaster.itemId, itemMaster.description) + .from(itemMaster, "im") + .join(orderLine, "ol").on(orderLine.itemId, equalTo(itemMaster.itemId)) + .and(orderLine.orderId, equalTo(constant("1"))) + .build() + .render(RenderingStrategies.MYBATIS3); + + String expectedStatement = "select ol.order_id, ol.quantity, im.item_id, im.description" + + " from ItemMaster im join OrderLine ol on ol.item_id = im.item_id" + + " and ol.order_id = 1"; + assertThat(selectStatement.getSelectStatement()).isEqualTo(expectedStatement); + + List> rows = mapper.selectManyMappedRows(selectStatement); + + assertThat(rows).hasSize(2); + Map row = rows.get(0); + assertThat(row).containsEntry("ORDER_ID", 1); + assertThat(row).containsEntry("QUANTITY", 1); + assertThat(row).containsEntry("DESCRIPTION", "Helmet"); + assertThat(row).containsEntry("ITEM_ID", 22); + + row = rows.get(1); + assertThat(row).containsEntry("ORDER_ID", 1); + assertThat(row).containsEntry("QUANTITY", 1); + assertThat(row).containsEntry("DESCRIPTION", "First Base Glove"); + assertThat(row).containsEntry("ITEM_ID", 33); + } + } } diff --git a/src/test/kotlin/examples/kotlin/mybatis3/joins/JoinMapperTest.kt b/src/test/kotlin/examples/kotlin/mybatis3/joins/JoinMapperTest.kt index c0be0a86b..11ce7be25 100644 --- a/src/test/kotlin/examples/kotlin/mybatis3/joins/JoinMapperTest.kt +++ b/src/test/kotlin/examples/kotlin/mybatis3/joins/JoinMapperTest.kt @@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import org.mybatis.dynamic.sql.util.Messages import org.mybatis.dynamic.sql.util.kotlin.KInvalidSQLException +import org.mybatis.dynamic.sql.util.kotlin.elements.constant import org.mybatis.dynamic.sql.util.kotlin.elements.invoke import org.mybatis.dynamic.sql.util.kotlin.elements.max import org.mybatis.dynamic.sql.util.kotlin.mybatis3.select @@ -121,6 +122,41 @@ class JoinMapperTest { } } + @Test + fun testSingleTableJoinWithConstant() { + sqlSessionFactory.openSession().use { session -> + val mapper = session.getMapper(JoinMapper::class.java) + + val selectStatement = select( + orderMaster.orderId, orderMaster.orderDate, + orderDetail.lineNumber, orderDetail.description, orderDetail.quantity + ) { + from(orderMaster, "om") + join(orderDetail, "od") { + on(orderMaster.orderId) equalTo orderDetail.orderId + and(orderMaster.orderId) equalTo constant("1") + } + } + + val expectedStatement = "select om.order_id, om.order_date, od.line_number, od.description, od.quantity" + + " from OrderMaster om join OrderDetail od on om.order_id = od.order_id" + + " and om.order_id = 1" + + assertThat(selectStatement.selectStatement).isEqualTo(expectedStatement) + + val rows = mapper.selectMany(selectStatement) + + assertThat(rows).hasSize(1) + + with(rows[0]) { + assertThat(id).isEqualTo(1) + assertThat(details).hasSize(2) + assertThat(details?.get(0)?.lineNumber).isEqualTo(1) + assertThat(details?.get(1)?.lineNumber).isEqualTo(2) + } + } + } + @Test fun testCompoundJoin1() { // this is a nonsensical join, but it does test the "and" capability From c46f5f5a9e8d3b14afa619f392f54000e33bf6d3 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Fri, 9 Jun 2023 16:49:31 -0400 Subject: [PATCH 8/8] Update changelog --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5affe6ae2..7c4a95341 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,34 @@ This log will detail notable changes to MyBatis Dynamic SQL. Full details are available on the GitHub milestone pages. +## Release 1.5.1 - Unreleased + +This is a minor release with a few small enhancements. + +GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/milestone/13](https://github.com/mybatis/mybatis-dynamic-sql/milestone/13) + +### Parameter Values in Joins + +We've added the ability to specify typed values in equi-joins. This allows you to avoid the use of constants, and it is +type safe. For example: + +```java +SelectStatementProvider selectStatement = select(orderLine.orderId, orderLine.quantity, itemMaster.itemId, itemMaster.description) + .from(itemMaster, "im") + .join(orderLine, "ol").on(orderLine.itemId, equalTo(itemMaster.itemId)) + .and(orderLine.orderId, equalTo(1)) + .build() + .render(RenderingStrategies.MYBATIS3); +``` + +Note the phrase `and(orderLine.orderId, equalTo(1))` which will be rendered with a bound SQL parameter. Currently, this +capability is limited to equality only. If you have a use for other functions (not equal, less then, greater than, etc.) +please let us know. + +In order to add this capability, we've modified the join DSL to add type information to the join columns. This should +be source code compatible with most uses. There could be an issue if you are joining tables with columns of different +types - which is a rare usage. Please let us know if this causes an undo hardship. + ## Release 1.5.0 - April 21, 2023 GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/milestone/12?closed=1](https://github.com/mybatis/mybatis-dynamic-sql/milestone/12?closed=1)