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

torand / FasterSQL / 12893661530

21 Jan 2025 06:40PM UTC coverage: 50.829%. Remained the same
12893661530

push

github

torand
refactor: rename expression -> condition

104 of 304 branches covered (34.21%)

Branch coverage included in aggregate %.

81 of 211 new or added lines in 24 files covered. (38.39%)

3 existing lines in 2 files now uncovered.

601 of 1083 relevant lines covered (55.49%)

2.91 hits per line

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

66.1
/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.condition.Condition;
22
import io.github.torand.fastersql.condition.OptionalCondition;
23
import io.github.torand.fastersql.constant.Constant;
24
import io.github.torand.fastersql.function.Function;
25
import io.github.torand.fastersql.util.functional.Optionals;
26

27
import java.util.Collection;
28
import java.util.List;
29
import java.util.Optional;
30
import java.util.stream.Stream;
31

32
import static io.github.torand.fastersql.Command.UPDATE;
33
import static io.github.torand.fastersql.util.collection.CollectionHelper.*;
34
import static io.github.torand.fastersql.util.contract.Requires.requireNonEmpty;
35
import static java.util.Objects.requireNonNull;
36
import static java.util.stream.Collectors.joining;
37

38
public class UpdateStatement extends PreparableStatement {
39
    private final Table<?> table;
40
    private final List<FieldValue> fieldValues;
41
    private final List<Condition> conditions;
42

43
    UpdateStatement(Table<?> table, Collection<FieldValue> fieldValues, Collection<Condition> conditions) {
2✔
44
        this.table = requireNonNull(table, "No table specified");
6✔
45
        this.fieldValues = asList(fieldValues);
4✔
46
        this.conditions = asList(conditions);
4✔
47
    }
1✔
48

49
    public UpdateStatement set(Field field, Constant constant) {
50
        requireNonNull(field, "No field specified");
×
51
        requireNonNull(constant, "No constant specified");
×
52

53
        List<FieldValue> concatenated = concat(this.fieldValues, new FieldValue(field, constant.value()));
×
NEW
54
        return new UpdateStatement(table, concatenated, conditions);
×
55
    }
56

57
    public UpdateStatement set(Field field, Function function) {
58
        requireNonNull(field, "No field specified");
4✔
59
        requireNonNull(function, "No function specified");
4✔
60

61
        List<FieldValue> concatenated = concat(this.fieldValues, new FieldValue(field, function));
14✔
62
        return new UpdateStatement(table, concatenated, conditions);
9✔
63
    }
64

65
    public UpdateStatement set(Field field, Object value) {
66
        requireNonNull(field, "No field specified");
4✔
67

68
        List<FieldValue> concatenated = concat(this.fieldValues, new FieldValue(field, value));
14✔
69
        return new UpdateStatement(table, concatenated, conditions);
9✔
70
    }
71

72
    public UpdateStatement set(Field field, Optional<?> maybeValue) {
73
        requireNonNull(field, "No field specified");
×
74
        requireNonNull(maybeValue, "No value specified");
×
75

76
        if (maybeValue.isPresent()) {
×
77
            List<FieldValue> concatenated = concat(this.fieldValues, new FieldValue(field, maybeValue.get()));
×
NEW
78
            return new UpdateStatement(table, concatenated, conditions);
×
79
        } else {
80
            return this;
×
81
        }
82
    }
83

84
    public UpdateStatement where(Condition... conditions) {
85
        requireNonEmpty(conditions, "No conditions specified");
6✔
86

87
        List<Condition> concatenated = concat(this.conditions, conditions);
5✔
88
        return new UpdateStatement(table, fieldValues, concatenated);
9✔
89
    }
90

91
    /**
92
     * Same as other method of same name, but only adds to the where clause conditions that are present.
93
     * @param maybeConditions the conditions that may be present or not
94
     * @return updated statement, for method chaining
95
     */
96
    public final UpdateStatement where(OptionalCondition... maybeConditions) {
NEW
97
        requireNonEmpty(maybeConditions, "No optional conditions specified");
×
98

NEW
99
        List<Condition> concatenated = concat(this.conditions, OptionalCondition.unwrap(maybeConditions));
×
100
        return new UpdateStatement(table, fieldValues, concatenated);
×
101
    }
102

103
    @Override
104
    String sql(Context context) {
105
        final Context localContext = context.withCommand(UPDATE);
4✔
106
        validate();
2✔
107

108
        StringBuilder sb = new StringBuilder();
4✔
109
        sb.append("update ");
4✔
110
        sb.append(table.sql(context));
7✔
111
        sb.append(" set ");
4✔
112
        sb.append(streamSafely(fieldValues).map(fv -> fv.field().sql(localContext) + " = " + fv.valueSql(localContext)).collect(joining(", ")));
22✔
113
        if (nonEmpty(conditions)) {
4!
114
            sb.append(" where ");
4✔
115
            sb.append(streamSafely(conditions).map(e -> e.sql(localContext)).collect(joining(" and ")));
17✔
116
        }
117

118
        return sb.toString();
3✔
119
    }
120

121
    @Override
122
    List<Object> params(Context context) {
123
        return Stream.concat(streamSafely(fieldValues).map(FieldValue::param).flatMap(Optionals::stream), streamSafely(conditions).flatMap(e -> e.params(context))).toList();
20✔
124
    }
125

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

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