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

trydofor / professional-wings / #134

28 Jan 2025 12:02PM UTC coverage: 63.525% (-0.2%) from 63.721%
#134

push

trydofor
🐍 happy lunar snake year #308

15 of 15 new or added lines in 3 files covered. (100.0%)

53 existing lines in 5 files now uncovered.

12933 of 20359 relevant lines covered (63.52%)

0.64 hits per line

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

80.65
/wings/faceless/src/main/java/pro/fessional/wings/faceless/database/helper/JdbcTemplateHelper.java
1
package pro.fessional.wings.faceless.database.helper;
2

3
import lombok.extern.slf4j.Slf4j;
4
import org.jetbrains.annotations.NotNull;
5
import org.springframework.jdbc.core.JdbcTemplate;
6
import org.springframework.jdbc.core.ResultSetExtractor;
7

8
import java.util.HashSet;
9
import java.util.function.Function;
10

11
/**
12
 * @author trydofor
13
 * @since 2024-01-25
14
 */
15
@Slf4j
1✔
16
public class JdbcTemplateHelper {
×
17

18
    public static final ResultSetExtractor<String> FirstStringOrNull = rs -> rs.next() ? rs.getString(1) : null;
1✔
19

20
    public static final ResultSetExtractor<Long> FirstLongOrNull = rs -> {
1✔
21
        if (rs.next()) {
1✔
22
            long v = rs.getLong(1);
1✔
23
            return rs.wasNull() ? null : v;
1✔
24
        }
25
        return null;
×
26
    };
27

28
    public static final ResultSetExtractor<Integer> FirstIntegerOrNull = rs -> {
1✔
29
        if (rs.next()) {
1✔
30
            int v = rs.getInt(1);
1✔
31
            return rs.wasNull() ? null : v;
1✔
32
        }
33
        return null;
×
34
    };
35

36
    public static final ResultSetExtractor<Boolean> FirstBooleanOrNull = rs -> {
1✔
37
        if (rs.next()) {
×
38
            boolean v = rs.getBoolean(1);
×
39
            return rs.wasNull() ? null : v;
×
40
        }
41
        return null;
×
42
    };
43

44
    /**
45
     * <pre>
46
     * where clause of PreparedStatement, must,
47
     * - start with ' WHERE ' case-ignored
48
     * - not empty
49
     * - not contains ';'
50
     * </pre>
51
     */
52
    public static String safeWhere(String where) {
53
        if (where == null || where.isEmpty()) {
1✔
54
            throw new IllegalArgumentException("where clause is empty");
×
55
        }
56
        if (where.contains(";")) {
1✔
57
            throw new IllegalArgumentException("where clause may be sql-injected, should not contains ';'");
×
58
        }
59
        final String key = " WHERE ";
1✔
60
        if (!where.regionMatches(true, 0, key, 0, key.length())) {
1✔
61
            throw new IllegalArgumentException("missing ' WHERE ' in where clause");
×
62
        }
63
        return where;
1✔
64
    }
65

66
    protected static final HashSet<String> SafeTables = new HashSet<>();
1✔
67
    protected static final HashSet<String> QuotedTables = new HashSet<>();
1✔
68

69
    /**
70
     * the sql to list table, and get the table name at the first column
71
     */
72
    @NotNull
73
    protected static String ShowTableSql = "SHOW TABLES";
1✔
74

75
    /**
76
     * in mysql (not ANSI_QUOTES), return `table`
77
     */
78
    @NotNull
79
    protected static Function<String, String> Quotes = (String name) -> {
1✔
80
        int pos0 = name.indexOf('`');
1✔
81
        if (pos0 >= 0) {
1✔
82
            int pos1 = name.lastIndexOf('`');
1✔
83
            if (pos0 == 0 && pos1 == name.length() - 1) {
1✔
84
                int pos = name.indexOf('`', pos0 + 1, pos1);
1✔
85
                if (pos < 0) return name;
1✔
86
            }
87
            name = name.replace("`", "");
1✔
88
        }
89
        return "`" + name + "`";
1✔
90
    };
91

92
    public static void initSafeTable(JdbcTemplate tmpl) {
93
        tmpl.query(ShowTableSql, rs -> {
1✔
94
            initSafeTable(rs.getString(1));
1✔
95
        });
1✔
96
    }
1✔
97

98
    public static void initSafeTable(String tbl) {
99
        log.info("init safe table={}", tbl);
1✔
100

101
        String lc = tbl.toLowerCase();
1✔
102
        String uc = tbl.toUpperCase();
1✔
103
        SafeTables.add(lc);
1✔
104
        SafeTables.add(uc);
1✔
105

106
        QuotedTables.add(Quotes.apply(lc));
1✔
107
        QuotedTables.add(Quotes.apply(uc));
1✔
108
    }
1✔
109

110
    /**
111
     * whether the table is in the safe list
112
     */
113
    public static boolean isSafeTable(String table) {
114
        return SafeTables.contains(table) || QuotedTables.contains(table);
1✔
115
    }
116

117
    /**
118
     * quote name, e.g. `table`
119
     */
120
    public static String safeName(@NotNull String name) {
121
        return Quotes.apply(name);
1✔
122
    }
123

124
    /**
125
     * check and quote table
126
     */
127
    public static String safeTable(String table) {
128
        if (table == null || table.isEmpty()) {
1✔
UNCOV
129
            throw new NullPointerException("table is empty");
×
130
        }
131

132
        int safe = 0;
1✔
133
        if (SafeTables.contains(table)) {
1✔
134
            safe = 1;
1✔
135
        }
136
        else if (QuotedTables.contains(table)) {
1✔
137
            safe = 2;
1✔
138
        }
139

140
        if (safe == 0) {
1✔
UNCOV
141
            throw new IllegalArgumentException("unsafe table " + table);
×
142
        }
143

144
        return safe == 1 ? Quotes.apply(table) : table;
1✔
145
    }
146
}
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