Skip to content

Commit d8574a8

Browse files
committed
Support for in line queries for tables.
`InlineQuery` can be used whereever a `Table` was used up to now. ``` Table one = ...; Select select = Select.builder() .select(one.column("id"), employee.column("name")) .from(one) .build(); InlineQuery inline = InlineQuery.create(select, "inline"); Select select = Select.builder() .select(inline.column("id"), inline.column("name")) .from(inline) .build(); ``` Join and From renderer now use the same FromTableVisitor. Also the SelectListVisitor reuses now the ExpressionVisitor. Fixes #1003
1 parent bbe22e0 commit d8574a8

30 files changed

+1200
-295
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/QueryMapper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ Expression getMappedObject(Expression expression, @Nullable RelationalPersistent
121121

122122
Column column = (Column) expression;
123123
Field field = createPropertyField(entity, column.getName());
124-
Table table = column.getTable();
124+
TableLike table = column.getTable();
125125

126126
Assert.state(table != null, String.format("The column %s must have a table set.", column));
127127

spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/PostgresDialect.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
import java.util.function.Consumer;
2424

2525
import org.springframework.data.relational.core.sql.IdentifierProcessing;
26-
import org.springframework.data.relational.core.sql.LockOptions;
27-
import org.springframework.data.relational.core.sql.SqlIdentifier;
28-
import org.springframework.data.relational.core.sql.Table;
2926
import org.springframework.data.relational.core.sql.IdentifierProcessing.LetterCasing;
3027
import org.springframework.data.relational.core.sql.IdentifierProcessing.Quoting;
28+
import org.springframework.data.relational.core.sql.LockOptions;
29+
import org.springframework.data.relational.core.sql.SqlIdentifier;
30+
import org.springframework.data.relational.core.sql.TableLike;
3131
import org.springframework.util.Assert;
3232
import org.springframework.util.ClassUtils;
3333

@@ -139,7 +139,7 @@ static class PostgresLockClause implements LockClause {
139139
@Override
140140
public String getLock(LockOptions lockOptions) {
141141

142-
List<Table> tables = lockOptions.getFrom().getTables();
142+
List<TableLike> tables = lockOptions.getFrom().getTables();
143143
if (tables.isEmpty()) {
144144
return "";
145145
}

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/AsteriskFromTable.java

+4-10
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,17 @@
1818
/**
1919
* {@link Segment} to select all columns from a {@link Table}.
2020
* <p/>
21-
* * Renders to: {@code
22-
*
23-
<table>
24-
* .*} as in {@code SELECT
25-
*
26-
<table>
27-
* .* FROM …}.
21+
* Renders to: {@code <table>.*} as in {@code SELECT <table>.* FROM …}.
2822
*
2923
* @author Mark Paluch
3024
* @since 1.1
3125
* @see Table#asterisk()
3226
*/
3327
public class AsteriskFromTable extends AbstractSegment implements Expression {
3428

35-
private final Table table;
29+
private final TableLike table;
3630

37-
AsteriskFromTable(Table table) {
31+
AsteriskFromTable(TableLike table) {
3832
super(table);
3933
this.table = table;
4034
}
@@ -46,7 +40,7 @@ public static AsteriskFromTable create(Table table) {
4640
/**
4741
* @return the associated {@link Table}.
4842
*/
49-
public Table getTable() {
43+
public TableLike getTable() {
5044
return table;
5145
}
5246

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Column.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
public class Column extends AbstractSegment implements Expression, Named {
3131

3232
private final SqlIdentifier name;
33-
private final Table table;
33+
private final TableLike table;
3434

35-
Column(String name, Table table) {
35+
Column(String name, TableLike table) {
3636

3737
super(table);
3838
Assert.notNull(name, "Name must not be null");
@@ -41,7 +41,7 @@ public class Column extends AbstractSegment implements Expression, Named {
4141
this.table = table;
4242
}
4343

44-
Column(SqlIdentifier name, Table table) {
44+
Column(SqlIdentifier name, TableLike table) {
4545

4646
super(table);
4747
Assert.notNull(name, "Name must not be null");
@@ -57,7 +57,7 @@ public class Column extends AbstractSegment implements Expression, Named {
5757
* @param table the table, must not be {@literal null}.
5858
* @return the new {@link Column}.
5959
*/
60-
public static Column create(String name, Table table) {
60+
public static Column create(String name, TableLike table) {
6161

6262
Assert.hasText(name, "Name must not be null or empty");
6363
Assert.notNull(table, "Table must not be null");
@@ -341,7 +341,7 @@ public SqlIdentifier getReferenceName() {
341341
* {@link Table}.
342342
*/
343343
@Nullable
344-
public Table getTable() {
344+
public TableLike getTable() {
345345
return table;
346346
}
347347

@@ -370,12 +370,12 @@ static class AliasedColumn extends Column implements Aliased {
370370

371371
private final SqlIdentifier alias;
372372

373-
private AliasedColumn(String name, Table table, String alias) {
373+
private AliasedColumn(String name, TableLike table, String alias) {
374374
super(name, table);
375375
this.alias = SqlIdentifier.unquoted(alias);
376376
}
377377

378-
private AliasedColumn(SqlIdentifier name, Table table, SqlIdentifier alias) {
378+
private AliasedColumn(SqlIdentifier name, TableLike table, SqlIdentifier alias) {
379379
super(name, table);
380380
this.alias = alias;
381381
}

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSelect.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class DefaultSelect implements Select {
4242
private final List<OrderByField> orderBy;
4343
private final @Nullable LockMode lockMode;
4444

45-
DefaultSelect(boolean distinct, List<Expression> selectList, List<Table> from, long limit, long offset,
45+
DefaultSelect(boolean distinct, List<Expression> selectList, List<TableLike> from, long limit, long offset,
4646
List<Join> joins, @Nullable Condition where, List<OrderByField> orderBy, @Nullable LockMode lockMode) {
4747

4848
this.distinct = distinct;

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSelectBuilder.java

+11-11
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class DefaultSelectBuilder implements SelectBuilder, SelectAndFrom, SelectFromAn
3838

3939
private boolean distinct = false;
4040
private List<Expression> selectList = new ArrayList<>();
41-
private List<Table> from = new ArrayList<>();
41+
private List<TableLike> from = new ArrayList<>();
4242
private long limit = -1;
4343
private long offset = -1;
4444
private List<Join> joins = new ArrayList<>();
@@ -107,7 +107,7 @@ public SelectFromAndJoin from(String table) {
107107
* @see org.springframework.data.relational.core.sql.SelectBuilder.SelectAndFrom#from(org.springframework.data.relational.core.sql.Table)
108108
*/
109109
@Override
110-
public SelectFromAndJoin from(Table table) {
110+
public SelectFromAndJoin from(TableLike table) {
111111
from.add(table);
112112
return this;
113113
}
@@ -117,7 +117,7 @@ public SelectFromAndJoin from(Table table) {
117117
* @see org.springframework.data.relational.core.sql.SelectBuilder.SelectAndFrom#from(org.springframework.data.relational.core.sql.Table[])
118118
*/
119119
@Override
120-
public SelectFromAndJoin from(Table... tables) {
120+
public SelectFromAndJoin from(TableLike... tables) {
121121
from.addAll(Arrays.asList(tables));
122122
return this;
123123
}
@@ -127,7 +127,7 @@ public SelectFromAndJoin from(Table... tables) {
127127
* @see org.springframework.data.relational.core.sql.SelectBuilder.SelectAndFrom#from(java.util.Collection)
128128
*/
129129
@Override
130-
public SelectFromAndJoin from(Collection<? extends Table> tables) {
130+
public SelectFromAndJoin from(Collection<? extends TableLike> tables) {
131131
from.addAll(tables);
132132
return this;
133133
}
@@ -248,7 +248,7 @@ public SelectOn join(String table) {
248248
* @see org.springframework.data.relational.core.sql.SelectBuilder.SelectJoin#join(org.springframework.data.relational.core.sql.Table)
249249
*/
250250
@Override
251-
public SelectOn join(Table table) {
251+
public SelectOn join(TableLike table) {
252252
return new JoinBuilder(table, this);
253253
}
254254

@@ -257,7 +257,7 @@ public SelectOn join(Table table) {
257257
* @see org.springframework.data.relational.core.sql.SelectBuilder.SelectJoin#join(org.springframework.data.relational.core.sql.Table)
258258
*/
259259
@Override
260-
public SelectOn leftOuterJoin(Table table) {
260+
public SelectOn leftOuterJoin(TableLike table) {
261261
return new JoinBuilder(table, this, JoinType.LEFT_OUTER_JOIN);
262262
}
263263

@@ -295,21 +295,21 @@ public Select build() {
295295
*/
296296
static class JoinBuilder implements SelectOn, SelectOnConditionComparison, SelectFromAndJoinCondition {
297297

298-
private final Table table;
298+
private final TableLike table;
299299
private final DefaultSelectBuilder selectBuilder;
300300
private final JoinType joinType;
301301
private @Nullable Expression from;
302302
private @Nullable Expression to;
303303
private @Nullable Condition condition;
304304

305-
JoinBuilder(Table table, DefaultSelectBuilder selectBuilder, JoinType joinType) {
305+
JoinBuilder(TableLike table, DefaultSelectBuilder selectBuilder, JoinType joinType) {
306306

307307
this.table = table;
308308
this.selectBuilder = selectBuilder;
309309
this.joinType = joinType;
310310
}
311311

312-
JoinBuilder(Table table, DefaultSelectBuilder selectBuilder) {
312+
JoinBuilder(TableLike table, DefaultSelectBuilder selectBuilder) {
313313
this(table, selectBuilder, JoinType.JOIN);
314314
}
315315

@@ -417,7 +417,7 @@ public SelectOn join(String table) {
417417
* @see org.springframework.data.relational.core.sql.SelectBuilder.SelectJoin#join(org.springframework.data.relational.core.sql.Table)
418418
*/
419419
@Override
420-
public SelectOn join(Table table) {
420+
public SelectOn join(TableLike table) {
421421
selectBuilder.join(finishJoin());
422422
return selectBuilder.join(table);
423423
}
@@ -427,7 +427,7 @@ public SelectOn join(Table table) {
427427
* @see org.springframework.data.relational.core.sql.SelectBuilder.SelectJoin#leftOuterJoin(org.springframework.data.relational.core.sql.Table)
428428
*/
429429
@Override
430-
public SelectOn leftOuterJoin(Table table) {
430+
public SelectOn leftOuterJoin(TableLike table) {
431431
selectBuilder.join(finishJoin());
432432
return selectBuilder.leftOuterJoin(table);
433433
}

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/From.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,20 @@
2929
*/
3030
public class From extends AbstractSegment {
3131

32-
private final List<Table> tables;
32+
private final List<TableLike> tables;
3333

34-
From(Table... tables) {
34+
From(TableLike... tables) {
3535
this(Arrays.asList(tables));
3636
}
3737

38-
From(List<Table> tables) {
38+
From(List<TableLike> tables) {
3939

40-
super(tables.toArray(new Table[] {}));
40+
super(tables.toArray(new TableLike[] {}));
4141

4242
this.tables = Collections.unmodifiableList(tables);
4343
}
4444

45-
public List<Table> getTables() {
45+
public List<TableLike> getTables() {
4646
return this.tables;
4747
}
4848

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2019-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.relational.core.sql;
17+
18+
import org.springframework.util.Assert;
19+
20+
/**
21+
* Represents a inline query within a SQL statement. Typically used in {@code FROM} or {@code JOIN} clauses.
22+
* <p/>
23+
* Renders to: {@code (<SELECT>) AS <ALIAS>} in a from or join clause, and to {@code <ALIAS>} when used in an
24+
* expression.
25+
* <p/>
26+
* Note that this does not implement {@link Aliased} because the Alias is not optional but required and therefore more
27+
* like a name although the SQL term is "alias".
28+
*
29+
* @author Jens Schauder
30+
* @since 2.3
31+
*/
32+
public class InlineQuery extends AbstractSegment implements TableLike {
33+
34+
private final Select select;
35+
private final SqlIdentifier alias;
36+
37+
InlineQuery(Select select, SqlIdentifier alias) {
38+
39+
super(select);
40+
41+
this.select = select;
42+
this.alias = alias;
43+
}
44+
45+
/**
46+
* Creates a new {@link InlineQuery} using an {@code alias}.
47+
*
48+
* @param select must not be {@literal null}.
49+
* @param alias must not be {@literal null} or empty.
50+
* @return the new {@link InlineQuery} using the {@code alias}.
51+
*/
52+
public static InlineQuery create(Select select, SqlIdentifier alias) {
53+
54+
Assert.notNull(select, "Select must not be null!");
55+
Assert.notNull(alias, "Alias must not be null or empty!");
56+
57+
return new InlineQuery(select, alias);
58+
}
59+
60+
/**
61+
* Creates a new {@link InlineQuery} using an {@code alias}.
62+
*
63+
* @param select must not be {@literal null} or empty.
64+
* @param alias must not be {@literal null} or empty.
65+
* @return the new {@link InlineQuery} using the {@code alias}.
66+
*/
67+
public static InlineQuery create(Select select, String alias) {
68+
return create(select, SqlIdentifier.unquoted(alias));
69+
}
70+
71+
/**
72+
* @return the table name.
73+
*/
74+
/*
75+
* (non-Javadoc)
76+
* @see org.springframework.data.relational.core.sql.Named#getName()
77+
*/
78+
public SqlIdentifier getName() {
79+
return alias;
80+
}
81+
82+
/**
83+
* @return the table name as it is used in references. This can be the actual {@link #getName() name} or an
84+
* {@link Aliased#getAlias() alias}.
85+
*/
86+
public SqlIdentifier getReferenceName() {
87+
return alias;
88+
}
89+
90+
/*
91+
* (non-Javadoc)
92+
* @see java.lang.Object#toString()
93+
*/
94+
@Override
95+
public String toString() {
96+
return "(" + select + ") AS " + alias;
97+
}
98+
99+
}

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Join.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
public class Join extends AbstractSegment {
3030

3131
private final JoinType type;
32-
private final Table joinTable;
32+
private final TableLike joinTable;
3333
private final Condition on;
3434

35-
Join(JoinType type, Table joinTable, Condition on) {
35+
Join(JoinType type, TableLike joinTable, Condition on) {
3636

3737
super(joinTable, on);
3838

@@ -51,7 +51,7 @@ public JoinType getType() {
5151
/**
5252
* @return the joined {@link Table}.
5353
*/
54-
public Table getJoinTable() {
54+
public TableLike getJoinTable() {
5555
return joinTable;
5656
}
5757

0 commit comments

Comments
 (0)