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

torand / FasterSQL / 13367709795

17 Feb 2025 10:06AM UTC coverage: 58.785% (+2.0%) from 56.762%
13367709795

push

github

torand
feat: support length function

148 of 338 branches covered (43.79%)

Branch coverage included in aggregate %.

10 of 17 new or added lines in 7 files covered. (58.82%)

66 existing lines in 9 files now uncovered.

829 of 1324 relevant lines covered (62.61%)

3.33 hits per line

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

86.44
/src/main/java/io/github/torand/fastersql/statement/UpdateStatement.java
1
/*
2
 * Copyright (c) 2024 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.Context;
19
import io.github.torand.fastersql.Field;
20
import io.github.torand.fastersql.Table;
21
import io.github.torand.fastersql.expression.Expression;
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.Optional;
28
import java.util.stream.Stream;
29

30
import static io.github.torand.fastersql.Command.UPDATE;
31
import static io.github.torand.fastersql.constant.Constants.$;
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.isEmpty;
35
import static io.github.torand.fastersql.util.collection.CollectionHelper.nonEmpty;
36
import static io.github.torand.fastersql.util.collection.CollectionHelper.streamSafely;
37
import static io.github.torand.fastersql.util.contract.Requires.requireNonEmpty;
38
import static java.util.Objects.requireNonNull;
39
import static java.util.stream.Collectors.joining;
40

41
public class UpdateStatement extends PreparableStatement {
42
    private final Table<?> table;
43
    private final List<FieldValue> fieldValues;
44
    private final List<Predicate> predicates;
45

46
    UpdateStatement(Table<?> table, Collection<FieldValue> fieldValues, Collection<Predicate> predicates) {
2✔
47
        this.table = requireNonNull(table, "No table specified");
6✔
48
        this.fieldValues = asList(fieldValues);
4✔
49
        this.predicates = asList(predicates);
4✔
50
    }
1✔
51

52
    public UpdateStatement set(Field field, Expression expression) {
53
        requireNonNull(field, "No field specified");
4✔
54
        requireNonNull(expression, "No expression specified");
4✔
55

56
        List<FieldValue> concatenated = concat(this.fieldValues, new FieldValue(field, expression));
14✔
57
        return new UpdateStatement(table, concatenated, predicates);
9✔
58
    }
59

60
    public UpdateStatement set(Field field, Object value) {
61
        requireNonNull(field, "No field specified");
4✔
62

63
        List<FieldValue> concatenated = concat(this.fieldValues, new FieldValue(field, $(value)));
15✔
64
        return new UpdateStatement(table, concatenated, predicates);
9✔
65
    }
66

67
    public UpdateStatement set(Field field, Optional<?> maybeValue) {
68
        requireNonNull(field, "No field specified");
4✔
69
        requireNonNull(maybeValue, "No value specified");
4✔
70

71
        if (maybeValue.isPresent()) {
3✔
72
            List<FieldValue> concatenated = concat(this.fieldValues, new FieldValue(field, $(maybeValue.get())));
16✔
73
            return new UpdateStatement(table, concatenated, predicates);
9✔
74
        } else {
75
            return this;
2✔
76
        }
77
    }
78

79
    public UpdateStatement where(Predicate... predicates) {
80
        requireNonEmpty(predicates, "No predicates specified");
6✔
81

82
        List<Predicate> concatenated = concat(this.predicates, predicates);
5✔
83
        return new UpdateStatement(table, fieldValues, concatenated);
9✔
84
    }
85

86
    /**
87
     * Same as other method of same name, but only adds to the where clause predicates that are present.
88
     * @param maybePredicates the predicates that may be present or not
89
     * @return updated statement, for method chaining
90
     */
91
    public final UpdateStatement where(OptionalPredicate... maybePredicates) {
UNCOV
92
        requireNonEmpty(maybePredicates, "No optional predicates specified");
×
93

UNCOV
94
        List<Predicate> concatenated = concat(this.predicates, OptionalPredicate.unwrap(maybePredicates));
×
UNCOV
95
        return new UpdateStatement(table, fieldValues, concatenated);
×
96
    }
97

98
    @Override
99
    String sql(Context context) {
100
        final Context localContext = context.withCommand(UPDATE);
4✔
101
        validate();
2✔
102

103
        StringBuilder sb = new StringBuilder();
4✔
104
        sb.append("update ");
4✔
105
        sb.append(table.sql(context));
7✔
106
        sb.append(" set ");
4✔
107
        sb.append(streamSafely(fieldValues).map(fv -> fv.field().sql(localContext) + " = " + fv.valueSql(localContext)).collect(joining(", ")));
22✔
108
        if (nonEmpty(predicates)) {
4!
109
            sb.append(" where ");
4✔
110
            sb.append(streamSafely(predicates).map(e -> e.sql(localContext)).collect(joining(" and ")));
17✔
111
        }
112

113
        return sb.toString();
3✔
114
    }
115

116
    @Override
117
    List<Object> params(Context context) {
118
        final Context localContext = context.withCommand(UPDATE);
4✔
119
        return Stream.concat(
4✔
120
                streamSafely(fieldValues).flatMap(fv -> fv.params(localContext)),
10✔
121
                streamSafely(predicates).flatMap(p -> p.params(localContext)))
8✔
122
            .toList();
1✔
123
    }
124

125
    private void validate() {
126
        if (isEmpty(fieldValues)) {
4!
UNCOV
127
            throw new IllegalStateException("No values to set");
×
128
        }
129
        validateFieldTableRelations(streamSafely(fieldValues).map(FieldValue::field));
7✔
130
        validateFieldTableRelations(streamSafely(predicates).flatMap(Predicate::fieldRefs));
7✔
131
    }
1✔
132

133
    private void validateFieldTableRelations(Stream<Field> fields) {
134
        fields
3✔
135
            .filter(f -> !table.name().equalsIgnoreCase(f.table().name()))
11!
136
            .findFirst()
2✔
137
            .ifPresent(f -> {
1✔
UNCOV
138
                throw new IllegalStateException("Field " + f.name() + " belongs to table " + f.table().name() + ", but is not specified in the UPDATE clause");
×
139
            });
140
    }
1✔
141
}
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