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

torand / FasterSQL / 15071216480

16 May 2025 02:49PM UTC coverage: 69.877% (+2.4%) from 67.475%
15071216480

push

github

web-flow
Merge pull request #30 from torand/access-support

Access support

229 of 414 branches covered (55.31%)

Branch coverage included in aggregate %.

105 of 152 new or added lines in 26 files covered. (69.08%)

3 existing lines in 3 files now uncovered.

1193 of 1621 relevant lines covered (73.6%)

3.92 hits per line

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

76.6
/src/main/java/io/github/torand/fastersql/statement/DeleteStatement.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.statement;
17

18
import io.github.torand.fastersql.Column;
19
import io.github.torand.fastersql.Context;
20
import io.github.torand.fastersql.Table;
21
import io.github.torand.fastersql.dialect.AnsiIsoDialect;
22
import io.github.torand.fastersql.predicate.OptionalPredicate;
23
import io.github.torand.fastersql.predicate.Predicate;
24

25
import java.util.Collection;
26
import java.util.List;
27
import java.util.function.Supplier;
28
import java.util.stream.Stream;
29

30
import static io.github.torand.fastersql.Command.DELETE;
31
import static io.github.torand.fastersql.statement.Helpers.unwrapSuppliers;
32
import static io.github.torand.fastersql.util.collection.CollectionHelper.asList;
33
import static io.github.torand.fastersql.util.collection.CollectionHelper.concat;
34
import static io.github.torand.fastersql.util.collection.CollectionHelper.nonEmpty;
35
import static io.github.torand.fastersql.util.collection.CollectionHelper.streamSafely;
36
import static io.github.torand.fastersql.util.contract.Requires.requireNonEmpty;
37
import static java.util.Objects.isNull;
38
import static java.util.Objects.requireNonNull;
39
import static java.util.stream.Collectors.joining;
40

41
/**
42
 * Implements a DELETE statement.
43
 */
44
public class DeleteStatement implements PreparableStatement {
45
    private final Table<?> fromTable;
46
    private final List<Predicate> predicates;
47

48
    DeleteStatement(Table<?> table, Collection<Predicate> predicates) {
2✔
49
        this.fromTable = requireNonNull(table, "No table specified");
6✔
50
        this.predicates = asList(predicates);
4✔
51
    }
1✔
52

53
    /**
54
     * Adds one or more predicates to the WHERE clause.
55
     * @param predicates the predicates.
56
     * @return the modified statement.
57
     */
58
    public DeleteStatement where(Predicate... predicates) {
59
        requireNonEmpty(predicates, "No predicates specified");
6✔
60
        List<Predicate> concatenated = concat(this.predicates, predicates);
5✔
61
        return new DeleteStatement(fromTable, concatenated);
7✔
62
    }
63

64
    /**
65
     * Adds optional predicates to the WHERE clause if the wrapped predicates are present.
66
     * @param maybePredicates the optional predicates.
67
     * @return the modified statement.
68
     */
69
    public final DeleteStatement where(OptionalPredicate... maybePredicates) {
70
        requireNonEmpty(maybePredicates, "No optional predicates specified");
×
71
        List<Predicate> concatenated = concat(this.predicates, OptionalPredicate.unwrap(maybePredicates));
×
72
        return new DeleteStatement(fromTable, concatenated);
×
73
    }
74

75
    /**
76
     * Adds supplied predicates to the WHERE clause, if the condition is true.
77
     * @param condition the condition.
78
     * @param predicateSuppliers the suppliers providing predicates
79
     * @return the modified statement.
80
     */
81
    @SafeVarargs
82
    public final DeleteStatement whereIf(boolean condition, Supplier<Predicate>... predicateSuppliers) {
83
        requireNonEmpty(predicateSuppliers, "No predicate suppliers specified");
6✔
84
        if (condition) {
2!
85
            List<Predicate> concatenated = concat(this.predicates, unwrapSuppliers(predicateSuppliers));
6✔
86
            return new DeleteStatement(fromTable, concatenated);
7✔
87
        }
88
        return this;
×
89
    }
90

91
    @Override
92
    public String sql(Context context) {
93
        final Context localContext = context.withCommand(DELETE);
4✔
94
        validate();
2✔
95

96
        StringBuilder sb = new StringBuilder();
4✔
97
        sb.append("delete from ");
4✔
98
        sb.append(fromTable.sql(localContext));
7✔
99

100
        if (nonEmpty(predicates)) {
4!
101
            sb.append(" where ");
4✔
102
            sb.append(streamSafely(predicates)
8✔
103
                .map(p -> p.sql(localContext))
6✔
104
                .collect(joining(" and ")));
3✔
105
        }
106

107
        return sb.toString();
3✔
108
    }
109

110
    @Override
111
    public Stream<Object> params(Context context) {
112
        return streamSafely(predicates)
6✔
113
            .flatMap(p -> p.params(context));
5✔
114
    }
115

116
    private void validate() {
117
        if (isNull(fromTable)) {
4!
118
            throw new IllegalStateException("No FROM clause specified");
×
119
        }
120

121
        // TODO: Verify that deleteTables is subset of fromTables
122

123
        validateColumnTableRelations(streamSafely(predicates).flatMap(Predicate::columnRefs));
7✔
124
    }
1✔
125

126
    private void validateColumnTableRelations(Stream<Column> columns) {
127
        columns
3✔
128
            .filter(c -> !fromTable.name().equalsIgnoreCase(c.table().name()))
11!
129
            .findFirst()
2✔
130
            .ifPresent(c -> {
1✔
131
                throw new IllegalStateException("Column " + c.name() + " belongs to table " + c.table().name() + ", but table is not specified in the FROM clause");
×
132
            });
133
    }
1✔
134

135
    @Override
136
    public String toString() {
NEW
137
        return toString(new AnsiIsoDialect());
×
138
    }
139
}
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