• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

torand / FasterSQL / 15346133148

30 May 2025 11:50AM UTC coverage: 70.397% (+0.1%) from 70.298%
15346133148

push

github

torand
chore: test javadoc publish

235 of 420 branches covered (55.95%)

Branch coverage included in aggregate %.

1237 of 1671 relevant lines covered (74.03%)

3.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.89
/src/main/java/io/github/torand/fastersql/join/Join.java
1
/*
2
 * Copyright (c) 2024-2025 Tore Eide Andersen
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
 *      http://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 io.github.torand.fastersql.join;
17

18
import io.github.torand.fastersql.alias.ColumnAlias;
19
import io.github.torand.fastersql.model.Column;
20
import io.github.torand.fastersql.model.Table;
21
import io.github.torand.fastersql.sql.Context;
22
import io.github.torand.fastersql.sql.Sql;
23

24
import java.util.List;
25
import java.util.stream.Stream;
26

27
import static io.github.torand.fastersql.util.collection.CollectionHelper.asList;
28
import static io.github.torand.fastersql.util.collection.CollectionHelper.concat;
29
import static io.github.torand.fastersql.util.collection.CollectionHelper.headOf;
30
import static io.github.torand.fastersql.util.collection.CollectionHelper.streamSafely;
31
import static io.github.torand.fastersql.util.contract.Requires.require;
32
import static java.util.Objects.requireNonNull;
33

34
/**
35
 * Implements a JOIN clause.
36
 */
37
public class Join implements Sql {
38

39
    private final List<Column> lefts;
40
    private final List<Column> rights;
41
    private final JoinMode mode;
42

43
    /**
44
     * Creates a join clause.
45
     * @param left the left side of the join.
46
     * @param right the right side of the join.
47
     */
48
    public Join(Column left, Column right) {
2✔
49
        this.lefts = asList(requireNonNull(left, "No left column specified"));
12✔
50
        this.rights = asList(requireNonNull(right, "No right column specified"));
12✔
51
        this.mode = JoinMode.INNER;
3✔
52
    }
1✔
53

54
    private Join(List<Column> lefts, List<Column> rights, JoinMode mode) {
×
55
        this.lefts = asList(lefts);
×
56
        this.rights = asList(rights);
×
57
        this.mode = mode;
×
58
    }
×
59

60
    /**
61
     * Specifies that this is a LEFT OUTER JOIN clause.
62
     * @return the modified JOIN clause.
63
     */
64
    public Join leftOuter() {
65
        return new Join(lefts, rights, JoinMode.LEFT_OUTER);
×
66
    }
67

68
    /**
69
     * Specifies that this is a RIGHT OUTER JOIN clause.
70
     * @return the modified JOIN clause.
71
     */
72
    public Join rightOuter() {
73
        return new Join(lefts, rights, JoinMode.RIGHT_OUTER);
×
74
    }
75

76
    /**
77
     * Creates a nested JOIN clause by combining this JOIN clause with the specified JOIN clause.
78
     * @param next the JOIN clause to combine with.
79
     * @return the nested JOIN clause.
80
     */
81
    public Join and(Join next) {
82
        require(() -> headOf(this.lefts).table().equals(headOf(next.lefts).table()), "Left side of nested joins must belong to the same table");
×
83
        require(() -> headOf(this.rights).table().equals(headOf(next.rights).table()), "Right side of nested joins must belong to the same table");
×
84

85
        List<Column> concatenatedLefts = concat(this.lefts, next.lefts);
×
86
        List<Column> concatenatedRights = concat(this.rights, next.rights);
×
87

88
        return new Join(concatenatedLefts, concatenatedRights, mode);
×
89
    }
90

91
    /**
92
     * Gets the table joined with.
93
     * @return the table joined with.
94
     */
95
    public Table<?> joined() {
96
        return headOf(rights).table();
6✔
97
    }
98

99
    // Sql
100

101
    @Override
102
    public String sql(Context context) {
103
        Table<?> rightTable = headOf(this.rights).table();
6✔
104
        StringBuilder sql = new StringBuilder()
6✔
105
            .append(mode.sql)
2✔
106
            .append(" ")
3✔
107
            .append(rightTable.sql(context))
3✔
108
            .append(" on ");
2✔
109

110
        for (int i = 0; i < this.lefts.size(); i++) {
9✔
111
            if (i > 0) {
2!
112
                sql.append(" and ");
×
113
            }
114
            sql.append(this.lefts.get(i).sql(context))
10✔
115
                .append(" = ")
4✔
116
                .append(this.rights.get(i).sql(context));
6✔
117
        }
118

119
        return sql.toString();
3✔
120
    }
121

122
    @Override
123
    public Stream<Object> params(Context context) {
124
        return Stream.empty();
×
125
    }
126

127
    @Override
128
    public Stream<Column> columnRefs() {
129
        return Stream.concat(streamSafely(lefts), streamSafely(rights));
8✔
130
    }
131

132
    @Override
133
    public Stream<ColumnAlias> aliasRefs() {
134
        return Stream.empty();
×
135
    }
136
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc