diff --git a/build.gradle.kts b/build.gradle.kts index 51fde7c7..66e5a8a3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ plugins { publishData { useEldoNexusRepos(false) - publishingVersion = "2.0.0" + publishingVersion = "2.1.0" } group = "de.chojo.sadu" diff --git a/sadu-core/src/main/java/de/chojo/sadu/core/configuration/DatabaseConfig.java b/sadu-core/src/main/java/de/chojo/sadu/core/configuration/DatabaseConfig.java new file mode 100644 index 00000000..429bbf3c --- /dev/null +++ b/sadu-core/src/main/java/de/chojo/sadu/core/configuration/DatabaseConfig.java @@ -0,0 +1,49 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.core.configuration; + +/** + * This interface represents the configuration for a database connection. + * It provides methods to retrieve the address, port, user, password, and database name. + */ +public interface DatabaseConfig { + /** + * Returns the address of the database server. + * + * @return the address of the database server + */ + String host(); + + /** + * Returns the port for the database connection. + * + * @return the port for the database connection + */ + String port(); + + /** + * Retrieves the username associated with the database connection. + * + * @return The username as a string. + */ + String user(); + + /** + * Returns the password for the database user. + * + * @return the password for the database user + */ + String password(); + + /** + * Returns the database for the database connection. + * + * @return The name of the database. + */ + String database(); + +} diff --git a/sadu-core/src/main/java/de/chojo/sadu/core/configuration/SchemaProvider.java b/sadu-core/src/main/java/de/chojo/sadu/core/configuration/SchemaProvider.java new file mode 100644 index 00000000..24531f7f --- /dev/null +++ b/sadu-core/src/main/java/de/chojo/sadu/core/configuration/SchemaProvider.java @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.core.configuration; + +public interface SchemaProvider { + String schema(); +} diff --git a/sadu-core/src/main/java/de/chojo/sadu/core/jdbc/RemoteJdbcConfig.java b/sadu-core/src/main/java/de/chojo/sadu/core/jdbc/RemoteJdbcConfig.java index 0581dc8f..f72b2a59 100644 --- a/sadu-core/src/main/java/de/chojo/sadu/core/jdbc/RemoteJdbcConfig.java +++ b/sadu-core/src/main/java/de/chojo/sadu/core/jdbc/RemoteJdbcConfig.java @@ -6,6 +6,7 @@ package de.chojo.sadu.core.jdbc; +import de.chojo.sadu.core.configuration.DatabaseConfig; import org.jetbrains.annotations.ApiStatus; import java.util.Optional; @@ -27,6 +28,23 @@ public abstract class RemoteJdbcConfig> extends Jd public RemoteJdbcConfig() { } + /** + * Apply the given {@link DatabaseConfig} to configure the connection settings. + * + * @param config the database configuration + * @return the builder instance with the applied configuration + * @throws IllegalArgumentException when an invalid port or database name is provided + * @throws IllegalArgumentException when the host, port, user, password, or database are empty or null + */ + public T withConfig(DatabaseConfig config) { + host(config.host()) + .port(config.port()) + .user(config.user()) + .password(config.password()) + .database(config.database()); + return self(); + } + /** * Sets the host explicit to local host. *

diff --git a/sadu-core/src/main/java/module-info.java b/sadu-core/src/main/java/module-info.java index 18903d67..99c386af 100644 --- a/sadu-core/src/main/java/module-info.java +++ b/sadu-core/src/main/java/module-info.java @@ -4,6 +4,7 @@ requires transitive org.slf4j; exports de.chojo.sadu.core.base; + exports de.chojo.sadu.core.configuration; exports de.chojo.sadu.core.conversion; exports de.chojo.sadu.core.databases; exports de.chojo.sadu.core.databases.exceptions; diff --git a/sadu-datasource/src/main/java/de/chojo/sadu/datasource/DatabaseConfig.java b/sadu-datasource/src/main/java/de/chojo/sadu/datasource/DatabaseConfig.java deleted file mode 100644 index ad8a0c1c..00000000 --- a/sadu-datasource/src/main/java/de/chojo/sadu/datasource/DatabaseConfig.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SPDX-License-Identifier: LGPL-3.0-or-later - * - * Copyright (C) RainbowDashLabs and Contributor - */ - -package de.chojo.sadu.datasource; - -import org.jetbrains.annotations.Nullable; - -import java.util.Properties; - -/** - * Class which provides basic data for a database - */ -public class DatabaseConfig { - private final String address; - private final String port; - private final String user; - private final String password; - private final String database; - - /** - * Create a new DbConfiguration. - *

- * Values which are null will be ignored - * - * @param address address - * @param port port - * @param user user - * @param password password - * @param database database - */ - public DatabaseConfig(@Nullable String address, @Nullable String port, @Nullable String user, @Nullable String password, @Nullable String database) { - this.address = address; - this.port = port; - this.user = user; - this.password = password; - this.database = database; - } - - /** - * Apply the settings to a property - * - * @param properties properties to apply the settings on - */ - public void apply(Properties properties) { - if (address != null) properties.setProperty("dataSource.serverName", address); - if (port != null) properties.setProperty("dataSource.portNumber", port); - if (user != null) properties.setProperty("dataSource.user", user); - if (password != null) properties.setProperty("dataSource.password", password); - if (database != null) properties.setProperty("dataSource.databaseName", database); - } -} diff --git a/sadu-datasource/src/main/java/de/chojo/sadu/datasource/configuration/SchemaDatabaseConfig.java b/sadu-datasource/src/main/java/de/chojo/sadu/datasource/configuration/SchemaDatabaseConfig.java new file mode 100644 index 00000000..6ddc56f2 --- /dev/null +++ b/sadu-datasource/src/main/java/de/chojo/sadu/datasource/configuration/SchemaDatabaseConfig.java @@ -0,0 +1,18 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.datasource.configuration; + +import de.chojo.sadu.core.configuration.DatabaseConfig; +import de.chojo.sadu.core.configuration.SchemaProvider; + +/** + * Record which provides basic data for a database connection with a schema + */ + +public record SchemaDatabaseConfig(String host, String port, String user, String password, String database, + String schema) implements DatabaseConfig, SchemaProvider { +} diff --git a/sadu-datasource/src/main/java/de/chojo/sadu/datasource/configuration/SimpleDatabaseConfig.java b/sadu-datasource/src/main/java/de/chojo/sadu/datasource/configuration/SimpleDatabaseConfig.java new file mode 100644 index 00000000..0758b6c0 --- /dev/null +++ b/sadu-datasource/src/main/java/de/chojo/sadu/datasource/configuration/SimpleDatabaseConfig.java @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.datasource.configuration; + +/** + * Record which provides basic data for a database connection + */ +public record SimpleDatabaseConfig(String host, String port, String user, String password, + String database) implements de.chojo.sadu.core.configuration.DatabaseConfig { +} diff --git a/sadu-datasource/src/main/java/module-info.java b/sadu-datasource/src/main/java/module-info.java index 6bb5804c..3065e672 100644 --- a/sadu-datasource/src/main/java/module-info.java +++ b/sadu-datasource/src/main/java/module-info.java @@ -5,4 +5,5 @@ exports de.chojo.sadu.datasource.stage; exports de.chojo.sadu.datasource; exports de.chojo.sadu.datasource.exceptions; + exports de.chojo.sadu.datasource.configuration; } diff --git a/sadu-examples/build.gradle.kts b/sadu-examples/build.gradle.kts index 8b78d731..bdcd7fad 100644 --- a/sadu-examples/build.gradle.kts +++ b/sadu-examples/build.gradle.kts @@ -7,6 +7,6 @@ dependencies { // database driver compileOnly("org.xerial", "sqlite-jdbc", "3.45.1.0") compileOnly("org.postgresql", "postgresql", "42.7.2") - compileOnly("org.mariadb.jdbc", "mariadb-java-client", "3.3.2") + compileOnly("org.mariadb.jdbc", "mariadb-java-client", "3.3.3") compileOnly("mysql", "mysql-connector-java", "8.0.33") } diff --git a/sadu-mapper/src/main/java/de/chojo/sadu/mapper/util/Results.java b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/util/Results.java index ea0504e3..4cbff95d 100644 --- a/sadu-mapper/src/main/java/de/chojo/sadu/mapper/util/Results.java +++ b/sadu-mapper/src/main/java/de/chojo/sadu/mapper/util/Results.java @@ -11,6 +11,8 @@ import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; @@ -78,4 +80,11 @@ public static Set columnTypes(ResultSetMetaData meta) throws SQLExceptio } return columns; } + + public static List generatedKeys(Statement stmt) throws SQLException { + var keys = new ArrayList(); + var generatedKeys = stmt.getGeneratedKeys(); + while (generatedKeys.next()) keys.add(generatedKeys.getLong(1)); + return keys; + } } diff --git a/sadu-postgresql/src/main/java/de/chojo/sadu/postgresql/jdbc/PostgreSqlJdbc.java b/sadu-postgresql/src/main/java/de/chojo/sadu/postgresql/jdbc/PostgreSqlJdbc.java index 9b7b01e3..d812eeb1 100644 --- a/sadu-postgresql/src/main/java/de/chojo/sadu/postgresql/jdbc/PostgreSqlJdbc.java +++ b/sadu-postgresql/src/main/java/de/chojo/sadu/postgresql/jdbc/PostgreSqlJdbc.java @@ -6,6 +6,8 @@ package de.chojo.sadu.postgresql.jdbc; +import de.chojo.sadu.core.configuration.DatabaseConfig; +import de.chojo.sadu.core.configuration.SchemaProvider; import de.chojo.sadu.core.jdbc.RemoteJdbcConfig; /** @@ -21,6 +23,14 @@ public String driver() { return "postgresql"; } + @Override + public PostgreSqlJdbc withConfig(DatabaseConfig config) { + if (config instanceof SchemaProvider s) { + currentSchema(s.schema()); + } + return super.withConfig(config); + } + /** * The connection timeout value, in milliseconds, or zero for no timeout. * Default: 30 000. diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/execution/writing/CalledBatchQuery.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/execution/writing/CalledBatchQuery.java index f1f31d72..7591ec8f 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/execution/writing/CalledBatchQuery.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/execution/writing/CalledBatchQuery.java @@ -6,7 +6,10 @@ package de.chojo.sadu.queries.api.execution.writing; -import de.chojo.sadu.queries.api.results.writing.ManipulationBatchResult; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionBatchResult; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationBatchResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationResult; /** * The CalledBatchQuery interface represents a batch query that can perform insert, update, and delete operations @@ -16,9 +19,19 @@ public interface CalledBatchQuery { /** * Inserts the specified values into the table. * - * @return The {@link ManipulationBatchResult} that represents the results of the insert operations. + * @return The {@link InsertionBatchResult} that represents the results of the insert operations. */ - ManipulationBatchResult insert(); + InsertionBatchResult insert(); + + /** + * Inserts the specified values into the table. + *

+ * Additionally, generated keys will be retrieved. + * + * @return The {@link InsertionBatchResult} that represents the results of the insert operations. + */ + InsertionBatchResult insertAndGetKeys(); + /** * Executes update operations as part of a batch query. @@ -26,12 +39,12 @@ public interface CalledBatchQuery { * * @return The {@link ManipulationBatchResult} that represents the results of the update operations. */ - ManipulationBatchResult update(); + ManipulationBatchResult update(); /** * Deletes the selected items or records from the data source. * * @return The {@link ManipulationBatchResult} that represents the results of the delete operations. */ - ManipulationBatchResult delete(); + ManipulationBatchResult delete(); } diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/execution/writing/CalledSingletonQuery.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/execution/writing/CalledSingletonQuery.java index 681cf03d..dcad58b2 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/execution/writing/CalledSingletonQuery.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/execution/writing/CalledSingletonQuery.java @@ -9,7 +9,8 @@ import de.chojo.sadu.mapper.MapperConfig; import de.chojo.sadu.mapper.rowmapper.RowMapping; import de.chojo.sadu.queries.api.execution.reading.Reader; -import de.chojo.sadu.queries.api.results.writing.ManipulationResult; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationResult; /** * Represents a query that can be executed as a singleton call. @@ -48,9 +49,17 @@ public interface CalledSingletonQuery { * Inserts a row into the database table represented by the initial symbol of the containing class, * and returns the result of the manipulation operation. * - * @return The result of the manipulation operation as a {@link ManipulationResult} object. + * @return The result of the manipulation operation as a {@link InsertionResult} object. + */ + InsertionResult insertAndGetKeys(); + + /** + * Inserts a row into the database table represented by the initial symbol of the containing class, + * and returns the result of the manipulation operation. + * + * @return The result of the manipulation operation as a {@link InsertionResult} object. */ - ManipulationResult insert(); + InsertionResult insert(); /** * Updates the data in the database based on the provided query. diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/insertion/InsertionBatchResult.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/insertion/InsertionBatchResult.java new file mode 100644 index 00000000..ecf51e97 --- /dev/null +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/insertion/InsertionBatchResult.java @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.queries.api.results.writing.insertion; + +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationBatchResult; + +import java.util.List; + +/** + * The InsertionBatchResult interface represents the result of a batch insertion operation. + * It extends the ManipulationBatchResult interface and adds the ability to retrieve the keys of the inserted rows. + * + * @param the type of InsertionResult + */ +public interface InsertionBatchResult extends ManipulationBatchResult, InsertionResult { + /** + * Retrieves the keys of the inserted rows of all executed statements. + * + * @return a List of Long representing the keys of the inserted rows + */ + @Override + List keys(); +} diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/insertion/InsertionResult.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/insertion/InsertionResult.java new file mode 100644 index 00000000..77aa370b --- /dev/null +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/insertion/InsertionResult.java @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.queries.api.results.writing.insertion; + +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationResult; + +import java.util.List; + +/** + * The InsertionResult interface represents the result of an insertion operation. + * It extends the ManipulationResult interface and adds the ability to retrieve the keys of the inserted rows. + */ +public interface InsertionResult extends ManipulationResult { + /** + * Retrieves the keys of the inserted rows. + * + * @return a List of Long representing the keys of the inserted rows + */ + List keys(); + +} diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/insertion/package-info.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/insertion/package-info.java new file mode 100644 index 00000000..e9d0209e --- /dev/null +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/insertion/package-info.java @@ -0,0 +1,4 @@ +/** + * Defines the result of an insertion action. + */ +package de.chojo.sadu.queries.api.results.writing.insertion; diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/ManipulationBatchResult.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/manipulation/ManipulationBatchResult.java similarity index 61% rename from sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/ManipulationBatchResult.java rename to sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/manipulation/ManipulationBatchResult.java index e3d5b446..79aa1290 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/ManipulationBatchResult.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/manipulation/ManipulationBatchResult.java @@ -4,17 +4,23 @@ * Copyright (C) RainbowDashLabs and Contributor */ -package de.chojo.sadu.queries.api.results.writing; +package de.chojo.sadu.queries.api.results.writing.manipulation; import java.util.List; -public interface ManipulationBatchResult extends ManipulationResult { +/** + * The ManipulationBatchResult interface represents the result of a batch manipulation operation. + * It extends the ManipulationResult interface and provides methods to retrieve individual results of each manipulation operation. + * + * @param the type of ManipulationResult + */ +public interface ManipulationBatchResult extends ManipulationResult { /** * Returns a list of ManipulationResult representing the results of each indivudual manipulation operation. * * @return The list of ManipulationResults. */ - List results(); + List results(); /** * Retrieves the number of rows affected by the all executions of the query. diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/ManipulationResult.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/manipulation/ManipulationResult.java similarity index 97% rename from sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/ManipulationResult.java rename to sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/manipulation/ManipulationResult.java index c37ab371..1dbde165 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/ManipulationResult.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/manipulation/ManipulationResult.java @@ -4,7 +4,7 @@ * Copyright (C) RainbowDashLabs and Contributor */ -package de.chojo.sadu.queries.api.results.writing; +package de.chojo.sadu.queries.api.results.writing.manipulation; import de.chojo.sadu.queries.api.results.BaseResult; diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/manipulation/package-info.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/manipulation/package-info.java new file mode 100644 index 00000000..71d773e2 --- /dev/null +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/api/results/writing/manipulation/package-info.java @@ -0,0 +1,4 @@ +/** + * Defines the result of a manipulation action like deleting and updating. + */ +package de.chojo.sadu.queries.api.results.writing.manipulation; diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/execution/writing/CalledBatchQueryImpl.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/execution/writing/CalledBatchQueryImpl.java index 265adf1d..3234b216 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/execution/writing/CalledBatchQueryImpl.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/execution/writing/CalledBatchQueryImpl.java @@ -6,18 +6,24 @@ package de.chojo.sadu.queries.execution.writing; +import de.chojo.sadu.mapper.util.Results; import de.chojo.sadu.queries.api.base.QueryProvider; import de.chojo.sadu.queries.api.execution.writing.CalledBatchQuery; -import de.chojo.sadu.queries.api.results.writing.ManipulationBatchResult; -import de.chojo.sadu.queries.api.results.writing.ManipulationResult; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionBatchResult; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationBatchResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationResult; import de.chojo.sadu.queries.call.CallImpl; import de.chojo.sadu.queries.calls.BatchCall; import de.chojo.sadu.queries.query.ParsedQueryImpl; import de.chojo.sadu.queries.query.QueryImpl; -import de.chojo.sadu.queries.results.writing.ManipulationBatchQuery; -import de.chojo.sadu.queries.results.writing.ManipulationResultImpl; +import de.chojo.sadu.queries.results.writing.insertion.InsertionBatchResultImpl; +import de.chojo.sadu.queries.results.writing.insertion.InsertionResultImpl; +import de.chojo.sadu.queries.results.writing.manipulation.ManipulationBatchResultImpl; +import de.chojo.sadu.queries.results.writing.manipulation.ManipulationResultImpl; import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.Collections; @@ -31,30 +37,57 @@ public CalledBatchQueryImpl(ParsedQueryImpl parsedQuery, BatchCall calls) { } @Override - public ManipulationBatchResult insert() { - return update(); + public InsertionBatchResult insertAndGetKeys() { + return query().callConnection(() -> new InsertionBatchResultImpl(this, Collections.emptyList()), conn -> { + var changed = new ArrayList(); + for (var call : calls.calls()) { + try (var stmt = conn.prepareStatement(parsedQuery.sql().tokenizedSql(), Statement.RETURN_GENERATED_KEYS)) { + ((CallImpl) call).apply(parsedQuery.sql(), stmt); + var changes = stmt.executeUpdate(); + changed.add(new InsertionResultImpl(this, changes, Results.generatedKeys(stmt))); + } catch (SQLException ex) { + query().handleException(ex); + } + } + return new InsertionBatchResultImpl(this, changed); + }); + } + + @Override + public InsertionBatchResult insert() { + return query().callConnection(() -> new InsertionBatchResultImpl(this, Collections.emptyList()), conn -> { + var changed = new ArrayList(); + for (var call : calls.calls()) { + try (var stmt = conn.prepareStatement(parsedQuery.sql().tokenizedSql())) { + ((CallImpl) call).apply(parsedQuery.sql(), stmt); + changed.add(new InsertionResultImpl(this, stmt.executeUpdate(), Collections.emptyList())); + } catch (SQLException ex) { + query().handleException(ex); + } + } + return new InsertionBatchResultImpl(this, changed); + }); } @SuppressWarnings("JDBCPrepareStatementWithNonConstantString") @Override - public ManipulationBatchResult update() { - return query().callConnection(() -> new ManipulationBatchQuery(this, Collections.emptyList()), conn -> { + public ManipulationBatchResult update() { + return query().callConnection(() -> new ManipulationBatchResultImpl<>(this, Collections.emptyList()), conn -> { var changed = new ArrayList(); for (var call : calls.calls()) { try (var stmt = conn.prepareStatement(parsedQuery.sql().tokenizedSql())) { - //TODO find way to return generated keys ((CallImpl) call).apply(parsedQuery.sql(), stmt); changed.add(new ManipulationResultImpl(this, stmt.executeUpdate())); } catch (SQLException ex) { query().handleException(ex); } } - return new ManipulationBatchQuery(this, changed); + return new ManipulationBatchResultImpl<>(this, changed); }); } @Override - public ManipulationBatchResult delete() { + public ManipulationBatchResult delete() { return update(); } diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/execution/writing/CalledSingletonQueryImpl.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/execution/writing/CalledSingletonQueryImpl.java index 69f14c6d..336cd8ea 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/execution/writing/CalledSingletonQueryImpl.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/execution/writing/CalledSingletonQueryImpl.java @@ -8,21 +8,26 @@ import de.chojo.sadu.mapper.MapperConfig; import de.chojo.sadu.mapper.rowmapper.RowMapping; +import de.chojo.sadu.mapper.util.Results; import de.chojo.sadu.queries.api.base.QueryProvider; import de.chojo.sadu.queries.api.call.Call; import de.chojo.sadu.queries.api.execution.reading.Reader; import de.chojo.sadu.queries.api.execution.writing.CalledSingletonQuery; -import de.chojo.sadu.queries.api.results.writing.ManipulationResult; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationResult; import de.chojo.sadu.queries.call.CallImpl; import de.chojo.sadu.queries.calls.SingletonCall; +import de.chojo.sadu.queries.execution.reading.AutoMappedQuery; +import de.chojo.sadu.queries.execution.reading.MappedQuery; import de.chojo.sadu.queries.query.ParsedQueryImpl; import de.chojo.sadu.queries.query.QueryImpl; import de.chojo.sadu.queries.query.TokenizedQuery; -import de.chojo.sadu.queries.execution.reading.AutoMappedQuery; -import de.chojo.sadu.queries.execution.reading.MappedQuery; -import de.chojo.sadu.queries.results.writing.ManipulationResultImpl; +import de.chojo.sadu.queries.results.writing.insertion.InsertionResultImpl; +import de.chojo.sadu.queries.results.writing.manipulation.ManipulationResultImpl; import java.sql.SQLException; +import java.sql.Statement; +import java.util.Collections; public class CalledSingletonQueryImpl implements QueryProvider, CalledSingletonQuery { private final ParsedQueryImpl query; @@ -49,24 +54,39 @@ public Reader mapAs(Class clazz, MapperConfig config) { } @Override - public ManipulationResult insert() { - return query.callConnection(() -> new ManipulationResultImpl(this, 0), conn -> { + public InsertionResult insert() { + return query.callConnection(() -> InsertionResultImpl.empty(this), conn -> { var changed = 0; //noinspection JDBCPrepareStatementWithNonConstantString try (var stmt = conn.prepareStatement(query.sql().tokenizedSql())) { - //TODO find way to return generated keys ((CallImpl) call.call()).apply(query.sql(), stmt); changed = stmt.executeUpdate(); } catch (SQLException ex) { query().handleException(ex); } - return new ManipulationResultImpl(this, changed); + return new InsertionResultImpl(this, changed, Collections.emptyList()); + }); + } + + @Override + public InsertionResult insertAndGetKeys() { + return query.callConnection(() -> InsertionResultImpl.empty(this), conn -> { + var changed = 0; + //noinspection JDBCPrepareStatementWithNonConstantString + try (var stmt = conn.prepareStatement(query.sql().tokenizedSql(), Statement.RETURN_GENERATED_KEYS)) { + ((CallImpl) call.call()).apply(query.sql(), stmt); + changed = stmt.executeUpdate(); + return new InsertionResultImpl(this, changed, Results.generatedKeys(stmt)); + } catch (SQLException ex) { + query().handleException(ex); + } + return InsertionResultImpl.empty(this); }); } @Override public ManipulationResult update() { - return query().callConnection(() -> new ManipulationResultImpl(this, 0), conn -> { + return query().callConnection(() -> ManipulationResultImpl.empty(this), conn -> { var changed = 0; //noinspection JDBCPrepareStatementWithNonConstantString try (var stmt = conn.prepareStatement(query.sql().tokenizedSql())) { diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/insertion/InsertionBatchResultImpl.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/insertion/InsertionBatchResultImpl.java new file mode 100644 index 00000000..d331e1c7 --- /dev/null +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/insertion/InsertionBatchResultImpl.java @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.queries.results.writing.insertion; + +import de.chojo.sadu.queries.api.base.QueryProvider; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionBatchResult; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionResult; +import de.chojo.sadu.queries.results.writing.manipulation.ManipulationBatchResultImpl; + +import java.util.List; + +public class InsertionBatchResultImpl extends ManipulationBatchResultImpl implements InsertionBatchResult { + public InsertionBatchResultImpl(QueryProvider query, List results) { + super(query, results); + } + + @Override + public List keys() { + return results().stream().flatMap(r -> r.keys().stream()).toList(); + } +} diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/insertion/InsertionResultImpl.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/insertion/InsertionResultImpl.java new file mode 100644 index 00000000..abb554f9 --- /dev/null +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/insertion/InsertionResultImpl.java @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * Copyright (C) RainbowDashLabs and Contributor + */ + +package de.chojo.sadu.queries.results.writing.insertion; + +import de.chojo.sadu.queries.api.base.QueryProvider; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionResult; +import de.chojo.sadu.queries.results.writing.manipulation.ManipulationResultImpl; + +import java.util.Collections; +import java.util.List; + +public class InsertionResultImpl extends ManipulationResultImpl implements InsertionResult { + private final List keys; + + public InsertionResultImpl(QueryProvider query, int rows, List keys) { + super(query, rows); + this.keys = keys; + } + + public static InsertionResultImpl empty(QueryProvider query) { + return new InsertionResultImpl(query, 0, Collections.emptyList()); + } + + @Override + public List keys() { + return keys; + } +} diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/insertion/package-info.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/insertion/package-info.java new file mode 100644 index 00000000..7fec6442 --- /dev/null +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/insertion/package-info.java @@ -0,0 +1,4 @@ +/** + * Implementation for results of an insertion query. + */ +package de.chojo.sadu.queries.results.writing.insertion; diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/ManipulationBatchQuery.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/manipulation/ManipulationBatchResultImpl.java similarity index 65% rename from sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/ManipulationBatchQuery.java rename to sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/manipulation/ManipulationBatchResultImpl.java index 5d371284..d6a3dd55 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/ManipulationBatchQuery.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/manipulation/ManipulationBatchResultImpl.java @@ -4,30 +4,30 @@ * Copyright (C) RainbowDashLabs and Contributor */ -package de.chojo.sadu.queries.results.writing; +package de.chojo.sadu.queries.results.writing.manipulation; import de.chojo.sadu.queries.api.base.QueryProvider; -import de.chojo.sadu.queries.api.results.writing.ManipulationBatchResult; -import de.chojo.sadu.queries.api.results.writing.ManipulationResult; -import de.chojo.sadu.queries.query.QueryImpl; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationBatchResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationResult; import de.chojo.sadu.queries.execution.writing.CalledBatchQueryImpl; +import de.chojo.sadu.queries.query.QueryImpl; import java.util.List; /** * Result of a {@link CalledBatchQueryImpl} */ -public class ManipulationBatchQuery implements QueryProvider, ManipulationBatchResult { +public class ManipulationBatchResultImpl implements QueryProvider, ManipulationBatchResult { private final QueryProvider query; - private final List results; + private final List results; - public ManipulationBatchQuery(QueryProvider query, List results) { + public ManipulationBatchResultImpl(QueryProvider query, List results) { this.query = query; this.results = results; } @Override - public List results() { + public List results() { return results; } diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/ManipulationResultImpl.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/manipulation/ManipulationResultImpl.java similarity index 78% rename from sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/ManipulationResultImpl.java rename to sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/manipulation/ManipulationResultImpl.java index ac1be730..4fb6ff01 100644 --- a/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/ManipulationResultImpl.java +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/manipulation/ManipulationResultImpl.java @@ -4,10 +4,10 @@ * Copyright (C) RainbowDashLabs and Contributor */ -package de.chojo.sadu.queries.results.writing; +package de.chojo.sadu.queries.results.writing.manipulation; import de.chojo.sadu.queries.api.base.QueryProvider; -import de.chojo.sadu.queries.api.results.writing.ManipulationResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationResult; import de.chojo.sadu.queries.execution.writing.CalledSingletonQueryImpl; import de.chojo.sadu.queries.query.QueryImpl; @@ -20,6 +20,10 @@ public class ManipulationResultImpl implements QueryProvider, ManipulationResult private final QueryProvider query; private final int rows; + public static ManipulationResultImpl empty(QueryProvider query) { + return new ManipulationResultImpl(query, 0); + } + public ManipulationResultImpl(QueryProvider query, int rows) { this.query = query; this.rows = rows; diff --git a/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/manipulation/package-info.java b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/manipulation/package-info.java new file mode 100644 index 00000000..bfb32a88 --- /dev/null +++ b/sadu-queries/src/main/java/de/chojo/sadu/queries/results/writing/manipulation/package-info.java @@ -0,0 +1,4 @@ +/** + * Implementation for results of an update or delete query. + */ +package de.chojo.sadu.queries.results.writing.manipulation; diff --git a/sadu-queries/src/main/java/module-info.java b/sadu-queries/src/main/java/module-info.java index 8f101257..81a25ed1 100644 --- a/sadu-queries/src/main/java/module-info.java +++ b/sadu-queries/src/main/java/module-info.java @@ -11,7 +11,8 @@ exports de.chojo.sadu.queries.api.parameter; exports de.chojo.sadu.queries.api.query; exports de.chojo.sadu.queries.api.results.reading; - exports de.chojo.sadu.queries.api.results.writing; + exports de.chojo.sadu.queries.api.results.writing.manipulation; + exports de.chojo.sadu.queries.api.results.writing.insertion; exports de.chojo.sadu.queries.api.storage; exports de.chojo.sadu.queries.call; @@ -29,8 +30,9 @@ exports de.chojo.sadu.queries.execution.reading; exports de.chojo.sadu.queries.execution.writing; + exports de.chojo.sadu.queries.results.writing.manipulation; + exports de.chojo.sadu.queries.results.writing.insertion; exports de.chojo.sadu.queries.results.reading; - exports de.chojo.sadu.queries.results.writing; exports de.chojo.sadu.queries.storage; } diff --git a/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/ReadTest.java b/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/ReadTest.java index c85e760c..e68542f4 100644 --- a/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/ReadTest.java +++ b/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/ReadTest.java @@ -13,7 +13,7 @@ import de.chojo.sadu.queries.api.call.Call; import de.chojo.sadu.queries.api.call.calls.Calls; import de.chojo.sadu.queries.api.results.reading.Result; -import de.chojo.sadu.queries.api.results.writing.ManipulationResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationResult; import de.chojo.sadu.queries.configuration.QueryConfiguration; import de.chojo.sadu.queries.configuration.QueryConfigurationBuilder; import de.chojo.sadu.queries.examples.dao.User; diff --git a/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/TransactionTest.java b/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/TransactionTest.java index 747d557b..11a56ec5 100644 --- a/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/TransactionTest.java +++ b/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/TransactionTest.java @@ -10,7 +10,7 @@ import de.chojo.sadu.mapper.RowMapperRegistry; import de.chojo.sadu.postgresql.mapper.PostgresqlMapper; import de.chojo.sadu.queries.api.call.calls.Calls; -import de.chojo.sadu.queries.api.results.writing.ManipulationResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationResult; import de.chojo.sadu.queries.configuration.QueryConfiguration; import de.chojo.sadu.queries.configuration.QueryConfigurationBuilder; import de.chojo.sadu.queries.examples.dao.User; diff --git a/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/WriteTest.java b/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/WriteTest.java index ffe459e2..38656c5e 100644 --- a/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/WriteTest.java +++ b/sadu-queries/src/test/java/de/chojo/sadu/queries/examples/WriteTest.java @@ -10,8 +10,9 @@ import de.chojo.sadu.mapper.RowMapperRegistry; import de.chojo.sadu.postgresql.mapper.PostgresqlMapper; import de.chojo.sadu.queries.api.call.Call; -import de.chojo.sadu.queries.api.results.writing.ManipulationBatchResult; -import de.chojo.sadu.queries.api.results.writing.ManipulationResult; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionBatchResult; +import de.chojo.sadu.queries.api.results.writing.insertion.InsertionResult; +import de.chojo.sadu.queries.api.results.writing.manipulation.ManipulationResult; import de.chojo.sadu.queries.call.adapter.UUIDAdapter; import de.chojo.sadu.queries.configuration.QueryConfiguration; import de.chojo.sadu.queries.configuration.QueryConfigurationBuilder; @@ -47,7 +48,7 @@ void afterAll() { @Test public void exampleIndex() { // Insert multiple entries at the same time - ManipulationBatchResult change = query + InsertionBatchResult change = query // Define the query .query("INSERT INTO users(uuid, name) VALUES(?::uuid,?)") // Create a new batch call @@ -65,7 +66,7 @@ public void exampleIndex() { Assertions.assertEquals(2, change.rows()); // Check how many rows for each batch execution were changed - for (ManipulationResult result : change.results()) { + for (InsertionResult result : change.results()) { Assertions.assertEquals(1, result.rows()); } } @@ -73,7 +74,7 @@ public void exampleIndex() { @Test public void exampleTokenized() { // Insert multiple entries at the same time - ManipulationBatchResult change = query + InsertionBatchResult change = query // Define the query .query("INSERT INTO users(uuid, name) VALUES(:uuid::uuid,?)") // Create a new batch call @@ -99,7 +100,7 @@ public void exampleTokenized() { @Test public void exampleStream() { // Insert multiple entries at the same time - ManipulationBatchResult change = query + InsertionBatchResult change = query // Define the query .query("INSERT INTO users(uuid, name) VALUES(:uuid::uuid,?)") // Create a new batch call @@ -113,15 +114,42 @@ public void exampleStream() { Assertions.assertEquals(change.rows(), 2); // Check how many rows for each batch execution were changed - for (ManipulationResult result : change.results()) { + for (InsertionResult result : change.results()) { + Assertions.assertEquals(result.rows(), 1); + } + } + + @Test + public void exampleGetKeys() { + // Insert multiple entries at the same time + InsertionBatchResult change = query + // Define the query + .query("INSERT INTO users(uuid, name) VALUES(:uuid::uuid,?)") + // Create a new batch call + .batch(Stream.generate(UUID::randomUUID).limit(2).map(id -> Call.of().bind("uuid", id, AS_STRING).bind((String) null))) + // Insert the data + .insertAndGetKeys(); + + // Check that something changed + Assertions.assertTrue(change.changed()); + // Check that two rows were added + Assertions.assertEquals(change.rows(), 2); + + // Check how many rows for each batch execution were changed + for (InsertionResult result : change.results()) { Assertions.assertEquals(result.rows(), 1); } + + // Check that we got one key back + for (InsertionResult result : change.results()) { + Assertions.assertEquals(result.keys().size(), 1); + } } @Test public void exampleSingle() { // Insert multiple entries at the same time - ManipulationResult change = query + InsertionResult change = query // Define the query .query("INSERT INTO users(uuid, name) VALUES(:uuid::uuid,?)") // Create a new call diff --git a/settings.gradle.kts b/settings.gradle.kts index 2c7c1444..77edd343 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -51,7 +51,7 @@ dependencyResolutionManagement { library("junit-params", "org.junit.jupiter", "junit-jupiter-params").versionRef("junit") bundle("junit", listOf("junit-jupiter", "junit-params")) - version("testcontainers", "1.19.5") + version("testcontainers", "1.19.6") library("testcontainers-postgres", "org.testcontainers", "postgresql").versionRef("testcontainers") library("testcontainers-mariadb", "org.testcontainers", "mariadb").versionRef("testcontainers") library("testcontainers-mysql", "org.testcontainers", "mysql").versionRef("testcontainers") @@ -62,7 +62,7 @@ dependencyResolutionManagement { library("slf4j-noop", "org.slf4j", "slf4j-nop").versionRef("slf4j") library("driver-postgres", "org.postgresql:postgresql:42.7.2") - library("driver-mariadb", "org.mariadb.jdbc:mariadb-java-client:3.3.2") + library("driver-mariadb", "org.mariadb.jdbc:mariadb-java-client:3.3.3") library("driver-sqlite", "org.xerial:sqlite-jdbc:3.45.1.0") library("driver-mysql", "com.mysql:mysql-connector-j:8.3.0")