Skip to content

Commit ce51537

Browse files
committed
Documentation for new sub-query support
1 parent ff48b5a commit ce51537

File tree

4 files changed

+255
-2
lines changed

4 files changed

+255
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ Kotlin DSL.
3535

3636
- Added a new sort specification that is useful in selects with joins ([#269](https://github.com/mybatis/mybatis-dynamic-sql/pull/269))
3737
- Added the capability to generate a camel cased alias for a column ([#272](https://github.com/mybatis/mybatis-dynamic-sql/issues/272))
38+
- Added sub-query support for "from" clauses in a select statement
39+
- Added Kotlin DSL updates to support sub-queries in select statements, where clauses, and insert statements
3840

3941
## Release 1.2.1 - September 29, 2020
4042

src/site/markdown/docs/subQueries.md

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
# SubQuery Support
2+
The library currently supports subQueries in the following areas:
3+
4+
1. In certain where conditions
5+
1. In certain insert statements
6+
1. In the "from" clause of a select statement
7+
8+
## SubQueries in Where Conditions
9+
The library support subQueries in the following where conditions:
10+
11+
- isEqualTo
12+
- isNotEqualTo
13+
- isIn
14+
- isNotIn
15+
- isGreaterThan
16+
- isGreaterThanOrEqualTo
17+
- isLessThan
18+
- isLessThanOrEqualTo
19+
20+
A Java example is as follows:
21+
22+
```java
23+
SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight)
24+
.from(animalData)
25+
.where(brainWeight, isEqualTo(
26+
select(min(brainWeight))
27+
.from(animalData)
28+
)
29+
)
30+
.orderBy(animalName)
31+
.build()
32+
.render(RenderingStrategies.MYBATIS3);
33+
```
34+
35+
### Kotlin Support
36+
The library includes Kotlin versions of the where conditions that allow use of the Kotlin subQuery builder. The Kotlin
37+
where conditions are in the `org.mybatis.dynamic.sql.util.kotlin` package. An example is as follows:
38+
39+
```kotlin
40+
val selectStatement = select(id, firstName, lastName, birthDate, employed, occupation, addressId) {
41+
from(Person)
42+
where(id, isEqualTo {
43+
select(max(id)) {
44+
from(Person)
45+
}
46+
})
47+
}
48+
```
49+
50+
## SubQueries in Insert Statements
51+
The library supports an INSERT statement that retrieves values from a SELECT statement. For example:
52+
53+
```java
54+
InsertSelectStatementProvider insertSelectStatement = insertInto(animalDataCopy)
55+
.withColumnList(id, animalName, bodyWeight, brainWeight)
56+
.withSelectStatement(
57+
select(id, animalName, bodyWeight, brainWeight)
58+
.from(animalData)
59+
.where(id, isLessThan(22))
60+
)
61+
.build()
62+
.render(RenderingStrategies.MYBATIS3);
63+
```
64+
65+
### Kotlin Support
66+
67+
The library includes a Kotlin builder for subQueries in insert statements that integrates with the select DSL. You
68+
can write inserts like this:
69+
70+
```kotlin
71+
val insertStatement = insertSelect(Person) {
72+
columns(id, firstName, lastName, birthDate, employed, occupation, addressId)
73+
select(add(id, constant<Int>("100")), firstName, lastName, birthDate, employed, occupation, addressId) {
74+
from(Person)
75+
orderBy(id)
76+
}
77+
}
78+
```
79+
80+
## SubQueries in a From Clause
81+
82+
The library supports subQueries in from clauses and the syntax is a natural extension of the
83+
select DSL. An example is as follows:
84+
85+
```java
86+
DerivedColumn<Integer> rowNum = DerivedColumn.of("rownum()");
87+
88+
SelectStatementProvider selectStatement =
89+
select(animalName, rowNum)
90+
.from(
91+
select(id, animalName)
92+
.from(animalData)
93+
.where(id, isLessThan(22))
94+
.orderBy(animalName.descending())
95+
)
96+
.where(rowNum, isLessThan(5))
97+
.and(animalName, isLike("%a%"))
98+
.build()
99+
.render(RenderingStrategies.MYBATIS3);
100+
```
101+
102+
Notice the use of a `DerivedColumn` to easily specify a function like `rownum()` that can be
103+
used both in the select list and in a where condition.
104+
105+
### Table Qualifiers with SubQueries
106+
107+
The library attempts to automatically calculate table qualifiers. If a table qualifier is specified,
108+
the library will automatically render the table qualifier on all columns associated with the
109+
table. For example with the following query:
110+
111+
```java
112+
SelectStatementProvider selectStatement =
113+
select(id, animalName)
114+
.from(animalData, "ad")
115+
.build()
116+
.render(RenderingStrategies.MYBATIS3);
117+
```
118+
119+
The library will render SQL as:
120+
121+
```sql
122+
select ad.id, ad.animal_name
123+
from AnimalData ad
124+
```
125+
126+
Notice that the table qualifier `ad` is automatically applied to columns in the select list.
127+
128+
In the case of join queries the table qualifier specified, or if not specified the table name
129+
itself, will be used as the table qualifier.
130+
131+
With subQueries, it is important to understand the limits of automatic table qualifiers. The rules are
132+
as follows:
133+
134+
1. The scope of automatic table qualifiers is limited to a single select statement. For subQueries, the outer
135+
query has a different scope than the subQuery.
136+
1. A qualifier can be applied to a subQuery as a whole, but that qualifier is not automatically applied to
137+
any column
138+
139+
As an example, consider the following query:
140+
141+
```java
142+
DerivedColumn<Integer> rowNum = DerivedColumn.of("rownum()");
143+
144+
SelectStatementProvider selectStatement =
145+
select(animalName, rowNum)
146+
.from(
147+
select(id, animalName)
148+
.from(animalData, "a")
149+
.where(id, isLessThan(22))
150+
.orderBy(animalName.descending()),
151+
"b"
152+
)
153+
.where(rowNum, isLessThan(5))
154+
.and(animalName, isLike("%a%"))
155+
.build()
156+
.render(RenderingStrategies.MYBATIS3);
157+
```
158+
159+
The rendered SQL will be as follows:
160+
161+
```sql
162+
select animal_name, rownum()
163+
from (select a.id, a.animal_name
164+
from AnimalDate a
165+
where id < #{parameters.p1}
166+
order by animal_name desc) b
167+
where rownum() < #{parameters.p2}
168+
and animal_name like #{parameters.p3}
169+
```
170+
171+
Notice that the qualifier `a` is automatically applied to columns in the subQuery and that the
172+
qualifier `b` is not applied anywhere.
173+
174+
If your query requires the subQuery qualifier to be applied to columns in the outer select list,
175+
you can manually apply the qualifier to columns as follows:
176+
177+
```java
178+
DerivedColumn<Integer> rowNum = DerivedColumn.of("rownum()");
179+
180+
SelectStatementProvider selectStatement =
181+
select(animalName.qualifiedWith("b"), rowNum)
182+
.from(
183+
select(id, animalName)
184+
.from(animalData, "a")
185+
.where(id, isLessThan(22))
186+
.orderBy(animalName.descending()),
187+
"b"
188+
)
189+
.where(rowNum, isLessThan(5))
190+
.and(animalName.qualifiedWith("b"), isLike("%a%"))
191+
.build()
192+
.render(RenderingStrategies.MYBATIS3);
193+
```
194+
195+
In this case, we have manually applied the qualifier `b` to columns in the outer query. The
196+
rendered SQL looks like this:
197+
198+
```sql
199+
select b.animal_name, rownum()
200+
from (select a.id, a.animal_name
201+
from AnimalDate a
202+
where id < #{parameters.p1}
203+
order by animal_name desc) b
204+
where rownum() < #{parameters.p2}
205+
and b.animal_name like #{parameters.p3}
206+
```
207+
208+
### Kotlin Support
209+
210+
The library includes a Kotlin builder for subQueries that integrates with the select DSL. You
211+
can write queries like this:
212+
213+
```kotlin
214+
val selectStatement =
215+
select(firstName, rowNum) {
216+
from {
217+
select(id, firstName) {
218+
from(Person)
219+
where(id, isLessThan(22))
220+
orderBy(firstName.descending())
221+
}
222+
}
223+
where(rowNum, isLessThan(5))
224+
and(firstName, isLike("%a%"))
225+
}
226+
```
227+
228+
The same rules about table qualifiers apply as stated above. In Kotlin, a subQuery qualifier
229+
can be added with the overloaded "+" operator as shown below:
230+
231+
```kotlin
232+
val selectStatement =
233+
select(firstName, rowNum) {
234+
from {
235+
select(id, firstName) {
236+
from(Person, "a")
237+
where(id, isLessThan(22))
238+
orderBy(firstName.descending())
239+
}
240+
+ "b"
241+
}
242+
where(rowNum, isLessThan(5))
243+
and(firstName, isLike("%a%"))
244+
}
245+
```
246+
247+
In this case the `a` qualifier is used in the context of the inner select statement and
248+
the `b` qualifier is applied to the subQuery as a whole.

src/site/markdown/index.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# MyBatis Dynamic SQL
2-
MyBatis Dynamic SQL is an SQL templating library that makes it easier to execute dynamic SQL with MyBatis. It generates SQL that is formatted in such a way that it can be directly executed by MyBatis.
2+
MyBatis Dynamic SQL is an SQL DSL (domain specific language). It allows developers to write SQL in Java or Kotlin using the natural feel of native SQL. It also
3+
includes many functions for creating very dynamic SQL statements based on current runtime parameter values.
34

4-
The library also supports generating SQL that is formatted for use by Spring JDBC Templates.
5+
The DSL will render standard SQL DELETE, INSERT, SELECT, and UPDATE statements - and associated
6+
parameters - that can be used directly by SQL execution engines like MyBatis or Spring JDBC template.
57

68
Please read the user's guide for detailed instructions on use. The user's guide is accessible through menu links to the left.
79

src/site/site.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<item href="docs/delete.html" name="DELETE Statements" />
4848
<item href="docs/insert.html" name="INSERT Statements" />
4949
<item href="docs/update.html" name="UPDATE Statements" />
50+
<item href="docs/subQueries.html" name="SubQuery Support" />
5051
<item href="docs/functions.html" name="Database Functions" />
5152
<item href="docs/mybatis3.html" name="MyBatis3 Support" />
5253
<item href="docs/kotlinMyBatis3.html" name="Kotlin Support for MyBatis3" />

0 commit comments

Comments
 (0)