From 182cb2f9a911fd360eec0cb78059762c9ba5c847 Mon Sep 17 00:00:00 2001 From: Lilly <46890129+RainbowDashLabs@users.noreply.github.com> Date: Wed, 4 Dec 2024 16:19:59 +0100 Subject: [PATCH] Add unit tests to verify functionality --- .../de/chojo/sadu/queries/call/CallImpl.java | 19 +++++---- .../chojo/sadu/queries/exception/Check.java | 16 +++++--- .../IllegalQueryParameterException.java | 6 +++ .../queries/exception/QueryException.java | 6 +++ .../exception/RuntimeQueryException.java | 6 +++ .../queries/parameter/TokenParameter.java | 4 ++ .../sadu/queries/query/TokenizedQuery.java | 11 ++++- .../chojo/sadu/queries/examples/BindTest.java | 41 +++++++++++++++++++ 8 files changed, 93 insertions(+), 16 deletions(-) diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/call/CallImpl.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/call/CallImpl.java index 06a90ef6..0f186a74 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/call/CallImpl.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/call/CallImpl.java @@ -45,7 +45,7 @@ * A call is a subelement of a {@link Calls}. It represents a single query call of any kind. */ public final class CallImpl implements Call { - private final List tokens = new ArrayList<>(); + private final List parameter = new ArrayList<>(); private int index = 1; public CallImpl() { @@ -56,12 +56,12 @@ private int nextIndex() { } private Call addToken(String token, ThrowingBiConsumer apply) { - tokens.add(new TokenParameter(token, apply)); + parameter.add(new TokenParameter(token, apply)); return this; } private Call addToken(ThrowingBiConsumer apply) { - tokens.add(new IndexParameter(nextIndex(), apply)); + parameter.add(new IndexParameter(nextIndex(), apply)); return this; } @@ -351,12 +351,15 @@ public Call bind(T value, Adapter adapter) { } public void apply(TokenizedQuery query, PreparedStatement stmt) throws SQLException { - int count = 0; - for (var token : tokens) { - token.apply(query, stmt); - if (token instanceof IndexParameter) count++; + int indexCount = 0; + var tokens = query.getNamedTokens(); + for (var param : parameter) { + param.apply(query, stmt); + if (param instanceof IndexParameter) indexCount++; + if (param instanceof TokenParameter token) tokens.remove(token.token()); } - Check.assertIndexFilled(count, query); + Check.assertIndexFilled(indexCount, query); + Check.missingToken(tokens, query); } /** diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/Check.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/Check.java index 758424ec..04611f54 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/Check.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/Check.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import java.sql.ResultSet; +import java.util.Set; public final class Check { public static void assertQueryResult(@Nullable Object object) { @@ -23,14 +24,17 @@ public static void assertQueryResult(@Nullable Object object) { } public static void assertIndexRange(int index, TokenizedQuery query) { - if (query.indexSize() >= index) { - throw new IllegalQueryParameterException("No parameter with index %s exists in query \"%s\". Only %s parameters are defined".formatted(index, query.sql(), query.indexSize())); - } + if (query.indexSize() >= index) return; + throw new IllegalQueryParameterException("No parameter with index %s exists in query \"%s\". Only %s parameter(s) is/are defined".formatted(index, query.sql(), query.indexSize())); } public static void assertIndexFilled(int count, TokenizedQuery query) { - if (query.indexSize() != count) { - throw new IllegalQueryParameterException("Missing index parameter. %s were given, but %s were set in query: \"%s\"".formatted(count, query.indexSize(), query.sql())); - } + if (query.indexSize() == count) return; + throw new IllegalQueryParameterException("Missing index parameter. %s were given, but %s were set in query: \"%s\"".formatted(count, query.indexSize(), query.sql())); + } + + public static void missingToken(Set tokens, TokenizedQuery query) { + if (tokens.isEmpty()) return; + throw new IllegalQueryParameterException("The parameters %s are not bound in query: %s".formatted(String.join(", ", tokens), query.sql())); } } diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/IllegalQueryParameterException.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/IllegalQueryParameterException.java index 07a9da70..0b995ac2 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/IllegalQueryParameterException.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/IllegalQueryParameterException.java @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + package de.chojo.sadu.queries.exception; public class IllegalQueryParameterException extends RuntimeQueryException{ diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/QueryException.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/QueryException.java index 3b8a6629..48a25899 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/QueryException.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/QueryException.java @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + package de.chojo.sadu.queries.exception; import de.chojo.sadu.queries.query.ParsedQueryImpl; diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/RuntimeQueryException.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/RuntimeQueryException.java index d824d1c0..c063fc37 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/RuntimeQueryException.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/exception/RuntimeQueryException.java @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + package de.chojo.sadu.queries.exception; public class RuntimeQueryException extends RuntimeException{ diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/parameter/TokenParameter.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/parameter/TokenParameter.java index 9914b07b..a8c356a0 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/parameter/TokenParameter.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/parameter/TokenParameter.java @@ -43,4 +43,8 @@ public void apply(TokenizedQuery query, PreparedStatement stmt) throws SQLExcept apply.accept(stmt, index); } } + + public String token() { + return token; + } } diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/query/TokenizedQuery.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/query/TokenizedQuery.java index fd229481..fe477ef2 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/query/TokenizedQuery.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/query/TokenizedQuery.java @@ -7,9 +7,12 @@ package de.chojo.sadu.queries.query; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.regex.Pattern; public class TokenizedQuery { @@ -47,14 +50,18 @@ public static TokenizedQuery create(String sql) { } public List getNamedTokenIndex(String token) { - return namedToken.get(token); + return namedToken.getOrDefault(token, Collections.emptyList()); + } + + public Set getNamedTokens() { + return new HashSet<>(namedToken.keySet()); } public int getIndexTokenIndex(int index) { return indexToken.get(index); } - public int indexSize(){ + public int indexSize() { return indexToken.size(); } diff --git a/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/BindTest.java b/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/BindTest.java index 272336e4..5159f732 100644 --- a/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/BindTest.java +++ b/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/BindTest.java @@ -13,6 +13,7 @@ import de.chojo.sadu.queries.api.configuration.QueryConfiguration; import de.chojo.sadu.queries.configuration.QueryConfigurationBuilder; import de.chojo.sadu.queries.examples.dao.User; +import de.chojo.sadu.queries.exception.IllegalQueryParameterException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -54,4 +55,44 @@ public void failOnInvalidToken() { .all(); }); } + + // Retrieve all matching users directly + @Test + public void failOnTooFewParameters() { + Assertions.assertThrows(IllegalQueryParameterException.class, () -> { + List users = query.query("SELECT * FROM users WHERE id = ?") + .single(call()) + .map(User.map()) + .all(); + }); + } + + @Test + public void failOnTooManyParameters() { + Assertions.assertThrows(IllegalQueryParameterException.class, () -> { + List users = query.query("SELECT * FROM users WHERE id = ?") + .single(call().bind(1).bind(1)) + .map(User.map()) + .all(); + }); + } + + @Test + public void failOnMissingNamedToken() { + Assertions.assertThrows(IllegalQueryParameterException.class, () -> { + List users = query.query("SELECT * FROM users WHERE id = ? AND name = :name") + .single(call().bind(1)) + .map(User.map()) + .all(); + }); + } + @Test + public void failOnUnknownNamedToken() { + Assertions.assertThrows(IllegalQueryParameterException.class, () -> { + List users = query.query("SELECT * FROM users WHERE id = ?") + .single(call().bind(1).bind("name", "name")) + .map(User.map()) + .all(); + }); + } }