All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.tonivade.puredbc.R2dbcTemplate Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2020-2024, Antonio Gabriel Muñoz Conejo 
 * Distributed under the terms of the MIT License
 */
package com.github.tonivade.puredbc;

import static com.github.tonivade.purefun.core.Precondition.checkNonNull;
import static com.github.tonivade.purefun.core.Unit.unit;
import java.util.List;
import org.reactivestreams.Publisher;
import com.github.tonivade.puredbc.sql.Field;
import com.github.tonivade.purefun.core.Function1;
import com.github.tonivade.purefun.core.Unit;
import com.github.tonivade.purefun.data.Range;
import com.github.tonivade.purefun.data.Sequence;
import com.github.tonivade.purefun.type.Option;
import io.r2dbc.spi.Connection;
import io.r2dbc.spi.ConnectionFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public final class R2dbcTemplate {

  private final ConnectionFactory connectionFactory;

  public R2dbcTemplate(ConnectionFactory connectionFactory) {
    this.connectionFactory = checkNonNull(connectionFactory);
  }

  public Mono update(String query, Sequence params) {
    return Mono.from(connectionFactory.create())
        .flatMap(conn -> doUpdate(query, params, conn)
            .delayUntil(result -> conn.commitTransaction())
            .doFinally(stmt -> conn.close()))
        .thenReturn(unit());
  }

  public  Mono> updateWithKeys(String query, Sequence params, Field field) {
    return Mono.from(connectionFactory.create())
        .flatMap(conn -> doUpdateWithKeys(query, params, conn, field)
            .flatMap(result -> Mono.from(applyToRow(row -> row.get(field), result)))
            .delayUntil(result -> conn.commitTransaction())
            .doFinally(stmt -> conn.close()))
        .map(Option::some).defaultIfEmpty(Option.none());
  }

  public  Mono> queryMeta(String query, Sequence params, Function1 rowMapper) {
    return doQuery(query, params)
        .flatMap(result -> Mono.from(applyToMeta(rowMapper, result)))
        .map(Option::some).defaultIfEmpty(Option.none());
  }

  public  Mono> queryOne(String query, Sequence params, Function1 rowMapper) {
    return doQuery(query, params)
        .flatMap(result -> Mono.from(applyToRow(rowMapper, result)))
        .map(Option::some).defaultIfEmpty(Option.none());
  }

  public  Flux> queryIterable(String query, Sequence params, Function1 rowMapper) {
    return doQuery(query, params)
        .flatMapMany(result -> Flux.from(applyToRow(rowMapper, result))).buffer(10);
  }

  private Mono doUpdate(String query, Sequence params, Connection conn) {
    return Mono.from(conn.beginTransaction())
        .then(createStatement(query, params, conn)
        .flatMap(stmt -> Mono.from(stmt.execute())));
  }

  private Mono doUpdateWithKeys(String query, Sequence params, Connection conn, Field field) {
    return Mono.from(conn.beginTransaction())
        .then(createStatement(query, params, conn).map(stmt -> stmt.returnGeneratedValues(field.name()))
        .flatMap(stmt -> Mono.from(stmt.execute())));
  }

  private Mono doQuery(String query, Sequence params) {
    return Mono.from(connectionFactory.create())
        .flatMap(conn -> createStatement(query, params, conn)
        .flatMap(stmt -> Mono.from(stmt.execute()))
        .doFinally(stmt -> Mono.from(conn.close()).then(Mono.empty())));
  }

  private Mono createStatement(String query, Sequence params, Connection conn) {
    return Mono.just(conn.createStatement(query))
        .map(stmt -> {
          int i = 0;
          for (var param : params) {
            switch (param) {
              case Range(var begin, var end) -> {
                stmt.bind(i++, begin);
                stmt.bind(i++, end);
              }
              case Iterable iterable -> {
                for (var p : iterable) {
                  stmt.bind(i++, p);
                }
              }
              case null, default -> stmt.bind(i++, param);
            }
          }
          return stmt;
        });
  }

  private  Publisher applyToRow(Function1 rowMapper, io.r2dbc.spi.Result result) {
    return result.map((row, meta) -> rowMapper.compose(R2dbcRow::new).apply(row));
  }

  private  Publisher applyToMeta(Function1 rowMapper, io.r2dbc.spi.Result result) {
    return result.map((row, meta) -> rowMapper.compose(R2dbcRowMetaData::new).apply(meta));
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy