Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
4be0cfc
Upsert implementation - wip
msupic Jun 11, 2026
ddb055e
Upsert implementation - wip
msupic Jun 11, 2026
7360d30
Upsert implementation - wip
msupic Jun 11, 2026
b044e35
Upsert implementation - wip
msupic Jun 11, 2026
7d53ae7
Upsert implementation - wip
msupic Jun 11, 2026
c3af05e
Upsert implementation - added tests for sqlserver and postgres
msupic Jun 12, 2026
a743cb3
Upsert implementation - minor refactoring
msupic Jun 12, 2026
2b5038e
Upsert implementation - added conflictProperties
msupic Jun 12, 2026
b815148
Upsert implementation - added conflictProperties
msupic Jun 12, 2026
f450bde
Upsert implementation - wip
msupic Jun 12, 2026
175c6af
Upsert implementation - wip
msupic Jun 15, 2026
b7c406c
Upsert implementation - wip
msupic Jun 15, 2026
e0a3164
Upsert implementation - wip
msupic Jun 15, 2026
fcf6598
Upsert implementation - wip
msupic Jun 15, 2026
8064427
Upsert implementation - modified test entities
msupic Jun 17, 2026
c082222
Upsert implementation - return generated ids
msupic Jun 18, 2026
ddf0f9e
Upsert implementation - added more tests
msupic Jun 18, 2026
44d7dc3
Upsert implementation - added more tests
msupic Jun 18, 2026
220d4e6
Upsert implementation - refactoring of OracleJdbcRepositoryOperations
msupic Jun 19, 2026
95af8a7
Upsert implementation - wip
msupic Jun 19, 2026
1a8caa9
Merge branch '5.1.x' of github.com:micronaut-projects/micronaut-data …
msupic Jun 19, 2026
1385289
Upsert implementation - updated upsert tests
msupic Jun 19, 2026
8930e15
Upsert implementation - sql server upsert implementation when returni…
msupic Jun 19, 2026
ca5f2a5
Upsert implementation - SqlQueryBuilder refactoring
msupic Jun 19, 2026
0ffe2e8
Upsert implementation - SqlUpsertQueryBuilder refactoring
msupic Jun 19, 2026
f1c36d4
Upsert implementation - SqlUpsertQueryBuilder refactoring
msupic Jun 19, 2026
1e19364
Upsert implementation - SqlUpsertQueryBuilder refactoring
msupic Jun 19, 2026
17fff91
Upsert implementation - SqlUpsertQueryBuilder refactoring
msupic Jun 19, 2026
9485276
Upsert implementation - SqlUpsertQueryBuilder refactoring
msupic Jun 23, 2026
6c6c4c3
Upsert implementation - SqlUpsertQueryBuilder refactoring
msupic Jun 23, 2026
56e53d3
Created SQL Server sequences before tables so generated columns can r…
msupic Jun 23, 2026
52123fd
Added sqlserver and postgres tests for cases when upsert called on en…
msupic Jun 23, 2026
9358d58
Added tests for cases when upsert called on entity which contains id …
msupic Jun 23, 2026
6608900
Added tests for cases when upsert called on entity which contains id …
msupic Jun 23, 2026
eb3a486
Enabled uuid-ossp for Postgres R2DBC tests
msupic Jun 24, 2026
10ccfbf
Updated upsert tests for R2DBC
msupic Jun 24, 2026
c7985a6
Upsert implementation for R2DBC
msupic Jun 24, 2026
5f3e725
Upsert implementation for R2DBC
msupic Jun 24, 2026
505ab5e
Added GeneratedValue.Type.SEQUENCE related tests to r2dbc
msupic Jun 26, 2026
608f085
Modified repository operations conditions
msupic Jun 26, 2026
16b7922
Merge branch '5.1.x' of github.com:micronaut-projects/micronaut-data …
msupic Jun 26, 2026
8ae5541
Temp change to test upsert implementation
msupic Jun 29, 2026
6b6a93b
Ready
msupic Jun 30, 2026
5156dcd
Remove CustomerProfileUuid records after each test
msupic Jul 1, 2026
0b355fd
Fixed PostgresDbInit
msupic Jul 1, 2026
9f4cb94
Replaced conflictProperties with conflictsOn in Upsert annotation
msupic Jul 1, 2026
7c0129f
Rolled back temp changes
msupic Jul 1, 2026
0a0fd14
Added docs
msupic Jul 2, 2026
26dc520
Merged 5.1.x into this branch
msupic Jul 2, 2026
f7955b2
Upsert impl for sqlite
msupic Jul 2, 2026
5da34f0
Upsert tests for sqlite
msupic Jul 2, 2026
6d83a7c
Updated docs
msupic Jul 2, 2026
2f7a7bf
Updated docs
msupic Jul 2, 2026
ab1bed9
Rolled back
msupic Jul 2, 2026
c0e0dd6
Addressed copilot comments
msupic Jul 3, 2026
ae7af3e
Created DataSourceConfigurationUtils and moved resolveConfiguredDataS…
msupic Jul 22, 2026
c159be9
Removed final from SqlServerJdbcRepositoryOperations and OracleJdbcRe…
msupic Jul 22, 2026
aee1245
Added javadoc to SqlUpsertQueryBuilder
msupic Jul 22, 2026
d81c489
Modified upsert docs to use snippet macro
msupic Jul 23, 2026
2ee748d
Merge branch '5.2.x' of github.com:micronaut-projects/micronaut-data …
msupic Jul 23, 2026
8a38d20
Trigger CI build
msupic Jul 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* Copyright 2017-2026 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.data.jdbc.operations;

import io.micronaut.context.condition.Condition;
import io.micronaut.context.condition.ConditionContext;
import io.micronaut.core.annotation.Internal;
import io.micronaut.data.jdbc.config.DataJdbcConfiguration;
import io.micronaut.data.runtime.support.DataSourceConfigurationUtils;

import java.util.List;
import java.util.Optional;

/**
* Condition that enables the default JDBC repository operations for datasources without a specialized implementation.
*/
@Internal
final class DefaultJdbcRepositoryOperationsCondition implements Condition {

/**
* Checks whether the current datasource is not configured with a dialect that requires specialized JDBC operations.
*
* @param context The condition context
* @return {@code true} when default JDBC operations should be enabled
*/
@Override
public boolean matches(ConditionContext context) {
return JdbcRepositoryOperationsConditions.isDefaultOperationsDialect(context);
}
}

/**
* Condition that enables Oracle-specific JDBC repository operations for Oracle datasources.
*/
@Internal
final class OracleJdbcRepositoryOperationsCondition implements Condition {

/**
* Checks whether the current datasource is configured with the Oracle dialect.
*
* @param context The condition context
* @return {@code true} when Oracle JDBC operations should be enabled
*/
@Override
public boolean matches(ConditionContext context) {
return JdbcRepositoryOperationsConditions.isOracleDialect(context);
}
}

/**
* Condition that enables SQL Server-specific JDBC repository operations for SQL Server datasources.
*/
@Internal
final class SqlServerJdbcRepositoryOperationsCondition implements Condition {

/**
* Checks whether the current datasource is configured with the SQL Server dialect.
*
* @param context The condition context
* @return {@code true} when SQL Server JDBC operations should be enabled
*/
@Override
public boolean matches(ConditionContext context) {
return JdbcRepositoryOperationsConditions.isSqlServerDialect(context);
}
}

/**
* Shared condition utilities for selecting the JDBC repository operations bean.
*/
@Internal
final class JdbcRepositoryOperationsConditions {

private static final String DATASOURCES = "datasources";
private static final String DIALECT = "dialect";
private static final String ORACLE_DIALECT = "ORACLE";
private static final String SQL_SERVER_DIALECT = "SQL_SERVER";
private static final String DEFAULT = "default";

private JdbcRepositoryOperationsConditions() {
}

/**
* Checks whether the datasource associated with the current bean resolution uses the Oracle dialect.
*
* @param context The condition context
* @return {@code true} when the datasource is configured with {@code datasources.<name>.dialect=ORACLE}
*/
static boolean isOracleDialect(ConditionContext context) {
return isDialect(context, ORACLE_DIALECT);
}

/**
* Checks whether the datasource associated with the current bean resolution uses the SQL Server dialect.
*
* @param context The condition context
* @return {@code true} when the datasource is configured with {@code datasources.<name>.dialect=SQL_SERVER}
*/
static boolean isSqlServerDialect(ConditionContext context) {
return isDialect(context, SQL_SERVER_DIALECT);
}

/**
* Checks whether default JDBC operations should remain available for the current condition evaluation.
*
* <p>When the condition is evaluated for a specific {@code @EachBean(DataSource)} instance, the
* current datasource qualifier is available and only that datasource is considered. When Micronaut
* evaluates the bean definition before a datasource qualifier is available, all configured
* datasources are considered so mixed datasource applications can still create default operations
* for non-special datasources while Oracle or SQL Server operations handle their own datasources.</p>
*
* @param context The condition context
* @return {@code true} when at least the current or one configured datasource should use default operations
*/
static boolean isDefaultOperationsDialect(ConditionContext context) {
Optional<String> dataSourceName = DataSourceConfigurationUtils.resolveDataSourceName(context);
if (dataSourceName.isPresent()) {
return !isDialect(context, dataSourceName.get(), ORACLE_DIALECT)
&& !isDialect(context, dataSourceName.get(), SQL_SERVER_DIALECT);
}
List<String> dataSourceNames = DataSourceConfigurationUtils.resolveConfiguredDataSourceNames(context, DATASOURCES, DataJdbcConfiguration.class);
if (dataSourceNames.isEmpty()) {
return true;
}
return dataSourceNames.stream()
.anyMatch(name -> !isDialect(context, name, ORACLE_DIALECT) && !isDialect(context, name, SQL_SERVER_DIALECT));
}

private static boolean isDialect(ConditionContext context, String expectedDialect) {
Optional<String> dataSourceName = DataSourceConfigurationUtils.resolveDataSourceName(context);
if (dataSourceName.isPresent()) {
return isDialect(context, dataSourceName.get(), expectedDialect);
}
List<String> dataSourceNames = DataSourceConfigurationUtils.resolveConfiguredDataSourceNames(context, DATASOURCES, DataJdbcConfiguration.class);
if (dataSourceNames.isEmpty()) {
return isDialect(context, DEFAULT, expectedDialect);
}
return dataSourceNames.stream().anyMatch(name -> isDialect(context, name, expectedDialect));
}

private static boolean isDialect(ConditionContext context, String dataSourceName, String expectedDialect) {
String dialectProperty = DATASOURCES + '.' + dataSourceName + '.' + DIALECT;
String dialect = context.getProperty(dialectProperty, String.class).orElse(null);
return expectedDialect.equalsIgnoreCase(dialect);
}
}
Loading
Loading