Skip to content

R2DBC support#22

Merged
deusaquilus merged 1 commit intomainfrom
r2dbc
Nov 28, 2025
Merged

R2DBC support#22
deusaquilus merged 1 commit intomainfrom
r2dbc

Conversation

@deusaquilus
Copy link
Member

@deusaquilus deusaquilus commented Nov 28, 2025

🚀 PR Comment: R2DBC Support Added

Overview

This PR introduces R2DBC (Reactive Relational Database Connectivity) support to the terpal-sql library, enabling fully reactive, non-blocking database access alongside the existing JDBC implementation.


🎯 Main Feature: R2DBC Support

The highlight of this commit is the addition of comprehensive R2DBC support with the following key components:

New Module Structure

  • controller-r2dbc: Core R2DBC controller implementation providing the foundation for reactive database operations
  • terpal-sql-r2dbc: R2DBC SQL module with complete test coverage

Multi-Database Support

The R2DBC implementation supports multiple database vendors out of the box through specialized controllers in R2dbcControllers:

Database Controller Placeholder Style Notes
PostgreSQL R2dbcControllers.Postgres $1, $2... Native UUID support, additional Postgres-specific encodings
SQL Server R2dbcControllers.SqlServer @param0, @param1... Named parameter binding, special OffsetDateTime handling
MySQL R2dbcControllers.Mysql ? (positional) Standard positional parameters
H2 R2dbcControllers.H2 $1, $2... Zero-based result row indexing, Long-based Int handling
Oracle R2dbcControllers.Oracle :1, :2... Special handling for empty strings (treated as NULL), OffsetDateTime-based encoding

Type Encoding/Decoding

The R2DBC implementation includes comprehensive type encoding support:

  • Basic types: Boolean, Byte, Char, Double, Float, Int, Long, Short, String, ByteArray
  • Kotlin datetime types: LocalDate, LocalDateTime, LocalTime, Instant
  • Java time types: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, OffsetTime, OffsetDateTime, Date
  • UUID support: Native UUID encoding (Postgres, H2) and String-based UUID encoding (SQL Server, MySQL, Oracle)
  • BigDecimal support through additional encoders

Database-Specific Quirks Handled

The implementation carefully handles various database-specific behaviors:

  • Oracle: Empty strings are treated as NULLs in R2DBC, so decoders convert null to empty string for String columns
  • H2: Uses Long internally for Int columns, requiring specialized decoders
  • SQL Server: Requires OffsetDateTime for Instant binding since direct Instant binding isn't supported

🔧 Minor Changes & Improvements

Enhanced Error Reporting

  1. New DecodingError exception class: Added a specialized ControllerError.DecodingError subclass for more precise error categorization during decoding operations.

  2. Improved error messages: Error messages now include index type description (zero-based vs one-based) for easier debugging:


   Error encoding String value: ... at (zero-based) index: 3
  1. dbTypeIsRelevant() method: Controllers can now indicate whether database type information should be included in error messages. R2DBC controllers return false since R2DBC doesn't use JDBC types.

  2. Safe column info access: Added columnInfoSafe(index) method that gracefully handles IndexOutOfBoundsException instead of throwing, preventing cascading errors during error reporting.

StartingIndex Enhancements

The StartingIndex sealed interface now includes a description property:

  • Zero.description = "zero-based"
  • One.description = "one-based"

This provides clearer context in error messages about whether indices are zero-based (R2DBC) or one-based (JDBC).

Code Quality Improvements

  • Added EncodingContext parameters startingIndex and dbTypeIsRelevant for better encoding context awareness
  • Wrapped decoder operations in try-catch blocks with informative error messages including column name and type info
  • Minor documentation comment added explaining Postgres driver dependency for JSON object wrapping

📊 Test Coverage

The PR includes comprehensive test suites for R2DBC across multiple databases:

  • Basic queries and actions
  • Encoding/decoding for all supported types
  • IN query parameter handling
  • SQL injection protection
  • Transaction management

@deusaquilus deusaquilus merged commit 4dfc549 into main Nov 28, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant